From 37b5c9ad9eff17616d3c85648cd8494b02cf7bb9 Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 22 Feb 2023 11:42:13 +0100 Subject: [PATCH] direct: More code style changes --- .pylintrc | 11 +- direct/src/cluster/ClusterClient.py | 28 +-- direct/src/cluster/ClusterConfig.py | 24 +-- direct/src/cluster/ClusterServer.py | 12 +- direct/src/controls/ControlManager.py | 7 +- direct/src/controls/InputState.py | 17 +- direct/src/controls/PhysicsWalker.py | 3 +- direct/src/directdevices/DirectJoybox.py | 52 ++--- direct/src/directnotify/DirectNotify.py | 4 +- direct/src/directscripts/extract_docs.py | 7 +- direct/src/directtools/DirectCameraControl.py | 12 +- direct/src/directtools/DirectGeometry.py | 11 +- direct/src/directtools/DirectManipulation.py | 16 +- direct/src/directtools/DirectSelection.py | 16 +- direct/src/directtools/DirectSession.py | 11 +- direct/src/directutil/Mopath.py | 13 +- direct/src/dist/FreezeTool.py | 117 +++++----- direct/src/dist/pefile.py | 6 +- .../src/distributed/ClientRepositoryBase.py | 18 +- .../src/distributed/ConnectionRepository.py | 6 +- direct/src/distributed/DistributedObject.py | 5 +- .../src/distributed/DistributedSmoothNode.py | 31 ++- .../distributed/DistributedSmoothNodeBase.py | 5 +- direct/src/distributed/MsgTypes.py | 4 +- direct/src/distributed/MsgTypesCMU.py | 2 +- direct/src/distributed/PyDatagram.py | 2 +- direct/src/distributed/PyDatagramIterator.py | 2 +- direct/src/filter/CommonFilters.py | 2 +- direct/src/fsm/ClassicFSM.py | 4 +- direct/src/fsm/FourState.py | 2 +- direct/src/fsm/FourStateAI.py | 2 +- direct/src/fsm/SampleFSM.py | 2 +- direct/src/gui/DirectButton.py | 4 +- direct/src/gui/DirectCheckBox.py | 4 +- direct/src/gui/DirectCheckButton.py | 5 +- direct/src/gui/DirectDialog.py | 19 +- direct/src/gui/DirectEntry.py | 4 +- direct/src/gui/DirectEntryScroll.py | 4 +- direct/src/gui/DirectGuiBase.py | 7 +- direct/src/gui/DirectLabel.py | 4 +- direct/src/gui/DirectOptionMenu.py | 3 +- direct/src/gui/DirectRadioButton.py | 5 +- direct/src/gui/DirectScrollBar.py | 7 +- direct/src/gui/DirectScrolledFrame.py | 3 +- direct/src/gui/DirectScrolledList.py | 6 +- direct/src/gui/DirectSlider.py | 7 +- direct/src/gui/DirectWaitBar.py | 4 +- direct/src/gui/OnscreenText.py | 3 +- direct/src/interval/IntervalGlobal.py | 4 +- direct/src/interval/LerpInterval.py | 41 +++- direct/src/leveleditor/AnimMgrBase.py | 26 +-- direct/src/leveleditor/CurveAnimUI.py | 73 ++++--- direct/src/leveleditor/CurveEditor.py | 7 +- direct/src/leveleditor/FileMgr.py | 2 +- direct/src/leveleditor/GraphEditorUI.py | 50 ++--- direct/src/leveleditor/LayerEditorUI.py | 12 +- direct/src/leveleditor/LevelEditorBase.py | 7 +- direct/src/leveleditor/LevelEditorUIBase.py | 72 ++++--- direct/src/leveleditor/LevelLoaderBase.py | 4 +- direct/src/leveleditor/ObjectMgrBase.py | 28 +-- direct/src/leveleditor/ObjectPalette.py | 3 +- direct/src/leveleditor/ObjectPaletteBase.py | 36 ++-- direct/src/leveleditor/ObjectPropertyUI.py | 50 +++-- direct/src/leveleditor/ProtoObjs.py | 12 +- direct/src/leveleditor/SceneGraphUIBase.py | 4 +- direct/src/leveleditor/testData.py | 2 +- direct/src/motiontrail/MotionTrail.py | 12 +- direct/src/particles/ParticleEffect.py | 2 +- direct/src/showbase/BufferViewer.py | 35 ++- direct/src/showbase/ContainerLeakDetector.py | 68 ++++-- direct/src/showbase/ContainerReport.py | 23 +- direct/src/showbase/DistancePhasedNode.py | 11 +- direct/src/showbase/ExceptionVarDump.py | 13 +- direct/src/showbase/Finder.py | 20 +- direct/src/showbase/GarbageReport.py | 12 +- direct/src/showbase/LeakDetectors.py | 16 +- direct/src/showbase/Loader.py | 8 +- direct/src/showbase/Messenger.py | 2 +- direct/src/showbase/MessengerLeakDetector.py | 9 +- direct/src/showbase/ObjectPool.py | 2 +- direct/src/showbase/OnScreenDebug.py | 2 +- direct/src/showbase/PythonUtil.py | 201 ++++++++++++++++-- direct/src/showbase/RandomNumGen.py | 5 +- direct/src/showbase/ReferrerSearch.py | 4 +- direct/src/showbase/ShowBase.py | 9 +- direct/src/showbase/Transitions.py | 11 +- direct/src/showbase/VFSImporter.py | 8 +- direct/src/showutil/BuildGeometry.py | 11 +- direct/src/stdpy/file.py | 10 +- direct/src/stdpy/thread.py | 14 +- direct/src/stdpy/threading.py | 27 ++- direct/src/task/Task.py | 49 ++++- direct/src/tkpanels/AnimPanel.py | 11 +- direct/src/tkpanels/DirectSessionPanel.py | 10 +- direct/src/tkpanels/FSMInspector.py | 6 +- direct/src/tkpanels/Inspector.py | 28 ++- direct/src/tkpanels/MopathRecorder.py | 8 +- direct/src/tkpanels/ParticlePanel.py | 137 ++++++++++-- direct/src/tkpanels/Placer.py | 11 +- direct/src/tkpanels/TaskManagerPanel.py | 4 +- direct/src/tkwidgets/AppShell.py | 13 +- direct/src/tkwidgets/Dial.py | 26 +-- direct/src/tkwidgets/EntryScale.py | 49 ++--- direct/src/tkwidgets/Floater.py | 7 +- direct/src/tkwidgets/SceneGraphExplorer.py | 5 +- direct/src/tkwidgets/Slider.py | 9 +- direct/src/tkwidgets/Valuator.py | 40 ++-- direct/src/tkwidgets/VectorWidgets.py | 16 +- .../src/tkwidgets/WidgetPropertiesDialog.py | 26 +-- direct/src/wxwidgets/WxPandaShell.py | 12 +- direct/src/wxwidgets/WxPandaWindow.py | 84 ++++---- direct/src/wxwidgets/WxSlider.py | 25 +-- 112 files changed, 1312 insertions(+), 775 deletions(-) diff --git a/.pylintrc b/.pylintrc index 0b04d46663..d0c95ee5a8 100644 --- a/.pylintrc +++ b/.pylintrc @@ -493,7 +493,8 @@ disable=raw-checker-failed, using-constant-test, wrong-import-order, wrong-import-position, - not-callable + not-callable, + wildcard-import # 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 @@ -615,6 +616,7 @@ contextmanager-decorators=contextlib.contextmanager # expressions are accepted. generated-members=base.cr, base.le, + base.localAvatar, Pmw.AboutDialog, Pmw.Balloon, Pmw.ButtonBox, @@ -629,8 +631,10 @@ generated-members=base.cr, Pmw.MenuBar, Pmw.MessageBar, Pmw.NoteBook, + Pmw.OK, Pmw.OptionMenu, Pmw.OptionMenu, + Pmw.PARTIAL, Pmw.PanedWidget, Pmw.ScrolledCanvas, Pmw.ScrolledFrame, @@ -640,8 +644,10 @@ generated-members=base.cr, Pmw.aboutcopyright, Pmw.aboutversion, Pmw.forwardmethods, + Pmw.integervalidator, Pmw.popgrab, Pmw.pushgrab, + Pmw.realvalidator, Pmw.setgeometryanddeiconify # Tells whether to warn about missing members when the owner of the attribute @@ -699,7 +705,8 @@ additional-builtins=base, cluster, launcher, taskMgr, - localAvatar + localAvatar, + game # Tells whether unused global variables should be treated as a violation. allow-global-unused-variables=yes diff --git a/direct/src/cluster/ClusterClient.py b/direct/src/cluster/ClusterClient.py index 80e57c16a6..fac896f1e4 100644 --- a/direct/src/cluster/ClusterClient.py +++ b/direct/src/cluster/ClusterClient.py @@ -113,7 +113,6 @@ class ClusterClient(DirectObject.DirectObject): self.notify.debug('post startMoveCam') self.startMoveSelectedTask() - def startReaderPollTask(self): """ Task to handle datagrams from server """ # Run this task just after the listener poll task @@ -130,7 +129,6 @@ class ClusterClient(DirectObject.DirectObject): return Task.cont - def startControlObjectTask(self): self.notify.debug("moving control objects") taskMgr.add(self.controlObjectTask,"controlObjectTask",50) @@ -152,7 +150,6 @@ class ClusterClient(DirectObject.DirectObject): self.notify.debug('adding move cam') taskMgr.add(self.moveCameraTask, "moveCamTask", 49) - def controlObjectTask(self, task): for pair in self.sortedControlMappings: object = pair[1] @@ -171,8 +168,6 @@ class ClusterClient(DirectObject.DirectObject): for server in serverList: self.serverList[server].sendNamedMovementDone() - - def redoSortedPriorities(self): self.sortedControlMappings = [] for key in self.controlMappings: @@ -194,7 +189,6 @@ class ClusterClient(DirectObject.DirectObject): for server in serverList: self.serverList[server].sendMoveNamedObject(xyz,hpr,scale,color,hidden,object) - def moveCameraTask(self, task): self.moveCamera( base.camera.getPos(render), @@ -221,7 +215,6 @@ class ClusterClient(DirectObject.DirectObject): server.sendMoveSelected(xyz, hpr, scale) return Task.cont - def addNamedObjectMapping(self, object, name, hasColor = True): if name not in self.objectMappings: self.objectMappings[name] = object @@ -233,7 +226,6 @@ class ClusterClient(DirectObject.DirectObject): if name in self.objectMappings: self.objectMappings.pop(name) - def addControlMapping(self, objectName, controlledName, serverList = None, offset = None, priority = 0): if objectName not in self.controlMappings: @@ -278,7 +270,6 @@ class ClusterClient(DirectObject.DirectObject): self.controlPriorities.pop(name) self.redoSortedPriorities() - def getNodePathFindCmd(self, nodePath): pathString = repr(nodePath) index = pathString.find('/') @@ -298,7 +289,6 @@ class ClusterClient(DirectObject.DirectObject): else: return pathString - def addObjectTag(self,object,selectFunction,deselectFunction,selectArgs,deselectArgs): newTag = {} newTag["selectFunction"] = selectFunction @@ -307,12 +297,10 @@ class ClusterClient(DirectObject.DirectObject): newTag["deselectArgs"] = deselectArgs self.taggedObjects[object] = newTag - def removeObjectTag(self,object): self.taggedObjects.pop(object) - def selectNodePath(self, nodePath): name = self.getNodePathName(nodePath) if name in self.taggedObjects: @@ -325,7 +313,6 @@ class ClusterClient(DirectObject.DirectObject): else: self(self.getNodePathFindCmd(nodePath) + '.select()', 0) - def deselectNodePath(self, nodePath): name = self.getNodePathName(nodePath) if name in self.taggedObjects: @@ -363,7 +350,6 @@ class ClusterClient(DirectObject.DirectObject): # Execute locally exec(commandString, __builtins__) - def handleDatagram(self,dgi,type,server): if type == CLUSTER_NONE: pass @@ -388,7 +374,6 @@ class ClusterClient(DirectObject.DirectObject): # clear the queue self.serverQueues[server] = [] - def handleNamedMovement(self, data): """ Update cameraJig position to reflect latest position """ @@ -408,7 +393,6 @@ class ClusterClient(DirectObject.DirectObject): else: self.notify.debug("recieved unknown named object command: "+name) - def exit(self): # Execute remotely for server in self.serverList: @@ -475,8 +459,6 @@ class DisplayConnection: self.qcr.addConnection(self.tcpConn) self.cw=ConnectionWriter(qcm, 0) - - def poll(self): """ Non blocking task to read all available datagrams """ dataGrams = [] @@ -491,9 +473,6 @@ class DisplayConnection: return dataGrams - - - def sendCamOffset(self, xyz, hpr): ClusterClient.notify.debug("send cam offset...") ClusterClient.notify.debug(("packet %d xyz, hpr=%f %f %f %f %f %f" % @@ -509,12 +488,11 @@ class DisplayConnection: (" fl, fs, fo=%0.3f, (%0.3f, %0.3f), (%0.3f, %0.3f)" % (focalLength, filmSize[0], filmSize[1], filmOffset[0], filmOffset[1]))) - ) + ) datagram = self.msgHandler.makeCamFrustumDatagram( focalLength, filmSize, filmOffset) self.cw.send(datagram, self.tcpConn) - def sendNamedMovementDone(self): datagram = self.msgHandler.makeNamedMovementDone() @@ -584,6 +562,7 @@ class DisplayConnection: frameCount, frameTime, dt) self.cw.send(datagram, self.tcpConn) + class ClusterConfigItem: def __init__(self, serverConfigName, serverName, serverDaemonPort, serverMsgPort): @@ -599,9 +578,11 @@ class ClusterConfigItem: self.focalLength = None self.filmSize = None self.filmOffset = None + def setCamOffset(self, xyz, hpr): self.xyz = xyz self.hpr = hpr + def setCamFrustum(self, focalLength, filmSize, filmOffset): self.fFrustum = 1 self.focalLength = focalLength @@ -689,6 +670,7 @@ def createClusterClient(): class DummyClusterClient(DirectObject.DirectObject): """ Dummy class to handle command strings when not in cluster mode """ notify = DirectNotifyGlobal.directNotify.newCategory("DummyClusterClient") + def __init__(self): pass diff --git a/direct/src/cluster/ClusterConfig.py b/direct/src/cluster/ClusterConfig.py index a71610ea7a..67c638c83a 100644 --- a/direct/src/cluster/ClusterConfig.py +++ b/direct/src/cluster/ClusterConfig.py @@ -26,7 +26,7 @@ ClientConfigs = { 'display mode': 'client', 'pos': Vec3(0), 'hpr': Vec3(0)} - ], + ], 'two-server': [{'display name': 'master', 'display mode': 'client', 'pos': Vec3(0), @@ -35,7 +35,7 @@ ClientConfigs = { 'pos': Vec3(0), 'hpr': Vec3(0) } - ], + ], 'three-server': [{'display name': 'master', 'display mode': 'client', 'pos': Vec3(0), @@ -48,14 +48,14 @@ ClientConfigs = { 'pos': Vec3(0), 'hpr': Vec3(0) } - ], + ], 'mono-cave': [{'display name': 'la', 'pos': Vec3(-0.105, -0.020, 5.000), 'hpr': Vec3(51.213, 0.000, 0.000), 'focal length': 0.809, 'film size': (1.000, 0.831), 'film offset': (0.000, 0.173), - }, + }, {'display name': 'lb', 'display mode': 'client', 'pos': Vec3(-0.105, -0.020, 5.000), @@ -71,7 +71,7 @@ ClientConfigs = { 'film size': (1.000, 0.830), 'film offset': (-0.000, 0.173), }, - ], + ], 'seamless-cave': [{'display name': 'master', 'display mode': 'client', 'pos': Vec3(-0.105, -0.020, 5.000), @@ -79,7 +79,7 @@ ClientConfigs = { 'focal length': 0.815, 'film size': (1.000, 0.831), 'film offset': (0.000, 0.173), - }, + }, {'display name': 'la', 'pos': Vec3(-0.105, -0.020, 5.000), 'hpr': Vec3(51.213, 0.000, 0.000), @@ -122,12 +122,12 @@ ClientConfigs = { 'film size': (1.000, 0.831), 'film offset': (-0.000, 0.173), }, - ], + ], 'ursula': [{'display name': 'master', 'display mode': 'client', 'pos': Vec3(0), 'hpr': Vec3(0), - }, + }, {'display name': 'l', 'pos': Vec3(-.105, 0, 0), 'hpr': Vec3(0, 0, 0), @@ -144,11 +144,11 @@ ClientConfigs = { #'film offset': (-0.105, -2), 'film offset': (-0.105, -1), } - ], + ], 'composite': [{'display name': 'master', 'display mode': 'client', 'pos': Vec3(0), - }, + }, {'display name': 'left', 'pos': Vec3(-0.105, -0.020, 5.000), 'hpr': Vec3(-0.370, 0.000, 0.000), @@ -163,5 +163,5 @@ ClientConfigs = { 'film size': (1.000, 0.831), 'film offset': (0.000, 0.173), } - ], - } + ], +} diff --git a/direct/src/cluster/ClusterServer.py b/direct/src/cluster/ClusterServer.py index 188e3543e0..ba707f17dd 100644 --- a/direct/src/cluster/ClusterServer.py +++ b/direct/src/cluster/ClusterServer.py @@ -40,6 +40,7 @@ import builtins # Also, I'm not sure multiple camera-group configurations are working for the # cluster system. + class ClusterServer(DirectObject.DirectObject): notify = DirectNotifyGlobal.directNotify.newCategory("ClusterServer") MSG_NUM = 2000000 @@ -101,8 +102,6 @@ class ClusterServer(DirectObject.DirectObject): clusterDaemonPort = CLUSTER_DAEMON_PORT self.daemon.serverReady(clusterDaemonClient, clusterDaemonPort) - - def startListenerPollTask(self): # Run this task near the start of frame, sometime after the dataLoop taskMgr.add(self.listenerPollTask, "serverListenerPollTask", -40) @@ -125,7 +124,6 @@ class ClusterServer(DirectObject.DirectObject): self.notify.warning("getNewConnection returned false") return Task.cont - def addNamedObjectMapping(self, object, name, hasColor = True, priority = 0): if name not in self.objectMappings: @@ -138,7 +136,6 @@ class ClusterServer(DirectObject.DirectObject): if name in self.objectMappings: self.objectMappings.pop(name) - def redoSortedPriorities(self): self.sortedControlMappings = [] @@ -148,7 +145,6 @@ class ClusterServer(DirectObject.DirectObject): self.sortedControlMappings.sort() - def addControlMapping(self, objectName, controlledName, offset = None, priority = 0): if objectName not in self.controlMappings: @@ -165,14 +161,12 @@ class ClusterServer(DirectObject.DirectObject): if objectName in self.controlMappings: self.controlOffsets[objectName] = offset - def removeControlMapping(self, name): if name in self.controlMappings: self.controlMappings.pop(name) self.controlPriorities.pop(name) self.redoSortedPriorities() - def startControlObjectTask(self): self.notify.debug("moving control objects") taskMgr.add(self.controlObjectTask,"controlObjectTask",50) @@ -189,7 +183,6 @@ class ClusterServer(DirectObject.DirectObject): self.sendNamedMovementDone() return Task.cont - def sendNamedMovementDone(self): self.notify.debug("named movement done") datagram = self.msgHandler.makeNamedMovementDone() @@ -333,7 +326,6 @@ class ClusterServer(DirectObject.DirectObject): else: self.notify.debug("recieved unknown named object command: "+name) - def handleMessageQueue(self): #print(self.messageQueue) for data in self.messageQueue: @@ -369,5 +361,5 @@ class ClusterServer(DirectObject.DirectObject): command = self.msgHandler.parseCommandStringDatagram(dgi) try: exec(command, __builtins__) - except: + except Exception: pass diff --git a/direct/src/controls/ControlManager.py b/direct/src/controls/ControlManager.py index 18e0fec0f3..d1a752e9e1 100755 --- a/direct/src/controls/ControlManager.py +++ b/direct/src/controls/ControlManager.py @@ -41,8 +41,6 @@ class ControlManager: #self.monitorTask = taskMgr.add(self.monitor, "ControlManager-%s"%(id(self)), priority=-1) self.forceAvJumpToken = None - - if self.passMessagesThrough: # for not breaking toontown ist=self.inputStateTokens 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("turnRight", "arrow_right", inputSource=inputState.ArrowKeys)) - def __str__(self): return 'ControlManager: using \'%s\'' % self.currentControlsName @@ -325,7 +322,7 @@ class ControlManager: self.WASDTurnTokens = ( inputState.watchWithModifiers("turnLeft", "a", inputSource=inputState.WASD), inputState.watchWithModifiers("turnRight", "d", inputSource=inputState.WASD), - ) + ) inputState.set("turnLeft", slideLeftWASDSet, inputSource=inputState.WASD) inputState.set("turnRight", slideRightWASDSet, inputSource=inputState.WASD) @@ -337,7 +334,7 @@ class ControlManager: self.WASDTurnTokens = ( inputState.watchWithModifiers("slideLeft", "a", inputSource=inputState.WASD), inputState.watchWithModifiers("slideRight", "d", inputSource=inputState.WASD), - ) + ) inputState.set("slideLeft", turnLeftWASDSet, inputSource=inputState.WASD) inputState.set("slideRight", turnRightWASDSet, inputSource=inputState.WASD) diff --git a/direct/src/controls/InputState.py b/direct/src/controls/InputState.py index 72939032d6..5510dca7b1 100755 --- a/direct/src/controls/InputState.py +++ b/direct/src/controls/InputState.py @@ -8,36 +8,47 @@ from direct.showbase.MessengerGlobal import messenger class InputStateToken: _SerialGen = SerialNumGen() Inval = 'invalidatedToken' + def __init__(self, inputState): self._id = InputStateToken._SerialGen.next() self._hash = self._id self._inputState = inputState + def release(self): # subclasses will override assert False + def isValid(self): return self._id != InputStateToken.Inval + def invalidate(self): self._id = InputStateToken.Inval + def __hash__(self): return self._hash #snake_case alias: is_valid = isValid + class InputStateWatchToken(InputStateToken, DirectObject.DirectObject): def release(self): self._inputState._ignore(self) self.ignoreAll() + + class InputStateForceToken(InputStateToken): def release(self): self._inputState._unforce(self) + class InputStateTokenGroup: def __init__(self): self._tokens = [] + def addToken(self, token): self._tokens.append(token) + def release(self): for token in self._tokens: token.release() @@ -46,6 +57,7 @@ class InputStateTokenGroup: #snake_case alias: add_token = addToken + class InputState(DirectObject.DirectObject): """ 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. # self.set(name, False, inputSource) - def force(self, name, value, inputSource): """ Force isSet(name) to return 'value'. @@ -213,7 +224,7 @@ class InputState(DirectObject.DirectObject): self.notify.error( "%s is trying to force '%s' to ON, but '%s' is already being forced OFF by %s" % (inputSource, name, name, self._forcingOff[name]) - ) + ) self._forcingOn.setdefault(name, set()) self._forcingOn[name].add(inputSource) else: @@ -221,7 +232,7 @@ class InputState(DirectObject.DirectObject): self.notify.error( "%s is trying to force '%s' to OFF, but '%s' is already being forced ON by %s" % (inputSource, name, name, self._forcingOn[name]) - ) + ) self._forcingOff.setdefault(name, set()) self._forcingOff[name].add(inputSource) return token diff --git a/direct/src/controls/PhysicsWalker.py b/direct/src/controls/PhysicsWalker.py index e7cc907991..4575856922 100755 --- a/direct/src/controls/PhysicsWalker.py +++ b/direct/src/controls/PhysicsWalker.py @@ -55,6 +55,7 @@ import math #import LineStream + class PhysicsWalker(DirectObject.DirectObject): notify = DirectNotifyGlobal.directNotify.newCategory("PhysicsWalker") @@ -546,7 +547,7 @@ class PhysicsWalker(DirectObject.DirectObject): onScreenDebug.add("highMark", "% 10.4f"%(self.highMark,)) #if airborneHeight < 0.1: #contact!=Vec3.zero(): if (airborneHeight > self.avatarRadius*0.5 - or physObject.getVelocity().getZ() > 0.0 + or physObject.getVelocity().getZ() > 0.0 ): # Check stair angles before changing this. # ...the avatar is airborne (maybe a lot or a tiny amount). self.isAirborne = 1 diff --git a/direct/src/directdevices/DirectJoybox.py b/direct/src/directdevices/DirectJoybox.py index 14ca267c5d..2f5026504b 100644 --- a/direct/src/directdevices/DirectJoybox.py +++ b/direct/src/directdevices/DirectJoybox.py @@ -35,6 +35,7 @@ JOYBOX_RANGE = JOYBOX_MAX - JOYBOX_MIN JOYBOX_TREAD_SEPERATION = 1.0 + class DirectJoybox(DirectObject): joyboxCount = 0 xyzMultiplier = 1.0 @@ -87,12 +88,10 @@ class DirectJoybox(DirectObject): # Spawn update task self.enable() - def setHeadingNodePath(self,np): self.headingNP = np - def enable(self): # Kill existing task self.disable() @@ -126,18 +125,25 @@ class DirectJoybox(DirectObject): def getNodePath(self): return self.nodePath + def setRefCS(self, refCS): self.refCS = refCS + def getRefCS(self): return self.refCS + def getEventName(self, index): return self.name + '-button-' + repr(index) + def setXyzMultiplier(self, multiplier): DirectJoybox.xyzMultiplier = multiplier + def getXyzMultiplier(self): return DirectJoybox.xyzMultiplier + def setHprMultiplier(self, multiplier): DirectJoybox.hprMultiplier = multiplier + def getHprMultiplier(self): return DirectJoybox.hprMultiplier @@ -193,6 +199,7 @@ class DirectJoybox(DirectObject): def acceptSwitchModeEvent(self, button = R_UPPER): self.accept(self.getEventName(button), self.switchMode) + def ignoreSwitchModeEvent(self, button = R_UPPER): self.ignore(self.getEventName(button)) @@ -208,7 +215,7 @@ class DirectJoybox(DirectObject): pass def showMode(self, modeText): - def hideText(state, s = self): + def hideText(state, s=self): s.readout.setText('') return Task.done taskMgr.remove(self.name + '-showMode') @@ -220,6 +227,7 @@ class DirectJoybox(DirectObject): def acceptUprightCameraEvent(self, button = L_UPPER): self.accept(self.getEventName(button), base.direct.cameraControl.orbitUprightCam) + def ignoreUprightCameraEvent(self, button = L_UPPER): self.ignore(self.getEventName(button)) @@ -230,29 +238,29 @@ class DirectJoybox(DirectObject): self.showMode(self.modeName) self.enable() - - def setUseHeadingNP(self,enabled): - + def setUseHeadingNP(self, enabled): self.useHeadingNP = enabled - def setRotateInPlace(self,enabled): - + def setRotateInPlace(self, enabled): self.rotateInPlace = enabled def joyboxFly(self): # Do nothing if no nodePath selected if self.nodePath is None: return + hprScale = ((self.aList[L_SLIDE] + 1.0) * 50.0 * DirectJoybox.hprMultiplier) posScale = ((self.aList[R_SLIDE] + 1.0) * 50.0 * DirectJoybox.xyzMultiplier) - def getAxisVal(index, s = self): + + def getAxisVal(index, s=self): try: return s.aList[s.mapping[index]] except IndexError: # If it is a null axis return 0 return 0.0 + x = getAxisVal(0) * self.modifier[0] y = getAxisVal(1) * self.modifier[1] z = getAxisVal(2) * self.modifier[2] @@ -262,13 +270,13 @@ class DirectJoybox(DirectObject): p = getAxisVal(4) * self.modifier[4] r = getAxisVal(5) * self.modifier[5] hpr = Vec3(h, p, r) * (hprScale * self.deltaTime) + # if we are using a heading nodepath, we want # to drive in the direction we are facing, # however, we don't want the z component to change if self.useHeadingNP and self.headingNP is not None: oldZ = pos.getZ() - pos = self.nodePath.getRelativeVector(self.headingNP, - pos) + pos = self.nodePath.getRelativeVector(self.headingNP, pos) pos.setZ(oldZ) # if we are using a heading NP we might want to rotate # in place around that NP @@ -282,7 +290,6 @@ class DirectJoybox(DirectObject): self.nodePath.wrtReparentTo(parent) hpr = Vec3(0,0,0) - self.nodePath.setPosHpr(self.nodePath, pos, hpr) def joeMode(self): @@ -291,25 +298,23 @@ class DirectJoybox(DirectObject): self.modifier = [1, 1, 1, -1, -1, 0] self.setMode(self.joyboxFly, 'Joe Mode') - def basicMode(self): self.mapping = [NULL_AXIS, R_FWD_BACK, NULL_AXIS, R_LEFT_RIGHT, NULL_AXIS, NULL_AXIS] - self.modifier = [0,1,0,-1,0,0] - self.setMode(self.joyboxFly,'Basic Mode') + self.modifier = [0, 1, 0, -1, 0, 0] + self.setMode(self.joyboxFly, 'Basic Mode') def fpsMode(self): self.mapping = [L_LEFT_RIGHT,R_FWD_BACK,L_FWD_BACK, R_LEFT_RIGHT, NULL_AXIS, NULL_AXIS] - self.modifier = [1,1,1,-1,0,0] - self.setMode(self.joyboxFly,'FPS Mode') + self.modifier = [1, 1, 1, -1, 0, 0] + self.setMode(self.joyboxFly, 'FPS Mode') def tankMode(self): - self.setMode(self.tankFly,'Tank Mode') + self.setMode(self.tankFly, 'Tank Mode') def nullMode(self): - self.setMode(self.nullFly,'Null Mode') - + self.setMode(self.nullFly, 'Null Mode') def lucMode(self): self.mapping = [R_LEFT_RIGHT, R_FWD_BACK, L_FWD_BACK, @@ -362,7 +367,6 @@ class DirectJoybox(DirectObject): def spaceMode(self): self.setMode(self.spaceFly, 'Space Mode') - def nullFly(self): return @@ -384,10 +388,6 @@ class DirectJoybox(DirectObject): self.nodePath.setH(self.nodePath,dh) self.nodePath.setY(self.nodePath,dy) - - - - def spaceFly(self): # Do nothing if no nodePath selected if self.nodePath is None: @@ -498,9 +498,9 @@ class DirectJoybox(DirectObject): # Restore the original hpr of the orbiter self.nodePath.setHpr(self.tempCS, 0, 0, 0) - # We need to override the DirectAnalog normalizeChannel to # correct the ranges of the two twist axes of the joybox. + def normalizeChannel(self, chan, minVal = -1, maxVal = 1): try: if chan == L_TWIST or chan == R_TWIST: diff --git a/direct/src/directnotify/DirectNotify.py b/direct/src/directnotify/DirectNotify.py index 97419ac67a..d2e2ba4a3e 100644 --- a/direct/src/directnotify/DirectNotify.py +++ b/direct/src/directnotify/DirectNotify.py @@ -5,6 +5,7 @@ DirectNotify module: this module contains the DirectNotify class from . import Notifier from . import Logger + class DirectNotify: """ DirectNotify class: this class contains methods for creating @@ -15,7 +16,7 @@ class DirectNotify: """ DirectNotify class keeps a dictionary of Notfiers """ - self.__categories = { } + self.__categories = {} # create a default log file self.logger = Logger.Logger() @@ -100,7 +101,6 @@ class DirectNotify: print("DirectNotify: unknown notify level: " + str(level) + " for category: " + str(categoryName)) - def setDconfigLevels(self): for categoryName in self.getCategories(): self.setDconfigLevel(categoryName) diff --git a/direct/src/directscripts/extract_docs.py b/direct/src/directscripts/extract_docs.py index 2b44beff49..8c2271cb31 100644 --- a/direct/src/directscripts/extract_docs.py +++ b/direct/src/directscripts/extract_docs.py @@ -65,6 +65,7 @@ def comment(code): else: return '' + def block_comment(code): code = code.strip() @@ -77,6 +78,7 @@ def block_comment(code): return code + def translateFunctionName(name): if name.startswith("__"): return name @@ -93,6 +95,7 @@ def translateFunctionName(name): new += i[0].upper() + i[1:] return new + def translateTypeName(name, mangle=True): # Equivalent to C++ classNameFromCppName class_name = "" @@ -115,6 +118,7 @@ def translateTypeName(name, mangle=True): return class_name + def translated_type_name(type, scoped=True): while interrogate_type_is_wrapped(type): if interrogate_type_is_const(type): @@ -205,7 +209,7 @@ def processFunction(handle, function, isConstructor = False): def processType(handle, type): 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): print(block_comment(interrogate_type_comment(type)), file=handle) @@ -258,6 +262,7 @@ def processType(handle, type): print("};", file=handle) + def processModule(handle, package): print("Processing module %s" % (package)) print("namespace %s {" % package, file=handle) diff --git a/direct/src/directtools/DirectCameraControl.py b/direct/src/directtools/DirectCameraControl.py index 417583f3a5..59db9bf185 100644 --- a/direct/src/directtools/DirectCameraControl.py +++ b/direct/src/directtools/DirectCameraControl.py @@ -14,6 +14,7 @@ CAM_MOVE_DURATION = 1.2 COA_MARKER_SF = 0.0075 Y_AXIS = Vec3(0, 1, 0) + class DirectCameraControl(DirectObject): notify = DirectNotifyGlobal.directNotify.newCategory('DirectCameraControl') @@ -50,7 +51,7 @@ class DirectCameraControl(DirectObject): ['DIRECT-mouse2Up', self.mouseFlyStop], ['DIRECT-mouse3', self.mouseDollyStart], ['DIRECT-mouse3Up', self.mouseDollyStop], - ] + ] # [gjeon] moved all of the hotkeys to single place for easy remapping ## self.keyEvents = [ @@ -101,7 +102,7 @@ class DirectCameraControl(DirectObject): ['DIRECT-removeManipulateCameraTask', self.removeManipulateCameraTask], ['DIRECT-zoomInCam', self.zoomCam, 0.5, t], ['DIRECT-zoomOutCam', self.zoomCam, -2.0, t], - ] + ] # set this to true to prevent the camera from rolling self.lockRoll = False # NIK - flag to determine whether to use maya camera controls @@ -351,7 +352,7 @@ class DirectCameraControl(DirectObject): else: 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) * state.zoomSF)) hVal = 0.0 @@ -613,7 +614,7 @@ class DirectCameraControl(DirectObject): startColor = Vec4(1, 0, 0, 1), blendType = 'easeInOut'), Func(self.coaMarker.stash) - ) + ) self.coaMarkerColorIval.start() def homeCam(self): @@ -699,7 +700,6 @@ class DirectCameraControl(DirectObject): name = 'manipulateCamera') self.__startManipulateCamera(ival = ival) - def zoomCam(self, zoomFactor, t): self.__stopManipulateCamera() # Record undo point @@ -769,7 +769,6 @@ class DirectCameraControl(DirectObject): name = 'manipulateCamera') self.__startManipulateCamera(ival = ival) - def swingCamAboutWidget(self, degrees, t): # Remove existing camera manipulation task self.__stopManipulateCamera() @@ -834,7 +833,6 @@ class DirectCameraControl(DirectObject): name = 'manipulateCamera') self.__startManipulateCamera(ival = ival) - def moveToFit(self): # How big is the active widget? widgetScale = base.direct.widget.scalingNode.getScale(render) diff --git a/direct/src/directtools/DirectGeometry.py b/direct/src/directtools/DirectGeometry.py index a4c7c61c8f..141d263c40 100644 --- a/direct/src/directtools/DirectGeometry.py +++ b/direct/src/directtools/DirectGeometry.py @@ -18,6 +18,7 @@ from .DirectGlobals import Q_EPSILON, UNIT_VEC, ZERO_VEC from .DirectUtil import CLAMP import math + class LineNodePath(NodePath): def __init__(self, parent = None, name = None, 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 ## 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 offset = planeOrigin - lineOrigin t = offset.dot(normal) / lineDir.dot(normal) hitPt = lineDir * t return hitPt + lineOrigin + def getNearProjectionPoint(nodePath): # Find the position of the projection of the specified node path # on the near plane @@ -158,6 +162,7 @@ def getNearProjectionPoint(nodePath): # Object is coplaner with camera, just return something reasonable return Point3(0, base.direct.dr.near, 0) + def getScreenXY(nodePath): # Where does the node path's projection fall on the near plane nearVec = getNearProjectionPoint(nodePath) @@ -172,6 +177,7 @@ def getScreenXY(nodePath): # Return the resulting value return screenXY + def getCrankAngle(center): # Used to compute current angle of mouse (relative to the coa's # origin) in screen space @@ -179,6 +185,7 @@ def getCrankAngle(center): y = base.direct.dr.mouseY - center[2] return 180 + rad2Deg(math.atan2(y, x)) + def relHpr(nodePath, base, h, p, r): # Compute nodePath2newNodePath relative to base coordinate system # nodePath2base @@ -202,6 +209,8 @@ def relHpr(nodePath, base, h, p, r): nodePath.setHpr(hpr) # Quaternion interpolation + + def qSlerp(startQuat, endQuat, t): startQ = Quat(startQuat) destQuat = Quat(Quat.identQuat()) diff --git a/direct/src/directtools/DirectManipulation.py b/direct/src/directtools/DirectManipulation.py index be56f6da5d..d77a7de7e3 100644 --- a/direct/src/directtools/DirectManipulation.py +++ b/direct/src/directtools/DirectManipulation.py @@ -72,7 +72,7 @@ class DirectManipulationControl(DirectObject): ['DIRECT-widgetScaleDown', self.scaleWidget, 0.5], ['shift-f', self.objectHandles.growToFit], ['i', self.plantSelectedNodePath], - ] + ] self.defaultSkipFlags = DG.SKIP_HIDDEN | DG.SKIP_BACKFACE self.optionalSkipFlags = 0 self.unmovableTagList = [] @@ -192,8 +192,8 @@ class DirectManipulationControl(DirectObject): return Task.done def watchMouseTask(self, state): - if (((abs (state.initX - base.direct.dr.mouseX)) > 0.01) or - ((abs (state.initY - base.direct.dr.mouseY)) > 0.01)): + if (abs(state.initX - base.direct.dr.mouseX) > 0.01 or + abs(state.initY - base.direct.dr.mouseY) > 0.01): taskMgr.remove('manip-move-wait') self.mode = 'move' self.manipulateObject() @@ -221,8 +221,8 @@ class DirectManipulationControl(DirectObject): endX = base.direct.dr.mouseX endY = base.direct.dr.mouseY - if (((abs (endX - startX)) < 0.01) and - ((abs (endY - startY)) < 0.01)): + if (abs(endX - startX) < 0.01 and + abs(endY - startY) < 0.01): return self.marquee = LineNodePath(base.render2d, 'marquee', 0.5, VBase4(.8, .6, .6, 1)) @@ -1056,8 +1056,8 @@ class DirectManipulationControl(DirectObject): self.initScale * (self.objectHandles.getWidgetIntersectPt( self.manipRef, 'y').length() / - self.initScaleMag) - ) + self.initScaleMag) + ) base.direct.widget.setScale(currScale) ## Utility functions ## @@ -1082,6 +1082,7 @@ class DirectManipulationControl(DirectObject): messenger.send('DIRECT_manipulateObjectCleanup', [base.direct.selected.getSelectedAsList()]) + class ObjectHandles(NodePath, DirectObject): def __init__(self, name='objectHandles'): # Initialize the superclass @@ -1754,6 +1755,7 @@ class ObjectHandles(NodePath, DirectObject): return self.hitPt + def drawBox(lines, center, sideLength): l = sideLength * 0.5 lines.moveTo(center[0] + l, center[1] + l, center[2] + l) diff --git a/direct/src/directtools/DirectSelection.py b/direct/src/directtools/DirectSelection.py index 1c6efed7b5..7e61335948 100644 --- a/direct/src/directtools/DirectSelection.py +++ b/direct/src/directtools/DirectSelection.py @@ -26,6 +26,8 @@ COA_ORIGIN = 0 COA_CENTER = 1 # MRM: To do: handle broken node paths in selected and deselected dicts + + class DirectNodePath(NodePath): # A node path augmented with info, bounding box, and utility methods def __init__(self, nodePath, bboxColor=None): @@ -65,6 +67,7 @@ class DirectNodePath(NodePath): def getMax(self): return self.bbox.getMax() + class SelectedNodePaths(DirectObject): def __init__(self): self.reset() @@ -445,7 +448,7 @@ class DirectBoundingBox: 'Max:\t\t%s\n' % self.vecAsString(self.max) + 'Center:\t\t%s\n' % self.vecAsString(self.center) + 'Radius:\t\t%.2f' % self.radius - ) + ) class SelectionQueue(CollisionHandlerQueue): @@ -588,18 +591,18 @@ class SelectionQueue(CollisionHandlerQueue): # Skip if parented to a camera. pass # 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): # Skip if in unpickable list pass - elif base.direct and\ + elif base.direct 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 pass - elif base.direct and\ + elif base.direct 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 pass else: @@ -608,6 +611,7 @@ class SelectionQueue(CollisionHandlerQueue): break return self.getCurrentEntry() + class SelectionRay(SelectionQueue): def __init__(self, parentNP = None): if parentNP is None: diff --git a/direct/src/directtools/DirectSession.py b/direct/src/directtools/DirectSession.py index 3a164820b0..0fddd6fa9b 100644 --- a/direct/src/directtools/DirectSession.py +++ b/direct/src/directtools/DirectSession.py @@ -134,7 +134,6 @@ class DirectSession(DirectObject): for i in range(len(fastrak))[1:]: self.fastrak.append(DirectFastrak.DirectFastrak(fastrak[0] + ':' + fastrak[i])) - self.fControl = 0 self.fAlt = 0 self.fShift = 0 @@ -196,7 +195,7 @@ class DirectSession(DirectObject): ['DIRECT-doWrtReparent', self.doWrtReparent], ['DIRECT-doReparent', self.doReparent], ['DIRECT-doSelect', self.doSelect], - ] + ] if base.wantTk: from direct.tkpanels import Placer @@ -265,7 +264,7 @@ class DirectSession(DirectObject): 'shift-[': ('DIRECT-Undo', 'DIRECT-Undo'), ']': ('DIRECT-Redo', 'DIRECT-Redo'), 'shift-]': ('DIRECT-Redo', 'DIRECT-Redo'), - } + } self.hotKeyMap = { 'c': ('Center Camera', 'DIRECT-centerCamIn'), @@ -293,14 +292,14 @@ class DirectSession(DirectObject): 'shift-a': ('Toggle Vis all', 'DIRECT-toggleVisAll'), 'w': ('Toggle Wireframe', 'DIRECT-toggleWireframe'), 'control-z': ('Undo', 'LE-Undo'), - 'shift-z' : ('Redo', 'LE-Redo'), + 'shift-z': ('Redo', 'LE-Redo'), 'control-d': ('Duplicate', 'LE-Duplicate'), 'control-l': ('Make Live', 'LE-MakeLive'), 'control-n': ('New Scene', 'LE-NewScene'), 'control-s': ('Save Scene', 'LE-SaveScene'), 'control-o': ('Open Scene', 'LE-OpenScene'), 'control-q': ('Quit', 'LE-Quit'), - } + } self.speicalKeyMap = { 'enter': 'DIRECT-enter', @@ -327,7 +326,6 @@ class DirectSession(DirectObject): self.cluster = DummyClusterClient() __builtins__['cluster'] = self.cluster - def addPassThroughKey(self,key): self.passThroughKeys.append(key) @@ -876,6 +874,7 @@ class DirectSession(DirectObject): # If nothing specified, try selected node path nodePath = self.selected.last base.direct.select(nodePath) + def fitTask(state, self = self): self.cameraControl.fitOnWidget() return Task.done diff --git a/direct/src/directutil/Mopath.py b/direct/src/directutil/Mopath.py index 8fce623b71..a42f3bab98 100644 --- a/direct/src/directutil/Mopath.py +++ b/direct/src/directutil/Mopath.py @@ -23,7 +23,7 @@ class Mopath(DirectObject): def __init__(self, name = None, fluid = 1, objectToLoad = None, upVectorNodePath = None, reverseUpVector = False): if name is None: - name = 'mopath%d' % self.nameIndex + name = f'mopath{self.nameIndex}' self.nameIndex = self.nameIndex + 1 self.name = name self.fluid = fluid @@ -38,12 +38,12 @@ class Mopath(DirectObject): self.upVectorNodePath = upVectorNodePath self.reverseUpVector = reverseUpVector self.reset() - if isinstance( objectToLoad, NodePath ): - self.loadNodePath( objectToLoad ) - elif isinstance( objectToLoad, str ): - self.loadFile( objectToLoad ) + if isinstance(objectToLoad, NodePath): + self.loadNodePath(objectToLoad) + elif isinstance(objectToLoad, str): + self.loadFile(objectToLoad) 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): return self.maxT * self.timeScale @@ -70,7 +70,6 @@ class Mopath(DirectObject): else: print('Mopath: no valid curves in nodePath: %s' % nodePath) - def reset(self): self.maxT = 0.0 self.loop = 0 diff --git a/direct/src/dist/FreezeTool.py b/direct/src/dist/FreezeTool.py index df6633acd4..52e4fc1ba5 100644 --- a/direct/src/dist/FreezeTool.py +++ b/direct/src/dist/FreezeTool.py @@ -275,32 +275,32 @@ class CompilationEnvironment: def compileExe(self, filename, basename, extraLink=[]): compile = self.compileObjExe % dict({ - 'python' : self.Python, - 'MSVC' : self.MSVC, - 'PSDK' : self.PSDK, - 'suffix64' : self.suffix64, - 'MD' : self.MD, - 'pythonIPath' : self.PythonIPath, - 'pythonVersion' : self.PythonVersion, - 'arch' : self.arch, - 'filename' : filename, - 'basename' : basename, - }, **sysconf.get_config_vars()) + 'python': self.Python, + 'MSVC': self.MSVC, + 'PSDK': self.PSDK, + 'suffix64': self.suffix64, + 'MD': self.MD, + 'pythonIPath': self.PythonIPath, + 'pythonVersion': self.PythonVersion, + 'arch': self.arch, + 'filename': filename, + 'basename': basename, + }, **sysconf.get_config_vars()) sys.stderr.write(compile + '\n') if os.system(compile) != 0: raise Exception('failed to compile %s.' % basename) link = self.linkExe % dict({ - 'python' : self.Python, - 'MSVC' : self.MSVC, - 'PSDK' : self.PSDK, - 'suffix64' : self.suffix64, - 'pythonIPath' : self.PythonIPath, - 'pythonVersion' : self.PythonVersion, - 'arch' : self.arch, - 'filename' : filename, - 'basename' : basename, - }, **sysconf.get_config_vars()) + 'python': self.Python, + 'MSVC': self.MSVC, + 'PSDK': self.PSDK, + 'suffix64': self.suffix64, + 'pythonIPath': self.PythonIPath, + 'pythonVersion': self.PythonVersion, + 'arch': self.arch, + 'filename': filename, + 'basename': basename, + }, **sysconf.get_config_vars()) link += ' ' + ' '.join(extraLink) sys.stderr.write(link + '\n') if os.system(link) != 0: @@ -308,38 +308,39 @@ class CompilationEnvironment: def compileDll(self, filename, basename, extraLink=[]): compile = self.compileObjDll % dict({ - 'python' : self.Python, - 'MSVC' : self.MSVC, - 'PSDK' : self.PSDK, - 'suffix64' : self.suffix64, - 'MD' : self.MD, - 'pythonIPath' : self.PythonIPath, - 'pythonVersion' : self.PythonVersion, - 'arch' : self.arch, - 'filename' : filename, - 'basename' : basename, - }, **sysconf.get_config_vars()) + 'python': self.Python, + 'MSVC': self.MSVC, + 'PSDK': self.PSDK, + 'suffix64': self.suffix64, + 'MD': self.MD, + 'pythonIPath': self.PythonIPath, + 'pythonVersion': self.PythonVersion, + 'arch': self.arch, + 'filename': filename, + 'basename': basename, + }, **sysconf.get_config_vars()) sys.stderr.write(compile + '\n') if os.system(compile) != 0: raise Exception('failed to compile %s.' % basename) link = self.linkDll % dict({ - 'python' : self.Python, - 'MSVC' : self.MSVC, - 'PSDK' : self.PSDK, - 'suffix64' : self.suffix64, - 'pythonIPath' : self.PythonIPath, - 'pythonVersion' : self.PythonVersion, - 'arch' : self.arch, - 'filename' : filename, - 'basename' : basename, - 'dllext' : self.dllext, - }, **sysconf.get_config_vars()) + 'python': self.Python, + 'MSVC': self.MSVC, + 'PSDK': self.PSDK, + 'suffix64': self.suffix64, + 'pythonIPath': self.PythonIPath, + 'pythonVersion': self.PythonVersion, + 'arch': self.arch, + 'filename': filename, + 'basename': basename, + 'dllext': self.dllext, + }, **sysconf.get_config_vars()) link += ' ' + ' '.join(extraLink) sys.stderr.write(link + '\n') if os.system(link) != 0: raise Exception('failed to link %s.' % basename) + # The code from frozenmain.c in the Python source repository. frozenMainCode = """ /* Python interpreter main program for frozen scripts */ @@ -675,7 +676,7 @@ okMissing = [ 'direct.extensions_native.extensions_darwin', '_manylinux', 'collections.Iterable', 'collections.Mapping', 'collections.MutableMapping', 'collections.Sequence', 'numpy_distutils', '_winapi', - ] +] # 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 @@ -722,6 +723,7 @@ lc_indices_to_slide = { LC_DATA_IN_CODE: [2], } + class Freezer: class ModuleDef: def __init__(self, moduleName, filename = None, @@ -1141,7 +1143,7 @@ class Freezer: if mdef.implicit and '.' in newName: # For implicit modules, check if the parent is excluded. parentName, baseName = newName.rsplit('.', 1) - if parentName in excludeDict : + if parentName in excludeDict: mdef = excludeDict[parentName] if mdef.exclude: @@ -1182,7 +1184,7 @@ class Freezer: self.__loadModule(mdef) # Since it successfully loaded, it's no longer a guess. mdef.guess = False - except: + except Exception: # Something went wrong, guess it's not an importable # module. pass @@ -1220,7 +1222,7 @@ class Freezer: try: self.__loadModule(self.ModuleDef(modname, implicit=True)) - except: + except Exception: missing.append(modname) # Now, any new modules we found get added to the export list. @@ -1596,7 +1598,7 @@ class Freezer: text = programFile % { 'moduleDefs': '\n'.join(moduleDefs), 'moduleList': '\n'.join(moduleList), - } + } if self.linkExtensionModules and self.extras: # Should we link in extension modules? If so, we write out a new @@ -1697,11 +1699,11 @@ class Freezer: if self.platform.startswith('win'): code += self.frozenDllMainCode initCode = self.mainInitCode % { - 'frozenMainCode' : code, - 'programName' : os.path.basename(basename), - 'dllexport' : dllexport, - 'dllimport' : dllimport, - } + 'frozenMainCode': code, + 'programName': os.path.basename(basename), + 'dllexport': dllexport, + 'dllimport': dllimport, + } if self.platform.startswith('win'): target = basename + '.exe' else: @@ -1716,10 +1718,10 @@ class Freezer: target = basename + '.so' initCode = dllInitCode % { - 'moduleName' : os.path.basename(basename), - 'dllexport' : dllexport, - 'dllimport' : dllimport, - } + 'moduleName': os.path.basename(basename), + 'dllexport': dllexport, + 'dllimport': dllimport, + } compileFunc = self.cenv.compileDll self.writeCode(filename, initCode=initCode) @@ -2357,7 +2359,6 @@ class Freezer: def makeForbiddenModuleListEntry(self, moduleName): return ' {"%s", NULL, 0},' % (moduleName) - def __writingModule(self, moduleName): """ Returns true if we are outputting the named module in this pass, false if we have already output in a previous pass, or diff --git a/direct/src/dist/pefile.py b/direct/src/dist/pefile.py index 6dbe1febb1..6478e2f914 100755 --- a/direct/src/dist/pefile.py +++ b/direct/src/dist/pefile.py @@ -28,6 +28,7 @@ def _unpack_zstring(mem, offs=0): c = mem[offs] return str + def _unpack_wstring(mem, offs=0): "Read a UCS-2 string from memory." name_len, = unpack(' 3: 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)) if len(dwords) > 5: 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)) if len(dwords) > 7: self.file_flags_mask = dwords[6] diff --git a/direct/src/distributed/ClientRepositoryBase.py b/direct/src/distributed/ClientRepositoryBase.py index d327cc81d4..ece578cad7 100644 --- a/direct/src/distributed/ClientRepositoryBase.py +++ b/direct/src/distributed/ClientRepositoryBase.py @@ -122,7 +122,7 @@ class ClientRepositoryBase(ConnectionRepository): def _getMsgName(self, msgId): # 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): self.context+=1 @@ -161,7 +161,7 @@ class ClientRepositoryBase(ConnectionRepository): # Look up the dclass assert parentId == self.GameGlobalsId or parentId in self.doId2do 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() # Create a new distributed object, and put it in the dictionary distObj = self.generateWithRequiredOtherFields(dclass, doId, di, parentId, zoneId) @@ -360,7 +360,6 @@ class ClientRepositoryBase(ConnectionRepository): # updateRequiredOtherFields calls announceGenerate return distObj - def disableDoId(self, doId, ownerView=False): table, cache = self.getTables(ownerView) # Make sure the object exists @@ -442,7 +441,6 @@ class ClientRepositoryBase(ConnectionRepository): # This object has been fully generated. It's OK to update. self.__doUpdate(doId, di, ovUpdated) - def __doUpdate(self, doId, di, ovUpdated): # Find the DO do = self.doId2do.get(doId) @@ -463,13 +461,12 @@ class ClientRepositoryBase(ConnectionRepository): if handle: dclass = self.dclassesByName[handle.dclassName] dclass.receiveUpdate(handle, di) - else: self.notify.warning( - "Asked to update non-existent DistObj " + str(doId)) - except: + f"Asked to update non-existent DistObj {doId}") + except Exception: 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): ovObj = self.doId2ownerView.get(doId) @@ -488,7 +485,7 @@ class ClientRepositoryBase(ConnectionRepository): self.bootedText = di.getString() 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: self.bootedIndex = None self.bootedText = None @@ -536,7 +533,6 @@ class ClientRepositoryBase(ConnectionRepository): doDict[doId] = do return doDict - def considerHeartbeat(self): """Send a heartbeat message if we haven't sent one recently.""" if not self.heartbeatStarted: @@ -566,7 +562,7 @@ class ClientRepositoryBase(ConnectionRepository): def waitForNextHeartBeat(self): taskMgr.doMethodLater(self.heartbeatInterval, self.sendHeartbeatTask, - "heartBeat", taskChain = 'net') + "heartBeat", taskChain='net') def replaceMethod(self, oldMethod, newFunction): return 0 diff --git a/direct/src/distributed/ConnectionRepository.py b/direct/src/distributed/ConnectionRepository.py index 7087ad8f30..62c2d5da46 100644 --- a/direct/src/distributed/ConnectionRepository.py +++ b/direct/src/distributed/ConnectionRepository.py @@ -13,6 +13,7 @@ import gc __all__ = ["ConnectionRepository", "GCTrigger"] + class ConnectionRepository( DoInterestManager, DoCollectionManager, CConnectionRepository): """ @@ -233,7 +234,7 @@ class ConnectionRepository( distObj.parentId = 0 distObj.zoneId = 0 # updateRequiredFields calls announceGenerate - return distObj + return distObj def readDCFile(self, dcFileNames = None): """ @@ -589,7 +590,7 @@ class ConnectionRepository( if self.http is None: try: self.http = HTTPClient() - except: + except Exception: pass return self.http @@ -667,6 +668,7 @@ class ConnectionRepository( def uniqueName(self, idString): return "%s-%s" % (idString, self.uniqueId) + class GCTrigger: # used to trigger garbage collection pass diff --git a/direct/src/distributed/DistributedObject.py b/direct/src/distributed/DistributedObject.py index d2bbd33d2a..ad53b6aa1a 100644 --- a/direct/src/distributed/DistributedObject.py +++ b/direct/src/distributed/DistributedObject.py @@ -24,7 +24,7 @@ ESNum2Str = { ESDisabled: 'ESDisabled', ESGenerating: 'ESGenerating', ESGenerated: 'ESGenerated', - } +} class DistributedObject(DistributedObjectBase): @@ -240,7 +240,6 @@ class DistributedObject(DistributedObjectBase): """ assert self.notify.debug('announceGenerate(): %s' % (self.doId)) - def _deactivateDO(self): # after this is called, the object is no longer an active DistributedObject # and it may be placed in the cache @@ -324,9 +323,9 @@ class DistributedObject(DistributedObjectBase): """ return self.doId - #This message was moved out of announce generate #to avoid ordering issues. + def postGenerateMessage(self): if self.activeState != ESGenerated: self.activeState = ESGenerated diff --git a/direct/src/distributed/DistributedSmoothNode.py b/direct/src/distributed/DistributedSmoothNode.py index 06da4ff1df..5e308f8e21 100644 --- a/direct/src/distributed/DistributedSmoothNode.py +++ b/direct/src/distributed/DistributedSmoothNode.py @@ -36,6 +36,8 @@ PredictionLag = ConfigVariableDouble("smooth-prediction-lag", 0.0) GlobalSmoothing = 0 GlobalPrediction = 0 + + def globalActivateSmoothing(smoothing, prediction): """ Globally activates or deactivates smoothing and prediction on all DistributedSmoothNodes currently in existence, or yet to be @@ -48,6 +50,7 @@ def globalActivateSmoothing(smoothing, prediction): for obj in base.cr.getAllOfType(DistributedSmoothNode): obj.activateSmoothing(smoothing, prediction) + # For historical reasons, we temporarily define # DistributedSmoothNode.activateSmoothing() to be the global function. # 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): self._smoothWrtReparents = flag + def getSmoothWrtReparents(self): return self._smoothWrtReparents @@ -213,42 +217,50 @@ class DistributedSmoothNode(DistributedNode.DistributedNode, def setSmStop(self, timestamp=None): self.setComponentTLive(timestamp) self.stopped = True + def setSmH(self, h, timestamp=None): self._checkResume(timestamp) self.setComponentH(h) self.setComponentTLive(timestamp) + def setSmZ(self, z, timestamp=None): self._checkResume(timestamp) self.setComponentZ(z) self.setComponentTLive(timestamp) + def setSmXY(self, x, y, timestamp=None): self._checkResume(timestamp) self.setComponentX(x) self.setComponentY(y) self.setComponentTLive(timestamp) + def setSmXZ(self, x, z, timestamp=None): self._checkResume(timestamp) self.setComponentX(x) self.setComponentZ(z) self.setComponentTLive(timestamp) + def setSmPos(self, x, y, z, timestamp=None): self._checkResume(timestamp) self.setComponentX(x) self.setComponentY(y) self.setComponentZ(z) self.setComponentTLive(timestamp) + def setSmHpr(self, h, p, r, timestamp=None): self._checkResume(timestamp) self.setComponentH(h) self.setComponentP(p) self.setComponentR(r) self.setComponentTLive(timestamp) + def setSmXYH(self, x, y, h, timestamp): self._checkResume(timestamp) self.setComponentX(x) self.setComponentY(y) self.setComponentH(h) self.setComponentTLive(timestamp) + def setSmXYZH(self, x, y, z, h, timestamp=None): self._checkResume(timestamp) self.setComponentX(x) @@ -256,6 +268,7 @@ class DistributedSmoothNode(DistributedNode.DistributedNode, self.setComponentZ(z) self.setComponentH(h) self.setComponentTLive(timestamp) + def setSmPosHpr(self, x, y, z, h, p, r, timestamp=None): self._checkResume(timestamp) self.setComponentX(x) @@ -285,26 +298,33 @@ class DistributedSmoothNode(DistributedNode.DistributedNode, @report(types = ['args'], dConfigParam = 'smoothnode') def setComponentX(self, x): self.smoother.setX(x) + @report(types = ['args'], dConfigParam = 'smoothnode') def setComponentY(self, y): self.smoother.setY(y) + @report(types = ['args'], dConfigParam = 'smoothnode') def setComponentZ(self, z): self.smoother.setZ(z) + @report(types = ['args'], dConfigParam = 'smoothnode') def setComponentH(self, h): self.smoother.setH(h) + @report(types = ['args'], dConfigParam = 'smoothnode') def setComponentP(self, p): self.smoother.setP(p) + @report(types = ['args'], dConfigParam = 'smoothnode') def setComponentR(self, r): self.smoother.setR(r) + @report(types = ['args'], dConfigParam = 'smoothnode') def setComponentL(self, l): if l != self.zoneId: # only perform set location if location is different self.setLocation(self.parentId,l) + @report(types = ['args'], dConfigParam = 'smoothnode') def setComponentT(self, timestamp): # 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. def getComponentL(self): return self.zoneId + def getComponentX(self): return self.getX() + def getComponentY(self): return self.getY() + def getComponentZ(self): return self.getZ() + def getComponentH(self): return self.getH() + def getComponentP(self): return self.getP() + def getComponentR(self): return self.getR() + def getComponentT(self): return 0 @@ -409,7 +436,6 @@ class DistributedSmoothNode(DistributedNode.DistributedNode, #printStack() self.smoother.clearPositions(1) - @report(types = ['args'], dConfigParam = 'smoothnode') def wrtReparentTo(self, parent): # We override this NodePath method to force it to @@ -476,7 +502,6 @@ class DistributedSmoothNode(DistributedNode.DistributedNode, serverTime, globalClockDelta.getUncertainty()) - def d_returnResync(self, avId, timestampB, serverTime, uncertainty): serverTimeSec = math.floor(serverTime) serverTimeUSec = (serverTime - serverTimeSec) * 10000.0 @@ -484,7 +509,7 @@ class DistributedSmoothNode(DistributedNode.DistributedNode, avId, timestampB, serverTimeSec, serverTimeUSec, uncertainty]) def returnResync(self, avId, timestampB, serverTimeSec, serverTimeUSec, - uncertainty): + uncertainty): """ A reply sent by a client whom we recently sent suggestResync to, this reports the client's new delta information so we can diff --git a/direct/src/distributed/DistributedSmoothNodeBase.py b/direct/src/distributed/DistributedSmoothNodeBase.py index d27b13e0cd..4d0f9a2cc3 100755 --- a/direct/src/distributed/DistributedSmoothNodeBase.py +++ b/direct/src/distributed/DistributedSmoothNodeBase.py @@ -13,8 +13,10 @@ class DummyTaskClass: def setDelay(self, blah): pass + DummyTask = DummyTaskClass() + class DistributedSmoothNodeBase: """common base class for DistributedSmoothNode and DistributedSmoothNodeAI """ @@ -43,6 +45,7 @@ class DistributedSmoothNodeBase: def b_clearSmoothing(self): self.d_clearSmoothing() self.clearSmoothing() + def d_clearSmoothing(self): self.sendUpdate("clearSmoothing", [0]) @@ -85,7 +88,7 @@ class DistributedSmoothNodeBase: BT.FULL: self.cnode.broadcastPosHprFull, BT.XYH: self.cnode.broadcastPosHprXyh, BT.XY: self.cnode.broadcastPosHprXy, - } + } # this comment is here so it will show up in a grep for 'def d_broadcastPosHpr' self.d_broadcastPosHpr = broadcastFuncs[self.broadcastType] diff --git a/direct/src/distributed/MsgTypes.py b/direct/src/distributed/MsgTypes.py index 14ce6ba55e..e595d3d88a 100644 --- a/direct/src/distributed/MsgTypes.py +++ b/direct/src/distributed/MsgTypes.py @@ -137,7 +137,7 @@ MsgName2Id = { 'CLIENTAGENT_ADD_INTEREST': 1200, 'CLIENTAGENT_ADD_INTEREST_MULTIPLE': 1201, 'CLIENTAGENT_REMOVE_INTEREST': 1203, - } +} # create id->name table for debugging MsgId2Names = invertDictLossless(MsgName2Id) @@ -157,7 +157,7 @@ QUIET_ZONE_IGNORED_LIST = [ #CLIENT_CREATE_OBJECT_REQUIRED, #CLIENT_CREATE_OBJECT_REQUIRED_OTHER, - ] +] # The following is a different set of numbers from above. # These are the sub-message types for CLIENT_LOGIN_2. diff --git a/direct/src/distributed/MsgTypesCMU.py b/direct/src/distributed/MsgTypesCMU.py index e7c7501730..ce728b3b6f 100644 --- a/direct/src/distributed/MsgTypesCMU.py +++ b/direct/src/distributed/MsgTypesCMU.py @@ -20,7 +20,7 @@ MsgName2Id = { 'CLIENT_OBJECT_UPDATE_FIELD_TARGETED_CMU' : 9011, 'CLIENT_OBJECT_UPDATE_FIELD' : 120, # Matches MsgTypes.CLIENT_OBJECT_SET_FIELD - } +} # create id->name table for debugging MsgId2Names = invertDictLossless(MsgName2Id) diff --git a/direct/src/distributed/PyDatagram.py b/direct/src/distributed/PyDatagram.py index 6fbd5abfff..fbaeafa6fe 100755 --- a/direct/src/distributed/PyDatagram.py +++ b/direct/src/distributed/PyDatagram.py @@ -48,7 +48,7 @@ class PyDatagram(Datagram): STString: (Datagram.addString, None), STBlob: (Datagram.addBlob, None), STBlob32: (Datagram.addBlob32, None), - } + } addChannel = Datagram.addUint64 diff --git a/direct/src/distributed/PyDatagramIterator.py b/direct/src/distributed/PyDatagramIterator.py index 6e9b6c532b..3f7cc3814d 100755 --- a/direct/src/distributed/PyDatagramIterator.py +++ b/direct/src/distributed/PyDatagramIterator.py @@ -46,7 +46,7 @@ class PyDatagramIterator(DatagramIterator): STString: DatagramIterator.getString, STBlob: DatagramIterator.getBlob, STBlob32: DatagramIterator.getBlob32, - } + } getChannel = DatagramIterator.getUint64 diff --git a/direct/src/filter/CommonFilters.py b/direct/src/filter/CommonFilters.py index 24aef5ddb0..85d0a18f16 100644 --- a/direct/src/filter/CommonFilters.py +++ b/direct/src/filter/CommonFilters.py @@ -351,7 +351,7 @@ class CommonFilters: text += "{\n" text += " o_color = tex2D(k_txcolor, %s);\n" % (texcoords["color"]) if "CartoonInk" in configuration: - text += CARTOON_BODY % {"texcoord" : texcoords["aux"]} + text += CARTOON_BODY % {"texcoord": texcoords["aux"]} if "AmbientOcclusion" in configuration: text += " o_color *= tex2D(k_txssao2, %s).r;\n" % (texcoords["ssao2"]) if "BlurSharpen" in configuration: diff --git a/direct/src/fsm/ClassicFSM.py b/direct/src/fsm/ClassicFSM.py index 799058d82e..6d45b5bb11 100644 --- a/direct/src/fsm/ClassicFSM.py +++ b/direct/src/fsm/ClassicFSM.py @@ -150,7 +150,6 @@ class ClassicFSM(DirectObject): def getCurrentState(self): return self.__currentState - # lookup funcs def getStateNamed(self, stateName): @@ -315,7 +314,6 @@ class ClassicFSM(DirectObject): ClassicFSM.notify.warning(msg) return 0 - def forceTransition(self, aStateName, enterArgList=[], exitArgList=[]): """ force a transition -- for debugging ONLY @@ -355,7 +353,7 @@ class ClassicFSM(DirectObject): self.__currentState.isTransitionDefined(aStateName) or aStateName in [self.__currentState.getName(), self.__finalState.getName()] - ) + ) if transitionDefined: return self.request(aStateName, enterArgList, exitArgList) diff --git a/direct/src/fsm/FourState.py b/direct/src/fsm/FourState.py index 8322273d27..a93b56fecf 100755 --- a/direct/src/fsm/FourState.py +++ b/direct/src/fsm/FourState.py @@ -115,7 +115,7 @@ class FourState: self.enterState4, self.exitState4, [names[1]]), - } + } self.fsm = ClassicFSM.ClassicFSM('FourState', list(self.states.values()), # Initial State diff --git a/direct/src/fsm/FourStateAI.py b/direct/src/fsm/FourStateAI.py index df8252d25e..84f1fa3b70 100755 --- a/direct/src/fsm/FourStateAI.py +++ b/direct/src/fsm/FourStateAI.py @@ -123,7 +123,7 @@ class FourStateAI: self.enterState4, self.exitState4, [names[1]]), - } + } self.fsm = ClassicFSM.ClassicFSM('FourState', list(self.states.values()), # Initial State diff --git a/direct/src/fsm/SampleFSM.py b/direct/src/fsm/SampleFSM.py index 6a60c18b32..dfda83ff5a 100644 --- a/direct/src/fsm/SampleFSM.py +++ b/direct/src/fsm/SampleFSM.py @@ -16,7 +16,7 @@ class ClassicStyle(FSM.FSM): 'Red': ['Green'], 'Yellow': ['Red'], 'Green': ['Yellow'], - } + } def enterRed(self): print("enterRed(self, '%s', '%s')" % (self.oldState, self.newState)) diff --git a/direct/src/gui/DirectButton.py b/direct/src/gui/DirectButton.py index 17fbe8a75f..0ed5523854 100644 --- a/direct/src/gui/DirectButton.py +++ b/direct/src/gui/DirectButton.py @@ -10,11 +10,13 @@ from panda3d.core import Mat4, MouseButton, PGButton from . import DirectGuiGlobals as DGG from .DirectFrame import DirectFrame + class DirectButton(DirectFrame): """ DirectButton(parent) - Create a DirectGuiWidget which responds to mouse clicks and execute a callback function if defined """ + def __init__(self, parent = None, **kw): # Inherits from DirectFrame # A Direct Frame can have: @@ -45,7 +47,7 @@ class DirectButton(DirectFrame): # Can only be specified at time of widget contruction # Do the text/graphics appear to move when the button is clicked ('pressEffect', 1, DGG.INITOPT), - ) + ) # Merge keyword options with default options self.defineoptions(kw, optiondefs) diff --git a/direct/src/gui/DirectCheckBox.py b/direct/src/gui/DirectCheckBox.py index 8488f701d2..fc0ce5f5ca 100755 --- a/direct/src/gui/DirectCheckBox.py +++ b/direct/src/gui/DirectCheckBox.py @@ -10,6 +10,7 @@ class DirectCheckBox(DirectButton): Uses an image swap rather than a text change to indicate state. """ + def __init__(self, parent = None, **kw): optiondefs = ( @@ -33,7 +34,7 @@ class DirectCheckBox(DirectButton): ('uncheckedImage', None, None), ('checkedImage', None, None), ('isChecked', False, None), - ) + ) # Merge keyword options with default options self.defineoptions(kw, optiondefs) @@ -42,7 +43,6 @@ class DirectCheckBox(DirectButton): self.initialiseoptions(DirectCheckBox) - def commandFunc(self, event): self['isChecked'] = not self['isChecked'] diff --git a/direct/src/gui/DirectCheckButton.py b/direct/src/gui/DirectCheckButton.py index 0f8344cdad..0674982c8d 100644 --- a/direct/src/gui/DirectCheckButton.py +++ b/direct/src/gui/DirectCheckButton.py @@ -12,12 +12,14 @@ from panda3d.core import PGFrameStyle, VBase4 from .DirectButton import DirectButton from .DirectLabel import DirectLabel + class DirectCheckButton(DirectButton): """ DirectCheckButton(parent) - Create a DirectGuiWidget which responds to mouse clicks by setting a state of on or off and execute a callback function (passing that state through) if defined """ + def __init__(self, parent = None, **kw): # Inherits from DirectButton # A Direct Frame can have: @@ -42,7 +44,7 @@ class DirectCheckButton(DirectButton): ('boxImageScale', 1, None), ('boxImageColor', None, None), ('boxRelief', 'sunken', None), - ) + ) # Merge keyword options with default options self.defineoptions(kw, optiondefs) # Initialize superclasses @@ -167,7 +169,6 @@ class DirectCheckButton(DirectButton): self.indicator.setPos(newpos[0], newpos[1], newpos[2]) - def commandFunc(self, event): self['indicatorValue'] = 1 - self['indicatorValue'] if self.colors is not None: diff --git a/direct/src/gui/DirectDialog.py b/direct/src/gui/DirectDialog.py index e6c1642f81..4b95dcb7f5 100644 --- a/direct/src/gui/DirectDialog.py +++ b/direct/src/gui/DirectDialog.py @@ -120,7 +120,7 @@ class DirectDialog(DirectFrame): ('command', None, None), ('extraArgs', [], None), ('sortOrder', DGG.NO_FADE_SORT_INDEX, None), - ) + ) # Merge keyword options with default options self.defineoptions(kw, optiondefs, dynamicGroups = ("button",)) @@ -178,7 +178,7 @@ class DirectDialog(DirectFrame): suppressKeys = self['suppressKeys'], frameSize = self['buttonSize'], command = lambda s = self, v = value: s.buttonCommand(v) - ) + ) self.buttonList.append(button) # Update dialog when everything has been initialised @@ -356,6 +356,7 @@ class DirectDialog(DirectFrame): button.destroy() DirectFrame.destroy(self) + class OkDialog(DirectDialog): def __init__(self, parent = None, **kw): # Inherits from DirectFrame @@ -363,12 +364,13 @@ class OkDialog(DirectDialog): # Define type of DirectGuiWidget ('buttonTextList', ['OK'], DGG.INITOPT), ('buttonValueList', [DGG.DIALOG_OK], DGG.INITOPT), - ) + ) # Merge keyword options with default options self.defineoptions(kw, optiondefs) DirectDialog.__init__(self, parent) self.initialiseoptions(OkDialog) + class OkCancelDialog(DirectDialog): def __init__(self, parent = None, **kw): # Inherits from DirectFrame @@ -376,12 +378,13 @@ class OkCancelDialog(DirectDialog): # Define type of DirectGuiWidget ('buttonTextList', ['OK','Cancel'], DGG.INITOPT), ('buttonValueList', [DGG.DIALOG_OK, DGG.DIALOG_CANCEL], DGG.INITOPT), - ) + ) # Merge keyword options with default options self.defineoptions(kw, optiondefs) DirectDialog.__init__(self, parent) self.initialiseoptions(OkCancelDialog) + class YesNoDialog(DirectDialog): def __init__(self, parent = None, **kw): # Inherits from DirectFrame @@ -389,12 +392,13 @@ class YesNoDialog(DirectDialog): # Define type of DirectGuiWidget ('buttonTextList', ['Yes', 'No'], DGG.INITOPT), ('buttonValueList', [DGG.DIALOG_YES, DGG.DIALOG_NO], DGG.INITOPT), - ) + ) # Merge keyword options with default options self.defineoptions(kw, optiondefs) DirectDialog.__init__(self, parent) self.initialiseoptions(YesNoDialog) + class YesNoCancelDialog(DirectDialog): def __init__(self, parent = None, **kw): # Inherits from DirectFrame @@ -403,12 +407,13 @@ class YesNoCancelDialog(DirectDialog): ('buttonTextList', ['Yes', 'No', 'Cancel'], DGG.INITOPT), ('buttonValueList', [DGG.DIALOG_YES, DGG.DIALOG_NO, DGG.DIALOG_CANCEL], DGG.INITOPT), - ) + ) # Merge keyword options with default options self.defineoptions(kw, optiondefs) DirectDialog.__init__(self, parent) self.initialiseoptions(YesNoCancelDialog) + class RetryCancelDialog(DirectDialog): def __init__(self, parent = None, **kw): # Inherits from DirectFrame @@ -416,7 +421,7 @@ class RetryCancelDialog(DirectDialog): # Define type of DirectGuiWidget ('buttonTextList', ['Retry','Cancel'], DGG.INITOPT), ('buttonValueList', [DGG.DIALOG_RETRY, DGG.DIALOG_CANCEL], DGG.INITOPT), - ) + ) # Merge keyword options with default options self.defineoptions(kw, optiondefs) DirectDialog.__init__(self, parent) diff --git a/direct/src/gui/DirectEntry.py b/direct/src/gui/DirectEntry.py index 4ba80852a3..f106e40aad 100644 --- a/direct/src/gui/DirectEntry.py +++ b/direct/src/gui/DirectEntry.py @@ -21,6 +21,7 @@ ENTRY_FOCUS_STATE = PGEntry.SFocus # 0 ENTRY_NO_FOCUS_STATE = PGEntry.SNoFocus # 1 ENTRY_INACTIVE_STATE = PGEntry.SInactive # 2 + class DirectEntry(DirectFrame): """ DirectEntry(parent) - Create a DirectGuiWidget which responds @@ -82,7 +83,7 @@ class DirectEntry(DirectFrame): ('autoCapitalize', 0, self.autoCapitalizeFunc), ('autoCapitalizeAllowPrefixes', DirectEntry.AllowCapNamePrefixes, None), ('autoCapitalizeForcePrefixes', DirectEntry.ForceCapNamePrefixes, None), - ) + ) # Merge keyword options with default options self.defineoptions(kw, optiondefs) @@ -215,6 +216,7 @@ class DirectEntry(DirectFrame): def _handleTyping(self, guiEvent): self._autoCapitalize() + def _handleErasing(self, guiEvent): self._autoCapitalize() diff --git a/direct/src/gui/DirectEntryScroll.py b/direct/src/gui/DirectEntryScroll.py index f2982872d2..9b77448af7 100644 --- a/direct/src/gui/DirectEntryScroll.py +++ b/direct/src/gui/DirectEntryScroll.py @@ -11,7 +11,7 @@ class DirectEntryScroll(DirectFrame): ('pgFunc', PGVirtualFrame, None), ('relief', None, None), ('clipSize', (-1, 1, -1, 1), self.setClipSize), - ) + ) self.defineoptions(kw, optiondefs) DirectFrame.__init__(self, parent, **kw) @@ -80,7 +80,6 @@ class DirectEntryScroll(DirectFrame): if abs(distanceToCenter) > (clipExtent * 0.5): self.moveToCenterCursor() - def moveToCenterCursor(self): cursorX = self.entry.guiItem.getCursorX() * self.entry['text_scale'][0] canvasX = self.canvas.getX() @@ -121,7 +120,6 @@ class DirectEntryScroll(DirectFrame): self.entry = None DirectFrame.destroy(self) - def getCanvas(self): return self.canvas diff --git a/direct/src/gui/DirectGuiBase.py b/direct/src/gui/DirectGuiBase.py index 4c7b85a232..fa2721f688 100644 --- a/direct/src/gui/DirectGuiBase.py +++ b/direct/src/gui/DirectGuiBase.py @@ -659,9 +659,11 @@ class DirectGuiBase(DirectObject.DirectObject): gEvent = event + self.guiId self.ignore(gEvent) + def toggleGuiGridSnap(): DirectGuiWidget.snapToGrid = 1 - DirectGuiWidget.snapToGrid + def setGuiGridSpacing(spacing): DirectGuiWidget.gridSpacing = spacing @@ -722,7 +724,7 @@ class DirectGuiWidget(DirectGuiBase, NodePath): ('suppressMouse', 1, DGG.INITOPT), ('suppressKeys', 0, DGG.INITOPT), ('enableEdit', 1, DGG.INITOPT), - ) + ) # Merge keyword options with default options self.defineoptions(kw, optiondefs) @@ -829,7 +831,7 @@ class DirectGuiWidget(DirectGuiBase, NodePath): vMouse2render2d = Point3(event.getMouse()[0], 0, event.getMouse()[1]) editVec = Vec3(vWidget2render2d - vMouse2render2d) if base.mouseWatcherNode.getModifierButtons().isDown( - KeyboardButton.control()): + KeyboardButton.control()): t = taskMgr.add(self.guiScaleTask, 'guiEditTask') t.refPos = vWidget2render2d t.editVecLen = editVec.length() @@ -911,7 +913,6 @@ class DirectGuiWidget(DirectGuiBase, NodePath): self.bounds[2] - bw[1], self.bounds[3] + bw[1]) - def getBounds(self, state = 0): self.stateNodePath[state].calcTightBounds(self.ll, self.ur) # Scale bounds to give a pad around graphics diff --git a/direct/src/gui/DirectLabel.py b/direct/src/gui/DirectLabel.py index 5b676daf65..24eef19dfe 100644 --- a/direct/src/gui/DirectLabel.py +++ b/direct/src/gui/DirectLabel.py @@ -9,11 +9,13 @@ __all__ = ['DirectLabel'] from panda3d.core import PGItem from .DirectFrame import DirectFrame + class DirectLabel(DirectFrame): """ DirectLabel(parent) - Create a DirectGuiWidget which has multiple states. User explicitly chooses a state to display """ + def __init__(self, parent = None, **kw): # Inherits from DirectFrame # A Direct Frame can have: @@ -32,7 +34,7 @@ class DirectLabel(DirectFrame): ('numStates', 1, None), ('state', self.inactiveInitState, None), ('activeState', 0, self.setActiveState), - ) + ) # Merge keyword options with default options self.defineoptions(kw, optiondefs) diff --git a/direct/src/gui/DirectOptionMenu.py b/direct/src/gui/DirectOptionMenu.py index 2b09943906..b923dcea74 100644 --- a/direct/src/gui/DirectOptionMenu.py +++ b/direct/src/gui/DirectOptionMenu.py @@ -21,6 +21,7 @@ class DirectOptionMenu(DirectButton): To cancel the popup menu click anywhere on the screen outside of the popup menu. No command is executed in this case. """ + def __init__(self, parent = None, **kw): # Inherits from DirectButton optiondefs = ( @@ -42,7 +43,7 @@ class DirectOptionMenu(DirectButton): ('text_align', TextNode.ALeft, None), # Remove press effect because it looks a bit funny ('pressEffect', 0, DGG.INITOPT), - ) + ) # Merge keyword options with default options self.defineoptions(kw, optiondefs) # Initialize superclasses diff --git a/direct/src/gui/DirectRadioButton.py b/direct/src/gui/DirectRadioButton.py index d395c3f2de..8dbff9b344 100755 --- a/direct/src/gui/DirectRadioButton.py +++ b/direct/src/gui/DirectRadioButton.py @@ -14,12 +14,14 @@ from . import DirectGuiGlobals as DGG from .DirectButton import DirectButton from .DirectLabel import DirectLabel + class DirectRadioButton(DirectButton): """ DirectRadioButton(parent) - Create a DirectGuiWidget which responds to mouse clicks by setting given value to given variable and execute a callback function (passing that state through) if defined """ + def __init__(self, parent = None, **kw): # Inherits from DirectButton # A Direct Frame can have: @@ -54,7 +56,7 @@ class DirectRadioButton(DirectButton): ('boxImageScale', 1.0, None), ('boxImageColor', VBase4(1, 1, 1, 1), None), ('boxRelief', None, None), - ) + ) # Merge keyword options with default options self.defineoptions(kw, optiondefs) # Initialize superclasses @@ -194,7 +196,6 @@ class DirectRadioButton(DirectButton): self.indicator.setPos(newpos[0], newpos[1], newpos[2]) - def commandFunc(self, event): if len(self['value']) == len(self['variable']) != 0: for i in range(len(self['value'])): diff --git a/direct/src/gui/DirectScrollBar.py b/direct/src/gui/DirectScrollBar.py index fc10a88d7d..ce62e2bf4e 100644 --- a/direct/src/gui/DirectScrollBar.py +++ b/direct/src/gui/DirectScrollBar.py @@ -17,6 +17,7 @@ class DirectScrollBar(DirectFrame): DirectScrollBar -- a widget which represents a scroll bar the user can use for paging through a large document or panel. """ + def __init__(self, parent = None, **kw): optiondefs = ( # Define type of DirectGuiWidget @@ -35,18 +36,18 @@ class DirectScrollBar(DirectFrame): # Function to be called repeatedly as the bar is scrolled ('command', None, None), ('extraArgs', [], None), - ) + ) if kw.get('orientation') in (DGG.VERTICAL, DGG.VERTICAL_INVERTED): # These are the default options for a vertical layout. optiondefs += ( ('frameSize', (-0.04, 0.04, -0.5, 0.5), None), - ) + ) else: # These are the default options for a horizontal layout. optiondefs += ( ('frameSize', (-0.5, 0.5, -0.04, 0.04), None), - ) + ) # Merge keyword options with default options self.defineoptions(kw, optiondefs) diff --git a/direct/src/gui/DirectScrolledFrame.py b/direct/src/gui/DirectScrolledFrame.py index ca434304e3..e934c4210d 100644 --- a/direct/src/gui/DirectScrolledFrame.py +++ b/direct/src/gui/DirectScrolledFrame.py @@ -24,6 +24,7 @@ class DirectScrolledFrame(DirectFrame): 0 and explicitly position and hide or show the scroll bars yourself. """ + def __init__(self, parent = None, **kw): optiondefs = ( # Define type of DirectGuiWidget @@ -35,7 +36,7 @@ class DirectScrolledFrame(DirectFrame): ('autoHideScrollBars', 1, self.setAutoHideScrollBars), ('scrollBarWidth', 0.08, self.setScrollBarWidth), ('borderWidth', (0.01, 0.01), self.setBorderWidth), - ) + ) # Merge keyword options with default options self.defineoptions(kw, optiondefs) diff --git a/direct/src/gui/DirectScrolledList.py b/direct/src/gui/DirectScrolledList.py index be5b33508a..9d9f9419d7 100644 --- a/direct/src/gui/DirectScrolledList.py +++ b/direct/src/gui/DirectScrolledList.py @@ -37,7 +37,7 @@ class DirectScrolledListItem(DirectButton): optiondefs = ( ('parent', self._parent, None), ('command', self.select, None), - ) + ) # Merge keyword options with default options self.defineoptions(kw, optiondefs) DirectButton.__init__(self) @@ -91,7 +91,7 @@ class DirectScrolledList(DirectFrame): ('forceHeight', None, self.setForceHeight), ('incButtonCallback', None, self.setIncButtonCallback), ('decButtonCallback', None, self.setDecButtonCallback), - ) + ) # Merge keyword options with default options 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"] try: self["numItemsVisible"] - except: + except Exception: # RAU hack to kill 27633 self.notify.info('crash 27633 fixed!') return diff --git a/direct/src/gui/DirectSlider.py b/direct/src/gui/DirectSlider.py index 6f3e8d7825..112d805038 100644 --- a/direct/src/gui/DirectSlider.py +++ b/direct/src/gui/DirectSlider.py @@ -18,6 +18,7 @@ class DirectSlider(DirectFrame): DirectSlider -- a widget which represents a slider that the user can pull left and right to represent a continuous value. """ + def __init__(self, parent = None, **kw): optiondefs = ( # Define type of DirectGuiWidget @@ -34,20 +35,20 @@ class DirectSlider(DirectFrame): # Function to be called repeatedly as slider is moved ('command', None, None), ('extraArgs', [], None), - ) + ) if kw.get('orientation') in (DGG.VERTICAL, DGG.VERTICAL_INVERTED): # These are the default options for a vertical layout. optiondefs += ( ('frameSize', (-0.08, 0.08, -1, 1), None), ('frameVisibleScale', (0.25, 1), None), - ) + ) else: # These are the default options for a horizontal layout. optiondefs += ( ('frameSize', (-1, 1, -0.08, 0.08), None), ('frameVisibleScale', (1, 0.25), None), - ) + ) # Merge keyword options with default options self.defineoptions(kw, optiondefs) diff --git a/direct/src/gui/DirectWaitBar.py b/direct/src/gui/DirectWaitBar.py index c6a42d8947..a6853fb306 100644 --- a/direct/src/gui/DirectWaitBar.py +++ b/direct/src/gui/DirectWaitBar.py @@ -33,12 +33,12 @@ class DirectWaitBar(DirectFrame): ('barTexture', None, self.setBarTexture), ('barRelief', DGG.FLAT, self.setBarRelief), ('sortOrder', DGG.NO_FADE_SORT_INDEX, None), - ) + ) if 'text' in kw: textoptiondefs = ( ('text_pos', (0, -0.025), None), ('text_scale', 0.1, None) - ) + ) else: textoptiondefs = () # Merge keyword options with default options diff --git a/direct/src/gui/OnscreenText.py b/direct/src/gui/OnscreenText.py index 67a9358957..e3a8912151 100644 --- a/direct/src/gui/OnscreenText.py +++ b/direct/src/gui/OnscreenText.py @@ -20,6 +20,7 @@ ScreenPrompt = 3 NameConfirm = 4 BlackOnWhite = 5 + class OnscreenText(NodePath): def __init__(self, text = '', @@ -465,7 +466,7 @@ class OnscreenText(NodePath): Mat4.scaleMat(Vec3.rfu(self.__scale[0], 1, self.__scale[1])) * Mat4.rotateMat(self.__roll, Vec3.back()) * Mat4.translateMat(Point3.rfu(self.__pos[0], 0, self.__pos[1])) - ) + ) self.textNode.setTransform(mat) def setWordwrap(self, wordwrap): diff --git a/direct/src/interval/IntervalGlobal.py b/direct/src/interval/IntervalGlobal.py index 41ee6444f7..595d62fb5b 100644 --- a/direct/src/interval/IntervalGlobal.py +++ b/direct/src/interval/IntervalGlobal.py @@ -15,8 +15,8 @@ from .IndirectInterval import * from .MopathInterval import * try: import panda3d.physics - ##Some people may have the particle system compiled out - if hasattr( panda3d.physics, 'ParticleSystem' ): + # Some people may have the particle system compiled out + if hasattr(panda3d.physics, 'ParticleSystem'): from .ParticleInterval import * if __debug__: from .TestInterval import * diff --git a/direct/src/interval/LerpInterval.py b/direct/src/interval/LerpInterval.py index 2dbeb018bd..ae218fe0f2 100644 --- a/direct/src/interval/LerpInterval.py +++ b/direct/src/interval/LerpInterval.py @@ -10,7 +10,7 @@ __all__ = [ 'LerpColorInterval', 'LerpColorScaleInterval', 'LerpTexOffsetInterval', 'LerpTexRotateInterval', 'LerpTexScaleInterval', 'LerpFunctionInterval', 'LerpFunc','LerpFunctionNoStateInterval','LerpFuncNS' - ] +] from panda3d.core import LOrientationf, NodePath from panda3d.direct import CInterval, CLerpNodePathInterval @@ -25,6 +25,7 @@ from . import LerpBlendHelpers # performance. # + class LerpNodePathInterval(CLerpNodePathInterval): # This is the base class for all of the lerps, defined below, that # affect a property on a NodePath, like pos or hpr. @@ -99,6 +100,7 @@ class LerpNodePathInterval(CLerpNodePathInterval): ## ##################################################################### + class LerpPosInterval(LerpNodePathInterval): def __init__(self, nodePath, duration, pos, startPos = None, other = None, blendType = 'noBlend', @@ -157,6 +159,7 @@ class LerpHprInterval(LerpNodePathInterval): self.setupParam(self.setStartQuat, self.startQuat) LerpNodePathInterval.privDoEvent(self, t, event) + class LerpQuatInterval(LerpNodePathInterval): def __init__(self, nodePath, duration, quat = None, startHpr = None, startQuat = None, @@ -195,6 +198,7 @@ class LerpQuatInterval(LerpNodePathInterval): self.setupParam(self.setStartQuat, self.startQuat) LerpNodePathInterval.privDoEvent(self, t, event) + class LerpScaleInterval(LerpNodePathInterval): def __init__(self, nodePath, duration, scale, startScale = None, other = None, blendType = 'noBlend', @@ -220,6 +224,7 @@ class LerpScaleInterval(LerpNodePathInterval): self.setupParam(self.setStartScale, self.startScale) LerpNodePathInterval.privDoEvent(self, t, event) + class LerpShearInterval(LerpNodePathInterval): def __init__(self, nodePath, duration, shear, startShear = None, other = None, blendType = 'noBlend', @@ -245,6 +250,7 @@ class LerpShearInterval(LerpNodePathInterval): self.setupParam(self.setStartShear, self.startShear) LerpNodePathInterval.privDoEvent(self, t, event) + class LerpPosHprInterval(LerpNodePathInterval): def __init__(self, nodePath, duration, pos, hpr, startPos = None, startHpr = None, startQuat = None, @@ -282,6 +288,7 @@ class LerpPosHprInterval(LerpNodePathInterval): self.setupParam(self.setStartQuat, self.startQuat) LerpNodePathInterval.privDoEvent(self, t, event) + class LerpPosQuatInterval(LerpNodePathInterval): def __init__(self, nodePath, duration, pos, quat = None, startPos = None, startHpr = None, startQuat = None, @@ -327,6 +334,7 @@ class LerpPosQuatInterval(LerpNodePathInterval): self.setupParam(self.setStartQuat, self.startQuat) LerpNodePathInterval.privDoEvent(self, t, event) + class LerpHprScaleInterval(LerpNodePathInterval): def __init__(self, nodePath, duration, hpr, scale, startHpr = None, startQuat = None, startScale = None, @@ -365,6 +373,7 @@ class LerpHprScaleInterval(LerpNodePathInterval): self.setupParam(self.setStartScale, self.startScale) LerpNodePathInterval.privDoEvent(self, t, event) + class LerpQuatScaleInterval(LerpNodePathInterval): def __init__(self, nodePath, duration, quat = None, scale = None, hpr = None, @@ -413,6 +422,7 @@ class LerpQuatScaleInterval(LerpNodePathInterval): self.setupParam(self.setStartScale, self.startScale) LerpNodePathInterval.privDoEvent(self, t, event) + class LerpPosHprScaleInterval(LerpNodePathInterval): def __init__(self, nodePath, duration, pos, hpr, scale, startPos = None, startHpr = None, startQuat = None, @@ -459,6 +469,7 @@ class LerpPosHprScaleInterval(LerpNodePathInterval): self.setupParam(self.setStartScale, self.startScale) LerpNodePathInterval.privDoEvent(self, t, event) + class LerpPosQuatScaleInterval(LerpNodePathInterval): def __init__(self, nodePath, duration, pos, quat = None, scale = None, startPos = None, startHpr = None, startQuat = None, @@ -515,6 +526,7 @@ class LerpPosQuatScaleInterval(LerpNodePathInterval): self.setupParam(self.setStartScale, self.startScale) LerpNodePathInterval.privDoEvent(self, t, event) + class LerpPosHprScaleShearInterval(LerpNodePathInterval): def __init__(self, nodePath, duration, pos, hpr, scale, shear, startPos = None, startHpr = None, startQuat = None, @@ -569,6 +581,7 @@ class LerpPosHprScaleShearInterval(LerpNodePathInterval): self.setupParam(self.setStartShear, self.startShear) LerpNodePathInterval.privDoEvent(self, t, event) + class LerpPosQuatScaleShearInterval(LerpNodePathInterval): def __init__(self, nodePath, duration, pos, quat = None, scale = None, shear = None, @@ -635,6 +648,7 @@ class LerpPosQuatScaleShearInterval(LerpNodePathInterval): self.setupParam(self.setStartShear, self.startShear) LerpNodePathInterval.privDoEvent(self, t, event) + class LerpColorInterval(LerpNodePathInterval): def __init__(self, nodePath, duration, color, startColor = None, other = None, blendType = 'noBlend', @@ -647,6 +661,7 @@ class LerpColorInterval(LerpNodePathInterval): if override is not None: self.setOverride(override) + class LerpColorScaleInterval(LerpNodePathInterval): def __init__(self, nodePath, duration, colorScale, startColorScale = None, other = None, blendType = 'noBlend', @@ -659,6 +674,7 @@ class LerpColorScaleInterval(LerpNodePathInterval): if override is not None: self.setOverride(override) + class LerpTexOffsetInterval(LerpNodePathInterval): def __init__(self, nodePath, duration, texOffset, startTexOffset = None, other = None, blendType = 'noBlend', @@ -674,6 +690,7 @@ class LerpTexOffsetInterval(LerpNodePathInterval): if override is not None: self.setOverride(override) + class LerpTexRotateInterval(LerpNodePathInterval): def __init__(self, nodePath, duration, texRotate, startTexRotate = None, other = None, blendType = 'noBlend', @@ -689,6 +706,7 @@ class LerpTexRotateInterval(LerpNodePathInterval): if override is not None: self.setOverride(override) + class LerpTexScaleInterval(LerpNodePathInterval): def __init__(self, nodePath, duration, texScale, startTexScale = None, other = None, blendType = 'noBlend', @@ -705,8 +723,6 @@ class LerpTexScaleInterval(LerpNodePathInterval): self.setOverride(override) - - # # The remaining intervals defined in this module are the old-school # Python-based intervals. @@ -733,6 +749,7 @@ class LerpFunctionNoStateInterval(Interval.Interval): # create LerpFunctionInterval DirectNotify category notify = directNotify.newCategory('LerpFunctionNoStateInterval') # Class methods + def __init__(self, function, duration = 0.0, fromData = 0, toData = 1, blendType = 'noBlend', extraArgs = [], name = None): """__init__(function, duration, fromData, toData, name) @@ -758,9 +775,8 @@ class LerpFunctionNoStateInterval(Interval.Interval): # Initialize superclass Interval.Interval.__init__(self, name, duration) - #def privDoEvent(self,t,event): - - #print "doing event",t,event + #def privDoEvent(self, t, event): + #print("doing event", t, event) #bt = self.blendType(t/self.duration) #data = (self.fromData * (1 - bt)) + (self.toData * bt) ## Evaluate function @@ -770,7 +786,7 @@ class LerpFunctionNoStateInterval(Interval.Interval): def privStep(self, t): # Evaluate the function - #print "doing priv step",t + #print("doing priv step", t) if t >= self.duration: # Set to end value if t > self.duration: @@ -787,12 +803,14 @@ class LerpFunctionNoStateInterval(Interval.Interval): self.function(*[data] + self.extraArgs) # 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.currT = t # New interface + + class LerpFuncNS(LerpFunctionNoStateInterval): def __init__(self, *args, **kw): LerpFunctionNoStateInterval.__init__(self, *args, **kw) @@ -810,6 +828,7 @@ class LerpFunctionInterval(Interval.Interval): # create LerpFunctionInterval DirectNotify category notify = directNotify.newCategory('LerpFunctionInterval') # Class methods + def __init__(self, function, duration = 0.0, fromData = 0, toData = 1, blendType = 'noBlend', extraArgs = [], name = None): """__init__(function, duration, fromData, toData, name) @@ -838,7 +857,7 @@ class LerpFunctionInterval(Interval.Interval): def privStep(self, t): # Evaluate the function - #print "doing priv step",t + #print("doing priv step", t) if t >= self.duration: # Set to end value self.function(*[self.toData] + self.extraArgs) @@ -853,12 +872,14 @@ class LerpFunctionInterval(Interval.Interval): self.function(*[data] + self.extraArgs) # 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.currT = t # New interface + + class LerpFunc(LerpFunctionInterval): def __init__(self, *args, **kw): LerpFunctionInterval.__init__(self, *args, **kw) diff --git a/direct/src/leveleditor/AnimMgrBase.py b/direct/src/leveleditor/AnimMgrBase.py index 40f8cdf59b..22260879ac 100755 --- a/direct/src/leveleditor/AnimMgrBase.py +++ b/direct/src/leveleditor/AnimMgrBase.py @@ -25,23 +25,23 @@ class AnimMgrBase: #normal properties self.lerpFuncs = { - 'H' : self.lerpFuncH, - 'P' : self.lerpFuncP, - 'R' : self.lerpFuncR, - 'SX' : self.lerpFuncSX, - 'SY' : self.lerpFuncSY, - 'SZ' : self.lerpFuncSZ, - 'CR' : self.lerpFuncCR, - 'CG' : self.lerpFuncCG, - 'CB' : self.lerpFuncCB, - 'CA' : self.lerpFuncCA + 'H': self.lerpFuncH, + 'P': self.lerpFuncP, + 'R': self.lerpFuncR, + 'SX': self.lerpFuncSX, + 'SY': self.lerpFuncSY, + 'SZ': self.lerpFuncSZ, + 'CR': self.lerpFuncCR, + 'CG': self.lerpFuncCG, + 'CB': self.lerpFuncCB, + 'CA': self.lerpFuncCA } #Properties which has animation curves self.curveLerpFuncs = { - 'X' : [ self.lerpFuncX, self.lerpCurveFuncX ], - 'Y' : [ self.lerpFuncY, self.lerpCurveFuncY ], - 'Z' : [ self.lerpFuncZ, self.lerpCurveFuncZ ] + 'X': [self.lerpFuncX, self.lerpCurveFuncX], + 'Y': [self.lerpFuncY, self.lerpCurveFuncY], + 'Z': [self.lerpFuncZ, self.lerpCurveFuncZ] } def reset(self): diff --git a/direct/src/leveleditor/CurveAnimUI.py b/direct/src/leveleditor/CurveAnimUI.py index ca6a47b489..0f55777f65 100755 --- a/direct/src/leveleditor/CurveAnimUI.py +++ b/direct/src/leveleditor/CurveAnimUI.py @@ -10,6 +10,7 @@ class CurveAnimUI(wx.Dialog): """ This is the Curve Animation Panel implementation. """ + def __init__(self, parent, editor): wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title="Curve Animation", pos=wx.DefaultPosition, size=(430, 140)) @@ -20,19 +21,19 @@ class CurveAnimUI(wx.Dialog): self.mainPanel = wx.Panel(self, -1) - self.chooseNode = wx.StaticText( self.mainPanel, -1, "Choose NodePath:") - self.chooseNodeTxt = wx.TextCtrl( self.mainPanel, -1, "") - self.chooseNodeButton = wx.Button( self.mainPanel, -1, "Choose..") + self.chooseNode = wx.StaticText(self.mainPanel, -1, "Choose NodePath:") + self.chooseNodeTxt = wx.TextCtrl(self.mainPanel, -1, "") + self.chooseNodeButton = wx.Button(self.mainPanel, -1, "Choose..") - self.chooseCurve = wx.StaticText( self.mainPanel, -1, "Choose attch Curve:") - self.chooseCurveTxt = wx.TextCtrl( self.mainPanel, -1, "") - self.chooseCurveButton = wx.Button( self.mainPanel, -1, "Choose..") + self.chooseCurve = wx.StaticText(self.mainPanel, -1, "Choose attch Curve:") + self.chooseCurveTxt = wx.TextCtrl(self.mainPanel, -1, "") + self.chooseCurveButton = wx.Button(self.mainPanel, -1, "Choose..") - self.duritionTime = wx.StaticText( self.mainPanel, -1, "Durition(Frame):") - self.duritionTimeSpin = wx.SpinCtrl( self.mainPanel, -1, "",size = (70,25), min=24, max=10000) + self.duritionTime = wx.StaticText(self.mainPanel, -1, "Durition(Frame):") + self.duritionTimeSpin = wx.SpinCtrl(self.mainPanel, -1, "", size=(70,25), min=24, max=10000) - self.createAnimButton = wx.Button( self.mainPanel, -1, "Creat") - self.saveAnimButton = wx.Button( self.mainPanel, -1, "Save Animation") + self.createAnimButton = wx.Button(self.mainPanel, -1, "Creat") + self.saveAnimButton = wx.Button(self.mainPanel, -1, "Save Animation") self.SetProperties() self.DoLayout() @@ -46,44 +47,44 @@ class CurveAnimUI(wx.Dialog): def SetProperties(self): self.duritionTimeSpin.SetValue(24) - self.chooseNodeTxt.SetMinSize((200,21)) - self.chooseCurveTxt.SetMinSize((200,21)) + self.chooseNodeTxt.SetMinSize((200, 21)) + self.chooseCurveTxt.SetMinSize((200, 21)) self.saveAnimButton.SetToolTipString("Save the animation to the global animation control") def DoLayout(self): dialogSizer = wx.BoxSizer(wx.VERTICAL) mainSizer = wx.FlexGridSizer(4, 3, 0, 0) - 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.chooseNodeButton, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5) + 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.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.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.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.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.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.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.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) - 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.Layout() 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'): - 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.Destroy() else: obj = self.editor.objectMgr.findObjectByNodePath(base.direct.selected.last) 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.Destroy() else: @@ -92,13 +93,13 @@ class CurveAnimUI(wx.Dialog): 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'): - 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.Destroy() else: obj = self.editor.objectMgr.findObjectByNodePath(base.direct.selected.last) 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.Destroy() elif obj[OG.OBJ_DEF].name == '__Curve__': @@ -108,43 +109,45 @@ class CurveAnimUI(wx.Dialog): def OnCreateAnim(self, evt): self.time = self.duritionTimeSpin.GetValue() 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.Destroy() else: self.curveSequence = self.editor.animMgr.singleCurveAnimation(self.nodePath, self.curve, self.time) self.curveSequence.start() - def OnSaveAnim(self,evt): + def OnSaveAnim(self, evt): 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.Destroy() else: 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') return hasKey = False for key in self.editor.animMgr.curveAnimation: 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.Destroy() hasKey = True return 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.Destroy() hasKey = True return 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') - def OnExit(self,evt): + def OnExit(self, evt): self.Destroy() self.editor.ui.curveAnimMenuItem.Check(False) diff --git a/direct/src/leveleditor/CurveEditor.py b/direct/src/leveleditor/CurveEditor.py index 08083962e0..0b131a6a91 100755 --- a/direct/src/leveleditor/CurveEditor.py +++ b/direct/src/leveleditor/CurveEditor.py @@ -11,6 +11,7 @@ from direct.task import Task class CurveEditor(DirectObject): """ CurveEditor will create and edit the curve """ + def __init__(self, editor): self.editor = editor self.i = 0 @@ -76,11 +77,11 @@ class CurveEditor(DirectObject): self.i = 0 for item in self.curveControl: item[1].hide() - if self.editor.preMode == self.editor.BASE_MODE : + if self.editor.preMode == self.editor.BASE_MODE: pass - if self.editor.preMode == self.editor.CREATE_CURVE_MODE : + if self.editor.preMode == self.editor.CREATE_CURVE_MODE: self.updateScene() - if self.editor.preMode == self.editor.EDIT_CURVE_MODE : + if self.editor.preMode == self.editor.EDIT_CURVE_MODE: self.doneEdit() self.curveControl = [] self.curve = [] diff --git a/direct/src/leveleditor/FileMgr.py b/direct/src/leveleditor/FileMgr.py index 1f11dc7133..09c1c4d09c 100755 --- a/direct/src/leveleditor/FileMgr.py +++ b/direct/src/leveleditor/FileMgr.py @@ -48,5 +48,5 @@ class FileMgr: module = imp.load_module(moduleName, file, pathname, description) self.editor.updateStatusReadout('Sucessfully opened file %s'%fileName) self.editor.fNeedToSave = False - except: + except Exception: print('failed to load %s'%fileName) diff --git a/direct/src/leveleditor/GraphEditorUI.py b/direct/src/leveleditor/GraphEditorUI.py index 7c256f6dd6..81b2cc9333 100755 --- a/direct/src/leveleditor/GraphEditorUI.py +++ b/direct/src/leveleditor/GraphEditorUI.py @@ -11,7 +11,7 @@ property = [ "translateX", "translateY", "translateZ" - ] +] #---------------------------------------------------------------------- ZoomIn = PyEmbeddedImage( @@ -79,10 +79,12 @@ TwoTangents = PyEmbeddedImage( #---------------------------------------------------------------------- + class GraphEditorWindow(wx.Window): """ This is the main graph editor window. """ + def __init__(self, parent, windowSize, property, xRange, yRange, curFrame, object): 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]) return - if len(list)>=3 : + if len(list) >= 3: for i in range(len(list)-1): x1 = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0] y1 = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1] @@ -406,7 +408,6 @@ class GraphEditorWindow(wx.Window): scale1 = (x2 - x1) / t1x y2 = y1 - t1y * scale1 - x3 = x4 - (x4 - x1) / 3.0 scale2 = (x4 - x3) / t2x y3 = y4 + t2y * scale2 @@ -445,12 +446,12 @@ class GraphEditorWindow(wx.Window): pointY = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1] 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.DrawCircle(pointX, pointY, 2) 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.DrawCircle(pointX, pointY, 2) @@ -460,64 +461,64 @@ class GraphEditorWindow(wx.Window): X1 = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0] Y1 = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1] 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] Y = list[i][j][AG.LOCAL_VALUE][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.DrawCircle(X, Y, 2) - dc.SetPen(wx.Pen("cyan",1)) + dc.SetPen(wx.Pen("cyan", 1)) dc.DrawLine(X1, Y1, X, Y) 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.DrawCircle(X, Y, 2) - dc.SetPen(wx.Pen("brown",1)) + dc.SetPen(wx.Pen("brown", 1)) dc.DrawLine(X1, Y1, X, Y) if self._OneTangent is False: if list[i][AG.IN_TANGENT][AG.SELECT] == 1: X = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][0] 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.DrawCircle(X, Y, 2) - dc.SetPen(wx.Pen("cyan",1)) + dc.SetPen(wx.Pen("cyan", 1)) dc.DrawLine(X1, Y1, X, Y) if list[i][AG.IN_TANGENT][AG.SELECT] == 0: X = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][0] 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.DrawCircle(X, Y, 2) - dc.SetPen(wx.Pen("navy",1)) + dc.SetPen(wx.Pen("navy", 1)) dc.DrawLine(X1, Y1, X, Y) if list[i][AG.OUT_TANGENT][AG.SELECT] == 1: X = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][0] 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.DrawCircle(X, Y, 2) - dc.SetPen(wx.Pen("cyan",1)) + dc.SetPen(wx.Pen("cyan", 1)) dc.DrawLine(X1, Y1, X, Y) if list[i][AG.OUT_TANGENT][AG.SELECT] == 0: X = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][0] 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.DrawCircle(X, Y, 2) - dc.SetPen(wx.Pen("brown",1)) + dc.SetPen(wx.Pen("brown", 1)) dc.DrawLine(X1, Y1, X, Y) def DrawSelectRec(self, dc): @@ -706,7 +707,7 @@ class GraphEditorWindow(wx.Window): newPointX = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][0] + moveX 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] 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 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] 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. """ + def __init__(self, parent, editor, object): wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title="Graph Editor", pos=wx.DefaultPosition, size=(735, 535)) @@ -805,10 +807,10 @@ class GraphEditorUI(wx.Dialog): bmpOneTangent = OneTangent.GetBitmap() bmpTwoTangents = TwoTangents.GetBitmap() - 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.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.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.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.mainPanel2 = wx.Panel(self, -1) diff --git a/direct/src/leveleditor/LayerEditorUI.py b/direct/src/leveleditor/LayerEditorUI.py index c2fccfd7b1..082d15b01a 100644 --- a/direct/src/leveleditor/LayerEditorUI.py +++ b/direct/src/leveleditor/LayerEditorUI.py @@ -16,7 +16,7 @@ class LayerEditorUI(wx.Panel): self.layersDataDict = dict() self.layersDataDictNextKey = 0 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") sizer = wx.BoxSizer(wx.VERTICAL) @@ -170,7 +170,7 @@ class LayerEditorUI(wx.Panel): def removeObj(self): objNodePath = base.direct.selected.last 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 obj = self.editor.objectMgr.findObjectByNodePath(objNodePath) if obj is not None: @@ -179,11 +179,11 @@ class LayerEditorUI(wx.Panel): def addObj(self): index = self.llist.GetFirstSelected() 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 objNodePath = base.direct.selected.last 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 # Checking if the object was laready added to the layer @@ -193,7 +193,7 @@ class LayerEditorUI(wx.Panel): layersData = self.layersDataDict[i] for j in range(len(layersData)): 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 # Looking for the object in the other layers # If the object is found - delete it. @@ -220,7 +220,7 @@ class LayerEditorUI(wx.Panel): def HideObj(self, hide): index = self.llist.GetFirstSelected() 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 key = self.llist.GetItemData(index) diff --git a/direct/src/leveleditor/LevelEditorBase.py b/direct/src/leveleditor/LevelEditorBase.py index f98b7f1038..c7b748aa56 100755 --- a/direct/src/leveleditor/LevelEditorBase.py +++ b/direct/src/leveleditor/LevelEditorBase.py @@ -28,6 +28,7 @@ from .MayaConverter import FROM_BAM_TO_MAYA, MayaConverter class LevelEditorBase(DirectObject): """ Base Class for Panda3D LevelEditor """ + def __init__(self): #loadPrcFileData('startup', 'window-type none') self.currentFile = None @@ -86,7 +87,7 @@ class LevelEditorBase(DirectObject): ('DIRECT-mouse3', self.handleMouse3), ('DIRECT-mouse3Up', self.handleMouse3Up), ('DIRECT-toggleWidgetVis', self.toggleWidget), - ]) + ]) # Add all the action events for event in self.actionEvents: @@ -143,14 +144,12 @@ class LevelEditorBase(DirectObject): if base.direct.fAlt or modifiers == 4: self.fMoveCamera = True return - if self.mode == self.CREATE_CURVE_MODE : + if self.mode == self.CREATE_CURVE_MODE: self.curveEditor.createCurve() - def handleMouse1Up(self): self.fMoveCamera = False - def handleMouse2(self, modifiers): if base.direct.fAlt or modifiers == 4: self.fMoveCamera = True diff --git a/direct/src/leveleditor/LevelEditorUIBase.py b/direct/src/leveleditor/LevelEditorUIBase.py index d2ec98b9e5..126bbf9f6b 100755 --- a/direct/src/leveleditor/LevelEditorUIBase.py +++ b/direct/src/leveleditor/LevelEditorUIBase.py @@ -21,6 +21,7 @@ from .AnimControlUI import AnimControlUI from .CurveAnimUI import CurveAnimUI from .GraphEditorUI import GraphEditorUI + class PandaTextDropTarget(wx.TextDropTarget): def __init__(self, editor, view): wx.TextDropTarget.__init__(self) @@ -104,6 +105,7 @@ class PandaTextDropTarget(wx.TextDropTarget): iRay.collisionNodePath.removeNode() del iRay + ID_NEW = 101 ID_OPEN = 102 ID_SAVE = 103 @@ -129,32 +131,34 @@ ID_CURVE_ANIM = 603 ID_ANIM = 701 ID_GRAPH = 702 + class LevelEditorUIBase(WxPandaShell): """ Class for Panda3D LevelEditor """ + def __init__(self, editor): self.MENU_TEXTS.update({ - ID_NEW : ("&New", "LE-NewScene"), - ID_OPEN : ("&Open", "LE-OpenScene"), - ID_SAVE : ("&Save", "LE-SaveScene"), - ID_SAVE_AS : ("Save &As", None), - ID_EXPORT_TO_MAYA : ("Export to Maya", None), - wx.ID_EXIT : ("&Quit", "LE-Quit"), - ID_DUPLICATE : ("&Duplicate", "LE-Duplicate"), - ID_MAKE_LIVE : ("Make &Live", "LE-MakeLive"), - ID_UNDO : ("&Undo", "LE-Undo"), - ID_REDO : ("&Redo", "LE-Redo"), - ID_SHOW_GRID : ("&Show Grid", None), - ID_GRID_SIZE : ("&Grid Size", None), - ID_GRID_SNAP : ("Grid S&nap", None), - ID_SHOW_PANDA_OBJECT : ("Show &Panda Objects", None), - ID_HOT_KEYS : ("&Hot Keys", None), - ID_PARENT_TO_SELECTED : ("&Parent To Selected", None), - ID_CREATE_CURVE : ("&Create Curve", None), - ID_EDIT_CURVE : ("&Edit Curve", None), - ID_CURVE_ANIM : ("&Curve Animation", None), - ID_ANIM : ("&Edit Animation", None), - ID_GRAPH : ("&Graph Editor", None) - }) + ID_NEW: ("&New", "LE-NewScene"), + ID_OPEN: ("&Open", "LE-OpenScene"), + ID_SAVE: ("&Save", "LE-SaveScene"), + ID_SAVE_AS: ("Save &As", None), + ID_EXPORT_TO_MAYA: ("Export to Maya", None), + wx.ID_EXIT: ("&Quit", "LE-Quit"), + ID_DUPLICATE: ("&Duplicate", "LE-Duplicate"), + ID_MAKE_LIVE: ("Make &Live", "LE-MakeLive"), + ID_UNDO: ("&Undo", "LE-Undo"), + ID_REDO: ("&Redo", "LE-Redo"), + ID_SHOW_GRID: ("&Show Grid", None), + ID_GRID_SIZE: ("&Grid Size", None), + ID_GRID_SNAP: ("Grid S&nap", None), + ID_SHOW_PANDA_OBJECT: ("Show &Panda Objects", None), + ID_HOT_KEYS: ("&Hot Keys", None), + ID_PARENT_TO_SELECTED: ("&Parent To Selected", None), + ID_CREATE_CURVE: ("&Create Curve", None), + ID_EDIT_CURVE: ("&Edit Curve", None), + ID_CURVE_ANIM: ("&Curve Animation", None), + ID_ANIM: ("&Edit Animation", None), + ID_GRAPH: ("&Graph Editor", None) + }) self.editor = editor WxPandaShell.__init__(self, fStartDirect=True) @@ -245,9 +249,9 @@ class LevelEditorUIBase(WxPandaShell): WxPandaShell.createMenu(self) - def onGraphEditor(self,e): + def onGraphEditor(self, e): 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.Destroy() self.graphEditorMenuItem.Check(False) @@ -257,7 +261,7 @@ class LevelEditorUIBase(WxPandaShell): self.graphEditorUI.Show() self.graphEditorMenuItem.Check(True) - def onAnimation(self,e): + def onAnimation(self, e): if self.editor.mode != self.editor.ANIM_MODE: self.animUI = AnimControlUI(self, self.editor) self.animUI.Show() @@ -265,12 +269,12 @@ class LevelEditorUIBase(WxPandaShell): if self.editor.mode == self.editor.ANIM_MODE: self.editAnimMenuItem.Check(True) - def onCurveAnim(self,e): + def onCurveAnim(self, e): self.curveAnimUI = CurveAnimUI(self, self.editor) self.curveAnimUI.Show() self.curveAnimMenuItem.Check(True) - def onCreateCurve(self,e): + def onCreateCurve(self, e): """Function to invoke curve creating, need to check previous mode""" if self.editor.mode == self.editor.CREATE_CURVE_MODE: self.createCurveMenuItem.Check(False) @@ -284,7 +288,7 @@ class LevelEditorUIBase(WxPandaShell): else: self.currentView = self.getCurrentView() 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.Destroy() self.createCurveMenuItem.Check(False) @@ -297,7 +301,7 @@ class LevelEditorUIBase(WxPandaShell): base.direct.manipulationControl.disableManipulation() 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""" if self.editor.mode == self.editor.EDIT_CURVE_MODE: self.editCurveMenuItem.Check(False) @@ -310,11 +314,11 @@ class LevelEditorUIBase(WxPandaShell): self.onEditCurve(None) else: 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.Destroy() self.editCurveMenuItem.Check(False) - if base.direct.selected.last is not None : + if base.direct.selected.last is not None: base.direct.manipulationControl.enableManipulation() self.createCurveMenuItem.Check(False) self.curveObj = self.editor.objectMgr.findObjectByNodePath(base.direct.selected.last) @@ -328,7 +332,7 @@ class LevelEditorUIBase(WxPandaShell): item[1].show() self.editor.curveEditor.curve.append((None, item[1].getPos())) 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.Destroy() self.editCurveMenuItem.Check(False) @@ -603,6 +607,7 @@ class LevelEditorUIBase(WxPandaShell): else: self.editor.objectMgr.replaceObjectWithTypeName(currObj, targetType) + class GridSizeUI(wx.Dialog): def __init__(self, parent, id, title, gridSize, gridSpacing): wx.Dialog.__init__(self, parent, id, title, size=(250, 240)) @@ -640,8 +645,10 @@ class GridSizeUI(wx.Dialog): base.le.ui.bindKeyEvents(True) self.Destroy() + class ViewportMenu(wx.Menu): """Represents a menu that appears when right-clicking a viewport.""" + def __init__(self): wx.Menu.__init__(self) @@ -664,6 +671,7 @@ class ViewportMenu(wx.Menu): parent.AppendMenu(id, name, subMenu) return subMenu + class CurveDegreeUI(wx.Dialog): def __init__(self, parent, id, title): wx.Dialog.__init__(self, parent, id, title, size=(150, 120)) diff --git a/direct/src/leveleditor/LevelLoaderBase.py b/direct/src/leveleditor/LevelLoaderBase.py index 1e3489e96b..3602603cd1 100755 --- a/direct/src/leveleditor/LevelLoaderBase.py +++ b/direct/src/leveleditor/LevelLoaderBase.py @@ -1,5 +1,6 @@ import imp + class LevelLoaderBase: """ Base calss for LevelLoader @@ -7,6 +8,7 @@ class LevelLoaderBase: which you will use to load level editor data in your game. Refer LevelLoader.py for example. """ + def __init__(self): self.defaultPath = None # this should be set in your LevelLoader.py self.initLoader() @@ -32,6 +34,6 @@ class LevelLoaderBase: try: module = imp.load_module(fileName, file, pathname, description) return True - except: + except Exception: print('failed to load %s'%fileName) return None diff --git a/direct/src/leveleditor/ObjectMgrBase.py b/direct/src/leveleditor/ObjectMgrBase.py index 33dad9a4bc..414531280e 100755 --- a/direct/src/leveleditor/ObjectMgrBase.py +++ b/direct/src/leveleditor/ObjectMgrBase.py @@ -18,7 +18,8 @@ from . import ObjectGlobals as OG # python wrapper around a panda.NodePath object class PythonNodePath(NodePath): def __init__(self,node): - NodePath.__init__(self,node) + NodePath.__init__(self, node) + class ObjectMgrBase: """ ObjectMgr will create, manage, update objects in the scene """ @@ -89,21 +90,21 @@ class ObjectMgrBase: for item in curveInfo: controler = base.render.attachNewNode("controler") controler = base.loader.loadModel('models/misc/smiley') - controlerPathname = 'controler%d' % item[0] + controlerPathname = f'controler{item[0]}' controler.setName(controlerPathname) controler.setPos(item[1]) controler.setColor(0, 0, 0, 1) controler.setScale(0.2) controler.reparentTo(base.render) - controler.setTag('OBJRoot','1') - controler.setTag('Controller','1') + controler.setTag('OBJRoot', '1') + controler.setTag('Controller', '1') curve.append((None, item[1])) curveControl.append((item[0], controler)) self.editor.curveEditor.degree = degree - self.editor.curveEditor.ropeUpdate (curve) + self.editor.curveEditor.ropeUpdate(curve) #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) self.editor.objectMgr.updateObjectPropValue(curveObj, 'Degree', degree, fSelectObject=False, fUndo=False) @@ -136,7 +137,7 @@ class ObjectMgrBase: newobj = nodePath newobj.reparentTo(parent) - newobj.setTag('OBJRoot','1') + newobj.setTag('OBJRoot', '1') # populate obj data using default values properties = {} @@ -254,7 +255,7 @@ class ObjectMgrBase: return None newobj.reparentTo(parent) - newobj.setTag('OBJRoot','1') + newobj.setTag('OBJRoot', '1') # populate obj data using default values properties = {} @@ -276,11 +277,11 @@ class ObjectMgrBase: obj = self.findObjectById(uid) 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: del self.Actor[i] 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: del self.Nodes[i] break @@ -300,11 +301,11 @@ class ObjectMgrBase: def removeObjectByNodePath(self, nodePath): uid = self.npIndex.get(nodePath) 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: del self.Actor[i] 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: del self.Nodes[i] break @@ -520,7 +521,7 @@ class ObjectMgrBase: return self.flatten(newobjModel, model, objDef, uid) newobj = PythonNodePath(newobjModel) - newobj.setTag('OBJRoot','1') + newobj.setTag('OBJRoot', '1') # reparent children objNP.findAllMatches("=OBJRoot").reparentTo(newobj) @@ -921,7 +922,6 @@ class ObjectMgrBase: self.findActors(child) - def findNodes(self, parent): for child in parent.getChildren(): if child.hasTag('OBJRoot') and not child.hasTag('Controller'): diff --git a/direct/src/leveleditor/ObjectPalette.py b/direct/src/leveleditor/ObjectPalette.py index 157570b36c..9da728efe4 100755 --- a/direct/src/leveleditor/ObjectPalette.py +++ b/direct/src/leveleditor/ObjectPalette.py @@ -17,6 +17,7 @@ and in the populate function you can define ObjectPalette tree structure. from . import ObjectGlobals as OG from .ObjectPaletteBase import ObjectBase, ObjectPaletteBase + class ObjectProp(ObjectBase): def __init__(self, *args, **kw): ObjectBase.__init__(self, *args, **kw) @@ -84,7 +85,7 @@ class ObjectPalette(ObjectPaletteBase): ('.updateSmiley', {'val':OG.ARG_VAL, 'obj':OG.ARG_OBJ}), 1, [1, 10]], - }), + }), 'Prop') # This object type will be added under the 'Prop' group. self.add(ObjectDoubleSmileys(name='H Double Smiley', createFunction = ('.createDoubleSmiley', {})), diff --git a/direct/src/leveleditor/ObjectPaletteBase.py b/direct/src/leveleditor/ObjectPaletteBase.py index f91461f843..6b7b0b2ac7 100755 --- a/direct/src/leveleditor/ObjectPaletteBase.py +++ b/direct/src/leveleditor/ObjectPaletteBase.py @@ -4,14 +4,19 @@ from . import ObjectGlobals as OG class ObjectGen: """ Base class for obj definitions """ + def __init__(self, name=''): self.name = name class ObjectBase(ObjectGen): """ 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) self.createFunction = createFunction self.model = model @@ -33,11 +38,14 @@ class ObjectBase(ObjectGen): class ObjectCurve(ObjectBase): def __init__(self, *args, **kw): ObjectBase.__init__(self, *args, **kw) - self.properties['Degree'] =[OG.PROP_UI_COMBO, # UI type - OG.PROP_INT, # data type - ('base.le.objectMgr.updateCurve', {'val':OG.ARG_VAL, 'obj':OG.ARG_OBJ}), # update function - 3, # default value - [2, 3, 4]] # value range + self.properties['Degree'] = [ + OG.PROP_UI_COMBO, # UI type + OG.PROP_INT, # data type + ('base.le.objectMgr.updateCurve', {'val': OG.ARG_VAL, 'obj': OG.ARG_OBJ}), # update function + 3, # default value + [2, 3, 4], # value range + ] + class ObjectPaletteBase: """ @@ -72,9 +80,9 @@ class ObjectPaletteBase: self.data[item.name] = item self.dataKeys.append(item.name) - def add(self, item, parentName = None): + def add(self, item, parentName=None): if isinstance(item, str): - self.insertItem(ObjectGen(name = item), parentName) + self.insertItem(ObjectGen(name=item), parentName) else: self.insertItem(item, parentName) @@ -91,9 +99,8 @@ class ObjectPaletteBase: if node is not None: deleteItems[key] = node return item - except: + except Exception: return None - return None def delete(self, name): try: @@ -103,14 +110,13 @@ class ObjectPaletteBase: deleteItems[name] = node for key in list(deleteItems.keys()): item = self.dataStruct.pop(key) - except: + except Exception: return - return def findItem(self, name): try: item = self.data[name] - except: + except Exception: return None return item @@ -137,7 +143,7 @@ class ObjectPaletteBase: item = self.data.pop(oldName) item.name = newName self.data[newName] = item - except: + except Exception: return False return True diff --git a/direct/src/leveleditor/ObjectPropertyUI.py b/direct/src/leveleditor/ObjectPropertyUI.py index 2e6e7c0196..0e163004e4 100755 --- a/direct/src/leveleditor/ObjectPropertyUI.py +++ b/direct/src/leveleditor/ObjectPropertyUI.py @@ -24,6 +24,7 @@ Key = PyEmbeddedImage( "EMaYtpbOXlu01vf5Hz/wDRuDdIDl5WtQAAAAAElFTkSuQmCC") #---------------------------------------------------------------------- + class AnimFileDrop(wx.FileDropTarget): def __init__(self, editor): wx.FileDropTarget.__init__(self) @@ -56,11 +57,13 @@ class AnimFileDrop(wx.FileDropTarget): obj[OG.OBJ_ANIM] = animName self.editor.ui.objectPropertyUI.updateProps(obj) + class ObjectPropUI(wx.Panel): """ Base class for ObjectPropUIs, It consists of label area and ui area. """ + def __init__(self, parent, label): wx.Panel.__init__(self, parent) self.parent = parent @@ -80,24 +83,22 @@ class ObjectPropUI(wx.Panel): self.setKeyButton.Bind(wx.EVT_BUTTON, self.onKey) - def onKey(self,evt): + def onKey(self, evt): self.parent = wx.GetTopLevelParent(self) if self.parent.editor.mode == self.parent.editor.ANIM_MODE: - obj= self.parent.editor.objectMgr.findObjectByNodePath(base.direct.selected.last) - - objUID = obj[OG.OBJ_UID] - propertyName = self.label.GetLabelText() + obj = self.parent.editor.objectMgr.findObjectByNodePath(base.direct.selected.last) value = self.getValue() frame = self.parent.editor.ui.animUI.curFrame - if (objUID, propertyName) in self.parent.editor.animMgr.keyFramesInfo: - for i in range(len(self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)])): - if self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)][i][AG.FRAME] == frame: - del self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)][i] - self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)].append([frame, value, [], []]) + if property in self.parent.editor.animMgr.keyFramesInfo: + for i in range(len(self.parent.editor.animMgr.keyFramesInfo[property])): + if self.parent.editor.animMgr.keyFramesInfo[property][i][AG.FRAME] == frame: + del self.parent.editor.animMgr.keyFramesInfo[property][i] + + self.parent.editor.animMgr.keyFramesInfo[property].append([frame, value, [], []]) #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 j in range(i+1, len(sortKeyList)): if sortKeyList[i][AG.FRAME]>sortKeyList[j][AG.FRAME]: @@ -105,9 +106,9 @@ class ObjectPropUI(wx.Panel): sortKeyList[i] = sortKeyList[j] 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: - self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)] = [[frame, value, [], []]] + self.parent.editor.animMgr.keyFramesInfo[property] = [[frame, value, [], []]] exist = False for keyFrame in self.parent.editor.animMgr.keyFrames: @@ -133,8 +134,10 @@ class ObjectPropUI(wx.Panel): if valFunc: self.ui.Bind(self.eventType, valFunc) + class ObjectPropUIEntry(ObjectPropUI): """ UI for string value properties """ + def __init__(self, parent, label): ObjectPropUI.__init__(self, parent, label) self.ui = wx.TextCtrl(self.uiPane, -1) @@ -144,8 +147,10 @@ class ObjectPropUIEntry(ObjectPropUI): def setValue(self, value): self.ui.SetValue(str(value)) + class ObjectPropUISlider(ObjectPropUI): """ UI for float value properties """ + def __init__(self, parent, label, value, minValue, maxValue): ObjectPropUI.__init__(self, parent, label) self.ui = WxSlider(self.uiPane, -1, value, minValue, maxValue, @@ -166,6 +171,7 @@ class ObjectPropUISlider(ObjectPropUI): class ObjectPropUISpinner(ObjectPropUI): """ UI for int value properties """ + def __init__(self, parent, label, value, minValue, maxValue): ObjectPropUI.__init__(self, parent, label) self.ui = wx.SpinCtrl(self.uiPane, -1, "", min=minValue, max=maxValue, initial=value) @@ -218,6 +224,7 @@ class ObjectPropUICombo(ObjectPropUI): def setItems(self, valueList): self.ui.SetItems(valueList) + class ObjectPropUITime(wx.Panel): def __init__(self, parent, label, value): wx.Panel.__init__(self, parent) @@ -288,9 +295,11 @@ class ObjectPropUITime(wx.Panel): self.uiHour.Bind(self.eventType, valFunc) self.uiMin.Bind(self.eventType, valFunc) + class ColorPicker(CubeColourDialog): - def __init__(self, parent, colourData=None, style=CCD_SHOW_ALPHA, alpha = 255, updateCB=None, exitCB=None): - self.updateCB=updateCB + def __init__(self, parent, colourData=None, style=CCD_SHOW_ALPHA, + alpha=255, updateCB=None, exitCB=None): + self.updateCB = updateCB CubeColourDialog.__init__(self, parent, colourData, style) self.okButton.Hide() self.cancelButton.Hide() @@ -306,6 +315,7 @@ class ColorPicker(CubeColourDialog): if self.updateCB: self.updateCB(self._colour.r, self._colour.g, self._colour.b, self._colour.alpha) + class ObjectPropertyUI(ScrolledPanel): def __init__(self, parent, editor): self.editor = editor @@ -329,7 +339,7 @@ class ObjectPropertyUI(ScrolledPanel): self.propPane.Destroy() self.SetSizer(None) 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): self.lastColorPickerPos = self.colorPicker.GetPosition() @@ -414,8 +424,11 @@ class ObjectPropertyUI(ScrolledPanel): self.propSY = ObjectPropUIEntry(self.transformPane, 'SY') self.propSZ = ObjectPropUIEntry(self.transformPane, 'SZ') - transformProps = [self.propX, self.propY, self.propZ, self.propH, self.propP, self.propR, - self.propSX, self.propSY, self.propSZ] + transformProps = [ + self.propX, self.propY, self.propZ, + self.propH, self.propP, self.propR, + self.propSX, self.propSY, self.propSZ, + ] sizer = wx.BoxSizer(wx.VERTICAL) sizer.AddMany(transformProps) @@ -635,7 +648,6 @@ class ObjectPropertyUI(ScrolledPanel): self.editor.objectMgr.onLeaveObjectPropUI, lambda p0=None, p1=obj, p2=key: self.editor.objectMgr.updateObjectProperty(p0, p1, p2)) - self.propsPane.SetSizer(sizer) self.Layout() self.SetupScrolling(self, scroll_y = True, rate_y = 20) diff --git a/direct/src/leveleditor/ProtoObjs.py b/direct/src/leveleditor/ProtoObjs.py index 59d433421e..cecc82a90b 100755 --- a/direct/src/leveleditor/ProtoObjs.py +++ b/direct/src/leveleditor/ProtoObjs.py @@ -9,7 +9,7 @@ class ProtoObjs: def __init__(self, name): self.dirname = os.path.dirname(__file__) self.name = name - self.filename = "/%s.py" % (name) + self.filename = f"/{name}.py" self.data = {} def populate(self): @@ -18,16 +18,16 @@ class ProtoObjs: file, pathname, description = imp.find_module(moduleName, [self.dirname]) module = imp.load_module(moduleName, file, pathname, description) self.data = module.protoData - except: - print("%s doesn't exist"%(self.name)) + except Exception: + print(f"{self.name} doesn't exist") return def saveProtoData(self, f): if not f: return - for key in self.data.keys(): - f.write("\t'%s':'%s',\n"%(key, self.data[key])) + for key, value in self.data.items(): + f.write(f"\t'{key}':'{value}',\n") def saveToFile(self): try: @@ -36,5 +36,5 @@ class ProtoObjs: self.saveProtoData(f) f.write("}\n") f.close() - except: + except Exception: pass diff --git a/direct/src/leveleditor/SceneGraphUIBase.py b/direct/src/leveleditor/SceneGraphUIBase.py index 258264fe69..38164b8370 100755 --- a/direct/src/leveleditor/SceneGraphUIBase.py +++ b/direct/src/leveleditor/SceneGraphUIBase.py @@ -7,6 +7,7 @@ from .ActionMgr import ActionChangeHierarchy, ActionDeleteObjById from . import ObjectGlobals as OG + class SceneGraphUIDropTarget(wx.TextDropTarget): def __init__(self, editor): print("in SceneGraphUIDropTarget::init...") @@ -17,6 +18,7 @@ class SceneGraphUIDropTarget(wx.TextDropTarget): print("in SceneGraphUIDropTarget::OnDropText...") self.editor.ui.sceneGraphUI.changeHierarchy(text, x, y) + class SceneGraphUIBase(wx.Panel): def __init__(self, parent, editor): wx.Panel.__init__(self, parent) @@ -121,7 +123,7 @@ class SceneGraphUIBase(wx.Panel): if obj is None: return - if parentNP is None : + if parentNP is None: parentNP = obj[OG.OBJ_NP].getParent() parentObj = self.editor.objectMgr.findObjectByNodePath(parentNP) diff --git a/direct/src/leveleditor/testData.py b/direct/src/leveleditor/testData.py index 994da998ab..2dc05f01e6 100755 --- a/direct/src/leveleditor/testData.py +++ b/direct/src/leveleditor/testData.py @@ -68,5 +68,5 @@ if objects['1252623762.9gjeon']: if hasattr(base, 'le'): ui.layerEditorUI.reset() - ui.layerEditorUI.addLayerEntry('Layer1', 1 ) + ui.layerEditorUI.addLayerEntry('Layer1', 1) ui.layerEditorUI.addLayerData(1, '1252538687.73gjeon') diff --git a/direct/src/motiontrail/MotionTrail.py b/direct/src/motiontrail/MotionTrail.py index 86e284aebe..49b429374a 100644 --- a/direct/src/motiontrail/MotionTrail.py +++ b/direct/src/motiontrail/MotionTrail.py @@ -229,7 +229,7 @@ class MotionTrail(NodePath, DirectObject): index = 0 while index < total_motion_trails: - motion_trail = MotionTrail.motion_trail_list [index] + motion_trail = MotionTrail.motion_trail_list[index] if MotionTrail.global_enable: if motion_trail.use_python_version: @@ -577,7 +577,7 @@ class MotionTrail(NodePath, DirectObject): v0 = start_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) @@ -589,7 +589,7 @@ class MotionTrail(NodePath, DirectObject): v1 = start_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) @@ -607,7 +607,7 @@ class MotionTrail(NodePath, DirectObject): index = 0 nurbs_curve_result_list = [] 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_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_end = self.vertex_list[vertex_segment_index + 1] - start_nurbs_curve_result = nurbs_curve_result_list [vertex_segment_index] - end_nurbs_curve_result = nurbs_curve_result_list [vertex_segment_index + 1] + start_nurbs_curve_result = nurbs_curve_result_list[vertex_segment_index] + end_nurbs_curve_result = nurbs_curve_result_list[vertex_segment_index + 1] start_nurbs_start_t = start_nurbs_curve_result.getStartT() start_nurbs_end_t = start_nurbs_curve_result.getEndT() diff --git a/direct/src/particles/ParticleEffect.py b/direct/src/particles/ParticleEffect.py index 9918b57ff4..054777f3e3 100644 --- a/direct/src/particles/ParticleEffect.py +++ b/direct/src/particles/ParticleEffect.py @@ -214,7 +214,7 @@ class ParticleEffect(NodePath): data = vfs.readFile(fn, True) data = data.replace(b'\r', b'') exec(data) - except: + except Exception: self.notify.warning('loadConfig: failed to load particle file: '+ repr(filename)) raise diff --git a/direct/src/showbase/BufferViewer.py b/direct/src/showbase/BufferViewer.py index 373bd4da42..4a7babcbc2 100644 --- a/direct/src/showbase/BufferViewer.py +++ b/direct/src/showbase/BufferViewer.py @@ -89,7 +89,7 @@ class BufferViewer(DirectObject): if not self.isValidTextureSet(elt): return 0 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): """Returns true if the buffer viewer is currently enabled.""" @@ -237,8 +237,8 @@ class BufferViewer(DirectObject): self.analyzeTextureSet(win, set) elif x == "all": self.analyzeTextureSet(self.engine, set) - else: return - + else: + return def makeFrame(self, sizex, sizey): """Access: private. Each texture card is displayed with @@ -271,14 +271,14 @@ class BufferViewer(DirectObject): triangles = GeomTriangles(Geom.UHStatic) for i in range(2): delta = i*8 - triangles.addVertices(0+delta, 4+delta, 1+delta) - triangles.addVertices(1+delta, 4+delta, 5+delta) - triangles.addVertices(1+delta, 5+delta, 2+delta) - triangles.addVertices(2+delta, 5+delta, 6+delta) - triangles.addVertices(2+delta, 6+delta, 3+delta) - triangles.addVertices(3+delta, 6+delta, 7+delta) - triangles.addVertices(3+delta, 7+delta, 0+delta) - triangles.addVertices(0+delta, 7+delta, 4+delta) + triangles.addVertices(0 + delta, 4 + delta, 1 + delta) + triangles.addVertices(1 + delta, 4 + delta, 5 + delta) + triangles.addVertices(1 + delta, 5 + delta, 2 + delta) + triangles.addVertices(2 + delta, 5 + delta, 6 + delta) + triangles.addVertices(2 + delta, 6 + delta, 3 + delta) + triangles.addVertices(3 + delta, 6 + delta, 7 + delta) + triangles.addVertices(3 + delta, 7 + delta, 0 + delta) + triangles.addVertices(0 + delta, 7 + delta, 4 + delta) triangles.closePrimitive() geom = Geom(vdata) @@ -287,7 +287,6 @@ class BufferViewer(DirectObject): geomnode.addGeom(geom) return NodePath(geomnode) - def maintainReadout(self, task): """Access: private. Whenever necessary, rebuilds the entire display from scratch. This is only done when the configuration @@ -408,24 +407,24 @@ class BufferViewer(DirectObject): 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()) 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 if (v_sizey < sizey) or (v_sizex < sizex): sizey = v_sizey sizex = v_sizex adjustment = 2 - h_sizex = float (self.win.getXSize() - adjustment) / float (cols) + h_sizex = float(self.win.getXSize() - adjustment) / float(cols) h_sizex -= bordersize if h_sizex < 1.0: h_sizex = 1.0 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 sizex = h_sizex else: @@ -466,7 +465,7 @@ class BufferViewer(DirectObject): for r in range(rows): for c in range(cols): - index = c + r*cols + index = c + r * cols if index < ncards: 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) placer = NodePath("card-structure") 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.reparentTo(self.renderParent) frame.instanceTo(placer) diff --git a/direct/src/showbase/ContainerLeakDetector.py b/direct/src/showbase/ContainerLeakDetector.py index 9a0919acc3..b172cbb4e3 100755 --- a/direct/src/showbase/ContainerLeakDetector.py +++ b/direct/src/showbase/ContainerLeakDetector.py @@ -33,6 +33,7 @@ def _createContainerLeak(): # use tuples as keys since they can't be weakref'd, and use an instance # since it can't be repr/eval'd # that will force the leak detector to hold a normal 'non-weak' reference + class LeakKey: pass base.leakContainer[(LeakKey(),)] = {} @@ -47,13 +48,17 @@ def _createContainerLeak(): return task.done leakContainer() + def _createTaskLeak(): leakTaskName = uniqueName('leakedTask') leakDoLaterName = uniqueName('leakedDoLater') + def nullTask(task=None): return task.cont + def nullDoLater(task=None): return task.done + def leakTask(task=None, leakTaskName=leakTaskName): base = getBase() taskMgr.add(nullTask, uniqueName(leakTaskName)) @@ -63,9 +68,11 @@ def _createTaskLeak(): return task.done leakTask() + class NoDictKey: pass + class Indirection: """ 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 Python will keep one copy and reduce memory usage """ + def __init__(self, evalStr=None, dictKey=NoDictKey): # if this is a dictionary lookup, pass dictKey instead of evalStr self.evalStr = evalStr @@ -89,7 +97,7 @@ class Indirection: try: keyEval = eval(keyRepr) useEval = True - except: + except Exception: pass if useEval: # check to make sure the eval succeeded @@ -114,6 +122,7 @@ class Indirection: def acquire(self): self._refCount += 1 + def release(self): self._refCount -= 1 if self._refCount == 0: @@ -164,6 +173,7 @@ class Indirection: def __repr__(self): return self.getString() + class ObjectRef: """ stores a reference to a container in a way that does not prevent garbage @@ -346,10 +356,12 @@ class ObjectRef: pass return result + class FindContainers(Job): """ Explore the Python graph, looking for objects that support __len__() """ + def __init__(self, name, leakDetector): Job.__init__(self, name) self._leakDetector = leakDetector @@ -382,7 +394,7 @@ class FindContainers(Job): pass try: base - except: + except Exception: pass else: ref = ObjectRef(Indirection(evalStr='base.__dict__'), id(base.__dict__)) @@ -391,7 +403,7 @@ class FindContainers(Job): pass try: simbase - except: + except Exception: pass else: 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? try: return len(startObj) - except: + except Exception: return 1 def _isDeadEnd(self, obj, objName=None): @@ -426,7 +438,7 @@ class FindContainers(Job): return True try: className = obj.__class__.__name__ - except: + except Exception: pass else: # 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 # proportional to their length for fw in makeFlywheelGen( - list(startRefWorkingList.source.values()), - countFunc=lambda x: self.getStartObjAffinity(x), - scale=.05): + list(startRefWorkingList.source.values()), + countFunc=lambda x: self.getStartObjAffinity(x), + scale=.05): yield None startRefWorkingList.refGen = fw if curObjRef is None: @@ -529,7 +541,7 @@ class FindContainers(Job): try: for containerRef in self._leakDetector.getContainerByIdGen(startId): yield None - except: + except Exception: # ref is invalid self.notify.debug('invalid startRef, stored as id %s' % startId) self._leakDetector.removeContainerById(startId) @@ -539,7 +551,7 @@ class FindContainers(Job): try: for curObj in curObjRef.getContainerGen(): yield None - except: + except Exception: self.notify.debug('lost current container, ref.getContainerGen() failed') # that container is gone, try again curObjRef = None @@ -642,6 +654,7 @@ class FindContainers(Job): raise yield Job.Done + class CheckContainers(Job): """ Job to check container sizes and find potential leaks; sub-job of ContainerLeakDetector @@ -724,7 +737,7 @@ class CheckContainers(Job): try: for container in self._leakDetector.getContainerByIdGen(objId): yield None - except: + except Exception: # TODO self.notify.debug('caught exception in getContainerByIdGen (1)') else: @@ -745,7 +758,7 @@ class CheckContainers(Job): try: for container in self._leakDetector.getContainerByIdGen(objId): yield None - except: + except Exception: # TODO self.notify.debug('caught exception in getContainerByIdGen (2)') else: @@ -766,7 +779,7 @@ class CheckContainers(Job): try: for container in self._leakDetector.getContainerByIdGen(objId): yield None - except: + except Exception: # TODO self.notify.debug('caught exception in getContainerByIdGen (3)') else: @@ -786,6 +799,7 @@ class CheckContainers(Job): raise yield Job.Done + class FPTObjsOfType(Job): def __init__(self, name, leakDetector, otn, doneCallback=None): Job.__init__(self, name) @@ -818,9 +832,9 @@ class FPTObjsOfType(Job): yield None try: for container in self._leakDetector.getContainerByIdGen( - id, getInstance=getInstance): + id, getInstance=getInstance): yield None - except: + except Exception: pass else: if hasattr(container, '__class__'): @@ -830,9 +844,9 @@ class FPTObjsOfType(Job): if self._otn.lower() in cName.lower(): try: for ptc in self._leakDetector.getContainerNameByIdGen( - id, getInstance=getInstance): + id, getInstance=getInstance): yield None - except: + except Exception: pass else: print('GPTC(' + self._otn + '):' + self.getJobName() + ': ' + ptc) @@ -846,6 +860,7 @@ class FPTObjsOfType(Job): if self._doneCallback: self._doneCallback(self) + class FPTObjsNamed(Job): def __init__(self, name, leakDetector, on, doneCallback=None): Job.__init__(self, name) @@ -878,7 +893,7 @@ class FPTObjsNamed(Job): try: for container in self._leakDetector.getContainerByIdGen(id): yield None - except: + except Exception: pass else: name = self._leakDetector._id2ref[id].getFinalIndirectionStr() @@ -886,7 +901,7 @@ class FPTObjsNamed(Job): try: for ptc in self._leakDetector.getContainerNameByIdGen(id): yield None - except: + except Exception: pass else: print('GPTCN(' + self._on + '):' + self.getJobName() + ': ' + ptc) @@ -900,11 +915,13 @@ class FPTObjsNamed(Job): if self._doneCallback: self._doneCallback(self) + class PruneObjectRefs(Job): """ Job to destroy any container refs that are no longer valid. Checks validity by asking for each container """ + def __init__(self, name, leakDetector): Job.__init__(self, name) self._leakDetector = leakDetector @@ -926,7 +943,7 @@ class PruneObjectRefs(Job): try: for container in self._leakDetector.getContainerByIdGen(id): yield None - except: + except Exception: # reference is invalid, remove it self._leakDetector.removeContainerById(id) _id2baseStartRef = self._leakDetector._findContainersJob._id2baseStartRef @@ -936,7 +953,7 @@ class PruneObjectRefs(Job): try: for container in _id2baseStartRef[id].getContainerGen(): yield None - except: + except Exception: # reference is invalid, remove it del _id2baseStartRef[id] _id2discoveredStartRef = self._leakDetector._findContainersJob._id2discoveredStartRef @@ -946,7 +963,7 @@ class PruneObjectRefs(Job): try: for container in _id2discoveredStartRef[id].getContainerGen(): yield None - except: + except Exception: # reference is invalid, remove it del _id2discoveredStartRef[id] except Exception as e: @@ -955,6 +972,7 @@ class PruneObjectRefs(Job): raise yield Job.Done + class ContainerLeakDetector(Job): """ Low-priority Python object-graph walker that looks for leaking containers. @@ -1028,12 +1046,14 @@ class ContainerLeakDetector(Job): @classmethod def addPrivateObj(cls, obj): cls.PrivateIds.add(id(obj)) + @classmethod def removePrivateObj(cls, obj): cls.PrivateIds.remove(id(obj)) def _getCheckTaskName(self): return 'checkForLeakingContainers-%s' % self._serialNum + def _getPruneTaskName(self): return 'pruneLeakingContainerRefs-%s' % self._serialNum @@ -1043,16 +1063,20 @@ class ContainerLeakDetector(Job): def getContainerByIdGen(self, id, **kwArgs): # return a generator to look up a container return self._id2ref[id].getContainerGen(**kwArgs) + def getContainerById(self, id): for result in self._id2ref[id].getContainerGen(): pass return result + def getContainerNameByIdGen(self, id, **kwArgs): return self._id2ref[id].getEvalStrGen(**kwArgs) + def getContainerNameById(self, id): if id in self._id2ref: return repr(self._id2ref[id]) return '' + def removeContainerById(self, id): if id in self._id2ref: self._id2ref[id].destroy() diff --git a/direct/src/showbase/ContainerReport.py b/direct/src/showbase/ContainerReport.py index 7731fc4dd0..6075d55062 100755 --- a/direct/src/showbase/ContainerReport.py +++ b/direct/src/showbase/ContainerReport.py @@ -53,22 +53,22 @@ class ContainerReport(Job): id(self._type2id2len), id(self._queue), id(self._instanceDictIds), - ])) + ])) # push on a few things that we want to give priority # for the sake of the variable-name printouts try: base - except: + except NameError: pass else: - self._enqueueContainer( base.__dict__, + self._enqueueContainer(base.__dict__, 'base') try: simbase - except: + except NameError: pass else: - self._enqueueContainer( simbase.__dict__, + self._enqueueContainer(simbase.__dict__, 'simbase') self._queue.push(__builtins__) self._id2pathStr[id(__builtins__)] = '' @@ -86,7 +86,7 @@ class ContainerReport(Job): try: if parentObj.__class__.__name__ == 'method-wrapper': continue - except: + except Exception: pass if isinstance(parentObj, (str, bytes)): @@ -142,7 +142,7 @@ class ContainerReport(Job): if not isinstance(parentObj, io.TextIOWrapper): try: itr = iter(parentObj) - except: + except Exception: pass else: try: @@ -150,7 +150,7 @@ class ContainerReport(Job): while 1: try: attr = next(itr) - except: + except Exception: # some custom classes don't do well when iterated attr = None break @@ -168,7 +168,7 @@ class ContainerReport(Job): try: childNames = dir(parentObj) - except: + except Exception: pass else: childName = None @@ -176,7 +176,7 @@ class ContainerReport(Job): for childName in childNames: try: child = getattr(parentObj, childName) - except: + except Exception: continue if id(child) not in self._visitedIds: self._visitedIds.add(id(child)) @@ -206,12 +206,13 @@ class ContainerReport(Job): # if it's a container, put it in the tables try: length = len(obj) - except: + except Exception: length = None if length is not None and length > 0: self._id2container[objId] = obj self._type2id2len.setdefault(type(obj), {}) self._type2id2len[type(obj)][objId] = length + def _examine(self, obj): # return False if it's an object that can't contain or lead to other objects if type(obj) in deadEndTypes: diff --git a/direct/src/showbase/DistancePhasedNode.py b/direct/src/showbase/DistancePhasedNode.py index 3757cbd61f..8ca2b3c12c 100755 --- a/direct/src/showbase/DistancePhasedNode.py +++ b/direct/src/showbase/DistancePhasedNode.py @@ -260,6 +260,7 @@ class DistancePhasedNode(PhasedObject, DirectObject, NodePath): self.cTrav.traverse(self) base.eventMgr.doEvents() + class BufferedDistancePhasedNode(DistancePhasedNode): """ This class is similar to DistancePhasedNode except you can also @@ -329,7 +330,7 @@ class BufferedDistancePhasedNode(DistancePhasedNode): if __debug__ and 0: - cSphere = CollisionSphere(0,0,0,0.1) + cSphere = CollisionSphere(0, 0, 0, 0.1) cNode = CollisionNode('camCol') cNode.addSolid(cSphere) cNodePath = NodePath(cNode) @@ -344,11 +345,11 @@ if __debug__ and 0: eventHandler.addOutPattern('exit%in') # messenger.toggleVerbose() - base.cTrav.addCollider(cNodePath,eventHandler) + base.cTrav.addCollider(cNodePath, eventHandler) - p = BufferedDistancePhasedNode('p',{'At':(10,20),'Near':(100,200),'Far':(1000, 1020)}, - autoCleanup = False, - fromCollideNode = cNodePath, + p = BufferedDistancePhasedNode('p', {'At': (10, 20), 'Near': (100, 200), 'Far': (1000, 1020)}, + autoCleanup=False, + fromCollideNode=cNodePath, ) p.reparentTo(render) diff --git a/direct/src/showbase/ExceptionVarDump.py b/direct/src/showbase/ExceptionVarDump.py index 53d269f4ee..b1ccf266a8 100755 --- a/direct/src/showbase/ExceptionVarDump.py +++ b/direct/src/showbase/ExceptionVarDump.py @@ -10,6 +10,7 @@ notify = directNotify.newCategory("ExceptionVarDump") reentry = 0 + def _varDump__init__(self, *args, **kArgs): global reentry if reentry > 0: @@ -30,8 +31,10 @@ def _varDump__init__(self, *args, **kArgs): self._moved__init__(*args, **kArgs) reentry -= 1 + sReentry = 0 + def _varDump__print(exc): global sReentry global notify @@ -60,6 +63,7 @@ def _varDump__print(exc): notify.info(exc._savedExcString) sReentry -= 1 + oldExcepthook = None # store these values here so that Task.py can always reliably access them # from its main exception handler @@ -68,9 +72,11 @@ wantStackDumpUpload = False variableDumpReasons = [] dumpOnExceptionInit = False + class _AttrNotFound: pass + def _excepthookDumpVars(eType, eValue, tb): origTb = tb 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__...) try: className = attr.__class__.__name__ - except: + except Exception: pass else: if className == 'method-wrapper': @@ -168,16 +174,17 @@ def _excepthookDumpVars(eType, eValue, tb): timeMgr = None try: timeMgr = base.cr.timeManager - except: + except Exception: try: timeMgr = simbase.air.timeManager - except: + except Exception: pass if timeMgr: timeMgr.setStackDump(s) oldExcepthook(eType, eValue, origTb) + def install(log, upload): """Installs the exception hook.""" global oldExcepthook diff --git a/direct/src/showbase/Finder.py b/direct/src/showbase/Finder.py index 02accf4a12..1b2c07bc5d 100644 --- a/direct/src/showbase/Finder.py +++ b/direct/src/showbase/Finder.py @@ -60,7 +60,7 @@ def rebindClass(filename): res = findClass(className) if not res: - print ('Warning: Finder could not find class') + print('Warning: Finder could not find class') # Remove the temp file we made file.close() os.remove(filename) @@ -87,7 +87,7 @@ def rebindClass(filename): file.close() os.remove(filename) - print (' Finished rebind') + print(' Finished rebind') def copyFuncs(fromClass, toClass): @@ -148,25 +148,28 @@ def copyFuncs(fromClass, toClass): # print "adding new func: ", oldFunc, funcName, newFunc setattr(toClass, funcName, newFunc) + def replaceMessengerFunc(replaceFuncList): try: messenger - except: + except Exception: return for oldFunc, funcName, newFunc in replaceFuncList: res = messenger.replaceMethod(oldFunc, newFunc) if res: print('replaced %s messenger function(s): %s' % (res, funcName)) + def replaceTaskMgrFunc(replaceFuncList): try: taskMgr - except: + except Exception: return for oldFunc, funcName, newFunc in replaceFuncList: if taskMgr.replaceMethod(oldFunc, newFunc): print('replaced taskMgr function: %s' % funcName) + def replaceStateFunc(replaceFuncList): if not sys.modules.get('base.direct.fsm.State'): return @@ -176,28 +179,31 @@ def replaceStateFunc(replaceFuncList): if res: print('replaced %s FSM transition function(s): %s' % (res, funcName)) + def replaceCRFunc(replaceFuncList): try: base.cr - except: + except Exception: return # 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. - if hasattr(base.cr,'isFake'): + if hasattr(base.cr, 'isFake'): return for oldFunc, funcName, newFunc in replaceFuncList: if base.cr.replaceMethod(oldFunc, newFunc): print('replaced DistributedObject function: %s' % funcName) + def replaceAIRFunc(replaceFuncList): try: simbase.air - except: + except Exception: return for oldFunc, funcName, newFunc in replaceFuncList: if simbase.air.replaceMethod(oldFunc, newFunc): print('replaced DistributedObject function: %s' % funcName) + def replaceIvalFunc(replaceFuncList): # Make sure we have imported IntervalManager and thus created # a global ivalMgr. diff --git a/direct/src/showbase/GarbageReport.py b/direct/src/showbase/GarbageReport.py index ce11b92443..fd101bc6c2 100644 --- a/direct/src/showbase/GarbageReport.py +++ b/direct/src/showbase/GarbageReport.py @@ -17,10 +17,12 @@ GarbageCycleCountAnnounceEvent = 'announceGarbageCycleDesc2num' class FakeObject: pass + class FakeDelObject: def __del__(self): pass + def _createGarbage(num=1): for i in range(num): a = FakeObject() @@ -32,6 +34,7 @@ def _createGarbage(num=1): a.other = b b.other = a + class GarbageReport(Job): """Detects leaked Python objects (via gc.collect()) and reports on garbage items, garbage-to-garbage references, and garbage cycles. @@ -252,7 +255,7 @@ class GarbageReport(Job): brackets = { tuple: '()', list: '[]', - }[type(obj)] + }[type(obj)] # get object being referenced by container nextObj = objs[index+1] cycleBySyntax += brackets[0] @@ -544,19 +547,23 @@ class GarbageReport(Job): break yield cycles + class GarbageLogger(GarbageReport): """If you just want to log the current garbage to the log file, make one of these. It automatically destroys itself after logging""" + def __init__(self, name, *args, **kArgs): kArgs['log'] = True kArgs['autoDestroy'] = True GarbageReport.__init__(self, name, *args, **kArgs) + class _CFGLGlobals: # for checkForGarbageLeaks LastNumGarbage = 0 LastNumCycles = 0 + def checkForGarbageLeaks(): gc.collect() numGarbage = len(gc.garbage) @@ -577,6 +584,7 @@ def checkForGarbageLeaks(): func('%s garbage cycles found, see info above' % _CFGLGlobals.LastNumCycles) return numGarbage + def b_checkForGarbageLeaks(wantReply=False): if not __dev__: return 0 @@ -586,7 +594,7 @@ def b_checkForGarbageLeaks(wantReply=False): try: # if this is the client, tell the AI to check for leaks too base.cr.timeManager - except: + except Exception: pass else: if base.cr.timeManager: diff --git a/direct/src/showbase/LeakDetectors.py b/direct/src/showbase/LeakDetectors.py index 0bdfef6ac6..0de20e0f4e 100755 --- a/direct/src/showbase/LeakDetectors.py +++ b/direct/src/showbase/LeakDetectors.py @@ -122,11 +122,7 @@ class SceneGraphLeakDetector(LeakDetector): LeakDetector.destroy(self) def __len__(self): - try: - # this will be available when the build server finishes - return self._render.countNumDescendants() - except: - return self._render.getNumDescendants() + return self._render.countNumDescendants() def __repr__(self): return 'SceneGraphLeakDetector(%s)' % self._render @@ -138,15 +134,7 @@ class SceneGraphLeakDetector(LeakDetector): class CppMemoryUsage(LeakDetector): def __len__(self): - haveMemoryUsage = True - try: - MemoryUsage - except: - haveMemoryUsage = False - if haveMemoryUsage: - return int(MemoryUsage.getCurrentCppSize()) - else: - return 0 + return MemoryUsage.getCurrentCppSize() class TaskLeakDetectorBase: diff --git a/direct/src/showbase/Loader.py b/direct/src/showbase/Loader.py index 2796c79972..92ed0cf72f 100644 --- a/direct/src/showbase/Loader.py +++ b/direct/src/showbase/Loader.py @@ -480,8 +480,8 @@ class Loader(DirectObject): i += 1 return cb - # font loading funcs + def loadFont(self, modelPath, spaceAdvance = None, lineHeight = None, pointSize = None, @@ -926,7 +926,6 @@ class Loader(DirectObject): return texture def unloadTexture(self, texture): - """ Removes the previously-loaded texture from the cache, so 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, callback = None, extraArgs = []): - """Loads one or more sound files, specifying the particular AudioManager that should be used to load them. The soundPath may be either a single filename, or a list of filenames. If a @@ -1021,7 +1019,7 @@ class Loader(DirectObject): def unloadSfx(self, sfx): if sfx: if self.base.sfxManagerList: - self.base.sfxManagerList[0].uncacheSound (sfx.getName()) + self.base.sfxManagerList[0].uncacheSound(sfx.getName()) ## def makeNodeNamesUnique(self, nodePath, nodeCount): ## if nodeCount == 0: @@ -1033,7 +1031,7 @@ class Loader(DirectObject): ## self.makeNodeNamesUnique(nodePath.getChild(i), nodeCount) def loadShader(self, shaderPath, okMissing = False): - shader = ShaderPool.loadShader (shaderPath) + shader = ShaderPool.loadShader(shaderPath) if not shader and not okMissing: message = 'Could not load shader file: %s' % (shaderPath) raise IOError(message) diff --git a/direct/src/showbase/Messenger.py b/direct/src/showbase/Messenger.py index 0740dec7da..0a7e38e82b 100644 --- a/direct/src/showbase/Messenger.py +++ b/direct/src/showbase/Messenger.py @@ -417,7 +417,7 @@ class Messenger: # Release the lock temporarily while we call the method. self.lock.release() try: - result = method (*(extraArgs + sentArgs)) + result = method(*(extraArgs + sentArgs)) finally: self.lock.acquire() diff --git a/direct/src/showbase/MessengerLeakDetector.py b/direct/src/showbase/MessengerLeakDetector.py index 73ab6376f4..534e3aa5c6 100755 --- a/direct/src/showbase/MessengerLeakDetector.py +++ b/direct/src/showbase/MessengerLeakDetector.py @@ -11,12 +11,15 @@ import builtins class MessengerLeakObject(DirectObject): def __init__(self): self.accept('leakEvent', self._handleEvent) + def _handleEvent(self): pass + def _leakMessengerObject(): leakObject = MessengerLeakObject() + class MessengerLeakDetector(Job): # check for objects that are only referenced by the messenger # and would otherwise be garbage collected @@ -37,19 +40,19 @@ class MessengerLeakDetector(Job): builtinIds.add(id(base)) builtinIds.add(id(base.cr)) builtinIds.add(id(base.cr.doId2do)) - except: + except Exception: pass try: builtinIds.add(id(simbase)) builtinIds.add(id(simbase.air)) builtinIds.add(id(simbase.air.doId2do)) - except: + except Exception: pass try: builtinIds.add(id(uber)) builtinIds.add(id(uber.air)) builtinIds.add(id(uber.air.doId2do)) - except: + except Exception: pass while True: diff --git a/direct/src/showbase/ObjectPool.py b/direct/src/showbase/ObjectPool.py index 5531dd1946..125fb7f326 100755 --- a/direct/src/showbase/ObjectPool.py +++ b/direct/src/showbase/ObjectPool.py @@ -43,7 +43,7 @@ class ObjectPool: self._type2objs[typ].append(obj) try: self._len2obj[len(obj)] = obj - except: + except Exception: pass self._count2types = invertDictLossless(type2count) diff --git a/direct/src/showbase/OnScreenDebug.py b/direct/src/showbase/OnScreenDebug.py index 67b5cf2418..7483d3c9f1 100755 --- a/direct/src/showbase/OnScreenDebug.py +++ b/direct/src/showbase/OnScreenDebug.py @@ -34,7 +34,7 @@ class OnScreenDebug: color = { "black": Vec4(0, 0, 0, 1), "white": Vec4(1, 1, 1, 1), - } + } fgColor = color[ConfigVariableString("on-screen-debug-fg-color", "white").value] bgColor = color[ConfigVariableString("on-screen-debug-bg-color", "black").value] fgColor.setW(ConfigVariableDouble("on-screen-debug-fg-alpha", 0.85).value) diff --git a/direct/src/showbase/PythonUtil.py b/direct/src/showbase/PythonUtil.py index a29d98b6a4..c460dbe73d 100644 --- a/direct/src/showbase/PythonUtil.py +++ b/direct/src/showbase/PythonUtil.py @@ -96,43 +96,59 @@ class Functor: s += ')' return s + class Stack: def __init__(self): self.__list = [] + def push(self, item): self.__list.append(item) + def top(self): # return the item on the top of the stack without popping it off return self.__list[-1] + def pop(self): return self.__list.pop() + def clear(self): self.__list = [] + def isEmpty(self): return len(self.__list) == 0 + def __len__(self): return len(self.__list) + class Queue: # FIFO queue # interface is intentionally identical to Stack (LIFO) def __init__(self): self.__list = [] + def push(self, item): self.__list.append(item) + def top(self): # return the next item at the front of the queue without popping it off return self.__list[0] + def front(self): return self.__list[0] + def back(self): return self.__list[-1] + def pop(self): return self.__list.pop(0) + def clear(self): self.__list = [] + def isEmpty(self): return len(self.__list) == 0 + def __len__(self): return len(self.__list) @@ -199,9 +215,11 @@ if __debug__: def printStack(): print(StackTrace(start=1).compact()) return True + def printReverseStack(): print(StackTrace(start=1).reverseCompact()) return True + def printVerboseStack(): print(StackTrace(start=1)) return True @@ -245,7 +263,8 @@ if __debug__: r += (v[:2000] + "...") else: r+=v - else: r+="*** undefined ***" + else: + r+="*** undefined ***" return r+')' def traceParentCall(): @@ -260,11 +279,13 @@ if __debug__: _POS_LIST = 4 _KEY_DICT = 8 + def doc(obj): if (isinstance(obj, types.MethodType)) or \ (isinstance(obj, types.FunctionType)): print(obj.__doc__) + def adjust(command = None, dim = 1, parent = None, **kw): """ adjust(command = None, parent = None, **kw) @@ -303,6 +324,7 @@ def adjust(command = None, dim = 1, parent = None, **kw): vg.pack(expand = 1, fill = 'x') return vg + def difference(a, b): """ difference(list, list): @@ -320,6 +342,7 @@ def difference(a, b): d.append(i) return d + def intersection(a, b): """ intersection(list, list): @@ -335,6 +358,7 @@ def intersection(a, b): d.append(i) return d + def union(a, b): """ union(list, list): @@ -346,6 +370,7 @@ def union(a, b): c.append(i) return c + def sameElements(a, b): if len(a) != len(b): return 0 @@ -357,6 +382,7 @@ def sameElements(a, b): return 0 return 1 + def makeList(x): """returns x, converted to a list""" if isinstance(x, list): @@ -366,6 +392,7 @@ def makeList(x): else: return [x,] + def makeTuple(x): """returns x, converted to a tuple""" if isinstance(x, list): @@ -375,10 +402,12 @@ def makeTuple(x): else: return (x,) + def list2dict(L, value=None): """creates dict using elements of list, all assigned to same value""" return dict([(k, value) for k in L]) + def listToIndex2item(L): """converts list to dict of list index->list item""" d = {} @@ -386,8 +415,10 @@ def listToIndex2item(L): d[i] = item return d + assert listToIndex2item(['a','b']) == {0: 'a', 1: 'b',} + def listToItem2index(L): """converts list to dict of list item->list index This is lossy if there are duplicate list items""" @@ -396,8 +427,10 @@ def listToItem2index(L): d[item] = i return d + assert listToItem2index(['a','b']) == {'a': 0, 'b': 1,} + def invertDict(D, lossy=False): """creates a dictionary by 'inverting' D; keys are placed in the new dictionary under their corresponding value in the old dictionary. @@ -414,6 +447,7 @@ def invertDict(D, lossy=False): n[value] = key return n + def invertDictLossless(D): """similar to invertDict, but values of new dict are lists of keys from old dict. No information is lost. @@ -428,10 +462,12 @@ def invertDictLossless(D): n[value].append(key) return n + def uniqueElements(L): """are all elements of list unique?""" return len(L) == len(list2dict(L)) + def disjoint(L1, L2): """returns non-zero if L1 and L2 have no common elements""" used = dict([(k, None) for k in L1]) @@ -440,6 +476,7 @@ def disjoint(L1, L2): return 0 return 1 + def contains(whole, sub): """ Return 1 if whole contains sub, 0 otherwise @@ -453,6 +490,7 @@ def contains(whole, sub): # If you got here, whole must contain sub return 1 + def replace(list, old, new, all=0): """ replace 'old' with 'new' in 'list' @@ -475,17 +513,20 @@ def replace(list, old, new, all=0): list[i] = new return numReplaced + rad90 = math.pi / 2. rad180 = math.pi rad270 = 1.5 * math.pi rad360 = 2. * math.pi + def reduceAngle(deg): """ Reduces an angle (in degrees) to a value in [-180..180) """ return ((deg + 180.) % 360.) - 180. + def fitSrcAngle2Dest(src, dest): """ given a src and destination angle, returns an equivalent src angle @@ -499,6 +540,7 @@ def fitSrcAngle2Dest(src, dest): """ return dest + reduceAngle(src - dest) + def fitDestAngle2Src(src, dest): """ given a src and destination angle, returns an equivalent dest angle @@ -511,6 +553,7 @@ def fitDestAngle2Src(src, dest): """ return src + (reduceAngle(dest - src)) + def closestDestAngle2(src, dest): # The function above didn't seem to do what I wanted. So I hacked # this one together. I can't really say I understand it. It's more @@ -526,6 +569,7 @@ def closestDestAngle2(src, dest): # otherwise just go to the original destination return dest + def closestDestAngle(src, dest): # The function above didn't seem to do what I wanted. So I hacked # this one together. I can't really say I understand it. It's more @@ -541,12 +585,14 @@ def closestDestAngle(src, dest): # otherwise just go to the original destination return dest + class StdoutCapture: # redirects stdout to a string def __init__(self): self._oldStdout = sys.stdout sys.stdout = self self._string = '' + def destroy(self): sys.stdout = self._oldStdout del self._oldStdout @@ -558,6 +604,7 @@ class StdoutCapture: def write(self, string): self._string = ''.join([self._string, string]) + class StdoutPassthrough(StdoutCapture): # like StdoutCapture but also allows output to go through to the OS as normal @@ -566,6 +613,7 @@ class StdoutPassthrough(StdoutCapture): self._string = ''.join([self._string, string]) self._oldStdout.write(string) + # constant profile defaults if __debug__: from io import StringIO @@ -731,7 +779,6 @@ if __debug__: # don't let marshalled data pile up profileFilename2marshalData.pop(filename, None) - # call this from the prompt, and break back out to the prompt # to stop profiling # @@ -746,6 +793,7 @@ if __debug__: # PythonUtil.startProfile(cmd='func()', filename='profileData') # del builtins.func # + def _profileWithoutGarbageLeak(cmd, filename): # The profile module isn't necessarily installed on every Python # installation, so we import it here, instead of in the module @@ -820,27 +868,34 @@ if __debug__: # restore stdout to what it was before sc.destroy() + def getSetterName(valueName, prefix='set'): # getSetterName('color') -> 'setColor' # getSetterName('color', 'get') -> 'getColor' return '%s%s%s' % (prefix, valueName[0].upper(), valueName[1:]) + + def getSetter(targetObj, valueName, prefix='set'): # getSetter(smiley, 'pos') -> smiley.setPos return getattr(targetObj, getSetterName(valueName, prefix)) + def mostDerivedLast(classList): """pass in list of classes. sorts list in-place, with derived classes appearing after their bases""" class ClassSortKey(object): __slots__ = 'classobj', + def __init__(self, classobj): self.classobj = classobj + def __lt__(self, other): return issubclass(other.classobj, self.classobj) classList.sort(key=ClassSortKey) + def bound(value, bound1, bound2): """ returns value if value is between bound1 and bound2 @@ -850,8 +905,11 @@ def bound(value, bound1, bound2): return min(max(value, bound2), bound1) else: return min(max(value, bound1), bound2) + + clamp = bound + def lerp(v0, v1, t): """ returns a value lerped between v0 and v1, according to t @@ -859,6 +917,7 @@ def lerp(v0, v1, t): """ return v0 + ((v1 - v0) * t) + def getShortestRotation(start, end): """ Given two heading values, return a tuple describing @@ -874,6 +933,7 @@ def getShortestRotation(start, end): start += 360 return (start, end) + def average(*args): """ returns simple average of list of values """ val = 0. @@ -881,21 +941,27 @@ def average(*args): val += arg return val / len(args) + class Averager: def __init__(self, name): self._name = name self.reset() + def reset(self): self._total = 0. self._count = 0 + def addValue(self, value): self._total += value self._count += 1 + def getAverage(self): return self._total / self._count + def getCount(self): return self._count + def addListsByValue(a, b): """ returns a new array containing the sums of the two array arguments @@ -906,6 +972,7 @@ def addListsByValue(a, b): c.append(x + y) return c + def boolEqual(a, b): """ returns true if a and b are both true or both false. @@ -914,6 +981,7 @@ def boolEqual(a, b): """ return (a and b) or not (a or b) + def lineupPos(i, num, spacing): """ use to line up a series of 'num' objects, in one dimension, @@ -926,6 +994,7 @@ def lineupPos(i, num, spacing): pos = float(i) * spacing return pos - ((float(spacing) * (num-1))/2.) + def formatElapsedSeconds(seconds): """ Returns a string of the form "mm:ss" or "hh:mm:ss" or "n days", @@ -953,6 +1022,7 @@ def formatElapsedSeconds(seconds): else: return "%s%d:%02d" % (sign, minutes, seconds) + def solveQuadratic(a, b, c): # quadratic equation: ax^2 + bx + c = 0 # quadratic formula: x = [-b +/- sqrt(b^2 - 4ac)] / 2a @@ -979,6 +1049,7 @@ def solveQuadratic(a, b, c): root2 = ((-b) + sqrtD) / twoA return [root1, root2] + if __debug__: def stackEntryInfo(depth=0, baseFileName=1): """ @@ -1054,6 +1125,7 @@ if __debug__: return '%s%s%s%s%s' % (fileName, separator, lineNum, separator, funcName) + def findPythonModule(module): # Look along the python load path for the indicated filename. # Returns the located pathname, or None if the filename is not @@ -1066,6 +1138,7 @@ def findPythonModule(module): return None + def clampScalar(value, a, b): # calling this ought to be faster than calling both min and max if a < b: @@ -1083,6 +1156,7 @@ def clampScalar(value, a, b): else: return value + def weightedChoice(choiceList, rng=random.random, sum=None): """given a list of (weight, item) pairs, chooses an item based on the weights. rng must return 0..1. if you happen to have the sum of the @@ -1109,12 +1183,14 @@ def weightedChoice(choiceList, rng=random.random, sum=None): # Return the last item. return item + def randFloat(a, b=0., rng=random.random): """returns a random float in [a, b] call with single argument to generate random float between arg and zero """ return lerp(a, b, rng()) + def normalDistrib(a, b, gauss=random.gauss): """ NOTE: assumes a < b @@ -1148,6 +1224,7 @@ def normalDistrib(a, b, gauss=random.gauss): if (r >= a) and (r <= b): return r + def weightedRand(valDict, rng=random.random): """ pass in a dictionary with a selection -> weight mapping. E.g.:: @@ -1178,11 +1255,13 @@ def weightedRand(valDict, rng=random.random): assert True, "Should never get here" return selections[-1] + def randUint31(rng=random.random): """returns a random integer in [0..2^31). rng must return float in [0..1]""" return int(rng() * 0x7FFFFFFF) + def randInt32(rng=random.random): """returns a random integer in [-2147483648..2147483647]. rng must return float in [0..1] @@ -1192,8 +1271,10 @@ def randInt32(rng=random.random): i *= -1 return i + class SerialNumGen: """generates serial numbers""" + def __init__(self, start=None): if start is None: start = 0 @@ -1205,6 +1286,7 @@ class SerialNumGen: __next__ = next + class SerialMaskedGen(SerialNumGen): def __init__(self, mask, start=None): self._mask = mask @@ -1216,11 +1298,14 @@ class SerialMaskedGen(SerialNumGen): __next__ = next + _serialGen = SerialNumGen() + def serialNum(): return _serialGen.next() + def uniqueName(name): return f'{name}-{serialNum()}' @@ -1265,14 +1350,17 @@ class Singleton(type): def __init__(cls, name, bases, dic): super(Singleton, cls).__init__(name, bases, dic) cls.instance=None + def __call__(cls, *args, **kw): if cls.instance is None: cls.instance=super(Singleton, cls).__call__(*args, **kw) return cls.instance + class SingletonError(ValueError): """ Used to indicate an inappropriate value for a Singleton.""" + def printListEnumGen(l): # log each individual item with a number in front of it digits = 0 @@ -1285,28 +1373,34 @@ def printListEnumGen(l): print(format % (i, l[i])) yield None + def printListEnum(l): for result in printListEnumGen(l): pass + # base class for all Panda C++ objects # libdtoolconfig doesn't seem to have this, grab it off of TypedObject dtoolSuperBase = None + def _getDtoolSuperBase(): global dtoolSuperBase from panda3d.core import TypedObject dtoolSuperBase = TypedObject.__bases__[0] assert dtoolSuperBase.__name__ == 'DTOOL_SUPER_BASE' + safeReprNotify = None + def _getSafeReprNotify(): global safeReprNotify from direct.directnotify.DirectNotifyGlobal import directNotify safeReprNotify = directNotify.newCategory("safeRepr") return safeReprNotify + def safeRepr(obj): global dtoolSuperBase if dtoolSuperBase is None: @@ -1327,6 +1421,7 @@ def safeRepr(obj): except Exception: return '<** FAILED REPR OF %s instance at %s **>' % (obj.__class__.__name__, hex(id(obj))) + def safeReprTypeOnFail(obj): global dtoolSuperBase if dtoolSuperBase is None: @@ -1345,7 +1440,6 @@ def safeReprTypeOnFail(obj): return '<** FAILED REPR OF %s instance at %s **>' % (obj.__class__.__name__, hex(id(obj))) - def fastRepr(obj, maxLen=200, strFactor=10, _visitedIds=None): """ caps the length of iterable types, so very large objects will print faster. also prevents infinite recursion """ @@ -1406,6 +1500,7 @@ def fastRepr(obj, maxLen=200, strFactor=10, _visitedIds=None): except Exception: return '<** FAILED REPR OF %s **>' % obj.__class__.__name__ + def convertTree(objTree, idList): newTree = {} for key in list(objTree.keys()): @@ -1414,6 +1509,7 @@ def convertTree(objTree, idList): r_convertTree(objTree[key], newTree[obj], idList) return newTree + def r_convertTree(oldTree, newTree, idList): for key in list(oldTree.keys()): obj = idList.get(key) @@ -1459,14 +1555,17 @@ def appendStr(obj, st): class ScratchPad: """empty class to stick values onto""" + def __init__(self, **kArgs): for key, value in kArgs.items(): setattr(self, key, value) self._keys = set(kArgs.keys()) + def add(self, **kArgs): for key, value in kArgs.items(): setattr(self, key, value) self._keys.update(list(kArgs.keys())) + def destroy(self): for key in self._keys: delattr(self, key) @@ -1474,14 +1573,18 @@ class ScratchPad: # allow dict [] syntax def __getitem__(self, itemName): return getattr(self, itemName) + def get(self, itemName, default=None): return getattr(self, itemName, default) # allow 'in' + def __contains__(self, itemName): return itemName in self._keys + class Sync: _SeriesGen = SerialNumGen() + def __init__(self, name, other=None): self._name = name if other is None: @@ -1490,10 +1593,13 @@ class Sync: else: self._series = other._series self._value = other._value + def invalidate(self): self._value = None + def change(self): self._value += 1 + def sync(self, other): if (self._series != other._series) or (self._value != other._value): self._series = other._series @@ -1501,13 +1607,16 @@ class Sync: return True else: return False + def isSynced(self, other): return ((self._series == other._series) and (self._value == other._value)) + def __repr__(self): return '%s(%s)' % (self.__class__.__name__, self._name, self._series, self._value) + def itype(obj): # version of type that gives more complete information about instance types global dtoolSuperBase @@ -1520,6 +1629,7 @@ def itype(obj): return "" % (obj.__class__) return t + def deeptype(obj, maxLen=100, _visitedIds=None): if _visitedIds is None: _visitedIds = set() @@ -1565,6 +1675,7 @@ def deeptype(obj, maxLen=100, _visitedIds=None): else: return str(itype(obj)) + def getNumberedTypedString(items, maxLen=5000, numPrefix=''): """get a string that has each item of the list on its own line, and each item is numbered on the left from zero""" @@ -1587,6 +1698,7 @@ def getNumberedTypedString(items, maxLen=5000, numPrefix=''): s += format % (i, itype(items[i]), objStr) return s + def getNumberedTypedSortedString(items, maxLen=5000, numPrefix=''): """get a string that has each item of the list on its own line, the items are stringwise-sorted, and each item is numbered on @@ -1615,6 +1727,7 @@ def getNumberedTypedSortedString(items, maxLen=5000, numPrefix=''): s += format % (i, itype(items[i]), strs[i]) return s + def printNumberedTyped(items, maxLen=5000): """print out each item of the list on its own line, with each item numbered on the left from zero""" @@ -1631,6 +1744,7 @@ def printNumberedTyped(items, maxLen=5000): objStr = '%s%s' % (objStr[:(maxLen-len(snip))], snip) print(format % (i, itype(items[i]), objStr)) + def printNumberedTypesGen(items, maxLen=5000): digits = 0 n = len(items) @@ -1642,14 +1756,17 @@ def printNumberedTypesGen(items, maxLen=5000): print(format % (i, itype(items[i]))) yield None + def printNumberedTypes(items, maxLen=5000): """print out the type of each item of the list on its own line, with each item numbered on the left from zero""" for result in printNumberedTypesGen(items, maxLen): yield result + class DelayedCall: """ calls a func after a specified delay """ + def __init__(self, func, name=None, delay=None): if name is None: name = 'anonymous' @@ -1660,25 +1777,32 @@ class DelayedCall: self._delay = delay self._finished = False self._addDoLater() + def destroy(self): self._finished = True self._removeDoLater() + def finish(self): if not self._finished: self._doCallback(None) self.destroy() + def _addDoLater(self): taskMgr.doMethodLater(self._delay, self._doCallback, self._taskName) + def _removeDoLater(self): taskMgr.remove(self._taskName) + def _doCallback(self, task): self._finished = True func = self._func del self._func func() + class FrameDelayedCall: """ calls a func after N frames """ + def __init__(self, name, callback, frames=None, cancelFunc=None): # checkFunc is optional; called every frame, if returns True, FrameDelay is cancelled # and callback is not called @@ -1691,19 +1815,24 @@ class FrameDelayedCall: self._taskName = uniqueName('%s-%s' % (self.__class__.__name__, self._name)) self._finished = False self._startTask() + def destroy(self): self._finished = True self._stopTask() + def finish(self): if not self._finished: self._finished = True self._callback() self.destroy() + def _startTask(self): taskMgr.add(self._frameTask, self._taskName) self._counter = 0 + def _stopTask(self): taskMgr.remove(self._taskName) + def _frameTask(self, task): if self._cancelFunc and self._cancelFunc(): self.destroy() @@ -1714,15 +1843,18 @@ class FrameDelayedCall: return task.done return task.cont + class DelayedFunctor: """ Waits for this object to be called, then calls supplied functor after a delay. Effectively inserts a time delay between the caller and the functor. """ + def __init__(self, functor, name=None, delay=None): self._functor = functor self._name = name # FunctionInterval requires __name__ self.__name__ = self._name self._delay = delay + def _callFunctor(self): cb = Functor(self._functor, *self._args, **self._kwArgs) del self._functor @@ -1733,14 +1865,17 @@ class DelayedFunctor: del self._delayedCall del self.__name__ cb() + def __call__(self, *args, **kwArgs): self._args = args self._kwArgs = kwArgs self._delayedCall = DelayedCall(self._callFunctor, self._name, self._delay) + class SubframeCall: """Calls a callback at a specific time during the frame using the task system""" + def __init__(self, functor, taskPriority, name=None): self._functor = functor self._name = name @@ -1748,6 +1883,7 @@ class SubframeCall: taskMgr.add(self._doCallback, self._taskName, priority=taskPriority) + def _doCallback(self, task): functor = self._functor del self._functor @@ -1755,11 +1891,13 @@ class SubframeCall: del self._name self._taskName = None return task.done + def cleanup(self): if self._taskName: taskMgr.remove(self._taskName) self._taskName = None + class PStatScope: collectors = {} @@ -1805,6 +1943,7 @@ class PStatScope: # print ' ',self.collectors[label] return self.collectors[label] + def pstatcollect(scope, level = None): def decorator(f): return f @@ -1826,7 +1965,10 @@ def pstatcollect(scope, level = None): return decorator + __report_indent = 0 + + def report(types = [], prefix = '', xform = None, notifyFunc = None, dConfigParam = []): """ This is a decorator generating function. Use is similar to @@ -1878,7 +2020,6 @@ def report(types = [], prefix = '', xform = None, notifyFunc = None, dConfigPara config strings resolve to True. """ - def indent(str): global __report_indent return ' '*__report_indent+str @@ -1927,21 +2068,20 @@ def report(types = [], prefix = '', xform = None, notifyFunc = None, dConfigPara globalClockDelta = importlib.import_module("direct.distributed.ClockDelta").globalClockDelta def decorator(f): - def wrap(*args,**kwargs): + def wrap(*args, **kwargs): if args: rArgs = [args[0].__class__.__name__ + ', '] else: rArgs = [] if 'args' in types: - rArgs += [repr(x)+', ' for x in args[1:]] + \ - [ x + ' = ' + '%s, ' % repr(y) for x,y in kwargs.items()] + rArgs += [repr(x) + ', ' for x in args[1:]] + \ + [x + ' = ' + '%s, ' % repr(y) for x, y in kwargs.items()] if not rArgs: rArgs = '()' else: - rArgs = '(' + functools.reduce(str.__add__,rArgs)[:-2] + ')' - + rArgs = '(' + functools.reduce(str.__add__, rArgs)[:-2] + ')' outStr = '%s%s' % (f.__name__, rArgs) @@ -1992,11 +2132,11 @@ def report(types = [], prefix = '', xform = None, notifyFunc = None, dConfigPara rVal = None try: __report_indent += 1 - rVal = f(*args,**kwargs) + rVal = f(*args, **kwargs) finally: __report_indent -= 1 if rVal is not None: - print(indent(' -> '+repr(rVal))) + print(indent(' -> ' + repr(rVal))) return rVal wrap.__name__ = f.__name__ @@ -2006,18 +2146,21 @@ def report(types = [], prefix = '', xform = None, notifyFunc = None, dConfigPara return wrap return decorator + def getBase(): try: return base except Exception: return simbase + def getRepository(): try: return base.cr except Exception: return simbase.air + exceptionLoggedNotify = None if __debug__: def exceptionLogged(append=True): @@ -2046,6 +2189,7 @@ if __debug__: if exceptionLoggedNotify is None: from direct.directnotify.DirectNotifyGlobal import directNotify exceptionLoggedNotify = directNotify.newCategory("ExceptionLogged") + def _exceptionLogged(*args, **kArgs): try: return f(*args, **kArgs) @@ -2073,20 +2217,25 @@ if __debug__: # http://en.wikipedia.org/wiki/Golden_ratio GoldenRatio = (1. + math.sqrt(5.)) / 2. + + class GoldenRectangle: @staticmethod def getLongerEdge(shorter): return shorter * GoldenRatio + @staticmethod def getShorterEdge(longer): return longer / GoldenRatio + def nullGen(): # generator that ends immediately if False: # yield that never runs but still exists, making this func a generator yield None + def loopGen(l): # generator that yields the items of an iterable object forever def _gen(l): @@ -2098,6 +2247,7 @@ def loopGen(l): _gen = None return gen + def makeFlywheelGen(objects, countList=None, countFunc=None, scale=None): # iterates and finally yields a flywheel generator object # the number of appearances for each object is controlled by passing in @@ -2135,6 +2285,7 @@ def makeFlywheelGen(objects, countList=None, countFunc=None, scale=None): # create the flywheel generator yield flywheel(index2objectAndCount) + def flywheel(*args, **kArgs): # create a flywheel generator # see arguments and comments in flywheelGen above @@ -2153,9 +2304,11 @@ def flywheel(*args, **kArgs): if __debug__: def quickProfile(name="unnamed"): import pstats + def profileDecorator(f): if not ConfigVariableBool("use-profiler", False): return f + def _profiled(*args, **kArgs): # must do this in here because we don't have base/simbase # at the time that PythonUtil is loaded @@ -2188,6 +2341,7 @@ if __debug__: return _profiled return profileDecorator + def getTotalAnnounceTime(): td=0 for objs in base.stats.values(): @@ -2195,6 +2349,7 @@ def getTotalAnnounceTime(): td+=getAnnounceGenerateTime(stat) return td + def getAnnounceGenerateTime(stat): val=0 stats=stat.stats @@ -2217,13 +2372,13 @@ class MiniLog: ('*'*50, self.name, '-'*50, '\n'.join(self.lines), '*'*50) def enterFunction(self, funcName, *args, **kw): - rArgs = [repr(x)+', ' for x in args] + \ - [ x + ' = ' + '%s, ' % repr(y) for x,y in kw.items()] + rArgs = [repr(x) + ', ' for x in args] + \ + [x + ' = ' + '%s, ' % repr(y) for x, y in kw.items()] if not rArgs: rArgs = '()' else: - rArgs = '(' + functools.reduce(str.__add__,rArgs)[:-2] + ')' + rArgs = '(' + functools.reduce(str.__add__, rArgs)[:-2] + ')' line = '%s%s' % (funcName, rArgs) self.appendFunctionCall(line) @@ -2249,6 +2404,7 @@ class MiniLog: self.lines = [] return outStr + class MiniLogSentry: def __init__(self, log, funcName, *args, **kw): self.log = log @@ -2260,13 +2416,16 @@ class MiniLogSentry: self.log.exitFunction() del self.log + def logBlock(id, msg): print('<< LOGBLOCK(%03d)' % id) print(str(msg)) print('/LOGBLOCK(%03d) >>' % id) + class HierarchyException(Exception): JOSWILSO = 0 + def __init__(self, owner, description): self.owner = owner self.desc = description @@ -2277,6 +2436,7 @@ class HierarchyException(Exception): def __repr__(self): return 'HierarchyException(%s)' % (self.owner, ) + def formatTimeCompact(seconds): # returns string in format '1d3h22m43s' result = '' @@ -2297,6 +2457,7 @@ def formatTimeCompact(seconds): result += '%ss' % seconds return result + if __debug__ and __name__ == '__main__': ftc = formatTimeCompact assert ftc(0) == '0s' @@ -2308,6 +2469,7 @@ if __debug__ and __name__ == '__main__': assert ftc(24*60*60 + 2*60*60 + 34*60 + 12) == '1d2h34m12s' del ftc + def formatTimeExact(seconds): # like formatTimeCompact but leaves off '0 seconds', '0 minutes' etc. for # times that are e.g. 1 hour, 3 days etc. @@ -2333,6 +2495,7 @@ def formatTimeExact(seconds): result += '%ss' % seconds return result + if __debug__ and __name__ == '__main__': fte = formatTimeExact assert fte(0) == '0s' @@ -2345,6 +2508,7 @@ if __debug__ and __name__ == '__main__': assert fte((24*60*60) + (2 * 60)) == '1d0h2m' del fte + class AlphabetCounter: # object that produces 'A', 'B', 'C', ... 'AA', 'AB', etc. def __init__(self): @@ -2375,6 +2539,7 @@ class AlphabetCounter: __next__ = next + if __debug__ and __name__ == '__main__': def testAlphabetCounter(): tempList = [] @@ -2402,6 +2567,7 @@ class Default: # useful for keyword arguments to virtual methods pass + def configIsToday(configName): # TODO: replace usage of strptime with something else # returns true if config string is a valid representation of today's date @@ -2419,12 +2585,14 @@ def configIsToday(configName): return True return False + def typeName(o): if hasattr(o, '__class__'): return o.__class__.__name__ else: return o.__name__ + def safeTypeName(o): try: return typeName(o) @@ -2436,6 +2604,7 @@ def safeTypeName(o): pass return '' + def histogramDict(l): d = {} for e in l: @@ -2443,6 +2612,7 @@ def histogramDict(l): d[e] += 1 return d + def unescapeHtmlString(s): # converts %## to corresponding character # replaces '+' with ' ' @@ -2461,8 +2631,10 @@ def unescapeHtmlString(s): result += char return result + class PriorityCallbacks: """ manage a set of prioritized callbacks, and allow them to be invoked in order of priority """ + def __init__(self): self._callbacks = [] @@ -2492,6 +2664,7 @@ class PriorityCallbacks: for priority, callback in self._callbacks: callback() + builtins.Functor = Functor builtins.Stack = Stack builtins.Queue = Queue diff --git a/direct/src/showbase/RandomNumGen.py b/direct/src/showbase/RandomNumGen.py index 7fcd732049..f3347955e1 100644 --- a/direct/src/showbase/RandomNumGen.py +++ b/direct/src/showbase/RandomNumGen.py @@ -5,6 +5,7 @@ __all__ = ['randHash', 'RandomNumGen'] from direct.directnotify import DirectNotifyGlobal from panda3d.core import Mersenne + def randHash(num): """ this returns a random 16-bit integer, given a seed integer. It will always return the same output given the same input. @@ -14,9 +15,9 @@ def randHash(num): rng = RandomNumGen(num) return rng.randint(0, (1<<16) - 1) + class RandomNumGen: - notify = \ - DirectNotifyGlobal.directNotify.newCategory("RandomNumGen") + notify = DirectNotifyGlobal.directNotify.newCategory("RandomNumGen") def __init__(self, seed): """seed must be an integer or another RandomNumGen""" diff --git a/direct/src/showbase/ReferrerSearch.py b/direct/src/showbase/ReferrerSearch.py index 2b27fdc04d..a10fccea2a 100755 --- a/direct/src/showbase/ReferrerSearch.py +++ b/direct/src/showbase/ReferrerSearch.py @@ -113,7 +113,7 @@ class ReferrerSearch(Job): (isinstance(ref, dict) and \ list(ref.keys()) == list(locals().keys())) 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 # ref-count. This usually indicates that it is some @@ -162,7 +162,7 @@ class ReferrerSearch(Job): # We found the reference on self ref is self.__dict__ or \ # 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 # ref-count. This usually indicates that it is some diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index 8c5ca231ea..22e1ff7864 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -146,6 +146,7 @@ if __debug__: from . import OnScreenDebug import warnings + @atexit.register def exitfunc(): 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 # hooks on messages, particularly on window-event. This doesn't # *seem* to cause anyone any problems. + + class ShowBase(DirectObject.DirectObject): #: The deprecated `.DConfig` interface for accessing config variables. @@ -610,6 +613,7 @@ class ShowBase(DirectObject.DirectObject): def pushCTrav(self, cTrav): self.cTravStack.push(self.cTrav) self.cTrav = cTrav + def popCTrav(self): 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 # down to the underlying _doOpenWindow() with all of the above # parameters. - func = lambda : self._doOpenWindow( + func = lambda: self._doOpenWindow( props = props, fbprops = fbprops, pipe = pipe, gsg = gsg, host = host, type = type, name = name, size = size, aspectRatio = aspectRatio, makeCamera = makeCamera, @@ -1728,7 +1732,6 @@ class ShowBase(DirectObject.DirectObject): np = mw.getParent().attachNewNode(mouseRecorder) mw.reparentTo(np) - mw = self.buttonThrowers[0].getParent() #: A special ButtonThrower to generate keyboard events and @@ -2861,7 +2864,6 @@ class ShowBase(DirectObject.DirectObject): camera = None, size = 128, cameraMask = PandaNode.getAllCameraMask(), sourceLens = None): - """ Similar to :meth:`screenshot()`, this sets up a temporary cube 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.taskMgr.run() - # Snake-case aliases, for people who prefer these. We're in the process # of migrating everyone to use the snake-case alternatives. make_default_pipe = makeDefaultPipe diff --git a/direct/src/showbase/Transitions.py b/direct/src/showbase/Transitions.py index d9fcc6cc07..aa79e4b38b 100644 --- a/direct/src/showbase/Transitions.py +++ b/direct/src/showbase/Transitions.py @@ -81,7 +81,7 @@ class Transitions: image = self.fadeModel, image_scale = (4, 2, 2), state = DGG.NORMAL, - ) + ) if not self.fadeModel: # No fade model was given, so we make this the fade model. self.fade["relief"] = DGG.FLAT @@ -255,7 +255,6 @@ class Transitions: self.alphaOn.set(r, g, b, 1) self.alphaOff.set(r, g, b, 0) - ################################################## # Iris ################################################## @@ -403,7 +402,7 @@ class Transitions: image_pos = (0,0,.1), image_color = (0.3,0.3,0.3,1), sortOrder = 0, - ) + ) self.letterboxBottom = DirectFrame( parent = self.letterbox, guiId = 'letterboxBottom', @@ -418,7 +417,7 @@ class Transitions: image_pos = (0,0,.1), image_color = (0.3,0.3,0.3,1), sortOrder = 0, - ) + ) # masad: always place these at the bottom of render self.letterboxTop.setBin('sorted',0) @@ -472,7 +471,7 @@ class Transitions: # startPos = Vec3(0, 0, 1), blendType=blendType ), - ), + ), Func(self.__finishLetterbox), name = self.letterboxTaskName, ) @@ -508,7 +507,7 @@ class Transitions: # startPos = Vec3(0, 0, 0.8), blendType=blendType ), - ), + ), Func(self.letterbox.stash), Func(self.__finishLetterbox), Func(messenger.send, 'letterboxOff'), diff --git a/direct/src/showbase/VFSImporter.py b/direct/src/showbase/VFSImporter.py index b96b6a2836..c6e69c5ca7 100644 --- a/direct/src/showbase/VFSImporter.py +++ b/direct/src/showbase/VFSImporter.py @@ -31,11 +31,11 @@ sharedPackages = {} vfs = VirtualFileSystem.getGlobalPtr() -compiledExtensions = [ 'pyc', 'pyo' ] +compiledExtensions = ['pyc', 'pyo'] if not __debug__: # In optimized mode, we prefer loading .pyo files over .pyc files. # We implement that by reversing the extension names. - compiledExtensions = [ 'pyo', 'pyc' ] + compiledExtensions = ['pyo', 'pyc'] class VFSImporter: @@ -104,6 +104,7 @@ class VFSImporter: #print >>sys.stderr, "not found." return None + class VFSLoader: """ The second part of VFSImporter, this is created for a particular .py file or directory. """ @@ -298,7 +299,6 @@ class VFSLoader: else: raise ValueError("Timestamp wrong on %s" % (vfile)) - def _compile(self, filename, source): """ Compiles the Python source code to a code object and attempts to write it to an appropriate .pyc file. May raise @@ -472,6 +472,8 @@ class VFSSharedLoader: _registered = False + + def register(): """ Register the VFSImporter on the path_hooks, if it has not already been registered, so that future Python import statements diff --git a/direct/src/showutil/BuildGeometry.py b/direct/src/showutil/BuildGeometry.py index ccf6979d46..1648b98f47 100644 --- a/direct/src/showutil/BuildGeometry.py +++ b/direct/src/showutil/BuildGeometry.py @@ -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]) 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(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") boxTextureWriter = GeomVertexWriter(boxVertexData, "texcoord") - boxVertexWriter.addData3f(-sX, sY, 0.0) boxNormalWriter.addData3f(0, 0, 1) 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.addPrimitive(boxTris) - attachNode.addGeom(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") boxColorWriter = GeomVertexWriter(boxVertexData, "color") - #Front 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) boxColorWriter.addData4f(color1[0], color1[1], color1[2], color1[3]) - #Left 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) boxColorWriter.addData4f(color2[0], color2[1], color2[2], color2[3]) - boxTris = GeomTristrips(Geom.UHStatic) # trianglestrip obejcet boxTris.addVertex(0)#(1) 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.addPrimitive(boxTris) - attachNode.addGeom(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") boxColorWriter = GeomVertexWriter(boxVertexData, "color") - boxVertexWriter.addData3f(-sX, sY, 0.0) boxNormalWriter.addData3f(0, 0, 1) 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.closePrimitive() - boxGeom = Geom(boxVertexData) boxGeom.addPrimitive(boxTris) - attachNode.addGeom(boxGeom) return boxGeom diff --git a/direct/src/stdpy/file.py b/direct/src/stdpy/file.py index d7eeb200dc..d14d334893 100644 --- a/direct/src/stdpy/file.py +++ b/direct/src/stdpy/file.py @@ -8,7 +8,7 @@ __all__ = [ 'open', 'listdir', 'walk', 'join', 'isfile', 'isdir', 'exists', 'lexists', 'getmtime', 'getsize', 'execfile', - ] +] from panda3d import core import os @@ -293,6 +293,7 @@ def listdir(path): files.append(file.getFilename().getBasename()) return files + def walk(top, topdown = True, onerror = None, followlinks = True): """ Implements os.walk over vfs. @@ -321,30 +322,37 @@ def walk(top, topdown = True, onerror = None, followlinks = True): if not topdown: yield (top, dirnames, filenames) + def isfile(path): return _vfs.isRegularFile(core.Filename.fromOsSpecific(path)) + def isdir(path): return _vfs.isDirectory(core.Filename.fromOsSpecific(path)) + def exists(path): return _vfs.exists(core.Filename.fromOsSpecific(path)) + def lexists(path): return _vfs.exists(core.Filename.fromOsSpecific(path)) + def getmtime(path): file = _vfs.getFile(core.Filename.fromOsSpecific(path), True) if not file: raise os.error return file.getTimestamp() + def getsize(path): file = _vfs.getFile(core.Filename.fromOsSpecific(path), True) if not file: raise os.error return file.getFileSize() + def execfile(path, globals=None, locals=None): file = _vfs.getFile(core.Filename.fromOsSpecific(path), True) if not file: diff --git a/direct/src/stdpy/thread.py b/direct/src/stdpy/thread.py index 31d4586c26..f20a2a54bc 100644 --- a/direct/src/stdpy/thread.py +++ b/direct/src/stdpy/thread.py @@ -14,7 +14,7 @@ __all__ = [ 'force_yield', 'consider_yield', 'forceYield', 'considerYield', 'TIMEOUT_MAX' - ] +] from panda3d import core import sys @@ -85,17 +85,22 @@ class LockType: def __exit__(self, t, v, tb): self.release() + # Helper to generate new thread names _counter = 0 + + def _newname(template="Thread-%d"): global _counter _counter = _counter + 1 return template % _counter + _threads = {} _nextThreadId = 0 _threadsLock = core.Mutex('thread._threadsLock') + def start_new_thread(function, args, kwargs = {}, name = None): def threadFunc(threadId, function = function, args = args, kwargs = kwargs): try: @@ -126,6 +131,7 @@ def start_new_thread(function, args, kwargs = {}, name = None): finally: _threadsLock.release() + def _add_thread(thread, wrapper): """ Adds the indicated core.Thread object, with the indicated Python wrapper, to the thread list. Returns the new thread ID. """ @@ -143,6 +149,7 @@ def _add_thread(thread, wrapper): finally: _threadsLock.release() + def _get_thread_wrapper(thread, wrapperClass): """ Returns the thread wrapper for the indicated thread. If there is not one, creates an instance of the indicated wrapperClass @@ -180,6 +187,7 @@ def _get_thread_wrapper(thread, wrapperClass): finally: _threadsLock.release() + def _get_thread_locals(thread, i): """ Returns the locals dictionary for the indicated thread. If there is not one, creates an empty dictionary. """ @@ -237,15 +245,19 @@ def interrupt_main(): # TODO. pass + def exit(): raise SystemExit + def allocate_lock(): return LockType() + def get_ident(): return core.Thread.getCurrentThread().this + def stack_size(size = 0): raise error diff --git a/direct/src/stdpy/threading.py b/direct/src/stdpy/threading.py index c4062b48a9..97cdf387f0 100644 --- a/direct/src/stdpy/threading.py +++ b/direct/src/stdpy/threading.py @@ -41,7 +41,7 @@ __all__ = [ 'enumerate', 'active_count', 'settrace', 'setprofile', 'stack_size', 'TIMEOUT_MAX', - ] +] TIMEOUT_MAX = _thread.TIMEOUT_MAX @@ -49,6 +49,7 @@ local = _thread._local _newname = _thread._newname ThreadError = _thread.error + class ThreadBase: """ A base class for both Thread and ExternalThread in this module. """ @@ -78,12 +79,14 @@ class ThreadBase: else: self.__dict__[key] = value + # Copy these static methods from Panda's Thread object. These are # useful if you may be running in Panda's SIMPLE_THREADS compilation # mode. ThreadBase.forceYield = core.Thread.forceYield ThreadBase.considerYield = core.Thread.considerYield + class Thread(ThreadBase): """ This class provides a wrapper around Panda's PythonThread object. The wrapper is designed to emulate Python's own @@ -161,6 +164,7 @@ class Thread(ThreadBase): self.__dict__['name'] = name self.__thread.setName(name) + class ExternalThread(ThreadBase): """ Returned for a Thread object that wasn't created by this interface. """ @@ -191,6 +195,7 @@ class ExternalThread(ThreadBase): def setDaemon(self, daemon): raise RuntimeError + class MainThread(ExternalThread): """ Returned for the MainThread object. """ @@ -198,6 +203,7 @@ class MainThread(ExternalThread): ExternalThread.__init__(self, extThread, threadId) self.__dict__['daemon'] = False + class Lock(core.Mutex): """ This class provides a wrapper around Panda's Mutex object. 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): self.release() + class Semaphore(core.Semaphore): """ This class provides a wrapper around Panda's Semaphore object. The wrapper is designed to emulate Python's own @@ -274,6 +281,7 @@ class Semaphore(core.Semaphore): def __exit__(self, t, v, tb): self.release() + class BoundedSemaphore(Semaphore): """ This class provides a wrapper around Panda's Semaphore object. The wrapper is designed to emulate Python's own @@ -289,6 +297,7 @@ class BoundedSemaphore(Semaphore): Semaphore.release(self) + class Event: """ This class is designed to emulate Python's own threading.Event object. """ @@ -339,6 +348,7 @@ class Event: finally: self.__lock.release() + class Timer(Thread): """Call a function after a specified number of seconds: @@ -365,6 +375,7 @@ class Timer(Thread): self.function(*self.args, **self.kwargs) self.finished.set() + def _create_thread_wrapper(t, threadId): """ Creates a thread wrapper for the indicated external thread. """ if isinstance(t, core.MainThread): @@ -374,16 +385,20 @@ def _create_thread_wrapper(t, threadId): return pyt + def current_thread(): t = core.Thread.getCurrentThread() return _thread._get_thread_wrapper(t, _create_thread_wrapper) + def main_thread(): t = core.Thread.getMainThread() return _thread._get_thread_wrapper(t, _create_thread_wrapper) + currentThread = current_thread + def enumerate(): tlist = [] _thread._threadsLock.acquire() @@ -395,24 +410,33 @@ def enumerate(): finally: _thread._threadsLock.release() + def active_count(): return len(enumerate()) + activeCount = active_count _settrace_func = None + + def settrace(func): global _settrace_func _settrace_func = func + _setprofile_func = None + + def setprofile(func): global _setprofile_func _setprofile_func = func + def stack_size(size = None): raise ThreadError + if __debug__: def _test(): from collections import deque @@ -482,7 +506,6 @@ if __debug__: self.queue.put("%s.%d" % (self.getName(), counter)) _sleep(random() * 0.00001) - class ConsumerThread(Thread): def __init__(self, queue, count): diff --git a/direct/src/task/Task.py b/direct/src/task/Task.py index e4e57264f5..b65a7149cc 100644 --- a/direct/src/task/Task.py +++ b/direct/src/task/Task.py @@ -74,10 +74,11 @@ def print_exc_plus(): #error we don't want. try: valueStr = str(value) - except: + except Exception: valueStr = "" print("\t%20s = %s" % (key, valueStr)) + # For historical purposes, we remap the C++-defined enumeration to # these Python names, and define them both at the module level, here, # and at the class level (below). The preferred access is via the @@ -109,21 +110,28 @@ Task.DtoolClassDict['pause'] = staticmethod(pause) gather = Task.gather shield = Task.shield + def sequence(*taskList): seq = AsyncTaskSequence('sequence') for task in taskList: seq.addTask(task) return seq + + Task.DtoolClassDict['sequence'] = staticmethod(sequence) + def loop(*taskList): seq = AsyncTaskSequence('loop') for task in taskList: seq.addTask(task) seq.setRepeatCount(-1) return seq + + Task.DtoolClassDict['loop'] = staticmethod(loop) + class TaskManager: notify = directNotify.newCategory("TaskManager") @@ -157,7 +165,7 @@ class TaskManager: taskId = None, profiled = False, session = None, - ) + ) def finalInit(self): # This function should be called once during startup, after @@ -317,7 +325,6 @@ class TaskManager: def doMethodLater(self, delayTime, funcOrTask, name, extraArgs = None, sort = None, priority = None, taskChain = None, uponDeath = None, appendTask = False, owner = None): - """Adds a task to be performed at some time in the future. This is identical to `add()`, except that the specified delayTime is applied to the Task object first, which means @@ -553,6 +560,7 @@ class TaskManager: try: if len(self._frameProfileQueue) > 0: numFrames, session, callback = self._frameProfileQueue.pop(0) + def _profileFunc(numFrames=numFrames): self._doProfiledFrames(numFrames) session.setFunc(_profileFunc) @@ -605,7 +613,7 @@ class TaskManager: # a nested try block are not caught by the inner try block's except try: (code, message) = ioError - except: + except Exception: code = 0 message = ioError return code, message @@ -709,7 +717,7 @@ class TaskManager: task = task, profiled = False, session = None, - ) + ) # Temporarily replace the task's own function with our # _profileTask method. @@ -817,6 +825,7 @@ class TaskManager: # run-once task l = [] + def _testDone(task, l=l): l.append(None) return task.done @@ -848,6 +857,7 @@ class TaskManager: # continued task l = [] + def _testCont(task, l = l): l.append(None) return task.cont @@ -862,6 +872,7 @@ class TaskManager: # continue until done task l = [] + def _testContDone(task, l = l): l.append(None) if len(l) >= 2: @@ -891,9 +902,11 @@ class TaskManager: # task sort l = [] + def _testPri1(task, l = l): l.append(1) return task.cont + def _testPri2(task, l = l): l.append(2) return task.cont @@ -913,6 +926,7 @@ class TaskManager: # task extraArgs l = [] + def _testExtraArgs(arg1, arg2, l=l): l.extend([arg1, arg2,]) return done @@ -925,6 +939,7 @@ class TaskManager: # task appendTask l = [] + def _testAppendTask(arg1, arg2, task, l=l): l.extend([arg1, arg2,]) return task.done @@ -937,8 +952,10 @@ class TaskManager: # task uponDeath l = [] + def _uponDeathFunc(task, l=l): l.append(task.name) + def _testUponDeath(task): return done tm.add(_testUponDeath, 'testUponDeath', uponDeath=_uponDeathFunc) @@ -953,10 +970,12 @@ class TaskManager: class _TaskOwner: def _addTask(self, task): self.addedTaskName = task.name + def _clearTask(self, task): self.clearedTaskName = task.name to = _TaskOwner() l = [] + def _testOwner(task): return done tm.add(_testOwner, 'testOwner', owner=to) @@ -968,15 +987,17 @@ class TaskManager: _TaskOwner = None tm._checkMemLeaks() - doLaterTests = [0,] # doLater l = [] + def _testDoLater1(task, l=l): l.append(1) + def _testDoLater2(task, l=l): l.append(2) + def _monitorDoLater(task, tm=tm, l=l, doLaterTests=doLaterTests): if task.time > .03: assert l == [1, 2,] @@ -996,10 +1017,13 @@ class TaskManager: # doLater sort l = [] + def _testDoLaterPri1(task, l=l): l.append(1) + def _testDoLaterPri2(task, l=l): l.append(2) + def _monitorDoLaterPri(task, tm=tm, l=l, doLaterTests=doLaterTests): if task.time > .02: assert l == [1, 2,] @@ -1019,8 +1043,10 @@ class TaskManager: # doLater extraArgs l = [] + def _testDoLaterExtraArgs(arg1, l=l): l.append(arg1) + def _monitorDoLaterExtraArgs(task, tm=tm, l=l, doLaterTests=doLaterTests): if task.time > .02: assert l == [3,] @@ -1038,9 +1064,11 @@ class TaskManager: # doLater appendTask l = [] + def _testDoLaterAppendTask(arg1, task, l=l): assert task.name == 'testDoLaterAppendTask' l.append(arg1) + def _monitorDoLaterAppendTask(task, tm=tm, l=l, doLaterTests=doLaterTests): if task.time > .02: assert l == [4,] @@ -1059,11 +1087,14 @@ class TaskManager: # doLater uponDeath l = [] + def _testUponDeathFunc(task, l=l): assert task.name == 'testDoLaterUponDeath' l.append(10) + def _testDoLaterUponDeath(arg1, l=l): return done + def _monitorDoLaterUponDeath(task, tm=tm, l=l, doLaterTests=doLaterTests): if task.time > .02: assert l == [10,] @@ -1085,12 +1116,15 @@ class TaskManager: class _DoLaterOwner: def _addTask(self, task): self.addedTaskName = task.name + def _clearTask(self, task): self.clearedTaskName = task.name doLaterOwner = _DoLaterOwner() l = [] + def _testDoLaterOwner(l=l): pass + def _monitorDoLaterOwner(task, tm=tm, l=l, doLaterOwner=doLaterOwner, doLaterTests=doLaterTests): if task.time > .02: @@ -1223,6 +1257,7 @@ class TaskManager: # create Task object and add to mgr l = [] + def _testTaskObj(task, l=l): l.append(None) return task.cont @@ -1240,6 +1275,7 @@ class TaskManager: # remove Task via task.remove() l = [] + def _testTaskObjRemove(task, l=l): l.append(None) return task.cont @@ -1299,6 +1335,7 @@ if __debug__: gc.enable() from direct.showbase.DirectObject import DirectObject from direct.task.TaskManagerGlobal import taskMgr + class TestClass(DirectObject): def doTask(self, task): return task.done diff --git a/direct/src/tkpanels/AnimPanel.py b/direct/src/tkpanels/AnimPanel.py index 2967394509..6e2db794a7 100644 --- a/direct/src/tkpanels/AnimPanel.py +++ b/direct/src/tkpanels/AnimPanel.py @@ -19,6 +19,7 @@ import tkinter as tk FRAMES = 0 SECONDS = 1 + class AnimPanel(AppShell): # Override class variables appname = 'Anim Panel' @@ -38,7 +39,7 @@ class AnimPanel(AppShell): ('title', self.appname, None), ('actorList', [], None), ('Actor_label_width', 12, None), - ) + ) self.defineoptions(kw, optiondefs) # direct session that spawned me, if any, used @@ -55,7 +56,6 @@ class AnimPanel(AppShell): # Initialize the superclass AppShell.__init__(self) - # Execute option callbacks self.initialiseoptions(AnimPanel) # We need to know when AnimPanel is closed @@ -270,7 +270,7 @@ class AnimPanel(AppShell): initialdir = '/i/beta', title = 'Load Animation', parent = self.component('hull') - ) + ) if not animFilename or animFilename == 'None': # no file selected, canceled return @@ -291,7 +291,6 @@ class AnimPanel(AppShell): self.clearActorControls() self.createActorControls() - def playActorControls(self): self.stopActorControls() self.lastT = ClockObject.getGlobalClock().getFrameTime() @@ -372,6 +371,7 @@ class AnimPanel(AppShell): self.destroyCallBack = None AppShell.destroy(self) + class ActorControl(Pmw.MegaWidget): def __init__(self, parent = None, **kw): @@ -391,7 +391,7 @@ class ActorControl(Pmw.MegaWidget): ('active', initActive, None), ('sLabel_width', 5, None), ('sLabel_font', DEFAULT_FONT, None), - ) + ) self.defineoptions(kw, optiondefs) # Initialize the superclass @@ -662,6 +662,7 @@ class ActorControl(Pmw.MegaWidget): self.fOneShot = 1 self.goToT((self.currT-(1/self.fps))%self.duration) + """ # EXAMPLE CODE from direct.actor import Actor diff --git a/direct/src/tkpanels/DirectSessionPanel.py b/direct/src/tkpanels/DirectSessionPanel.py index 95915facbc..b3e521deea 100644 --- a/direct/src/tkpanels/DirectSessionPanel.py +++ b/direct/src/tkpanels/DirectSessionPanel.py @@ -37,7 +37,7 @@ class DirectSessionPanel(AppShell): INITOPT = Pmw.INITOPT optiondefs = ( ('title', self.appname, None), - ) + ) self.defineoptions(kw, optiondefs) # Call superclass initialization function @@ -82,7 +82,7 @@ class DirectSessionPanel(AppShell): ('DIRECT_redoListEmpty', self.redoListEmptyHook), ('DIRECT_selectedNodePath', self.selectedNodePathHook), ('DIRECT_addLight', self.addLight), - ] + ] for event, method in self.actionEvents: self.accept(event, method) @@ -476,7 +476,6 @@ class DirectSessionPanel(AppShell): lightFrame.pack(expand = 1, fill = tk.BOTH) - def createGridPage(self, gridPage): tk.Label(gridPage, text = 'Grid', font=('MSSansSerif', 14, 'bold')).pack(expand = 0) @@ -649,7 +648,7 @@ class DirectSessionPanel(AppShell): else: # Good eval but not a node path, give up nodePath = None - except: + except Exception: # Bogus eval nodePath = None # Clear bogus entry from listbox @@ -699,7 +698,7 @@ class DirectSessionPanel(AppShell): else: # Good eval but not a node path, give up nodePath = None - except: + except Exception: # Bogus eval nodePath = None # Clear bogus entry from listbox @@ -740,6 +739,7 @@ class DirectSessionPanel(AppShell): # Background # def setBackgroundColor(self, r, g, b): self.setBackgroundColorVec((r, g, b)) + def setBackgroundColorVec(self, color): base.setBackgroundColor(color[0]/255.0, color[1]/255.0, diff --git a/direct/src/tkpanels/FSMInspector.py b/direct/src/tkpanels/FSMInspector.py index fff7e3a3a1..12049542fa 100644 --- a/direct/src/tkpanels/FSMInspector.py +++ b/direct/src/tkpanels/FSMInspector.py @@ -128,7 +128,7 @@ class FSMInspector(AppShell): optiondefs = ( ('title', fsm.getName(), None), ('gridSize', '0.25i', self._setGridSize), - ) + ) self.defineoptions(kw, optiondefs) self.fsm = fsm @@ -393,6 +393,7 @@ class FSMInspector(AppShell): self.ignore(self.name + '_' + si.getName() + '_entered') self.ignore(self.name + '_' + si.getName() + '_exited') + class StateInspector(Pmw.MegaArchetype): def __init__(self, inspector, state, **kw): @@ -412,7 +413,7 @@ class StateInspector(Pmw.MegaArchetype): optiondefs = ( ('radius', '0.375i', self._setRadius), ('gridSize', '0.25i', self._setGridSize), - ) + ) self.defineoptions(kw, optiondefs) # Initialize the parent class @@ -439,7 +440,6 @@ class StateInspector(Pmw.MegaArchetype): half, half, tags = (self.tag,)) - # The Popup State Menu self._popupMenu = tk.Menu(self._canvas, tearoff = 0) self._popupMenu.add_command(label = 'Request transition to ' + diff --git a/direct/src/tkpanels/Inspector.py b/direct/src/tkpanels/Inspector.py index 13df2f05d3..592e670cea 100644 --- a/direct/src/tkpanels/Inspector.py +++ b/direct/src/tkpanels/Inspector.py @@ -19,6 +19,7 @@ import tkinter as tk ### public API + def inspect(anObject): """Opens up a window for visually inspecting the details of a given Python object. See :ref:`inspection-utilities`. @@ -30,6 +31,7 @@ def inspect(anObject): ### private + def inspectorFor(anObject): typeName = type(anObject).__name__.capitalize() + 'Type' if typeName in _InspectorMap: @@ -72,7 +74,8 @@ def initializeInspectorMap(): 'StringType': 'SequenceInspector', 'TupleType': 'SequenceInspector', 'TypeType': 'Inspector', - 'UnboundMethodType': 'FunctionInspector'} + 'UnboundMethodType': 'FunctionInspector', + } for each in notFinishedTypes: _InspectorMap[each] = 'Inspector' @@ -119,10 +122,7 @@ class Inspector: object = self.partNumber(partNumber) doc = None if callable(object): - try: - doc = object.__doc__ - except: - pass + doc = getattr(object, '__doc__', None) if doc: return str(object) + '\n' + str(doc) else: @@ -150,10 +150,12 @@ class Inspector: ### + class ModuleInspector(Inspector): def namedParts(self): return ['__dict__'] + class ClassInspector(Inspector): def namedParts(self): return ['__bases__'] + list(self.object.__dict__.keys()) @@ -161,34 +163,41 @@ class ClassInspector(Inspector): def title(self): return self.object.__name__ + ' Class' + class InstanceInspector(Inspector): def title(self): return self.object.__class__.__name__ + def namedParts(self): return ['__class__'] + dir(self.object) ### + class FunctionInspector(Inspector): def title(self): return self.object.__name__ + "()" + class InstanceMethodInspector(Inspector): def title(self): return str(self.object.__self__.__class__) + "." + self.object.__name__ + "()" + class CodeInspector(Inspector): def title(self): return str(self.object) ### + class ComplexInspector(Inspector): def namedParts(self): return ['real', 'imag'] ### + class DictionaryInspector(Inspector): def initializePartsList(self): @@ -208,6 +217,7 @@ class DictionaryInspector(Inspector): else: return getattr(self.object, key) + class SequenceInspector(Inspector): def initializePartsList(self): Inspector.initializePartsList(self) @@ -224,6 +234,7 @@ class SequenceInspector(Inspector): else: return getattr(self.object, index) + class SliceInspector(Inspector): def namedParts(self): return ['start', 'stop', 'step'] @@ -232,6 +243,7 @@ class SliceInspector(Inspector): ### Initialization initializeInspectorMap() + class InspectorWindow: def __init__(self, inspector): self.inspectors = [inspector] @@ -346,8 +358,8 @@ class InspectorWindow: command = self.commandWidget.get(commandStart, commandStart + ' lineend') if command: - partDict = { 'this': self.selectedPart(), - 'object': self.topInspector().object } + partDict = {'this': self.selectedPart(), + 'object': self.topInspector().object} result = eval(command, partDict) self.commandWidget.insert(tk.INSERT, repr(result) + '\n>>> ') self.commandWidget.see(tk.INSERT) @@ -395,7 +407,7 @@ class InspectorWindow: text = tk.Label( 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.pack() #Private diff --git a/direct/src/tkpanels/MopathRecorder.py b/direct/src/tkpanels/MopathRecorder.py index 14f1017adc..033338cb33 100644 --- a/direct/src/tkpanels/MopathRecorder.py +++ b/direct/src/tkpanels/MopathRecorder.py @@ -46,6 +46,7 @@ PRF_UTILITIES = [ 'lambda s = self: s.playbackMarker.setZ(render, 0.0)', 'lambda s = self: s.followTerrain(10.0)'] + class MopathRecorder(AppShell, DirectObject): # Override class variables here appname = 'Mopath Recorder Panel' @@ -63,7 +64,7 @@ class MopathRecorder(AppShell, DirectObject): ('title', self.appname, None), ('nodePath', None, None), ('name', name, None) - ) + ) self.defineoptions(kw, optiondefs) # Call superclass initialization function @@ -191,7 +192,7 @@ class MopathRecorder(AppShell, DirectObject): ('DIRECT_manipulateObjectStart', self.manipulateObjectStartHook), ('DIRECT_manipulateObjectCleanup', self.manipulateObjectCleanupHook), - ] + ] for event, method in self.actionEvents: self.accept(event, method) @@ -930,6 +931,7 @@ class MopathRecorder(AppShell, DirectObject): def disableKeyframeButton(self): self.getWidget('Recording', 'Add Keyframe')['state'] = 'disabled' + def enableKeyframeButton(self): self.getWidget('Recording', 'Add Keyframe')['state'] = 'normal' @@ -1211,7 +1213,7 @@ class MopathRecorder(AppShell, DirectObject): else: # Good eval but not a node path, give up nodePath = None - except: + except Exception: # Bogus eval nodePath = None # Clear bogus entry from listbox diff --git a/direct/src/tkpanels/ParticlePanel.py b/direct/src/tkpanels/ParticlePanel.py index 55862d8031..aeebb9cd25 100644 --- a/direct/src/tkpanels/ParticlePanel.py +++ b/direct/src/tkpanels/ParticlePanel.py @@ -66,7 +66,7 @@ class ParticlePanel(AppShell): INITOPT = Pmw.INITOPT optiondefs = ( ('title', self.appname, None), - ) + ) self.defineoptions(kw, optiondefs) # Record particle effect @@ -113,7 +113,6 @@ class ParticlePanel(AppShell): self.particleEffect) self.forcePagesDict = {} - def createInterface(self): # Handle to the toplevels hull interior = self.interior() @@ -171,6 +170,7 @@ class ParticlePanel(AppShell): self.effectsLabelMenu.add_command( label = 'Place Particle Effect', command = lambda s = self: Placer.place(s.particleEffect)) + def togglePEVis(s = self): if s.particleEffect.isHidden(): s.particleEffect.show() @@ -257,7 +257,7 @@ class ParticlePanel(AppShell): 'Age in seconds at which the system (vs. particles) should die', self.setSystemLifespan, 0.0, None, None) - ) + ) self.createFloaters(systemPage, systemFloaterDefs) # Checkboxes @@ -327,19 +327,18 @@ class ParticlePanel(AppShell): self.createCheckbutton( zSpinPage, 'Z Spin Factory', 'Enable Angular Velocity', - ("On: angular velocity is used; " + - "Off: final angle is used"), + 'On: angular velocity is used; Off: final angle is used', self.toggleAngularVelocity, 0, side = tk.TOP) self.createFloater( zSpinPage, 'Z Spin Factory', 'Angular Velocity', - 'How fast sprites rotate', - command = self.setFactoryZSpinAngularVelocity) + 'How fast sprites rotate', + command = self.setFactoryZSpinAngularVelocity) self.createFloater( zSpinPage, 'Z Spin Factory', 'Angular Velocity Spread', - 'Variation in how fast sprites rotate', - command = self.setFactoryZSpinAngularVelocitySpread) + 'Variation in how fast sprites rotate', + command = self.setFactoryZSpinAngularVelocitySpread) self.createAngleDial(zSpinPage, 'Z Spin Factory', 'Initial Angle', 'Starting angle in degrees', @@ -996,7 +995,7 @@ class ParticlePanel(AppShell): widgets.append( self.createFloater(parent, category, label, balloonHelp, command, min, max, resolution) - ) + ) return widgets def createFloater(self, parent, category, text, balloonHelp, @@ -1158,7 +1157,7 @@ class ParticlePanel(AppShell): label = effect.getName(), command = (lambda s = self, e = effect: s.selectEffectNamed(e.getName())) - ) + ) effectActive = tk.IntVar() effectActive.set(effect.isEnabled()) self.effectsEnableMenu.add_checkbutton( @@ -1183,7 +1182,7 @@ class ParticlePanel(AppShell): label = name, command = (lambda s = self, n = name: s.selectParticlesNamed(n)) - ) + ) particleActive = tk.IntVar() particleActive.set(particle.isEnabled()) self.particlesEnableMenu.add_checkbutton( @@ -1208,7 +1207,7 @@ class ParticlePanel(AppShell): label = name, command = (lambda s = self, n = name: s.selectForceGroupNamed(n)) - ) + ) forceActive = tk.IntVar() forceActive.set(force.isEnabled()) self.forceGroupEnableMenu.add_checkbutton( @@ -1379,24 +1378,33 @@ class ParticlePanel(AppShell): self.particles.getLocalVelocityFlag()) self.getVariable('System', 'System Grows Older').set( self.particles.getSystemGrowsOlderFlag()) + def setSystemPoolSize(self, value): self.particles.setPoolSize(int(value)) + def setSystemBirthRate(self, value): self.particles.setBirthRate(value) + def setSystemLitterSize(self, value): self.particles.setLitterSize(int(value)) + def setSystemLitterSpread(self, value): self.particles.setLitterSpread(int(value)) + def setSystemLifespan(self, value): self.particles.setSystemLifespan(value) + def toggleSystemLocalVelocity(self): self.particles.setLocalVelocityFlag( self.getVariable('System', 'Render Space Velocities').get()) + def toggleSystemGrowsOlder(self): self.particles.setSystemGrowsOlderFlag( self.getVariable('System', 'System Grows Older').get()) + def setSystemPos(self, pos): self.particles.nodePath.setPos(Vec3(pos[0], pos[1], pos[2])) + def setSystemHpr(self, pos): self.particles.nodePath.setHpr(Vec3(pos[0], pos[1], pos[2])) @@ -1427,28 +1435,39 @@ class ParticlePanel(AppShell): def setFactoryLifeSpan(self, value): self.particles.factory.setLifespanBase(value) + def setFactoryLifeSpanSpread(self, value): self.particles.factory.setLifespanSpread(value) + def setFactoryParticleMass(self, value): self.particles.factory.setMassBase(value) + def setFactoryParticleMassSpread(self, value): self.particles.factory.setMassSpread(value) + def setFactoryTerminalVelocity(self, value): self.particles.factory.setTerminalVelocityBase(value) + def setFactoryTerminalVelocitySpread(self, value): self.particles.factory.setTerminalVelocitySpread(value) # Point Page # # Z Spin Page # + def setFactoryZSpinInitialAngle(self, angle): self.particles.factory.setInitialAngle(angle) + def setFactoryZSpinInitialAngleSpread(self, spread): self.particles.factory.setInitialAngleSpread(spread) + def setFactoryZSpinFinalAngle(self, angle): self.particles.factory.setFinalAngle(angle) + def setFactoryZSpinFinalAngleSpread(self, spread): self.particles.factory.setFinalAngleSpread(spread) + def setFactoryZSpinAngularVelocity(self, vel): self.particles.factory.setAngularVelocity(vel) + def setFactoryZSpinAngularVelocitySpread(self, spread): self.particles.factory.setAngularVelocitySpread(spread) @@ -1539,6 +1558,7 @@ class ParticlePanel(AppShell): self.getWidget('Tangent Ring Emitter', 'Radius Spread').set( radiusSpread, 0) # All # + def setEmissionType(self, newType = None): if newType: type = newType @@ -1601,57 +1621,76 @@ class ParticlePanel(AppShell): self.particles.emitter.setMinBound(Point3(point[0], point[1], point[2])) + def setEmitterBoxPoint2(self, point): self.particles.emitter.setMaxBound(Point3(point[0], point[1], point[2])) # Disc # + def setEmitterDiscRadius(self, radius): self.particles.emitter.setRadius(radius) + def setEmitterDiscInnerAngle(self, angle): self.particles.emitter.setInnerAngle(angle) + def setEmitterDiscInnerVelocity(self, velocity): self.particles.emitter.setInnerMagnitude(velocity) + def setEmitterDiscOuterAngle(self, angle): self.particles.emitter.setOuterAngle(angle) + def setEmitterDiscOuterVelocity(self, velocity): self.particles.emitter.setOuterMagnitude(velocity) + def toggleEmitterDiscCubicLerping(self): self.particles.emitter.setCubicLerping( self.getVariable('Disc Emitter', 'Cubic Lerping').get()) # Line # + def setEmitterLinePoint1(self, point): self.particles.emitter.setEndpoint1(Point3(point[0], point[1], point[2])) + def setEmitterLinePoint2(self, point): self.particles.emitter.setEndpoint2(Point3(point[0], point[1], point[2])) # Point # + def setEmitterPointPosition(self, pos): self.particles.emitter.setLocation(Point3(pos[0], pos[1], pos[2])) # Rectangle # + def setEmitterRectanglePoint1(self, point): self.particles.emitter.setMinBound(Point2(point[0], point[1])) + def setEmitterRectanglePoint2(self, point): self.particles.emitter.setMaxBound(Point2(point[0], point[1])) # Ring # + def setEmitterRingRadius(self, radius): self.particles.emitter.setRadius(radius) + def setEmitterRingRadiusSpread(self, radiusSpread): self.particles.emitter.setRadiusSpread(radiusSpread) + def setEmitterRingLaunchAngle(self, angle): self.particles.emitter.setAngle(angle) # Sphere surface # + def setEmitterSphereSurfaceRadius(self, radius): self.particles.emitter.setRadius(radius) # Sphere volume # + def setEmitterSphereVolumeRadius(self, radius): self.particles.emitter.setRadius(radius) # Tangent ring # + def setEmitterTangentRingRadius(self, radius): self.particles.emitter.setRadius(radius) + def setEmitterTangentRingRadiusSpread(self, radiusSpread): self.particles.emitter.setRadiusSpread(radiusSpread) @@ -1849,13 +1888,16 @@ class ParticlePanel(AppShell): self.particles.renderer.setHeadColor( Vec4(color[0]/255.0, color[1]/255.0, color[2]/255.0, color[3]/255.0)) + def setRendererLineTailColor(self, color): self.particles.renderer.setTailColor( Vec4(color[0]/255.0, color[1]/255.0, color[2]/255.0, color[3]/255.0)) + def setRendererLineScaleFactor(self, sf): self.particles.renderer.setLineScaleFactor(sf) # Geom # + def setRendererGeomNode(self, event): node = None nodePath = base.loader.loadModel(self.rendererGeomNode.get()) @@ -1865,16 +1907,20 @@ class ParticlePanel(AppShell): self.particles.geomReference = self.rendererGeomNode.get() self.particles.renderer.setGeomNode(node) # Point # + def setRendererPointSize(self, size): self.particles.renderer.setPointSize(size) + def setRendererPointStartColor(self, color): self.particles.renderer.setStartColor( Vec4(color[0]/255.0, color[1]/255.0, color[2]/255.0, color[3]/255.0)) + def setRendererPointEndColor(self, color): self.particles.renderer.setEndColor( Vec4(color[0]/255.0, color[1]/255.0, color[2]/255.0, color[3]/255.0)) + def rendererPointSelectBlendType(self, blendType): if blendType == "PP_ONE_COLOR": bType = PointParticleRenderer.PPONECOLOR @@ -1883,6 +1929,7 @@ class ParticlePanel(AppShell): elif blendType == "PP_BLEND_VEL": bType = PointParticleRenderer.PPBLENDVEL self.particles.renderer.setBlendType(bType) + def rendererPointSelectBlendMethod(self, blendMethod): if blendMethod == "PP_NO_BLEND": bMethod = BaseParticleRenderer.PPNOBLEND @@ -1892,18 +1939,23 @@ class ParticlePanel(AppShell): bMethod = BaseParticleRenderer.PPBLENDCUBIC self.particles.renderer.setBlendMethod(bMethod) # Sparkle # + def setRendererSparkleCenterColor(self, color): self.particles.renderer.setCenterColor( Vec4(color[0]/255.0, color[1]/255.0, color[2]/255.0, color[3]/255.0)) + def setRendererSparkleEdgeColor(self, color): self.particles.renderer.setEdgeColor( Vec4(color[0]/255.0, color[1]/255.0, color[2]/255.0, color[3]/255.0)) + def setRendererSparkleBirthRadius(self, radius): self.particles.renderer.setBirthRadius(radius) + def setRendererSparkleDeathRadius(self, radius): self.particles.renderer.setDeathRadius(radius) + def setRendererSparkleLifeScale(self, lifeScaleMethod): if lifeScaleMethod == 'SP_NO_SCALE': lScale = SparkleParticleRenderer.SPNOSCALE @@ -1911,6 +1963,7 @@ class ParticlePanel(AppShell): lScale = SparkleParticleRenderer.SPSCALE self.particles.renderer.setLifeScale(lScale) # Sprite # + def setSpriteSourceType(self): if self.rendererSpriteSourceType.get() == 0: self.rendererSpriteTextureEntry['state'] = 'normal' @@ -1929,9 +1982,11 @@ class ParticlePanel(AppShell): def setRendererSpriteAnimationFrameRate(self, rate): self.particles.renderer.setAnimateFramesRate(rate) + def setRendererSpriteAnimationEnable(self): self.particles.renderer.setAnimateFramesEnable( self.getVariable('Sprite Renderer','Enable Animation').get()) + def addRendererSpriteAnimationTexture(self): ren = self.particles.getRenderer() parent = self.rendererSpriteAnimationFrame @@ -1953,6 +2008,7 @@ class ParticlePanel(AppShell): self.rendererSpriteAnimationWidgetList.append( self.createSpriteAnimationTextureWidget(parent, anim, repr(frameNum))) parent.pack(fill=tk.BOTH, expand=1) + def addRendererSpriteAnimationFromNode(self): ren = self.particles.getRenderer() parent = self.rendererSpriteAnimationFrame @@ -1978,9 +2034,11 @@ class ParticlePanel(AppShell): def toggleRendererSpriteXScale(self): self.particles.renderer.setXScaleFlag( self.getVariable('Sprite Renderer', 'X Scale').get()) + def toggleRendererSpriteYScale(self): self.particles.renderer.setYScaleFlag( self.getVariable('Sprite Renderer', 'Y Scale').get()) + def toggleRendererSpriteAnimAngle(self): self.particles.renderer.setAnimAngleFlag( self.getVariable('Sprite Renderer', 'Anim Angle').get()) @@ -1991,14 +2049,19 @@ class ParticlePanel(AppShell): def setRendererSpriteInitialXScale(self, xScale): self.particles.renderer.setInitialXScale(xScale) + def setRendererSpriteFinalXScale(self, xScale): self.particles.renderer.setFinalXScale(xScale) + def setRendererSpriteInitialYScale(self, yScale): self.particles.renderer.setInitialYScale(yScale) + def setRendererSpriteFinalYScale(self, yScale): self.particles.renderer.setFinalYScale(yScale) + def setRendererSpriteNonAnimatedTheta(self, theta): self.particles.renderer.setNonanimatedTheta(theta) + def setRendererSpriteBlendMethod(self, blendMethod): if blendMethod == 'PP_NO_BLEND': bMethod = BaseParticleRenderer.PPNOBLEND @@ -2008,9 +2071,11 @@ class ParticlePanel(AppShell): bMethod = BaseParticleRenderer.PPBLENDCUBIC else: bMethod = BaseParticleRenderer.PPNOBLEND + def toggleRendererSpriteAlphaDisable(self): self.particles.renderer.setAlphaDisable( self.getVariable('Sprite Renderer', 'Alpha Disable').get()) + def setRendererColorBlendAttrib(self, rendererName, blendMethodStr, incomingOperandStr, fbufferOperandStr): self.particles.getRenderer().setColorBlendMode(getattr(ColorBlendAttrib, blendMethodStr), getattr(ColorBlendAttrib, incomingOperandStr), @@ -2024,48 +2089,56 @@ class ParticlePanel(AppShell): self.getWidget(rendererName,'Fbuffer Op.').pack_forget() self.updateRendererWidgets() + def setRendererSpriteColorBlendMethod(self, blendMethod): blendMethodStr = blendMethod incomingOperandStr = self.getVariable('Sprite Renderer','Incoming Op.').get() fbufferOperandStr = self.getVariable('Sprite Renderer','Fbuffer Op.').get() self.setRendererColorBlendAttrib('Sprite Renderer', blendMethodStr, incomingOperandStr, fbufferOperandStr) + def setRendererSpriteColorBlendIncomingOperand(self, operand): blendMethodStr = self.getVariable('Sprite Renderer','Color Blend').get() incomingOperandStr = operand fbufferOperandStr = self.getVariable('Sprite Renderer','Fbuffer Op.').get() self.setRendererColorBlendAttrib('Sprite Renderer', blendMethodStr, incomingOperandStr, fbufferOperandStr) + def setRendererSpriteColorBlendFbufferOperand(self, operand): blendMethodStr = self.getVariable('Sprite Renderer','Color Blend').get() incomingOperandStr = self.getVariable('Sprite Renderer','Incoming Op.').get() fbufferOperandStr = operand self.setRendererColorBlendAttrib('Sprite Renderer', blendMethodStr, incomingOperandStr, fbufferOperandStr) - # GeomParticleRenderer Functionality + def toggleRendererGeomXScale(self): self.particles.renderer.setXScaleFlag( self.getVariable('Geom Renderer', 'X Scale').get()) + def toggleRendererGeomYScale(self): self.particles.renderer.setYScaleFlag( self.getVariable('Geom Renderer', 'Y Scale').get()) + def toggleRendererGeomZScale(self): self.particles.renderer.setZScaleFlag( self.getVariable('Geom Renderer', 'Z Scale').get()) def setRendererGeomInitialXScale(self, xScale): self.particles.renderer.setInitialXScale(xScale) + def setRendererGeomFinalXScale(self, xScale): self.particles.renderer.setFinalXScale(xScale) def setRendererGeomInitialYScale(self, yScale): self.particles.renderer.setInitialYScale(yScale) + def setRendererGeomFinalYScale(self, yScale): self.particles.renderer.setFinalYScale(yScale) def setRendererGeomInitialZScale(self, zScale): self.particles.renderer.setInitialZScale(zScale) + def setRendererGeomFinalZScale(self, zScale): self.particles.renderer.setFinalZScale(zScale) @@ -2087,7 +2160,6 @@ class ParticlePanel(AppShell): fbufferOperandStr = operand self.setRendererColorBlendAttrib('Geom Renderer', blendMethodStr, incomingOperandStr, fbufferOperandStr) - def addConstantInterpolationSegment(self, id = None): ren = self.particles.getRenderer() cim = ren.getColorInterpolationManager() @@ -2187,17 +2259,22 @@ class ParticlePanel(AppShell): def createInterpolationSegmentFrame(self, parent, segName, seg): frame = tk.Frame(parent, relief = tk.RAISED, borderwidth = 2) lFrame = tk.Frame(frame, relief = tk.FLAT) + def removeInterpolationSegmentFrame(s = self, seg = seg, fr = frame): s.particles.getRenderer().getColorInterpolationManager().clearSegment(seg.getId()) fr.pack_forget() + def setSegEnabled(s=self, n=segName): enabled = s.getVariable('Sprite Renderer', n+' Enabled') seg.setEnabled(enabled.get()) + def setIsModulated(s=self, n=segName): modulated = s.getVariable('Sprite Renderer', n+' isModulated') seg.setIsModulated(modulated.get()) + def setSegBegin(time): seg.setTimeBegin(time) + def setSegEnd(time): seg.setTimeEnd(time) tk.Button(lFrame, text = 'X', @@ -2236,6 +2313,7 @@ class ParticlePanel(AppShell): def createConstantInterpolationSegmentWidget(self, parent, segName, segment): fun = segment.getFunction() + def setSegColorA(color): fun.setColorA( Vec4(color[0]/255.0, color[1]/255.0, @@ -2255,10 +2333,12 @@ class ParticlePanel(AppShell): def createLinearInterpolationSegmentWidget(self, parent, segName, segment): fun = segment.getFunction() + def setSegColorA(color): fun.setColorA( Vec4(color[0]/255.0, color[1]/255.0, color[2]/255.0, color[3]/255.0)) + def setSegColorB(color): fun.setColorB( Vec4(color[0]/255.0, color[1]/255.0, @@ -2284,16 +2364,20 @@ class ParticlePanel(AppShell): def createStepwaveInterpolationSegmentWidget(self, parent, segName, segment): fun = segment.getFunction() + def setColorA(color): fun.setColorA( Vec4(color[0]/255.0, color[1]/255.0, color[2]/255.0, color[3]/255.0)) + def setColorB(color): fun.setColorB( Vec4(color[0]/255.0, color[1]/255.0, color[2]/255.0, color[3]/255.0)) + def setWidthA(width): fun.setWidthA(width) + def setWidthB(width): fun.setWidthB(width) @@ -2327,14 +2411,17 @@ class ParticlePanel(AppShell): def createSinusoidInterpolationSegmentWidget(self, parent, segName, segment): fun = segment.getFunction() + def setColorA(color): fun.setColorA( Vec4(color[0]/255.0, color[1]/255.0, color[2]/255.0, color[3]/255.0)) + def setColorB(color): fun.setColorB( Vec4(color[0]/255.0, color[1]/255.0, color[2]/255.0, color[3]/255.0)) + def setPeriod(period): fun.setPeriod(period) @@ -2543,18 +2630,25 @@ class ParticlePanel(AppShell): def addLinearVectorForce(self): self.addForce(LinearVectorForce()) + def addLinearFrictionForce(self): self.addForce(LinearFrictionForce()) + def addLinearJitterForce(self): self.addForce(LinearJitterForce()) + def addLinearNoiseForce(self): self.addForce(LinearNoiseForce()) + def addLinearSinkForce(self): self.addForce(LinearSinkForce()) + def addLinearSourceForce(self): self.addForce(LinearSourceForce()) + def addLinearCylinderVortexForce(self): self.addForce(LinearCylinderVortexForce()) + def addLinearUserDefinedForce(self): self.addForce(LinearUserDefinedForce()) @@ -2650,6 +2744,7 @@ class ParticlePanel(AppShell): def createForceFrame(self, forcePage, forceName, force): frame = tk.Frame(forcePage, relief = tk.RAISED, borderwidth = 2) lFrame = tk.Frame(frame, relief = tk.FLAT) + def removeForce(s = self, f = force, fr = frame): s.forceGroup.removeForce(f) fr.pack_forget() @@ -2667,9 +2762,11 @@ class ParticlePanel(AppShell): def createLinearForceWidgets(self, frame, pageName, forceName, force): def setAmplitude(amp, f = force): f.setAmplitude(amp) + def toggleMassDependent(s=self, f=force, p=pageName, n=forceName): v = s.getVariable(p, n+' Mass Dependent') f.setMassDependent(v.get()) + def setVectorMasks(s=self, f=force, p=pageName, n=forceName): xMask = s.getVariable(p, n+' Mask X').get() yMask = s.getVariable(p, n+' Mask Y').get() @@ -2698,6 +2795,7 @@ class ParticlePanel(AppShell): def createForceActiveWidget(self, frame, pageName, forceName, force): cbName = forceName + ' Active' + def toggle(s = self, f = force, p = pageName, n = cbName): s.toggleForce(f, p, n) self.createCheckbutton(frame, pageName, cbName, @@ -2741,10 +2839,13 @@ class ParticlePanel(AppShell): def createLinearCylinderVortexForceWidget(self, forcePage, pageName, count, force): forceName = 'Vortex Force-' + repr(count) + def setCoef(coef, f = force): f.setCoef(coef) + def setLength(length, f = force): f.setLength(length) + def setRadius(radius, f = force): f.setRadius(radius) frame = self.createForceFrame(forcePage, forceName, force) @@ -2775,8 +2876,10 @@ class ParticlePanel(AppShell): if type == 'FT_ONE_OVER_R_CUBED': #f.setFalloffType(LinearDistanceForce.FTONEOVERRCUBED) f.setFalloffType(2) + def setForceCenter(vec, f = force): f.setForceCenter(Point3(vec[0], vec[1], vec[2])) + def setRadius(radius, f = force): f.setRadius(radius) forceName = type + ' Force-' + repr(count) @@ -2813,12 +2916,12 @@ class ParticlePanel(AppShell): ###################################################################### + # Create demo in root window for testing. if __name__ == '__main__': - try: base - except: + except NameError: from direct.showbase.ShowBase import ShowBase base = ShowBase() diff --git a/direct/src/tkpanels/Placer.py b/direct/src/tkpanels/Placer.py index c807818f2a..addbe1f414 100644 --- a/direct/src/tkpanels/Placer.py +++ b/direct/src/tkpanels/Placer.py @@ -15,6 +15,7 @@ import tkinter as tk #TODO: Task to monitor pose + class Placer(AppShell): # Override class variables here appname = 'Placer Panel' @@ -28,7 +29,7 @@ class Placer(AppShell): optiondefs = ( ('title', self.appname, None), ('nodePath', base.direct.camera, None), - ) + ) self.defineoptions(kw, optiondefs) # Call superclass initialization function @@ -355,8 +356,8 @@ class Placer(AppShell): self.scaleY['command'] = self.xform self.scaleZ['command'] = self.xform - ### WIDGET OPERATIONS ### + def setMovementMode(self, movementMode): # Set prefix namePrefix = '' @@ -407,7 +408,7 @@ class Placer(AppShell): else: # Good eval but not a node path, give up nodePath = None - except: + except Exception: # Bogus eval nodePath = None # Clear bogus entry from listbox @@ -464,7 +465,7 @@ class Placer(AppShell): else: # Good eval but not a node path, give up nodePath = None - except: + except Exception: # Bogus eval nodePath = None # Clear bogus entry from listbox @@ -782,11 +783,13 @@ class Placer(AppShell): self.orbitFromCS.removeNode() self.orbitToCS.removeNode() + def place(nodePath): return Placer(nodePath = nodePath) ###################################################################### + # Create demo in root window for testing. if __name__ == '__main__': root = Pmw.initialise() diff --git a/direct/src/tkpanels/TaskManagerPanel.py b/direct/src/tkpanels/TaskManagerPanel.py index 4a936837d8..3f974c1fb2 100644 --- a/direct/src/tkpanels/TaskManagerPanel.py +++ b/direct/src/tkpanels/TaskManagerPanel.py @@ -21,7 +21,7 @@ class TaskManagerPanel(AppShell): INITOPT = Pmw.INITOPT optiondefs = ( ('title', self.appname, None), - ) + ) self.defineoptions(kw, optiondefs) self.taskMgr = taskMgr @@ -38,10 +38,10 @@ class TaskManagerPanel(AppShell): self.taskMgrWidget = TaskManagerWidget( self.interior(), self.taskMgr) - def onDestroy(self, event): self.taskMgrWidget.onDestroy() + class TaskManagerWidget(DirectObject): """ TaskManagerWidget class: this class contains methods for creating diff --git a/direct/src/tkwidgets/AppShell.py b/direct/src/tkwidgets/AppShell.py index efc118801d..ad76a7ccae 100644 --- a/direct/src/tkwidgets/AppShell.py +++ b/direct/src/tkwidgets/AppShell.py @@ -27,9 +27,11 @@ if not hasattr(builtins, "widgetDict"): if not hasattr(builtins, "variableDict"): builtins.variableDict = {} + def resetWidgetDict(): builtins.widgetDict = {} + def resetVariableDict(): builtins.variableDict = {} @@ -63,7 +65,7 @@ class AppShell(Pmw.MegaWidget, DirectObject): ('frameheight', self.frameHeight, Pmw.INITOPT), ('usecommandarea', self.usecommandarea, Pmw.INITOPT), ('usestatusarea', self.usestatusarea, Pmw.INITOPT), - ) + ) self.defineoptions(kw, optiondefs) # If no toplevel passed in, create one if parent is None: @@ -166,7 +168,6 @@ class AppShell(Pmw.MegaWidget, DirectObject): padx=self['padx'], pady=self['pady']) - def __createMessageBar(self): # Create the message bar area for help and status messages. frame = self.createcomponent('bottomtray', (), None, @@ -199,9 +200,8 @@ class AppShell(Pmw.MegaWidget, DirectObject): Pmw.aboutversion(self.appversion) Pmw.aboutcopyright(self.copyright) Pmw.aboutcontact( - 'For more information, contact:\n %s\n Phone: %s\n Email: %s' %\ - (self.contactname, self.contactphone, - self.contactemail)) + 'For more information, contact:\n %s\n Phone: %s\n Email: %s' % \ + (self.contactname, self.contactphone, self.contactemail)) self.about = Pmw.AboutDialog(self._hull, applicationname=self.appname) self.about.withdraw() @@ -509,6 +509,7 @@ class AppShell(Pmw.MegaWidget, DirectObject): # Record widget self.addWidget(category, text, widget) return widget + def transformRGB(self, rgb, max = 1.0): retval = '#' for v in [rgb[0], rgb[1], rgb[2]]: @@ -520,6 +521,7 @@ class AppShell(Pmw.MegaWidget, DirectObject): retval = "%s%02x" % (retval, int(v)) return retval + class TestAppShell(AppShell): # Override class variables here appname = 'Test Application Shell' @@ -549,5 +551,6 @@ class TestAppShell(AppShell): self.createButtons() self.createMain() + if __name__ == '__main__': test = TestAppShell(balloon_state='none') diff --git a/direct/src/tkwidgets/Dial.py b/direct/src/tkwidgets/Dial.py index 7be1f9993a..2b1c062439 100644 --- a/direct/src/tkwidgets/Dial.py +++ b/direct/src/tkwidgets/Dial.py @@ -22,11 +22,13 @@ INNER_SF = 0.2 DIAL_FULL_SIZE = 45 DIAL_MINI_SIZE = 30 + class Dial(Valuator): """ Valuator widget which includes an angle dial and an entry for setting floating point values """ + def __init__(self, parent = None, **kw): INITOPT = Pmw.INITOPT optiondefs = ( @@ -35,7 +37,7 @@ class Dial(Valuator): ('delta', 1.0, self.setDelta), ('fSnap', 0, self.setSnap), ('fRollover', 1, self.setRollover), - ) + ) self.defineoptions(kw, optiondefs) Valuator.__init__(self, parent) self.initialiseoptions(Dial) @@ -70,19 +72,19 @@ class Dial(Valuator): def addValuatorPropertiesToDialog(self): self.addPropertyToDialog( 'base', - { 'widget': self._valuator, - 'type': 'real', - 'help': 'Dial value = base + delta * numRevs'}) + {'widget': self._valuator, + 'type': 'real', + 'help': 'Dial value = base + delta * numRevs'}) self.addPropertyToDialog( 'delta', - { 'widget': self._valuator, - 'type': 'real', - 'help': 'Dial value = base + delta * numRevs'}) + {'widget': self._valuator, + 'type': 'real', + 'help': 'Dial value = base + delta * numRevs'}) self.addPropertyToDialog( 'numSegments', - { 'widget': self._valuator, - 'type': 'integer', - 'help': 'Number of segments to divide dial into.'}) + {'widget': self._valuator, + 'type': 'integer', + 'help': 'Number of segments to divide dial into.'}) def addValuatorMenuEntries(self): # The popup menu @@ -137,7 +139,7 @@ class AngleDial(Dial): ('delta', 360.0, None), ('fRollover', 0, None), ('dial_numSegments', 12, None), - ) + ) self.defineoptions(kw, optiondefs) # Initialize the superclass Dial.__init__(self, parent) @@ -179,7 +181,7 @@ class DialWidget(Pmw.MegaWidget): ('postCallback', None, None), # Extra data to be passed to callback function, needs to be a list ('callbackData', [], None), - ) + ) self.defineoptions(kw, optiondefs) # Initialize the superclass diff --git a/direct/src/tkwidgets/EntryScale.py b/direct/src/tkwidgets/EntryScale.py index 014bfd77c7..cb6516275c 100644 --- a/direct/src/tkwidgets/EntryScale.py +++ b/direct/src/tkwidgets/EntryScale.py @@ -20,16 +20,16 @@ class EntryScale(Pmw.MegaWidget): optiondefs = ( ('state', None, None), ('value', 0.0, Pmw.INITOPT), - ('resolution', 0.001, None), - ('command', None, None), - ('preCallback', None, None), - ('postCallback', None, None), - ('callbackData', [], None), - ('min', 0.0, self._updateValidate), - ('max', 100.0, self._updateValidate), - ('text', 'EntryScale', self._updateLabelText), - ('numDigits', 2, self._setSigDigits), - ) + ('resolution', 0.001, None), + ('command', None, None), + ('preCallback', None, None), + ('postCallback', None, None), + ('callbackData', [], None), + ('min', 0.0, self._updateValidate), + ('max', 100.0, self._updateValidate), + ('text', 'EntryScale', self._updateLabelText), + ('numDigits', 2, self._setSigDigits), + ) self.defineoptions(kw, optiondefs) # Initialise superclass @@ -57,16 +57,16 @@ class EntryScale(Pmw.MegaWidget): (('entry', 'entryField_entry'),), None, Pmw.EntryField, self.labelFrame, - entry_width = 10, - validate = { 'validator': 'real', - 'min': self['min'], - 'max': self['max'], - 'minstrict': 0, - 'maxstrict': 0}, - entry_justify = 'right', - entry_textvar = self.entryValue, - command = self._entryCommand) - self.entry.pack(side='left', padx = 4) + entry_width=10, + validate={'validator': 'real', + 'min': self['min'], + 'max': self['max'], + 'minstrict': 0, + 'maxstrict': 0}, + entry_justify='right', + entry_textvar=self.entryValue, + command=self._entryCommand) + self.entry.pack(side='left', padx=4) # Create the EntryScale's label self.label = self.createcomponent('label', (), None, @@ -270,6 +270,7 @@ class EntryScale(Pmw.MegaWidget): def onRelease(self, *args): """ User redefinable callback executed on button release """ + class EntryScaleGroup(Pmw.MegaToplevel): def __init__(self, parent = None, **kw): @@ -295,7 +296,7 @@ class EntryScaleGroup(Pmw.MegaToplevel): ('labels', DEFAULT_LABELS, self._updateLabels), # Destroy or withdraw ('fDestroy', 0, INITOPT) - ) + ) self.defineoptions(kw, optiondefs) # Initialize the toplevel widget @@ -450,9 +451,9 @@ def rgbPanel(nodePath, callback = None): dim = 4, labels = ['R','G','B','A'], value = [int(initColor[0]), - int(initColor[1]), - int(initColor[2]), - int(initColor[3])], + int(initColor[1]), + int(initColor[2]), + int(initColor[3])], Valuator_max = 255, Valuator_resolution = 1, # Destroy not withdraw panel on dismiss diff --git a/direct/src/tkwidgets/Floater.py b/direct/src/tkwidgets/Floater.py index a3adbde188..6544eb3890 100644 --- a/direct/src/tkwidgets/Floater.py +++ b/direct/src/tkwidgets/Floater.py @@ -16,12 +16,13 @@ import tkinter as tk FLOATER_WIDTH = 22 FLOATER_HEIGHT = 18 + class Floater(Valuator): def __init__(self, parent = None, **kw): INITOPT = Pmw.INITOPT optiondefs = ( ('style', VALUATOR_MINI, INITOPT), - ) + ) self.defineoptions(kw, optiondefs) # Initialize the superclass Valuator.__init__(self, parent) @@ -70,7 +71,7 @@ class FloaterWidget(Pmw.MegaWidget): ('postCallback', None, None), # Extra data to be passed to callback function, needs to be a list ('callbackData', [], None), - ) + ) self.defineoptions(kw, optiondefs) # Initialize the superclass @@ -234,7 +235,7 @@ class FloaterGroup(Pmw.MegaToplevel): ('command', None, None), # A tuple of labels, one for each floater ('labels', DEFAULT_LABELS, self._updateLabels), - ) + ) self.defineoptions(kw, optiondefs) # Initialize the toplevel widget diff --git a/direct/src/tkwidgets/SceneGraphExplorer.py b/direct/src/tkwidgets/SceneGraphExplorer.py index c4e2e515af..0a0feeb490 100644 --- a/direct/src/tkwidgets/SceneGraphExplorer.py +++ b/direct/src/tkwidgets/SceneGraphExplorer.py @@ -28,8 +28,10 @@ DEFAULT_MENU_ITEMS = [ 'Place', 'Set Name', 'Set Color', 'Explore', 'Separator'] + class SceneGraphExplorer(Pmw.MegaWidget, DirectObject): "Graphical display of a scene graph" + def __init__(self, parent = None, nodePath = None, isItemEditable = True, **kw): if nodePath is None: nodePath = base.render @@ -37,7 +39,7 @@ class SceneGraphExplorer(Pmw.MegaWidget, DirectObject): # Define the megawidget options. optiondefs = ( ('menuItems', [], Pmw.INITOPT), - ) + ) self.defineoptions(kw, optiondefs) # Initialise superclass @@ -147,6 +149,7 @@ class SceneGraphExplorer(Pmw.MegaWidget, DirectObject): sceneGraphItem.reveal() sceneGraphItem.select() + class SceneGraphExplorerItem(TreeItem): """Example TreeItem subclass -- browse the file system.""" diff --git a/direct/src/tkwidgets/Slider.py b/direct/src/tkwidgets/Slider.py index 1f9d9e5da4..fc5b9e05a7 100644 --- a/direct/src/tkwidgets/Slider.py +++ b/direct/src/tkwidgets/Slider.py @@ -9,18 +9,20 @@ from .Valuator import Valuator, rgbPanel, VALUATOR_MINI, VALUATOR_FULL import Pmw import tkinter as tk + class Slider(Valuator): """ Valuator widget which includes an min/max slider and an entry for setting floating point values in a range """ + def __init__(self, parent = None, **kw): INITOPT = Pmw.INITOPT optiondefs = ( ('min', 0.0, self.setMin), ('max', 100.0, self.setMax), ('style', VALUATOR_MINI, INITOPT), - ) + ) self.defineoptions(kw, optiondefs) Valuator.__init__(self, parent) # Can not enter None for min or max, update propertyDict to reflect @@ -441,14 +443,19 @@ class SliderWidget(Pmw.MegaWidget): def _incrementValue(self, event): self.set(self.value + self.increment) + def _bigIncrementValue(self, event): self.set(self.value + self.increment * 10.0) + def _decrementValue(self, event): self.set(self.value - self.increment) + def _bigDecrementValue(self, event): self.set(self.value - self.increment * 10.0) + def _goToMin(self, event): self.set(self['min']) + def _goToMax(self, event): self.set(self['max']) diff --git a/direct/src/tkwidgets/Valuator.py b/direct/src/tkwidgets/Valuator.py index fbc1706b39..4d5f4b86d9 100644 --- a/direct/src/tkwidgets/Valuator.py +++ b/direct/src/tkwidgets/Valuator.py @@ -12,11 +12,13 @@ import Pmw VALUATOR_MINI = 'mini' VALUATOR_FULL = 'full' + class Valuator(Pmw.MegaWidget): sfBase = 3.0 sfDist = 7 deadband = 5 """ Base class for widgets used to interactively adjust numeric values """ + def __init__(self, parent = None, **kw): #define the megawidget options INITOPT = Pmw.INITOPT @@ -45,7 +47,7 @@ class Valuator(Pmw.MegaWidget): ('postCallback', None, None), # Extra data to be passed to callback function, needs to be a list ('callbackData', [], None), - ) + ) self.defineoptions(kw, optiondefs) # Initialize the superclass @@ -126,15 +128,15 @@ class Valuator(Pmw.MegaWidget): }, 'min': - { 'widget': self, - 'type': 'real', - 'fNone': 1, - 'help': 'Minimum allowable value. Enter None for no minimum.'}, + {'widget': self, + 'type': 'real', + 'fNone': 1, + 'help': 'Minimum allowable value. Enter None for no minimum.'}, 'max': - { 'widget': self, - 'type': 'real', - 'fNone': 1, - 'help': 'Maximum allowable value. Enter None for no maximum.'}, + {'widget': self, + 'type': 'real', + 'fNone': 1, + 'help': 'Maximum allowable value. Enter None for no maximum.'}, 'numDigits': {'widget': self, 'type': 'integer', @@ -149,10 +151,10 @@ class Valuator(Pmw.MegaWidget): }, 'resetValue': - { 'widget': self, - 'type': 'real', - 'help': 'Enter value to set widget to on reset.'} - } + {'widget': self, + 'type': 'real', + 'help': 'Enter value to set widget to on reset.'} + } # Property list defines the display order of the properties self.propertyList = [ 'state', 'text', 'min', 'max', 'numDigits', @@ -308,7 +310,6 @@ class Valuator(Pmw.MegaWidget): self._popupMenu.post(event.widget.winfo_pointerx(), event.widget.winfo_pointery()) - def _popupPropertiesDialog(self): WidgetPropertiesDialog.WidgetPropertiesDialog( self.propertyDict, @@ -339,6 +340,7 @@ DIAL = 'dial' ANGLEDIAL = 'angledial' SLIDER = 'slider' + class ValuatorGroup(Pmw.MegaWidget): def __init__(self, parent = None, **kw): @@ -369,7 +371,7 @@ class ValuatorGroup(Pmw.MegaWidget): ('postCallback', None, None), # Extra data to be passed to callback function, needs to be a list ('callbackData', [], None), - ) + ) self.defineoptions(kw, optiondefs) # Initialize the toplevel widget @@ -407,7 +409,7 @@ class ValuatorGroup(Pmw.MegaWidget): preCallback = self._preCallback, postCallback = self._postCallback, callbackData = [self], - ) + ) f.pack(side = self['side'], expand = 1, fill = tk.X) self._valuatorList.append(f) @@ -472,7 +474,6 @@ class ValuatorGroup(Pmw.MegaWidget): return str - class ValuatorGroupPanel(Pmw.MegaToplevel): def __init__(self, parent = None, **kw): @@ -506,7 +507,7 @@ class ValuatorGroupPanel(Pmw.MegaToplevel): ('callbackData', [], self._setCallbackData), # Destroy or withdraw ('fDestroy', 0, INITOPT) - ) + ) self.defineoptions(kw, optiondefs) # Initialize the toplevel widget @@ -593,6 +594,7 @@ class ValuatorGroupPanel(Pmw.MegaToplevel): def reset(self): self.set(self['value']) + Pmw.forwardmethods(ValuatorGroupPanel, ValuatorGroup, 'valuatorGroup') @@ -665,7 +667,6 @@ def rgbPanel(nodePath, callback = None, style = 'mini'): 'Valuator Group', 'command', label='Clear Transparency', command=lambda: nodePath.clearTransparency()) - # System color picker menubar.addmenuitem( 'Valuator Group', 'command', @@ -702,6 +703,7 @@ def lightRGBPanel(light, style = 'mini'): initialcolor = tuple(vgp.get()[:3]))[0] if color: vgp.set((color[0], color[1], color[2], vgp.getAt(3))) + def printToLog(): n = light.getName() c=light.getColor() diff --git a/direct/src/tkwidgets/VectorWidgets.py b/direct/src/tkwidgets/VectorWidgets.py index fe0efd1e36..6797782f71 100644 --- a/direct/src/tkwidgets/VectorWidgets.py +++ b/direct/src/tkwidgets/VectorWidgets.py @@ -35,7 +35,7 @@ class VectorEntry(Pmw.MegaWidget): ('numDigits', 2, self._setSigDigits), ('type', 'floater', None), ('state', 'normal', self._setState), - ) + ) self.defineoptions(kw, optiondefs) # Initialize superclass @@ -105,7 +105,6 @@ class VectorEntry(Pmw.MegaWidget): self._floaters.userdeletefunc(self._floaters.withdraw) self._floaters.withdraw() - # Make sure entries are updated self.set(self['value']) @@ -252,13 +251,14 @@ class VectorEntry(Pmw.MegaWidget): self.component('fGroup').configure( valuator_entry_background = self.entryBackground) + class Vector2Entry(VectorEntry): def __init__(self, parent = None, **kw): # Initialize options for the class optiondefs = ( ('dim', 2, Pmw.INITOPT), ('fGroup_labels', ('X','Y','Z'), None), - ) + ) self.defineoptions(kw, optiondefs) # Initialize the superclass, make sure dim makes it to superclass VectorEntry.__init__(self, parent, dim = self['dim']) @@ -266,13 +266,14 @@ class Vector2Entry(VectorEntry): # where myClass is the argument passed into inialiseoptions self.initialiseoptions(Vector2Entry) + class Vector3Entry(VectorEntry): def __init__(self, parent = None, **kw): # Initialize options for the class optiondefs = ( ('dim', 3, Pmw.INITOPT), ('fGroup_labels', ('X','Y','Z'), None), - ) + ) self.defineoptions(kw, optiondefs) # Initialize the superclass, make sure dim makes it to superclass VectorEntry.__init__(self, parent, dim = self['dim']) @@ -280,13 +281,14 @@ class Vector3Entry(VectorEntry): # where myClass is the argument passed into inialiseoptions self.initialiseoptions(Vector3Entry) + class Vector4Entry(VectorEntry): def __init__(self, parent = None, **kw): # Initialize options for the class optiondefs = ( ('dim', 4, Pmw.INITOPT), ('fGroup_labels', ('X','Y','Z','W'), None), - ) + ) self.defineoptions(kw, optiondefs) # Initialize the superclass, make sure dim makes it to superclass VectorEntry.__init__(self, parent, dim = self['dim']) @@ -294,6 +296,7 @@ class Vector4Entry(VectorEntry): # where myClass is the argument passed into inialiseoptions self.initialiseoptions(Vector4Entry) + class ColorEntry(VectorEntry): def __init__(self, parent = None, **kw): # Initialize options for the class (overriding some superclass options) @@ -305,7 +308,7 @@ class ColorEntry(VectorEntry): ('max', 255.0, None), ('nuDigits', 0, None), ('valuator_resolution', 1.0, None), - ) + ) self.defineoptions(kw, optiondefs) # Initialize the superclass, make sure dim makes it to superclass @@ -327,6 +330,7 @@ class ColorEntry(VectorEntry): if color: self.set((color[0], color[1], color[2], self.getAt(3))) + if __name__ == '__main__': root = tk.Toplevel() root.title('Vector Widget demo') diff --git a/direct/src/tkwidgets/WidgetPropertiesDialog.py b/direct/src/tkwidgets/WidgetPropertiesDialog.py index 61c65b30fe..92d48b4d9f 100644 --- a/direct/src/tkwidgets/WidgetPropertiesDialog.py +++ b/direct/src/tkwidgets/WidgetPropertiesDialog.py @@ -8,6 +8,7 @@ import tkinter as tk class WidgetPropertiesDialog(tk.Toplevel): """Class to open dialogs to adjust widget properties.""" + def __init__(self, propertyDict, propertyList = None, parent = None, title = 'Widget Properties'): """Initialize a dialog. @@ -44,8 +45,8 @@ class WidgetPropertiesDialog(tk.Toplevel): # Initialize window state self.grab_set() self.protocol("WM_DELETE_WINDOW", self.cancel) - self.geometry("+%d+%d" % (parent.winfo_rootx()+50, - parent.winfo_rooty()+50)) + self.geometry("+%d+%d" % (parent.winfo_rootx() + 50, + parent.winfo_rooty() + 50)) self.initial_focus.focus_set() self.wait_window(self) @@ -83,18 +84,18 @@ class WidgetPropertiesDialog(tk.Toplevel): helpString = propertySet.get('help', None) # Create label label = tk.Label(master, text=property, justify=tk.LEFT) - label.grid(row=count, column = 0, padx=5, sticky=tk.W) + label.grid(row=count, column=0, padx=5, sticky=tk.W) # Create entry - entry = Pmw.EntryField(master, entry_justify = 'right') - entry.grid(row=count, column = 1, padx=5, sticky=tk.W+tk.E) + entry = Pmw.EntryField(master, entry_justify=tk.RIGHT) + entry.grid(row=count, column=1, padx=5, sticky=tk.W + tk.E) if initialvalue is None: entry.insert(0, 'None') else: entry.insert(0, initialvalue) # Create balloon for help - balloon = Pmw.Balloon(state = 'balloon') + balloon = Pmw.Balloon(state='balloon') self.balloonList.append(balloon) # extra info if None is allowed value if helpString is None: @@ -106,23 +107,23 @@ class WidgetPropertiesDialog(tk.Toplevel): if entryType == 'real': # Only allow real numbers if fAllowNone: - entry['validate'] = { 'validator': self.realOrNone } + entry['validate'] = {'validator': self.realOrNone} else: - entry['validate'] = { 'validator': 'real' } + entry['validate'] = {'validator': 'real'} if helpString is None: helpString = 'Enter a floating point number' + extra + '.' elif entryType == 'integer': # Only allow integer values if fAllowNone: - entry['validate'] = { 'validator': self.intOrNone } + entry['validate'] = {'validator': self.intOrNone} else: - entry['validate'] = { 'validator': 'integer' } + entry['validate'] = {'validator': 'integer'} if helpString is None: - helpString = 'Enter an integer' + extra + '.' + helpString = f'Enter an integer{extra}.' else: # Anything goes with a string widget if helpString is None: - helpString = 'Enter a string' + extra + '.' + helpString = f'Enter a string{extra}.' # Bind balloon with help string to entry balloon.bind(entry, helpString) # Create callback to execute whenever a value is changed @@ -133,6 +134,7 @@ class WidgetPropertiesDialog(tk.Toplevel): # Keep track of the entrys entryList.append(entry) count += 1 + # Set initial focus if len(entryList) > 0: entry = entryList[0] diff --git a/direct/src/wxwidgets/WxPandaShell.py b/direct/src/wxwidgets/WxPandaShell.py index 73fbbf005d..ff8ec51981 100755 --- a/direct/src/wxwidgets/WxPandaShell.py +++ b/direct/src/wxwidgets/WxPandaShell.py @@ -26,12 +26,12 @@ class WxPandaShell(WxAppShell): '\nAll Rights Reserved.') MENU_TEXTS = { - ID_FOUR_VIEW : ("Four Views", None), - ID_TOP_VIEW : ("Top View", None), - ID_FRONT_VIEW : ("Front View", None), - ID_LEFT_VIEW : ("Left View", None), - ID_PERSP_VIEW : ("Persp View", None), - } + ID_FOUR_VIEW: ("Four Views", None), + ID_TOP_VIEW: ("Top View", None), + ID_FRONT_VIEW: ("Front View", None), + ID_LEFT_VIEW: ("Left View", None), + ID_PERSP_VIEW: ("Persp View", None), + } def __init__(self, fStartDirect = False): base = getattr(ShowBaseGlobal, 'base', None) diff --git a/direct/src/wxwidgets/WxPandaWindow.py b/direct/src/wxwidgets/WxPandaWindow.py index 4bf1176b26..4c1025f1a7 100644 --- a/direct/src/wxwidgets/WxPandaWindow.py +++ b/direct/src/wxwidgets/WxPandaWindow.py @@ -24,6 +24,7 @@ from panda3d.core import ( __all__ = ['WxPandaWindow'] + class EmbeddedPandaWindow(wx.Window): """ This class implements a Panda3D window that is directly embedded within the frame. It is fully supported on Windows, @@ -76,6 +77,7 @@ class EmbeddedPandaWindow(wx.Window): self.win.requestProperties(wp) event.Skip() + if not hasattr(wxgl, 'GLCanvas'): OpenGLPandaWindow = None else: @@ -87,42 +89,42 @@ else: removeCallbackWindow = ConfigVariableBool('remove-callback-window', True) Keymap = { - wx.WXK_BACK : KeyboardButton.backspace(), - wx.WXK_TAB : KeyboardButton.tab(), - wx.WXK_RETURN : KeyboardButton.enter(), - wx.WXK_ESCAPE : KeyboardButton.escape(), - wx.WXK_DELETE : KeyboardButton._del(), # del is a Python keyword - wx.WXK_SHIFT : KeyboardButton.shift(), - wx.WXK_ALT : KeyboardButton.alt(), - wx.WXK_CONTROL : KeyboardButton.control(), - wx.WXK_MENU : KeyboardButton.meta(), - wx.WXK_PAUSE : KeyboardButton.pause(), - wx.WXK_END : KeyboardButton.end(), - wx.WXK_HOME : KeyboardButton.home(), - wx.WXK_LEFT : KeyboardButton.left(), - wx.WXK_UP : KeyboardButton.up(), - wx.WXK_RIGHT : KeyboardButton.right(), - wx.WXK_DOWN : KeyboardButton.down(), - wx.WXK_PRINT : KeyboardButton.printScreen(), - wx.WXK_INSERT : KeyboardButton.insert(), - wx.WXK_F1 : KeyboardButton.f1(), - wx.WXK_F2 : KeyboardButton.f2(), - wx.WXK_F3 : KeyboardButton.f3(), - wx.WXK_F4 : KeyboardButton.f4(), - wx.WXK_F5 : KeyboardButton.f5(), - wx.WXK_F6 : KeyboardButton.f6(), - wx.WXK_F7 : KeyboardButton.f7(), - wx.WXK_F8 : KeyboardButton.f8(), - wx.WXK_F9 : KeyboardButton.f9(), - wx.WXK_F10 : KeyboardButton.f10(), - wx.WXK_F11 : KeyboardButton.f11(), - wx.WXK_F12 : KeyboardButton.f12(), - wx.WXK_NUMLOCK : KeyboardButton.numLock(), - wx.WXK_SCROLL : KeyboardButton.scrollLock(), - wx.WXK_PAGEUP : KeyboardButton.pageUp(), - wx.WXK_PAGEDOWN : KeyboardButton.pageDown(), - wx.WXK_COMMAND : KeyboardButton.meta(), - } + wx.WXK_BACK: KeyboardButton.backspace(), + wx.WXK_TAB: KeyboardButton.tab(), + wx.WXK_RETURN: KeyboardButton.enter(), + wx.WXK_ESCAPE: KeyboardButton.escape(), + wx.WXK_DELETE: KeyboardButton._del(), # del is a Python keyword + wx.WXK_SHIFT: KeyboardButton.shift(), + wx.WXK_ALT: KeyboardButton.alt(), + wx.WXK_CONTROL: KeyboardButton.control(), + wx.WXK_MENU: KeyboardButton.meta(), + wx.WXK_PAUSE: KeyboardButton.pause(), + wx.WXK_END: KeyboardButton.end(), + wx.WXK_HOME: KeyboardButton.home(), + wx.WXK_LEFT: KeyboardButton.left(), + wx.WXK_UP: KeyboardButton.up(), + wx.WXK_RIGHT: KeyboardButton.right(), + wx.WXK_DOWN: KeyboardButton.down(), + wx.WXK_PRINT: KeyboardButton.printScreen(), + wx.WXK_INSERT: KeyboardButton.insert(), + wx.WXK_F1: KeyboardButton.f1(), + wx.WXK_F2: KeyboardButton.f2(), + wx.WXK_F3: KeyboardButton.f3(), + wx.WXK_F4: KeyboardButton.f4(), + wx.WXK_F5: KeyboardButton.f5(), + wx.WXK_F6: KeyboardButton.f6(), + wx.WXK_F7: KeyboardButton.f7(), + wx.WXK_F8: KeyboardButton.f8(), + wx.WXK_F9: KeyboardButton.f9(), + wx.WXK_F10: KeyboardButton.f10(), + wx.WXK_F11: KeyboardButton.f11(), + wx.WXK_F12: KeyboardButton.f12(), + wx.WXK_NUMLOCK: KeyboardButton.numLock(), + wx.WXK_SCROLL: KeyboardButton.scrollLock(), + wx.WXK_PAGEUP: KeyboardButton.pageUp(), + wx.WXK_PAGEDOWN: KeyboardButton.pageDown(), + wx.WXK_COMMAND: KeyboardButton.meta(), + } def __init__(self, *args, **kw): gsg = None @@ -139,7 +141,7 @@ else: attribList = [ wxgl.WX_GL_RGBA, True, wxgl.WX_GL_LEVEL, 0, - ] + ] if not fbprops.isSingleBuffered(): attribList.append(wxgl.WX_GL_DOUBLEBUFFER) attribList.append(True) @@ -163,10 +165,10 @@ else: gsg = None callbackWindowDict = { - 'Events' : self.__eventsCallback, - 'Properties' : self.__propertiesCallback, - 'Render' : self.__renderCallback, - } + 'Events': self.__eventsCallback, + 'Properties': self.__propertiesCallback, + 'Render': self.__renderCallback, + } # Make sure we have an OpenGL GraphicsPipe. if not base.pipe: diff --git a/direct/src/wxwidgets/WxSlider.py b/direct/src/wxwidgets/WxSlider.py index 48ed06b041..5f504c8896 100755 --- a/direct/src/wxwidgets/WxSlider.py +++ b/direct/src/wxwidgets/WxSlider.py @@ -9,9 +9,10 @@ import wx class WxSlider(wx.Slider): - def __init__(self, parent, id, value, minValue, maxValue,\ - pos=wx.DefaultPosition, size=wx.DefaultSize,\ - style=wx.SL_HORIZONTAL, validator=wx.DefaultValidator, name="slider", textSize=(40,20)): + def __init__(self, parent, id, value, minValue, maxValue, + pos=wx.DefaultPosition, size=wx.DefaultSize, + style=wx.SL_HORIZONTAL, validator=wx.DefaultValidator, + name="slider", textSize=(40, 20)): self.maxValue = maxValue self.minValue = minValue @@ -25,13 +26,13 @@ class WxSlider(wx.Slider): if style & wx.SL_HORIZONTAL: newStyle = wx.SL_HORIZONTAL if style & wx.SL_LABELS: - wx.StaticText(parent, -1, "%.2f"%minValue, (pos[0], pos[1])) - strMaxValue = "%.2f"%maxValue - wx.StaticText(parent, -1, strMaxValue, (pos[0] + size[0] - len(strMaxValue) * 8 , pos[1])) - strValue = "%.2f"%value - self.textValue = wx.TextCtrl(parent, -1, strValue,\ - (pos[0] + size[0] /2 - textSize[0]/2, pos[1]), textSize,\ - wx.TE_CENTER | wx.TE_PROCESS_ENTER) + wx.StaticText(parent, -1, "%.2f" % minValue, (pos[0], pos[1])) + strMaxValue = "%.2f" % maxValue + wx.StaticText(parent, -1, strMaxValue, (pos[0] + size[0] - len(strMaxValue) * 8, pos[1])) + strValue = "%.2f" % value + self.textValue = wx.TextCtrl(parent, -1, strValue, + (pos[0] + size[0] / 2 - textSize[0] / 2, pos[1]), + textSize, wx.TE_CENTER | wx.TE_PROCESS_ENTER) self.textValue.Disable() newPos = (pos[0], pos[1] + 20) @@ -52,7 +53,7 @@ class WxSlider(wx.Slider): def SetValue(self, value): # overriding wx.Slider.SetValue() - self.textValue.SetValue("%.2f"%value) + self.textValue.SetValue("%.2f" % value) intVal = 100.0 / (self.maxValue - self.minValue) * (value - self.minValue) wx.Slider.SetValue(self, intVal) @@ -60,7 +61,7 @@ class WxSlider(wx.Slider): # update textValue from slider self.textValue.Clear() floatVal = wx.Slider.GetValue(self) * (self.maxValue - self.minValue) / 100.0 + self.minValue - self.textValue.WriteText("%.2f"%floatVal) + self.textValue.WriteText("%.2f" % floatVal) if self.updateCB: # callback function sould receive event as the argument self.updateCB(event) event.Skip()