*** empty log message ***

This commit is contained in:
Dustin Barnard 2007-09-12 23:51:55 +00:00
parent ccfffc6fdc
commit 30f14e0b2c
3 changed files with 308 additions and 12 deletions

View File

@ -51,6 +51,16 @@ class ClusterClient(DirectObject.DirectObject):
self.qcm=QueuedConnectionManager()
self.serverList = []
self.msgHandler = ClusterMsgHandler(ClusterClient.MGR_NUM, self.notify)
# A dictionary of objects that can be accessed by name
self.objectMappings = {}
# a dictionary of name objects and the corresponding names of
# objects they are to control on the server side
self.controlMappings = {}
self.controlOffsets = {}
self.taggedObjects = {}
for serverConfig in configList:
server = DisplayConnection(
self.qcm, serverConfig.serverName,
@ -78,6 +88,27 @@ class ClusterClient(DirectObject.DirectObject):
self.notify.debug('post startMoveCam')
self.startMoveSelectedTask()
def startReaderPollTask(self):
""" Task to handle datagrams from server """
# Run this task just after the listener poll task
taskMgr.add(self._readerPollTask, "clientReaderPollTask", -39)
def _readerPollTask(self, state):
""" Non blocking task to read all available datagrams """
for server in self.serverList:
datagrams = server.poll()
for data in datagrams:
self.handleDatagram(data[0],data[1])
return Task.cont
def startControlObjectTask(self):
self.notify.debug("moving control objects")
taskMgr.add(self.controlObjectTask,"controlObjectTask")
def startSynchronizeTimeTask(self):
self.notify.debug('broadcasting frame time')
taskMgr.add(self.synchronizeTimeTask, "synchronizeTimeTask", -40)
@ -94,6 +125,27 @@ class ClusterClient(DirectObject.DirectObject):
self.notify.debug('adding move cam')
taskMgr.add(self.moveCameraTask, "moveCamTask", 49)
def controlObjectTask(self, task):
for object in self.controlMappings:
name = self.controlMappings[object][0]
serverList = self.controlMappings[object][1]
if (self.objectMapping.has_key(object)):
self.moveObject(self.objectMappings[object],name,serverList,
self.controlOffsets[object])
return Task.cont
def moveObject(self, nodePath, object, serverList, offset):
self.notify.debug('moving object '+object)
xyz = nodePath.getPos(render) + offset
hpr = nodePath.getHpr(render)
scale = nodePath.getScale(render)
hidden = nodePath.isHidden()
for server in serverList:
self.serverList[server].sendMoveNamedObject(xyz,hpr,scale,hidden,object)
def moveCameraTask(self, task):
self.moveCamera(
base.camera.getPos(render),
@ -120,6 +172,39 @@ class ClusterClient(DirectObject.DirectObject):
server.sendMoveSelected(xyz, hpr, scale)
return Task.cont
def addNamedObjectMapping(self,object,name):
if (not self.objectMappings.has_key(name)):
self.objectMappings[name] = object
else:
self.notify.debug('attempt to add duplicate named object: '+name)
def removeObjectMapping(self,name):
if (self.objectMappings.has_key(name)):
self.objectMappings.pop(name)
def addControlMapping(self,objectName,controlledName, serverList = None,
offset = None):
if (not self.controlMappings.has_key(objectName)):
if (serverList == None):
serverList = range(len(self.serverList))
if (offset == None):
offset = Vec3(0,0,0)
self.controlMappings[objectName] = [controlledName,serverList]
self.controlOffsets[objectName] = offset
else:
self.notify.debug('attempt to add duplicate controlled object: '+name)
def setControlMappingOffset(self,objectName,offset):
if (self.controlMappings.has_key(objectName)):
self.controlOffsets[objectName] = offset
def removeControlMapping(self,name):
if (self.controlMappings.has_key(name)):
self.controlMappings.pop(name)
def getNodePathFindCmd(self, nodePath):
import string
pathString = `nodePath`
@ -131,10 +216,53 @@ class ClusterClient(DirectObject.DirectObject):
else:
return rootName
def getNodePathName(self, nodePath):
import string
pathString = `nodePath`
index = string.find(pathString, '/')
if index != -1:
name = pathString[index+1:]
return name
else:
return pathString
def addObjectTag(self,object,selectFunction,deselectFunction,selectArgs,deselectArgs):
newTag = {}
newTag["selectFunction"] = selectFunction
newTag["selectArgs"] = selectArgs
newTag["deselectFunction"] = deselectFunction
newTag["deselectArgs"] = deselectArgs
self.taggedObjects[object] = newTag
def removeObjectTag(self,object):
self.taggedObjects.pop(object)
def selectNodePath(self, nodePath):
self(self.getNodePathFindCmd(nodePath) + '.select()', 0)
name = self.getNodePathName(nodePath)
if self.taggedObjects.has_key(name):
taskMgr.remove("moveSelectedTask")
tag = self.taggedObjects[name]
function = tag["selectFunction"]
args = tag["selectArgs"]
if (function != None):
function(*args)
else:
self(self.getNodePathFindCmd(nodePath) + '.select()', 0)
def deselectNodePath(self, nodePath):
name = self.getNodePathName(nodePath)
if self.taggedObjects.has_key(name):
tag = self.taggedObjects[name]
function = tag["deselectFunction"]
args = tag["deselectArgs"]
if (function != None):
function(*args)
self.startMoveSelectedTask()
self(self.getNodePathFindCmd(nodePath) + '.deselect()', 0)
def sendCamFrustum(self, focalLength, filmSize, filmOffset, indexList=[]):
@ -163,6 +291,31 @@ class ClusterClient(DirectObject.DirectObject):
# Execute locally
exec(commandString, __builtins__)
def handleDatagram(self,dgi,type):
if (type == CLUSTER_NONE):
pass
elif (type == CLUSTER_NAMED_OBJECT_MOVEMENT):
self.handleNamedMovement(dgi)
else:
self.notify.warning("Received unsupported packet type:" % type)
return type
def handleNamedMovement(self, dgi):
""" Update cameraJig position to reflect latest position """
(name,x, y, z, h, p, r, sx, sy, sz, hidden) = self.msgHandler.parseNamedMovementDatagram(
dgi)
if (self.objectMappings.has_key(name)):
self.objectMappings[name].setPosHpr(render, x, y, z, h, p, r)
self.objectMappings[name].setScale(render,sx,sy,sz)
if (hidden):
self.objectMappings[name].hide()
else:
self.objectMappings[name].show()
else:
self.notify.debug("recieved unknown named object command: "+name)
def exit(self):
# Execute remotely
for server in self.serverList:
@ -178,6 +331,7 @@ class ClusterClientSync(ClusterClient):
#I probably don't need this
self.waitForSwap = 0
self.ready = 0
print "creating synced client"
self.startSwapCoordinatorTask()
def startSwapCoordinatorTask(self):
@ -200,6 +354,8 @@ class ClusterClientSync(ClusterClient):
base.graphicsEngine.flipFrame()
self.notify.debug(
"------------------------------------------END swap")
#print "syncing"
return Task.cont
def moveCamera(self, xyz, hpr):
@ -226,6 +382,25 @@ class DisplayConnection:
self.qcr.addConnection(self.tcpConn)
self.cw=ConnectionWriter(qcm, 0)
def poll(self):
""" Non blocking task to read all available datagrams """
dataGrams = []
while 1:
(datagram, dgi, type) = self.msgHandler.nonBlockingRead(self.qcr)
# Queue is empty, done for now
if type is CLUSTER_NONE:
break
else:
# Got a datagram, add it to the list
dataGrams.append([dgi, type, datagram])
return dataGrams
def sendCamOffset(self, xyz, hpr):
ClusterClient.notify.debug("send cam offset...")
ClusterClient.notify.debug(("packet %d xyz, hpr=%f %f %f %f %f %f" %
@ -246,6 +421,16 @@ class DisplayConnection:
focalLength, filmSize, filmOffset)
self.cw.send(datagram, self.tcpConn)
def sendMoveNamedObject(self, xyz, hpr, name):
ClusterClient.notify.debug("send named object move...")
ClusterClient.notify.debug(("packet %d xyz, hpr=%f %f %f %f %f %f" %
(self.msgHandler.packetNumber, xyz[0], xyz[1], xyz[2],
hpr[0], hpr[1], hpr[2])))
datagram = self.msgHandler.makeNamedObjectMovementDatagram(xyz, hpr,
name)
self.cw.send(datagram, self.tcpConn)
def sendMoveCam(self, xyz, hpr):
ClusterClient.notify.debug("send cam move...")
ClusterClient.notify.debug(("packet %d xyz, hpr=%f %f %f %f %f %f" %

View File

@ -9,16 +9,17 @@ from direct.distributed.PyDatagramIterator import PyDatagramIterator
import time
#these are the types of messages that are currently supported.
CLUSTER_NONE = 0
CLUSTER_CAM_OFFSET = 1
CLUSTER_CAM_FRUSTUM = 2
CLUSTER_CAM_MOVEMENT = 3
CLUSTER_SWAP_READY = 4
CLUSTER_SWAP_NOW = 5
CLUSTER_COMMAND_STRING = 6
CLUSTER_SELECTED_MOVEMENT = 7
CLUSTER_TIME_DATA = 8
CLUSTER_EXIT = 100
CLUSTER_NONE = 0
CLUSTER_CAM_OFFSET = 1
CLUSTER_CAM_FRUSTUM = 2
CLUSTER_CAM_MOVEMENT = 3
CLUSTER_SWAP_READY = 4
CLUSTER_SWAP_NOW = 5
CLUSTER_COMMAND_STRING = 6
CLUSTER_SELECTED_MOVEMENT = 7
CLUSTER_TIME_DATA = 8
CLUSTER_NAMED_OBJECT_MOVEMENT = 9
CLUSTER_EXIT = 100
#Port number for cluster rendering
# DAEMON PORT IS PORT USED FOR STARTUP MESSAGE EXCHANGE
@ -156,6 +157,24 @@ class ClusterMsgHandler:
datagram.addFloat32(hpr[2])
return datagram
def makeNamedObjectMovementDatagram(self, xyz, hpr, scale, hidden, name):
datagram = PyDatagram()
datagram.addUint32(self.packetNumber)
self.packetNumber = self.packetNumber + 1
datagram.addUint8(CLUSTER_NAMED_OBJECT_MOVEMENT)
datagram.addString(name)
datagram.addFloat32(xyz[0])
datagram.addFloat32(xyz[1])
datagram.addFloat32(xyz[2])
datagram.addFloat32(hpr[0])
datagram.addFloat32(hpr[1])
datagram.addFloat32(hpr[2])
datagram.addFloat32(scale[0])
datagram.addFloat32(scale[1])
datagram.addFloat32(scale[2])
datagram.addBool(hidden)
return datagram
def parseCamMovementDatagram(self, dgi):
x=dgi.getFloat32()
y=dgi.getFloat32()
@ -167,6 +186,21 @@ class ClusterMsgHandler:
(x, y, z, h, p, r)))
return (x, y, z, h, p, r)
def parseNamedMovementDatagram(self, dgi):
name = dgi.getString()
x=dgi.getFloat32()
y=dgi.getFloat32()
z=dgi.getFloat32()
h=dgi.getFloat32()
p=dgi.getFloat32()
r=dgi.getFloat32()
sx = dgi.getFloat32()
sy = dgi.getFloat32()
sz = dgi.getFloat32()
hidden = dgi.getBool()
return (name,x, y, z, h, p, r, sx, sy, sz, hidden)
def makeSelectedMovementDatagram(self, xyz, hpr, scale):
datagram = PyDatagram()
datagram.addUint32(self.packetNumber)
@ -181,6 +215,7 @@ class ClusterMsgHandler:
datagram.addFloat32(scale[0])
datagram.addFloat32(scale[1])
datagram.addFloat32(scale[2])
#datagram.addBool(hidden)
return datagram
def parseSelectedMovementDatagram(self, dgi):

View File

@ -54,6 +54,12 @@ class ClusterServer(DirectObject.DirectObject):
globalClock.setMode(ClockObject.MSlave)
# Send verification of startup to client
self.daemon = DirectD()
self.objectMappings = {}
self.controlMappings = {}
self.controlOffsets = {}
# These must be passed in as bootstrap arguments and stored in
# the __builtins__ namespace
try:
@ -66,6 +72,8 @@ class ClusterServer(DirectObject.DirectObject):
clusterDaemonPort = CLUSTER_DAEMON_PORT
self.daemon.serverReady(clusterDaemonClient, clusterDaemonPort)
def startListenerPollTask(self):
# Run this task near the start of frame, sometime after the dataLoop
taskMgr.add(self.listenerPollTask, "serverListenerPollTask", -40)
@ -88,6 +96,58 @@ class ClusterServer(DirectObject.DirectObject):
self.notify.warning("getNewConnection returned false")
return Task.cont
def addNamedObjectMapping(self,object,name):
if (not self.objectMappings.has_key(name)):
self.objectMappings[name] = object
else:
self.notify.debug('attempt to add duplicate named object: '+name)
def removeObjectMapping(self,name):
if (self.objectMappings.has_key(name)):
self.objectMappings.pop(name)
def addControlMapping(self,objectName,controlledName, offset = None):
if (not self.controlMappings.has_key(objectName)):
self.controlMappings[objectName] = controlledName
if (offset == None):
offset = Vec3(0,0,0)
self.controlOffsets[objectName] = offset
else:
self.notify.debug('attempt to add duplicate controlled object: '+name)
def setControlMappingOffset(self,objectName,offset):
if (self.controlMappings.has_key(objectName)):
self.controlOffsets[objectName] = offset
def removeControlMapping(self,name):
if (self.controlMappings.has_key(name)):
self.controlMappings.pop(name)
def startControlObjectTask(self):
self.notify.debug("moving control objects")
taskMgr.add(self.controlObjectTask,"controlObjectTask")
def controlObjectTask(self, task):
for object in self.controlMappings:
name = self.controlMappings[object]
if (self.objectMappings.has_key(object)):
self.moveObject(self.objectMappings[object],name,self.controlOffsets[object])
return Task.cont
def moveObject(self, nodePath, object, offset):
self.notify.debug('moving object '+object)
xyz = nodePath.getPos(render) + offset
hpr = nodePath.getHpr(render)
scale = nodePath.getScale(render)
hidden = nodePath.isHidden()
datagram = self.msgHandler.makeNamedObjectMovementDatagram(xyz,hpr,scale,hidden,object)
self.cw.send(datagram, self.lastConnection)
def startReaderPollTask(self):
""" Task to handle datagrams from client """
# Run this task just after the listener poll task
@ -171,6 +231,8 @@ class ClusterServer(DirectObject.DirectObject):
elif (type == CLUSTER_TIME_DATA):
self.notify.debug('time data')
self.handleTimeData(dgi)
elif (type == CLUSTER_NAMED_OBJECT_MOVEMENT):
self.handleNamedMovement(dgi)
else:
self.notify.warning("Received unknown packet type:" % type)
return type
@ -189,11 +251,25 @@ class ClusterServer(DirectObject.DirectObject):
self.lens.setFilmSize(fs[0], fs[1])
self.lens.setFilmOffset(fo[0], fo[1])
def handleNamedMovement(self, dgi):
""" Update cameraJig position to reflect latest position """
(name,x, y, z, h, p, r,sx,sy,sz, hidden) = self.msgHandler.parseNamedMovementDatagram(
dgi)
if (self.objectMappings.has_key(name)):
self.objectMappings[name].setPosHpr(render, x, y, z, h, p, r)
self.objectMappings[name].setScale(render,sx,sy,sz)
if (hidden):
self.objectMappings[name].hide()
else:
self.objectMappings[name].show()
else:
self.notify.debug("recieved unknown named object command: "+name)
def handleCamMovement(self, dgi):
""" Update cameraJig position to reflect latest position """
(x, y, z, h, p, r) = self.msgHandler.parseCamMovementDatagram(dgi)
self.cameraJig.setPosHpr(render, x, y, z, h, p, r)
self.fPosReceived = 1
self.fPosReceived = 1
def handleSelectedMovement(self, dgi):
""" Update cameraJig position to reflect latest position """