open_toontown_panda3d/direct/src/distributed/DistributedCamera.py

264 lines
8.1 KiB
Python
Executable File

from panda3d.core import ConfigVariableInt, GeomNode, NodePath, PerspectiveLens, Point3, VBase2
from direct.fsm.FSM import FSM
from direct.interval.IntervalGlobal import LerpScaleInterval, Sequence
from direct.distributed.DistributedObject import DistributedObject
from direct.showbase.MessengerGlobal import messenger
_camera_id = ConfigVariableInt('camera-id', -1)
_aware_of_cameras = ConfigVariableInt('aware-of-cameras', 0)
class Fixture(NodePath, FSM):
def __init__(self, id, parent, pos, hpr, fov):
NodePath.__init__(self, 'cam-%s' % id)
FSM.__init__(self, '%s-fsm' % self.getName())
self.id = id
self.lens = PerspectiveLens()
self.lens.setFov(base.camLens.getFov())
model = base.loader.loadModel('models/misc/camera', okMissing = True)
model.reparentTo(self)
self.reparentTo(parent)
self.setPos(pos)
self.setHpr(hpr)
self.setFov(fov)
self.setLightOff(100)
self.hide()
self.scaleIval = None
self.recordingInProgress = False
self.dirty = False
def __str__(self):
return 'Fixture(%d, \'%s\', %s, %s, %s)' % (self.id, self.state, self.getPos(), self.getHpr(), self.getFov())
def pack(self):
return 'Camera(%s, %s, %s)' % (self.getPos(), self.getHpr(), self.getFov())
def setId(self, id):
self.id = id
def setFov(self, fov):
"""
fov should be a VBase2. Use VBase2(0) to indicate default.
"""
if fov != VBase2(0):
self.lens.setFov(fov)
self.setupFrustum()
def adjustFov(self, x, y):
fov = self.lens.getFov()
self.lens.setFov(fov[0]+x, fov[1]+y)
self.dirty = True
def getFov(self):
return self.lens.getFov()
def setupFrustum(self):
oldFrustum = self.find('frustum')
if oldFrustum:
oldFrustum.detachNode()
self.attachNewNode(GeomNode('frustum')).node().addGeom(self.lens.makeGeometry())
def setRecordingInProgress(self, inProgress):
self.recordingInProgress = inProgress
if self.recordingInProgress and _camera_id.value >= 0:
self.hide()
else:
self.show()
def show(self):
if _aware_of_cameras and not self.recordingInProgress:
NodePath.show(self)
def getScaleIval(self):
if not self.scaleIval:
self.scaleIval = Sequence(LerpScaleInterval(self.getChild(0), 0.25, 2, startScale = 1, blendType = 'easeInOut'),
LerpScaleInterval(self.getChild(0), 0.25, 1, startScale = 2, blendType = 'easeInOut'))
return self.scaleIval
def setState(self, state):
self.request(state)
def defaultFilter(self, request, args):
if request == self.getCurrentOrNextState():
return None
return FSM.defaultFilter(self, request, args)
def exitOff(self):
self.accept('recordingInProgress', self.setRecordingInProgress)
def enterOff(self):
self.ignore('recordingInProgress')
if self.scaleIval:
self.scaleIval.finish()
self.scaleIval = None
self.hide()
def enterStandby(self):
self.show()
if self.id == _camera_id.value:
self.setColorScale(3,0,0,1)
self.getScaleIval().loop()
else:
self.setColorScale(3,3,0,1)
self.getScaleIval().finish()
def enterBlinking(self):
self.show()
self.setColorScale(0,3,0,1)
self.getScaleIval().loop()
def exitBlinking(self):
if self.scaleIval:
self.scaleIval.finish()
def enterRecording(self):
if _camera_id.value == self.id:
self.demand('Using')
else:
self.show()
self.setColorScale(3,0,0,1)
self.getScaleIval().loop()
def exitRecording(self):
if self.scaleIval:
self.scaleIval.finish()
def enterUsing(self, args = []):
localAvatar.b_setGameState('Camera')
base.camera.setPosHpr(0,0,0,0,0,0)
base.camera.reparentTo(self)
self.hide()
base.cam.node().setLens(self.lens)
if args and args[0]:
self.accept('arrow_left', self.adjustFov, [-0.5,0])
self.accept('arrow_left-repeat', self.adjustFov, [-2,0])
self.accept('arrow_right', self.adjustFov, [0.5,0])
self.accept('arrow_right-repeat', self.adjustFov, [2,0])
self.accept('arrow_down', self.adjustFov, [0,-0.5])
self.accept('arrow_down-repeat', self.adjustFov, [0,-2])
self.accept('arrow_up', self.adjustFov, [0,0.5])
self.accept('arrow_up-repeat', self.adjustFov, [0,2])
# Could be toggled on/off on a fixture by fixture basis
# if added to the dc definition of the Fixture struct and
# saved out to the Camera file.
lodNodes = render.findAllMatches('**/+LODNode')
for lodNode in lodNodes:
lodNode.node().forceSwitch(lodNode.node().getHighestSwitch())
def exitUsing(self):
self.ignore('arrow_left')
self.ignore('arrow_left-repeat')
self.ignore('arrow_right')
self.ignore('arrow_right-repeat')
self.ignore('arrow_down')
self.ignore('arrow_down-repeat')
self.ignore('arrow_up')
self.ignore('arrow_up-repeat')
base.cam.node().setLens(base.camLens)
localAvatar.b_setGameState('LandRoam')
self.show()
if self.dirty:
messenger.send('refresh-fixture', [self.id, self.pack()])
self.dirty = False
class DistributedCamera(DistributedObject):
def __init__(self, cr):
DistributedObject.__init__(self, cr)
self.parent = None
self.fixtures = {}
self.cameraId = _camera_id.value
def __getitem__(self, index):
return self.fixtures.get(index)
def __str__(self):
out = ''
for fixture in self.fixtures.values():
out = '%s\n%s' % (out, fixture)
return out[1:]
def pack(self):
out = ''
for fixture in self.fixtures.values():
out = '%s\n%s' % (out, fixture.pack())
return out[1:]
def disable(self):
self.ignore('escape')
self.parent = None
for fixture in self.fixtures.values():
fixture.cleanup()
fixture.detachNode()
self.fixtures = {}
DistributedObject.disable(self)
def getOV(self):
return self.cr.doId2ownerView.get(self.getDoId())
def setCamParent(self, doId):
if doId != self.parent:
if not doId:
self.parent = render
else:
self.parent = self.cr.getDo(doId)
for fix in self.fixtures.values():
fix.reparentTo(self.parent)
def getCamParent(self):
return self.parent
def setFixtures(self, fixtures):
for x in range(len(fixtures), len(self.fixtures)):
fixture = self.fixtures.pop(x)
fixture.cleanup()
fixture.detachNode()
recordingInProgress = False
for x,fixture in enumerate(fixtures):
pos = Point3(*(fixture[:3]))
hpr = Point3(*(fixture[3:6]))
fov = VBase2(*(fixture[6:8]))
state = fixture[8]
if x not in self.fixtures:
self.fixtures[x] = Fixture(x, self.parent, Point3(0), hpr = Point3(0), fov = VBase2(0))
fix = self.fixtures.get(x)
fix.setId(x)
fix.setPosHpr(pos,hpr)
fix.setState(state)
fix.setFov(fov)
recordingInProgress |= state == 'Recording'
messenger.send('recordingInProgress', [recordingInProgress])
def testFixture(self, index):
fixture = self.fixtures.get(index)
if fixture:
fixture.request('Using', [True])
self.accept('escape', self.stopTesting, [index])
def stopTesting(self, index):
fixture = self.fixtures.get(index)
if fixture:
self.ignore('escape')
fixture.request('Standby')
localAvatar.b_setGameState('LandRoam')