direct: More code style changes

This commit is contained in:
rdb 2023-02-22 11:42:13 +01:00
parent 9a15e9245c
commit 37b5c9ad9e
112 changed files with 1312 additions and 775 deletions

View File

@ -493,7 +493,8 @@ disable=raw-checker-failed,
using-constant-test, using-constant-test,
wrong-import-order, wrong-import-order,
wrong-import-position, wrong-import-position,
not-callable not-callable,
wildcard-import
# Enable the message, report, category or checker with the given id(s). You can # Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option # either give multiple identifier separated by comma (,) or put this option
@ -615,6 +616,7 @@ contextmanager-decorators=contextlib.contextmanager
# expressions are accepted. # expressions are accepted.
generated-members=base.cr, generated-members=base.cr,
base.le, base.le,
base.localAvatar,
Pmw.AboutDialog, Pmw.AboutDialog,
Pmw.Balloon, Pmw.Balloon,
Pmw.ButtonBox, Pmw.ButtonBox,
@ -629,8 +631,10 @@ generated-members=base.cr,
Pmw.MenuBar, Pmw.MenuBar,
Pmw.MessageBar, Pmw.MessageBar,
Pmw.NoteBook, Pmw.NoteBook,
Pmw.OK,
Pmw.OptionMenu, Pmw.OptionMenu,
Pmw.OptionMenu, Pmw.OptionMenu,
Pmw.PARTIAL,
Pmw.PanedWidget, Pmw.PanedWidget,
Pmw.ScrolledCanvas, Pmw.ScrolledCanvas,
Pmw.ScrolledFrame, Pmw.ScrolledFrame,
@ -640,8 +644,10 @@ generated-members=base.cr,
Pmw.aboutcopyright, Pmw.aboutcopyright,
Pmw.aboutversion, Pmw.aboutversion,
Pmw.forwardmethods, Pmw.forwardmethods,
Pmw.integervalidator,
Pmw.popgrab, Pmw.popgrab,
Pmw.pushgrab, Pmw.pushgrab,
Pmw.realvalidator,
Pmw.setgeometryanddeiconify Pmw.setgeometryanddeiconify
# Tells whether to warn about missing members when the owner of the attribute # Tells whether to warn about missing members when the owner of the attribute
@ -699,7 +705,8 @@ additional-builtins=base,
cluster, cluster,
launcher, launcher,
taskMgr, taskMgr,
localAvatar localAvatar,
game
# Tells whether unused global variables should be treated as a violation. # Tells whether unused global variables should be treated as a violation.
allow-global-unused-variables=yes allow-global-unused-variables=yes

View File

@ -113,7 +113,6 @@ class ClusterClient(DirectObject.DirectObject):
self.notify.debug('post startMoveCam') self.notify.debug('post startMoveCam')
self.startMoveSelectedTask() self.startMoveSelectedTask()
def startReaderPollTask(self): def startReaderPollTask(self):
""" Task to handle datagrams from server """ """ Task to handle datagrams from server """
# Run this task just after the listener poll task # Run this task just after the listener poll task
@ -130,7 +129,6 @@ class ClusterClient(DirectObject.DirectObject):
return Task.cont return Task.cont
def startControlObjectTask(self): def startControlObjectTask(self):
self.notify.debug("moving control objects") self.notify.debug("moving control objects")
taskMgr.add(self.controlObjectTask,"controlObjectTask",50) taskMgr.add(self.controlObjectTask,"controlObjectTask",50)
@ -152,7 +150,6 @@ class ClusterClient(DirectObject.DirectObject):
self.notify.debug('adding move cam') self.notify.debug('adding move cam')
taskMgr.add(self.moveCameraTask, "moveCamTask", 49) taskMgr.add(self.moveCameraTask, "moveCamTask", 49)
def controlObjectTask(self, task): def controlObjectTask(self, task):
for pair in self.sortedControlMappings: for pair in self.sortedControlMappings:
object = pair[1] object = pair[1]
@ -171,8 +168,6 @@ class ClusterClient(DirectObject.DirectObject):
for server in serverList: for server in serverList:
self.serverList[server].sendNamedMovementDone() self.serverList[server].sendNamedMovementDone()
def redoSortedPriorities(self): def redoSortedPriorities(self):
self.sortedControlMappings = [] self.sortedControlMappings = []
for key in self.controlMappings: for key in self.controlMappings:
@ -194,7 +189,6 @@ class ClusterClient(DirectObject.DirectObject):
for server in serverList: for server in serverList:
self.serverList[server].sendMoveNamedObject(xyz,hpr,scale,color,hidden,object) self.serverList[server].sendMoveNamedObject(xyz,hpr,scale,color,hidden,object)
def moveCameraTask(self, task): def moveCameraTask(self, task):
self.moveCamera( self.moveCamera(
base.camera.getPos(render), base.camera.getPos(render),
@ -221,7 +215,6 @@ class ClusterClient(DirectObject.DirectObject):
server.sendMoveSelected(xyz, hpr, scale) server.sendMoveSelected(xyz, hpr, scale)
return Task.cont return Task.cont
def addNamedObjectMapping(self, object, name, hasColor = True): def addNamedObjectMapping(self, object, name, hasColor = True):
if name not in self.objectMappings: if name not in self.objectMappings:
self.objectMappings[name] = object self.objectMappings[name] = object
@ -233,7 +226,6 @@ class ClusterClient(DirectObject.DirectObject):
if name in self.objectMappings: if name in self.objectMappings:
self.objectMappings.pop(name) self.objectMappings.pop(name)
def addControlMapping(self, objectName, controlledName, serverList = None, def addControlMapping(self, objectName, controlledName, serverList = None,
offset = None, priority = 0): offset = None, priority = 0):
if objectName not in self.controlMappings: if objectName not in self.controlMappings:
@ -278,7 +270,6 @@ class ClusterClient(DirectObject.DirectObject):
self.controlPriorities.pop(name) self.controlPriorities.pop(name)
self.redoSortedPriorities() self.redoSortedPriorities()
def getNodePathFindCmd(self, nodePath): def getNodePathFindCmd(self, nodePath):
pathString = repr(nodePath) pathString = repr(nodePath)
index = pathString.find('/') index = pathString.find('/')
@ -298,7 +289,6 @@ class ClusterClient(DirectObject.DirectObject):
else: else:
return pathString return pathString
def addObjectTag(self,object,selectFunction,deselectFunction,selectArgs,deselectArgs): def addObjectTag(self,object,selectFunction,deselectFunction,selectArgs,deselectArgs):
newTag = {} newTag = {}
newTag["selectFunction"] = selectFunction newTag["selectFunction"] = selectFunction
@ -307,12 +297,10 @@ class ClusterClient(DirectObject.DirectObject):
newTag["deselectArgs"] = deselectArgs newTag["deselectArgs"] = deselectArgs
self.taggedObjects[object] = newTag self.taggedObjects[object] = newTag
def removeObjectTag(self,object): def removeObjectTag(self,object):
self.taggedObjects.pop(object) self.taggedObjects.pop(object)
def selectNodePath(self, nodePath): def selectNodePath(self, nodePath):
name = self.getNodePathName(nodePath) name = self.getNodePathName(nodePath)
if name in self.taggedObjects: if name in self.taggedObjects:
@ -325,7 +313,6 @@ class ClusterClient(DirectObject.DirectObject):
else: else:
self(self.getNodePathFindCmd(nodePath) + '.select()', 0) self(self.getNodePathFindCmd(nodePath) + '.select()', 0)
def deselectNodePath(self, nodePath): def deselectNodePath(self, nodePath):
name = self.getNodePathName(nodePath) name = self.getNodePathName(nodePath)
if name in self.taggedObjects: if name in self.taggedObjects:
@ -363,7 +350,6 @@ class ClusterClient(DirectObject.DirectObject):
# Execute locally # Execute locally
exec(commandString, __builtins__) exec(commandString, __builtins__)
def handleDatagram(self,dgi,type,server): def handleDatagram(self,dgi,type,server):
if type == CLUSTER_NONE: if type == CLUSTER_NONE:
pass pass
@ -388,7 +374,6 @@ class ClusterClient(DirectObject.DirectObject):
# clear the queue # clear the queue
self.serverQueues[server] = [] self.serverQueues[server] = []
def handleNamedMovement(self, data): def handleNamedMovement(self, data):
""" Update cameraJig position to reflect latest position """ """ Update cameraJig position to reflect latest position """
@ -408,7 +393,6 @@ class ClusterClient(DirectObject.DirectObject):
else: else:
self.notify.debug("recieved unknown named object command: "+name) self.notify.debug("recieved unknown named object command: "+name)
def exit(self): def exit(self):
# Execute remotely # Execute remotely
for server in self.serverList: for server in self.serverList:
@ -475,8 +459,6 @@ class DisplayConnection:
self.qcr.addConnection(self.tcpConn) self.qcr.addConnection(self.tcpConn)
self.cw=ConnectionWriter(qcm, 0) self.cw=ConnectionWriter(qcm, 0)
def poll(self): def poll(self):
""" Non blocking task to read all available datagrams """ """ Non blocking task to read all available datagrams """
dataGrams = [] dataGrams = []
@ -491,9 +473,6 @@ class DisplayConnection:
return dataGrams return dataGrams
def sendCamOffset(self, xyz, hpr): def sendCamOffset(self, xyz, hpr):
ClusterClient.notify.debug("send cam offset...") ClusterClient.notify.debug("send cam offset...")
ClusterClient.notify.debug(("packet %d xyz, hpr=%f %f %f %f %f %f" % ClusterClient.notify.debug(("packet %d xyz, hpr=%f %f %f %f %f %f" %
@ -509,12 +488,11 @@ class DisplayConnection:
(" fl, fs, fo=%0.3f, (%0.3f, %0.3f), (%0.3f, %0.3f)" % (" fl, fs, fo=%0.3f, (%0.3f, %0.3f), (%0.3f, %0.3f)" %
(focalLength, filmSize[0], filmSize[1], (focalLength, filmSize[0], filmSize[1],
filmOffset[0], filmOffset[1]))) filmOffset[0], filmOffset[1])))
) )
datagram = self.msgHandler.makeCamFrustumDatagram( datagram = self.msgHandler.makeCamFrustumDatagram(
focalLength, filmSize, filmOffset) focalLength, filmSize, filmOffset)
self.cw.send(datagram, self.tcpConn) self.cw.send(datagram, self.tcpConn)
def sendNamedMovementDone(self): def sendNamedMovementDone(self):
datagram = self.msgHandler.makeNamedMovementDone() datagram = self.msgHandler.makeNamedMovementDone()
@ -584,6 +562,7 @@ class DisplayConnection:
frameCount, frameTime, dt) frameCount, frameTime, dt)
self.cw.send(datagram, self.tcpConn) self.cw.send(datagram, self.tcpConn)
class ClusterConfigItem: class ClusterConfigItem:
def __init__(self, serverConfigName, serverName, def __init__(self, serverConfigName, serverName,
serverDaemonPort, serverMsgPort): serverDaemonPort, serverMsgPort):
@ -599,9 +578,11 @@ class ClusterConfigItem:
self.focalLength = None self.focalLength = None
self.filmSize = None self.filmSize = None
self.filmOffset = None self.filmOffset = None
def setCamOffset(self, xyz, hpr): def setCamOffset(self, xyz, hpr):
self.xyz = xyz self.xyz = xyz
self.hpr = hpr self.hpr = hpr
def setCamFrustum(self, focalLength, filmSize, filmOffset): def setCamFrustum(self, focalLength, filmSize, filmOffset):
self.fFrustum = 1 self.fFrustum = 1
self.focalLength = focalLength self.focalLength = focalLength
@ -689,6 +670,7 @@ def createClusterClient():
class DummyClusterClient(DirectObject.DirectObject): class DummyClusterClient(DirectObject.DirectObject):
""" Dummy class to handle command strings when not in cluster mode """ """ Dummy class to handle command strings when not in cluster mode """
notify = DirectNotifyGlobal.directNotify.newCategory("DummyClusterClient") notify = DirectNotifyGlobal.directNotify.newCategory("DummyClusterClient")
def __init__(self): def __init__(self):
pass pass

View File

@ -26,7 +26,7 @@ ClientConfigs = {
'display mode': 'client', 'display mode': 'client',
'pos': Vec3(0), 'pos': Vec3(0),
'hpr': Vec3(0)} 'hpr': Vec3(0)}
], ],
'two-server': [{'display name': 'master', 'two-server': [{'display name': 'master',
'display mode': 'client', 'display mode': 'client',
'pos': Vec3(0), 'pos': Vec3(0),
@ -35,7 +35,7 @@ ClientConfigs = {
'pos': Vec3(0), 'pos': Vec3(0),
'hpr': Vec3(0) 'hpr': Vec3(0)
} }
], ],
'three-server': [{'display name': 'master', 'three-server': [{'display name': 'master',
'display mode': 'client', 'display mode': 'client',
'pos': Vec3(0), 'pos': Vec3(0),
@ -48,14 +48,14 @@ ClientConfigs = {
'pos': Vec3(0), 'pos': Vec3(0),
'hpr': Vec3(0) 'hpr': Vec3(0)
} }
], ],
'mono-cave': [{'display name': 'la', 'mono-cave': [{'display name': 'la',
'pos': Vec3(-0.105, -0.020, 5.000), 'pos': Vec3(-0.105, -0.020, 5.000),
'hpr': Vec3(51.213, 0.000, 0.000), 'hpr': Vec3(51.213, 0.000, 0.000),
'focal length': 0.809, 'focal length': 0.809,
'film size': (1.000, 0.831), 'film size': (1.000, 0.831),
'film offset': (0.000, 0.173), 'film offset': (0.000, 0.173),
}, },
{'display name': 'lb', {'display name': 'lb',
'display mode': 'client', 'display mode': 'client',
'pos': Vec3(-0.105, -0.020, 5.000), 'pos': Vec3(-0.105, -0.020, 5.000),
@ -71,7 +71,7 @@ ClientConfigs = {
'film size': (1.000, 0.830), 'film size': (1.000, 0.830),
'film offset': (-0.000, 0.173), 'film offset': (-0.000, 0.173),
}, },
], ],
'seamless-cave': [{'display name': 'master', 'seamless-cave': [{'display name': 'master',
'display mode': 'client', 'display mode': 'client',
'pos': Vec3(-0.105, -0.020, 5.000), 'pos': Vec3(-0.105, -0.020, 5.000),
@ -79,7 +79,7 @@ ClientConfigs = {
'focal length': 0.815, 'focal length': 0.815,
'film size': (1.000, 0.831), 'film size': (1.000, 0.831),
'film offset': (0.000, 0.173), 'film offset': (0.000, 0.173),
}, },
{'display name': 'la', {'display name': 'la',
'pos': Vec3(-0.105, -0.020, 5.000), 'pos': Vec3(-0.105, -0.020, 5.000),
'hpr': Vec3(51.213, 0.000, 0.000), 'hpr': Vec3(51.213, 0.000, 0.000),
@ -122,12 +122,12 @@ ClientConfigs = {
'film size': (1.000, 0.831), 'film size': (1.000, 0.831),
'film offset': (-0.000, 0.173), 'film offset': (-0.000, 0.173),
}, },
], ],
'ursula': [{'display name': 'master', 'ursula': [{'display name': 'master',
'display mode': 'client', 'display mode': 'client',
'pos': Vec3(0), 'pos': Vec3(0),
'hpr': Vec3(0), 'hpr': Vec3(0),
}, },
{'display name': 'l', {'display name': 'l',
'pos': Vec3(-.105, 0, 0), 'pos': Vec3(-.105, 0, 0),
'hpr': Vec3(0, 0, 0), 'hpr': Vec3(0, 0, 0),
@ -144,11 +144,11 @@ ClientConfigs = {
#'film offset': (-0.105, -2), #'film offset': (-0.105, -2),
'film offset': (-0.105, -1), 'film offset': (-0.105, -1),
} }
], ],
'composite': [{'display name': 'master', 'composite': [{'display name': 'master',
'display mode': 'client', 'display mode': 'client',
'pos': Vec3(0), 'pos': Vec3(0),
}, },
{'display name': 'left', {'display name': 'left',
'pos': Vec3(-0.105, -0.020, 5.000), 'pos': Vec3(-0.105, -0.020, 5.000),
'hpr': Vec3(-0.370, 0.000, 0.000), 'hpr': Vec3(-0.370, 0.000, 0.000),
@ -163,5 +163,5 @@ ClientConfigs = {
'film size': (1.000, 0.831), 'film size': (1.000, 0.831),
'film offset': (0.000, 0.173), 'film offset': (0.000, 0.173),
} }
], ],
} }

View File

@ -40,6 +40,7 @@ import builtins
# Also, I'm not sure multiple camera-group configurations are working for the # Also, I'm not sure multiple camera-group configurations are working for the
# cluster system. # cluster system.
class ClusterServer(DirectObject.DirectObject): class ClusterServer(DirectObject.DirectObject):
notify = DirectNotifyGlobal.directNotify.newCategory("ClusterServer") notify = DirectNotifyGlobal.directNotify.newCategory("ClusterServer")
MSG_NUM = 2000000 MSG_NUM = 2000000
@ -101,8 +102,6 @@ class ClusterServer(DirectObject.DirectObject):
clusterDaemonPort = CLUSTER_DAEMON_PORT clusterDaemonPort = CLUSTER_DAEMON_PORT
self.daemon.serverReady(clusterDaemonClient, clusterDaemonPort) self.daemon.serverReady(clusterDaemonClient, clusterDaemonPort)
def startListenerPollTask(self): def startListenerPollTask(self):
# Run this task near the start of frame, sometime after the dataLoop # Run this task near the start of frame, sometime after the dataLoop
taskMgr.add(self.listenerPollTask, "serverListenerPollTask", -40) taskMgr.add(self.listenerPollTask, "serverListenerPollTask", -40)
@ -125,7 +124,6 @@ class ClusterServer(DirectObject.DirectObject):
self.notify.warning("getNewConnection returned false") self.notify.warning("getNewConnection returned false")
return Task.cont return Task.cont
def addNamedObjectMapping(self, object, name, hasColor = True, def addNamedObjectMapping(self, object, name, hasColor = True,
priority = 0): priority = 0):
if name not in self.objectMappings: if name not in self.objectMappings:
@ -138,7 +136,6 @@ class ClusterServer(DirectObject.DirectObject):
if name in self.objectMappings: if name in self.objectMappings:
self.objectMappings.pop(name) self.objectMappings.pop(name)
def redoSortedPriorities(self): def redoSortedPriorities(self):
self.sortedControlMappings = [] self.sortedControlMappings = []
@ -148,7 +145,6 @@ class ClusterServer(DirectObject.DirectObject):
self.sortedControlMappings.sort() self.sortedControlMappings.sort()
def addControlMapping(self, objectName, controlledName, offset = None, def addControlMapping(self, objectName, controlledName, offset = None,
priority = 0): priority = 0):
if objectName not in self.controlMappings: if objectName not in self.controlMappings:
@ -165,14 +161,12 @@ class ClusterServer(DirectObject.DirectObject):
if objectName in self.controlMappings: if objectName in self.controlMappings:
self.controlOffsets[objectName] = offset self.controlOffsets[objectName] = offset
def removeControlMapping(self, name): def removeControlMapping(self, name):
if name in self.controlMappings: if name in self.controlMappings:
self.controlMappings.pop(name) self.controlMappings.pop(name)
self.controlPriorities.pop(name) self.controlPriorities.pop(name)
self.redoSortedPriorities() self.redoSortedPriorities()
def startControlObjectTask(self): def startControlObjectTask(self):
self.notify.debug("moving control objects") self.notify.debug("moving control objects")
taskMgr.add(self.controlObjectTask,"controlObjectTask",50) taskMgr.add(self.controlObjectTask,"controlObjectTask",50)
@ -189,7 +183,6 @@ class ClusterServer(DirectObject.DirectObject):
self.sendNamedMovementDone() self.sendNamedMovementDone()
return Task.cont return Task.cont
def sendNamedMovementDone(self): def sendNamedMovementDone(self):
self.notify.debug("named movement done") self.notify.debug("named movement done")
datagram = self.msgHandler.makeNamedMovementDone() datagram = self.msgHandler.makeNamedMovementDone()
@ -333,7 +326,6 @@ class ClusterServer(DirectObject.DirectObject):
else: else:
self.notify.debug("recieved unknown named object command: "+name) self.notify.debug("recieved unknown named object command: "+name)
def handleMessageQueue(self): def handleMessageQueue(self):
#print(self.messageQueue) #print(self.messageQueue)
for data in self.messageQueue: for data in self.messageQueue:
@ -369,5 +361,5 @@ class ClusterServer(DirectObject.DirectObject):
command = self.msgHandler.parseCommandStringDatagram(dgi) command = self.msgHandler.parseCommandStringDatagram(dgi)
try: try:
exec(command, __builtins__) exec(command, __builtins__)
except: except Exception:
pass pass

View File

@ -41,8 +41,6 @@ class ControlManager:
#self.monitorTask = taskMgr.add(self.monitor, "ControlManager-%s"%(id(self)), priority=-1) #self.monitorTask = taskMgr.add(self.monitor, "ControlManager-%s"%(id(self)), priority=-1)
self.forceAvJumpToken = None self.forceAvJumpToken = None
if self.passMessagesThrough: # for not breaking toontown if self.passMessagesThrough: # for not breaking toontown
ist=self.inputStateTokens ist=self.inputStateTokens
ist.append(inputState.watchWithModifiers("forward", "arrow_up", inputSource=inputState.ArrowKeys)) ist.append(inputState.watchWithModifiers("forward", "arrow_up", inputSource=inputState.ArrowKeys))
@ -50,7 +48,6 @@ class ControlManager:
ist.append(inputState.watchWithModifiers("turnLeft", "arrow_left", inputSource=inputState.ArrowKeys)) ist.append(inputState.watchWithModifiers("turnLeft", "arrow_left", inputSource=inputState.ArrowKeys))
ist.append(inputState.watchWithModifiers("turnRight", "arrow_right", inputSource=inputState.ArrowKeys)) ist.append(inputState.watchWithModifiers("turnRight", "arrow_right", inputSource=inputState.ArrowKeys))
def __str__(self): def __str__(self):
return 'ControlManager: using \'%s\'' % self.currentControlsName return 'ControlManager: using \'%s\'' % self.currentControlsName
@ -325,7 +322,7 @@ class ControlManager:
self.WASDTurnTokens = ( self.WASDTurnTokens = (
inputState.watchWithModifiers("turnLeft", "a", inputSource=inputState.WASD), inputState.watchWithModifiers("turnLeft", "a", inputSource=inputState.WASD),
inputState.watchWithModifiers("turnRight", "d", inputSource=inputState.WASD), inputState.watchWithModifiers("turnRight", "d", inputSource=inputState.WASD),
) )
inputState.set("turnLeft", slideLeftWASDSet, inputSource=inputState.WASD) inputState.set("turnLeft", slideLeftWASDSet, inputSource=inputState.WASD)
inputState.set("turnRight", slideRightWASDSet, inputSource=inputState.WASD) inputState.set("turnRight", slideRightWASDSet, inputSource=inputState.WASD)
@ -337,7 +334,7 @@ class ControlManager:
self.WASDTurnTokens = ( self.WASDTurnTokens = (
inputState.watchWithModifiers("slideLeft", "a", inputSource=inputState.WASD), inputState.watchWithModifiers("slideLeft", "a", inputSource=inputState.WASD),
inputState.watchWithModifiers("slideRight", "d", inputSource=inputState.WASD), inputState.watchWithModifiers("slideRight", "d", inputSource=inputState.WASD),
) )
inputState.set("slideLeft", turnLeftWASDSet, inputSource=inputState.WASD) inputState.set("slideLeft", turnLeftWASDSet, inputSource=inputState.WASD)
inputState.set("slideRight", turnRightWASDSet, inputSource=inputState.WASD) inputState.set("slideRight", turnRightWASDSet, inputSource=inputState.WASD)

View File

@ -8,36 +8,47 @@ from direct.showbase.MessengerGlobal import messenger
class InputStateToken: class InputStateToken:
_SerialGen = SerialNumGen() _SerialGen = SerialNumGen()
Inval = 'invalidatedToken' Inval = 'invalidatedToken'
def __init__(self, inputState): def __init__(self, inputState):
self._id = InputStateToken._SerialGen.next() self._id = InputStateToken._SerialGen.next()
self._hash = self._id self._hash = self._id
self._inputState = inputState self._inputState = inputState
def release(self): def release(self):
# subclasses will override # subclasses will override
assert False assert False
def isValid(self): def isValid(self):
return self._id != InputStateToken.Inval return self._id != InputStateToken.Inval
def invalidate(self): def invalidate(self):
self._id = InputStateToken.Inval self._id = InputStateToken.Inval
def __hash__(self): def __hash__(self):
return self._hash return self._hash
#snake_case alias: #snake_case alias:
is_valid = isValid is_valid = isValid
class InputStateWatchToken(InputStateToken, DirectObject.DirectObject): class InputStateWatchToken(InputStateToken, DirectObject.DirectObject):
def release(self): def release(self):
self._inputState._ignore(self) self._inputState._ignore(self)
self.ignoreAll() self.ignoreAll()
class InputStateForceToken(InputStateToken): class InputStateForceToken(InputStateToken):
def release(self): def release(self):
self._inputState._unforce(self) self._inputState._unforce(self)
class InputStateTokenGroup: class InputStateTokenGroup:
def __init__(self): def __init__(self):
self._tokens = [] self._tokens = []
def addToken(self, token): def addToken(self, token):
self._tokens.append(token) self._tokens.append(token)
def release(self): def release(self):
for token in self._tokens: for token in self._tokens:
token.release() token.release()
@ -46,6 +57,7 @@ class InputStateTokenGroup:
#snake_case alias: #snake_case alias:
add_token = addToken add_token = addToken
class InputState(DirectObject.DirectObject): class InputState(DirectObject.DirectObject):
""" """
InputState is for tracking the on/off state of some events. InputState is for tracking the on/off state of some events.
@ -190,7 +202,6 @@ class InputState(DirectObject.DirectObject):
# input state simply because we're not looking at it anymore. # input state simply because we're not looking at it anymore.
# self.set(name, False, inputSource) # self.set(name, False, inputSource)
def force(self, name, value, inputSource): def force(self, name, value, inputSource):
""" """
Force isSet(name) to return 'value'. Force isSet(name) to return 'value'.
@ -213,7 +224,7 @@ class InputState(DirectObject.DirectObject):
self.notify.error( self.notify.error(
"%s is trying to force '%s' to ON, but '%s' is already being forced OFF by %s" % "%s is trying to force '%s' to ON, but '%s' is already being forced OFF by %s" %
(inputSource, name, name, self._forcingOff[name]) (inputSource, name, name, self._forcingOff[name])
) )
self._forcingOn.setdefault(name, set()) self._forcingOn.setdefault(name, set())
self._forcingOn[name].add(inputSource) self._forcingOn[name].add(inputSource)
else: else:
@ -221,7 +232,7 @@ class InputState(DirectObject.DirectObject):
self.notify.error( self.notify.error(
"%s is trying to force '%s' to OFF, but '%s' is already being forced ON by %s" % "%s is trying to force '%s' to OFF, but '%s' is already being forced ON by %s" %
(inputSource, name, name, self._forcingOn[name]) (inputSource, name, name, self._forcingOn[name])
) )
self._forcingOff.setdefault(name, set()) self._forcingOff.setdefault(name, set())
self._forcingOff[name].add(inputSource) self._forcingOff[name].add(inputSource)
return token return token

View File

@ -55,6 +55,7 @@ import math
#import LineStream #import LineStream
class PhysicsWalker(DirectObject.DirectObject): class PhysicsWalker(DirectObject.DirectObject):
notify = DirectNotifyGlobal.directNotify.newCategory("PhysicsWalker") notify = DirectNotifyGlobal.directNotify.newCategory("PhysicsWalker")
@ -546,7 +547,7 @@ class PhysicsWalker(DirectObject.DirectObject):
onScreenDebug.add("highMark", "% 10.4f"%(self.highMark,)) onScreenDebug.add("highMark", "% 10.4f"%(self.highMark,))
#if airborneHeight < 0.1: #contact!=Vec3.zero(): #if airborneHeight < 0.1: #contact!=Vec3.zero():
if (airborneHeight > self.avatarRadius*0.5 if (airborneHeight > self.avatarRadius*0.5
or physObject.getVelocity().getZ() > 0.0 or physObject.getVelocity().getZ() > 0.0
): # Check stair angles before changing this. ): # Check stair angles before changing this.
# ...the avatar is airborne (maybe a lot or a tiny amount). # ...the avatar is airborne (maybe a lot or a tiny amount).
self.isAirborne = 1 self.isAirborne = 1

View File

@ -35,6 +35,7 @@ JOYBOX_RANGE = JOYBOX_MAX - JOYBOX_MIN
JOYBOX_TREAD_SEPERATION = 1.0 JOYBOX_TREAD_SEPERATION = 1.0
class DirectJoybox(DirectObject): class DirectJoybox(DirectObject):
joyboxCount = 0 joyboxCount = 0
xyzMultiplier = 1.0 xyzMultiplier = 1.0
@ -87,12 +88,10 @@ class DirectJoybox(DirectObject):
# Spawn update task # Spawn update task
self.enable() self.enable()
def setHeadingNodePath(self,np): def setHeadingNodePath(self,np):
self.headingNP = np self.headingNP = np
def enable(self): def enable(self):
# Kill existing task # Kill existing task
self.disable() self.disable()
@ -126,18 +125,25 @@ class DirectJoybox(DirectObject):
def getNodePath(self): def getNodePath(self):
return self.nodePath return self.nodePath
def setRefCS(self, refCS): def setRefCS(self, refCS):
self.refCS = refCS self.refCS = refCS
def getRefCS(self): def getRefCS(self):
return self.refCS return self.refCS
def getEventName(self, index): def getEventName(self, index):
return self.name + '-button-' + repr(index) return self.name + '-button-' + repr(index)
def setXyzMultiplier(self, multiplier): def setXyzMultiplier(self, multiplier):
DirectJoybox.xyzMultiplier = multiplier DirectJoybox.xyzMultiplier = multiplier
def getXyzMultiplier(self): def getXyzMultiplier(self):
return DirectJoybox.xyzMultiplier return DirectJoybox.xyzMultiplier
def setHprMultiplier(self, multiplier): def setHprMultiplier(self, multiplier):
DirectJoybox.hprMultiplier = multiplier DirectJoybox.hprMultiplier = multiplier
def getHprMultiplier(self): def getHprMultiplier(self):
return DirectJoybox.hprMultiplier return DirectJoybox.hprMultiplier
@ -193,6 +199,7 @@ class DirectJoybox(DirectObject):
def acceptSwitchModeEvent(self, button = R_UPPER): def acceptSwitchModeEvent(self, button = R_UPPER):
self.accept(self.getEventName(button), self.switchMode) self.accept(self.getEventName(button), self.switchMode)
def ignoreSwitchModeEvent(self, button = R_UPPER): def ignoreSwitchModeEvent(self, button = R_UPPER):
self.ignore(self.getEventName(button)) self.ignore(self.getEventName(button))
@ -208,7 +215,7 @@ class DirectJoybox(DirectObject):
pass pass
def showMode(self, modeText): def showMode(self, modeText):
def hideText(state, s = self): def hideText(state, s=self):
s.readout.setText('') s.readout.setText('')
return Task.done return Task.done
taskMgr.remove(self.name + '-showMode') taskMgr.remove(self.name + '-showMode')
@ -220,6 +227,7 @@ class DirectJoybox(DirectObject):
def acceptUprightCameraEvent(self, button = L_UPPER): def acceptUprightCameraEvent(self, button = L_UPPER):
self.accept(self.getEventName(button), self.accept(self.getEventName(button),
base.direct.cameraControl.orbitUprightCam) base.direct.cameraControl.orbitUprightCam)
def ignoreUprightCameraEvent(self, button = L_UPPER): def ignoreUprightCameraEvent(self, button = L_UPPER):
self.ignore(self.getEventName(button)) self.ignore(self.getEventName(button))
@ -230,29 +238,29 @@ class DirectJoybox(DirectObject):
self.showMode(self.modeName) self.showMode(self.modeName)
self.enable() self.enable()
def setUseHeadingNP(self, enabled):
def setUseHeadingNP(self,enabled):
self.useHeadingNP = enabled self.useHeadingNP = enabled
def setRotateInPlace(self,enabled): def setRotateInPlace(self, enabled):
self.rotateInPlace = enabled self.rotateInPlace = enabled
def joyboxFly(self): def joyboxFly(self):
# Do nothing if no nodePath selected # Do nothing if no nodePath selected
if self.nodePath is None: if self.nodePath is None:
return return
hprScale = ((self.aList[L_SLIDE] + 1.0) * hprScale = ((self.aList[L_SLIDE] + 1.0) *
50.0 * DirectJoybox.hprMultiplier) 50.0 * DirectJoybox.hprMultiplier)
posScale = ((self.aList[R_SLIDE] + 1.0) * posScale = ((self.aList[R_SLIDE] + 1.0) *
50.0 * DirectJoybox.xyzMultiplier) 50.0 * DirectJoybox.xyzMultiplier)
def getAxisVal(index, s = self):
def getAxisVal(index, s=self):
try: try:
return s.aList[s.mapping[index]] return s.aList[s.mapping[index]]
except IndexError: except IndexError:
# If it is a null axis return 0 # If it is a null axis return 0
return 0.0 return 0.0
x = getAxisVal(0) * self.modifier[0] x = getAxisVal(0) * self.modifier[0]
y = getAxisVal(1) * self.modifier[1] y = getAxisVal(1) * self.modifier[1]
z = getAxisVal(2) * self.modifier[2] z = getAxisVal(2) * self.modifier[2]
@ -262,13 +270,13 @@ class DirectJoybox(DirectObject):
p = getAxisVal(4) * self.modifier[4] p = getAxisVal(4) * self.modifier[4]
r = getAxisVal(5) * self.modifier[5] r = getAxisVal(5) * self.modifier[5]
hpr = Vec3(h, p, r) * (hprScale * self.deltaTime) hpr = Vec3(h, p, r) * (hprScale * self.deltaTime)
# if we are using a heading nodepath, we want # if we are using a heading nodepath, we want
# to drive in the direction we are facing, # to drive in the direction we are facing,
# however, we don't want the z component to change # however, we don't want the z component to change
if self.useHeadingNP and self.headingNP is not None: if self.useHeadingNP and self.headingNP is not None:
oldZ = pos.getZ() oldZ = pos.getZ()
pos = self.nodePath.getRelativeVector(self.headingNP, pos = self.nodePath.getRelativeVector(self.headingNP, pos)
pos)
pos.setZ(oldZ) pos.setZ(oldZ)
# if we are using a heading NP we might want to rotate # if we are using a heading NP we might want to rotate
# in place around that NP # in place around that NP
@ -282,7 +290,6 @@ class DirectJoybox(DirectObject):
self.nodePath.wrtReparentTo(parent) self.nodePath.wrtReparentTo(parent)
hpr = Vec3(0,0,0) hpr = Vec3(0,0,0)
self.nodePath.setPosHpr(self.nodePath, pos, hpr) self.nodePath.setPosHpr(self.nodePath, pos, hpr)
def joeMode(self): def joeMode(self):
@ -291,25 +298,23 @@ class DirectJoybox(DirectObject):
self.modifier = [1, 1, 1, -1, -1, 0] self.modifier = [1, 1, 1, -1, -1, 0]
self.setMode(self.joyboxFly, 'Joe Mode') self.setMode(self.joyboxFly, 'Joe Mode')
def basicMode(self): def basicMode(self):
self.mapping = [NULL_AXIS, R_FWD_BACK, NULL_AXIS, self.mapping = [NULL_AXIS, R_FWD_BACK, NULL_AXIS,
R_LEFT_RIGHT, NULL_AXIS, NULL_AXIS] R_LEFT_RIGHT, NULL_AXIS, NULL_AXIS]
self.modifier = [0,1,0,-1,0,0] self.modifier = [0, 1, 0, -1, 0, 0]
self.setMode(self.joyboxFly,'Basic Mode') self.setMode(self.joyboxFly, 'Basic Mode')
def fpsMode(self): def fpsMode(self):
self.mapping = [L_LEFT_RIGHT,R_FWD_BACK,L_FWD_BACK, self.mapping = [L_LEFT_RIGHT,R_FWD_BACK,L_FWD_BACK,
R_LEFT_RIGHT, NULL_AXIS, NULL_AXIS] R_LEFT_RIGHT, NULL_AXIS, NULL_AXIS]
self.modifier = [1,1,1,-1,0,0] self.modifier = [1, 1, 1, -1, 0, 0]
self.setMode(self.joyboxFly,'FPS Mode') self.setMode(self.joyboxFly, 'FPS Mode')
def tankMode(self): def tankMode(self):
self.setMode(self.tankFly,'Tank Mode') self.setMode(self.tankFly, 'Tank Mode')
def nullMode(self): def nullMode(self):
self.setMode(self.nullFly,'Null Mode') self.setMode(self.nullFly, 'Null Mode')
def lucMode(self): def lucMode(self):
self.mapping = [R_LEFT_RIGHT, R_FWD_BACK, L_FWD_BACK, self.mapping = [R_LEFT_RIGHT, R_FWD_BACK, L_FWD_BACK,
@ -362,7 +367,6 @@ class DirectJoybox(DirectObject):
def spaceMode(self): def spaceMode(self):
self.setMode(self.spaceFly, 'Space Mode') self.setMode(self.spaceFly, 'Space Mode')
def nullFly(self): def nullFly(self):
return return
@ -384,10 +388,6 @@ class DirectJoybox(DirectObject):
self.nodePath.setH(self.nodePath,dh) self.nodePath.setH(self.nodePath,dh)
self.nodePath.setY(self.nodePath,dy) self.nodePath.setY(self.nodePath,dy)
def spaceFly(self): def spaceFly(self):
# Do nothing if no nodePath selected # Do nothing if no nodePath selected
if self.nodePath is None: if self.nodePath is None:
@ -498,9 +498,9 @@ class DirectJoybox(DirectObject):
# Restore the original hpr of the orbiter # Restore the original hpr of the orbiter
self.nodePath.setHpr(self.tempCS, 0, 0, 0) self.nodePath.setHpr(self.tempCS, 0, 0, 0)
# We need to override the DirectAnalog normalizeChannel to # We need to override the DirectAnalog normalizeChannel to
# correct the ranges of the two twist axes of the joybox. # correct the ranges of the two twist axes of the joybox.
def normalizeChannel(self, chan, minVal = -1, maxVal = 1): def normalizeChannel(self, chan, minVal = -1, maxVal = 1):
try: try:
if chan == L_TWIST or chan == R_TWIST: if chan == L_TWIST or chan == R_TWIST:

View File

@ -5,6 +5,7 @@ DirectNotify module: this module contains the DirectNotify class
from . import Notifier from . import Notifier
from . import Logger from . import Logger
class DirectNotify: class DirectNotify:
""" """
DirectNotify class: this class contains methods for creating DirectNotify class: this class contains methods for creating
@ -15,7 +16,7 @@ class DirectNotify:
""" """
DirectNotify class keeps a dictionary of Notfiers DirectNotify class keeps a dictionary of Notfiers
""" """
self.__categories = { } self.__categories = {}
# create a default log file # create a default log file
self.logger = Logger.Logger() self.logger = Logger.Logger()
@ -100,7 +101,6 @@ class DirectNotify:
print("DirectNotify: unknown notify level: " + str(level) print("DirectNotify: unknown notify level: " + str(level)
+ " for category: " + str(categoryName)) + " for category: " + str(categoryName))
def setDconfigLevels(self): def setDconfigLevels(self):
for categoryName in self.getCategories(): for categoryName in self.getCategories():
self.setDconfigLevel(categoryName) self.setDconfigLevel(categoryName)

View File

@ -65,6 +65,7 @@ def comment(code):
else: else:
return '' return ''
def block_comment(code): def block_comment(code):
code = code.strip() code = code.strip()
@ -77,6 +78,7 @@ def block_comment(code):
return code return code
def translateFunctionName(name): def translateFunctionName(name):
if name.startswith("__"): if name.startswith("__"):
return name return name
@ -93,6 +95,7 @@ def translateFunctionName(name):
new += i[0].upper() + i[1:] new += i[0].upper() + i[1:]
return new return new
def translateTypeName(name, mangle=True): def translateTypeName(name, mangle=True):
# Equivalent to C++ classNameFromCppName # Equivalent to C++ classNameFromCppName
class_name = "" class_name = ""
@ -115,6 +118,7 @@ def translateTypeName(name, mangle=True):
return class_name return class_name
def translated_type_name(type, scoped=True): def translated_type_name(type, scoped=True):
while interrogate_type_is_wrapped(type): while interrogate_type_is_wrapped(type):
if interrogate_type_is_const(type): if interrogate_type_is_const(type):
@ -205,7 +209,7 @@ def processFunction(handle, function, isConstructor = False):
def processType(handle, type): def processType(handle, type):
typename = translated_type_name(type, scoped=False) typename = translated_type_name(type, scoped=False)
derivations = [ translated_type_name(interrogate_type_get_derivation(type, n)) for n in range(interrogate_type_number_of_derivations(type)) ] derivations = [translated_type_name(interrogate_type_get_derivation(type, n)) for n in range(interrogate_type_number_of_derivations(type))]
if interrogate_type_has_comment(type): if interrogate_type_has_comment(type):
print(block_comment(interrogate_type_comment(type)), file=handle) print(block_comment(interrogate_type_comment(type)), file=handle)
@ -258,6 +262,7 @@ def processType(handle, type):
print("};", file=handle) print("};", file=handle)
def processModule(handle, package): def processModule(handle, package):
print("Processing module %s" % (package)) print("Processing module %s" % (package))
print("namespace %s {" % package, file=handle) print("namespace %s {" % package, file=handle)

View File

@ -14,6 +14,7 @@ CAM_MOVE_DURATION = 1.2
COA_MARKER_SF = 0.0075 COA_MARKER_SF = 0.0075
Y_AXIS = Vec3(0, 1, 0) Y_AXIS = Vec3(0, 1, 0)
class DirectCameraControl(DirectObject): class DirectCameraControl(DirectObject):
notify = DirectNotifyGlobal.directNotify.newCategory('DirectCameraControl') notify = DirectNotifyGlobal.directNotify.newCategory('DirectCameraControl')
@ -50,7 +51,7 @@ class DirectCameraControl(DirectObject):
['DIRECT-mouse2Up', self.mouseFlyStop], ['DIRECT-mouse2Up', self.mouseFlyStop],
['DIRECT-mouse3', self.mouseDollyStart], ['DIRECT-mouse3', self.mouseDollyStart],
['DIRECT-mouse3Up', self.mouseDollyStop], ['DIRECT-mouse3Up', self.mouseDollyStop],
] ]
# [gjeon] moved all of the hotkeys to single place for easy remapping # [gjeon] moved all of the hotkeys to single place for easy remapping
## self.keyEvents = [ ## self.keyEvents = [
@ -101,7 +102,7 @@ class DirectCameraControl(DirectObject):
['DIRECT-removeManipulateCameraTask', self.removeManipulateCameraTask], ['DIRECT-removeManipulateCameraTask', self.removeManipulateCameraTask],
['DIRECT-zoomInCam', self.zoomCam, 0.5, t], ['DIRECT-zoomInCam', self.zoomCam, 0.5, t],
['DIRECT-zoomOutCam', self.zoomCam, -2.0, t], ['DIRECT-zoomOutCam', self.zoomCam, -2.0, t],
] ]
# set this to true to prevent the camera from rolling # set this to true to prevent the camera from rolling
self.lockRoll = False self.lockRoll = False
# NIK - flag to determine whether to use maya camera controls # NIK - flag to determine whether to use maya camera controls
@ -351,7 +352,7 @@ class DirectCameraControl(DirectObject):
else: else:
moveDir = Vec3(Y_AXIS) moveDir = Vec3(Y_AXIS)
if self.useMayaCamControls : # use maya controls if self.useMayaCamControls: # use maya controls
moveDir.assign(moveDir * ((base.direct.dr.mouseDeltaX -1.0 * base.direct.dr.mouseDeltaY) moveDir.assign(moveDir * ((base.direct.dr.mouseDeltaX -1.0 * base.direct.dr.mouseDeltaY)
* state.zoomSF)) * state.zoomSF))
hVal = 0.0 hVal = 0.0
@ -613,7 +614,7 @@ class DirectCameraControl(DirectObject):
startColor = Vec4(1, 0, 0, 1), startColor = Vec4(1, 0, 0, 1),
blendType = 'easeInOut'), blendType = 'easeInOut'),
Func(self.coaMarker.stash) Func(self.coaMarker.stash)
) )
self.coaMarkerColorIval.start() self.coaMarkerColorIval.start()
def homeCam(self): def homeCam(self):
@ -699,7 +700,6 @@ class DirectCameraControl(DirectObject):
name = 'manipulateCamera') name = 'manipulateCamera')
self.__startManipulateCamera(ival = ival) self.__startManipulateCamera(ival = ival)
def zoomCam(self, zoomFactor, t): def zoomCam(self, zoomFactor, t):
self.__stopManipulateCamera() self.__stopManipulateCamera()
# Record undo point # Record undo point
@ -769,7 +769,6 @@ class DirectCameraControl(DirectObject):
name = 'manipulateCamera') name = 'manipulateCamera')
self.__startManipulateCamera(ival = ival) self.__startManipulateCamera(ival = ival)
def swingCamAboutWidget(self, degrees, t): def swingCamAboutWidget(self, degrees, t):
# Remove existing camera manipulation task # Remove existing camera manipulation task
self.__stopManipulateCamera() self.__stopManipulateCamera()
@ -834,7 +833,6 @@ class DirectCameraControl(DirectObject):
name = 'manipulateCamera') name = 'manipulateCamera')
self.__startManipulateCamera(ival = ival) self.__startManipulateCamera(ival = ival)
def moveToFit(self): def moveToFit(self):
# How big is the active widget? # How big is the active widget?
widgetScale = base.direct.widget.scalingNode.getScale(render) widgetScale = base.direct.widget.scalingNode.getScale(render)

View File

@ -18,6 +18,7 @@ from .DirectGlobals import Q_EPSILON, UNIT_VEC, ZERO_VEC
from .DirectUtil import CLAMP from .DirectUtil import CLAMP
import math import math
class LineNodePath(NodePath): class LineNodePath(NodePath):
def __init__(self, parent = None, name = None, def __init__(self, parent = None, name = None,
thickness = 1.0, colorVec = VBase4(1)): thickness = 1.0, colorVec = VBase4(1)):
@ -140,13 +141,16 @@ class LineNodePath(NodePath):
## ##
## Given a point in space, and a direction, find the point of intersection ## Given a point in space, and a direction, find the point of intersection
## of that ray with a plane at the specified origin, with the specified normal ## of that ray with a plane at the specified origin, with the specified normal
def planeIntersect (lineOrigin, lineDir, planeOrigin, normal):
def planeIntersect(lineOrigin, lineDir, planeOrigin, normal):
t = 0 t = 0
offset = planeOrigin - lineOrigin offset = planeOrigin - lineOrigin
t = offset.dot(normal) / lineDir.dot(normal) t = offset.dot(normal) / lineDir.dot(normal)
hitPt = lineDir * t hitPt = lineDir * t
return hitPt + lineOrigin return hitPt + lineOrigin
def getNearProjectionPoint(nodePath): def getNearProjectionPoint(nodePath):
# Find the position of the projection of the specified node path # Find the position of the projection of the specified node path
# on the near plane # on the near plane
@ -158,6 +162,7 @@ def getNearProjectionPoint(nodePath):
# Object is coplaner with camera, just return something reasonable # Object is coplaner with camera, just return something reasonable
return Point3(0, base.direct.dr.near, 0) return Point3(0, base.direct.dr.near, 0)
def getScreenXY(nodePath): def getScreenXY(nodePath):
# Where does the node path's projection fall on the near plane # Where does the node path's projection fall on the near plane
nearVec = getNearProjectionPoint(nodePath) nearVec = getNearProjectionPoint(nodePath)
@ -172,6 +177,7 @@ def getScreenXY(nodePath):
# Return the resulting value # Return the resulting value
return screenXY return screenXY
def getCrankAngle(center): def getCrankAngle(center):
# Used to compute current angle of mouse (relative to the coa's # Used to compute current angle of mouse (relative to the coa's
# origin) in screen space # origin) in screen space
@ -179,6 +185,7 @@ def getCrankAngle(center):
y = base.direct.dr.mouseY - center[2] y = base.direct.dr.mouseY - center[2]
return 180 + rad2Deg(math.atan2(y, x)) return 180 + rad2Deg(math.atan2(y, x))
def relHpr(nodePath, base, h, p, r): def relHpr(nodePath, base, h, p, r):
# Compute nodePath2newNodePath relative to base coordinate system # Compute nodePath2newNodePath relative to base coordinate system
# nodePath2base # nodePath2base
@ -202,6 +209,8 @@ def relHpr(nodePath, base, h, p, r):
nodePath.setHpr(hpr) nodePath.setHpr(hpr)
# Quaternion interpolation # Quaternion interpolation
def qSlerp(startQuat, endQuat, t): def qSlerp(startQuat, endQuat, t):
startQ = Quat(startQuat) startQ = Quat(startQuat)
destQuat = Quat(Quat.identQuat()) destQuat = Quat(Quat.identQuat())

View File

@ -72,7 +72,7 @@ class DirectManipulationControl(DirectObject):
['DIRECT-widgetScaleDown', self.scaleWidget, 0.5], ['DIRECT-widgetScaleDown', self.scaleWidget, 0.5],
['shift-f', self.objectHandles.growToFit], ['shift-f', self.objectHandles.growToFit],
['i', self.plantSelectedNodePath], ['i', self.plantSelectedNodePath],
] ]
self.defaultSkipFlags = DG.SKIP_HIDDEN | DG.SKIP_BACKFACE self.defaultSkipFlags = DG.SKIP_HIDDEN | DG.SKIP_BACKFACE
self.optionalSkipFlags = 0 self.optionalSkipFlags = 0
self.unmovableTagList = [] self.unmovableTagList = []
@ -192,8 +192,8 @@ class DirectManipulationControl(DirectObject):
return Task.done return Task.done
def watchMouseTask(self, state): def watchMouseTask(self, state):
if (((abs (state.initX - base.direct.dr.mouseX)) > 0.01) or if (abs(state.initX - base.direct.dr.mouseX) > 0.01 or
((abs (state.initY - base.direct.dr.mouseY)) > 0.01)): abs(state.initY - base.direct.dr.mouseY) > 0.01):
taskMgr.remove('manip-move-wait') taskMgr.remove('manip-move-wait')
self.mode = 'move' self.mode = 'move'
self.manipulateObject() self.manipulateObject()
@ -221,8 +221,8 @@ class DirectManipulationControl(DirectObject):
endX = base.direct.dr.mouseX endX = base.direct.dr.mouseX
endY = base.direct.dr.mouseY endY = base.direct.dr.mouseY
if (((abs (endX - startX)) < 0.01) and if (abs(endX - startX) < 0.01 and
((abs (endY - startY)) < 0.01)): abs(endY - startY) < 0.01):
return return
self.marquee = LineNodePath(base.render2d, 'marquee', 0.5, VBase4(.8, .6, .6, 1)) self.marquee = LineNodePath(base.render2d, 'marquee', 0.5, VBase4(.8, .6, .6, 1))
@ -1056,8 +1056,8 @@ class DirectManipulationControl(DirectObject):
self.initScale * self.initScale *
(self.objectHandles.getWidgetIntersectPt( (self.objectHandles.getWidgetIntersectPt(
self.manipRef, 'y').length() / self.manipRef, 'y').length() /
self.initScaleMag) self.initScaleMag)
) )
base.direct.widget.setScale(currScale) base.direct.widget.setScale(currScale)
## Utility functions ## ## Utility functions ##
@ -1082,6 +1082,7 @@ class DirectManipulationControl(DirectObject):
messenger.send('DIRECT_manipulateObjectCleanup', messenger.send('DIRECT_manipulateObjectCleanup',
[base.direct.selected.getSelectedAsList()]) [base.direct.selected.getSelectedAsList()])
class ObjectHandles(NodePath, DirectObject): class ObjectHandles(NodePath, DirectObject):
def __init__(self, name='objectHandles'): def __init__(self, name='objectHandles'):
# Initialize the superclass # Initialize the superclass
@ -1754,6 +1755,7 @@ class ObjectHandles(NodePath, DirectObject):
return self.hitPt return self.hitPt
def drawBox(lines, center, sideLength): def drawBox(lines, center, sideLength):
l = sideLength * 0.5 l = sideLength * 0.5
lines.moveTo(center[0] + l, center[1] + l, center[2] + l) lines.moveTo(center[0] + l, center[1] + l, center[2] + l)

View File

@ -26,6 +26,8 @@ COA_ORIGIN = 0
COA_CENTER = 1 COA_CENTER = 1
# MRM: To do: handle broken node paths in selected and deselected dicts # MRM: To do: handle broken node paths in selected and deselected dicts
class DirectNodePath(NodePath): class DirectNodePath(NodePath):
# A node path augmented with info, bounding box, and utility methods # A node path augmented with info, bounding box, and utility methods
def __init__(self, nodePath, bboxColor=None): def __init__(self, nodePath, bboxColor=None):
@ -65,6 +67,7 @@ class DirectNodePath(NodePath):
def getMax(self): def getMax(self):
return self.bbox.getMax() return self.bbox.getMax()
class SelectedNodePaths(DirectObject): class SelectedNodePaths(DirectObject):
def __init__(self): def __init__(self):
self.reset() self.reset()
@ -445,7 +448,7 @@ class DirectBoundingBox:
'Max:\t\t%s\n' % self.vecAsString(self.max) + 'Max:\t\t%s\n' % self.vecAsString(self.max) +
'Center:\t\t%s\n' % self.vecAsString(self.center) + 'Center:\t\t%s\n' % self.vecAsString(self.center) +
'Radius:\t\t%.2f' % self.radius 'Radius:\t\t%.2f' % self.radius
) )
class SelectionQueue(CollisionHandlerQueue): class SelectionQueue(CollisionHandlerQueue):
@ -588,18 +591,18 @@ class SelectionQueue(CollisionHandlerQueue):
# Skip if parented to a camera. # Skip if parented to a camera.
pass pass
# Can pick unpickable, use the first visible node # Can pick unpickable, use the first visible node
elif (skipFlags & DG.SKIP_UNPICKABLE) and\ elif (skipFlags & DG.SKIP_UNPICKABLE) and \
(nodePath.getName() in self.unpickable): (nodePath.getName() in self.unpickable):
# Skip if in unpickable list # Skip if in unpickable list
pass pass
elif base.direct and\ elif base.direct and \
((skipFlags & DG.SKIP_WIDGET) and ((skipFlags & DG.SKIP_WIDGET) and
(nodePath.getTag('WidgetName') != base.direct.widget.getName())): (nodePath.getTag('WidgetName') != base.direct.widget.getName())):
# Skip if this widget part is not belong to current widget # Skip if this widget part is not belong to current widget
pass pass
elif base.direct and\ elif base.direct and \
((skipFlags & DG.SKIP_WIDGET) and base.direct.fControl and ((skipFlags & DG.SKIP_WIDGET) and base.direct.fControl and
(nodePath.getName()[2:] == 'ring')): (nodePath.getName()[2:] == 'ring')):
# Skip when ununiformly scale in ortho view # Skip when ununiformly scale in ortho view
pass pass
else: else:
@ -608,6 +611,7 @@ class SelectionQueue(CollisionHandlerQueue):
break break
return self.getCurrentEntry() return self.getCurrentEntry()
class SelectionRay(SelectionQueue): class SelectionRay(SelectionQueue):
def __init__(self, parentNP = None): def __init__(self, parentNP = None):
if parentNP is None: if parentNP is None:

View File

@ -134,7 +134,6 @@ class DirectSession(DirectObject):
for i in range(len(fastrak))[1:]: for i in range(len(fastrak))[1:]:
self.fastrak.append(DirectFastrak.DirectFastrak(fastrak[0] + ':' + fastrak[i])) self.fastrak.append(DirectFastrak.DirectFastrak(fastrak[0] + ':' + fastrak[i]))
self.fControl = 0 self.fControl = 0
self.fAlt = 0 self.fAlt = 0
self.fShift = 0 self.fShift = 0
@ -196,7 +195,7 @@ class DirectSession(DirectObject):
['DIRECT-doWrtReparent', self.doWrtReparent], ['DIRECT-doWrtReparent', self.doWrtReparent],
['DIRECT-doReparent', self.doReparent], ['DIRECT-doReparent', self.doReparent],
['DIRECT-doSelect', self.doSelect], ['DIRECT-doSelect', self.doSelect],
] ]
if base.wantTk: if base.wantTk:
from direct.tkpanels import Placer from direct.tkpanels import Placer
@ -265,7 +264,7 @@ class DirectSession(DirectObject):
'shift-[': ('DIRECT-Undo', 'DIRECT-Undo'), 'shift-[': ('DIRECT-Undo', 'DIRECT-Undo'),
']': ('DIRECT-Redo', 'DIRECT-Redo'), ']': ('DIRECT-Redo', 'DIRECT-Redo'),
'shift-]': ('DIRECT-Redo', 'DIRECT-Redo'), 'shift-]': ('DIRECT-Redo', 'DIRECT-Redo'),
} }
self.hotKeyMap = { self.hotKeyMap = {
'c': ('Center Camera', 'DIRECT-centerCamIn'), 'c': ('Center Camera', 'DIRECT-centerCamIn'),
@ -293,14 +292,14 @@ class DirectSession(DirectObject):
'shift-a': ('Toggle Vis all', 'DIRECT-toggleVisAll'), 'shift-a': ('Toggle Vis all', 'DIRECT-toggleVisAll'),
'w': ('Toggle Wireframe', 'DIRECT-toggleWireframe'), 'w': ('Toggle Wireframe', 'DIRECT-toggleWireframe'),
'control-z': ('Undo', 'LE-Undo'), 'control-z': ('Undo', 'LE-Undo'),
'shift-z' : ('Redo', 'LE-Redo'), 'shift-z': ('Redo', 'LE-Redo'),
'control-d': ('Duplicate', 'LE-Duplicate'), 'control-d': ('Duplicate', 'LE-Duplicate'),
'control-l': ('Make Live', 'LE-MakeLive'), 'control-l': ('Make Live', 'LE-MakeLive'),
'control-n': ('New Scene', 'LE-NewScene'), 'control-n': ('New Scene', 'LE-NewScene'),
'control-s': ('Save Scene', 'LE-SaveScene'), 'control-s': ('Save Scene', 'LE-SaveScene'),
'control-o': ('Open Scene', 'LE-OpenScene'), 'control-o': ('Open Scene', 'LE-OpenScene'),
'control-q': ('Quit', 'LE-Quit'), 'control-q': ('Quit', 'LE-Quit'),
} }
self.speicalKeyMap = { self.speicalKeyMap = {
'enter': 'DIRECT-enter', 'enter': 'DIRECT-enter',
@ -327,7 +326,6 @@ class DirectSession(DirectObject):
self.cluster = DummyClusterClient() self.cluster = DummyClusterClient()
__builtins__['cluster'] = self.cluster __builtins__['cluster'] = self.cluster
def addPassThroughKey(self,key): def addPassThroughKey(self,key):
self.passThroughKeys.append(key) self.passThroughKeys.append(key)
@ -876,6 +874,7 @@ class DirectSession(DirectObject):
# If nothing specified, try selected node path # If nothing specified, try selected node path
nodePath = self.selected.last nodePath = self.selected.last
base.direct.select(nodePath) base.direct.select(nodePath)
def fitTask(state, self = self): def fitTask(state, self = self):
self.cameraControl.fitOnWidget() self.cameraControl.fitOnWidget()
return Task.done return Task.done

View File

@ -23,7 +23,7 @@ class Mopath(DirectObject):
def __init__(self, name = None, fluid = 1, objectToLoad = None, upVectorNodePath = None, reverseUpVector = False): def __init__(self, name = None, fluid = 1, objectToLoad = None, upVectorNodePath = None, reverseUpVector = False):
if name is None: if name is None:
name = 'mopath%d' % self.nameIndex name = f'mopath{self.nameIndex}'
self.nameIndex = self.nameIndex + 1 self.nameIndex = self.nameIndex + 1
self.name = name self.name = name
self.fluid = fluid self.fluid = fluid
@ -38,12 +38,12 @@ class Mopath(DirectObject):
self.upVectorNodePath = upVectorNodePath self.upVectorNodePath = upVectorNodePath
self.reverseUpVector = reverseUpVector self.reverseUpVector = reverseUpVector
self.reset() self.reset()
if isinstance( objectToLoad, NodePath ): if isinstance(objectToLoad, NodePath):
self.loadNodePath( objectToLoad ) self.loadNodePath(objectToLoad)
elif isinstance( objectToLoad, str ): elif isinstance(objectToLoad, str):
self.loadFile( objectToLoad ) self.loadFile(objectToLoad)
elif objectToLoad is not None: elif objectToLoad is not None:
print("Mopath: Unable to load object '%s', objectToLoad must be a file name string or a NodePath" % objectToLoad) print(f"Mopath: Unable to load object '{objectToLoad}', objectToLoad must be a file name string or a NodePath")
def getMaxT(self): def getMaxT(self):
return self.maxT * self.timeScale return self.maxT * self.timeScale
@ -70,7 +70,6 @@ class Mopath(DirectObject):
else: else:
print('Mopath: no valid curves in nodePath: %s' % nodePath) print('Mopath: no valid curves in nodePath: %s' % nodePath)
def reset(self): def reset(self):
self.maxT = 0.0 self.maxT = 0.0
self.loop = 0 self.loop = 0

View File

@ -275,32 +275,32 @@ class CompilationEnvironment:
def compileExe(self, filename, basename, extraLink=[]): def compileExe(self, filename, basename, extraLink=[]):
compile = self.compileObjExe % dict({ compile = self.compileObjExe % dict({
'python' : self.Python, 'python': self.Python,
'MSVC' : self.MSVC, 'MSVC': self.MSVC,
'PSDK' : self.PSDK, 'PSDK': self.PSDK,
'suffix64' : self.suffix64, 'suffix64': self.suffix64,
'MD' : self.MD, 'MD': self.MD,
'pythonIPath' : self.PythonIPath, 'pythonIPath': self.PythonIPath,
'pythonVersion' : self.PythonVersion, 'pythonVersion': self.PythonVersion,
'arch' : self.arch, 'arch': self.arch,
'filename' : filename, 'filename': filename,
'basename' : basename, 'basename': basename,
}, **sysconf.get_config_vars()) }, **sysconf.get_config_vars())
sys.stderr.write(compile + '\n') sys.stderr.write(compile + '\n')
if os.system(compile) != 0: if os.system(compile) != 0:
raise Exception('failed to compile %s.' % basename) raise Exception('failed to compile %s.' % basename)
link = self.linkExe % dict({ link = self.linkExe % dict({
'python' : self.Python, 'python': self.Python,
'MSVC' : self.MSVC, 'MSVC': self.MSVC,
'PSDK' : self.PSDK, 'PSDK': self.PSDK,
'suffix64' : self.suffix64, 'suffix64': self.suffix64,
'pythonIPath' : self.PythonIPath, 'pythonIPath': self.PythonIPath,
'pythonVersion' : self.PythonVersion, 'pythonVersion': self.PythonVersion,
'arch' : self.arch, 'arch': self.arch,
'filename' : filename, 'filename': filename,
'basename' : basename, 'basename': basename,
}, **sysconf.get_config_vars()) }, **sysconf.get_config_vars())
link += ' ' + ' '.join(extraLink) link += ' ' + ' '.join(extraLink)
sys.stderr.write(link + '\n') sys.stderr.write(link + '\n')
if os.system(link) != 0: if os.system(link) != 0:
@ -308,38 +308,39 @@ class CompilationEnvironment:
def compileDll(self, filename, basename, extraLink=[]): def compileDll(self, filename, basename, extraLink=[]):
compile = self.compileObjDll % dict({ compile = self.compileObjDll % dict({
'python' : self.Python, 'python': self.Python,
'MSVC' : self.MSVC, 'MSVC': self.MSVC,
'PSDK' : self.PSDK, 'PSDK': self.PSDK,
'suffix64' : self.suffix64, 'suffix64': self.suffix64,
'MD' : self.MD, 'MD': self.MD,
'pythonIPath' : self.PythonIPath, 'pythonIPath': self.PythonIPath,
'pythonVersion' : self.PythonVersion, 'pythonVersion': self.PythonVersion,
'arch' : self.arch, 'arch': self.arch,
'filename' : filename, 'filename': filename,
'basename' : basename, 'basename': basename,
}, **sysconf.get_config_vars()) }, **sysconf.get_config_vars())
sys.stderr.write(compile + '\n') sys.stderr.write(compile + '\n')
if os.system(compile) != 0: if os.system(compile) != 0:
raise Exception('failed to compile %s.' % basename) raise Exception('failed to compile %s.' % basename)
link = self.linkDll % dict({ link = self.linkDll % dict({
'python' : self.Python, 'python': self.Python,
'MSVC' : self.MSVC, 'MSVC': self.MSVC,
'PSDK' : self.PSDK, 'PSDK': self.PSDK,
'suffix64' : self.suffix64, 'suffix64': self.suffix64,
'pythonIPath' : self.PythonIPath, 'pythonIPath': self.PythonIPath,
'pythonVersion' : self.PythonVersion, 'pythonVersion': self.PythonVersion,
'arch' : self.arch, 'arch': self.arch,
'filename' : filename, 'filename': filename,
'basename' : basename, 'basename': basename,
'dllext' : self.dllext, 'dllext': self.dllext,
}, **sysconf.get_config_vars()) }, **sysconf.get_config_vars())
link += ' ' + ' '.join(extraLink) link += ' ' + ' '.join(extraLink)
sys.stderr.write(link + '\n') sys.stderr.write(link + '\n')
if os.system(link) != 0: if os.system(link) != 0:
raise Exception('failed to link %s.' % basename) raise Exception('failed to link %s.' % basename)
# The code from frozenmain.c in the Python source repository. # The code from frozenmain.c in the Python source repository.
frozenMainCode = """ frozenMainCode = """
/* Python interpreter main program for frozen scripts */ /* Python interpreter main program for frozen scripts */
@ -675,7 +676,7 @@ okMissing = [
'direct.extensions_native.extensions_darwin', '_manylinux', 'direct.extensions_native.extensions_darwin', '_manylinux',
'collections.Iterable', 'collections.Mapping', 'collections.MutableMapping', 'collections.Iterable', 'collections.Mapping', 'collections.MutableMapping',
'collections.Sequence', 'numpy_distutils', '_winapi', 'collections.Sequence', 'numpy_distutils', '_winapi',
] ]
# Since around macOS 10.15, Apple's codesigning process has become more strict. # Since around macOS 10.15, Apple's codesigning process has become more strict.
# Appending data to the end of a Mach-O binary is now explicitly forbidden. The # Appending data to the end of a Mach-O binary is now explicitly forbidden. The
@ -722,6 +723,7 @@ lc_indices_to_slide = {
LC_DATA_IN_CODE: [2], LC_DATA_IN_CODE: [2],
} }
class Freezer: class Freezer:
class ModuleDef: class ModuleDef:
def __init__(self, moduleName, filename = None, def __init__(self, moduleName, filename = None,
@ -1141,7 +1143,7 @@ class Freezer:
if mdef.implicit and '.' in newName: if mdef.implicit and '.' in newName:
# For implicit modules, check if the parent is excluded. # For implicit modules, check if the parent is excluded.
parentName, baseName = newName.rsplit('.', 1) parentName, baseName = newName.rsplit('.', 1)
if parentName in excludeDict : if parentName in excludeDict:
mdef = excludeDict[parentName] mdef = excludeDict[parentName]
if mdef.exclude: if mdef.exclude:
@ -1182,7 +1184,7 @@ class Freezer:
self.__loadModule(mdef) self.__loadModule(mdef)
# Since it successfully loaded, it's no longer a guess. # Since it successfully loaded, it's no longer a guess.
mdef.guess = False mdef.guess = False
except: except Exception:
# Something went wrong, guess it's not an importable # Something went wrong, guess it's not an importable
# module. # module.
pass pass
@ -1220,7 +1222,7 @@ class Freezer:
try: try:
self.__loadModule(self.ModuleDef(modname, implicit=True)) self.__loadModule(self.ModuleDef(modname, implicit=True))
except: except Exception:
missing.append(modname) missing.append(modname)
# Now, any new modules we found get added to the export list. # Now, any new modules we found get added to the export list.
@ -1596,7 +1598,7 @@ class Freezer:
text = programFile % { text = programFile % {
'moduleDefs': '\n'.join(moduleDefs), 'moduleDefs': '\n'.join(moduleDefs),
'moduleList': '\n'.join(moduleList), 'moduleList': '\n'.join(moduleList),
} }
if self.linkExtensionModules and self.extras: if self.linkExtensionModules and self.extras:
# Should we link in extension modules? If so, we write out a new # Should we link in extension modules? If so, we write out a new
@ -1697,11 +1699,11 @@ class Freezer:
if self.platform.startswith('win'): if self.platform.startswith('win'):
code += self.frozenDllMainCode code += self.frozenDllMainCode
initCode = self.mainInitCode % { initCode = self.mainInitCode % {
'frozenMainCode' : code, 'frozenMainCode': code,
'programName' : os.path.basename(basename), 'programName': os.path.basename(basename),
'dllexport' : dllexport, 'dllexport': dllexport,
'dllimport' : dllimport, 'dllimport': dllimport,
} }
if self.platform.startswith('win'): if self.platform.startswith('win'):
target = basename + '.exe' target = basename + '.exe'
else: else:
@ -1716,10 +1718,10 @@ class Freezer:
target = basename + '.so' target = basename + '.so'
initCode = dllInitCode % { initCode = dllInitCode % {
'moduleName' : os.path.basename(basename), 'moduleName': os.path.basename(basename),
'dllexport' : dllexport, 'dllexport': dllexport,
'dllimport' : dllimport, 'dllimport': dllimport,
} }
compileFunc = self.cenv.compileDll compileFunc = self.cenv.compileDll
self.writeCode(filename, initCode=initCode) self.writeCode(filename, initCode=initCode)
@ -2357,7 +2359,6 @@ class Freezer:
def makeForbiddenModuleListEntry(self, moduleName): def makeForbiddenModuleListEntry(self, moduleName):
return ' {"%s", NULL, 0},' % (moduleName) return ' {"%s", NULL, 0},' % (moduleName)
def __writingModule(self, moduleName): def __writingModule(self, moduleName):
""" Returns true if we are outputting the named module in this """ Returns true if we are outputting the named module in this
pass, false if we have already output in a previous pass, or pass, false if we have already output in a previous pass, or

View File

@ -28,6 +28,7 @@ def _unpack_zstring(mem, offs=0):
c = mem[offs] c = mem[offs]
return str return str
def _unpack_wstring(mem, offs=0): def _unpack_wstring(mem, offs=0):
"Read a UCS-2 string from memory." "Read a UCS-2 string from memory."
name_len, = unpack('<H', mem[offs:offs+2]) name_len, = unpack('<H', mem[offs:offs+2])
@ -37,6 +38,7 @@ def _unpack_wstring(mem, offs=0):
name += chr(*unpack('<H', mem[offs:offs+2])) name += chr(*unpack('<H', mem[offs:offs+2]))
return name return name
def _padded(n, boundary): def _padded(n, boundary):
align = n % boundary align = n % boundary
if align: if align:
@ -250,11 +252,11 @@ class VersionInfoResource(object):
self.struct_version = dwords[1] self.struct_version = dwords[1]
if len(dwords) > 3: if len(dwords) > 3:
self.file_version = \ self.file_version = \
(int(dwords[2] >> 16), int(dwords[2] & 0xffff), (int(dwords[2] >> 16), int(dwords[2] & 0xffff),
int(dwords[3] >> 16), int(dwords[3] & 0xffff)) int(dwords[3] >> 16), int(dwords[3] & 0xffff))
if len(dwords) > 5: if len(dwords) > 5:
self.product_version = \ self.product_version = \
(int(dwords[4] >> 16), int(dwords[4] & 0xffff), (int(dwords[4] >> 16), int(dwords[4] & 0xffff),
int(dwords[5] >> 16), int(dwords[5] & 0xffff)) int(dwords[5] >> 16), int(dwords[5] & 0xffff))
if len(dwords) > 7: if len(dwords) > 7:
self.file_flags_mask = dwords[6] self.file_flags_mask = dwords[6]

View File

@ -122,7 +122,7 @@ class ClientRepositoryBase(ConnectionRepository):
def _getMsgName(self, msgId): def _getMsgName(self, msgId):
# we might get a list of message names, use the first one # we might get a list of message names, use the first one
return makeList(MsgId2Names.get(msgId, 'UNKNOWN MESSAGE: %s' % msgId))[0] return makeList(MsgId2Names.get(msgId, f'UNKNOWN MESSAGE: {msgId}'))[0]
def allocateContext(self): def allocateContext(self):
self.context+=1 self.context+=1
@ -161,7 +161,7 @@ class ClientRepositoryBase(ConnectionRepository):
# Look up the dclass # Look up the dclass
assert parentId == self.GameGlobalsId or parentId in self.doId2do assert parentId == self.GameGlobalsId or parentId in self.doId2do
dclass = self.dclassesByNumber[classId] dclass = self.dclassesByNumber[classId]
assert self.notify.debug("performing generate for %s %s" % (dclass.getName(), doId)) assert self.notify.debug(f"performing generate for {dclass.getName()} {doId}")
dclass.startGenerate() dclass.startGenerate()
# Create a new distributed object, and put it in the dictionary # Create a new distributed object, and put it in the dictionary
distObj = self.generateWithRequiredOtherFields(dclass, doId, di, parentId, zoneId) distObj = self.generateWithRequiredOtherFields(dclass, doId, di, parentId, zoneId)
@ -360,7 +360,6 @@ class ClientRepositoryBase(ConnectionRepository):
# updateRequiredOtherFields calls announceGenerate # updateRequiredOtherFields calls announceGenerate
return distObj return distObj
def disableDoId(self, doId, ownerView=False): def disableDoId(self, doId, ownerView=False):
table, cache = self.getTables(ownerView) table, cache = self.getTables(ownerView)
# Make sure the object exists # Make sure the object exists
@ -442,7 +441,6 @@ class ClientRepositoryBase(ConnectionRepository):
# This object has been fully generated. It's OK to update. # This object has been fully generated. It's OK to update.
self.__doUpdate(doId, di, ovUpdated) self.__doUpdate(doId, di, ovUpdated)
def __doUpdate(self, doId, di, ovUpdated): def __doUpdate(self, doId, di, ovUpdated):
# Find the DO # Find the DO
do = self.doId2do.get(doId) do = self.doId2do.get(doId)
@ -463,13 +461,12 @@ class ClientRepositoryBase(ConnectionRepository):
if handle: if handle:
dclass = self.dclassesByName[handle.dclassName] dclass = self.dclassesByName[handle.dclassName]
dclass.receiveUpdate(handle, di) dclass.receiveUpdate(handle, di)
else: else:
self.notify.warning( self.notify.warning(
"Asked to update non-existent DistObj " + str(doId)) f"Asked to update non-existent DistObj {doId}")
except: except Exception:
self.notify.warning( self.notify.warning(
"Asked to update non-existent DistObj " + str(doId) + "and failed to find it") f"Asked to update non-existent DistObj {doId} and failed to find it")
def __doUpdateOwner(self, doId, di): def __doUpdateOwner(self, doId, di):
ovObj = self.doId2ownerView.get(doId) ovObj = self.doId2ownerView.get(doId)
@ -488,7 +485,7 @@ class ClientRepositoryBase(ConnectionRepository):
self.bootedText = di.getString() self.bootedText = di.getString()
self.notify.warning( self.notify.warning(
"Server is booting us out (%d): %s" % (self.bootedIndex, self.bootedText)) f"Server is booting us out ({self.bootedIndex}): {self.bootedText}")
else: else:
self.bootedIndex = None self.bootedIndex = None
self.bootedText = None self.bootedText = None
@ -536,7 +533,6 @@ class ClientRepositoryBase(ConnectionRepository):
doDict[doId] = do doDict[doId] = do
return doDict return doDict
def considerHeartbeat(self): def considerHeartbeat(self):
"""Send a heartbeat message if we haven't sent one recently.""" """Send a heartbeat message if we haven't sent one recently."""
if not self.heartbeatStarted: if not self.heartbeatStarted:
@ -566,7 +562,7 @@ class ClientRepositoryBase(ConnectionRepository):
def waitForNextHeartBeat(self): def waitForNextHeartBeat(self):
taskMgr.doMethodLater(self.heartbeatInterval, self.sendHeartbeatTask, taskMgr.doMethodLater(self.heartbeatInterval, self.sendHeartbeatTask,
"heartBeat", taskChain = 'net') "heartBeat", taskChain='net')
def replaceMethod(self, oldMethod, newFunction): def replaceMethod(self, oldMethod, newFunction):
return 0 return 0

View File

@ -13,6 +13,7 @@ import gc
__all__ = ["ConnectionRepository", "GCTrigger"] __all__ = ["ConnectionRepository", "GCTrigger"]
class ConnectionRepository( class ConnectionRepository(
DoInterestManager, DoCollectionManager, CConnectionRepository): DoInterestManager, DoCollectionManager, CConnectionRepository):
""" """
@ -233,7 +234,7 @@ class ConnectionRepository(
distObj.parentId = 0 distObj.parentId = 0
distObj.zoneId = 0 distObj.zoneId = 0
# updateRequiredFields calls announceGenerate # updateRequiredFields calls announceGenerate
return distObj return distObj
def readDCFile(self, dcFileNames = None): def readDCFile(self, dcFileNames = None):
""" """
@ -589,7 +590,7 @@ class ConnectionRepository(
if self.http is None: if self.http is None:
try: try:
self.http = HTTPClient() self.http = HTTPClient()
except: except Exception:
pass pass
return self.http return self.http
@ -667,6 +668,7 @@ class ConnectionRepository(
def uniqueName(self, idString): def uniqueName(self, idString):
return "%s-%s" % (idString, self.uniqueId) return "%s-%s" % (idString, self.uniqueId)
class GCTrigger: class GCTrigger:
# used to trigger garbage collection # used to trigger garbage collection
pass pass

View File

@ -24,7 +24,7 @@ ESNum2Str = {
ESDisabled: 'ESDisabled', ESDisabled: 'ESDisabled',
ESGenerating: 'ESGenerating', ESGenerating: 'ESGenerating',
ESGenerated: 'ESGenerated', ESGenerated: 'ESGenerated',
} }
class DistributedObject(DistributedObjectBase): class DistributedObject(DistributedObjectBase):
@ -240,7 +240,6 @@ class DistributedObject(DistributedObjectBase):
""" """
assert self.notify.debug('announceGenerate(): %s' % (self.doId)) assert self.notify.debug('announceGenerate(): %s' % (self.doId))
def _deactivateDO(self): def _deactivateDO(self):
# after this is called, the object is no longer an active DistributedObject # after this is called, the object is no longer an active DistributedObject
# and it may be placed in the cache # and it may be placed in the cache
@ -324,9 +323,9 @@ class DistributedObject(DistributedObjectBase):
""" """
return self.doId return self.doId
#This message was moved out of announce generate #This message was moved out of announce generate
#to avoid ordering issues. #to avoid ordering issues.
def postGenerateMessage(self): def postGenerateMessage(self):
if self.activeState != ESGenerated: if self.activeState != ESGenerated:
self.activeState = ESGenerated self.activeState = ESGenerated

View File

@ -36,6 +36,8 @@ PredictionLag = ConfigVariableDouble("smooth-prediction-lag", 0.0)
GlobalSmoothing = 0 GlobalSmoothing = 0
GlobalPrediction = 0 GlobalPrediction = 0
def globalActivateSmoothing(smoothing, prediction): def globalActivateSmoothing(smoothing, prediction):
""" Globally activates or deactivates smoothing and prediction on """ Globally activates or deactivates smoothing and prediction on
all DistributedSmoothNodes currently in existence, or yet to be all DistributedSmoothNodes currently in existence, or yet to be
@ -48,6 +50,7 @@ def globalActivateSmoothing(smoothing, prediction):
for obj in base.cr.getAllOfType(DistributedSmoothNode): for obj in base.cr.getAllOfType(DistributedSmoothNode):
obj.activateSmoothing(smoothing, prediction) obj.activateSmoothing(smoothing, prediction)
# For historical reasons, we temporarily define # For historical reasons, we temporarily define
# DistributedSmoothNode.activateSmoothing() to be the global function. # DistributedSmoothNode.activateSmoothing() to be the global function.
# We'll remove this soon, so it won't get confused with the instance # We'll remove this soon, so it won't get confused with the instance
@ -154,6 +157,7 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
def setSmoothWrtReparents(self, flag): def setSmoothWrtReparents(self, flag):
self._smoothWrtReparents = flag self._smoothWrtReparents = flag
def getSmoothWrtReparents(self): def getSmoothWrtReparents(self):
return self._smoothWrtReparents return self._smoothWrtReparents
@ -213,42 +217,50 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
def setSmStop(self, timestamp=None): def setSmStop(self, timestamp=None):
self.setComponentTLive(timestamp) self.setComponentTLive(timestamp)
self.stopped = True self.stopped = True
def setSmH(self, h, timestamp=None): def setSmH(self, h, timestamp=None):
self._checkResume(timestamp) self._checkResume(timestamp)
self.setComponentH(h) self.setComponentH(h)
self.setComponentTLive(timestamp) self.setComponentTLive(timestamp)
def setSmZ(self, z, timestamp=None): def setSmZ(self, z, timestamp=None):
self._checkResume(timestamp) self._checkResume(timestamp)
self.setComponentZ(z) self.setComponentZ(z)
self.setComponentTLive(timestamp) self.setComponentTLive(timestamp)
def setSmXY(self, x, y, timestamp=None): def setSmXY(self, x, y, timestamp=None):
self._checkResume(timestamp) self._checkResume(timestamp)
self.setComponentX(x) self.setComponentX(x)
self.setComponentY(y) self.setComponentY(y)
self.setComponentTLive(timestamp) self.setComponentTLive(timestamp)
def setSmXZ(self, x, z, timestamp=None): def setSmXZ(self, x, z, timestamp=None):
self._checkResume(timestamp) self._checkResume(timestamp)
self.setComponentX(x) self.setComponentX(x)
self.setComponentZ(z) self.setComponentZ(z)
self.setComponentTLive(timestamp) self.setComponentTLive(timestamp)
def setSmPos(self, x, y, z, timestamp=None): def setSmPos(self, x, y, z, timestamp=None):
self._checkResume(timestamp) self._checkResume(timestamp)
self.setComponentX(x) self.setComponentX(x)
self.setComponentY(y) self.setComponentY(y)
self.setComponentZ(z) self.setComponentZ(z)
self.setComponentTLive(timestamp) self.setComponentTLive(timestamp)
def setSmHpr(self, h, p, r, timestamp=None): def setSmHpr(self, h, p, r, timestamp=None):
self._checkResume(timestamp) self._checkResume(timestamp)
self.setComponentH(h) self.setComponentH(h)
self.setComponentP(p) self.setComponentP(p)
self.setComponentR(r) self.setComponentR(r)
self.setComponentTLive(timestamp) self.setComponentTLive(timestamp)
def setSmXYH(self, x, y, h, timestamp): def setSmXYH(self, x, y, h, timestamp):
self._checkResume(timestamp) self._checkResume(timestamp)
self.setComponentX(x) self.setComponentX(x)
self.setComponentY(y) self.setComponentY(y)
self.setComponentH(h) self.setComponentH(h)
self.setComponentTLive(timestamp) self.setComponentTLive(timestamp)
def setSmXYZH(self, x, y, z, h, timestamp=None): def setSmXYZH(self, x, y, z, h, timestamp=None):
self._checkResume(timestamp) self._checkResume(timestamp)
self.setComponentX(x) self.setComponentX(x)
@ -256,6 +268,7 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
self.setComponentZ(z) self.setComponentZ(z)
self.setComponentH(h) self.setComponentH(h)
self.setComponentTLive(timestamp) self.setComponentTLive(timestamp)
def setSmPosHpr(self, x, y, z, h, p, r, timestamp=None): def setSmPosHpr(self, x, y, z, h, p, r, timestamp=None):
self._checkResume(timestamp) self._checkResume(timestamp)
self.setComponentX(x) self.setComponentX(x)
@ -285,26 +298,33 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
@report(types = ['args'], dConfigParam = 'smoothnode') @report(types = ['args'], dConfigParam = 'smoothnode')
def setComponentX(self, x): def setComponentX(self, x):
self.smoother.setX(x) self.smoother.setX(x)
@report(types = ['args'], dConfigParam = 'smoothnode') @report(types = ['args'], dConfigParam = 'smoothnode')
def setComponentY(self, y): def setComponentY(self, y):
self.smoother.setY(y) self.smoother.setY(y)
@report(types = ['args'], dConfigParam = 'smoothnode') @report(types = ['args'], dConfigParam = 'smoothnode')
def setComponentZ(self, z): def setComponentZ(self, z):
self.smoother.setZ(z) self.smoother.setZ(z)
@report(types = ['args'], dConfigParam = 'smoothnode') @report(types = ['args'], dConfigParam = 'smoothnode')
def setComponentH(self, h): def setComponentH(self, h):
self.smoother.setH(h) self.smoother.setH(h)
@report(types = ['args'], dConfigParam = 'smoothnode') @report(types = ['args'], dConfigParam = 'smoothnode')
def setComponentP(self, p): def setComponentP(self, p):
self.smoother.setP(p) self.smoother.setP(p)
@report(types = ['args'], dConfigParam = 'smoothnode') @report(types = ['args'], dConfigParam = 'smoothnode')
def setComponentR(self, r): def setComponentR(self, r):
self.smoother.setR(r) self.smoother.setR(r)
@report(types = ['args'], dConfigParam = 'smoothnode') @report(types = ['args'], dConfigParam = 'smoothnode')
def setComponentL(self, l): def setComponentL(self, l):
if l != self.zoneId: if l != self.zoneId:
# only perform set location if location is different # only perform set location if location is different
self.setLocation(self.parentId,l) self.setLocation(self.parentId,l)
@report(types = ['args'], dConfigParam = 'smoothnode') @report(types = ['args'], dConfigParam = 'smoothnode')
def setComponentT(self, timestamp): def setComponentT(self, timestamp):
# This is a little bit hacky. If *this* function is called, # This is a little bit hacky. If *this* function is called,
@ -387,18 +407,25 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
# match set* in more cases than the Disney server does. # match set* in more cases than the Disney server does.
def getComponentL(self): def getComponentL(self):
return self.zoneId return self.zoneId
def getComponentX(self): def getComponentX(self):
return self.getX() return self.getX()
def getComponentY(self): def getComponentY(self):
return self.getY() return self.getY()
def getComponentZ(self): def getComponentZ(self):
return self.getZ() return self.getZ()
def getComponentH(self): def getComponentH(self):
return self.getH() return self.getH()
def getComponentP(self): def getComponentP(self):
return self.getP() return self.getP()
def getComponentR(self): def getComponentR(self):
return self.getR() return self.getR()
def getComponentT(self): def getComponentT(self):
return 0 return 0
@ -409,7 +436,6 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
#printStack() #printStack()
self.smoother.clearPositions(1) self.smoother.clearPositions(1)
@report(types = ['args'], dConfigParam = 'smoothnode') @report(types = ['args'], dConfigParam = 'smoothnode')
def wrtReparentTo(self, parent): def wrtReparentTo(self, parent):
# We override this NodePath method to force it to # We override this NodePath method to force it to
@ -476,7 +502,6 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
serverTime, serverTime,
globalClockDelta.getUncertainty()) globalClockDelta.getUncertainty())
def d_returnResync(self, avId, timestampB, serverTime, uncertainty): def d_returnResync(self, avId, timestampB, serverTime, uncertainty):
serverTimeSec = math.floor(serverTime) serverTimeSec = math.floor(serverTime)
serverTimeUSec = (serverTime - serverTimeSec) * 10000.0 serverTimeUSec = (serverTime - serverTimeSec) * 10000.0
@ -484,7 +509,7 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
avId, timestampB, serverTimeSec, serverTimeUSec, uncertainty]) avId, timestampB, serverTimeSec, serverTimeUSec, uncertainty])
def returnResync(self, avId, timestampB, serverTimeSec, serverTimeUSec, def returnResync(self, avId, timestampB, serverTimeSec, serverTimeUSec,
uncertainty): uncertainty):
""" """
A reply sent by a client whom we recently sent suggestResync A reply sent by a client whom we recently sent suggestResync
to, this reports the client's new delta information so we can to, this reports the client's new delta information so we can

View File

@ -13,8 +13,10 @@ class DummyTaskClass:
def setDelay(self, blah): def setDelay(self, blah):
pass pass
DummyTask = DummyTaskClass() DummyTask = DummyTaskClass()
class DistributedSmoothNodeBase: class DistributedSmoothNodeBase:
"""common base class for DistributedSmoothNode and DistributedSmoothNodeAI """common base class for DistributedSmoothNode and DistributedSmoothNodeAI
""" """
@ -43,6 +45,7 @@ class DistributedSmoothNodeBase:
def b_clearSmoothing(self): def b_clearSmoothing(self):
self.d_clearSmoothing() self.d_clearSmoothing()
self.clearSmoothing() self.clearSmoothing()
def d_clearSmoothing(self): def d_clearSmoothing(self):
self.sendUpdate("clearSmoothing", [0]) self.sendUpdate("clearSmoothing", [0])
@ -85,7 +88,7 @@ class DistributedSmoothNodeBase:
BT.FULL: self.cnode.broadcastPosHprFull, BT.FULL: self.cnode.broadcastPosHprFull,
BT.XYH: self.cnode.broadcastPosHprXyh, BT.XYH: self.cnode.broadcastPosHprXyh,
BT.XY: self.cnode.broadcastPosHprXy, BT.XY: self.cnode.broadcastPosHprXy,
} }
# this comment is here so it will show up in a grep for 'def d_broadcastPosHpr' # this comment is here so it will show up in a grep for 'def d_broadcastPosHpr'
self.d_broadcastPosHpr = broadcastFuncs[self.broadcastType] self.d_broadcastPosHpr = broadcastFuncs[self.broadcastType]

View File

@ -137,7 +137,7 @@ MsgName2Id = {
'CLIENTAGENT_ADD_INTEREST': 1200, 'CLIENTAGENT_ADD_INTEREST': 1200,
'CLIENTAGENT_ADD_INTEREST_MULTIPLE': 1201, 'CLIENTAGENT_ADD_INTEREST_MULTIPLE': 1201,
'CLIENTAGENT_REMOVE_INTEREST': 1203, 'CLIENTAGENT_REMOVE_INTEREST': 1203,
} }
# create id->name table for debugging # create id->name table for debugging
MsgId2Names = invertDictLossless(MsgName2Id) MsgId2Names = invertDictLossless(MsgName2Id)
@ -157,7 +157,7 @@ QUIET_ZONE_IGNORED_LIST = [
#CLIENT_CREATE_OBJECT_REQUIRED, #CLIENT_CREATE_OBJECT_REQUIRED,
#CLIENT_CREATE_OBJECT_REQUIRED_OTHER, #CLIENT_CREATE_OBJECT_REQUIRED_OTHER,
] ]
# The following is a different set of numbers from above. # The following is a different set of numbers from above.
# These are the sub-message types for CLIENT_LOGIN_2. # These are the sub-message types for CLIENT_LOGIN_2.

View File

@ -20,7 +20,7 @@ MsgName2Id = {
'CLIENT_OBJECT_UPDATE_FIELD_TARGETED_CMU' : 9011, 'CLIENT_OBJECT_UPDATE_FIELD_TARGETED_CMU' : 9011,
'CLIENT_OBJECT_UPDATE_FIELD' : 120, # Matches MsgTypes.CLIENT_OBJECT_SET_FIELD 'CLIENT_OBJECT_UPDATE_FIELD' : 120, # Matches MsgTypes.CLIENT_OBJECT_SET_FIELD
} }
# create id->name table for debugging # create id->name table for debugging
MsgId2Names = invertDictLossless(MsgName2Id) MsgId2Names = invertDictLossless(MsgName2Id)

View File

@ -48,7 +48,7 @@ class PyDatagram(Datagram):
STString: (Datagram.addString, None), STString: (Datagram.addString, None),
STBlob: (Datagram.addBlob, None), STBlob: (Datagram.addBlob, None),
STBlob32: (Datagram.addBlob32, None), STBlob32: (Datagram.addBlob32, None),
} }
addChannel = Datagram.addUint64 addChannel = Datagram.addUint64

View File

@ -46,7 +46,7 @@ class PyDatagramIterator(DatagramIterator):
STString: DatagramIterator.getString, STString: DatagramIterator.getString,
STBlob: DatagramIterator.getBlob, STBlob: DatagramIterator.getBlob,
STBlob32: DatagramIterator.getBlob32, STBlob32: DatagramIterator.getBlob32,
} }
getChannel = DatagramIterator.getUint64 getChannel = DatagramIterator.getUint64

View File

@ -351,7 +351,7 @@ class CommonFilters:
text += "{\n" text += "{\n"
text += " o_color = tex2D(k_txcolor, %s);\n" % (texcoords["color"]) text += " o_color = tex2D(k_txcolor, %s);\n" % (texcoords["color"])
if "CartoonInk" in configuration: if "CartoonInk" in configuration:
text += CARTOON_BODY % {"texcoord" : texcoords["aux"]} text += CARTOON_BODY % {"texcoord": texcoords["aux"]}
if "AmbientOcclusion" in configuration: if "AmbientOcclusion" in configuration:
text += " o_color *= tex2D(k_txssao2, %s).r;\n" % (texcoords["ssao2"]) text += " o_color *= tex2D(k_txssao2, %s).r;\n" % (texcoords["ssao2"])
if "BlurSharpen" in configuration: if "BlurSharpen" in configuration:

View File

@ -150,7 +150,6 @@ class ClassicFSM(DirectObject):
def getCurrentState(self): def getCurrentState(self):
return self.__currentState return self.__currentState
# lookup funcs # lookup funcs
def getStateNamed(self, stateName): def getStateNamed(self, stateName):
@ -315,7 +314,6 @@ class ClassicFSM(DirectObject):
ClassicFSM.notify.warning(msg) ClassicFSM.notify.warning(msg)
return 0 return 0
def forceTransition(self, aStateName, enterArgList=[], exitArgList=[]): def forceTransition(self, aStateName, enterArgList=[], exitArgList=[]):
""" """
force a transition -- for debugging ONLY force a transition -- for debugging ONLY
@ -355,7 +353,7 @@ class ClassicFSM(DirectObject):
self.__currentState.isTransitionDefined(aStateName) or self.__currentState.isTransitionDefined(aStateName) or
aStateName in [self.__currentState.getName(), aStateName in [self.__currentState.getName(),
self.__finalState.getName()] self.__finalState.getName()]
) )
if transitionDefined: if transitionDefined:
return self.request(aStateName, enterArgList, exitArgList) return self.request(aStateName, enterArgList, exitArgList)

View File

@ -115,7 +115,7 @@ class FourState:
self.enterState4, self.enterState4,
self.exitState4, self.exitState4,
[names[1]]), [names[1]]),
} }
self.fsm = ClassicFSM.ClassicFSM('FourState', self.fsm = ClassicFSM.ClassicFSM('FourState',
list(self.states.values()), list(self.states.values()),
# Initial State # Initial State

View File

@ -123,7 +123,7 @@ class FourStateAI:
self.enterState4, self.enterState4,
self.exitState4, self.exitState4,
[names[1]]), [names[1]]),
} }
self.fsm = ClassicFSM.ClassicFSM('FourState', self.fsm = ClassicFSM.ClassicFSM('FourState',
list(self.states.values()), list(self.states.values()),
# Initial State # Initial State

View File

@ -16,7 +16,7 @@ class ClassicStyle(FSM.FSM):
'Red': ['Green'], 'Red': ['Green'],
'Yellow': ['Red'], 'Yellow': ['Red'],
'Green': ['Yellow'], 'Green': ['Yellow'],
} }
def enterRed(self): def enterRed(self):
print("enterRed(self, '%s', '%s')" % (self.oldState, self.newState)) print("enterRed(self, '%s', '%s')" % (self.oldState, self.newState))

View File

@ -10,11 +10,13 @@ from panda3d.core import Mat4, MouseButton, PGButton
from . import DirectGuiGlobals as DGG from . import DirectGuiGlobals as DGG
from .DirectFrame import DirectFrame from .DirectFrame import DirectFrame
class DirectButton(DirectFrame): class DirectButton(DirectFrame):
""" """
DirectButton(parent) - Create a DirectGuiWidget which responds DirectButton(parent) - Create a DirectGuiWidget which responds
to mouse clicks and execute a callback function if defined to mouse clicks and execute a callback function if defined
""" """
def __init__(self, parent = None, **kw): def __init__(self, parent = None, **kw):
# Inherits from DirectFrame # Inherits from DirectFrame
# A Direct Frame can have: # A Direct Frame can have:
@ -45,7 +47,7 @@ class DirectButton(DirectFrame):
# Can only be specified at time of widget contruction # Can only be specified at time of widget contruction
# Do the text/graphics appear to move when the button is clicked # Do the text/graphics appear to move when the button is clicked
('pressEffect', 1, DGG.INITOPT), ('pressEffect', 1, DGG.INITOPT),
) )
# Merge keyword options with default options # Merge keyword options with default options
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)

View File

@ -10,6 +10,7 @@ class DirectCheckBox(DirectButton):
Uses an image swap rather than a text change to indicate state. Uses an image swap rather than a text change to indicate state.
""" """
def __init__(self, parent = None, **kw): def __init__(self, parent = None, **kw):
optiondefs = ( optiondefs = (
@ -33,7 +34,7 @@ class DirectCheckBox(DirectButton):
('uncheckedImage', None, None), ('uncheckedImage', None, None),
('checkedImage', None, None), ('checkedImage', None, None),
('isChecked', False, None), ('isChecked', False, None),
) )
# Merge keyword options with default options # Merge keyword options with default options
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)
@ -42,7 +43,6 @@ class DirectCheckBox(DirectButton):
self.initialiseoptions(DirectCheckBox) self.initialiseoptions(DirectCheckBox)
def commandFunc(self, event): def commandFunc(self, event):
self['isChecked'] = not self['isChecked'] self['isChecked'] = not self['isChecked']

View File

@ -12,12 +12,14 @@ from panda3d.core import PGFrameStyle, VBase4
from .DirectButton import DirectButton from .DirectButton import DirectButton
from .DirectLabel import DirectLabel from .DirectLabel import DirectLabel
class DirectCheckButton(DirectButton): class DirectCheckButton(DirectButton):
""" """
DirectCheckButton(parent) - Create a DirectGuiWidget which responds DirectCheckButton(parent) - Create a DirectGuiWidget which responds
to mouse clicks by setting a state of on or off and execute a callback to mouse clicks by setting a state of on or off and execute a callback
function (passing that state through) if defined function (passing that state through) if defined
""" """
def __init__(self, parent = None, **kw): def __init__(self, parent = None, **kw):
# Inherits from DirectButton # Inherits from DirectButton
# A Direct Frame can have: # A Direct Frame can have:
@ -42,7 +44,7 @@ class DirectCheckButton(DirectButton):
('boxImageScale', 1, None), ('boxImageScale', 1, None),
('boxImageColor', None, None), ('boxImageColor', None, None),
('boxRelief', 'sunken', None), ('boxRelief', 'sunken', None),
) )
# Merge keyword options with default options # Merge keyword options with default options
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)
# Initialize superclasses # Initialize superclasses
@ -167,7 +169,6 @@ class DirectCheckButton(DirectButton):
self.indicator.setPos(newpos[0], newpos[1], newpos[2]) self.indicator.setPos(newpos[0], newpos[1], newpos[2])
def commandFunc(self, event): def commandFunc(self, event):
self['indicatorValue'] = 1 - self['indicatorValue'] self['indicatorValue'] = 1 - self['indicatorValue']
if self.colors is not None: if self.colors is not None:

View File

@ -120,7 +120,7 @@ class DirectDialog(DirectFrame):
('command', None, None), ('command', None, None),
('extraArgs', [], None), ('extraArgs', [], None),
('sortOrder', DGG.NO_FADE_SORT_INDEX, None), ('sortOrder', DGG.NO_FADE_SORT_INDEX, None),
) )
# Merge keyword options with default options # Merge keyword options with default options
self.defineoptions(kw, optiondefs, dynamicGroups = ("button",)) self.defineoptions(kw, optiondefs, dynamicGroups = ("button",))
@ -178,7 +178,7 @@ class DirectDialog(DirectFrame):
suppressKeys = self['suppressKeys'], suppressKeys = self['suppressKeys'],
frameSize = self['buttonSize'], frameSize = self['buttonSize'],
command = lambda s = self, v = value: s.buttonCommand(v) command = lambda s = self, v = value: s.buttonCommand(v)
) )
self.buttonList.append(button) self.buttonList.append(button)
# Update dialog when everything has been initialised # Update dialog when everything has been initialised
@ -356,6 +356,7 @@ class DirectDialog(DirectFrame):
button.destroy() button.destroy()
DirectFrame.destroy(self) DirectFrame.destroy(self)
class OkDialog(DirectDialog): class OkDialog(DirectDialog):
def __init__(self, parent = None, **kw): def __init__(self, parent = None, **kw):
# Inherits from DirectFrame # Inherits from DirectFrame
@ -363,12 +364,13 @@ class OkDialog(DirectDialog):
# Define type of DirectGuiWidget # Define type of DirectGuiWidget
('buttonTextList', ['OK'], DGG.INITOPT), ('buttonTextList', ['OK'], DGG.INITOPT),
('buttonValueList', [DGG.DIALOG_OK], DGG.INITOPT), ('buttonValueList', [DGG.DIALOG_OK], DGG.INITOPT),
) )
# Merge keyword options with default options # Merge keyword options with default options
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)
DirectDialog.__init__(self, parent) DirectDialog.__init__(self, parent)
self.initialiseoptions(OkDialog) self.initialiseoptions(OkDialog)
class OkCancelDialog(DirectDialog): class OkCancelDialog(DirectDialog):
def __init__(self, parent = None, **kw): def __init__(self, parent = None, **kw):
# Inherits from DirectFrame # Inherits from DirectFrame
@ -376,12 +378,13 @@ class OkCancelDialog(DirectDialog):
# Define type of DirectGuiWidget # Define type of DirectGuiWidget
('buttonTextList', ['OK','Cancel'], DGG.INITOPT), ('buttonTextList', ['OK','Cancel'], DGG.INITOPT),
('buttonValueList', [DGG.DIALOG_OK, DGG.DIALOG_CANCEL], DGG.INITOPT), ('buttonValueList', [DGG.DIALOG_OK, DGG.DIALOG_CANCEL], DGG.INITOPT),
) )
# Merge keyword options with default options # Merge keyword options with default options
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)
DirectDialog.__init__(self, parent) DirectDialog.__init__(self, parent)
self.initialiseoptions(OkCancelDialog) self.initialiseoptions(OkCancelDialog)
class YesNoDialog(DirectDialog): class YesNoDialog(DirectDialog):
def __init__(self, parent = None, **kw): def __init__(self, parent = None, **kw):
# Inherits from DirectFrame # Inherits from DirectFrame
@ -389,12 +392,13 @@ class YesNoDialog(DirectDialog):
# Define type of DirectGuiWidget # Define type of DirectGuiWidget
('buttonTextList', ['Yes', 'No'], DGG.INITOPT), ('buttonTextList', ['Yes', 'No'], DGG.INITOPT),
('buttonValueList', [DGG.DIALOG_YES, DGG.DIALOG_NO], DGG.INITOPT), ('buttonValueList', [DGG.DIALOG_YES, DGG.DIALOG_NO], DGG.INITOPT),
) )
# Merge keyword options with default options # Merge keyword options with default options
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)
DirectDialog.__init__(self, parent) DirectDialog.__init__(self, parent)
self.initialiseoptions(YesNoDialog) self.initialiseoptions(YesNoDialog)
class YesNoCancelDialog(DirectDialog): class YesNoCancelDialog(DirectDialog):
def __init__(self, parent = None, **kw): def __init__(self, parent = None, **kw):
# Inherits from DirectFrame # Inherits from DirectFrame
@ -403,12 +407,13 @@ class YesNoCancelDialog(DirectDialog):
('buttonTextList', ['Yes', 'No', 'Cancel'], DGG.INITOPT), ('buttonTextList', ['Yes', 'No', 'Cancel'], DGG.INITOPT),
('buttonValueList', [DGG.DIALOG_YES, DGG.DIALOG_NO, DGG.DIALOG_CANCEL], ('buttonValueList', [DGG.DIALOG_YES, DGG.DIALOG_NO, DGG.DIALOG_CANCEL],
DGG.INITOPT), DGG.INITOPT),
) )
# Merge keyword options with default options # Merge keyword options with default options
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)
DirectDialog.__init__(self, parent) DirectDialog.__init__(self, parent)
self.initialiseoptions(YesNoCancelDialog) self.initialiseoptions(YesNoCancelDialog)
class RetryCancelDialog(DirectDialog): class RetryCancelDialog(DirectDialog):
def __init__(self, parent = None, **kw): def __init__(self, parent = None, **kw):
# Inherits from DirectFrame # Inherits from DirectFrame
@ -416,7 +421,7 @@ class RetryCancelDialog(DirectDialog):
# Define type of DirectGuiWidget # Define type of DirectGuiWidget
('buttonTextList', ['Retry','Cancel'], DGG.INITOPT), ('buttonTextList', ['Retry','Cancel'], DGG.INITOPT),
('buttonValueList', [DGG.DIALOG_RETRY, DGG.DIALOG_CANCEL], DGG.INITOPT), ('buttonValueList', [DGG.DIALOG_RETRY, DGG.DIALOG_CANCEL], DGG.INITOPT),
) )
# Merge keyword options with default options # Merge keyword options with default options
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)
DirectDialog.__init__(self, parent) DirectDialog.__init__(self, parent)

View File

@ -21,6 +21,7 @@ ENTRY_FOCUS_STATE = PGEntry.SFocus # 0
ENTRY_NO_FOCUS_STATE = PGEntry.SNoFocus # 1 ENTRY_NO_FOCUS_STATE = PGEntry.SNoFocus # 1
ENTRY_INACTIVE_STATE = PGEntry.SInactive # 2 ENTRY_INACTIVE_STATE = PGEntry.SInactive # 2
class DirectEntry(DirectFrame): class DirectEntry(DirectFrame):
""" """
DirectEntry(parent) - Create a DirectGuiWidget which responds DirectEntry(parent) - Create a DirectGuiWidget which responds
@ -82,7 +83,7 @@ class DirectEntry(DirectFrame):
('autoCapitalize', 0, self.autoCapitalizeFunc), ('autoCapitalize', 0, self.autoCapitalizeFunc),
('autoCapitalizeAllowPrefixes', DirectEntry.AllowCapNamePrefixes, None), ('autoCapitalizeAllowPrefixes', DirectEntry.AllowCapNamePrefixes, None),
('autoCapitalizeForcePrefixes', DirectEntry.ForceCapNamePrefixes, None), ('autoCapitalizeForcePrefixes', DirectEntry.ForceCapNamePrefixes, None),
) )
# Merge keyword options with default options # Merge keyword options with default options
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)
@ -215,6 +216,7 @@ class DirectEntry(DirectFrame):
def _handleTyping(self, guiEvent): def _handleTyping(self, guiEvent):
self._autoCapitalize() self._autoCapitalize()
def _handleErasing(self, guiEvent): def _handleErasing(self, guiEvent):
self._autoCapitalize() self._autoCapitalize()

View File

@ -11,7 +11,7 @@ class DirectEntryScroll(DirectFrame):
('pgFunc', PGVirtualFrame, None), ('pgFunc', PGVirtualFrame, None),
('relief', None, None), ('relief', None, None),
('clipSize', (-1, 1, -1, 1), self.setClipSize), ('clipSize', (-1, 1, -1, 1), self.setClipSize),
) )
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)
DirectFrame.__init__(self, parent, **kw) DirectFrame.__init__(self, parent, **kw)
@ -80,7 +80,6 @@ class DirectEntryScroll(DirectFrame):
if abs(distanceToCenter) > (clipExtent * 0.5): if abs(distanceToCenter) > (clipExtent * 0.5):
self.moveToCenterCursor() self.moveToCenterCursor()
def moveToCenterCursor(self): def moveToCenterCursor(self):
cursorX = self.entry.guiItem.getCursorX() * self.entry['text_scale'][0] cursorX = self.entry.guiItem.getCursorX() * self.entry['text_scale'][0]
canvasX = self.canvas.getX() canvasX = self.canvas.getX()
@ -121,7 +120,6 @@ class DirectEntryScroll(DirectFrame):
self.entry = None self.entry = None
DirectFrame.destroy(self) DirectFrame.destroy(self)
def getCanvas(self): def getCanvas(self):
return self.canvas return self.canvas

View File

@ -659,9 +659,11 @@ class DirectGuiBase(DirectObject.DirectObject):
gEvent = event + self.guiId gEvent = event + self.guiId
self.ignore(gEvent) self.ignore(gEvent)
def toggleGuiGridSnap(): def toggleGuiGridSnap():
DirectGuiWidget.snapToGrid = 1 - DirectGuiWidget.snapToGrid DirectGuiWidget.snapToGrid = 1 - DirectGuiWidget.snapToGrid
def setGuiGridSpacing(spacing): def setGuiGridSpacing(spacing):
DirectGuiWidget.gridSpacing = spacing DirectGuiWidget.gridSpacing = spacing
@ -722,7 +724,7 @@ class DirectGuiWidget(DirectGuiBase, NodePath):
('suppressMouse', 1, DGG.INITOPT), ('suppressMouse', 1, DGG.INITOPT),
('suppressKeys', 0, DGG.INITOPT), ('suppressKeys', 0, DGG.INITOPT),
('enableEdit', 1, DGG.INITOPT), ('enableEdit', 1, DGG.INITOPT),
) )
# Merge keyword options with default options # Merge keyword options with default options
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)
@ -829,7 +831,7 @@ class DirectGuiWidget(DirectGuiBase, NodePath):
vMouse2render2d = Point3(event.getMouse()[0], 0, event.getMouse()[1]) vMouse2render2d = Point3(event.getMouse()[0], 0, event.getMouse()[1])
editVec = Vec3(vWidget2render2d - vMouse2render2d) editVec = Vec3(vWidget2render2d - vMouse2render2d)
if base.mouseWatcherNode.getModifierButtons().isDown( if base.mouseWatcherNode.getModifierButtons().isDown(
KeyboardButton.control()): KeyboardButton.control()):
t = taskMgr.add(self.guiScaleTask, 'guiEditTask') t = taskMgr.add(self.guiScaleTask, 'guiEditTask')
t.refPos = vWidget2render2d t.refPos = vWidget2render2d
t.editVecLen = editVec.length() t.editVecLen = editVec.length()
@ -911,7 +913,6 @@ class DirectGuiWidget(DirectGuiBase, NodePath):
self.bounds[2] - bw[1], self.bounds[2] - bw[1],
self.bounds[3] + bw[1]) self.bounds[3] + bw[1])
def getBounds(self, state = 0): def getBounds(self, state = 0):
self.stateNodePath[state].calcTightBounds(self.ll, self.ur) self.stateNodePath[state].calcTightBounds(self.ll, self.ur)
# Scale bounds to give a pad around graphics # Scale bounds to give a pad around graphics

View File

@ -9,11 +9,13 @@ __all__ = ['DirectLabel']
from panda3d.core import PGItem from panda3d.core import PGItem
from .DirectFrame import DirectFrame from .DirectFrame import DirectFrame
class DirectLabel(DirectFrame): class DirectLabel(DirectFrame):
""" """
DirectLabel(parent) - Create a DirectGuiWidget which has multiple DirectLabel(parent) - Create a DirectGuiWidget which has multiple
states. User explicitly chooses a state to display states. User explicitly chooses a state to display
""" """
def __init__(self, parent = None, **kw): def __init__(self, parent = None, **kw):
# Inherits from DirectFrame # Inherits from DirectFrame
# A Direct Frame can have: # A Direct Frame can have:
@ -32,7 +34,7 @@ class DirectLabel(DirectFrame):
('numStates', 1, None), ('numStates', 1, None),
('state', self.inactiveInitState, None), ('state', self.inactiveInitState, None),
('activeState', 0, self.setActiveState), ('activeState', 0, self.setActiveState),
) )
# Merge keyword options with default options # Merge keyword options with default options
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)

View File

@ -21,6 +21,7 @@ class DirectOptionMenu(DirectButton):
To cancel the popup menu click anywhere on the screen outside of the To cancel the popup menu click anywhere on the screen outside of the
popup menu. No command is executed in this case. popup menu. No command is executed in this case.
""" """
def __init__(self, parent = None, **kw): def __init__(self, parent = None, **kw):
# Inherits from DirectButton # Inherits from DirectButton
optiondefs = ( optiondefs = (
@ -42,7 +43,7 @@ class DirectOptionMenu(DirectButton):
('text_align', TextNode.ALeft, None), ('text_align', TextNode.ALeft, None),
# Remove press effect because it looks a bit funny # Remove press effect because it looks a bit funny
('pressEffect', 0, DGG.INITOPT), ('pressEffect', 0, DGG.INITOPT),
) )
# Merge keyword options with default options # Merge keyword options with default options
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)
# Initialize superclasses # Initialize superclasses

View File

@ -14,12 +14,14 @@ from . import DirectGuiGlobals as DGG
from .DirectButton import DirectButton from .DirectButton import DirectButton
from .DirectLabel import DirectLabel from .DirectLabel import DirectLabel
class DirectRadioButton(DirectButton): class DirectRadioButton(DirectButton):
""" """
DirectRadioButton(parent) - Create a DirectGuiWidget which responds DirectRadioButton(parent) - Create a DirectGuiWidget which responds
to mouse clicks by setting given value to given variable and to mouse clicks by setting given value to given variable and
execute a callback function (passing that state through) if defined execute a callback function (passing that state through) if defined
""" """
def __init__(self, parent = None, **kw): def __init__(self, parent = None, **kw):
# Inherits from DirectButton # Inherits from DirectButton
# A Direct Frame can have: # A Direct Frame can have:
@ -54,7 +56,7 @@ class DirectRadioButton(DirectButton):
('boxImageScale', 1.0, None), ('boxImageScale', 1.0, None),
('boxImageColor', VBase4(1, 1, 1, 1), None), ('boxImageColor', VBase4(1, 1, 1, 1), None),
('boxRelief', None, None), ('boxRelief', None, None),
) )
# Merge keyword options with default options # Merge keyword options with default options
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)
# Initialize superclasses # Initialize superclasses
@ -194,7 +196,6 @@ class DirectRadioButton(DirectButton):
self.indicator.setPos(newpos[0], newpos[1], newpos[2]) self.indicator.setPos(newpos[0], newpos[1], newpos[2])
def commandFunc(self, event): def commandFunc(self, event):
if len(self['value']) == len(self['variable']) != 0: if len(self['value']) == len(self['variable']) != 0:
for i in range(len(self['value'])): for i in range(len(self['value'])):

View File

@ -17,6 +17,7 @@ class DirectScrollBar(DirectFrame):
DirectScrollBar -- a widget which represents a scroll bar the user can DirectScrollBar -- a widget which represents a scroll bar the user can
use for paging through a large document or panel. use for paging through a large document or panel.
""" """
def __init__(self, parent = None, **kw): def __init__(self, parent = None, **kw):
optiondefs = ( optiondefs = (
# Define type of DirectGuiWidget # Define type of DirectGuiWidget
@ -35,18 +36,18 @@ class DirectScrollBar(DirectFrame):
# Function to be called repeatedly as the bar is scrolled # Function to be called repeatedly as the bar is scrolled
('command', None, None), ('command', None, None),
('extraArgs', [], None), ('extraArgs', [], None),
) )
if kw.get('orientation') in (DGG.VERTICAL, DGG.VERTICAL_INVERTED): if kw.get('orientation') in (DGG.VERTICAL, DGG.VERTICAL_INVERTED):
# These are the default options for a vertical layout. # These are the default options for a vertical layout.
optiondefs += ( optiondefs += (
('frameSize', (-0.04, 0.04, -0.5, 0.5), None), ('frameSize', (-0.04, 0.04, -0.5, 0.5), None),
) )
else: else:
# These are the default options for a horizontal layout. # These are the default options for a horizontal layout.
optiondefs += ( optiondefs += (
('frameSize', (-0.5, 0.5, -0.04, 0.04), None), ('frameSize', (-0.5, 0.5, -0.04, 0.04), None),
) )
# Merge keyword options with default options # Merge keyword options with default options
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)

View File

@ -24,6 +24,7 @@ class DirectScrolledFrame(DirectFrame):
0 and explicitly position and hide or show the scroll bars 0 and explicitly position and hide or show the scroll bars
yourself. yourself.
""" """
def __init__(self, parent = None, **kw): def __init__(self, parent = None, **kw):
optiondefs = ( optiondefs = (
# Define type of DirectGuiWidget # Define type of DirectGuiWidget
@ -35,7 +36,7 @@ class DirectScrolledFrame(DirectFrame):
('autoHideScrollBars', 1, self.setAutoHideScrollBars), ('autoHideScrollBars', 1, self.setAutoHideScrollBars),
('scrollBarWidth', 0.08, self.setScrollBarWidth), ('scrollBarWidth', 0.08, self.setScrollBarWidth),
('borderWidth', (0.01, 0.01), self.setBorderWidth), ('borderWidth', (0.01, 0.01), self.setBorderWidth),
) )
# Merge keyword options with default options # Merge keyword options with default options
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)

View File

@ -37,7 +37,7 @@ class DirectScrolledListItem(DirectButton):
optiondefs = ( optiondefs = (
('parent', self._parent, None), ('parent', self._parent, None),
('command', self.select, None), ('command', self.select, None),
) )
# Merge keyword options with default options # Merge keyword options with default options
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)
DirectButton.__init__(self) DirectButton.__init__(self)
@ -91,7 +91,7 @@ class DirectScrolledList(DirectFrame):
('forceHeight', None, self.setForceHeight), ('forceHeight', None, self.setForceHeight),
('incButtonCallback', None, self.setIncButtonCallback), ('incButtonCallback', None, self.setIncButtonCallback),
('decButtonCallback', None, self.setDecButtonCallback), ('decButtonCallback', None, self.setDecButtonCallback),
) )
# Merge keyword options with default options # Merge keyword options with default options
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)
@ -198,7 +198,7 @@ class DirectScrolledList(DirectFrame):
#print "scrollTo[", index,"] called, len(self[items])=", len(self["items"])," self[numItemsVisible]=", self["numItemsVisible"] #print "scrollTo[", index,"] called, len(self[items])=", len(self["items"])," self[numItemsVisible]=", self["numItemsVisible"]
try: try:
self["numItemsVisible"] self["numItemsVisible"]
except: except Exception:
# RAU hack to kill 27633 # RAU hack to kill 27633
self.notify.info('crash 27633 fixed!') self.notify.info('crash 27633 fixed!')
return return

View File

@ -18,6 +18,7 @@ class DirectSlider(DirectFrame):
DirectSlider -- a widget which represents a slider that the DirectSlider -- a widget which represents a slider that the
user can pull left and right to represent a continuous value. user can pull left and right to represent a continuous value.
""" """
def __init__(self, parent = None, **kw): def __init__(self, parent = None, **kw):
optiondefs = ( optiondefs = (
# Define type of DirectGuiWidget # Define type of DirectGuiWidget
@ -34,20 +35,20 @@ class DirectSlider(DirectFrame):
# Function to be called repeatedly as slider is moved # Function to be called repeatedly as slider is moved
('command', None, None), ('command', None, None),
('extraArgs', [], None), ('extraArgs', [], None),
) )
if kw.get('orientation') in (DGG.VERTICAL, DGG.VERTICAL_INVERTED): if kw.get('orientation') in (DGG.VERTICAL, DGG.VERTICAL_INVERTED):
# These are the default options for a vertical layout. # These are the default options for a vertical layout.
optiondefs += ( optiondefs += (
('frameSize', (-0.08, 0.08, -1, 1), None), ('frameSize', (-0.08, 0.08, -1, 1), None),
('frameVisibleScale', (0.25, 1), None), ('frameVisibleScale', (0.25, 1), None),
) )
else: else:
# These are the default options for a horizontal layout. # These are the default options for a horizontal layout.
optiondefs += ( optiondefs += (
('frameSize', (-1, 1, -0.08, 0.08), None), ('frameSize', (-1, 1, -0.08, 0.08), None),
('frameVisibleScale', (1, 0.25), None), ('frameVisibleScale', (1, 0.25), None),
) )
# Merge keyword options with default options # Merge keyword options with default options
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)

View File

@ -33,12 +33,12 @@ class DirectWaitBar(DirectFrame):
('barTexture', None, self.setBarTexture), ('barTexture', None, self.setBarTexture),
('barRelief', DGG.FLAT, self.setBarRelief), ('barRelief', DGG.FLAT, self.setBarRelief),
('sortOrder', DGG.NO_FADE_SORT_INDEX, None), ('sortOrder', DGG.NO_FADE_SORT_INDEX, None),
) )
if 'text' in kw: if 'text' in kw:
textoptiondefs = ( textoptiondefs = (
('text_pos', (0, -0.025), None), ('text_pos', (0, -0.025), None),
('text_scale', 0.1, None) ('text_scale', 0.1, None)
) )
else: else:
textoptiondefs = () textoptiondefs = ()
# Merge keyword options with default options # Merge keyword options with default options

View File

@ -20,6 +20,7 @@ ScreenPrompt = 3
NameConfirm = 4 NameConfirm = 4
BlackOnWhite = 5 BlackOnWhite = 5
class OnscreenText(NodePath): class OnscreenText(NodePath):
def __init__(self, text = '', def __init__(self, text = '',
@ -465,7 +466,7 @@ class OnscreenText(NodePath):
Mat4.scaleMat(Vec3.rfu(self.__scale[0], 1, self.__scale[1])) * Mat4.scaleMat(Vec3.rfu(self.__scale[0], 1, self.__scale[1])) *
Mat4.rotateMat(self.__roll, Vec3.back()) * Mat4.rotateMat(self.__roll, Vec3.back()) *
Mat4.translateMat(Point3.rfu(self.__pos[0], 0, self.__pos[1])) Mat4.translateMat(Point3.rfu(self.__pos[0], 0, self.__pos[1]))
) )
self.textNode.setTransform(mat) self.textNode.setTransform(mat)
def setWordwrap(self, wordwrap): def setWordwrap(self, wordwrap):

View File

@ -15,8 +15,8 @@ from .IndirectInterval import *
from .MopathInterval import * from .MopathInterval import *
try: try:
import panda3d.physics import panda3d.physics
##Some people may have the particle system compiled out # Some people may have the particle system compiled out
if hasattr( panda3d.physics, 'ParticleSystem' ): if hasattr(panda3d.physics, 'ParticleSystem'):
from .ParticleInterval import * from .ParticleInterval import *
if __debug__: if __debug__:
from .TestInterval import * from .TestInterval import *

View File

@ -10,7 +10,7 @@ __all__ = [
'LerpColorInterval', 'LerpColorScaleInterval', 'LerpColorInterval', 'LerpColorScaleInterval',
'LerpTexOffsetInterval', 'LerpTexRotateInterval', 'LerpTexScaleInterval', 'LerpTexOffsetInterval', 'LerpTexRotateInterval', 'LerpTexScaleInterval',
'LerpFunctionInterval', 'LerpFunc','LerpFunctionNoStateInterval','LerpFuncNS' 'LerpFunctionInterval', 'LerpFunc','LerpFunctionNoStateInterval','LerpFuncNS'
] ]
from panda3d.core import LOrientationf, NodePath from panda3d.core import LOrientationf, NodePath
from panda3d.direct import CInterval, CLerpNodePathInterval from panda3d.direct import CInterval, CLerpNodePathInterval
@ -25,6 +25,7 @@ from . import LerpBlendHelpers
# performance. # performance.
# #
class LerpNodePathInterval(CLerpNodePathInterval): class LerpNodePathInterval(CLerpNodePathInterval):
# This is the base class for all of the lerps, defined below, that # This is the base class for all of the lerps, defined below, that
# affect a property on a NodePath, like pos or hpr. # affect a property on a NodePath, like pos or hpr.
@ -99,6 +100,7 @@ class LerpNodePathInterval(CLerpNodePathInterval):
## ##
##################################################################### #####################################################################
class LerpPosInterval(LerpNodePathInterval): class LerpPosInterval(LerpNodePathInterval):
def __init__(self, nodePath, duration, pos, startPos = None, def __init__(self, nodePath, duration, pos, startPos = None,
other = None, blendType = 'noBlend', other = None, blendType = 'noBlend',
@ -157,6 +159,7 @@ class LerpHprInterval(LerpNodePathInterval):
self.setupParam(self.setStartQuat, self.startQuat) self.setupParam(self.setStartQuat, self.startQuat)
LerpNodePathInterval.privDoEvent(self, t, event) LerpNodePathInterval.privDoEvent(self, t, event)
class LerpQuatInterval(LerpNodePathInterval): class LerpQuatInterval(LerpNodePathInterval):
def __init__(self, nodePath, duration, quat = None, def __init__(self, nodePath, duration, quat = None,
startHpr = None, startQuat = None, startHpr = None, startQuat = None,
@ -195,6 +198,7 @@ class LerpQuatInterval(LerpNodePathInterval):
self.setupParam(self.setStartQuat, self.startQuat) self.setupParam(self.setStartQuat, self.startQuat)
LerpNodePathInterval.privDoEvent(self, t, event) LerpNodePathInterval.privDoEvent(self, t, event)
class LerpScaleInterval(LerpNodePathInterval): class LerpScaleInterval(LerpNodePathInterval):
def __init__(self, nodePath, duration, scale, startScale = None, def __init__(self, nodePath, duration, scale, startScale = None,
other = None, blendType = 'noBlend', other = None, blendType = 'noBlend',
@ -220,6 +224,7 @@ class LerpScaleInterval(LerpNodePathInterval):
self.setupParam(self.setStartScale, self.startScale) self.setupParam(self.setStartScale, self.startScale)
LerpNodePathInterval.privDoEvent(self, t, event) LerpNodePathInterval.privDoEvent(self, t, event)
class LerpShearInterval(LerpNodePathInterval): class LerpShearInterval(LerpNodePathInterval):
def __init__(self, nodePath, duration, shear, startShear = None, def __init__(self, nodePath, duration, shear, startShear = None,
other = None, blendType = 'noBlend', other = None, blendType = 'noBlend',
@ -245,6 +250,7 @@ class LerpShearInterval(LerpNodePathInterval):
self.setupParam(self.setStartShear, self.startShear) self.setupParam(self.setStartShear, self.startShear)
LerpNodePathInterval.privDoEvent(self, t, event) LerpNodePathInterval.privDoEvent(self, t, event)
class LerpPosHprInterval(LerpNodePathInterval): class LerpPosHprInterval(LerpNodePathInterval):
def __init__(self, nodePath, duration, pos, hpr, def __init__(self, nodePath, duration, pos, hpr,
startPos = None, startHpr = None, startQuat = None, startPos = None, startHpr = None, startQuat = None,
@ -282,6 +288,7 @@ class LerpPosHprInterval(LerpNodePathInterval):
self.setupParam(self.setStartQuat, self.startQuat) self.setupParam(self.setStartQuat, self.startQuat)
LerpNodePathInterval.privDoEvent(self, t, event) LerpNodePathInterval.privDoEvent(self, t, event)
class LerpPosQuatInterval(LerpNodePathInterval): class LerpPosQuatInterval(LerpNodePathInterval):
def __init__(self, nodePath, duration, pos, quat = None, def __init__(self, nodePath, duration, pos, quat = None,
startPos = None, startHpr = None, startQuat = None, startPos = None, startHpr = None, startQuat = None,
@ -327,6 +334,7 @@ class LerpPosQuatInterval(LerpNodePathInterval):
self.setupParam(self.setStartQuat, self.startQuat) self.setupParam(self.setStartQuat, self.startQuat)
LerpNodePathInterval.privDoEvent(self, t, event) LerpNodePathInterval.privDoEvent(self, t, event)
class LerpHprScaleInterval(LerpNodePathInterval): class LerpHprScaleInterval(LerpNodePathInterval):
def __init__(self, nodePath, duration, hpr, scale, def __init__(self, nodePath, duration, hpr, scale,
startHpr = None, startQuat = None, startScale = None, startHpr = None, startQuat = None, startScale = None,
@ -365,6 +373,7 @@ class LerpHprScaleInterval(LerpNodePathInterval):
self.setupParam(self.setStartScale, self.startScale) self.setupParam(self.setStartScale, self.startScale)
LerpNodePathInterval.privDoEvent(self, t, event) LerpNodePathInterval.privDoEvent(self, t, event)
class LerpQuatScaleInterval(LerpNodePathInterval): class LerpQuatScaleInterval(LerpNodePathInterval):
def __init__(self, nodePath, duration, quat = None, scale = None, def __init__(self, nodePath, duration, quat = None, scale = None,
hpr = None, hpr = None,
@ -413,6 +422,7 @@ class LerpQuatScaleInterval(LerpNodePathInterval):
self.setupParam(self.setStartScale, self.startScale) self.setupParam(self.setStartScale, self.startScale)
LerpNodePathInterval.privDoEvent(self, t, event) LerpNodePathInterval.privDoEvent(self, t, event)
class LerpPosHprScaleInterval(LerpNodePathInterval): class LerpPosHprScaleInterval(LerpNodePathInterval):
def __init__(self, nodePath, duration, pos, hpr, scale, def __init__(self, nodePath, duration, pos, hpr, scale,
startPos = None, startHpr = None, startQuat = None, startPos = None, startHpr = None, startQuat = None,
@ -459,6 +469,7 @@ class LerpPosHprScaleInterval(LerpNodePathInterval):
self.setupParam(self.setStartScale, self.startScale) self.setupParam(self.setStartScale, self.startScale)
LerpNodePathInterval.privDoEvent(self, t, event) LerpNodePathInterval.privDoEvent(self, t, event)
class LerpPosQuatScaleInterval(LerpNodePathInterval): class LerpPosQuatScaleInterval(LerpNodePathInterval):
def __init__(self, nodePath, duration, pos, quat = None, scale = None, def __init__(self, nodePath, duration, pos, quat = None, scale = None,
startPos = None, startHpr = None, startQuat = None, startPos = None, startHpr = None, startQuat = None,
@ -515,6 +526,7 @@ class LerpPosQuatScaleInterval(LerpNodePathInterval):
self.setupParam(self.setStartScale, self.startScale) self.setupParam(self.setStartScale, self.startScale)
LerpNodePathInterval.privDoEvent(self, t, event) LerpNodePathInterval.privDoEvent(self, t, event)
class LerpPosHprScaleShearInterval(LerpNodePathInterval): class LerpPosHprScaleShearInterval(LerpNodePathInterval):
def __init__(self, nodePath, duration, pos, hpr, scale, shear, def __init__(self, nodePath, duration, pos, hpr, scale, shear,
startPos = None, startHpr = None, startQuat = None, startPos = None, startHpr = None, startQuat = None,
@ -569,6 +581,7 @@ class LerpPosHprScaleShearInterval(LerpNodePathInterval):
self.setupParam(self.setStartShear, self.startShear) self.setupParam(self.setStartShear, self.startShear)
LerpNodePathInterval.privDoEvent(self, t, event) LerpNodePathInterval.privDoEvent(self, t, event)
class LerpPosQuatScaleShearInterval(LerpNodePathInterval): class LerpPosQuatScaleShearInterval(LerpNodePathInterval):
def __init__(self, nodePath, duration, pos, quat = None, scale = None, def __init__(self, nodePath, duration, pos, quat = None, scale = None,
shear = None, shear = None,
@ -635,6 +648,7 @@ class LerpPosQuatScaleShearInterval(LerpNodePathInterval):
self.setupParam(self.setStartShear, self.startShear) self.setupParam(self.setStartShear, self.startShear)
LerpNodePathInterval.privDoEvent(self, t, event) LerpNodePathInterval.privDoEvent(self, t, event)
class LerpColorInterval(LerpNodePathInterval): class LerpColorInterval(LerpNodePathInterval):
def __init__(self, nodePath, duration, color, startColor = None, def __init__(self, nodePath, duration, color, startColor = None,
other = None, blendType = 'noBlend', other = None, blendType = 'noBlend',
@ -647,6 +661,7 @@ class LerpColorInterval(LerpNodePathInterval):
if override is not None: if override is not None:
self.setOverride(override) self.setOverride(override)
class LerpColorScaleInterval(LerpNodePathInterval): class LerpColorScaleInterval(LerpNodePathInterval):
def __init__(self, nodePath, duration, colorScale, startColorScale = None, def __init__(self, nodePath, duration, colorScale, startColorScale = None,
other = None, blendType = 'noBlend', other = None, blendType = 'noBlend',
@ -659,6 +674,7 @@ class LerpColorScaleInterval(LerpNodePathInterval):
if override is not None: if override is not None:
self.setOverride(override) self.setOverride(override)
class LerpTexOffsetInterval(LerpNodePathInterval): class LerpTexOffsetInterval(LerpNodePathInterval):
def __init__(self, nodePath, duration, texOffset, startTexOffset = None, def __init__(self, nodePath, duration, texOffset, startTexOffset = None,
other = None, blendType = 'noBlend', other = None, blendType = 'noBlend',
@ -674,6 +690,7 @@ class LerpTexOffsetInterval(LerpNodePathInterval):
if override is not None: if override is not None:
self.setOverride(override) self.setOverride(override)
class LerpTexRotateInterval(LerpNodePathInterval): class LerpTexRotateInterval(LerpNodePathInterval):
def __init__(self, nodePath, duration, texRotate, startTexRotate = None, def __init__(self, nodePath, duration, texRotate, startTexRotate = None,
other = None, blendType = 'noBlend', other = None, blendType = 'noBlend',
@ -689,6 +706,7 @@ class LerpTexRotateInterval(LerpNodePathInterval):
if override is not None: if override is not None:
self.setOverride(override) self.setOverride(override)
class LerpTexScaleInterval(LerpNodePathInterval): class LerpTexScaleInterval(LerpNodePathInterval):
def __init__(self, nodePath, duration, texScale, startTexScale = None, def __init__(self, nodePath, duration, texScale, startTexScale = None,
other = None, blendType = 'noBlend', other = None, blendType = 'noBlend',
@ -705,8 +723,6 @@ class LerpTexScaleInterval(LerpNodePathInterval):
self.setOverride(override) self.setOverride(override)
# #
# The remaining intervals defined in this module are the old-school # The remaining intervals defined in this module are the old-school
# Python-based intervals. # Python-based intervals.
@ -733,6 +749,7 @@ class LerpFunctionNoStateInterval(Interval.Interval):
# create LerpFunctionInterval DirectNotify category # create LerpFunctionInterval DirectNotify category
notify = directNotify.newCategory('LerpFunctionNoStateInterval') notify = directNotify.newCategory('LerpFunctionNoStateInterval')
# Class methods # Class methods
def __init__(self, function, duration = 0.0, fromData = 0, toData = 1, def __init__(self, function, duration = 0.0, fromData = 0, toData = 1,
blendType = 'noBlend', extraArgs = [], name = None): blendType = 'noBlend', extraArgs = [], name = None):
"""__init__(function, duration, fromData, toData, name) """__init__(function, duration, fromData, toData, name)
@ -758,9 +775,8 @@ class LerpFunctionNoStateInterval(Interval.Interval):
# Initialize superclass # Initialize superclass
Interval.Interval.__init__(self, name, duration) Interval.Interval.__init__(self, name, duration)
#def privDoEvent(self,t,event): #def privDoEvent(self, t, event):
#print("doing event", t, event)
#print "doing event",t,event
#bt = self.blendType(t/self.duration) #bt = self.blendType(t/self.duration)
#data = (self.fromData * (1 - bt)) + (self.toData * bt) #data = (self.fromData * (1 - bt)) + (self.toData * bt)
## Evaluate function ## Evaluate function
@ -770,7 +786,7 @@ class LerpFunctionNoStateInterval(Interval.Interval):
def privStep(self, t): def privStep(self, t):
# Evaluate the function # Evaluate the function
#print "doing priv step",t #print("doing priv step", t)
if t >= self.duration: if t >= self.duration:
# Set to end value # Set to end value
if t > self.duration: if t > self.duration:
@ -787,12 +803,14 @@ class LerpFunctionNoStateInterval(Interval.Interval):
self.function(*[data] + self.extraArgs) self.function(*[data] + self.extraArgs)
# Print debug information # Print debug information
# assert self.notify.debug('updateFunc() - %s: t = %f' % (self.name, t)) #assert self.notify.debug('updateFunc() - %s: t = %f' % (self.name, t))
self.state = CInterval.SStarted self.state = CInterval.SStarted
self.currT = t self.currT = t
# New interface # New interface
class LerpFuncNS(LerpFunctionNoStateInterval): class LerpFuncNS(LerpFunctionNoStateInterval):
def __init__(self, *args, **kw): def __init__(self, *args, **kw):
LerpFunctionNoStateInterval.__init__(self, *args, **kw) LerpFunctionNoStateInterval.__init__(self, *args, **kw)
@ -810,6 +828,7 @@ class LerpFunctionInterval(Interval.Interval):
# create LerpFunctionInterval DirectNotify category # create LerpFunctionInterval DirectNotify category
notify = directNotify.newCategory('LerpFunctionInterval') notify = directNotify.newCategory('LerpFunctionInterval')
# Class methods # Class methods
def __init__(self, function, duration = 0.0, fromData = 0, toData = 1, def __init__(self, function, duration = 0.0, fromData = 0, toData = 1,
blendType = 'noBlend', extraArgs = [], name = None): blendType = 'noBlend', extraArgs = [], name = None):
"""__init__(function, duration, fromData, toData, name) """__init__(function, duration, fromData, toData, name)
@ -838,7 +857,7 @@ class LerpFunctionInterval(Interval.Interval):
def privStep(self, t): def privStep(self, t):
# Evaluate the function # Evaluate the function
#print "doing priv step",t #print("doing priv step", t)
if t >= self.duration: if t >= self.duration:
# Set to end value # Set to end value
self.function(*[self.toData] + self.extraArgs) self.function(*[self.toData] + self.extraArgs)
@ -853,12 +872,14 @@ class LerpFunctionInterval(Interval.Interval):
self.function(*[data] + self.extraArgs) self.function(*[data] + self.extraArgs)
# Print debug information # Print debug information
# assert self.notify.debug('updateFunc() - %s: t = %f' % (self.name, t)) #assert self.notify.debug('updateFunc() - %s: t = %f' % (self.name, t))
self.state = CInterval.SStarted self.state = CInterval.SStarted
self.currT = t self.currT = t
# New interface # New interface
class LerpFunc(LerpFunctionInterval): class LerpFunc(LerpFunctionInterval):
def __init__(self, *args, **kw): def __init__(self, *args, **kw):
LerpFunctionInterval.__init__(self, *args, **kw) LerpFunctionInterval.__init__(self, *args, **kw)

View File

@ -25,23 +25,23 @@ class AnimMgrBase:
#normal properties #normal properties
self.lerpFuncs = { self.lerpFuncs = {
'H' : self.lerpFuncH, 'H': self.lerpFuncH,
'P' : self.lerpFuncP, 'P': self.lerpFuncP,
'R' : self.lerpFuncR, 'R': self.lerpFuncR,
'SX' : self.lerpFuncSX, 'SX': self.lerpFuncSX,
'SY' : self.lerpFuncSY, 'SY': self.lerpFuncSY,
'SZ' : self.lerpFuncSZ, 'SZ': self.lerpFuncSZ,
'CR' : self.lerpFuncCR, 'CR': self.lerpFuncCR,
'CG' : self.lerpFuncCG, 'CG': self.lerpFuncCG,
'CB' : self.lerpFuncCB, 'CB': self.lerpFuncCB,
'CA' : self.lerpFuncCA 'CA': self.lerpFuncCA
} }
#Properties which has animation curves #Properties which has animation curves
self.curveLerpFuncs = { self.curveLerpFuncs = {
'X' : [ self.lerpFuncX, self.lerpCurveFuncX ], 'X': [self.lerpFuncX, self.lerpCurveFuncX],
'Y' : [ self.lerpFuncY, self.lerpCurveFuncY ], 'Y': [self.lerpFuncY, self.lerpCurveFuncY],
'Z' : [ self.lerpFuncZ, self.lerpCurveFuncZ ] 'Z': [self.lerpFuncZ, self.lerpCurveFuncZ]
} }
def reset(self): def reset(self):

View File

@ -10,6 +10,7 @@ class CurveAnimUI(wx.Dialog):
""" """
This is the Curve Animation Panel implementation. This is the Curve Animation Panel implementation.
""" """
def __init__(self, parent, editor): def __init__(self, parent, editor):
wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title="Curve Animation", wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title="Curve Animation",
pos=wx.DefaultPosition, size=(430, 140)) pos=wx.DefaultPosition, size=(430, 140))
@ -20,19 +21,19 @@ class CurveAnimUI(wx.Dialog):
self.mainPanel = wx.Panel(self, -1) self.mainPanel = wx.Panel(self, -1)
self.chooseNode = wx.StaticText( self.mainPanel, -1, "Choose NodePath:") self.chooseNode = wx.StaticText(self.mainPanel, -1, "Choose NodePath:")
self.chooseNodeTxt = wx.TextCtrl( self.mainPanel, -1, "") self.chooseNodeTxt = wx.TextCtrl(self.mainPanel, -1, "")
self.chooseNodeButton = wx.Button( self.mainPanel, -1, "Choose..") self.chooseNodeButton = wx.Button(self.mainPanel, -1, "Choose..")
self.chooseCurve = wx.StaticText( self.mainPanel, -1, "Choose attch Curve:") self.chooseCurve = wx.StaticText(self.mainPanel, -1, "Choose attch Curve:")
self.chooseCurveTxt = wx.TextCtrl( self.mainPanel, -1, "") self.chooseCurveTxt = wx.TextCtrl(self.mainPanel, -1, "")
self.chooseCurveButton = wx.Button( self.mainPanel, -1, "Choose..") self.chooseCurveButton = wx.Button(self.mainPanel, -1, "Choose..")
self.duritionTime = wx.StaticText( self.mainPanel, -1, "Durition(Frame):") self.duritionTime = wx.StaticText(self.mainPanel, -1, "Durition(Frame):")
self.duritionTimeSpin = wx.SpinCtrl( self.mainPanel, -1, "",size = (70,25), min=24, max=10000) self.duritionTimeSpin = wx.SpinCtrl(self.mainPanel, -1, "", size=(70,25), min=24, max=10000)
self.createAnimButton = wx.Button( self.mainPanel, -1, "Creat") self.createAnimButton = wx.Button(self.mainPanel, -1, "Creat")
self.saveAnimButton = wx.Button( self.mainPanel, -1, "Save Animation") self.saveAnimButton = wx.Button(self.mainPanel, -1, "Save Animation")
self.SetProperties() self.SetProperties()
self.DoLayout() self.DoLayout()
@ -46,44 +47,44 @@ class CurveAnimUI(wx.Dialog):
def SetProperties(self): def SetProperties(self):
self.duritionTimeSpin.SetValue(24) self.duritionTimeSpin.SetValue(24)
self.chooseNodeTxt.SetMinSize((200,21)) self.chooseNodeTxt.SetMinSize((200, 21))
self.chooseCurveTxt.SetMinSize((200,21)) self.chooseCurveTxt.SetMinSize((200, 21))
self.saveAnimButton.SetToolTipString("Save the animation to the global animation control") self.saveAnimButton.SetToolTipString("Save the animation to the global animation control")
def DoLayout(self): def DoLayout(self):
dialogSizer = wx.BoxSizer(wx.VERTICAL) dialogSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer = wx.FlexGridSizer(4, 3, 0, 0) mainSizer = wx.FlexGridSizer(4, 3, 0, 0)
mainSizer.Add(self.chooseNode, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 10) mainSizer.Add(self.chooseNode, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 10)
mainSizer.Add(self.chooseNodeTxt, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5) mainSizer.Add(self.chooseNodeTxt, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 5)
mainSizer.Add(self.chooseNodeButton, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5) mainSizer.Add(self.chooseNodeButton, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 5)
mainSizer.Add(self.chooseCurve, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 10) mainSizer.Add(self.chooseCurve, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 10)
mainSizer.Add(self.chooseCurveTxt, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5) mainSizer.Add(self.chooseCurveTxt, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 5)
mainSizer.Add(self.chooseCurveButton, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5) mainSizer.Add(self.chooseCurveButton, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 5)
mainSizer.Add(self.duritionTime, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 10) mainSizer.Add(self.duritionTime, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 10)
mainSizer.Add(self.duritionTimeSpin, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5) mainSizer.Add(self.duritionTimeSpin, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 5)
mainSizer.Add(self.createAnimButton, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5) mainSizer.Add(self.createAnimButton, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 5)
mainSizer.Add(self.saveAnimButton, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5) mainSizer.Add(self.saveAnimButton, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 5)
self.mainPanel.SetSizerAndFit(mainSizer) self.mainPanel.SetSizerAndFit(mainSizer)
dialogSizer.Add(self.mainPanel, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) dialogSizer.Add(self.mainPanel, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
self.SetSizer(dialogSizer) self.SetSizer(dialogSizer)
self.Layout() self.Layout()
def OnChooseNode(self, evt): def OnChooseNode(self, evt):
if base.direct.selected.last is None or base.direct.selected.last.hasTag('Controller') or not base.direct.selected.last.hasTag('OBJRoot'): if base.direct.selected.last is None or base.direct.selected.last.hasTag('Controller') or not base.direct.selected.last.hasTag('OBJRoot'):
dlg = wx.MessageDialog(None, 'Please select an object.', 'NOTICE', wx.OK ) dlg = wx.MessageDialog(None, 'Please select an object.', 'NOTICE', wx.OK)
dlg.ShowModal() dlg.ShowModal()
dlg.Destroy() dlg.Destroy()
else: else:
obj = self.editor.objectMgr.findObjectByNodePath(base.direct.selected.last) obj = self.editor.objectMgr.findObjectByNodePath(base.direct.selected.last)
if obj[OG.OBJ_DEF].name == '__Curve__': if obj[OG.OBJ_DEF].name == '__Curve__':
dlg = wx.MessageDialog(None, 'Please select an object, not a curve.', 'NOTICE', wx.OK ) dlg = wx.MessageDialog(None, 'Please select an object, not a curve.', 'NOTICE', wx.OK)
dlg.ShowModal() dlg.ShowModal()
dlg.Destroy() dlg.Destroy()
else: else:
@ -92,13 +93,13 @@ class CurveAnimUI(wx.Dialog):
def OnChooseCurve(self, evt): def OnChooseCurve(self, evt):
if base.direct.selected.last is None or base.direct.selected.last.hasTag('Controller') or not base.direct.selected.last.hasTag('OBJRoot'): if base.direct.selected.last is None or base.direct.selected.last.hasTag('Controller') or not base.direct.selected.last.hasTag('OBJRoot'):
dlg = wx.MessageDialog(None, 'Please select a curve.', 'NOTICE', wx.OK ) dlg = wx.MessageDialog(None, 'Please select a curve.', 'NOTICE', wx.OK)
dlg.ShowModal() dlg.ShowModal()
dlg.Destroy() dlg.Destroy()
else: else:
obj = self.editor.objectMgr.findObjectByNodePath(base.direct.selected.last) obj = self.editor.objectMgr.findObjectByNodePath(base.direct.selected.last)
if obj[OG.OBJ_DEF].name != '__Curve__': if obj[OG.OBJ_DEF].name != '__Curve__':
dlg = wx.MessageDialog(None, 'Please select a curve, not an object.', 'NOTICE', wx.OK ) dlg = wx.MessageDialog(None, 'Please select a curve, not an object.', 'NOTICE', wx.OK)
dlg.ShowModal() dlg.ShowModal()
dlg.Destroy() dlg.Destroy()
elif obj[OG.OBJ_DEF].name == '__Curve__': elif obj[OG.OBJ_DEF].name == '__Curve__':
@ -108,43 +109,45 @@ class CurveAnimUI(wx.Dialog):
def OnCreateAnim(self, evt): def OnCreateAnim(self, evt):
self.time = self.duritionTimeSpin.GetValue() self.time = self.duritionTimeSpin.GetValue()
if self.nodePath is None or self.curve is None: if self.nodePath is None or self.curve is None:
dlg = wx.MessageDialog(None, 'Please select an object and a curve first.', 'NOTICE', wx.OK ) dlg = wx.MessageDialog(None, 'Please select an object and a curve first.', 'NOTICE', wx.OK)
dlg.ShowModal() dlg.ShowModal()
dlg.Destroy() dlg.Destroy()
else: else:
self.curveSequence = self.editor.animMgr.singleCurveAnimation(self.nodePath, self.curve, self.time) self.curveSequence = self.editor.animMgr.singleCurveAnimation(self.nodePath, self.curve, self.time)
self.curveSequence.start() self.curveSequence.start()
def OnSaveAnim(self,evt): def OnSaveAnim(self, evt):
if not self.curveSequence: if not self.curveSequence:
dlg = wx.MessageDialog(None, 'Please create a animation first.', 'NOTICE', wx.OK ) dlg = wx.MessageDialog(None, 'Please create an animation first.', 'NOTICE', wx.OK)
dlg.ShowModal() dlg.ShowModal()
dlg.Destroy() dlg.Destroy()
else: else:
if self.editor.animMgr.curveAnimation == {}: if self.editor.animMgr.curveAnimation == {}:
self.editor.animMgr.curveAnimation[(self.nodePath[OG.OBJ_UID],self.curve[OG.OBJ_UID])] = (self.nodePath[OG.OBJ_UID],self.curve[OG.OBJ_UID],self.time) self.editor.animMgr.curveAnimation[(self.nodePath[OG.OBJ_UID], self.curve[OG.OBJ_UID])] = \
(self.nodePath[OG.OBJ_UID], self.curve[OG.OBJ_UID], self.time)
self.editor.updateStatusReadout('Sucessfully saved to global animation list') self.editor.updateStatusReadout('Sucessfully saved to global animation list')
return return
hasKey = False hasKey = False
for key in self.editor.animMgr.curveAnimation: for key in self.editor.animMgr.curveAnimation:
if key == (self.nodePath[OG.OBJ_UID], self.curve[OG.OBJ_UID]): if key == (self.nodePath[OG.OBJ_UID], self.curve[OG.OBJ_UID]):
dlg = wx.MessageDialog(None, 'Already have the animation for this object attach to this curve.', 'NOTICE', wx.OK ) dlg = wx.MessageDialog(None, 'Already have the animation for this object attach to this curve.', 'NOTICE', wx.OK)
dlg.ShowModal() dlg.ShowModal()
dlg.Destroy() dlg.Destroy()
hasKey = True hasKey = True
return return
elif self.nodePath[OG.OBJ_UID] == key[0]: elif self.nodePath[OG.OBJ_UID] == key[0]:
dlg = wx.MessageDialog(None, 'This object is already attached to a curve.', 'NOTICE', wx.OK ) dlg = wx.MessageDialog(None, 'This object is already attached to a curve.', 'NOTICE', wx.OK)
dlg.ShowModal() dlg.ShowModal()
dlg.Destroy() dlg.Destroy()
hasKey = True hasKey = True
return return
if not hasKey and self.editor.animMgr.curveAnimation != {}: if not hasKey and self.editor.animMgr.curveAnimation != {}:
self.editor.animMgr.curveAnimation[(self.nodePath[OG.OBJ_UID],self.curve[OG.OBJ_UID])] = (self.nodePath[OG.OBJ_UID],self.curve[OG.OBJ_UID],self.time) self.editor.animMgr.curveAnimation[(self.nodePath[OG.OBJ_UID], self.curve[OG.OBJ_UID])] = \
(self.nodePath[OG.OBJ_UID], self.curve[OG.OBJ_UID], self.time)
self.editor.updateStatusReadout('Sucessfully saved to global animation list') self.editor.updateStatusReadout('Sucessfully saved to global animation list')
def OnExit(self,evt): def OnExit(self, evt):
self.Destroy() self.Destroy()
self.editor.ui.curveAnimMenuItem.Check(False) self.editor.ui.curveAnimMenuItem.Check(False)

View File

@ -11,6 +11,7 @@ from direct.task import Task
class CurveEditor(DirectObject): class CurveEditor(DirectObject):
""" CurveEditor will create and edit the curve """ """ CurveEditor will create and edit the curve """
def __init__(self, editor): def __init__(self, editor):
self.editor = editor self.editor = editor
self.i = 0 self.i = 0
@ -76,11 +77,11 @@ class CurveEditor(DirectObject):
self.i = 0 self.i = 0
for item in self.curveControl: for item in self.curveControl:
item[1].hide() item[1].hide()
if self.editor.preMode == self.editor.BASE_MODE : if self.editor.preMode == self.editor.BASE_MODE:
pass pass
if self.editor.preMode == self.editor.CREATE_CURVE_MODE : if self.editor.preMode == self.editor.CREATE_CURVE_MODE:
self.updateScene() self.updateScene()
if self.editor.preMode == self.editor.EDIT_CURVE_MODE : if self.editor.preMode == self.editor.EDIT_CURVE_MODE:
self.doneEdit() self.doneEdit()
self.curveControl = [] self.curveControl = []
self.curve = [] self.curve = []

View File

@ -48,5 +48,5 @@ class FileMgr:
module = imp.load_module(moduleName, file, pathname, description) module = imp.load_module(moduleName, file, pathname, description)
self.editor.updateStatusReadout('Sucessfully opened file %s'%fileName) self.editor.updateStatusReadout('Sucessfully opened file %s'%fileName)
self.editor.fNeedToSave = False self.editor.fNeedToSave = False
except: except Exception:
print('failed to load %s'%fileName) print('failed to load %s'%fileName)

View File

@ -11,7 +11,7 @@ property = [
"translateX", "translateX",
"translateY", "translateY",
"translateZ" "translateZ"
] ]
#---------------------------------------------------------------------- #----------------------------------------------------------------------
ZoomIn = PyEmbeddedImage( ZoomIn = PyEmbeddedImage(
@ -79,10 +79,12 @@ TwoTangents = PyEmbeddedImage(
#---------------------------------------------------------------------- #----------------------------------------------------------------------
class GraphEditorWindow(wx.Window): class GraphEditorWindow(wx.Window):
""" """
This is the main graph editor window. This is the main graph editor window.
""" """
def __init__(self, parent, windowSize, property, xRange, yRange, curFrame, object): def __init__(self, parent, windowSize, property, xRange, yRange, curFrame, object):
wx.Window.__init__(self, parent, size = windowSize, style = wx.SUNKEN_BORDER) wx.Window.__init__(self, parent, size = windowSize, style = wx.SUNKEN_BORDER)
@ -388,7 +390,7 @@ class GraphEditorWindow(wx.Window):
dc.DrawLine(list[0][AG.KEYFRAME][AG.LOCAL_VALUE][0], list[0][AG.KEYFRAME][AG.LOCAL_VALUE][1], list[1][AG.KEYFRAME][AG.LOCAL_VALUE][0], list[1][AG.KEYFRAME][AG.LOCAL_VALUE][1]) dc.DrawLine(list[0][AG.KEYFRAME][AG.LOCAL_VALUE][0], list[0][AG.KEYFRAME][AG.LOCAL_VALUE][1], list[1][AG.KEYFRAME][AG.LOCAL_VALUE][0], list[1][AG.KEYFRAME][AG.LOCAL_VALUE][1])
return return
if len(list)>=3 : if len(list) >= 3:
for i in range(len(list)-1): for i in range(len(list)-1):
x1 = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0] x1 = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0]
y1 = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1] y1 = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1]
@ -406,7 +408,6 @@ class GraphEditorWindow(wx.Window):
scale1 = (x2 - x1) / t1x scale1 = (x2 - x1) / t1x
y2 = y1 - t1y * scale1 y2 = y1 - t1y * scale1
x3 = x4 - (x4 - x1) / 3.0 x3 = x4 - (x4 - x1) / 3.0
scale2 = (x4 - x3) / t2x scale2 = (x4 - x3) / t2x
y3 = y4 + t2y * scale2 y3 = y4 + t2y * scale2
@ -445,12 +446,12 @@ class GraphEditorWindow(wx.Window):
pointY = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1] pointY = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1]
if list[i][AG.KEYFRAME][AG.SELECT] == 0: if list[i][AG.KEYFRAME][AG.SELECT] == 0:
dc.SetPen(wx.Pen("black",3)) dc.SetPen(wx.Pen("black", 3))
dc.SetBrush(wx.Brush("black")) dc.SetBrush(wx.Brush("black"))
dc.DrawCircle(pointX, pointY, 2) dc.DrawCircle(pointX, pointY, 2)
if list[i][AG.KEYFRAME][AG.SELECT] == 1: if list[i][AG.KEYFRAME][AG.SELECT] == 1:
dc.SetPen(wx.Pen("cyan",3)) dc.SetPen(wx.Pen("cyan", 3))
dc.SetBrush(wx.Brush("cyan")) dc.SetBrush(wx.Brush("cyan"))
dc.DrawCircle(pointX, pointY, 2) dc.DrawCircle(pointX, pointY, 2)
@ -460,64 +461,64 @@ class GraphEditorWindow(wx.Window):
X1 = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0] X1 = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0]
Y1 = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1] Y1 = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1]
if self._OneTangent is True: if self._OneTangent is True:
for j in range(3,5): for j in range(3, 5):
X = list[i][j][AG.LOCAL_VALUE][0] X = list[i][j][AG.LOCAL_VALUE][0]
Y = list[i][j][AG.LOCAL_VALUE][1] Y = list[i][j][AG.LOCAL_VALUE][1]
if list[i][j][AG.SELECT] == 1: if list[i][j][AG.SELECT] == 1:
dc.SetPen(wx.Pen("cyan",3)) dc.SetPen(wx.Pen("cyan", 3))
dc.SetBrush(wx.Brush("cyan")) dc.SetBrush(wx.Brush("cyan"))
dc.DrawCircle(X, Y, 2) dc.DrawCircle(X, Y, 2)
dc.SetPen(wx.Pen("cyan",1)) dc.SetPen(wx.Pen("cyan", 1))
dc.DrawLine(X1, Y1, X, Y) dc.DrawLine(X1, Y1, X, Y)
if list[i][j][AG.SELECT] == 0: if list[i][j][AG.SELECT] == 0:
dc.SetPen(wx.Pen("brown",3)) dc.SetPen(wx.Pen("brown", 3))
dc.SetBrush(wx.Brush("brown")) dc.SetBrush(wx.Brush("brown"))
dc.DrawCircle(X, Y, 2) dc.DrawCircle(X, Y, 2)
dc.SetPen(wx.Pen("brown",1)) dc.SetPen(wx.Pen("brown", 1))
dc.DrawLine(X1, Y1, X, Y) dc.DrawLine(X1, Y1, X, Y)
if self._OneTangent is False: if self._OneTangent is False:
if list[i][AG.IN_TANGENT][AG.SELECT] == 1: if list[i][AG.IN_TANGENT][AG.SELECT] == 1:
X = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][0] X = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][0]
Y = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][1] Y = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][1]
dc.SetPen(wx.Pen("cyan",3)) dc.SetPen(wx.Pen("cyan", 3))
dc.SetBrush(wx.Brush("cyan")) dc.SetBrush(wx.Brush("cyan"))
dc.DrawCircle(X, Y, 2) dc.DrawCircle(X, Y, 2)
dc.SetPen(wx.Pen("cyan",1)) dc.SetPen(wx.Pen("cyan", 1))
dc.DrawLine(X1, Y1, X, Y) dc.DrawLine(X1, Y1, X, Y)
if list[i][AG.IN_TANGENT][AG.SELECT] == 0: if list[i][AG.IN_TANGENT][AG.SELECT] == 0:
X = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][0] X = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][0]
Y = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][1] Y = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][1]
dc.SetPen(wx.Pen("navy",3)) dc.SetPen(wx.Pen("navy", 3))
dc.SetBrush(wx.Brush("navy")) dc.SetBrush(wx.Brush("navy"))
dc.DrawCircle(X, Y, 2) dc.DrawCircle(X, Y, 2)
dc.SetPen(wx.Pen("navy",1)) dc.SetPen(wx.Pen("navy", 1))
dc.DrawLine(X1, Y1, X, Y) dc.DrawLine(X1, Y1, X, Y)
if list[i][AG.OUT_TANGENT][AG.SELECT] == 1: if list[i][AG.OUT_TANGENT][AG.SELECT] == 1:
X = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][0] X = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][0]
Y = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][1] Y = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][1]
dc.SetPen(wx.Pen("cyan",3)) dc.SetPen(wx.Pen("cyan", 3))
dc.SetBrush(wx.Brush("cyan")) dc.SetBrush(wx.Brush("cyan"))
dc.DrawCircle(X, Y, 2) dc.DrawCircle(X, Y, 2)
dc.SetPen(wx.Pen("cyan",1)) dc.SetPen(wx.Pen("cyan", 1))
dc.DrawLine(X1, Y1, X, Y) dc.DrawLine(X1, Y1, X, Y)
if list[i][AG.OUT_TANGENT][AG.SELECT] == 0: if list[i][AG.OUT_TANGENT][AG.SELECT] == 0:
X = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][0] X = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][0]
Y = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][1] Y = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][1]
dc.SetPen(wx.Pen("brown",3)) dc.SetPen(wx.Pen("brown", 3))
dc.SetBrush(wx.Brush("brown")) dc.SetBrush(wx.Brush("brown"))
dc.DrawCircle(X, Y, 2) dc.DrawCircle(X, Y, 2)
dc.SetPen(wx.Pen("brown",1)) dc.SetPen(wx.Pen("brown", 1))
dc.DrawLine(X1, Y1, X, Y) dc.DrawLine(X1, Y1, X, Y)
def DrawSelectRec(self, dc): def DrawSelectRec(self, dc):
@ -706,7 +707,7 @@ class GraphEditorWindow(wx.Window):
newPointX = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][0] + moveX newPointX = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][0] + moveX
newPointY = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][1] + moveY newPointY = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][1] + moveY
newSlope = [list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0] - newPointX , newPointY - list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1]] newSlope = [list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0] - newPointX, newPointY - list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1]]
temp0 = self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.INSLOPE][0] temp0 = self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.INSLOPE][0]
temp1 = self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.INSLOPE][1] temp1 = self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.INSLOPE][1]
@ -740,7 +741,7 @@ class GraphEditorWindow(wx.Window):
newPointX = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][0] + moveX newPointX = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][0] + moveX
newPointY = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][1] + moveY newPointY = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][1] + moveY
newSlope = [newPointX - list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0] , list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1] - newPointY] newSlope = [newPointX - list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0], list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1] - newPointY]
temp0 = self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.OUTSLOPE][0] temp0 = self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.OUTSLOPE][0]
temp1 = self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.OUTSLOPE][1] temp1 = self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.OUTSLOPE][1]
@ -785,6 +786,7 @@ class GraphEditorUI(wx.Dialog):
""" """
This is the graph editor main class implementation. This is the graph editor main class implementation.
""" """
def __init__(self, parent, editor, object): def __init__(self, parent, editor, object):
wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title="Graph Editor", wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title="Graph Editor",
pos=wx.DefaultPosition, size=(735, 535)) pos=wx.DefaultPosition, size=(735, 535))
@ -805,10 +807,10 @@ class GraphEditorUI(wx.Dialog):
bmpOneTangent = OneTangent.GetBitmap() bmpOneTangent = OneTangent.GetBitmap()
bmpTwoTangents = TwoTangents.GetBitmap() bmpTwoTangents = TwoTangents.GetBitmap()
self.buttonZoomIn = wx.BitmapButton(self.mainPanel1, -1, bmpZoomIn, size = (30,30),style = wx.BU_AUTODRAW) self.buttonZoomIn = wx.BitmapButton(self.mainPanel1, -1, bmpZoomIn, size = (30, 30),style = wx.BU_AUTODRAW)
self.buttonZoomOut = wx.BitmapButton(self.mainPanel1, -1, bmpZoomOut, size = (30,30),style = wx.BU_AUTODRAW) self.buttonZoomOut = wx.BitmapButton(self.mainPanel1, -1, bmpZoomOut, size = (30, 30),style = wx.BU_AUTODRAW)
self.buttonOneTangent = wx.BitmapButton(self.mainPanel1, -1, bmpOneTangent, size = (30,30),style = wx.BU_AUTODRAW) self.buttonOneTangent = wx.BitmapButton(self.mainPanel1, -1, bmpOneTangent, size = (30, 30),style = wx.BU_AUTODRAW)
self.buttonTwoTangents = wx.BitmapButton(self.mainPanel1, -1, bmpTwoTangents, size = (30,30),style = wx.BU_AUTODRAW) self.buttonTwoTangents = wx.BitmapButton(self.mainPanel1, -1, bmpTwoTangents, size = (30, 30),style = wx.BU_AUTODRAW)
self.mainPanel2 = wx.Panel(self, -1) self.mainPanel2 = wx.Panel(self, -1)

View File

@ -16,7 +16,7 @@ class LayerEditorUI(wx.Panel):
self.layersDataDict = dict() self.layersDataDict = dict()
self.layersDataDictNextKey = 0 self.layersDataDictNextKey = 0
self.systemLayerKeys = [] self.systemLayerKeys = []
self.llist = wx.ListCtrl(self, -1, style=wx.LC_REPORT|wx.LC_EDIT_LABELS|wx.LC_NO_HEADER) self.llist = wx.ListCtrl(self, -1, style=wx.LC_REPORT | wx.LC_EDIT_LABELS | wx.LC_NO_HEADER)
self.llist.InsertColumn(0, "Layers") self.llist.InsertColumn(0, "Layers")
sizer = wx.BoxSizer(wx.VERTICAL) sizer = wx.BoxSizer(wx.VERTICAL)
@ -170,7 +170,7 @@ class LayerEditorUI(wx.Panel):
def removeObj(self): def removeObj(self):
objNodePath = base.direct.selected.last objNodePath = base.direct.selected.last
if objNodePath is None: if objNodePath is None:
wx.MessageBox("No object was selected.", self.editorTxt, wx.OK|wx.ICON_EXCLAMATION) wx.MessageBox("No object was selected.", self.editorTxt, wx.OK | wx.ICON_EXCLAMATION)
return return
obj = self.editor.objectMgr.findObjectByNodePath(objNodePath) obj = self.editor.objectMgr.findObjectByNodePath(objNodePath)
if obj is not None: if obj is not None:
@ -179,11 +179,11 @@ class LayerEditorUI(wx.Panel):
def addObj(self): def addObj(self):
index = self.llist.GetFirstSelected() index = self.llist.GetFirstSelected()
if index == -1: if index == -1:
wx.MessageBox("No layer was selected.", self.editorTxt, wx.OK|wx.ICON_EXCLAMATION) wx.MessageBox("No layer was selected.", self.editorTxt, wx.OK | wx.ICON_EXCLAMATION)
return return
objNodePath = base.direct.selected.last objNodePath = base.direct.selected.last
if objNodePath is None: if objNodePath is None:
wx.MessageBox("No object was selected.", self.editorTxt, wx.OK|wx.ICON_EXCLAMATION) wx.MessageBox("No object was selected.", self.editorTxt, wx.OK | wx.ICON_EXCLAMATION)
return return
# Checking if the object was laready added to the layer # Checking if the object was laready added to the layer
@ -193,7 +193,7 @@ class LayerEditorUI(wx.Panel):
layersData = self.layersDataDict[i] layersData = self.layersDataDict[i]
for j in range(len(layersData)): for j in range(len(layersData)):
if layersData[j] == obj[OG.OBJ_UID]: if layersData[j] == obj[OG.OBJ_UID]:
wx.MessageBox("Selected object already is this layer", self.editorTxt, wx.OK|wx.ICON_EXCLAMATION) wx.MessageBox("Selected object already is this layer", self.editorTxt, wx.OK | wx.ICON_EXCLAMATION)
return return
# Looking for the object in the other layers # Looking for the object in the other layers
# If the object is found - delete it. # If the object is found - delete it.
@ -220,7 +220,7 @@ class LayerEditorUI(wx.Panel):
def HideObj(self, hide): def HideObj(self, hide):
index = self.llist.GetFirstSelected() index = self.llist.GetFirstSelected()
if index == -1: if index == -1:
wx.MessageBox("No layer was selected.", self.editorTxt, wx.OK|wx.ICON_EXCLAMATION) wx.MessageBox("No layer was selected.", self.editorTxt, wx.OK | wx.ICON_EXCLAMATION)
return return
key = self.llist.GetItemData(index) key = self.llist.GetItemData(index)

View File

@ -28,6 +28,7 @@ from .MayaConverter import FROM_BAM_TO_MAYA, MayaConverter
class LevelEditorBase(DirectObject): class LevelEditorBase(DirectObject):
""" Base Class for Panda3D LevelEditor """ """ Base Class for Panda3D LevelEditor """
def __init__(self): def __init__(self):
#loadPrcFileData('startup', 'window-type none') #loadPrcFileData('startup', 'window-type none')
self.currentFile = None self.currentFile = None
@ -86,7 +87,7 @@ class LevelEditorBase(DirectObject):
('DIRECT-mouse3', self.handleMouse3), ('DIRECT-mouse3', self.handleMouse3),
('DIRECT-mouse3Up', self.handleMouse3Up), ('DIRECT-mouse3Up', self.handleMouse3Up),
('DIRECT-toggleWidgetVis', self.toggleWidget), ('DIRECT-toggleWidgetVis', self.toggleWidget),
]) ])
# Add all the action events # Add all the action events
for event in self.actionEvents: for event in self.actionEvents:
@ -143,14 +144,12 @@ class LevelEditorBase(DirectObject):
if base.direct.fAlt or modifiers == 4: if base.direct.fAlt or modifiers == 4:
self.fMoveCamera = True self.fMoveCamera = True
return return
if self.mode == self.CREATE_CURVE_MODE : if self.mode == self.CREATE_CURVE_MODE:
self.curveEditor.createCurve() self.curveEditor.createCurve()
def handleMouse1Up(self): def handleMouse1Up(self):
self.fMoveCamera = False self.fMoveCamera = False
def handleMouse2(self, modifiers): def handleMouse2(self, modifiers):
if base.direct.fAlt or modifiers == 4: if base.direct.fAlt or modifiers == 4:
self.fMoveCamera = True self.fMoveCamera = True

View File

@ -21,6 +21,7 @@ from .AnimControlUI import AnimControlUI
from .CurveAnimUI import CurveAnimUI from .CurveAnimUI import CurveAnimUI
from .GraphEditorUI import GraphEditorUI from .GraphEditorUI import GraphEditorUI
class PandaTextDropTarget(wx.TextDropTarget): class PandaTextDropTarget(wx.TextDropTarget):
def __init__(self, editor, view): def __init__(self, editor, view):
wx.TextDropTarget.__init__(self) wx.TextDropTarget.__init__(self)
@ -104,6 +105,7 @@ class PandaTextDropTarget(wx.TextDropTarget):
iRay.collisionNodePath.removeNode() iRay.collisionNodePath.removeNode()
del iRay del iRay
ID_NEW = 101 ID_NEW = 101
ID_OPEN = 102 ID_OPEN = 102
ID_SAVE = 103 ID_SAVE = 103
@ -129,32 +131,34 @@ ID_CURVE_ANIM = 603
ID_ANIM = 701 ID_ANIM = 701
ID_GRAPH = 702 ID_GRAPH = 702
class LevelEditorUIBase(WxPandaShell): class LevelEditorUIBase(WxPandaShell):
""" Class for Panda3D LevelEditor """ """ Class for Panda3D LevelEditor """
def __init__(self, editor): def __init__(self, editor):
self.MENU_TEXTS.update({ self.MENU_TEXTS.update({
ID_NEW : ("&New", "LE-NewScene"), ID_NEW: ("&New", "LE-NewScene"),
ID_OPEN : ("&Open", "LE-OpenScene"), ID_OPEN: ("&Open", "LE-OpenScene"),
ID_SAVE : ("&Save", "LE-SaveScene"), ID_SAVE: ("&Save", "LE-SaveScene"),
ID_SAVE_AS : ("Save &As", None), ID_SAVE_AS: ("Save &As", None),
ID_EXPORT_TO_MAYA : ("Export to Maya", None), ID_EXPORT_TO_MAYA: ("Export to Maya", None),
wx.ID_EXIT : ("&Quit", "LE-Quit"), wx.ID_EXIT: ("&Quit", "LE-Quit"),
ID_DUPLICATE : ("&Duplicate", "LE-Duplicate"), ID_DUPLICATE: ("&Duplicate", "LE-Duplicate"),
ID_MAKE_LIVE : ("Make &Live", "LE-MakeLive"), ID_MAKE_LIVE: ("Make &Live", "LE-MakeLive"),
ID_UNDO : ("&Undo", "LE-Undo"), ID_UNDO: ("&Undo", "LE-Undo"),
ID_REDO : ("&Redo", "LE-Redo"), ID_REDO: ("&Redo", "LE-Redo"),
ID_SHOW_GRID : ("&Show Grid", None), ID_SHOW_GRID: ("&Show Grid", None),
ID_GRID_SIZE : ("&Grid Size", None), ID_GRID_SIZE: ("&Grid Size", None),
ID_GRID_SNAP : ("Grid S&nap", None), ID_GRID_SNAP: ("Grid S&nap", None),
ID_SHOW_PANDA_OBJECT : ("Show &Panda Objects", None), ID_SHOW_PANDA_OBJECT: ("Show &Panda Objects", None),
ID_HOT_KEYS : ("&Hot Keys", None), ID_HOT_KEYS: ("&Hot Keys", None),
ID_PARENT_TO_SELECTED : ("&Parent To Selected", None), ID_PARENT_TO_SELECTED: ("&Parent To Selected", None),
ID_CREATE_CURVE : ("&Create Curve", None), ID_CREATE_CURVE: ("&Create Curve", None),
ID_EDIT_CURVE : ("&Edit Curve", None), ID_EDIT_CURVE: ("&Edit Curve", None),
ID_CURVE_ANIM : ("&Curve Animation", None), ID_CURVE_ANIM: ("&Curve Animation", None),
ID_ANIM : ("&Edit Animation", None), ID_ANIM: ("&Edit Animation", None),
ID_GRAPH : ("&Graph Editor", None) ID_GRAPH: ("&Graph Editor", None)
}) })
self.editor = editor self.editor = editor
WxPandaShell.__init__(self, fStartDirect=True) WxPandaShell.__init__(self, fStartDirect=True)
@ -245,9 +249,9 @@ class LevelEditorUIBase(WxPandaShell):
WxPandaShell.createMenu(self) WxPandaShell.createMenu(self)
def onGraphEditor(self,e): def onGraphEditor(self, e):
if base.direct.selected.last is None: if base.direct.selected.last is None:
dlg = wx.MessageDialog(None, 'Please select a object first.', 'NOTICE', wx.OK ) dlg = wx.MessageDialog(None, 'Please select a object first.', 'NOTICE', wx.OK)
dlg.ShowModal() dlg.ShowModal()
dlg.Destroy() dlg.Destroy()
self.graphEditorMenuItem.Check(False) self.graphEditorMenuItem.Check(False)
@ -257,7 +261,7 @@ class LevelEditorUIBase(WxPandaShell):
self.graphEditorUI.Show() self.graphEditorUI.Show()
self.graphEditorMenuItem.Check(True) self.graphEditorMenuItem.Check(True)
def onAnimation(self,e): def onAnimation(self, e):
if self.editor.mode != self.editor.ANIM_MODE: if self.editor.mode != self.editor.ANIM_MODE:
self.animUI = AnimControlUI(self, self.editor) self.animUI = AnimControlUI(self, self.editor)
self.animUI.Show() self.animUI.Show()
@ -265,12 +269,12 @@ class LevelEditorUIBase(WxPandaShell):
if self.editor.mode == self.editor.ANIM_MODE: if self.editor.mode == self.editor.ANIM_MODE:
self.editAnimMenuItem.Check(True) self.editAnimMenuItem.Check(True)
def onCurveAnim(self,e): def onCurveAnim(self, e):
self.curveAnimUI = CurveAnimUI(self, self.editor) self.curveAnimUI = CurveAnimUI(self, self.editor)
self.curveAnimUI.Show() self.curveAnimUI.Show()
self.curveAnimMenuItem.Check(True) self.curveAnimMenuItem.Check(True)
def onCreateCurve(self,e): def onCreateCurve(self, e):
"""Function to invoke curve creating, need to check previous mode""" """Function to invoke curve creating, need to check previous mode"""
if self.editor.mode == self.editor.CREATE_CURVE_MODE: if self.editor.mode == self.editor.CREATE_CURVE_MODE:
self.createCurveMenuItem.Check(False) self.createCurveMenuItem.Check(False)
@ -284,7 +288,7 @@ class LevelEditorUIBase(WxPandaShell):
else: else:
self.currentView = self.getCurrentView() self.currentView = self.getCurrentView()
if self.currentView is None: if self.currentView is None:
dlg = wx.MessageDialog(None, 'Please select a viewport first.Do not support curve creation under four viewports.', 'NOTICE', wx.OK ) dlg = wx.MessageDialog(None, 'Please select a viewport first.Do not support curve creation under four viewports.', 'NOTICE', wx.OK)
dlg.ShowModal() dlg.ShowModal()
dlg.Destroy() dlg.Destroy()
self.createCurveMenuItem.Check(False) self.createCurveMenuItem.Check(False)
@ -297,7 +301,7 @@ class LevelEditorUIBase(WxPandaShell):
base.direct.manipulationControl.disableManipulation() base.direct.manipulationControl.disableManipulation()
self.editCurveMenuItem.Check(False) self.editCurveMenuItem.Check(False)
def onEditCurve(self,e): def onEditCurve(self, e):
"""Function to invoke curve editing and translate global information to local information. Need to check previous mode""" """Function to invoke curve editing and translate global information to local information. Need to check previous mode"""
if self.editor.mode == self.editor.EDIT_CURVE_MODE: if self.editor.mode == self.editor.EDIT_CURVE_MODE:
self.editCurveMenuItem.Check(False) self.editCurveMenuItem.Check(False)
@ -310,11 +314,11 @@ class LevelEditorUIBase(WxPandaShell):
self.onEditCurve(None) self.onEditCurve(None)
else: else:
if base.direct.selected.last is None: if base.direct.selected.last is None:
dlg = wx.MessageDialog(None, 'Please select a curve first.', 'NOTICE', wx.OK ) dlg = wx.MessageDialog(None, 'Please select a curve first.', 'NOTICE', wx.OK)
dlg.ShowModal() dlg.ShowModal()
dlg.Destroy() dlg.Destroy()
self.editCurveMenuItem.Check(False) self.editCurveMenuItem.Check(False)
if base.direct.selected.last is not None : if base.direct.selected.last is not None:
base.direct.manipulationControl.enableManipulation() base.direct.manipulationControl.enableManipulation()
self.createCurveMenuItem.Check(False) self.createCurveMenuItem.Check(False)
self.curveObj = self.editor.objectMgr.findObjectByNodePath(base.direct.selected.last) self.curveObj = self.editor.objectMgr.findObjectByNodePath(base.direct.selected.last)
@ -328,7 +332,7 @@ class LevelEditorUIBase(WxPandaShell):
item[1].show() item[1].show()
self.editor.curveEditor.curve.append((None, item[1].getPos())) self.editor.curveEditor.curve.append((None, item[1].getPos()))
else: else:
dlg = wx.MessageDialog(None, 'Please select a curve first.', 'NOTICE', wx.OK ) dlg = wx.MessageDialog(None, 'Please select a curve first.', 'NOTICE', wx.OK)
dlg.ShowModal() dlg.ShowModal()
dlg.Destroy() dlg.Destroy()
self.editCurveMenuItem.Check(False) self.editCurveMenuItem.Check(False)
@ -603,6 +607,7 @@ class LevelEditorUIBase(WxPandaShell):
else: else:
self.editor.objectMgr.replaceObjectWithTypeName(currObj, targetType) self.editor.objectMgr.replaceObjectWithTypeName(currObj, targetType)
class GridSizeUI(wx.Dialog): class GridSizeUI(wx.Dialog):
def __init__(self, parent, id, title, gridSize, gridSpacing): def __init__(self, parent, id, title, gridSize, gridSpacing):
wx.Dialog.__init__(self, parent, id, title, size=(250, 240)) wx.Dialog.__init__(self, parent, id, title, size=(250, 240))
@ -640,8 +645,10 @@ class GridSizeUI(wx.Dialog):
base.le.ui.bindKeyEvents(True) base.le.ui.bindKeyEvents(True)
self.Destroy() self.Destroy()
class ViewportMenu(wx.Menu): class ViewportMenu(wx.Menu):
"""Represents a menu that appears when right-clicking a viewport.""" """Represents a menu that appears when right-clicking a viewport."""
def __init__(self): def __init__(self):
wx.Menu.__init__(self) wx.Menu.__init__(self)
@ -664,6 +671,7 @@ class ViewportMenu(wx.Menu):
parent.AppendMenu(id, name, subMenu) parent.AppendMenu(id, name, subMenu)
return subMenu return subMenu
class CurveDegreeUI(wx.Dialog): class CurveDegreeUI(wx.Dialog):
def __init__(self, parent, id, title): def __init__(self, parent, id, title):
wx.Dialog.__init__(self, parent, id, title, size=(150, 120)) wx.Dialog.__init__(self, parent, id, title, size=(150, 120))

View File

@ -1,5 +1,6 @@
import imp import imp
class LevelLoaderBase: class LevelLoaderBase:
""" """
Base calss for LevelLoader Base calss for LevelLoader
@ -7,6 +8,7 @@ class LevelLoaderBase:
which you will use to load level editor data in your game. which you will use to load level editor data in your game.
Refer LevelLoader.py for example. Refer LevelLoader.py for example.
""" """
def __init__(self): def __init__(self):
self.defaultPath = None # this should be set in your LevelLoader.py self.defaultPath = None # this should be set in your LevelLoader.py
self.initLoader() self.initLoader()
@ -32,6 +34,6 @@ class LevelLoaderBase:
try: try:
module = imp.load_module(fileName, file, pathname, description) module = imp.load_module(fileName, file, pathname, description)
return True return True
except: except Exception:
print('failed to load %s'%fileName) print('failed to load %s'%fileName)
return None return None

View File

@ -18,7 +18,8 @@ from . import ObjectGlobals as OG
# python wrapper around a panda.NodePath object # python wrapper around a panda.NodePath object
class PythonNodePath(NodePath): class PythonNodePath(NodePath):
def __init__(self,node): def __init__(self,node):
NodePath.__init__(self,node) NodePath.__init__(self, node)
class ObjectMgrBase: class ObjectMgrBase:
""" ObjectMgr will create, manage, update objects in the scene """ """ ObjectMgr will create, manage, update objects in the scene """
@ -89,21 +90,21 @@ class ObjectMgrBase:
for item in curveInfo: for item in curveInfo:
controler = base.render.attachNewNode("controler") controler = base.render.attachNewNode("controler")
controler = base.loader.loadModel('models/misc/smiley') controler = base.loader.loadModel('models/misc/smiley')
controlerPathname = 'controler%d' % item[0] controlerPathname = f'controler{item[0]}'
controler.setName(controlerPathname) controler.setName(controlerPathname)
controler.setPos(item[1]) controler.setPos(item[1])
controler.setColor(0, 0, 0, 1) controler.setColor(0, 0, 0, 1)
controler.setScale(0.2) controler.setScale(0.2)
controler.reparentTo(base.render) controler.reparentTo(base.render)
controler.setTag('OBJRoot','1') controler.setTag('OBJRoot', '1')
controler.setTag('Controller','1') controler.setTag('Controller', '1')
curve.append((None, item[1])) curve.append((None, item[1]))
curveControl.append((item[0], controler)) curveControl.append((item[0], controler))
self.editor.curveEditor.degree = degree self.editor.curveEditor.degree = degree
self.editor.curveEditor.ropeUpdate (curve) self.editor.curveEditor.ropeUpdate(curve)
#add new curve to the scene #add new curve to the scene
curveObjNP = self.addNewCurve(curveControl, degree, uid, parent, fSelectObject, nodePath = self.editor.curveEditor.currentRope) curveObjNP = self.addNewCurve(curveControl, degree, uid, parent, fSelectObject, nodePath=self.editor.curveEditor.currentRope)
curveObj = self.findObjectByNodePath(curveObjNP) curveObj = self.findObjectByNodePath(curveObjNP)
self.editor.objectMgr.updateObjectPropValue(curveObj, 'Degree', degree, fSelectObject=False, fUndo=False) self.editor.objectMgr.updateObjectPropValue(curveObj, 'Degree', degree, fSelectObject=False, fUndo=False)
@ -136,7 +137,7 @@ class ObjectMgrBase:
newobj = nodePath newobj = nodePath
newobj.reparentTo(parent) newobj.reparentTo(parent)
newobj.setTag('OBJRoot','1') newobj.setTag('OBJRoot', '1')
# populate obj data using default values # populate obj data using default values
properties = {} properties = {}
@ -254,7 +255,7 @@ class ObjectMgrBase:
return None return None
newobj.reparentTo(parent) newobj.reparentTo(parent)
newobj.setTag('OBJRoot','1') newobj.setTag('OBJRoot', '1')
# populate obj data using default values # populate obj data using default values
properties = {} properties = {}
@ -276,11 +277,11 @@ class ObjectMgrBase:
obj = self.findObjectById(uid) obj = self.findObjectById(uid)
nodePath = obj[OG.OBJ_NP] nodePath = obj[OG.OBJ_NP]
for i in range(0,len(self.Actor)): for i in range(0, len(self.Actor)):
if self.Actor[i] == obj: if self.Actor[i] == obj:
del self.Actor[i] del self.Actor[i]
break break
for i in range(0,len(self.Nodes)): for i in range(0, len(self.Nodes)):
if self.Nodes[i][OG.OBJ_UID] == uid: if self.Nodes[i][OG.OBJ_UID] == uid:
del self.Nodes[i] del self.Nodes[i]
break break
@ -300,11 +301,11 @@ class ObjectMgrBase:
def removeObjectByNodePath(self, nodePath): def removeObjectByNodePath(self, nodePath):
uid = self.npIndex.get(nodePath) uid = self.npIndex.get(nodePath)
if uid: if uid:
for i in range(0,len(self.Actor)): for i in range(0, len(self.Actor)):
if self.Actor[i][OG.OBJ_UID] == uid: if self.Actor[i][OG.OBJ_UID] == uid:
del self.Actor[i] del self.Actor[i]
break break
for i in range(0,len(self.Nodes)): for i in range(0, len(self.Nodes)):
if self.Nodes[i][OG.OBJ_UID] == uid: if self.Nodes[i][OG.OBJ_UID] == uid:
del self.Nodes[i] del self.Nodes[i]
break break
@ -520,7 +521,7 @@ class ObjectMgrBase:
return return
self.flatten(newobjModel, model, objDef, uid) self.flatten(newobjModel, model, objDef, uid)
newobj = PythonNodePath(newobjModel) newobj = PythonNodePath(newobjModel)
newobj.setTag('OBJRoot','1') newobj.setTag('OBJRoot', '1')
# reparent children # reparent children
objNP.findAllMatches("=OBJRoot").reparentTo(newobj) objNP.findAllMatches("=OBJRoot").reparentTo(newobj)
@ -921,7 +922,6 @@ class ObjectMgrBase:
self.findActors(child) self.findActors(child)
def findNodes(self, parent): def findNodes(self, parent):
for child in parent.getChildren(): for child in parent.getChildren():
if child.hasTag('OBJRoot') and not child.hasTag('Controller'): if child.hasTag('OBJRoot') and not child.hasTag('Controller'):

View File

@ -17,6 +17,7 @@ and in the populate function you can define ObjectPalette tree structure.
from . import ObjectGlobals as OG from . import ObjectGlobals as OG
from .ObjectPaletteBase import ObjectBase, ObjectPaletteBase from .ObjectPaletteBase import ObjectBase, ObjectPaletteBase
class ObjectProp(ObjectBase): class ObjectProp(ObjectBase):
def __init__(self, *args, **kw): def __init__(self, *args, **kw):
ObjectBase.__init__(self, *args, **kw) ObjectBase.__init__(self, *args, **kw)
@ -84,7 +85,7 @@ class ObjectPalette(ObjectPaletteBase):
('.updateSmiley', ('.updateSmiley',
{'val':OG.ARG_VAL, 'obj':OG.ARG_OBJ}), {'val':OG.ARG_VAL, 'obj':OG.ARG_OBJ}),
1, [1, 10]], 1, [1, 10]],
}), }),
'Prop') # This object type will be added under the 'Prop' group. 'Prop') # This object type will be added under the 'Prop' group.
self.add(ObjectDoubleSmileys(name='H Double Smiley', self.add(ObjectDoubleSmileys(name='H Double Smiley',
createFunction = ('.createDoubleSmiley', {})), createFunction = ('.createDoubleSmiley', {})),

View File

@ -4,14 +4,19 @@ from . import ObjectGlobals as OG
class ObjectGen: class ObjectGen:
""" Base class for obj definitions """ """ Base class for obj definitions """
def __init__(self, name=''): def __init__(self, name=''):
self.name = name self.name = name
class ObjectBase(ObjectGen): class ObjectBase(ObjectGen):
""" Base class for obj definitions """ """ Base class for obj definitions """
def __init__(self, name='', createFunction = None, model = None, models= [], anims = [], animNames = [], animDict = {}, properties={},
movable = True, actor = False, named=False, updateModelFunction = None, orderedProperties=[], propertiesMask={}): def __init__(self, name='', createFunction=None, model=None, models=[],
anims=[], animNames=[], animDict={}, properties={},
movable=True, actor=False, named=False,
updateModelFunction=None, orderedProperties=[],
propertiesMask={}):
ObjectGen.__init__(self, name) ObjectGen.__init__(self, name)
self.createFunction = createFunction self.createFunction = createFunction
self.model = model self.model = model
@ -33,11 +38,14 @@ class ObjectBase(ObjectGen):
class ObjectCurve(ObjectBase): class ObjectCurve(ObjectBase):
def __init__(self, *args, **kw): def __init__(self, *args, **kw):
ObjectBase.__init__(self, *args, **kw) ObjectBase.__init__(self, *args, **kw)
self.properties['Degree'] =[OG.PROP_UI_COMBO, # UI type self.properties['Degree'] = [
OG.PROP_INT, # data type OG.PROP_UI_COMBO, # UI type
('base.le.objectMgr.updateCurve', {'val':OG.ARG_VAL, 'obj':OG.ARG_OBJ}), # update function OG.PROP_INT, # data type
3, # default value ('base.le.objectMgr.updateCurve', {'val': OG.ARG_VAL, 'obj': OG.ARG_OBJ}), # update function
[2, 3, 4]] # value range 3, # default value
[2, 3, 4], # value range
]
class ObjectPaletteBase: class ObjectPaletteBase:
""" """
@ -72,9 +80,9 @@ class ObjectPaletteBase:
self.data[item.name] = item self.data[item.name] = item
self.dataKeys.append(item.name) self.dataKeys.append(item.name)
def add(self, item, parentName = None): def add(self, item, parentName=None):
if isinstance(item, str): if isinstance(item, str):
self.insertItem(ObjectGen(name = item), parentName) self.insertItem(ObjectGen(name=item), parentName)
else: else:
self.insertItem(item, parentName) self.insertItem(item, parentName)
@ -91,9 +99,8 @@ class ObjectPaletteBase:
if node is not None: if node is not None:
deleteItems[key] = node deleteItems[key] = node
return item return item
except: except Exception:
return None return None
return None
def delete(self, name): def delete(self, name):
try: try:
@ -103,14 +110,13 @@ class ObjectPaletteBase:
deleteItems[name] = node deleteItems[name] = node
for key in list(deleteItems.keys()): for key in list(deleteItems.keys()):
item = self.dataStruct.pop(key) item = self.dataStruct.pop(key)
except: except Exception:
return return
return
def findItem(self, name): def findItem(self, name):
try: try:
item = self.data[name] item = self.data[name]
except: except Exception:
return None return None
return item return item
@ -137,7 +143,7 @@ class ObjectPaletteBase:
item = self.data.pop(oldName) item = self.data.pop(oldName)
item.name = newName item.name = newName
self.data[newName] = item self.data[newName] = item
except: except Exception:
return False return False
return True return True

View File

@ -24,6 +24,7 @@ Key = PyEmbeddedImage(
"EMaYtpbOXlu01vf5Hz/wDRuDdIDl5WtQAAAAAElFTkSuQmCC") "EMaYtpbOXlu01vf5Hz/wDRuDdIDl5WtQAAAAAElFTkSuQmCC")
#---------------------------------------------------------------------- #----------------------------------------------------------------------
class AnimFileDrop(wx.FileDropTarget): class AnimFileDrop(wx.FileDropTarget):
def __init__(self, editor): def __init__(self, editor):
wx.FileDropTarget.__init__(self) wx.FileDropTarget.__init__(self)
@ -56,11 +57,13 @@ class AnimFileDrop(wx.FileDropTarget):
obj[OG.OBJ_ANIM] = animName obj[OG.OBJ_ANIM] = animName
self.editor.ui.objectPropertyUI.updateProps(obj) self.editor.ui.objectPropertyUI.updateProps(obj)
class ObjectPropUI(wx.Panel): class ObjectPropUI(wx.Panel):
""" """
Base class for ObjectPropUIs, Base class for ObjectPropUIs,
It consists of label area and ui area. It consists of label area and ui area.
""" """
def __init__(self, parent, label): def __init__(self, parent, label):
wx.Panel.__init__(self, parent) wx.Panel.__init__(self, parent)
self.parent = parent self.parent = parent
@ -80,24 +83,22 @@ class ObjectPropUI(wx.Panel):
self.setKeyButton.Bind(wx.EVT_BUTTON, self.onKey) self.setKeyButton.Bind(wx.EVT_BUTTON, self.onKey)
def onKey(self,evt): def onKey(self, evt):
self.parent = wx.GetTopLevelParent(self) self.parent = wx.GetTopLevelParent(self)
if self.parent.editor.mode == self.parent.editor.ANIM_MODE: if self.parent.editor.mode == self.parent.editor.ANIM_MODE:
obj= self.parent.editor.objectMgr.findObjectByNodePath(base.direct.selected.last) obj = self.parent.editor.objectMgr.findObjectByNodePath(base.direct.selected.last)
objUID = obj[OG.OBJ_UID]
propertyName = self.label.GetLabelText()
value = self.getValue() value = self.getValue()
frame = self.parent.editor.ui.animUI.curFrame frame = self.parent.editor.ui.animUI.curFrame
if (objUID, propertyName) in self.parent.editor.animMgr.keyFramesInfo: if property in self.parent.editor.animMgr.keyFramesInfo:
for i in range(len(self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)])): for i in range(len(self.parent.editor.animMgr.keyFramesInfo[property])):
if self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)][i][AG.FRAME] == frame: if self.parent.editor.animMgr.keyFramesInfo[property][i][AG.FRAME] == frame:
del self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)][i] del self.parent.editor.animMgr.keyFramesInfo[property][i]
self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)].append([frame, value, [], []])
self.parent.editor.animMgr.keyFramesInfo[property].append([frame, value, [], []])
#sort keyFrameInfo list by the order of frame number #sort keyFrameInfo list by the order of frame number
sortKeyList = self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)] sortKeyList = self.parent.editor.animMgr.keyFramesInfo[property]
for i in range(0, len(sortKeyList)-1): for i in range(0, len(sortKeyList)-1):
for j in range(i+1, len(sortKeyList)): for j in range(i+1, len(sortKeyList)):
if sortKeyList[i][AG.FRAME]>sortKeyList[j][AG.FRAME]: if sortKeyList[i][AG.FRAME]>sortKeyList[j][AG.FRAME]:
@ -105,9 +106,9 @@ class ObjectPropUI(wx.Panel):
sortKeyList[i] = sortKeyList[j] sortKeyList[i] = sortKeyList[j]
sortKeyList[j] = temp sortKeyList[j] = temp
self.parent.editor.animMgr.generateSlope(self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)]) self.parent.editor.animMgr.generateSlope(self.parent.editor.animMgr.keyFramesInfo[property])
else: else:
self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)] = [[frame, value, [], []]] self.parent.editor.animMgr.keyFramesInfo[property] = [[frame, value, [], []]]
exist = False exist = False
for keyFrame in self.parent.editor.animMgr.keyFrames: for keyFrame in self.parent.editor.animMgr.keyFrames:
@ -133,8 +134,10 @@ class ObjectPropUI(wx.Panel):
if valFunc: if valFunc:
self.ui.Bind(self.eventType, valFunc) self.ui.Bind(self.eventType, valFunc)
class ObjectPropUIEntry(ObjectPropUI): class ObjectPropUIEntry(ObjectPropUI):
""" UI for string value properties """ """ UI for string value properties """
def __init__(self, parent, label): def __init__(self, parent, label):
ObjectPropUI.__init__(self, parent, label) ObjectPropUI.__init__(self, parent, label)
self.ui = wx.TextCtrl(self.uiPane, -1) self.ui = wx.TextCtrl(self.uiPane, -1)
@ -144,8 +147,10 @@ class ObjectPropUIEntry(ObjectPropUI):
def setValue(self, value): def setValue(self, value):
self.ui.SetValue(str(value)) self.ui.SetValue(str(value))
class ObjectPropUISlider(ObjectPropUI): class ObjectPropUISlider(ObjectPropUI):
""" UI for float value properties """ """ UI for float value properties """
def __init__(self, parent, label, value, minValue, maxValue): def __init__(self, parent, label, value, minValue, maxValue):
ObjectPropUI.__init__(self, parent, label) ObjectPropUI.__init__(self, parent, label)
self.ui = WxSlider(self.uiPane, -1, value, minValue, maxValue, self.ui = WxSlider(self.uiPane, -1, value, minValue, maxValue,
@ -166,6 +171,7 @@ class ObjectPropUISlider(ObjectPropUI):
class ObjectPropUISpinner(ObjectPropUI): class ObjectPropUISpinner(ObjectPropUI):
""" UI for int value properties """ """ UI for int value properties """
def __init__(self, parent, label, value, minValue, maxValue): def __init__(self, parent, label, value, minValue, maxValue):
ObjectPropUI.__init__(self, parent, label) ObjectPropUI.__init__(self, parent, label)
self.ui = wx.SpinCtrl(self.uiPane, -1, "", min=minValue, max=maxValue, initial=value) self.ui = wx.SpinCtrl(self.uiPane, -1, "", min=minValue, max=maxValue, initial=value)
@ -218,6 +224,7 @@ class ObjectPropUICombo(ObjectPropUI):
def setItems(self, valueList): def setItems(self, valueList):
self.ui.SetItems(valueList) self.ui.SetItems(valueList)
class ObjectPropUITime(wx.Panel): class ObjectPropUITime(wx.Panel):
def __init__(self, parent, label, value): def __init__(self, parent, label, value):
wx.Panel.__init__(self, parent) wx.Panel.__init__(self, parent)
@ -288,9 +295,11 @@ class ObjectPropUITime(wx.Panel):
self.uiHour.Bind(self.eventType, valFunc) self.uiHour.Bind(self.eventType, valFunc)
self.uiMin.Bind(self.eventType, valFunc) self.uiMin.Bind(self.eventType, valFunc)
class ColorPicker(CubeColourDialog): class ColorPicker(CubeColourDialog):
def __init__(self, parent, colourData=None, style=CCD_SHOW_ALPHA, alpha = 255, updateCB=None, exitCB=None): def __init__(self, parent, colourData=None, style=CCD_SHOW_ALPHA,
self.updateCB=updateCB alpha=255, updateCB=None, exitCB=None):
self.updateCB = updateCB
CubeColourDialog.__init__(self, parent, colourData, style) CubeColourDialog.__init__(self, parent, colourData, style)
self.okButton.Hide() self.okButton.Hide()
self.cancelButton.Hide() self.cancelButton.Hide()
@ -306,6 +315,7 @@ class ColorPicker(CubeColourDialog):
if self.updateCB: if self.updateCB:
self.updateCB(self._colour.r, self._colour.g, self._colour.b, self._colour.alpha) self.updateCB(self._colour.r, self._colour.g, self._colour.b, self._colour.alpha)
class ObjectPropertyUI(ScrolledPanel): class ObjectPropertyUI(ScrolledPanel):
def __init__(self, parent, editor): def __init__(self, parent, editor):
self.editor = editor self.editor = editor
@ -329,7 +339,7 @@ class ObjectPropertyUI(ScrolledPanel):
self.propPane.Destroy() self.propPane.Destroy()
self.SetSizer(None) self.SetSizer(None)
self.Layout() self.Layout()
self.SetupScrolling(self, scroll_y = True, rate_y = 20) self.SetupScrolling(self, scroll_y=True, rate_y=20)
def colorPickerExitCB(self, evt=None): def colorPickerExitCB(self, evt=None):
self.lastColorPickerPos = self.colorPicker.GetPosition() self.lastColorPickerPos = self.colorPicker.GetPosition()
@ -414,8 +424,11 @@ class ObjectPropertyUI(ScrolledPanel):
self.propSY = ObjectPropUIEntry(self.transformPane, 'SY') self.propSY = ObjectPropUIEntry(self.transformPane, 'SY')
self.propSZ = ObjectPropUIEntry(self.transformPane, 'SZ') self.propSZ = ObjectPropUIEntry(self.transformPane, 'SZ')
transformProps = [self.propX, self.propY, self.propZ, self.propH, self.propP, self.propR, transformProps = [
self.propSX, self.propSY, self.propSZ] self.propX, self.propY, self.propZ,
self.propH, self.propP, self.propR,
self.propSX, self.propSY, self.propSZ,
]
sizer = wx.BoxSizer(wx.VERTICAL) sizer = wx.BoxSizer(wx.VERTICAL)
sizer.AddMany(transformProps) sizer.AddMany(transformProps)
@ -635,7 +648,6 @@ class ObjectPropertyUI(ScrolledPanel):
self.editor.objectMgr.onLeaveObjectPropUI, self.editor.objectMgr.onLeaveObjectPropUI,
lambda p0=None, p1=obj, p2=key: self.editor.objectMgr.updateObjectProperty(p0, p1, p2)) lambda p0=None, p1=obj, p2=key: self.editor.objectMgr.updateObjectProperty(p0, p1, p2))
self.propsPane.SetSizer(sizer) self.propsPane.SetSizer(sizer)
self.Layout() self.Layout()
self.SetupScrolling(self, scroll_y = True, rate_y = 20) self.SetupScrolling(self, scroll_y = True, rate_y = 20)

View File

@ -9,7 +9,7 @@ class ProtoObjs:
def __init__(self, name): def __init__(self, name):
self.dirname = os.path.dirname(__file__) self.dirname = os.path.dirname(__file__)
self.name = name self.name = name
self.filename = "/%s.py" % (name) self.filename = f"/{name}.py"
self.data = {} self.data = {}
def populate(self): def populate(self):
@ -18,16 +18,16 @@ class ProtoObjs:
file, pathname, description = imp.find_module(moduleName, [self.dirname]) file, pathname, description = imp.find_module(moduleName, [self.dirname])
module = imp.load_module(moduleName, file, pathname, description) module = imp.load_module(moduleName, file, pathname, description)
self.data = module.protoData self.data = module.protoData
except: except Exception:
print("%s doesn't exist"%(self.name)) print(f"{self.name} doesn't exist")
return return
def saveProtoData(self, f): def saveProtoData(self, f):
if not f: if not f:
return return
for key in self.data.keys(): for key, value in self.data.items():
f.write("\t'%s':'%s',\n"%(key, self.data[key])) f.write(f"\t'{key}':'{value}',\n")
def saveToFile(self): def saveToFile(self):
try: try:
@ -36,5 +36,5 @@ class ProtoObjs:
self.saveProtoData(f) self.saveProtoData(f)
f.write("}\n") f.write("}\n")
f.close() f.close()
except: except Exception:
pass pass

View File

@ -7,6 +7,7 @@ from .ActionMgr import ActionChangeHierarchy, ActionDeleteObjById
from . import ObjectGlobals as OG from . import ObjectGlobals as OG
class SceneGraphUIDropTarget(wx.TextDropTarget): class SceneGraphUIDropTarget(wx.TextDropTarget):
def __init__(self, editor): def __init__(self, editor):
print("in SceneGraphUIDropTarget::init...") print("in SceneGraphUIDropTarget::init...")
@ -17,6 +18,7 @@ class SceneGraphUIDropTarget(wx.TextDropTarget):
print("in SceneGraphUIDropTarget::OnDropText...") print("in SceneGraphUIDropTarget::OnDropText...")
self.editor.ui.sceneGraphUI.changeHierarchy(text, x, y) self.editor.ui.sceneGraphUI.changeHierarchy(text, x, y)
class SceneGraphUIBase(wx.Panel): class SceneGraphUIBase(wx.Panel):
def __init__(self, parent, editor): def __init__(self, parent, editor):
wx.Panel.__init__(self, parent) wx.Panel.__init__(self, parent)
@ -121,7 +123,7 @@ class SceneGraphUIBase(wx.Panel):
if obj is None: if obj is None:
return return
if parentNP is None : if parentNP is None:
parentNP = obj[OG.OBJ_NP].getParent() parentNP = obj[OG.OBJ_NP].getParent()
parentObj = self.editor.objectMgr.findObjectByNodePath(parentNP) parentObj = self.editor.objectMgr.findObjectByNodePath(parentNP)

View File

@ -68,5 +68,5 @@ if objects['1252623762.9gjeon']:
if hasattr(base, 'le'): if hasattr(base, 'le'):
ui.layerEditorUI.reset() ui.layerEditorUI.reset()
ui.layerEditorUI.addLayerEntry('Layer1', 1 ) ui.layerEditorUI.addLayerEntry('Layer1', 1)
ui.layerEditorUI.addLayerData(1, '1252538687.73gjeon') ui.layerEditorUI.addLayerData(1, '1252538687.73gjeon')

View File

@ -229,7 +229,7 @@ class MotionTrail(NodePath, DirectObject):
index = 0 index = 0
while index < total_motion_trails: while index < total_motion_trails:
motion_trail = MotionTrail.motion_trail_list [index] motion_trail = MotionTrail.motion_trail_list[index]
if MotionTrail.global_enable: if MotionTrail.global_enable:
if motion_trail.use_python_version: if motion_trail.use_python_version:
@ -577,7 +577,7 @@ class MotionTrail(NodePath, DirectObject):
v0 = start_transform.xform(motion_trail_vertex_start.vertex) v0 = start_transform.xform(motion_trail_vertex_start.vertex)
v2 = end_transform.xform(motion_trail_vertex_start.vertex) v2 = end_transform.xform(motion_trail_vertex_start.vertex)
nurbs_curve_evaluator = nurbs_curve_evaluator_list [vertex_segment_index] nurbs_curve_evaluator = nurbs_curve_evaluator_list[vertex_segment_index]
nurbs_curve_evaluator.setVertex(segment_index, v0) nurbs_curve_evaluator.setVertex(segment_index, v0)
@ -589,7 +589,7 @@ class MotionTrail(NodePath, DirectObject):
v1 = start_transform.xform(motion_trail_vertex_end.vertex) v1 = start_transform.xform(motion_trail_vertex_end.vertex)
v3 = end_transform.xform(motion_trail_vertex_end.vertex) v3 = end_transform.xform(motion_trail_vertex_end.vertex)
nurbs_curve_evaluator = nurbs_curve_evaluator_list [vertex_segment_index + 1] nurbs_curve_evaluator = nurbs_curve_evaluator_list[vertex_segment_index + 1]
nurbs_curve_evaluator.setVertex(segment_index, v1) nurbs_curve_evaluator.setVertex(segment_index, v1)
@ -607,7 +607,7 @@ class MotionTrail(NodePath, DirectObject):
index = 0 index = 0
nurbs_curve_result_list = [] nurbs_curve_result_list = []
while index < self.total_vertices: while index < self.total_vertices:
nurbs_curve_evaluator = nurbs_curve_evaluator_list [index] nurbs_curve_evaluator = nurbs_curve_evaluator_list[index]
nurbs_curve_result = nurbs_curve_evaluator.evaluate() nurbs_curve_result = nurbs_curve_evaluator.evaluate()
nurbs_curve_result_list = nurbs_curve_result_list + [nurbs_curve_result] nurbs_curve_result_list = nurbs_curve_result_list + [nurbs_curve_result]
@ -665,8 +665,8 @@ class MotionTrail(NodePath, DirectObject):
motion_trail_vertex_start = self.vertex_list[vertex_segment_index] motion_trail_vertex_start = self.vertex_list[vertex_segment_index]
motion_trail_vertex_end = self.vertex_list[vertex_segment_index + 1] motion_trail_vertex_end = self.vertex_list[vertex_segment_index + 1]
start_nurbs_curve_result = nurbs_curve_result_list [vertex_segment_index] start_nurbs_curve_result = nurbs_curve_result_list[vertex_segment_index]
end_nurbs_curve_result = nurbs_curve_result_list [vertex_segment_index + 1] end_nurbs_curve_result = nurbs_curve_result_list[vertex_segment_index + 1]
start_nurbs_start_t = start_nurbs_curve_result.getStartT() start_nurbs_start_t = start_nurbs_curve_result.getStartT()
start_nurbs_end_t = start_nurbs_curve_result.getEndT() start_nurbs_end_t = start_nurbs_curve_result.getEndT()

View File

@ -214,7 +214,7 @@ class ParticleEffect(NodePath):
data = vfs.readFile(fn, True) data = vfs.readFile(fn, True)
data = data.replace(b'\r', b'') data = data.replace(b'\r', b'')
exec(data) exec(data)
except: except Exception:
self.notify.warning('loadConfig: failed to load particle file: '+ repr(filename)) self.notify.warning('loadConfig: failed to load particle file: '+ repr(filename))
raise raise

View File

@ -89,7 +89,7 @@ class BufferViewer(DirectObject):
if not self.isValidTextureSet(elt): if not self.isValidTextureSet(elt):
return 0 return 0
else: else:
return (x=="all") or (isinstance(x, Texture)) or (isinstance(x, GraphicsOutput)) return x == "all" or isinstance(x, Texture) or isinstance(x, GraphicsOutput)
def isEnabled(self): def isEnabled(self):
"""Returns true if the buffer viewer is currently enabled.""" """Returns true if the buffer viewer is currently enabled."""
@ -237,8 +237,8 @@ class BufferViewer(DirectObject):
self.analyzeTextureSet(win, set) self.analyzeTextureSet(win, set)
elif x == "all": elif x == "all":
self.analyzeTextureSet(self.engine, set) self.analyzeTextureSet(self.engine, set)
else: return else:
return
def makeFrame(self, sizex, sizey): def makeFrame(self, sizex, sizey):
"""Access: private. Each texture card is displayed with """Access: private. Each texture card is displayed with
@ -271,14 +271,14 @@ class BufferViewer(DirectObject):
triangles = GeomTriangles(Geom.UHStatic) triangles = GeomTriangles(Geom.UHStatic)
for i in range(2): for i in range(2):
delta = i*8 delta = i*8
triangles.addVertices(0+delta, 4+delta, 1+delta) triangles.addVertices(0 + delta, 4 + delta, 1 + delta)
triangles.addVertices(1+delta, 4+delta, 5+delta) triangles.addVertices(1 + delta, 4 + delta, 5 + delta)
triangles.addVertices(1+delta, 5+delta, 2+delta) triangles.addVertices(1 + delta, 5 + delta, 2 + delta)
triangles.addVertices(2+delta, 5+delta, 6+delta) triangles.addVertices(2 + delta, 5 + delta, 6 + delta)
triangles.addVertices(2+delta, 6+delta, 3+delta) triangles.addVertices(2 + delta, 6 + delta, 3 + delta)
triangles.addVertices(3+delta, 6+delta, 7+delta) triangles.addVertices(3 + delta, 6 + delta, 7 + delta)
triangles.addVertices(3+delta, 7+delta, 0+delta) triangles.addVertices(3 + delta, 7 + delta, 0 + delta)
triangles.addVertices(0+delta, 7+delta, 4+delta) triangles.addVertices(0 + delta, 7 + delta, 4 + delta)
triangles.closePrimitive() triangles.closePrimitive()
geom = Geom(vdata) geom = Geom(vdata)
@ -287,7 +287,6 @@ class BufferViewer(DirectObject):
geomnode.addGeom(geom) geomnode.addGeom(geom)
return NodePath(geomnode) return NodePath(geomnode)
def maintainReadout(self, task): def maintainReadout(self, task):
"""Access: private. Whenever necessary, rebuilds the entire """Access: private. Whenever necessary, rebuilds the entire
display from scratch. This is only done when the configuration display from scratch. This is only done when the configuration
@ -408,24 +407,24 @@ class BufferViewer(DirectObject):
bordersize = 4.0 bordersize = 4.0
if (float(self.sizex)==0.0) and (float(self.sizey)==0.0): if float(self.sizex) == 0.0 and float(self.sizey) == 0.0:
sizey = int(0.4266666667 * self.win.getYSize()) sizey = int(0.4266666667 * self.win.getYSize())
sizex = (sizey * aspectx) // aspecty sizex = (sizey * aspectx) // aspecty
v_sizey = (self.win.getYSize() - (rows-1) - (rows*2)) // rows v_sizey = (self.win.getYSize() - (rows - 1) - (rows * 2)) // rows
v_sizex = (v_sizey * aspectx) // aspecty v_sizex = (v_sizey * aspectx) // aspecty
if (v_sizey < sizey) or (v_sizex < sizex): if (v_sizey < sizey) or (v_sizex < sizex):
sizey = v_sizey sizey = v_sizey
sizex = v_sizex sizex = v_sizex
adjustment = 2 adjustment = 2
h_sizex = float (self.win.getXSize() - adjustment) / float (cols) h_sizex = float(self.win.getXSize() - adjustment) / float(cols)
h_sizex -= bordersize h_sizex -= bordersize
if h_sizex < 1.0: if h_sizex < 1.0:
h_sizex = 1.0 h_sizex = 1.0
h_sizey = (h_sizex * aspecty) // aspectx h_sizey = (h_sizex * aspecty) // aspectx
if (h_sizey < sizey) or (h_sizex < sizex): if h_sizey < sizey or h_sizex < sizex:
sizey = h_sizey sizey = h_sizey
sizex = h_sizex sizex = h_sizex
else: else:
@ -466,7 +465,7 @@ class BufferViewer(DirectObject):
for r in range(rows): for r in range(rows):
for c in range(cols): for c in range(cols):
index = c + r*cols index = c + r * cols
if index < ncards: if index < ncards:
index = (index + self.cardindex) % len(cards) index = (index + self.cardindex) % len(cards)
@ -474,7 +473,7 @@ class BufferViewer(DirectObject):
posy = diry * (1.0 - ((r + 0.5) * (fsizey + fpixely * bordersize))) - (fpixely * diry) posy = diry * (1.0 - ((r + 0.5) * (fsizey + fpixely * bordersize))) - (fpixely * diry)
placer = NodePath("card-structure") placer = NodePath("card-structure")
placer.setPos(Point3.rfu(posx, 0, posy)) placer.setPos(Point3.rfu(posx, 0, posy))
placer.setScale(Vec3.rfu(fsizex*0.5, 1.0, fsizey*0.5)) placer.setScale(Vec3.rfu(fsizex * 0.5, 1.0, fsizey * 0.5))
placer.setBin(self.cullbin, self.cullsort) placer.setBin(self.cullbin, self.cullsort)
placer.reparentTo(self.renderParent) placer.reparentTo(self.renderParent)
frame.instanceTo(placer) frame.instanceTo(placer)

View File

@ -33,6 +33,7 @@ def _createContainerLeak():
# use tuples as keys since they can't be weakref'd, and use an instance # use tuples as keys since they can't be weakref'd, and use an instance
# since it can't be repr/eval'd # since it can't be repr/eval'd
# that will force the leak detector to hold a normal 'non-weak' reference # that will force the leak detector to hold a normal 'non-weak' reference
class LeakKey: class LeakKey:
pass pass
base.leakContainer[(LeakKey(),)] = {} base.leakContainer[(LeakKey(),)] = {}
@ -47,13 +48,17 @@ def _createContainerLeak():
return task.done return task.done
leakContainer() leakContainer()
def _createTaskLeak(): def _createTaskLeak():
leakTaskName = uniqueName('leakedTask') leakTaskName = uniqueName('leakedTask')
leakDoLaterName = uniqueName('leakedDoLater') leakDoLaterName = uniqueName('leakedDoLater')
def nullTask(task=None): def nullTask(task=None):
return task.cont return task.cont
def nullDoLater(task=None): def nullDoLater(task=None):
return task.done return task.done
def leakTask(task=None, leakTaskName=leakTaskName): def leakTask(task=None, leakTaskName=leakTaskName):
base = getBase() base = getBase()
taskMgr.add(nullTask, uniqueName(leakTaskName)) taskMgr.add(nullTask, uniqueName(leakTaskName))
@ -63,9 +68,11 @@ def _createTaskLeak():
return task.done return task.done
leakTask() leakTask()
class NoDictKey: class NoDictKey:
pass pass
class Indirection: class Indirection:
""" """
Represents the indirection that brings you from a container to an element of the container. Represents the indirection that brings you from a container to an element of the container.
@ -75,6 +82,7 @@ class Indirection:
TODO: store string components that are duplicates of strings in the actual system so that TODO: store string components that are duplicates of strings in the actual system so that
Python will keep one copy and reduce memory usage Python will keep one copy and reduce memory usage
""" """
def __init__(self, evalStr=None, dictKey=NoDictKey): def __init__(self, evalStr=None, dictKey=NoDictKey):
# if this is a dictionary lookup, pass dictKey instead of evalStr # if this is a dictionary lookup, pass dictKey instead of evalStr
self.evalStr = evalStr self.evalStr = evalStr
@ -89,7 +97,7 @@ class Indirection:
try: try:
keyEval = eval(keyRepr) keyEval = eval(keyRepr)
useEval = True useEval = True
except: except Exception:
pass pass
if useEval: if useEval:
# check to make sure the eval succeeded # check to make sure the eval succeeded
@ -114,6 +122,7 @@ class Indirection:
def acquire(self): def acquire(self):
self._refCount += 1 self._refCount += 1
def release(self): def release(self):
self._refCount -= 1 self._refCount -= 1
if self._refCount == 0: if self._refCount == 0:
@ -164,6 +173,7 @@ class Indirection:
def __repr__(self): def __repr__(self):
return self.getString() return self.getString()
class ObjectRef: class ObjectRef:
""" """
stores a reference to a container in a way that does not prevent garbage stores a reference to a container in a way that does not prevent garbage
@ -346,10 +356,12 @@ class ObjectRef:
pass pass
return result return result
class FindContainers(Job): class FindContainers(Job):
""" """
Explore the Python graph, looking for objects that support __len__() Explore the Python graph, looking for objects that support __len__()
""" """
def __init__(self, name, leakDetector): def __init__(self, name, leakDetector):
Job.__init__(self, name) Job.__init__(self, name)
self._leakDetector = leakDetector self._leakDetector = leakDetector
@ -382,7 +394,7 @@ class FindContainers(Job):
pass pass
try: try:
base base
except: except Exception:
pass pass
else: else:
ref = ObjectRef(Indirection(evalStr='base.__dict__'), id(base.__dict__)) ref = ObjectRef(Indirection(evalStr='base.__dict__'), id(base.__dict__))
@ -391,7 +403,7 @@ class FindContainers(Job):
pass pass
try: try:
simbase simbase
except: except Exception:
pass pass
else: else:
ref = ObjectRef(Indirection(evalStr='simbase.__dict__'), id(simbase.__dict__)) ref = ObjectRef(Indirection(evalStr='simbase.__dict__'), id(simbase.__dict__))
@ -411,7 +423,7 @@ class FindContainers(Job):
# how good of a starting object is this object for traversing the object graph? # how good of a starting object is this object for traversing the object graph?
try: try:
return len(startObj) return len(startObj)
except: except Exception:
return 1 return 1
def _isDeadEnd(self, obj, objName=None): def _isDeadEnd(self, obj, objName=None):
@ -426,7 +438,7 @@ class FindContainers(Job):
return True return True
try: try:
className = obj.__class__.__name__ className = obj.__class__.__name__
except: except Exception:
pass pass
else: else:
# prevent infinite recursion in built-in containers related to methods # prevent infinite recursion in built-in containers related to methods
@ -512,9 +524,9 @@ class FindContainers(Job):
# make a generator that yields containers a # of times that is # make a generator that yields containers a # of times that is
# proportional to their length # proportional to their length
for fw in makeFlywheelGen( for fw in makeFlywheelGen(
list(startRefWorkingList.source.values()), list(startRefWorkingList.source.values()),
countFunc=lambda x: self.getStartObjAffinity(x), countFunc=lambda x: self.getStartObjAffinity(x),
scale=.05): scale=.05):
yield None yield None
startRefWorkingList.refGen = fw startRefWorkingList.refGen = fw
if curObjRef is None: if curObjRef is None:
@ -529,7 +541,7 @@ class FindContainers(Job):
try: try:
for containerRef in self._leakDetector.getContainerByIdGen(startId): for containerRef in self._leakDetector.getContainerByIdGen(startId):
yield None yield None
except: except Exception:
# ref is invalid # ref is invalid
self.notify.debug('invalid startRef, stored as id %s' % startId) self.notify.debug('invalid startRef, stored as id %s' % startId)
self._leakDetector.removeContainerById(startId) self._leakDetector.removeContainerById(startId)
@ -539,7 +551,7 @@ class FindContainers(Job):
try: try:
for curObj in curObjRef.getContainerGen(): for curObj in curObjRef.getContainerGen():
yield None yield None
except: except Exception:
self.notify.debug('lost current container, ref.getContainerGen() failed') self.notify.debug('lost current container, ref.getContainerGen() failed')
# that container is gone, try again # that container is gone, try again
curObjRef = None curObjRef = None
@ -642,6 +654,7 @@ class FindContainers(Job):
raise raise
yield Job.Done yield Job.Done
class CheckContainers(Job): class CheckContainers(Job):
""" """
Job to check container sizes and find potential leaks; sub-job of ContainerLeakDetector Job to check container sizes and find potential leaks; sub-job of ContainerLeakDetector
@ -724,7 +737,7 @@ class CheckContainers(Job):
try: try:
for container in self._leakDetector.getContainerByIdGen(objId): for container in self._leakDetector.getContainerByIdGen(objId):
yield None yield None
except: except Exception:
# TODO # TODO
self.notify.debug('caught exception in getContainerByIdGen (1)') self.notify.debug('caught exception in getContainerByIdGen (1)')
else: else:
@ -745,7 +758,7 @@ class CheckContainers(Job):
try: try:
for container in self._leakDetector.getContainerByIdGen(objId): for container in self._leakDetector.getContainerByIdGen(objId):
yield None yield None
except: except Exception:
# TODO # TODO
self.notify.debug('caught exception in getContainerByIdGen (2)') self.notify.debug('caught exception in getContainerByIdGen (2)')
else: else:
@ -766,7 +779,7 @@ class CheckContainers(Job):
try: try:
for container in self._leakDetector.getContainerByIdGen(objId): for container in self._leakDetector.getContainerByIdGen(objId):
yield None yield None
except: except Exception:
# TODO # TODO
self.notify.debug('caught exception in getContainerByIdGen (3)') self.notify.debug('caught exception in getContainerByIdGen (3)')
else: else:
@ -786,6 +799,7 @@ class CheckContainers(Job):
raise raise
yield Job.Done yield Job.Done
class FPTObjsOfType(Job): class FPTObjsOfType(Job):
def __init__(self, name, leakDetector, otn, doneCallback=None): def __init__(self, name, leakDetector, otn, doneCallback=None):
Job.__init__(self, name) Job.__init__(self, name)
@ -818,9 +832,9 @@ class FPTObjsOfType(Job):
yield None yield None
try: try:
for container in self._leakDetector.getContainerByIdGen( for container in self._leakDetector.getContainerByIdGen(
id, getInstance=getInstance): id, getInstance=getInstance):
yield None yield None
except: except Exception:
pass pass
else: else:
if hasattr(container, '__class__'): if hasattr(container, '__class__'):
@ -830,9 +844,9 @@ class FPTObjsOfType(Job):
if self._otn.lower() in cName.lower(): if self._otn.lower() in cName.lower():
try: try:
for ptc in self._leakDetector.getContainerNameByIdGen( for ptc in self._leakDetector.getContainerNameByIdGen(
id, getInstance=getInstance): id, getInstance=getInstance):
yield None yield None
except: except Exception:
pass pass
else: else:
print('GPTC(' + self._otn + '):' + self.getJobName() + ': ' + ptc) print('GPTC(' + self._otn + '):' + self.getJobName() + ': ' + ptc)
@ -846,6 +860,7 @@ class FPTObjsOfType(Job):
if self._doneCallback: if self._doneCallback:
self._doneCallback(self) self._doneCallback(self)
class FPTObjsNamed(Job): class FPTObjsNamed(Job):
def __init__(self, name, leakDetector, on, doneCallback=None): def __init__(self, name, leakDetector, on, doneCallback=None):
Job.__init__(self, name) Job.__init__(self, name)
@ -878,7 +893,7 @@ class FPTObjsNamed(Job):
try: try:
for container in self._leakDetector.getContainerByIdGen(id): for container in self._leakDetector.getContainerByIdGen(id):
yield None yield None
except: except Exception:
pass pass
else: else:
name = self._leakDetector._id2ref[id].getFinalIndirectionStr() name = self._leakDetector._id2ref[id].getFinalIndirectionStr()
@ -886,7 +901,7 @@ class FPTObjsNamed(Job):
try: try:
for ptc in self._leakDetector.getContainerNameByIdGen(id): for ptc in self._leakDetector.getContainerNameByIdGen(id):
yield None yield None
except: except Exception:
pass pass
else: else:
print('GPTCN(' + self._on + '):' + self.getJobName() + ': ' + ptc) print('GPTCN(' + self._on + '):' + self.getJobName() + ': ' + ptc)
@ -900,11 +915,13 @@ class FPTObjsNamed(Job):
if self._doneCallback: if self._doneCallback:
self._doneCallback(self) self._doneCallback(self)
class PruneObjectRefs(Job): class PruneObjectRefs(Job):
""" """
Job to destroy any container refs that are no longer valid. Job to destroy any container refs that are no longer valid.
Checks validity by asking for each container Checks validity by asking for each container
""" """
def __init__(self, name, leakDetector): def __init__(self, name, leakDetector):
Job.__init__(self, name) Job.__init__(self, name)
self._leakDetector = leakDetector self._leakDetector = leakDetector
@ -926,7 +943,7 @@ class PruneObjectRefs(Job):
try: try:
for container in self._leakDetector.getContainerByIdGen(id): for container in self._leakDetector.getContainerByIdGen(id):
yield None yield None
except: except Exception:
# reference is invalid, remove it # reference is invalid, remove it
self._leakDetector.removeContainerById(id) self._leakDetector.removeContainerById(id)
_id2baseStartRef = self._leakDetector._findContainersJob._id2baseStartRef _id2baseStartRef = self._leakDetector._findContainersJob._id2baseStartRef
@ -936,7 +953,7 @@ class PruneObjectRefs(Job):
try: try:
for container in _id2baseStartRef[id].getContainerGen(): for container in _id2baseStartRef[id].getContainerGen():
yield None yield None
except: except Exception:
# reference is invalid, remove it # reference is invalid, remove it
del _id2baseStartRef[id] del _id2baseStartRef[id]
_id2discoveredStartRef = self._leakDetector._findContainersJob._id2discoveredStartRef _id2discoveredStartRef = self._leakDetector._findContainersJob._id2discoveredStartRef
@ -946,7 +963,7 @@ class PruneObjectRefs(Job):
try: try:
for container in _id2discoveredStartRef[id].getContainerGen(): for container in _id2discoveredStartRef[id].getContainerGen():
yield None yield None
except: except Exception:
# reference is invalid, remove it # reference is invalid, remove it
del _id2discoveredStartRef[id] del _id2discoveredStartRef[id]
except Exception as e: except Exception as e:
@ -955,6 +972,7 @@ class PruneObjectRefs(Job):
raise raise
yield Job.Done yield Job.Done
class ContainerLeakDetector(Job): class ContainerLeakDetector(Job):
""" """
Low-priority Python object-graph walker that looks for leaking containers. Low-priority Python object-graph walker that looks for leaking containers.
@ -1028,12 +1046,14 @@ class ContainerLeakDetector(Job):
@classmethod @classmethod
def addPrivateObj(cls, obj): def addPrivateObj(cls, obj):
cls.PrivateIds.add(id(obj)) cls.PrivateIds.add(id(obj))
@classmethod @classmethod
def removePrivateObj(cls, obj): def removePrivateObj(cls, obj):
cls.PrivateIds.remove(id(obj)) cls.PrivateIds.remove(id(obj))
def _getCheckTaskName(self): def _getCheckTaskName(self):
return 'checkForLeakingContainers-%s' % self._serialNum return 'checkForLeakingContainers-%s' % self._serialNum
def _getPruneTaskName(self): def _getPruneTaskName(self):
return 'pruneLeakingContainerRefs-%s' % self._serialNum return 'pruneLeakingContainerRefs-%s' % self._serialNum
@ -1043,16 +1063,20 @@ class ContainerLeakDetector(Job):
def getContainerByIdGen(self, id, **kwArgs): def getContainerByIdGen(self, id, **kwArgs):
# return a generator to look up a container # return a generator to look up a container
return self._id2ref[id].getContainerGen(**kwArgs) return self._id2ref[id].getContainerGen(**kwArgs)
def getContainerById(self, id): def getContainerById(self, id):
for result in self._id2ref[id].getContainerGen(): for result in self._id2ref[id].getContainerGen():
pass pass
return result return result
def getContainerNameByIdGen(self, id, **kwArgs): def getContainerNameByIdGen(self, id, **kwArgs):
return self._id2ref[id].getEvalStrGen(**kwArgs) return self._id2ref[id].getEvalStrGen(**kwArgs)
def getContainerNameById(self, id): def getContainerNameById(self, id):
if id in self._id2ref: if id in self._id2ref:
return repr(self._id2ref[id]) return repr(self._id2ref[id])
return '<unknown container>' return '<unknown container>'
def removeContainerById(self, id): def removeContainerById(self, id):
if id in self._id2ref: if id in self._id2ref:
self._id2ref[id].destroy() self._id2ref[id].destroy()

View File

@ -53,22 +53,22 @@ class ContainerReport(Job):
id(self._type2id2len), id(self._type2id2len),
id(self._queue), id(self._queue),
id(self._instanceDictIds), id(self._instanceDictIds),
])) ]))
# push on a few things that we want to give priority # push on a few things that we want to give priority
# for the sake of the variable-name printouts # for the sake of the variable-name printouts
try: try:
base base
except: except NameError:
pass pass
else: else:
self._enqueueContainer( base.__dict__, self._enqueueContainer(base.__dict__,
'base') 'base')
try: try:
simbase simbase
except: except NameError:
pass pass
else: else:
self._enqueueContainer( simbase.__dict__, self._enqueueContainer(simbase.__dict__,
'simbase') 'simbase')
self._queue.push(__builtins__) self._queue.push(__builtins__)
self._id2pathStr[id(__builtins__)] = '' self._id2pathStr[id(__builtins__)] = ''
@ -86,7 +86,7 @@ class ContainerReport(Job):
try: try:
if parentObj.__class__.__name__ == 'method-wrapper': if parentObj.__class__.__name__ == 'method-wrapper':
continue continue
except: except Exception:
pass pass
if isinstance(parentObj, (str, bytes)): if isinstance(parentObj, (str, bytes)):
@ -142,7 +142,7 @@ class ContainerReport(Job):
if not isinstance(parentObj, io.TextIOWrapper): if not isinstance(parentObj, io.TextIOWrapper):
try: try:
itr = iter(parentObj) itr = iter(parentObj)
except: except Exception:
pass pass
else: else:
try: try:
@ -150,7 +150,7 @@ class ContainerReport(Job):
while 1: while 1:
try: try:
attr = next(itr) attr = next(itr)
except: except Exception:
# some custom classes don't do well when iterated # some custom classes don't do well when iterated
attr = None attr = None
break break
@ -168,7 +168,7 @@ class ContainerReport(Job):
try: try:
childNames = dir(parentObj) childNames = dir(parentObj)
except: except Exception:
pass pass
else: else:
childName = None childName = None
@ -176,7 +176,7 @@ class ContainerReport(Job):
for childName in childNames: for childName in childNames:
try: try:
child = getattr(parentObj, childName) child = getattr(parentObj, childName)
except: except Exception:
continue continue
if id(child) not in self._visitedIds: if id(child) not in self._visitedIds:
self._visitedIds.add(id(child)) self._visitedIds.add(id(child))
@ -206,12 +206,13 @@ class ContainerReport(Job):
# if it's a container, put it in the tables # if it's a container, put it in the tables
try: try:
length = len(obj) length = len(obj)
except: except Exception:
length = None length = None
if length is not None and length > 0: if length is not None and length > 0:
self._id2container[objId] = obj self._id2container[objId] = obj
self._type2id2len.setdefault(type(obj), {}) self._type2id2len.setdefault(type(obj), {})
self._type2id2len[type(obj)][objId] = length self._type2id2len[type(obj)][objId] = length
def _examine(self, obj): def _examine(self, obj):
# return False if it's an object that can't contain or lead to other objects # return False if it's an object that can't contain or lead to other objects
if type(obj) in deadEndTypes: if type(obj) in deadEndTypes:

View File

@ -260,6 +260,7 @@ class DistancePhasedNode(PhasedObject, DirectObject, NodePath):
self.cTrav.traverse(self) self.cTrav.traverse(self)
base.eventMgr.doEvents() base.eventMgr.doEvents()
class BufferedDistancePhasedNode(DistancePhasedNode): class BufferedDistancePhasedNode(DistancePhasedNode):
""" """
This class is similar to DistancePhasedNode except you can also This class is similar to DistancePhasedNode except you can also
@ -329,7 +330,7 @@ class BufferedDistancePhasedNode(DistancePhasedNode):
if __debug__ and 0: if __debug__ and 0:
cSphere = CollisionSphere(0,0,0,0.1) cSphere = CollisionSphere(0, 0, 0, 0.1)
cNode = CollisionNode('camCol') cNode = CollisionNode('camCol')
cNode.addSolid(cSphere) cNode.addSolid(cSphere)
cNodePath = NodePath(cNode) cNodePath = NodePath(cNode)
@ -344,11 +345,11 @@ if __debug__ and 0:
eventHandler.addOutPattern('exit%in') eventHandler.addOutPattern('exit%in')
# messenger.toggleVerbose() # messenger.toggleVerbose()
base.cTrav.addCollider(cNodePath,eventHandler) base.cTrav.addCollider(cNodePath, eventHandler)
p = BufferedDistancePhasedNode('p',{'At':(10,20),'Near':(100,200),'Far':(1000, 1020)}, p = BufferedDistancePhasedNode('p', {'At': (10, 20), 'Near': (100, 200), 'Far': (1000, 1020)},
autoCleanup = False, autoCleanup=False,
fromCollideNode = cNodePath, fromCollideNode=cNodePath,
) )
p.reparentTo(render) p.reparentTo(render)

View File

@ -10,6 +10,7 @@ notify = directNotify.newCategory("ExceptionVarDump")
reentry = 0 reentry = 0
def _varDump__init__(self, *args, **kArgs): def _varDump__init__(self, *args, **kArgs):
global reentry global reentry
if reentry > 0: if reentry > 0:
@ -30,8 +31,10 @@ def _varDump__init__(self, *args, **kArgs):
self._moved__init__(*args, **kArgs) self._moved__init__(*args, **kArgs)
reentry -= 1 reentry -= 1
sReentry = 0 sReentry = 0
def _varDump__print(exc): def _varDump__print(exc):
global sReentry global sReentry
global notify global notify
@ -60,6 +63,7 @@ def _varDump__print(exc):
notify.info(exc._savedExcString) notify.info(exc._savedExcString)
sReentry -= 1 sReentry -= 1
oldExcepthook = None oldExcepthook = None
# store these values here so that Task.py can always reliably access them # store these values here so that Task.py can always reliably access them
# from its main exception handler # from its main exception handler
@ -68,9 +72,11 @@ wantStackDumpUpload = False
variableDumpReasons = [] variableDumpReasons = []
dumpOnExceptionInit = False dumpOnExceptionInit = False
class _AttrNotFound: class _AttrNotFound:
pass pass
def _excepthookDumpVars(eType, eValue, tb): def _excepthookDumpVars(eType, eValue, tb):
origTb = tb origTb = tb
excStrs = traceback.format_exception(eType, eValue, origTb) excStrs = traceback.format_exception(eType, eValue, origTb)
@ -137,7 +143,7 @@ def _excepthookDumpVars(eType, eValue, tb):
# prevent infinite recursion on method wrappers (__init__.__init__.__init__...) # prevent infinite recursion on method wrappers (__init__.__init__.__init__...)
try: try:
className = attr.__class__.__name__ className = attr.__class__.__name__
except: except Exception:
pass pass
else: else:
if className == 'method-wrapper': if className == 'method-wrapper':
@ -168,16 +174,17 @@ def _excepthookDumpVars(eType, eValue, tb):
timeMgr = None timeMgr = None
try: try:
timeMgr = base.cr.timeManager timeMgr = base.cr.timeManager
except: except Exception:
try: try:
timeMgr = simbase.air.timeManager timeMgr = simbase.air.timeManager
except: except Exception:
pass pass
if timeMgr: if timeMgr:
timeMgr.setStackDump(s) timeMgr.setStackDump(s)
oldExcepthook(eType, eValue, origTb) oldExcepthook(eType, eValue, origTb)
def install(log, upload): def install(log, upload):
"""Installs the exception hook.""" """Installs the exception hook."""
global oldExcepthook global oldExcepthook

View File

@ -60,7 +60,7 @@ def rebindClass(filename):
res = findClass(className) res = findClass(className)
if not res: if not res:
print ('Warning: Finder could not find class') print('Warning: Finder could not find class')
# Remove the temp file we made # Remove the temp file we made
file.close() file.close()
os.remove(filename) os.remove(filename)
@ -87,7 +87,7 @@ def rebindClass(filename):
file.close() file.close()
os.remove(filename) os.remove(filename)
print (' Finished rebind') print(' Finished rebind')
def copyFuncs(fromClass, toClass): def copyFuncs(fromClass, toClass):
@ -148,25 +148,28 @@ def copyFuncs(fromClass, toClass):
# print "adding new func: ", oldFunc, funcName, newFunc # print "adding new func: ", oldFunc, funcName, newFunc
setattr(toClass, funcName, newFunc) setattr(toClass, funcName, newFunc)
def replaceMessengerFunc(replaceFuncList): def replaceMessengerFunc(replaceFuncList):
try: try:
messenger messenger
except: except Exception:
return return
for oldFunc, funcName, newFunc in replaceFuncList: for oldFunc, funcName, newFunc in replaceFuncList:
res = messenger.replaceMethod(oldFunc, newFunc) res = messenger.replaceMethod(oldFunc, newFunc)
if res: if res:
print('replaced %s messenger function(s): %s' % (res, funcName)) print('replaced %s messenger function(s): %s' % (res, funcName))
def replaceTaskMgrFunc(replaceFuncList): def replaceTaskMgrFunc(replaceFuncList):
try: try:
taskMgr taskMgr
except: except Exception:
return return
for oldFunc, funcName, newFunc in replaceFuncList: for oldFunc, funcName, newFunc in replaceFuncList:
if taskMgr.replaceMethod(oldFunc, newFunc): if taskMgr.replaceMethod(oldFunc, newFunc):
print('replaced taskMgr function: %s' % funcName) print('replaced taskMgr function: %s' % funcName)
def replaceStateFunc(replaceFuncList): def replaceStateFunc(replaceFuncList):
if not sys.modules.get('base.direct.fsm.State'): if not sys.modules.get('base.direct.fsm.State'):
return return
@ -176,28 +179,31 @@ def replaceStateFunc(replaceFuncList):
if res: if res:
print('replaced %s FSM transition function(s): %s' % (res, funcName)) print('replaced %s FSM transition function(s): %s' % (res, funcName))
def replaceCRFunc(replaceFuncList): def replaceCRFunc(replaceFuncList):
try: try:
base.cr base.cr
except: except Exception:
return return
# masad: Gyedo's fake cr causes a crash in followingreplaceMethod on rebinding, so # masad: Gyedo's fake cr causes a crash in followingreplaceMethod on rebinding, so
# I throw in the isFake check. I still think the fake cr should be eliminated. # I throw in the isFake check. I still think the fake cr should be eliminated.
if hasattr(base.cr,'isFake'): if hasattr(base.cr, 'isFake'):
return return
for oldFunc, funcName, newFunc in replaceFuncList: for oldFunc, funcName, newFunc in replaceFuncList:
if base.cr.replaceMethod(oldFunc, newFunc): if base.cr.replaceMethod(oldFunc, newFunc):
print('replaced DistributedObject function: %s' % funcName) print('replaced DistributedObject function: %s' % funcName)
def replaceAIRFunc(replaceFuncList): def replaceAIRFunc(replaceFuncList):
try: try:
simbase.air simbase.air
except: except Exception:
return return
for oldFunc, funcName, newFunc in replaceFuncList: for oldFunc, funcName, newFunc in replaceFuncList:
if simbase.air.replaceMethod(oldFunc, newFunc): if simbase.air.replaceMethod(oldFunc, newFunc):
print('replaced DistributedObject function: %s' % funcName) print('replaced DistributedObject function: %s' % funcName)
def replaceIvalFunc(replaceFuncList): def replaceIvalFunc(replaceFuncList):
# Make sure we have imported IntervalManager and thus created # Make sure we have imported IntervalManager and thus created
# a global ivalMgr. # a global ivalMgr.

View File

@ -17,10 +17,12 @@ GarbageCycleCountAnnounceEvent = 'announceGarbageCycleDesc2num'
class FakeObject: class FakeObject:
pass pass
class FakeDelObject: class FakeDelObject:
def __del__(self): def __del__(self):
pass pass
def _createGarbage(num=1): def _createGarbage(num=1):
for i in range(num): for i in range(num):
a = FakeObject() a = FakeObject()
@ -32,6 +34,7 @@ def _createGarbage(num=1):
a.other = b a.other = b
b.other = a b.other = a
class GarbageReport(Job): class GarbageReport(Job):
"""Detects leaked Python objects (via gc.collect()) and reports on garbage """Detects leaked Python objects (via gc.collect()) and reports on garbage
items, garbage-to-garbage references, and garbage cycles. items, garbage-to-garbage references, and garbage cycles.
@ -252,7 +255,7 @@ class GarbageReport(Job):
brackets = { brackets = {
tuple: '()', tuple: '()',
list: '[]', list: '[]',
}[type(obj)] }[type(obj)]
# get object being referenced by container # get object being referenced by container
nextObj = objs[index+1] nextObj = objs[index+1]
cycleBySyntax += brackets[0] cycleBySyntax += brackets[0]
@ -544,19 +547,23 @@ class GarbageReport(Job):
break break
yield cycles yield cycles
class GarbageLogger(GarbageReport): class GarbageLogger(GarbageReport):
"""If you just want to log the current garbage to the log file, make """If you just want to log the current garbage to the log file, make
one of these. It automatically destroys itself after logging""" one of these. It automatically destroys itself after logging"""
def __init__(self, name, *args, **kArgs): def __init__(self, name, *args, **kArgs):
kArgs['log'] = True kArgs['log'] = True
kArgs['autoDestroy'] = True kArgs['autoDestroy'] = True
GarbageReport.__init__(self, name, *args, **kArgs) GarbageReport.__init__(self, name, *args, **kArgs)
class _CFGLGlobals: class _CFGLGlobals:
# for checkForGarbageLeaks # for checkForGarbageLeaks
LastNumGarbage = 0 LastNumGarbage = 0
LastNumCycles = 0 LastNumCycles = 0
def checkForGarbageLeaks(): def checkForGarbageLeaks():
gc.collect() gc.collect()
numGarbage = len(gc.garbage) numGarbage = len(gc.garbage)
@ -577,6 +584,7 @@ def checkForGarbageLeaks():
func('%s garbage cycles found, see info above' % _CFGLGlobals.LastNumCycles) func('%s garbage cycles found, see info above' % _CFGLGlobals.LastNumCycles)
return numGarbage return numGarbage
def b_checkForGarbageLeaks(wantReply=False): def b_checkForGarbageLeaks(wantReply=False):
if not __dev__: if not __dev__:
return 0 return 0
@ -586,7 +594,7 @@ def b_checkForGarbageLeaks(wantReply=False):
try: try:
# if this is the client, tell the AI to check for leaks too # if this is the client, tell the AI to check for leaks too
base.cr.timeManager base.cr.timeManager
except: except Exception:
pass pass
else: else:
if base.cr.timeManager: if base.cr.timeManager:

View File

@ -122,11 +122,7 @@ class SceneGraphLeakDetector(LeakDetector):
LeakDetector.destroy(self) LeakDetector.destroy(self)
def __len__(self): def __len__(self):
try: return self._render.countNumDescendants()
# this will be available when the build server finishes
return self._render.countNumDescendants()
except:
return self._render.getNumDescendants()
def __repr__(self): def __repr__(self):
return 'SceneGraphLeakDetector(%s)' % self._render return 'SceneGraphLeakDetector(%s)' % self._render
@ -138,15 +134,7 @@ class SceneGraphLeakDetector(LeakDetector):
class CppMemoryUsage(LeakDetector): class CppMemoryUsage(LeakDetector):
def __len__(self): def __len__(self):
haveMemoryUsage = True return MemoryUsage.getCurrentCppSize()
try:
MemoryUsage
except:
haveMemoryUsage = False
if haveMemoryUsage:
return int(MemoryUsage.getCurrentCppSize())
else:
return 0
class TaskLeakDetectorBase: class TaskLeakDetectorBase:

View File

@ -480,8 +480,8 @@ class Loader(DirectObject):
i += 1 i += 1
return cb return cb
# font loading funcs # font loading funcs
def loadFont(self, modelPath, def loadFont(self, modelPath,
spaceAdvance = None, lineHeight = None, spaceAdvance = None, lineHeight = None,
pointSize = None, pointSize = None,
@ -926,7 +926,6 @@ class Loader(DirectObject):
return texture return texture
def unloadTexture(self, texture): def unloadTexture(self, texture):
""" """
Removes the previously-loaded texture from the cache, so Removes the previously-loaded texture from the cache, so
that when the last reference to it is gone, it will be that when the last reference to it is gone, it will be
@ -971,7 +970,6 @@ class Loader(DirectObject):
def loadSound(self, manager, soundPath, positional = False, def loadSound(self, manager, soundPath, positional = False,
callback = None, extraArgs = []): callback = None, extraArgs = []):
"""Loads one or more sound files, specifying the particular """Loads one or more sound files, specifying the particular
AudioManager that should be used to load them. The soundPath AudioManager that should be used to load them. The soundPath
may be either a single filename, or a list of filenames. If a may be either a single filename, or a list of filenames. If a
@ -1021,7 +1019,7 @@ class Loader(DirectObject):
def unloadSfx(self, sfx): def unloadSfx(self, sfx):
if sfx: if sfx:
if self.base.sfxManagerList: if self.base.sfxManagerList:
self.base.sfxManagerList[0].uncacheSound (sfx.getName()) self.base.sfxManagerList[0].uncacheSound(sfx.getName())
## def makeNodeNamesUnique(self, nodePath, nodeCount): ## def makeNodeNamesUnique(self, nodePath, nodeCount):
## if nodeCount == 0: ## if nodeCount == 0:
@ -1033,7 +1031,7 @@ class Loader(DirectObject):
## self.makeNodeNamesUnique(nodePath.getChild(i), nodeCount) ## self.makeNodeNamesUnique(nodePath.getChild(i), nodeCount)
def loadShader(self, shaderPath, okMissing = False): def loadShader(self, shaderPath, okMissing = False):
shader = ShaderPool.loadShader (shaderPath) shader = ShaderPool.loadShader(shaderPath)
if not shader and not okMissing: if not shader and not okMissing:
message = 'Could not load shader file: %s' % (shaderPath) message = 'Could not load shader file: %s' % (shaderPath)
raise IOError(message) raise IOError(message)

View File

@ -417,7 +417,7 @@ class Messenger:
# Release the lock temporarily while we call the method. # Release the lock temporarily while we call the method.
self.lock.release() self.lock.release()
try: try:
result = method (*(extraArgs + sentArgs)) result = method(*(extraArgs + sentArgs))
finally: finally:
self.lock.acquire() self.lock.acquire()

View File

@ -11,12 +11,15 @@ import builtins
class MessengerLeakObject(DirectObject): class MessengerLeakObject(DirectObject):
def __init__(self): def __init__(self):
self.accept('leakEvent', self._handleEvent) self.accept('leakEvent', self._handleEvent)
def _handleEvent(self): def _handleEvent(self):
pass pass
def _leakMessengerObject(): def _leakMessengerObject():
leakObject = MessengerLeakObject() leakObject = MessengerLeakObject()
class MessengerLeakDetector(Job): class MessengerLeakDetector(Job):
# check for objects that are only referenced by the messenger # check for objects that are only referenced by the messenger
# and would otherwise be garbage collected # and would otherwise be garbage collected
@ -37,19 +40,19 @@ class MessengerLeakDetector(Job):
builtinIds.add(id(base)) builtinIds.add(id(base))
builtinIds.add(id(base.cr)) builtinIds.add(id(base.cr))
builtinIds.add(id(base.cr.doId2do)) builtinIds.add(id(base.cr.doId2do))
except: except Exception:
pass pass
try: try:
builtinIds.add(id(simbase)) builtinIds.add(id(simbase))
builtinIds.add(id(simbase.air)) builtinIds.add(id(simbase.air))
builtinIds.add(id(simbase.air.doId2do)) builtinIds.add(id(simbase.air.doId2do))
except: except Exception:
pass pass
try: try:
builtinIds.add(id(uber)) builtinIds.add(id(uber))
builtinIds.add(id(uber.air)) builtinIds.add(id(uber.air))
builtinIds.add(id(uber.air.doId2do)) builtinIds.add(id(uber.air.doId2do))
except: except Exception:
pass pass
while True: while True:

View File

@ -43,7 +43,7 @@ class ObjectPool:
self._type2objs[typ].append(obj) self._type2objs[typ].append(obj)
try: try:
self._len2obj[len(obj)] = obj self._len2obj[len(obj)] = obj
except: except Exception:
pass pass
self._count2types = invertDictLossless(type2count) self._count2types = invertDictLossless(type2count)

View File

@ -34,7 +34,7 @@ class OnScreenDebug:
color = { color = {
"black": Vec4(0, 0, 0, 1), "black": Vec4(0, 0, 0, 1),
"white": Vec4(1, 1, 1, 1), "white": Vec4(1, 1, 1, 1),
} }
fgColor = color[ConfigVariableString("on-screen-debug-fg-color", "white").value] fgColor = color[ConfigVariableString("on-screen-debug-fg-color", "white").value]
bgColor = color[ConfigVariableString("on-screen-debug-bg-color", "black").value] bgColor = color[ConfigVariableString("on-screen-debug-bg-color", "black").value]
fgColor.setW(ConfigVariableDouble("on-screen-debug-fg-alpha", 0.85).value) fgColor.setW(ConfigVariableDouble("on-screen-debug-fg-alpha", 0.85).value)

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,7 @@ __all__ = ['randHash', 'RandomNumGen']
from direct.directnotify import DirectNotifyGlobal from direct.directnotify import DirectNotifyGlobal
from panda3d.core import Mersenne from panda3d.core import Mersenne
def randHash(num): def randHash(num):
""" this returns a random 16-bit integer, given a seed integer. """ this returns a random 16-bit integer, given a seed integer.
It will always return the same output given the same input. It will always return the same output given the same input.
@ -14,9 +15,9 @@ def randHash(num):
rng = RandomNumGen(num) rng = RandomNumGen(num)
return rng.randint(0, (1<<16) - 1) return rng.randint(0, (1<<16) - 1)
class RandomNumGen: class RandomNumGen:
notify = \ notify = DirectNotifyGlobal.directNotify.newCategory("RandomNumGen")
DirectNotifyGlobal.directNotify.newCategory("RandomNumGen")
def __init__(self, seed): def __init__(self, seed):
"""seed must be an integer or another RandomNumGen""" """seed must be an integer or another RandomNumGen"""

View File

@ -113,7 +113,7 @@ class ReferrerSearch(Job):
(isinstance(ref, dict) and \ (isinstance(ref, dict) and \
list(ref.keys()) == list(locals().keys())) or \ list(ref.keys()) == list(locals().keys())) or \
ref is self.__dict__ or \ ref is self.__dict__ or \
id(ref) in self.visited) ] id(ref) in self.visited)]
# Check to see if this object has an unusually large # Check to see if this object has an unusually large
# ref-count. This usually indicates that it is some # ref-count. This usually indicates that it is some
@ -162,7 +162,7 @@ class ReferrerSearch(Job):
# We found the reference on self # We found the reference on self
ref is self.__dict__ or \ ref is self.__dict__ or \
# We've already seen this referrer # We've already seen this referrer
id(ref) in self.visited) ] id(ref) in self.visited)]
# Check to see if this object has an unusually large # Check to see if this object has an unusually large
# ref-count. This usually indicates that it is some # ref-count. This usually indicates that it is some

View File

@ -146,6 +146,7 @@ if __debug__:
from . import OnScreenDebug from . import OnScreenDebug
import warnings import warnings
@atexit.register @atexit.register
def exitfunc(): def exitfunc():
if getattr(builtins, 'base', None) is not None: if getattr(builtins, 'base', None) is not None:
@ -154,6 +155,8 @@ def exitfunc():
# Now ShowBase is a DirectObject. We need this so ShowBase can hang # Now ShowBase is a DirectObject. We need this so ShowBase can hang
# hooks on messages, particularly on window-event. This doesn't # hooks on messages, particularly on window-event. This doesn't
# *seem* to cause anyone any problems. # *seem* to cause anyone any problems.
class ShowBase(DirectObject.DirectObject): class ShowBase(DirectObject.DirectObject):
#: The deprecated `.DConfig` interface for accessing config variables. #: The deprecated `.DConfig` interface for accessing config variables.
@ -610,6 +613,7 @@ class ShowBase(DirectObject.DirectObject):
def pushCTrav(self, cTrav): def pushCTrav(self, cTrav):
self.cTravStack.push(self.cTrav) self.cTravStack.push(self.cTrav)
self.cTrav = cTrav self.cTrav = cTrav
def popCTrav(self): def popCTrav(self):
self.cTrav = self.cTravStack.pop() self.cTrav = self.cTravStack.pop()
@ -829,7 +833,7 @@ class ShowBase(DirectObject.DirectObject):
# Save this lambda here for convenience; we'll use it to call # Save this lambda here for convenience; we'll use it to call
# down to the underlying _doOpenWindow() with all of the above # down to the underlying _doOpenWindow() with all of the above
# parameters. # parameters.
func = lambda : self._doOpenWindow( func = lambda: self._doOpenWindow(
props = props, fbprops = fbprops, pipe = pipe, gsg = gsg, props = props, fbprops = fbprops, pipe = pipe, gsg = gsg,
host = host, type = type, name = name, size = size, host = host, type = type, name = name, size = size,
aspectRatio = aspectRatio, makeCamera = makeCamera, aspectRatio = aspectRatio, makeCamera = makeCamera,
@ -1728,7 +1732,6 @@ class ShowBase(DirectObject.DirectObject):
np = mw.getParent().attachNewNode(mouseRecorder) np = mw.getParent().attachNewNode(mouseRecorder)
mw.reparentTo(np) mw.reparentTo(np)
mw = self.buttonThrowers[0].getParent() mw = self.buttonThrowers[0].getParent()
#: A special ButtonThrower to generate keyboard events and #: A special ButtonThrower to generate keyboard events and
@ -2861,7 +2864,6 @@ class ShowBase(DirectObject.DirectObject):
camera = None, size = 128, camera = None, size = 128,
cameraMask = PandaNode.getAllCameraMask(), cameraMask = PandaNode.getAllCameraMask(),
sourceLens = None): sourceLens = None):
""" """
Similar to :meth:`screenshot()`, this sets up a temporary cube Similar to :meth:`screenshot()`, this sets up a temporary cube
map Texture which it uses to take a series of six snapshots of map Texture which it uses to take a series of six snapshots of
@ -3428,7 +3430,6 @@ class ShowBase(DirectObject.DirectObject):
(self.appRunner.interactiveConsole and not self.appRunner.initialAppImport): (self.appRunner.interactiveConsole and not self.appRunner.initialAppImport):
self.taskMgr.run() self.taskMgr.run()
# Snake-case aliases, for people who prefer these. We're in the process # Snake-case aliases, for people who prefer these. We're in the process
# of migrating everyone to use the snake-case alternatives. # of migrating everyone to use the snake-case alternatives.
make_default_pipe = makeDefaultPipe make_default_pipe = makeDefaultPipe

View File

@ -81,7 +81,7 @@ class Transitions:
image = self.fadeModel, image = self.fadeModel,
image_scale = (4, 2, 2), image_scale = (4, 2, 2),
state = DGG.NORMAL, state = DGG.NORMAL,
) )
if not self.fadeModel: if not self.fadeModel:
# No fade model was given, so we make this the fade model. # No fade model was given, so we make this the fade model.
self.fade["relief"] = DGG.FLAT self.fade["relief"] = DGG.FLAT
@ -255,7 +255,6 @@ class Transitions:
self.alphaOn.set(r, g, b, 1) self.alphaOn.set(r, g, b, 1)
self.alphaOff.set(r, g, b, 0) self.alphaOff.set(r, g, b, 0)
################################################## ##################################################
# Iris # Iris
################################################## ##################################################
@ -403,7 +402,7 @@ class Transitions:
image_pos = (0,0,.1), image_pos = (0,0,.1),
image_color = (0.3,0.3,0.3,1), image_color = (0.3,0.3,0.3,1),
sortOrder = 0, sortOrder = 0,
) )
self.letterboxBottom = DirectFrame( self.letterboxBottom = DirectFrame(
parent = self.letterbox, parent = self.letterbox,
guiId = 'letterboxBottom', guiId = 'letterboxBottom',
@ -418,7 +417,7 @@ class Transitions:
image_pos = (0,0,.1), image_pos = (0,0,.1),
image_color = (0.3,0.3,0.3,1), image_color = (0.3,0.3,0.3,1),
sortOrder = 0, sortOrder = 0,
) )
# masad: always place these at the bottom of render # masad: always place these at the bottom of render
self.letterboxTop.setBin('sorted',0) self.letterboxTop.setBin('sorted',0)
@ -472,7 +471,7 @@ class Transitions:
# startPos = Vec3(0, 0, 1), # startPos = Vec3(0, 0, 1),
blendType=blendType blendType=blendType
), ),
), ),
Func(self.__finishLetterbox), Func(self.__finishLetterbox),
name = self.letterboxTaskName, name = self.letterboxTaskName,
) )
@ -508,7 +507,7 @@ class Transitions:
# startPos = Vec3(0, 0, 0.8), # startPos = Vec3(0, 0, 0.8),
blendType=blendType blendType=blendType
), ),
), ),
Func(self.letterbox.stash), Func(self.letterbox.stash),
Func(self.__finishLetterbox), Func(self.__finishLetterbox),
Func(messenger.send, 'letterboxOff'), Func(messenger.send, 'letterboxOff'),

View File

@ -31,11 +31,11 @@ sharedPackages = {}
vfs = VirtualFileSystem.getGlobalPtr() vfs = VirtualFileSystem.getGlobalPtr()
compiledExtensions = [ 'pyc', 'pyo' ] compiledExtensions = ['pyc', 'pyo']
if not __debug__: if not __debug__:
# In optimized mode, we prefer loading .pyo files over .pyc files. # In optimized mode, we prefer loading .pyo files over .pyc files.
# We implement that by reversing the extension names. # We implement that by reversing the extension names.
compiledExtensions = [ 'pyo', 'pyc' ] compiledExtensions = ['pyo', 'pyc']
class VFSImporter: class VFSImporter:
@ -104,6 +104,7 @@ class VFSImporter:
#print >>sys.stderr, "not found." #print >>sys.stderr, "not found."
return None return None
class VFSLoader: class VFSLoader:
""" The second part of VFSImporter, this is created for a """ The second part of VFSImporter, this is created for a
particular .py file or directory. """ particular .py file or directory. """
@ -298,7 +299,6 @@ class VFSLoader:
else: else:
raise ValueError("Timestamp wrong on %s" % (vfile)) raise ValueError("Timestamp wrong on %s" % (vfile))
def _compile(self, filename, source): def _compile(self, filename, source):
""" Compiles the Python source code to a code object and """ Compiles the Python source code to a code object and
attempts to write it to an appropriate .pyc file. May raise attempts to write it to an appropriate .pyc file. May raise
@ -472,6 +472,8 @@ class VFSSharedLoader:
_registered = False _registered = False
def register(): def register():
""" Register the VFSImporter on the path_hooks, if it has not """ Register the VFSImporter on the path_hooks, if it has not
already been registered, so that future Python import statements already been registered, so that future Python import statements

View File

@ -51,7 +51,7 @@ def addCircle(attachNode, vertexCount, radius, color = Vec4(1.0, 1.0, 1.0, 1.0),
targetCircleColorWriter.addData4f(centerColor[0], centerColor[1], centerColor[2], centerColor[3]) targetCircleColorWriter.addData4f(centerColor[0], centerColor[1], centerColor[2], centerColor[3])
for vertex in targetCircleShape: for vertex in targetCircleShape:
targetCircleVertexWriter.addData3f(0.0 + vertex[0] , 0.0 + vertex[1] , zFloat) targetCircleVertexWriter.addData3f(0.0 + vertex[0], 0.0 + vertex[1], zFloat)
targetCircleColorWriter.addData4f(color[0], color[1], color[2], color[3]) targetCircleColorWriter.addData4f(color[0], color[1], color[2], color[3])
#targetCircleColorWriter.addData4f(1.0, 1.0, 1.0, 1.0) #targetCircleColorWriter.addData4f(1.0, 1.0, 1.0, 1.0)
@ -96,7 +96,6 @@ def addSquare(attachNode, sizeX, sizeY, color = Vec4(1.0, 1.0, 1.0, 1.0), layer
boxColorWriter = GeomVertexWriter(boxVertexData, "color") boxColorWriter = GeomVertexWriter(boxVertexData, "color")
boxTextureWriter = GeomVertexWriter(boxVertexData, "texcoord") boxTextureWriter = GeomVertexWriter(boxVertexData, "texcoord")
boxVertexWriter.addData3f(-sX, sY, 0.0) boxVertexWriter.addData3f(-sX, sY, 0.0)
boxNormalWriter.addData3f(0, 0, 1) boxNormalWriter.addData3f(0, 0, 1)
boxColorWriter.addData4f(color[0], color[1], color[2], color[3]) boxColorWriter.addData4f(color[0], color[1], color[2], color[3])
@ -128,7 +127,6 @@ def addSquare(attachNode, sizeX, sizeY, color = Vec4(1.0, 1.0, 1.0, 1.0), layer
boxGeom = Geom(boxVertexData) boxGeom = Geom(boxVertexData)
boxGeom.addPrimitive(boxTris) boxGeom.addPrimitive(boxTris)
attachNode.addGeom(boxGeom) attachNode.addGeom(boxGeom)
return boxGeom return boxGeom
@ -163,7 +161,6 @@ def addBox(attachNode, sizeX, sizeY, sizeZ, color = Vec4(1.0, 1.0, 1.0, 1.0), da
boxNormalWriter = GeomVertexWriter(boxVertexData, "normal") boxNormalWriter = GeomVertexWriter(boxVertexData, "normal")
boxColorWriter = GeomVertexWriter(boxVertexData, "color") boxColorWriter = GeomVertexWriter(boxVertexData, "color")
#Front #Front
boxVertexWriter.addData3f(sX, sY, sZ) boxVertexWriter.addData3f(sX, sY, sZ)
@ -254,7 +251,6 @@ def addBox(attachNode, sizeX, sizeY, sizeZ, color = Vec4(1.0, 1.0, 1.0, 1.0), da
boxNormalWriter.addData3f(0, 0, 1) boxNormalWriter.addData3f(0, 0, 1)
boxColorWriter.addData4f(color1[0], color1[1], color1[2], color1[3]) boxColorWriter.addData4f(color1[0], color1[1], color1[2], color1[3])
#Left #Left
boxVertexWriter.addData3f(-sX, sY, -sZ) boxVertexWriter.addData3f(-sX, sY, -sZ)
@ -273,7 +269,6 @@ def addBox(attachNode, sizeX, sizeY, sizeZ, color = Vec4(1.0, 1.0, 1.0, 1.0), da
boxNormalWriter.addData3f(0, 0, 1) boxNormalWriter.addData3f(0, 0, 1)
boxColorWriter.addData4f(color2[0], color2[1], color2[2], color2[3]) boxColorWriter.addData4f(color2[0], color2[1], color2[2], color2[3])
boxTris = GeomTristrips(Geom.UHStatic) # trianglestrip obejcet boxTris = GeomTristrips(Geom.UHStatic) # trianglestrip obejcet
boxTris.addVertex(0)#(1) boxTris.addVertex(0)#(1)
boxTris.addVertex(1)#(2) boxTris.addVertex(1)#(2)
@ -314,7 +309,6 @@ def addBox(attachNode, sizeX, sizeY, sizeZ, color = Vec4(1.0, 1.0, 1.0, 1.0), da
boxGeom = Geom(boxVertexData) boxGeom = Geom(boxVertexData)
boxGeom.addPrimitive(boxTris) boxGeom.addPrimitive(boxTris)
attachNode.addGeom(boxGeom) attachNode.addGeom(boxGeom)
return boxGeom return boxGeom
@ -344,7 +338,6 @@ def addArrow(attachNode, sizeX, sizeY, color = Vec4(1.0, 1.0, 1.0, 1.0), layer =
boxNormalWriter = GeomVertexWriter(boxVertexData, "normal") boxNormalWriter = GeomVertexWriter(boxVertexData, "normal")
boxColorWriter = GeomVertexWriter(boxVertexData, "color") boxColorWriter = GeomVertexWriter(boxVertexData, "color")
boxVertexWriter.addData3f(-sX, sY, 0.0) boxVertexWriter.addData3f(-sX, sY, 0.0)
boxNormalWriter.addData3f(0, 0, 1) boxNormalWriter.addData3f(0, 0, 1)
boxColorWriter.addData4f(color[0], color[1], color[2], color[3]) boxColorWriter.addData4f(color[0], color[1], color[2], color[3])
@ -386,11 +379,9 @@ def addArrow(attachNode, sizeX, sizeY, color = Vec4(1.0, 1.0, 1.0, 1.0), layer =
boxTris.addVertex(6) boxTris.addVertex(6)
boxTris.closePrimitive() boxTris.closePrimitive()
boxGeom = Geom(boxVertexData) boxGeom = Geom(boxVertexData)
boxGeom.addPrimitive(boxTris) boxGeom.addPrimitive(boxTris)
attachNode.addGeom(boxGeom) attachNode.addGeom(boxGeom)
return boxGeom return boxGeom

View File

@ -8,7 +8,7 @@ __all__ = [
'open', 'listdir', 'walk', 'join', 'open', 'listdir', 'walk', 'join',
'isfile', 'isdir', 'exists', 'lexists', 'getmtime', 'getsize', 'isfile', 'isdir', 'exists', 'lexists', 'getmtime', 'getsize',
'execfile', 'execfile',
] ]
from panda3d import core from panda3d import core
import os import os
@ -293,6 +293,7 @@ def listdir(path):
files.append(file.getFilename().getBasename()) files.append(file.getFilename().getBasename())
return files return files
def walk(top, topdown = True, onerror = None, followlinks = True): def walk(top, topdown = True, onerror = None, followlinks = True):
""" Implements os.walk over vfs. """ Implements os.walk over vfs.
@ -321,30 +322,37 @@ def walk(top, topdown = True, onerror = None, followlinks = True):
if not topdown: if not topdown:
yield (top, dirnames, filenames) yield (top, dirnames, filenames)
def isfile(path): def isfile(path):
return _vfs.isRegularFile(core.Filename.fromOsSpecific(path)) return _vfs.isRegularFile(core.Filename.fromOsSpecific(path))
def isdir(path): def isdir(path):
return _vfs.isDirectory(core.Filename.fromOsSpecific(path)) return _vfs.isDirectory(core.Filename.fromOsSpecific(path))
def exists(path): def exists(path):
return _vfs.exists(core.Filename.fromOsSpecific(path)) return _vfs.exists(core.Filename.fromOsSpecific(path))
def lexists(path): def lexists(path):
return _vfs.exists(core.Filename.fromOsSpecific(path)) return _vfs.exists(core.Filename.fromOsSpecific(path))
def getmtime(path): def getmtime(path):
file = _vfs.getFile(core.Filename.fromOsSpecific(path), True) file = _vfs.getFile(core.Filename.fromOsSpecific(path), True)
if not file: if not file:
raise os.error raise os.error
return file.getTimestamp() return file.getTimestamp()
def getsize(path): def getsize(path):
file = _vfs.getFile(core.Filename.fromOsSpecific(path), True) file = _vfs.getFile(core.Filename.fromOsSpecific(path), True)
if not file: if not file:
raise os.error raise os.error
return file.getFileSize() return file.getFileSize()
def execfile(path, globals=None, locals=None): def execfile(path, globals=None, locals=None):
file = _vfs.getFile(core.Filename.fromOsSpecific(path), True) file = _vfs.getFile(core.Filename.fromOsSpecific(path), True)
if not file: if not file:

View File

@ -14,7 +14,7 @@ __all__ = [
'force_yield', 'consider_yield', 'force_yield', 'consider_yield',
'forceYield', 'considerYield', 'forceYield', 'considerYield',
'TIMEOUT_MAX' 'TIMEOUT_MAX'
] ]
from panda3d import core from panda3d import core
import sys import sys
@ -85,17 +85,22 @@ class LockType:
def __exit__(self, t, v, tb): def __exit__(self, t, v, tb):
self.release() self.release()
# Helper to generate new thread names # Helper to generate new thread names
_counter = 0 _counter = 0
def _newname(template="Thread-%d"): def _newname(template="Thread-%d"):
global _counter global _counter
_counter = _counter + 1 _counter = _counter + 1
return template % _counter return template % _counter
_threads = {} _threads = {}
_nextThreadId = 0 _nextThreadId = 0
_threadsLock = core.Mutex('thread._threadsLock') _threadsLock = core.Mutex('thread._threadsLock')
def start_new_thread(function, args, kwargs = {}, name = None): def start_new_thread(function, args, kwargs = {}, name = None):
def threadFunc(threadId, function = function, args = args, kwargs = kwargs): def threadFunc(threadId, function = function, args = args, kwargs = kwargs):
try: try:
@ -126,6 +131,7 @@ def start_new_thread(function, args, kwargs = {}, name = None):
finally: finally:
_threadsLock.release() _threadsLock.release()
def _add_thread(thread, wrapper): def _add_thread(thread, wrapper):
""" Adds the indicated core.Thread object, with the indicated Python """ Adds the indicated core.Thread object, with the indicated Python
wrapper, to the thread list. Returns the new thread ID. """ wrapper, to the thread list. Returns the new thread ID. """
@ -143,6 +149,7 @@ def _add_thread(thread, wrapper):
finally: finally:
_threadsLock.release() _threadsLock.release()
def _get_thread_wrapper(thread, wrapperClass): def _get_thread_wrapper(thread, wrapperClass):
""" Returns the thread wrapper for the indicated thread. If there """ Returns the thread wrapper for the indicated thread. If there
is not one, creates an instance of the indicated wrapperClass is not one, creates an instance of the indicated wrapperClass
@ -180,6 +187,7 @@ def _get_thread_wrapper(thread, wrapperClass):
finally: finally:
_threadsLock.release() _threadsLock.release()
def _get_thread_locals(thread, i): def _get_thread_locals(thread, i):
""" Returns the locals dictionary for the indicated thread. If """ Returns the locals dictionary for the indicated thread. If
there is not one, creates an empty dictionary. """ there is not one, creates an empty dictionary. """
@ -237,15 +245,19 @@ def interrupt_main():
# TODO. # TODO.
pass pass
def exit(): def exit():
raise SystemExit raise SystemExit
def allocate_lock(): def allocate_lock():
return LockType() return LockType()
def get_ident(): def get_ident():
return core.Thread.getCurrentThread().this return core.Thread.getCurrentThread().this
def stack_size(size = 0): def stack_size(size = 0):
raise error raise error

View File

@ -41,7 +41,7 @@ __all__ = [
'enumerate', 'active_count', 'enumerate', 'active_count',
'settrace', 'setprofile', 'stack_size', 'settrace', 'setprofile', 'stack_size',
'TIMEOUT_MAX', 'TIMEOUT_MAX',
] ]
TIMEOUT_MAX = _thread.TIMEOUT_MAX TIMEOUT_MAX = _thread.TIMEOUT_MAX
@ -49,6 +49,7 @@ local = _thread._local
_newname = _thread._newname _newname = _thread._newname
ThreadError = _thread.error ThreadError = _thread.error
class ThreadBase: class ThreadBase:
""" A base class for both Thread and ExternalThread in this """ A base class for both Thread and ExternalThread in this
module. """ module. """
@ -78,12 +79,14 @@ class ThreadBase:
else: else:
self.__dict__[key] = value self.__dict__[key] = value
# Copy these static methods from Panda's Thread object. These are # Copy these static methods from Panda's Thread object. These are
# useful if you may be running in Panda's SIMPLE_THREADS compilation # useful if you may be running in Panda's SIMPLE_THREADS compilation
# mode. # mode.
ThreadBase.forceYield = core.Thread.forceYield ThreadBase.forceYield = core.Thread.forceYield
ThreadBase.considerYield = core.Thread.considerYield ThreadBase.considerYield = core.Thread.considerYield
class Thread(ThreadBase): class Thread(ThreadBase):
""" This class provides a wrapper around Panda's PythonThread """ This class provides a wrapper around Panda's PythonThread
object. The wrapper is designed to emulate Python's own object. The wrapper is designed to emulate Python's own
@ -161,6 +164,7 @@ class Thread(ThreadBase):
self.__dict__['name'] = name self.__dict__['name'] = name
self.__thread.setName(name) self.__thread.setName(name)
class ExternalThread(ThreadBase): class ExternalThread(ThreadBase):
""" Returned for a Thread object that wasn't created by this """ Returned for a Thread object that wasn't created by this
interface. """ interface. """
@ -191,6 +195,7 @@ class ExternalThread(ThreadBase):
def setDaemon(self, daemon): def setDaemon(self, daemon):
raise RuntimeError raise RuntimeError
class MainThread(ExternalThread): class MainThread(ExternalThread):
""" Returned for the MainThread object. """ """ Returned for the MainThread object. """
@ -198,6 +203,7 @@ class MainThread(ExternalThread):
ExternalThread.__init__(self, extThread, threadId) ExternalThread.__init__(self, extThread, threadId)
self.__dict__['daemon'] = False self.__dict__['daemon'] = False
class Lock(core.Mutex): class Lock(core.Mutex):
""" This class provides a wrapper around Panda's Mutex object. """ This class provides a wrapper around Panda's Mutex object.
The wrapper is designed to emulate Python's own threading.Lock The wrapper is designed to emulate Python's own threading.Lock
@ -254,6 +260,7 @@ class Condition(core.ConditionVar):
def __exit__(self, t, v, tb): def __exit__(self, t, v, tb):
self.release() self.release()
class Semaphore(core.Semaphore): class Semaphore(core.Semaphore):
""" This class provides a wrapper around Panda's Semaphore """ This class provides a wrapper around Panda's Semaphore
object. The wrapper is designed to emulate Python's own object. The wrapper is designed to emulate Python's own
@ -274,6 +281,7 @@ class Semaphore(core.Semaphore):
def __exit__(self, t, v, tb): def __exit__(self, t, v, tb):
self.release() self.release()
class BoundedSemaphore(Semaphore): class BoundedSemaphore(Semaphore):
""" This class provides a wrapper around Panda's Semaphore """ This class provides a wrapper around Panda's Semaphore
object. The wrapper is designed to emulate Python's own object. The wrapper is designed to emulate Python's own
@ -289,6 +297,7 @@ class BoundedSemaphore(Semaphore):
Semaphore.release(self) Semaphore.release(self)
class Event: class Event:
""" This class is designed to emulate Python's own threading.Event """ This class is designed to emulate Python's own threading.Event
object. """ object. """
@ -339,6 +348,7 @@ class Event:
finally: finally:
self.__lock.release() self.__lock.release()
class Timer(Thread): class Timer(Thread):
"""Call a function after a specified number of seconds: """Call a function after a specified number of seconds:
@ -365,6 +375,7 @@ class Timer(Thread):
self.function(*self.args, **self.kwargs) self.function(*self.args, **self.kwargs)
self.finished.set() self.finished.set()
def _create_thread_wrapper(t, threadId): def _create_thread_wrapper(t, threadId):
""" Creates a thread wrapper for the indicated external thread. """ """ Creates a thread wrapper for the indicated external thread. """
if isinstance(t, core.MainThread): if isinstance(t, core.MainThread):
@ -374,16 +385,20 @@ def _create_thread_wrapper(t, threadId):
return pyt return pyt
def current_thread(): def current_thread():
t = core.Thread.getCurrentThread() t = core.Thread.getCurrentThread()
return _thread._get_thread_wrapper(t, _create_thread_wrapper) return _thread._get_thread_wrapper(t, _create_thread_wrapper)
def main_thread(): def main_thread():
t = core.Thread.getMainThread() t = core.Thread.getMainThread()
return _thread._get_thread_wrapper(t, _create_thread_wrapper) return _thread._get_thread_wrapper(t, _create_thread_wrapper)
currentThread = current_thread currentThread = current_thread
def enumerate(): def enumerate():
tlist = [] tlist = []
_thread._threadsLock.acquire() _thread._threadsLock.acquire()
@ -395,24 +410,33 @@ def enumerate():
finally: finally:
_thread._threadsLock.release() _thread._threadsLock.release()
def active_count(): def active_count():
return len(enumerate()) return len(enumerate())
activeCount = active_count activeCount = active_count
_settrace_func = None _settrace_func = None
def settrace(func): def settrace(func):
global _settrace_func global _settrace_func
_settrace_func = func _settrace_func = func
_setprofile_func = None _setprofile_func = None
def setprofile(func): def setprofile(func):
global _setprofile_func global _setprofile_func
_setprofile_func = func _setprofile_func = func
def stack_size(size = None): def stack_size(size = None):
raise ThreadError raise ThreadError
if __debug__: if __debug__:
def _test(): def _test():
from collections import deque from collections import deque
@ -482,7 +506,6 @@ if __debug__:
self.queue.put("%s.%d" % (self.getName(), counter)) self.queue.put("%s.%d" % (self.getName(), counter))
_sleep(random() * 0.00001) _sleep(random() * 0.00001)
class ConsumerThread(Thread): class ConsumerThread(Thread):
def __init__(self, queue, count): def __init__(self, queue, count):

View File

@ -74,10 +74,11 @@ def print_exc_plus():
#error we don't want. #error we don't want.
try: try:
valueStr = str(value) valueStr = str(value)
except: except Exception:
valueStr = "<ERROR WHILE PRINTING VALUE>" valueStr = "<ERROR WHILE PRINTING VALUE>"
print("\t%20s = %s" % (key, valueStr)) print("\t%20s = %s" % (key, valueStr))
# For historical purposes, we remap the C++-defined enumeration to # For historical purposes, we remap the C++-defined enumeration to
# these Python names, and define them both at the module level, here, # these Python names, and define them both at the module level, here,
# and at the class level (below). The preferred access is via the # and at the class level (below). The preferred access is via the
@ -109,21 +110,28 @@ Task.DtoolClassDict['pause'] = staticmethod(pause)
gather = Task.gather gather = Task.gather
shield = Task.shield shield = Task.shield
def sequence(*taskList): def sequence(*taskList):
seq = AsyncTaskSequence('sequence') seq = AsyncTaskSequence('sequence')
for task in taskList: for task in taskList:
seq.addTask(task) seq.addTask(task)
return seq return seq
Task.DtoolClassDict['sequence'] = staticmethod(sequence) Task.DtoolClassDict['sequence'] = staticmethod(sequence)
def loop(*taskList): def loop(*taskList):
seq = AsyncTaskSequence('loop') seq = AsyncTaskSequence('loop')
for task in taskList: for task in taskList:
seq.addTask(task) seq.addTask(task)
seq.setRepeatCount(-1) seq.setRepeatCount(-1)
return seq return seq
Task.DtoolClassDict['loop'] = staticmethod(loop) Task.DtoolClassDict['loop'] = staticmethod(loop)
class TaskManager: class TaskManager:
notify = directNotify.newCategory("TaskManager") notify = directNotify.newCategory("TaskManager")
@ -157,7 +165,7 @@ class TaskManager:
taskId = None, taskId = None,
profiled = False, profiled = False,
session = None, session = None,
) )
def finalInit(self): def finalInit(self):
# This function should be called once during startup, after # This function should be called once during startup, after
@ -317,7 +325,6 @@ class TaskManager:
def doMethodLater(self, delayTime, funcOrTask, name, extraArgs = None, def doMethodLater(self, delayTime, funcOrTask, name, extraArgs = None,
sort = None, priority = None, taskChain = None, sort = None, priority = None, taskChain = None,
uponDeath = None, appendTask = False, owner = None): uponDeath = None, appendTask = False, owner = None):
"""Adds a task to be performed at some time in the future. """Adds a task to be performed at some time in the future.
This is identical to `add()`, except that the specified This is identical to `add()`, except that the specified
delayTime is applied to the Task object first, which means delayTime is applied to the Task object first, which means
@ -553,6 +560,7 @@ class TaskManager:
try: try:
if len(self._frameProfileQueue) > 0: if len(self._frameProfileQueue) > 0:
numFrames, session, callback = self._frameProfileQueue.pop(0) numFrames, session, callback = self._frameProfileQueue.pop(0)
def _profileFunc(numFrames=numFrames): def _profileFunc(numFrames=numFrames):
self._doProfiledFrames(numFrames) self._doProfiledFrames(numFrames)
session.setFunc(_profileFunc) session.setFunc(_profileFunc)
@ -605,7 +613,7 @@ class TaskManager:
# a nested try block are not caught by the inner try block's except # a nested try block are not caught by the inner try block's except
try: try:
(code, message) = ioError (code, message) = ioError
except: except Exception:
code = 0 code = 0
message = ioError message = ioError
return code, message return code, message
@ -709,7 +717,7 @@ class TaskManager:
task = task, task = task,
profiled = False, profiled = False,
session = None, session = None,
) )
# Temporarily replace the task's own function with our # Temporarily replace the task's own function with our
# _profileTask method. # _profileTask method.
@ -817,6 +825,7 @@ class TaskManager:
# run-once task # run-once task
l = [] l = []
def _testDone(task, l=l): def _testDone(task, l=l):
l.append(None) l.append(None)
return task.done return task.done
@ -848,6 +857,7 @@ class TaskManager:
# continued task # continued task
l = [] l = []
def _testCont(task, l = l): def _testCont(task, l = l):
l.append(None) l.append(None)
return task.cont return task.cont
@ -862,6 +872,7 @@ class TaskManager:
# continue until done task # continue until done task
l = [] l = []
def _testContDone(task, l = l): def _testContDone(task, l = l):
l.append(None) l.append(None)
if len(l) >= 2: if len(l) >= 2:
@ -891,9 +902,11 @@ class TaskManager:
# task sort # task sort
l = [] l = []
def _testPri1(task, l = l): def _testPri1(task, l = l):
l.append(1) l.append(1)
return task.cont return task.cont
def _testPri2(task, l = l): def _testPri2(task, l = l):
l.append(2) l.append(2)
return task.cont return task.cont
@ -913,6 +926,7 @@ class TaskManager:
# task extraArgs # task extraArgs
l = [] l = []
def _testExtraArgs(arg1, arg2, l=l): def _testExtraArgs(arg1, arg2, l=l):
l.extend([arg1, arg2,]) l.extend([arg1, arg2,])
return done return done
@ -925,6 +939,7 @@ class TaskManager:
# task appendTask # task appendTask
l = [] l = []
def _testAppendTask(arg1, arg2, task, l=l): def _testAppendTask(arg1, arg2, task, l=l):
l.extend([arg1, arg2,]) l.extend([arg1, arg2,])
return task.done return task.done
@ -937,8 +952,10 @@ class TaskManager:
# task uponDeath # task uponDeath
l = [] l = []
def _uponDeathFunc(task, l=l): def _uponDeathFunc(task, l=l):
l.append(task.name) l.append(task.name)
def _testUponDeath(task): def _testUponDeath(task):
return done return done
tm.add(_testUponDeath, 'testUponDeath', uponDeath=_uponDeathFunc) tm.add(_testUponDeath, 'testUponDeath', uponDeath=_uponDeathFunc)
@ -953,10 +970,12 @@ class TaskManager:
class _TaskOwner: class _TaskOwner:
def _addTask(self, task): def _addTask(self, task):
self.addedTaskName = task.name self.addedTaskName = task.name
def _clearTask(self, task): def _clearTask(self, task):
self.clearedTaskName = task.name self.clearedTaskName = task.name
to = _TaskOwner() to = _TaskOwner()
l = [] l = []
def _testOwner(task): def _testOwner(task):
return done return done
tm.add(_testOwner, 'testOwner', owner=to) tm.add(_testOwner, 'testOwner', owner=to)
@ -968,15 +987,17 @@ class TaskManager:
_TaskOwner = None _TaskOwner = None
tm._checkMemLeaks() tm._checkMemLeaks()
doLaterTests = [0,] doLaterTests = [0,]
# doLater # doLater
l = [] l = []
def _testDoLater1(task, l=l): def _testDoLater1(task, l=l):
l.append(1) l.append(1)
def _testDoLater2(task, l=l): def _testDoLater2(task, l=l):
l.append(2) l.append(2)
def _monitorDoLater(task, tm=tm, l=l, doLaterTests=doLaterTests): def _monitorDoLater(task, tm=tm, l=l, doLaterTests=doLaterTests):
if task.time > .03: if task.time > .03:
assert l == [1, 2,] assert l == [1, 2,]
@ -996,10 +1017,13 @@ class TaskManager:
# doLater sort # doLater sort
l = [] l = []
def _testDoLaterPri1(task, l=l): def _testDoLaterPri1(task, l=l):
l.append(1) l.append(1)
def _testDoLaterPri2(task, l=l): def _testDoLaterPri2(task, l=l):
l.append(2) l.append(2)
def _monitorDoLaterPri(task, tm=tm, l=l, doLaterTests=doLaterTests): def _monitorDoLaterPri(task, tm=tm, l=l, doLaterTests=doLaterTests):
if task.time > .02: if task.time > .02:
assert l == [1, 2,] assert l == [1, 2,]
@ -1019,8 +1043,10 @@ class TaskManager:
# doLater extraArgs # doLater extraArgs
l = [] l = []
def _testDoLaterExtraArgs(arg1, l=l): def _testDoLaterExtraArgs(arg1, l=l):
l.append(arg1) l.append(arg1)
def _monitorDoLaterExtraArgs(task, tm=tm, l=l, doLaterTests=doLaterTests): def _monitorDoLaterExtraArgs(task, tm=tm, l=l, doLaterTests=doLaterTests):
if task.time > .02: if task.time > .02:
assert l == [3,] assert l == [3,]
@ -1038,9 +1064,11 @@ class TaskManager:
# doLater appendTask # doLater appendTask
l = [] l = []
def _testDoLaterAppendTask(arg1, task, l=l): def _testDoLaterAppendTask(arg1, task, l=l):
assert task.name == 'testDoLaterAppendTask' assert task.name == 'testDoLaterAppendTask'
l.append(arg1) l.append(arg1)
def _monitorDoLaterAppendTask(task, tm=tm, l=l, doLaterTests=doLaterTests): def _monitorDoLaterAppendTask(task, tm=tm, l=l, doLaterTests=doLaterTests):
if task.time > .02: if task.time > .02:
assert l == [4,] assert l == [4,]
@ -1059,11 +1087,14 @@ class TaskManager:
# doLater uponDeath # doLater uponDeath
l = [] l = []
def _testUponDeathFunc(task, l=l): def _testUponDeathFunc(task, l=l):
assert task.name == 'testDoLaterUponDeath' assert task.name == 'testDoLaterUponDeath'
l.append(10) l.append(10)
def _testDoLaterUponDeath(arg1, l=l): def _testDoLaterUponDeath(arg1, l=l):
return done return done
def _monitorDoLaterUponDeath(task, tm=tm, l=l, doLaterTests=doLaterTests): def _monitorDoLaterUponDeath(task, tm=tm, l=l, doLaterTests=doLaterTests):
if task.time > .02: if task.time > .02:
assert l == [10,] assert l == [10,]
@ -1085,12 +1116,15 @@ class TaskManager:
class _DoLaterOwner: class _DoLaterOwner:
def _addTask(self, task): def _addTask(self, task):
self.addedTaskName = task.name self.addedTaskName = task.name
def _clearTask(self, task): def _clearTask(self, task):
self.clearedTaskName = task.name self.clearedTaskName = task.name
doLaterOwner = _DoLaterOwner() doLaterOwner = _DoLaterOwner()
l = [] l = []
def _testDoLaterOwner(l=l): def _testDoLaterOwner(l=l):
pass pass
def _monitorDoLaterOwner(task, tm=tm, l=l, doLaterOwner=doLaterOwner, def _monitorDoLaterOwner(task, tm=tm, l=l, doLaterOwner=doLaterOwner,
doLaterTests=doLaterTests): doLaterTests=doLaterTests):
if task.time > .02: if task.time > .02:
@ -1223,6 +1257,7 @@ class TaskManager:
# create Task object and add to mgr # create Task object and add to mgr
l = [] l = []
def _testTaskObj(task, l=l): def _testTaskObj(task, l=l):
l.append(None) l.append(None)
return task.cont return task.cont
@ -1240,6 +1275,7 @@ class TaskManager:
# remove Task via task.remove() # remove Task via task.remove()
l = [] l = []
def _testTaskObjRemove(task, l=l): def _testTaskObjRemove(task, l=l):
l.append(None) l.append(None)
return task.cont return task.cont
@ -1299,6 +1335,7 @@ if __debug__:
gc.enable() gc.enable()
from direct.showbase.DirectObject import DirectObject from direct.showbase.DirectObject import DirectObject
from direct.task.TaskManagerGlobal import taskMgr from direct.task.TaskManagerGlobal import taskMgr
class TestClass(DirectObject): class TestClass(DirectObject):
def doTask(self, task): def doTask(self, task):
return task.done return task.done

View File

@ -19,6 +19,7 @@ import tkinter as tk
FRAMES = 0 FRAMES = 0
SECONDS = 1 SECONDS = 1
class AnimPanel(AppShell): class AnimPanel(AppShell):
# Override class variables # Override class variables
appname = 'Anim Panel' appname = 'Anim Panel'
@ -38,7 +39,7 @@ class AnimPanel(AppShell):
('title', self.appname, None), ('title', self.appname, None),
('actorList', [], None), ('actorList', [], None),
('Actor_label_width', 12, None), ('Actor_label_width', 12, None),
) )
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)
# direct session that spawned me, if any, used # direct session that spawned me, if any, used
@ -55,7 +56,6 @@ class AnimPanel(AppShell):
# Initialize the superclass # Initialize the superclass
AppShell.__init__(self) AppShell.__init__(self)
# Execute option callbacks # Execute option callbacks
self.initialiseoptions(AnimPanel) self.initialiseoptions(AnimPanel)
# We need to know when AnimPanel is closed # We need to know when AnimPanel is closed
@ -270,7 +270,7 @@ class AnimPanel(AppShell):
initialdir = '/i/beta', initialdir = '/i/beta',
title = 'Load Animation', title = 'Load Animation',
parent = self.component('hull') parent = self.component('hull')
) )
if not animFilename or animFilename == 'None': if not animFilename or animFilename == 'None':
# no file selected, canceled # no file selected, canceled
return return
@ -291,7 +291,6 @@ class AnimPanel(AppShell):
self.clearActorControls() self.clearActorControls()
self.createActorControls() self.createActorControls()
def playActorControls(self): def playActorControls(self):
self.stopActorControls() self.stopActorControls()
self.lastT = ClockObject.getGlobalClock().getFrameTime() self.lastT = ClockObject.getGlobalClock().getFrameTime()
@ -372,6 +371,7 @@ class AnimPanel(AppShell):
self.destroyCallBack = None self.destroyCallBack = None
AppShell.destroy(self) AppShell.destroy(self)
class ActorControl(Pmw.MegaWidget): class ActorControl(Pmw.MegaWidget):
def __init__(self, parent = None, **kw): def __init__(self, parent = None, **kw):
@ -391,7 +391,7 @@ class ActorControl(Pmw.MegaWidget):
('active', initActive, None), ('active', initActive, None),
('sLabel_width', 5, None), ('sLabel_width', 5, None),
('sLabel_font', DEFAULT_FONT, None), ('sLabel_font', DEFAULT_FONT, None),
) )
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)
# Initialize the superclass # Initialize the superclass
@ -662,6 +662,7 @@ class ActorControl(Pmw.MegaWidget):
self.fOneShot = 1 self.fOneShot = 1
self.goToT((self.currT-(1/self.fps))%self.duration) self.goToT((self.currT-(1/self.fps))%self.duration)
""" """
# EXAMPLE CODE # EXAMPLE CODE
from direct.actor import Actor from direct.actor import Actor

View File

@ -37,7 +37,7 @@ class DirectSessionPanel(AppShell):
INITOPT = Pmw.INITOPT INITOPT = Pmw.INITOPT
optiondefs = ( optiondefs = (
('title', self.appname, None), ('title', self.appname, None),
) )
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)
# Call superclass initialization function # Call superclass initialization function
@ -82,7 +82,7 @@ class DirectSessionPanel(AppShell):
('DIRECT_redoListEmpty', self.redoListEmptyHook), ('DIRECT_redoListEmpty', self.redoListEmptyHook),
('DIRECT_selectedNodePath', self.selectedNodePathHook), ('DIRECT_selectedNodePath', self.selectedNodePathHook),
('DIRECT_addLight', self.addLight), ('DIRECT_addLight', self.addLight),
] ]
for event, method in self.actionEvents: for event, method in self.actionEvents:
self.accept(event, method) self.accept(event, method)
@ -476,7 +476,6 @@ class DirectSessionPanel(AppShell):
lightFrame.pack(expand = 1, fill = tk.BOTH) lightFrame.pack(expand = 1, fill = tk.BOTH)
def createGridPage(self, gridPage): def createGridPage(self, gridPage):
tk.Label(gridPage, text = 'Grid', tk.Label(gridPage, text = 'Grid',
font=('MSSansSerif', 14, 'bold')).pack(expand = 0) font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
@ -649,7 +648,7 @@ class DirectSessionPanel(AppShell):
else: else:
# Good eval but not a node path, give up # Good eval but not a node path, give up
nodePath = None nodePath = None
except: except Exception:
# Bogus eval # Bogus eval
nodePath = None nodePath = None
# Clear bogus entry from listbox # Clear bogus entry from listbox
@ -699,7 +698,7 @@ class DirectSessionPanel(AppShell):
else: else:
# Good eval but not a node path, give up # Good eval but not a node path, give up
nodePath = None nodePath = None
except: except Exception:
# Bogus eval # Bogus eval
nodePath = None nodePath = None
# Clear bogus entry from listbox # Clear bogus entry from listbox
@ -740,6 +739,7 @@ class DirectSessionPanel(AppShell):
# Background # # Background #
def setBackgroundColor(self, r, g, b): def setBackgroundColor(self, r, g, b):
self.setBackgroundColorVec((r, g, b)) self.setBackgroundColorVec((r, g, b))
def setBackgroundColorVec(self, color): def setBackgroundColorVec(self, color):
base.setBackgroundColor(color[0]/255.0, base.setBackgroundColor(color[0]/255.0,
color[1]/255.0, color[1]/255.0,

View File

@ -128,7 +128,7 @@ class FSMInspector(AppShell):
optiondefs = ( optiondefs = (
('title', fsm.getName(), None), ('title', fsm.getName(), None),
('gridSize', '0.25i', self._setGridSize), ('gridSize', '0.25i', self._setGridSize),
) )
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)
self.fsm = fsm self.fsm = fsm
@ -393,6 +393,7 @@ class FSMInspector(AppShell):
self.ignore(self.name + '_' + si.getName() + '_entered') self.ignore(self.name + '_' + si.getName() + '_entered')
self.ignore(self.name + '_' + si.getName() + '_exited') self.ignore(self.name + '_' + si.getName() + '_exited')
class StateInspector(Pmw.MegaArchetype): class StateInspector(Pmw.MegaArchetype):
def __init__(self, inspector, state, **kw): def __init__(self, inspector, state, **kw):
@ -412,7 +413,7 @@ class StateInspector(Pmw.MegaArchetype):
optiondefs = ( optiondefs = (
('radius', '0.375i', self._setRadius), ('radius', '0.375i', self._setRadius),
('gridSize', '0.25i', self._setGridSize), ('gridSize', '0.25i', self._setGridSize),
) )
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)
# Initialize the parent class # Initialize the parent class
@ -439,7 +440,6 @@ class StateInspector(Pmw.MegaArchetype):
half, half, half, half,
tags = (self.tag,)) tags = (self.tag,))
# The Popup State Menu # The Popup State Menu
self._popupMenu = tk.Menu(self._canvas, tearoff = 0) self._popupMenu = tk.Menu(self._canvas, tearoff = 0)
self._popupMenu.add_command(label = 'Request transition to ' + self._popupMenu.add_command(label = 'Request transition to ' +

View File

@ -19,6 +19,7 @@ import tkinter as tk
### public API ### public API
def inspect(anObject): def inspect(anObject):
"""Opens up a window for visually inspecting the details of a given Python """Opens up a window for visually inspecting the details of a given Python
object. See :ref:`inspection-utilities`. object. See :ref:`inspection-utilities`.
@ -30,6 +31,7 @@ def inspect(anObject):
### private ### private
def inspectorFor(anObject): def inspectorFor(anObject):
typeName = type(anObject).__name__.capitalize() + 'Type' typeName = type(anObject).__name__.capitalize() + 'Type'
if typeName in _InspectorMap: if typeName in _InspectorMap:
@ -72,7 +74,8 @@ def initializeInspectorMap():
'StringType': 'SequenceInspector', 'StringType': 'SequenceInspector',
'TupleType': 'SequenceInspector', 'TupleType': 'SequenceInspector',
'TypeType': 'Inspector', 'TypeType': 'Inspector',
'UnboundMethodType': 'FunctionInspector'} 'UnboundMethodType': 'FunctionInspector',
}
for each in notFinishedTypes: for each in notFinishedTypes:
_InspectorMap[each] = 'Inspector' _InspectorMap[each] = 'Inspector'
@ -119,10 +122,7 @@ class Inspector:
object = self.partNumber(partNumber) object = self.partNumber(partNumber)
doc = None doc = None
if callable(object): if callable(object):
try: doc = getattr(object, '__doc__', None)
doc = object.__doc__
except:
pass
if doc: if doc:
return str(object) + '\n' + str(doc) return str(object) + '\n' + str(doc)
else: else:
@ -150,10 +150,12 @@ class Inspector:
### ###
class ModuleInspector(Inspector): class ModuleInspector(Inspector):
def namedParts(self): def namedParts(self):
return ['__dict__'] return ['__dict__']
class ClassInspector(Inspector): class ClassInspector(Inspector):
def namedParts(self): def namedParts(self):
return ['__bases__'] + list(self.object.__dict__.keys()) return ['__bases__'] + list(self.object.__dict__.keys())
@ -161,34 +163,41 @@ class ClassInspector(Inspector):
def title(self): def title(self):
return self.object.__name__ + ' Class' return self.object.__name__ + ' Class'
class InstanceInspector(Inspector): class InstanceInspector(Inspector):
def title(self): def title(self):
return self.object.__class__.__name__ return self.object.__class__.__name__
def namedParts(self): def namedParts(self):
return ['__class__'] + dir(self.object) return ['__class__'] + dir(self.object)
### ###
class FunctionInspector(Inspector): class FunctionInspector(Inspector):
def title(self): def title(self):
return self.object.__name__ + "()" return self.object.__name__ + "()"
class InstanceMethodInspector(Inspector): class InstanceMethodInspector(Inspector):
def title(self): def title(self):
return str(self.object.__self__.__class__) + "." + self.object.__name__ + "()" return str(self.object.__self__.__class__) + "." + self.object.__name__ + "()"
class CodeInspector(Inspector): class CodeInspector(Inspector):
def title(self): def title(self):
return str(self.object) return str(self.object)
### ###
class ComplexInspector(Inspector): class ComplexInspector(Inspector):
def namedParts(self): def namedParts(self):
return ['real', 'imag'] return ['real', 'imag']
### ###
class DictionaryInspector(Inspector): class DictionaryInspector(Inspector):
def initializePartsList(self): def initializePartsList(self):
@ -208,6 +217,7 @@ class DictionaryInspector(Inspector):
else: else:
return getattr(self.object, key) return getattr(self.object, key)
class SequenceInspector(Inspector): class SequenceInspector(Inspector):
def initializePartsList(self): def initializePartsList(self):
Inspector.initializePartsList(self) Inspector.initializePartsList(self)
@ -224,6 +234,7 @@ class SequenceInspector(Inspector):
else: else:
return getattr(self.object, index) return getattr(self.object, index)
class SliceInspector(Inspector): class SliceInspector(Inspector):
def namedParts(self): def namedParts(self):
return ['start', 'stop', 'step'] return ['start', 'stop', 'step']
@ -232,6 +243,7 @@ class SliceInspector(Inspector):
### Initialization ### Initialization
initializeInspectorMap() initializeInspectorMap()
class InspectorWindow: class InspectorWindow:
def __init__(self, inspector): def __init__(self, inspector):
self.inspectors = [inspector] self.inspectors = [inspector]
@ -346,8 +358,8 @@ class InspectorWindow:
command = self.commandWidget.get(commandStart, command = self.commandWidget.get(commandStart,
commandStart + ' lineend') commandStart + ' lineend')
if command: if command:
partDict = { 'this': self.selectedPart(), partDict = {'this': self.selectedPart(),
'object': self.topInspector().object } 'object': self.topInspector().object}
result = eval(command, partDict) result = eval(command, partDict)
self.commandWidget.insert(tk.INSERT, repr(result) + '\n>>> ') self.commandWidget.insert(tk.INSERT, repr(result) + '\n>>> ')
self.commandWidget.see(tk.INSERT) self.commandWidget.see(tk.INSERT)
@ -395,7 +407,7 @@ class InspectorWindow:
text = tk.Label( text = tk.Label(
frame, justify = tk.LEFT, frame, justify = tk.LEFT,
text = "ListBox shows selected object's attributes\nDouble click or use right arrow on an instance variable to dive down.\nDouble click self or use left arrow to pop back up.\nUse up and down arrow keys to move from item to item in the current level.\n\nValue box (upper right) shows current value of selected item\n\nCommand box (lower right) is used to evaluate python commands\nLocal variables 'object' and 'this' are defined as the current object being inspected\nand the current attribute selected." text = "ListBox shows selected object's attributes\nDouble click or use right arrow on an instance variable to dive down.\nDouble click self or use left arrow to pop back up.\nUse up and down arrow keys to move from item to item in the current level.\n\nValue box (upper right) shows current value of selected item\n\nCommand box (lower right) is used to evaluate python commands\nLocal variables 'object' and 'this' are defined as the current object being inspected\nand the current attribute selected."
) )
text.pack() text.pack()
#Private #Private

View File

@ -46,6 +46,7 @@ PRF_UTILITIES = [
'lambda s = self: s.playbackMarker.setZ(render, 0.0)', 'lambda s = self: s.playbackMarker.setZ(render, 0.0)',
'lambda s = self: s.followTerrain(10.0)'] 'lambda s = self: s.followTerrain(10.0)']
class MopathRecorder(AppShell, DirectObject): class MopathRecorder(AppShell, DirectObject):
# Override class variables here # Override class variables here
appname = 'Mopath Recorder Panel' appname = 'Mopath Recorder Panel'
@ -63,7 +64,7 @@ class MopathRecorder(AppShell, DirectObject):
('title', self.appname, None), ('title', self.appname, None),
('nodePath', None, None), ('nodePath', None, None),
('name', name, None) ('name', name, None)
) )
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)
# Call superclass initialization function # Call superclass initialization function
@ -191,7 +192,7 @@ class MopathRecorder(AppShell, DirectObject):
('DIRECT_manipulateObjectStart', self.manipulateObjectStartHook), ('DIRECT_manipulateObjectStart', self.manipulateObjectStartHook),
('DIRECT_manipulateObjectCleanup', ('DIRECT_manipulateObjectCleanup',
self.manipulateObjectCleanupHook), self.manipulateObjectCleanupHook),
] ]
for event, method in self.actionEvents: for event, method in self.actionEvents:
self.accept(event, method) self.accept(event, method)
@ -930,6 +931,7 @@ class MopathRecorder(AppShell, DirectObject):
def disableKeyframeButton(self): def disableKeyframeButton(self):
self.getWidget('Recording', 'Add Keyframe')['state'] = 'disabled' self.getWidget('Recording', 'Add Keyframe')['state'] = 'disabled'
def enableKeyframeButton(self): def enableKeyframeButton(self):
self.getWidget('Recording', 'Add Keyframe')['state'] = 'normal' self.getWidget('Recording', 'Add Keyframe')['state'] = 'normal'
@ -1211,7 +1213,7 @@ class MopathRecorder(AppShell, DirectObject):
else: else:
# Good eval but not a node path, give up # Good eval but not a node path, give up
nodePath = None nodePath = None
except: except Exception:
# Bogus eval # Bogus eval
nodePath = None nodePath = None
# Clear bogus entry from listbox # Clear bogus entry from listbox

View File

@ -66,7 +66,7 @@ class ParticlePanel(AppShell):
INITOPT = Pmw.INITOPT INITOPT = Pmw.INITOPT
optiondefs = ( optiondefs = (
('title', self.appname, None), ('title', self.appname, None),
) )
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)
# Record particle effect # Record particle effect
@ -113,7 +113,6 @@ class ParticlePanel(AppShell):
self.particleEffect) self.particleEffect)
self.forcePagesDict = {} self.forcePagesDict = {}
def createInterface(self): def createInterface(self):
# Handle to the toplevels hull # Handle to the toplevels hull
interior = self.interior() interior = self.interior()
@ -171,6 +170,7 @@ class ParticlePanel(AppShell):
self.effectsLabelMenu.add_command( self.effectsLabelMenu.add_command(
label = 'Place Particle Effect', label = 'Place Particle Effect',
command = lambda s = self: Placer.place(s.particleEffect)) command = lambda s = self: Placer.place(s.particleEffect))
def togglePEVis(s = self): def togglePEVis(s = self):
if s.particleEffect.isHidden(): if s.particleEffect.isHidden():
s.particleEffect.show() s.particleEffect.show()
@ -257,7 +257,7 @@ class ParticlePanel(AppShell):
'Age in seconds at which the system (vs. particles) should die', 'Age in seconds at which the system (vs. particles) should die',
self.setSystemLifespan, self.setSystemLifespan,
0.0, None, None) 0.0, None, None)
) )
self.createFloaters(systemPage, systemFloaterDefs) self.createFloaters(systemPage, systemFloaterDefs)
# Checkboxes # Checkboxes
@ -327,19 +327,18 @@ class ParticlePanel(AppShell):
self.createCheckbutton( self.createCheckbutton(
zSpinPage, 'Z Spin Factory', 'Enable Angular Velocity', zSpinPage, 'Z Spin Factory', 'Enable Angular Velocity',
("On: angular velocity is used; " + 'On: angular velocity is used; Off: final angle is used',
"Off: final angle is used"),
self.toggleAngularVelocity, 0, side = tk.TOP) self.toggleAngularVelocity, 0, side = tk.TOP)
self.createFloater( self.createFloater(
zSpinPage, 'Z Spin Factory', 'Angular Velocity', zSpinPage, 'Z Spin Factory', 'Angular Velocity',
'How fast sprites rotate', 'How fast sprites rotate',
command = self.setFactoryZSpinAngularVelocity) command = self.setFactoryZSpinAngularVelocity)
self.createFloater( self.createFloater(
zSpinPage, 'Z Spin Factory', 'Angular Velocity Spread', zSpinPage, 'Z Spin Factory', 'Angular Velocity Spread',
'Variation in how fast sprites rotate', 'Variation in how fast sprites rotate',
command = self.setFactoryZSpinAngularVelocitySpread) command = self.setFactoryZSpinAngularVelocitySpread)
self.createAngleDial(zSpinPage, 'Z Spin Factory', 'Initial Angle', self.createAngleDial(zSpinPage, 'Z Spin Factory', 'Initial Angle',
'Starting angle in degrees', 'Starting angle in degrees',
@ -996,7 +995,7 @@ class ParticlePanel(AppShell):
widgets.append( widgets.append(
self.createFloater(parent, category, label, balloonHelp, self.createFloater(parent, category, label, balloonHelp,
command, min, max, resolution) command, min, max, resolution)
) )
return widgets return widgets
def createFloater(self, parent, category, text, balloonHelp, def createFloater(self, parent, category, text, balloonHelp,
@ -1158,7 +1157,7 @@ class ParticlePanel(AppShell):
label = effect.getName(), label = effect.getName(),
command = (lambda s = self, command = (lambda s = self,
e = effect: s.selectEffectNamed(e.getName())) e = effect: s.selectEffectNamed(e.getName()))
) )
effectActive = tk.IntVar() effectActive = tk.IntVar()
effectActive.set(effect.isEnabled()) effectActive.set(effect.isEnabled())
self.effectsEnableMenu.add_checkbutton( self.effectsEnableMenu.add_checkbutton(
@ -1183,7 +1182,7 @@ class ParticlePanel(AppShell):
label = name, label = name,
command = (lambda s = self, command = (lambda s = self,
n = name: s.selectParticlesNamed(n)) n = name: s.selectParticlesNamed(n))
) )
particleActive = tk.IntVar() particleActive = tk.IntVar()
particleActive.set(particle.isEnabled()) particleActive.set(particle.isEnabled())
self.particlesEnableMenu.add_checkbutton( self.particlesEnableMenu.add_checkbutton(
@ -1208,7 +1207,7 @@ class ParticlePanel(AppShell):
label = name, label = name,
command = (lambda s = self, command = (lambda s = self,
n = name: s.selectForceGroupNamed(n)) n = name: s.selectForceGroupNamed(n))
) )
forceActive = tk.IntVar() forceActive = tk.IntVar()
forceActive.set(force.isEnabled()) forceActive.set(force.isEnabled())
self.forceGroupEnableMenu.add_checkbutton( self.forceGroupEnableMenu.add_checkbutton(
@ -1379,24 +1378,33 @@ class ParticlePanel(AppShell):
self.particles.getLocalVelocityFlag()) self.particles.getLocalVelocityFlag())
self.getVariable('System', 'System Grows Older').set( self.getVariable('System', 'System Grows Older').set(
self.particles.getSystemGrowsOlderFlag()) self.particles.getSystemGrowsOlderFlag())
def setSystemPoolSize(self, value): def setSystemPoolSize(self, value):
self.particles.setPoolSize(int(value)) self.particles.setPoolSize(int(value))
def setSystemBirthRate(self, value): def setSystemBirthRate(self, value):
self.particles.setBirthRate(value) self.particles.setBirthRate(value)
def setSystemLitterSize(self, value): def setSystemLitterSize(self, value):
self.particles.setLitterSize(int(value)) self.particles.setLitterSize(int(value))
def setSystemLitterSpread(self, value): def setSystemLitterSpread(self, value):
self.particles.setLitterSpread(int(value)) self.particles.setLitterSpread(int(value))
def setSystemLifespan(self, value): def setSystemLifespan(self, value):
self.particles.setSystemLifespan(value) self.particles.setSystemLifespan(value)
def toggleSystemLocalVelocity(self): def toggleSystemLocalVelocity(self):
self.particles.setLocalVelocityFlag( self.particles.setLocalVelocityFlag(
self.getVariable('System', 'Render Space Velocities').get()) self.getVariable('System', 'Render Space Velocities').get())
def toggleSystemGrowsOlder(self): def toggleSystemGrowsOlder(self):
self.particles.setSystemGrowsOlderFlag( self.particles.setSystemGrowsOlderFlag(
self.getVariable('System', 'System Grows Older').get()) self.getVariable('System', 'System Grows Older').get())
def setSystemPos(self, pos): def setSystemPos(self, pos):
self.particles.nodePath.setPos(Vec3(pos[0], pos[1], pos[2])) self.particles.nodePath.setPos(Vec3(pos[0], pos[1], pos[2]))
def setSystemHpr(self, pos): def setSystemHpr(self, pos):
self.particles.nodePath.setHpr(Vec3(pos[0], pos[1], pos[2])) self.particles.nodePath.setHpr(Vec3(pos[0], pos[1], pos[2]))
@ -1427,28 +1435,39 @@ class ParticlePanel(AppShell):
def setFactoryLifeSpan(self, value): def setFactoryLifeSpan(self, value):
self.particles.factory.setLifespanBase(value) self.particles.factory.setLifespanBase(value)
def setFactoryLifeSpanSpread(self, value): def setFactoryLifeSpanSpread(self, value):
self.particles.factory.setLifespanSpread(value) self.particles.factory.setLifespanSpread(value)
def setFactoryParticleMass(self, value): def setFactoryParticleMass(self, value):
self.particles.factory.setMassBase(value) self.particles.factory.setMassBase(value)
def setFactoryParticleMassSpread(self, value): def setFactoryParticleMassSpread(self, value):
self.particles.factory.setMassSpread(value) self.particles.factory.setMassSpread(value)
def setFactoryTerminalVelocity(self, value): def setFactoryTerminalVelocity(self, value):
self.particles.factory.setTerminalVelocityBase(value) self.particles.factory.setTerminalVelocityBase(value)
def setFactoryTerminalVelocitySpread(self, value): def setFactoryTerminalVelocitySpread(self, value):
self.particles.factory.setTerminalVelocitySpread(value) self.particles.factory.setTerminalVelocitySpread(value)
# Point Page # # Point Page #
# Z Spin Page # # Z Spin Page #
def setFactoryZSpinInitialAngle(self, angle): def setFactoryZSpinInitialAngle(self, angle):
self.particles.factory.setInitialAngle(angle) self.particles.factory.setInitialAngle(angle)
def setFactoryZSpinInitialAngleSpread(self, spread): def setFactoryZSpinInitialAngleSpread(self, spread):
self.particles.factory.setInitialAngleSpread(spread) self.particles.factory.setInitialAngleSpread(spread)
def setFactoryZSpinFinalAngle(self, angle): def setFactoryZSpinFinalAngle(self, angle):
self.particles.factory.setFinalAngle(angle) self.particles.factory.setFinalAngle(angle)
def setFactoryZSpinFinalAngleSpread(self, spread): def setFactoryZSpinFinalAngleSpread(self, spread):
self.particles.factory.setFinalAngleSpread(spread) self.particles.factory.setFinalAngleSpread(spread)
def setFactoryZSpinAngularVelocity(self, vel): def setFactoryZSpinAngularVelocity(self, vel):
self.particles.factory.setAngularVelocity(vel) self.particles.factory.setAngularVelocity(vel)
def setFactoryZSpinAngularVelocitySpread(self, spread): def setFactoryZSpinAngularVelocitySpread(self, spread):
self.particles.factory.setAngularVelocitySpread(spread) self.particles.factory.setAngularVelocitySpread(spread)
@ -1539,6 +1558,7 @@ class ParticlePanel(AppShell):
self.getWidget('Tangent Ring Emitter', 'Radius Spread').set( self.getWidget('Tangent Ring Emitter', 'Radius Spread').set(
radiusSpread, 0) radiusSpread, 0)
# All # # All #
def setEmissionType(self, newType = None): def setEmissionType(self, newType = None):
if newType: if newType:
type = newType type = newType
@ -1601,57 +1621,76 @@ class ParticlePanel(AppShell):
self.particles.emitter.setMinBound(Point3(point[0], self.particles.emitter.setMinBound(Point3(point[0],
point[1], point[1],
point[2])) point[2]))
def setEmitterBoxPoint2(self, point): def setEmitterBoxPoint2(self, point):
self.particles.emitter.setMaxBound(Point3(point[0], self.particles.emitter.setMaxBound(Point3(point[0],
point[1], point[1],
point[2])) point[2]))
# Disc # # Disc #
def setEmitterDiscRadius(self, radius): def setEmitterDiscRadius(self, radius):
self.particles.emitter.setRadius(radius) self.particles.emitter.setRadius(radius)
def setEmitterDiscInnerAngle(self, angle): def setEmitterDiscInnerAngle(self, angle):
self.particles.emitter.setInnerAngle(angle) self.particles.emitter.setInnerAngle(angle)
def setEmitterDiscInnerVelocity(self, velocity): def setEmitterDiscInnerVelocity(self, velocity):
self.particles.emitter.setInnerMagnitude(velocity) self.particles.emitter.setInnerMagnitude(velocity)
def setEmitterDiscOuterAngle(self, angle): def setEmitterDiscOuterAngle(self, angle):
self.particles.emitter.setOuterAngle(angle) self.particles.emitter.setOuterAngle(angle)
def setEmitterDiscOuterVelocity(self, velocity): def setEmitterDiscOuterVelocity(self, velocity):
self.particles.emitter.setOuterMagnitude(velocity) self.particles.emitter.setOuterMagnitude(velocity)
def toggleEmitterDiscCubicLerping(self): def toggleEmitterDiscCubicLerping(self):
self.particles.emitter.setCubicLerping( self.particles.emitter.setCubicLerping(
self.getVariable('Disc Emitter', 'Cubic Lerping').get()) self.getVariable('Disc Emitter', 'Cubic Lerping').get())
# Line # # Line #
def setEmitterLinePoint1(self, point): def setEmitterLinePoint1(self, point):
self.particles.emitter.setEndpoint1(Point3(point[0], self.particles.emitter.setEndpoint1(Point3(point[0],
point[1], point[1],
point[2])) point[2]))
def setEmitterLinePoint2(self, point): def setEmitterLinePoint2(self, point):
self.particles.emitter.setEndpoint2(Point3(point[0], self.particles.emitter.setEndpoint2(Point3(point[0],
point[1], point[1],
point[2])) point[2]))
# Point # # Point #
def setEmitterPointPosition(self, pos): def setEmitterPointPosition(self, pos):
self.particles.emitter.setLocation(Point3(pos[0], pos[1], pos[2])) self.particles.emitter.setLocation(Point3(pos[0], pos[1], pos[2]))
# Rectangle # # Rectangle #
def setEmitterRectanglePoint1(self, point): def setEmitterRectanglePoint1(self, point):
self.particles.emitter.setMinBound(Point2(point[0], point[1])) self.particles.emitter.setMinBound(Point2(point[0], point[1]))
def setEmitterRectanglePoint2(self, point): def setEmitterRectanglePoint2(self, point):
self.particles.emitter.setMaxBound(Point2(point[0], point[1])) self.particles.emitter.setMaxBound(Point2(point[0], point[1]))
# Ring # # Ring #
def setEmitterRingRadius(self, radius): def setEmitterRingRadius(self, radius):
self.particles.emitter.setRadius(radius) self.particles.emitter.setRadius(radius)
def setEmitterRingRadiusSpread(self, radiusSpread): def setEmitterRingRadiusSpread(self, radiusSpread):
self.particles.emitter.setRadiusSpread(radiusSpread) self.particles.emitter.setRadiusSpread(radiusSpread)
def setEmitterRingLaunchAngle(self, angle): def setEmitterRingLaunchAngle(self, angle):
self.particles.emitter.setAngle(angle) self.particles.emitter.setAngle(angle)
# Sphere surface # # Sphere surface #
def setEmitterSphereSurfaceRadius(self, radius): def setEmitterSphereSurfaceRadius(self, radius):
self.particles.emitter.setRadius(radius) self.particles.emitter.setRadius(radius)
# Sphere volume # # Sphere volume #
def setEmitterSphereVolumeRadius(self, radius): def setEmitterSphereVolumeRadius(self, radius):
self.particles.emitter.setRadius(radius) self.particles.emitter.setRadius(radius)
# Tangent ring # # Tangent ring #
def setEmitterTangentRingRadius(self, radius): def setEmitterTangentRingRadius(self, radius):
self.particles.emitter.setRadius(radius) self.particles.emitter.setRadius(radius)
def setEmitterTangentRingRadiusSpread(self, radiusSpread): def setEmitterTangentRingRadiusSpread(self, radiusSpread):
self.particles.emitter.setRadiusSpread(radiusSpread) self.particles.emitter.setRadiusSpread(radiusSpread)
@ -1849,13 +1888,16 @@ class ParticlePanel(AppShell):
self.particles.renderer.setHeadColor( self.particles.renderer.setHeadColor(
Vec4(color[0]/255.0, color[1]/255.0, Vec4(color[0]/255.0, color[1]/255.0,
color[2]/255.0, color[3]/255.0)) color[2]/255.0, color[3]/255.0))
def setRendererLineTailColor(self, color): def setRendererLineTailColor(self, color):
self.particles.renderer.setTailColor( self.particles.renderer.setTailColor(
Vec4(color[0]/255.0, color[1]/255.0, Vec4(color[0]/255.0, color[1]/255.0,
color[2]/255.0, color[3]/255.0)) color[2]/255.0, color[3]/255.0))
def setRendererLineScaleFactor(self, sf): def setRendererLineScaleFactor(self, sf):
self.particles.renderer.setLineScaleFactor(sf) self.particles.renderer.setLineScaleFactor(sf)
# Geom # # Geom #
def setRendererGeomNode(self, event): def setRendererGeomNode(self, event):
node = None node = None
nodePath = base.loader.loadModel(self.rendererGeomNode.get()) nodePath = base.loader.loadModel(self.rendererGeomNode.get())
@ -1865,16 +1907,20 @@ class ParticlePanel(AppShell):
self.particles.geomReference = self.rendererGeomNode.get() self.particles.geomReference = self.rendererGeomNode.get()
self.particles.renderer.setGeomNode(node) self.particles.renderer.setGeomNode(node)
# Point # # Point #
def setRendererPointSize(self, size): def setRendererPointSize(self, size):
self.particles.renderer.setPointSize(size) self.particles.renderer.setPointSize(size)
def setRendererPointStartColor(self, color): def setRendererPointStartColor(self, color):
self.particles.renderer.setStartColor( self.particles.renderer.setStartColor(
Vec4(color[0]/255.0, color[1]/255.0, Vec4(color[0]/255.0, color[1]/255.0,
color[2]/255.0, color[3]/255.0)) color[2]/255.0, color[3]/255.0))
def setRendererPointEndColor(self, color): def setRendererPointEndColor(self, color):
self.particles.renderer.setEndColor( self.particles.renderer.setEndColor(
Vec4(color[0]/255.0, color[1]/255.0, Vec4(color[0]/255.0, color[1]/255.0,
color[2]/255.0, color[3]/255.0)) color[2]/255.0, color[3]/255.0))
def rendererPointSelectBlendType(self, blendType): def rendererPointSelectBlendType(self, blendType):
if blendType == "PP_ONE_COLOR": if blendType == "PP_ONE_COLOR":
bType = PointParticleRenderer.PPONECOLOR bType = PointParticleRenderer.PPONECOLOR
@ -1883,6 +1929,7 @@ class ParticlePanel(AppShell):
elif blendType == "PP_BLEND_VEL": elif blendType == "PP_BLEND_VEL":
bType = PointParticleRenderer.PPBLENDVEL bType = PointParticleRenderer.PPBLENDVEL
self.particles.renderer.setBlendType(bType) self.particles.renderer.setBlendType(bType)
def rendererPointSelectBlendMethod(self, blendMethod): def rendererPointSelectBlendMethod(self, blendMethod):
if blendMethod == "PP_NO_BLEND": if blendMethod == "PP_NO_BLEND":
bMethod = BaseParticleRenderer.PPNOBLEND bMethod = BaseParticleRenderer.PPNOBLEND
@ -1892,18 +1939,23 @@ class ParticlePanel(AppShell):
bMethod = BaseParticleRenderer.PPBLENDCUBIC bMethod = BaseParticleRenderer.PPBLENDCUBIC
self.particles.renderer.setBlendMethod(bMethod) self.particles.renderer.setBlendMethod(bMethod)
# Sparkle # # Sparkle #
def setRendererSparkleCenterColor(self, color): def setRendererSparkleCenterColor(self, color):
self.particles.renderer.setCenterColor( self.particles.renderer.setCenterColor(
Vec4(color[0]/255.0, color[1]/255.0, Vec4(color[0]/255.0, color[1]/255.0,
color[2]/255.0, color[3]/255.0)) color[2]/255.0, color[3]/255.0))
def setRendererSparkleEdgeColor(self, color): def setRendererSparkleEdgeColor(self, color):
self.particles.renderer.setEdgeColor( self.particles.renderer.setEdgeColor(
Vec4(color[0]/255.0, color[1]/255.0, Vec4(color[0]/255.0, color[1]/255.0,
color[2]/255.0, color[3]/255.0)) color[2]/255.0, color[3]/255.0))
def setRendererSparkleBirthRadius(self, radius): def setRendererSparkleBirthRadius(self, radius):
self.particles.renderer.setBirthRadius(radius) self.particles.renderer.setBirthRadius(radius)
def setRendererSparkleDeathRadius(self, radius): def setRendererSparkleDeathRadius(self, radius):
self.particles.renderer.setDeathRadius(radius) self.particles.renderer.setDeathRadius(radius)
def setRendererSparkleLifeScale(self, lifeScaleMethod): def setRendererSparkleLifeScale(self, lifeScaleMethod):
if lifeScaleMethod == 'SP_NO_SCALE': if lifeScaleMethod == 'SP_NO_SCALE':
lScale = SparkleParticleRenderer.SPNOSCALE lScale = SparkleParticleRenderer.SPNOSCALE
@ -1911,6 +1963,7 @@ class ParticlePanel(AppShell):
lScale = SparkleParticleRenderer.SPSCALE lScale = SparkleParticleRenderer.SPSCALE
self.particles.renderer.setLifeScale(lScale) self.particles.renderer.setLifeScale(lScale)
# Sprite # # Sprite #
def setSpriteSourceType(self): def setSpriteSourceType(self):
if self.rendererSpriteSourceType.get() == 0: if self.rendererSpriteSourceType.get() == 0:
self.rendererSpriteTextureEntry['state'] = 'normal' self.rendererSpriteTextureEntry['state'] = 'normal'
@ -1929,9 +1982,11 @@ class ParticlePanel(AppShell):
def setRendererSpriteAnimationFrameRate(self, rate): def setRendererSpriteAnimationFrameRate(self, rate):
self.particles.renderer.setAnimateFramesRate(rate) self.particles.renderer.setAnimateFramesRate(rate)
def setRendererSpriteAnimationEnable(self): def setRendererSpriteAnimationEnable(self):
self.particles.renderer.setAnimateFramesEnable( self.particles.renderer.setAnimateFramesEnable(
self.getVariable('Sprite Renderer','Enable Animation').get()) self.getVariable('Sprite Renderer','Enable Animation').get())
def addRendererSpriteAnimationTexture(self): def addRendererSpriteAnimationTexture(self):
ren = self.particles.getRenderer() ren = self.particles.getRenderer()
parent = self.rendererSpriteAnimationFrame parent = self.rendererSpriteAnimationFrame
@ -1953,6 +2008,7 @@ class ParticlePanel(AppShell):
self.rendererSpriteAnimationWidgetList.append( self.rendererSpriteAnimationWidgetList.append(
self.createSpriteAnimationTextureWidget(parent, anim, repr(frameNum))) self.createSpriteAnimationTextureWidget(parent, anim, repr(frameNum)))
parent.pack(fill=tk.BOTH, expand=1) parent.pack(fill=tk.BOTH, expand=1)
def addRendererSpriteAnimationFromNode(self): def addRendererSpriteAnimationFromNode(self):
ren = self.particles.getRenderer() ren = self.particles.getRenderer()
parent = self.rendererSpriteAnimationFrame parent = self.rendererSpriteAnimationFrame
@ -1978,9 +2034,11 @@ class ParticlePanel(AppShell):
def toggleRendererSpriteXScale(self): def toggleRendererSpriteXScale(self):
self.particles.renderer.setXScaleFlag( self.particles.renderer.setXScaleFlag(
self.getVariable('Sprite Renderer', 'X Scale').get()) self.getVariable('Sprite Renderer', 'X Scale').get())
def toggleRendererSpriteYScale(self): def toggleRendererSpriteYScale(self):
self.particles.renderer.setYScaleFlag( self.particles.renderer.setYScaleFlag(
self.getVariable('Sprite Renderer', 'Y Scale').get()) self.getVariable('Sprite Renderer', 'Y Scale').get())
def toggleRendererSpriteAnimAngle(self): def toggleRendererSpriteAnimAngle(self):
self.particles.renderer.setAnimAngleFlag( self.particles.renderer.setAnimAngleFlag(
self.getVariable('Sprite Renderer', 'Anim Angle').get()) self.getVariable('Sprite Renderer', 'Anim Angle').get())
@ -1991,14 +2049,19 @@ class ParticlePanel(AppShell):
def setRendererSpriteInitialXScale(self, xScale): def setRendererSpriteInitialXScale(self, xScale):
self.particles.renderer.setInitialXScale(xScale) self.particles.renderer.setInitialXScale(xScale)
def setRendererSpriteFinalXScale(self, xScale): def setRendererSpriteFinalXScale(self, xScale):
self.particles.renderer.setFinalXScale(xScale) self.particles.renderer.setFinalXScale(xScale)
def setRendererSpriteInitialYScale(self, yScale): def setRendererSpriteInitialYScale(self, yScale):
self.particles.renderer.setInitialYScale(yScale) self.particles.renderer.setInitialYScale(yScale)
def setRendererSpriteFinalYScale(self, yScale): def setRendererSpriteFinalYScale(self, yScale):
self.particles.renderer.setFinalYScale(yScale) self.particles.renderer.setFinalYScale(yScale)
def setRendererSpriteNonAnimatedTheta(self, theta): def setRendererSpriteNonAnimatedTheta(self, theta):
self.particles.renderer.setNonanimatedTheta(theta) self.particles.renderer.setNonanimatedTheta(theta)
def setRendererSpriteBlendMethod(self, blendMethod): def setRendererSpriteBlendMethod(self, blendMethod):
if blendMethod == 'PP_NO_BLEND': if blendMethod == 'PP_NO_BLEND':
bMethod = BaseParticleRenderer.PPNOBLEND bMethod = BaseParticleRenderer.PPNOBLEND
@ -2008,9 +2071,11 @@ class ParticlePanel(AppShell):
bMethod = BaseParticleRenderer.PPBLENDCUBIC bMethod = BaseParticleRenderer.PPBLENDCUBIC
else: else:
bMethod = BaseParticleRenderer.PPNOBLEND bMethod = BaseParticleRenderer.PPNOBLEND
def toggleRendererSpriteAlphaDisable(self): def toggleRendererSpriteAlphaDisable(self):
self.particles.renderer.setAlphaDisable( self.particles.renderer.setAlphaDisable(
self.getVariable('Sprite Renderer', 'Alpha Disable').get()) self.getVariable('Sprite Renderer', 'Alpha Disable').get())
def setRendererColorBlendAttrib(self, rendererName, blendMethodStr, incomingOperandStr, fbufferOperandStr): def setRendererColorBlendAttrib(self, rendererName, blendMethodStr, incomingOperandStr, fbufferOperandStr):
self.particles.getRenderer().setColorBlendMode(getattr(ColorBlendAttrib, blendMethodStr), self.particles.getRenderer().setColorBlendMode(getattr(ColorBlendAttrib, blendMethodStr),
getattr(ColorBlendAttrib, incomingOperandStr), getattr(ColorBlendAttrib, incomingOperandStr),
@ -2024,48 +2089,56 @@ class ParticlePanel(AppShell):
self.getWidget(rendererName,'Fbuffer Op.').pack_forget() self.getWidget(rendererName,'Fbuffer Op.').pack_forget()
self.updateRendererWidgets() self.updateRendererWidgets()
def setRendererSpriteColorBlendMethod(self, blendMethod): def setRendererSpriteColorBlendMethod(self, blendMethod):
blendMethodStr = blendMethod blendMethodStr = blendMethod
incomingOperandStr = self.getVariable('Sprite Renderer','Incoming Op.').get() incomingOperandStr = self.getVariable('Sprite Renderer','Incoming Op.').get()
fbufferOperandStr = self.getVariable('Sprite Renderer','Fbuffer Op.').get() fbufferOperandStr = self.getVariable('Sprite Renderer','Fbuffer Op.').get()
self.setRendererColorBlendAttrib('Sprite Renderer', blendMethodStr, incomingOperandStr, fbufferOperandStr) self.setRendererColorBlendAttrib('Sprite Renderer', blendMethodStr, incomingOperandStr, fbufferOperandStr)
def setRendererSpriteColorBlendIncomingOperand(self, operand): def setRendererSpriteColorBlendIncomingOperand(self, operand):
blendMethodStr = self.getVariable('Sprite Renderer','Color Blend').get() blendMethodStr = self.getVariable('Sprite Renderer','Color Blend').get()
incomingOperandStr = operand incomingOperandStr = operand
fbufferOperandStr = self.getVariable('Sprite Renderer','Fbuffer Op.').get() fbufferOperandStr = self.getVariable('Sprite Renderer','Fbuffer Op.').get()
self.setRendererColorBlendAttrib('Sprite Renderer', blendMethodStr, incomingOperandStr, fbufferOperandStr) self.setRendererColorBlendAttrib('Sprite Renderer', blendMethodStr, incomingOperandStr, fbufferOperandStr)
def setRendererSpriteColorBlendFbufferOperand(self, operand): def setRendererSpriteColorBlendFbufferOperand(self, operand):
blendMethodStr = self.getVariable('Sprite Renderer','Color Blend').get() blendMethodStr = self.getVariable('Sprite Renderer','Color Blend').get()
incomingOperandStr = self.getVariable('Sprite Renderer','Incoming Op.').get() incomingOperandStr = self.getVariable('Sprite Renderer','Incoming Op.').get()
fbufferOperandStr = operand fbufferOperandStr = operand
self.setRendererColorBlendAttrib('Sprite Renderer', blendMethodStr, incomingOperandStr, fbufferOperandStr) self.setRendererColorBlendAttrib('Sprite Renderer', blendMethodStr, incomingOperandStr, fbufferOperandStr)
# GeomParticleRenderer Functionality # GeomParticleRenderer Functionality
def toggleRendererGeomXScale(self): def toggleRendererGeomXScale(self):
self.particles.renderer.setXScaleFlag( self.particles.renderer.setXScaleFlag(
self.getVariable('Geom Renderer', 'X Scale').get()) self.getVariable('Geom Renderer', 'X Scale').get())
def toggleRendererGeomYScale(self): def toggleRendererGeomYScale(self):
self.particles.renderer.setYScaleFlag( self.particles.renderer.setYScaleFlag(
self.getVariable('Geom Renderer', 'Y Scale').get()) self.getVariable('Geom Renderer', 'Y Scale').get())
def toggleRendererGeomZScale(self): def toggleRendererGeomZScale(self):
self.particles.renderer.setZScaleFlag( self.particles.renderer.setZScaleFlag(
self.getVariable('Geom Renderer', 'Z Scale').get()) self.getVariable('Geom Renderer', 'Z Scale').get())
def setRendererGeomInitialXScale(self, xScale): def setRendererGeomInitialXScale(self, xScale):
self.particles.renderer.setInitialXScale(xScale) self.particles.renderer.setInitialXScale(xScale)
def setRendererGeomFinalXScale(self, xScale): def setRendererGeomFinalXScale(self, xScale):
self.particles.renderer.setFinalXScale(xScale) self.particles.renderer.setFinalXScale(xScale)
def setRendererGeomInitialYScale(self, yScale): def setRendererGeomInitialYScale(self, yScale):
self.particles.renderer.setInitialYScale(yScale) self.particles.renderer.setInitialYScale(yScale)
def setRendererGeomFinalYScale(self, yScale): def setRendererGeomFinalYScale(self, yScale):
self.particles.renderer.setFinalYScale(yScale) self.particles.renderer.setFinalYScale(yScale)
def setRendererGeomInitialZScale(self, zScale): def setRendererGeomInitialZScale(self, zScale):
self.particles.renderer.setInitialZScale(zScale) self.particles.renderer.setInitialZScale(zScale)
def setRendererGeomFinalZScale(self, zScale): def setRendererGeomFinalZScale(self, zScale):
self.particles.renderer.setFinalZScale(zScale) self.particles.renderer.setFinalZScale(zScale)
@ -2087,7 +2160,6 @@ class ParticlePanel(AppShell):
fbufferOperandStr = operand fbufferOperandStr = operand
self.setRendererColorBlendAttrib('Geom Renderer', blendMethodStr, incomingOperandStr, fbufferOperandStr) self.setRendererColorBlendAttrib('Geom Renderer', blendMethodStr, incomingOperandStr, fbufferOperandStr)
def addConstantInterpolationSegment(self, id = None): def addConstantInterpolationSegment(self, id = None):
ren = self.particles.getRenderer() ren = self.particles.getRenderer()
cim = ren.getColorInterpolationManager() cim = ren.getColorInterpolationManager()
@ -2187,17 +2259,22 @@ class ParticlePanel(AppShell):
def createInterpolationSegmentFrame(self, parent, segName, seg): def createInterpolationSegmentFrame(self, parent, segName, seg):
frame = tk.Frame(parent, relief = tk.RAISED, borderwidth = 2) frame = tk.Frame(parent, relief = tk.RAISED, borderwidth = 2)
lFrame = tk.Frame(frame, relief = tk.FLAT) lFrame = tk.Frame(frame, relief = tk.FLAT)
def removeInterpolationSegmentFrame(s = self, seg = seg, fr = frame): def removeInterpolationSegmentFrame(s = self, seg = seg, fr = frame):
s.particles.getRenderer().getColorInterpolationManager().clearSegment(seg.getId()) s.particles.getRenderer().getColorInterpolationManager().clearSegment(seg.getId())
fr.pack_forget() fr.pack_forget()
def setSegEnabled(s=self, n=segName): def setSegEnabled(s=self, n=segName):
enabled = s.getVariable('Sprite Renderer', n+' Enabled') enabled = s.getVariable('Sprite Renderer', n+' Enabled')
seg.setEnabled(enabled.get()) seg.setEnabled(enabled.get())
def setIsModulated(s=self, n=segName): def setIsModulated(s=self, n=segName):
modulated = s.getVariable('Sprite Renderer', n+' isModulated') modulated = s.getVariable('Sprite Renderer', n+' isModulated')
seg.setIsModulated(modulated.get()) seg.setIsModulated(modulated.get())
def setSegBegin(time): def setSegBegin(time):
seg.setTimeBegin(time) seg.setTimeBegin(time)
def setSegEnd(time): def setSegEnd(time):
seg.setTimeEnd(time) seg.setTimeEnd(time)
tk.Button(lFrame, text = 'X', tk.Button(lFrame, text = 'X',
@ -2236,6 +2313,7 @@ class ParticlePanel(AppShell):
def createConstantInterpolationSegmentWidget(self, parent, segName, segment): def createConstantInterpolationSegmentWidget(self, parent, segName, segment):
fun = segment.getFunction() fun = segment.getFunction()
def setSegColorA(color): def setSegColorA(color):
fun.setColorA( fun.setColorA(
Vec4(color[0]/255.0, color[1]/255.0, Vec4(color[0]/255.0, color[1]/255.0,
@ -2255,10 +2333,12 @@ class ParticlePanel(AppShell):
def createLinearInterpolationSegmentWidget(self, parent, segName, segment): def createLinearInterpolationSegmentWidget(self, parent, segName, segment):
fun = segment.getFunction() fun = segment.getFunction()
def setSegColorA(color): def setSegColorA(color):
fun.setColorA( fun.setColorA(
Vec4(color[0]/255.0, color[1]/255.0, Vec4(color[0]/255.0, color[1]/255.0,
color[2]/255.0, color[3]/255.0)) color[2]/255.0, color[3]/255.0))
def setSegColorB(color): def setSegColorB(color):
fun.setColorB( fun.setColorB(
Vec4(color[0]/255.0, color[1]/255.0, Vec4(color[0]/255.0, color[1]/255.0,
@ -2284,16 +2364,20 @@ class ParticlePanel(AppShell):
def createStepwaveInterpolationSegmentWidget(self, parent, segName, segment): def createStepwaveInterpolationSegmentWidget(self, parent, segName, segment):
fun = segment.getFunction() fun = segment.getFunction()
def setColorA(color): def setColorA(color):
fun.setColorA( fun.setColorA(
Vec4(color[0]/255.0, color[1]/255.0, Vec4(color[0]/255.0, color[1]/255.0,
color[2]/255.0, color[3]/255.0)) color[2]/255.0, color[3]/255.0))
def setColorB(color): def setColorB(color):
fun.setColorB( fun.setColorB(
Vec4(color[0]/255.0, color[1]/255.0, Vec4(color[0]/255.0, color[1]/255.0,
color[2]/255.0, color[3]/255.0)) color[2]/255.0, color[3]/255.0))
def setWidthA(width): def setWidthA(width):
fun.setWidthA(width) fun.setWidthA(width)
def setWidthB(width): def setWidthB(width):
fun.setWidthB(width) fun.setWidthB(width)
@ -2327,14 +2411,17 @@ class ParticlePanel(AppShell):
def createSinusoidInterpolationSegmentWidget(self, parent, segName, segment): def createSinusoidInterpolationSegmentWidget(self, parent, segName, segment):
fun = segment.getFunction() fun = segment.getFunction()
def setColorA(color): def setColorA(color):
fun.setColorA( fun.setColorA(
Vec4(color[0]/255.0, color[1]/255.0, Vec4(color[0]/255.0, color[1]/255.0,
color[2]/255.0, color[3]/255.0)) color[2]/255.0, color[3]/255.0))
def setColorB(color): def setColorB(color):
fun.setColorB( fun.setColorB(
Vec4(color[0]/255.0, color[1]/255.0, Vec4(color[0]/255.0, color[1]/255.0,
color[2]/255.0, color[3]/255.0)) color[2]/255.0, color[3]/255.0))
def setPeriod(period): def setPeriod(period):
fun.setPeriod(period) fun.setPeriod(period)
@ -2543,18 +2630,25 @@ class ParticlePanel(AppShell):
def addLinearVectorForce(self): def addLinearVectorForce(self):
self.addForce(LinearVectorForce()) self.addForce(LinearVectorForce())
def addLinearFrictionForce(self): def addLinearFrictionForce(self):
self.addForce(LinearFrictionForce()) self.addForce(LinearFrictionForce())
def addLinearJitterForce(self): def addLinearJitterForce(self):
self.addForce(LinearJitterForce()) self.addForce(LinearJitterForce())
def addLinearNoiseForce(self): def addLinearNoiseForce(self):
self.addForce(LinearNoiseForce()) self.addForce(LinearNoiseForce())
def addLinearSinkForce(self): def addLinearSinkForce(self):
self.addForce(LinearSinkForce()) self.addForce(LinearSinkForce())
def addLinearSourceForce(self): def addLinearSourceForce(self):
self.addForce(LinearSourceForce()) self.addForce(LinearSourceForce())
def addLinearCylinderVortexForce(self): def addLinearCylinderVortexForce(self):
self.addForce(LinearCylinderVortexForce()) self.addForce(LinearCylinderVortexForce())
def addLinearUserDefinedForce(self): def addLinearUserDefinedForce(self):
self.addForce(LinearUserDefinedForce()) self.addForce(LinearUserDefinedForce())
@ -2650,6 +2744,7 @@ class ParticlePanel(AppShell):
def createForceFrame(self, forcePage, forceName, force): def createForceFrame(self, forcePage, forceName, force):
frame = tk.Frame(forcePage, relief = tk.RAISED, borderwidth = 2) frame = tk.Frame(forcePage, relief = tk.RAISED, borderwidth = 2)
lFrame = tk.Frame(frame, relief = tk.FLAT) lFrame = tk.Frame(frame, relief = tk.FLAT)
def removeForce(s = self, f = force, fr = frame): def removeForce(s = self, f = force, fr = frame):
s.forceGroup.removeForce(f) s.forceGroup.removeForce(f)
fr.pack_forget() fr.pack_forget()
@ -2667,9 +2762,11 @@ class ParticlePanel(AppShell):
def createLinearForceWidgets(self, frame, pageName, forceName, force): def createLinearForceWidgets(self, frame, pageName, forceName, force):
def setAmplitude(amp, f = force): def setAmplitude(amp, f = force):
f.setAmplitude(amp) f.setAmplitude(amp)
def toggleMassDependent(s=self, f=force, p=pageName, n=forceName): def toggleMassDependent(s=self, f=force, p=pageName, n=forceName):
v = s.getVariable(p, n+' Mass Dependent') v = s.getVariable(p, n+' Mass Dependent')
f.setMassDependent(v.get()) f.setMassDependent(v.get())
def setVectorMasks(s=self, f=force, p=pageName, n=forceName): def setVectorMasks(s=self, f=force, p=pageName, n=forceName):
xMask = s.getVariable(p, n+' Mask X').get() xMask = s.getVariable(p, n+' Mask X').get()
yMask = s.getVariable(p, n+' Mask Y').get() yMask = s.getVariable(p, n+' Mask Y').get()
@ -2698,6 +2795,7 @@ class ParticlePanel(AppShell):
def createForceActiveWidget(self, frame, pageName, forceName, force): def createForceActiveWidget(self, frame, pageName, forceName, force):
cbName = forceName + ' Active' cbName = forceName + ' Active'
def toggle(s = self, f = force, p = pageName, n = cbName): def toggle(s = self, f = force, p = pageName, n = cbName):
s.toggleForce(f, p, n) s.toggleForce(f, p, n)
self.createCheckbutton(frame, pageName, cbName, self.createCheckbutton(frame, pageName, cbName,
@ -2741,10 +2839,13 @@ class ParticlePanel(AppShell):
def createLinearCylinderVortexForceWidget(self, forcePage, pageName, def createLinearCylinderVortexForceWidget(self, forcePage, pageName,
count, force): count, force):
forceName = 'Vortex Force-' + repr(count) forceName = 'Vortex Force-' + repr(count)
def setCoef(coef, f = force): def setCoef(coef, f = force):
f.setCoef(coef) f.setCoef(coef)
def setLength(length, f = force): def setLength(length, f = force):
f.setLength(length) f.setLength(length)
def setRadius(radius, f = force): def setRadius(radius, f = force):
f.setRadius(radius) f.setRadius(radius)
frame = self.createForceFrame(forcePage, forceName, force) frame = self.createForceFrame(forcePage, forceName, force)
@ -2775,8 +2876,10 @@ class ParticlePanel(AppShell):
if type == 'FT_ONE_OVER_R_CUBED': if type == 'FT_ONE_OVER_R_CUBED':
#f.setFalloffType(LinearDistanceForce.FTONEOVERRCUBED) #f.setFalloffType(LinearDistanceForce.FTONEOVERRCUBED)
f.setFalloffType(2) f.setFalloffType(2)
def setForceCenter(vec, f = force): def setForceCenter(vec, f = force):
f.setForceCenter(Point3(vec[0], vec[1], vec[2])) f.setForceCenter(Point3(vec[0], vec[1], vec[2]))
def setRadius(radius, f = force): def setRadius(radius, f = force):
f.setRadius(radius) f.setRadius(radius)
forceName = type + ' Force-' + repr(count) forceName = type + ' Force-' + repr(count)
@ -2813,12 +2916,12 @@ class ParticlePanel(AppShell):
###################################################################### ######################################################################
# Create demo in root window for testing. # Create demo in root window for testing.
if __name__ == '__main__': if __name__ == '__main__':
try: try:
base base
except: except NameError:
from direct.showbase.ShowBase import ShowBase from direct.showbase.ShowBase import ShowBase
base = ShowBase() base = ShowBase()

View File

@ -15,6 +15,7 @@ import tkinter as tk
#TODO: Task to monitor pose #TODO: Task to monitor pose
class Placer(AppShell): class Placer(AppShell):
# Override class variables here # Override class variables here
appname = 'Placer Panel' appname = 'Placer Panel'
@ -28,7 +29,7 @@ class Placer(AppShell):
optiondefs = ( optiondefs = (
('title', self.appname, None), ('title', self.appname, None),
('nodePath', base.direct.camera, None), ('nodePath', base.direct.camera, None),
) )
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)
# Call superclass initialization function # Call superclass initialization function
@ -355,8 +356,8 @@ class Placer(AppShell):
self.scaleY['command'] = self.xform self.scaleY['command'] = self.xform
self.scaleZ['command'] = self.xform self.scaleZ['command'] = self.xform
### WIDGET OPERATIONS ### ### WIDGET OPERATIONS ###
def setMovementMode(self, movementMode): def setMovementMode(self, movementMode):
# Set prefix # Set prefix
namePrefix = '' namePrefix = ''
@ -407,7 +408,7 @@ class Placer(AppShell):
else: else:
# Good eval but not a node path, give up # Good eval but not a node path, give up
nodePath = None nodePath = None
except: except Exception:
# Bogus eval # Bogus eval
nodePath = None nodePath = None
# Clear bogus entry from listbox # Clear bogus entry from listbox
@ -464,7 +465,7 @@ class Placer(AppShell):
else: else:
# Good eval but not a node path, give up # Good eval but not a node path, give up
nodePath = None nodePath = None
except: except Exception:
# Bogus eval # Bogus eval
nodePath = None nodePath = None
# Clear bogus entry from listbox # Clear bogus entry from listbox
@ -782,11 +783,13 @@ class Placer(AppShell):
self.orbitFromCS.removeNode() self.orbitFromCS.removeNode()
self.orbitToCS.removeNode() self.orbitToCS.removeNode()
def place(nodePath): def place(nodePath):
return Placer(nodePath = nodePath) return Placer(nodePath = nodePath)
###################################################################### ######################################################################
# Create demo in root window for testing. # Create demo in root window for testing.
if __name__ == '__main__': if __name__ == '__main__':
root = Pmw.initialise() root = Pmw.initialise()

View File

@ -21,7 +21,7 @@ class TaskManagerPanel(AppShell):
INITOPT = Pmw.INITOPT INITOPT = Pmw.INITOPT
optiondefs = ( optiondefs = (
('title', self.appname, None), ('title', self.appname, None),
) )
self.defineoptions(kw, optiondefs) self.defineoptions(kw, optiondefs)
self.taskMgr = taskMgr self.taskMgr = taskMgr
@ -38,10 +38,10 @@ class TaskManagerPanel(AppShell):
self.taskMgrWidget = TaskManagerWidget( self.taskMgrWidget = TaskManagerWidget(
self.interior(), self.taskMgr) self.interior(), self.taskMgr)
def onDestroy(self, event): def onDestroy(self, event):
self.taskMgrWidget.onDestroy() self.taskMgrWidget.onDestroy()
class TaskManagerWidget(DirectObject): class TaskManagerWidget(DirectObject):
""" """
TaskManagerWidget class: this class contains methods for creating TaskManagerWidget class: this class contains methods for creating

Some files were not shown because too many files have changed in this diff Show More