Poodletooth-iLand/otp/otpbase/OTPBase.py

335 lines
12 KiB
Python

import math
import re
import time
import OTPGlobals
import OTPRender
from direct.showbase.ShowBase import ShowBase
from otp.ai.MagicWordGlobal import *
from pandac.PandaModules import Camera, TPLow, VBase4, ColorWriteAttrib, Filename, getModelPath, NodePath, Vec4
class OTPBase(ShowBase):
def __init__(self, windowType = None):
self.wantEnviroDR = False
ShowBase.__init__(self, windowType=windowType)
if config.GetBool('want-phase-checker', 0):
from direct.showbase import Loader
Loader.phaseChecker = self.loaderPhaseChecker
self.errorAccumulatorBuffer = ''
taskMgr.add(self.delayedErrorCheck, 'delayedErrorCheck', priority=10000)
self.idTags = config.GetBool('want-id-tags', 0)
if not self.idTags:
del self.idTags
self.wantNametags = self.config.GetBool('want-nametags', 1)
self.slowCloseShard = self.config.GetBool('slow-close-shard', 0)
self.slowCloseShardDelay = self.config.GetFloat('slow-close-shard-delay', 10.0)
self.fillShardsToIdealPop = self.config.GetBool('fill-shards-to-ideal-pop', 1)
self.logPrivateInfo = self.config.GetBool('log-private-info', __dev__)
self.wantDynamicShadows = 1
self.stereoEnabled = False
self.enviroDR = None
self.enviroCam = None
self.pixelZoomSetup = False
self.gameOptionsCode = ''
self.locationCode = ''
self.locationCodeChanged = time.time()
if base.cam:
if self.wantEnviroDR:
base.cam.node().setCameraMask(OTPRender.MainCameraBitmask)
else:
base.cam.node().setCameraMask(OTPRender.MainCameraBitmask | OTPRender.EnviroCameraBitmask)
taskMgr.setupTaskChain('net')
return
def setTaskChainNetThreaded(self):
if base.config.GetBool('want-threaded-network', 0):
taskMgr.setupTaskChain('net', numThreads=1, frameBudget=0.001, threadPriority=TPLow)
def setTaskChainNetNonthreaded(self):
taskMgr.setupTaskChain('net', numThreads=0, frameBudget=-1)
def toggleStereo(self):
self.stereoEnabled = not self.stereoEnabled
if self.stereoEnabled:
if not base.win.isStereo():
base.win.setRedBlueStereo(True, ColorWriteAttrib.CRed, ColorWriteAttrib.CGreen | ColorWriteAttrib.CBlue)
if self.wantEnviroDR:
self.setupEnviroCamera()
return
mainDR = base.camNode.getDisplayRegion(0)
if self.stereoEnabled:
if not mainDR.isStereo():
base.win.removeDisplayRegion(mainDR)
mainDR = base.win.makeStereoDisplayRegion()
mainDR.getRightEye().setClearDepthActive(True)
mainDR.setCamera(base.cam)
elif mainDR.isStereo():
base.win.removeDisplayRegion(mainDR)
mainDR = base.win.makeMonoDisplayRegion()
mainDR.setCamera(base.cam)
def setupEnviroCamera(self):
clearColor = VBase4(0, 0, 0, 1)
if self.enviroDR:
clearColor = self.enviroDR.getClearColor()
self.win.removeDisplayRegion(self.enviroDR)
if not self.enviroCam:
self.enviroCam = self.cam.attachNewNode(Camera('enviroCam'))
mainDR = self.camNode.getDisplayRegion(0)
if self.stereoEnabled:
self.enviroDR = self.win.makeStereoDisplayRegion()
if not mainDR.isStereo():
self.win.removeDisplayRegion(mainDR)
mainDR = self.win.makeStereoDisplayRegion()
mainDR.setCamera(self.cam)
ml = mainDR.getLeftEye()
mr = mainDR.getRightEye()
el = self.enviroDR.getLeftEye()
er = self.enviroDR.getRightEye()
el.setSort(-8)
ml.setSort(-6)
er.setSort(-4)
er.setClearDepthActive(True)
mr.setSort(-2)
mr.setClearDepthActive(False)
else:
self.enviroDR = self.win.makeMonoDisplayRegion()
if mainDR.isStereo():
self.win.removeDisplayRegion(mainDR)
mainDR = self.win.makeMonoDisplayRegion()
mainDR.setCamera(self.cam)
self.enviroDR.setSort(-10)
self.enviroDR.setClearColor(clearColor)
self.win.setClearColor(clearColor)
self.enviroDR.setCamera(self.enviroCam)
self.enviroCamNode = self.enviroCam.node()
self.enviroCamNode.setLens(self.cam.node().getLens())
self.enviroCamNode.setCameraMask(OTPRender.EnviroCameraBitmask)
render.hide(OTPRender.EnviroCameraBitmask)
self.camList.append(self.enviroCam)
self.backgroundDrawable = self.enviroDR
self.enviroDR.setTextureReloadPriority(-10)
if self.pixelZoomSetup:
self.setupAutoPixelZoom()
def setupAutoPixelZoom(self):
self.win.setPixelZoom(1)
self.enviroDR.setPixelZoom(1)
if not self.stereoEnabled:
self.enviroDR.setClearColorActive(True)
self.enviroDR.setClearDepthActive(True)
self.win.setClearColorActive(False)
self.win.setClearDepthActive(False)
self.backgroundDrawable = self.enviroDR
else:
self.enviroDR.setClearColorActive(False)
self.enviroDR.setClearDepthActive(False)
self.enviroDR.getRightEye().setClearDepthActive(True)
self.win.setClearColorActive(True)
self.win.setClearDepthActive(True)
self.backgroundDrawable = self.win
self.pixelZoomSetup = True
self.targetPixelZoom = 1.0
self.pixelZoomTask = None
self.pixelZoomCamHistory = 2.0
self.pixelZoomCamMovedList = []
self.pixelZoomStarted = None
flag = self.config.GetBool('enable-pixel-zoom', True)
self.enablePixelZoom(flag)
return
def enablePixelZoom(self, flag):
if not self.backgroundDrawable.supportsPixelZoom():
flag = False
self.pixelZoomEnabled = flag
taskMgr.remove('chasePixelZoom')
if flag:
taskMgr.add(self.__chasePixelZoom, 'chasePixelZoom', priority=-52)
else:
self.backgroundDrawable.setPixelZoom(1)
def __chasePixelZoom(self, task):
now = globalClock.getFrameTime()
pos = base.cam.getNetTransform().getPos()
prevPos = base.cam.getNetPrevTransform().getPos()
d2 = (pos - prevPos).lengthSquared()
if d2:
d = math.sqrt(d2)
self.pixelZoomCamMovedList.append((now, d))
while self.pixelZoomCamMovedList and self.pixelZoomCamMovedList[0][0] < now - self.pixelZoomCamHistory:
del self.pixelZoomCamMovedList[0]
dist = sum(map(lambda pair: pair[1], self.pixelZoomCamMovedList))
speed = dist / self.pixelZoomCamHistory
if speed < 5:
self.backgroundDrawable.setPixelZoom(4)
self.pixelZoomStart = None
elif speed > 10:
if self.pixelZoomStart == None:
self.pixelZoomStart = now
elapsed = now - self.pixelZoomStart
if elapsed > 10:
self.backgroundDrawable.setPixelZoom(16)
elif elapsed > 5:
self.backgroundDrawable.setPixelZoom(8)
return task.cont
def getShardPopLimits(self):
return (100, 200, -1)
def setLocationCode(self, locationCode):
if locationCode != self.locationCode:
self.locationCode = locationCode
self.locationCodeChanged = time.time()
def delayedErrorCheck(self, task):
if self.errorAccumulatorBuffer:
buffer = self.errorAccumulatorBuffer
self.errorAccumulatorBuffer = ''
self.notify.error('\nAccumulated Phase Errors!:\n %s' % buffer)
return task.cont
def loaderPhaseChecker(self, path, loaderOptions):
if 'audio/' in path:
return 1
file = Filename(path)
if not file.getExtension():
file.setExtension('bam')
mp = getModelPath()
path = mp.findFile(file).cStr()
if not path:
return
match = re.match('.*phase_([^/]+)/', path)
if not match:
if 'dmodels' in path:
return
else:
self.errorAccumulatorBuffer += 'file not in phase (%s, %s)\n' % (file, path)
return
basePhase = float(match.groups()[0])
model = loader.loader.loadSync(Filename(path), loaderOptions)
if model:
model = NodePath(model)
for tex in model.findAllTextures():
texPath = tex.getFullpath().cStr()
match = re.match('.*phase_([^/]+)/', texPath)
if match:
texPhase = float(match.groups()[0])
if texPhase > basePhase:
self.errorAccumulatorBuffer += 'texture phase is higher than the models (%s, %s)\n' % (path, texPath)
def getRepository(self):
return self.cr
def openMainWindow(self, *args, **kw):
result = ShowBase.openMainWindow(self, *args, **kw)
if result:
self.wantEnviroDR = not self.win.getGsg().isHardware() or config.GetBool('want-background-region', 1)
self.backgroundDrawable = self.win
return result
def run(self):
try:
taskMgr.run()
except SystemExit:
self.notify.info('Normal exit.')
self.destroy()
raise
except:
self.notify.warning('Handling Python exception.')
if getattr(self, 'cr', None):
if self.cr.timeManager:
from otp.otpbase import OTPGlobals
self.cr.timeManager.setDisconnectReason(OTPGlobals.DisconnectPythonError)
self.cr.timeManager.setExceptionInfo()
self.cr.sendDisconnect()
self.notify.info('Exception exit.\n')
self.destroy()
import traceback
traceback.print_exc()
@magicWord(category=CATEGORY_COMMUNITY_MANAGER)
def oobe():
"""
Toggle the 'out of body experience' view.
"""
base.oobe()
@magicWord(category=CATEGORY_PROGRAMMER)
def oobeCull():
"""
Toggle the 'out of body experience' view with culling debugging.
"""
base.oobeCull()
@magicWord(category=CATEGORY_COMMUNITY_MANAGER)
def wire():
"""
Toggle the 'wireframe' view.
"""
base.toggleWireframe()
@magicWord(category=CATEGORY_COMMUNITY_MANAGER)
def idNametags():
"""
Display avatar IDs inside nametags.
"""
messenger.send('nameTagShowAvId')
@magicWord(category=CATEGORY_COMMUNITY_MANAGER)
def nameNametags():
"""
Display only avatar names inside nametags.
"""
messenger.send('nameTagShowName')
@magicWord(category=CATEGORY_COMMUNITY_MANAGER)
def a2d():
"""
Toggle aspect2d.
"""
if aspect2d.isHidden():
aspect2d.show()
else:
aspect2d.hide()
@magicWord(category=CATEGORY_COMMUNITY_MANAGER)
def placer():
"""
Toggle the camera placer.
"""
base.camera.place()
@magicWord(category=CATEGORY_COMMUNITY_MANAGER)
def explorer():
"""
Toggle the scene graph explorer.
"""
base.render.explore()
@magicWord(category=CATEGORY_COMMUNITY_MANAGER)
def neglect():
"""
toggle the neglection of network updates on the invoker's client.
"""
if base.cr.networkPlugPulled():
base.cr.restoreNetworkPlug()
return 'You are no longer neglecting network updates.'
else:
base.cr.pullNetworkPlug()
return 'You are now neglecting network updates.'
@magicWord(category=CATEGORY_COMMUNITY_MANAGER, types=[float, float, float, float])
def backgroundColor(r=None, g=1, b=1, a=1):
"""
set the background color. Specify no arguments for the default background
color.
"""
if r is None:
r, g, b, a = OTPGlobals.DefaultBackgroundColor
base.setBackgroundColor(Vec4(r, g, b, a))
return 'The background color has been changed.'