Browse Source

The direct tree is now valid Python 2 *and* 3

rdb 9 years ago
parent
commit
23bf9ea5c7
100 changed files with 703 additions and 711 deletions
  1. 89 107
      direct/src/actor/Actor.py
  2. 1 1
      direct/src/actor/DistributedActor.py
  3. 8 10
      direct/src/cluster/ClusterClient.py
  4. 1 1
      direct/src/cluster/ClusterConfig.py
  5. 2 2
      direct/src/cluster/ClusterServer.py
  6. 3 3
      direct/src/controls/BattleWalker.py
  7. 1 1
      direct/src/controls/GhostWalker.py
  8. 1 1
      direct/src/controls/ObserverWalker.py
  9. 2 2
      direct/src/controls/PhysicsWalker.py
  10. 1 1
      direct/src/controls/TwoDWalker.py
  11. 1 1
      direct/src/directbase/ThreeUpStart.py
  12. 1 1
      direct/src/directdevices/DirectFastrak.py
  13. 1 1
      direct/src/directdevices/DirectJoybox.py
  14. 1 1
      direct/src/directdevices/DirectRadamec.py
  15. 4 4
      direct/src/directnotify/DirectNotify.py
  16. 1 1
      direct/src/directnotify/DirectNotifyGlobal.py
  17. 1 1
      direct/src/directnotify/LoggerGlobal.py
  18. 2 2
      direct/src/directnotify/Notifier.py
  19. 4 3
      direct/src/directnotify/RotatingLog.py
  20. 5 5
      direct/src/directscripts/eggcacher.py
  21. 41 39
      direct/src/directscripts/extract_docs.py
  22. 26 26
      direct/src/directscripts/gendocs.py
  23. 28 28
      direct/src/directscripts/packpanda.py
  24. 6 6
      direct/src/directtools/DirectCameraControl.py
  25. 9 9
      direct/src/directtools/DirectGeometry.py
  26. 2 2
      direct/src/directtools/DirectGlobals.py
  27. 2 2
      direct/src/directtools/DirectGrid.py
  28. 1 1
      direct/src/directtools/DirectLights.py
  29. 6 7
      direct/src/directtools/DirectManipulation.py
  30. 6 6
      direct/src/directtools/DirectSelection.py
  31. 17 16
      direct/src/directtools/DirectSession.py
  32. 1 1
      direct/src/directtools/DirectUtil.py
  33. 2 2
      direct/src/directutil/DeltaProfiler.py
  34. 1 1
      direct/src/directutil/DistributedLargeBlobSender.py
  35. 1 1
      direct/src/directutil/DistributedLargeBlobSenderAI.py
  36. 1 1
      direct/src/directutil/MemoryLeakHelpers.py
  37. 6 6
      direct/src/directutil/Mopath.py
  38. 3 3
      direct/src/directutil/Verify.py
  39. 4 4
      direct/src/distributed/AsyncRequest.py
  40. 1 1
      direct/src/distributed/CRCache.py
  41. 2 2
      direct/src/distributed/CRDataCache.py
  42. 6 6
      direct/src/distributed/ClientRepository.py
  43. 13 15
      direct/src/distributed/ClientRepositoryBase.py
  44. 3 6
      direct/src/distributed/ConnectionRepository.py
  45. 6 6
      direct/src/distributed/DistributedCamera.py
  46. 1 1
      direct/src/distributed/DistributedCartesianGrid.py
  47. 2 2
      direct/src/distributed/DistributedCartesianGridAI.py
  48. 5 6
      direct/src/distributed/DistributedNode.py
  49. 4 4
      direct/src/distributed/DistributedNodeAI.py
  50. 2 2
      direct/src/distributed/DistributedNodeUD.py
  51. 18 15
      direct/src/distributed/DistributedObject.py
  52. 18 16
      direct/src/distributed/DistributedObjectAI.py
  53. 6 7
      direct/src/distributed/DistributedObjectBase.py
  54. 1 1
      direct/src/distributed/DistributedObjectGlobalAI.py
  55. 1 1
      direct/src/distributed/DistributedObjectGlobalUD.py
  56. 12 10
      direct/src/distributed/DistributedObjectOV.py
  57. 14 12
      direct/src/distributed/DistributedObjectUD.py
  58. 3 3
      direct/src/distributed/DistributedSmoothNode.py
  59. 2 2
      direct/src/distributed/DistributedSmoothNodeAI.py
  60. 1 1
      direct/src/distributed/DistributedSmoothNodeBase.py
  61. 14 14
      direct/src/distributed/DoCollectionManager.py
  62. 26 26
      direct/src/distributed/DoInterestManager.py
  63. 1 1
      direct/src/distributed/GridChild.py
  64. 6 2
      direct/src/distributed/NetMessenger.py
  65. 2 2
      direct/src/distributed/OldClientRepository.py
  66. 2 2
      direct/src/distributed/ParentMgr.py
  67. 6 8
      direct/src/distributed/ServerRepository.py
  68. 1 1
      direct/src/distributed/TimeManagerAI.py
  69. 4 1
      direct/src/doc/howto.adjust
  70. 19 16
      direct/src/extensions_native/CInterval_extensions.py
  71. 2 2
      direct/src/extensions_native/NodePath_extensions.py
  72. 1 2
      direct/src/extensions_native/extension_native_helpers.py
  73. 1 1
      direct/src/filter/CommonFilters.py
  74. 7 10
      direct/src/fsm/ClassicFSM.py
  75. 5 5
      direct/src/fsm/FSM.py
  76. 3 3
      direct/src/fsm/FourState.py
  77. 3 3
      direct/src/fsm/FourStateAI.py
  78. 20 21
      direct/src/fsm/SampleFSM.py
  79. 2 2
      direct/src/fsm/State.py
  80. 0 1
      direct/src/fsm/StateData.py
  81. 5 6
      direct/src/fsm/StatePush.py
  82. 3 3
      direct/src/gui/DirectButton.py
  83. 1 1
      direct/src/gui/DirectCheckBox.py
  84. 3 3
      direct/src/gui/DirectCheckButton.py
  85. 9 9
      direct/src/gui/DirectDialog.py
  86. 21 17
      direct/src/gui/DirectEntry.py
  87. 4 4
      direct/src/gui/DirectEntryScroll.py
  88. 17 11
      direct/src/gui/DirectFrame.py
  89. 19 19
      direct/src/gui/DirectGui.py
  90. 22 23
      direct/src/gui/DirectGuiBase.py
  91. 9 9
      direct/src/gui/DirectGuiTest.py
  92. 1 1
      direct/src/gui/DirectLabel.py
  93. 6 8
      direct/src/gui/DirectOptionMenu.py
  94. 4 4
      direct/src/gui/DirectRadioButton.py
  95. 4 4
      direct/src/gui/DirectScrollBar.py
  96. 4 4
      direct/src/gui/DirectScrolledFrame.py
  97. 7 8
      direct/src/gui/DirectScrolledList.py
  98. 4 4
      direct/src/gui/DirectSlider.py
  99. 3 3
      direct/src/gui/DirectWaitBar.py
  100. 18 18
      direct/src/gui/OnscreenGeom.py

+ 89 - 107
direct/src/actor/Actor.py

@@ -6,7 +6,7 @@ from panda3d.core import *
 from panda3d.core import Loader as PandaLoader
 from direct.showbase.DirectObject import DirectObject
 from direct.directnotify import DirectNotifyGlobal
-import types
+
 
 class Actor(DirectObject, NodePath):
     """
@@ -239,30 +239,30 @@ class Actor(DirectObject, NodePath):
             #   models{}{}, anims{}{} = multi-part actor w/ LOD
             #
             # make sure we have models
-            if (models):
+            if models:
                 # do we have a dictionary of models?
-                if (type(models)==type({})):
+                if type(models) == dict:
                     # if this is a dictionary of dictionaries
-                    if (type(models[models.keys()[0]]) == type({})):
+                    if type(models[next(iter(models))]) == dict:
                         # then it must be a multipart actor w/LOD
                         self.setLODNode(node = lodNode)
                         # preserve numerical order for lod's
                         # this will make it easier to set ranges
-                        sortedKeys = models.keys()
+                        sortedKeys = list(models.keys())
                         sortedKeys.sort()
                         for lodName in sortedKeys:
                             # make a node under the LOD switch
                             # for each lod (just because!)
                             self.addLOD(str(lodName))
                             # iterate over both dicts
-                            for modelName in models[lodName].keys():
+                            for modelName in models[lodName]:
                                 self.loadModel(models[lodName][modelName],
                                                modelName, lodName, copy = copy,
                                                okMissing = okMissing)
                     # then if there is a dictionary of dictionaries of anims
-                    elif (type(anims[anims.keys()[0]])==type({})):
+                    elif type(anims[next(iter(anims))]) == dict:
                         # then this is a multipart actor w/o LOD
-                        for partName in models.keys():
+                        for partName in models:
                             # pass in each part
                             self.loadModel(models[partName], partName,
                                            copy = copy, okMissing = okMissing)
@@ -270,7 +270,7 @@ class Actor(DirectObject, NodePath):
                         # it is a single part actor w/LOD
                         self.setLODNode(node = lodNode)
                         # preserve order of LOD's
-                        sortedKeys = models.keys()
+                        sortedKeys = list(models.keys())
                         sortedKeys.sort()
                         for lodName in sortedKeys:
                             self.addLOD(str(lodName))
@@ -283,28 +283,28 @@ class Actor(DirectObject, NodePath):
 
             # load anims
             # make sure the actor has animations
-            if (anims):
-                if (len(anims) >= 1):
+            if anims:
+                if len(anims) >= 1:
                     # if so, does it have a dictionary of dictionaries?
-                    if (type(anims[anims.keys()[0]])==type({})):
+                    if type(anims[next(iter(anims))]) == dict:
                         # are the models a dict of dicts too?
-                        if (type(models)==type({})):
-                            if (type(models[models.keys()[0]]) == type({})):
+                        if type(models) == dict:
+                            if type(models[next(iter(models))]) == dict:
                                 # then we have a multi-part w/ LOD
-                                sortedKeys = models.keys()
+                                sortedKeys = list(models.keys())
                                 sortedKeys.sort()
                                 for lodName in sortedKeys:
                                     # iterate over both dicts
-                                    for partName in anims.keys():
+                                    for partName in anims:
                                         self.loadAnims(
                                             anims[partName], partName, lodName)
                             else:
                                 # then it must be multi-part w/o LOD
-                                for partName in anims.keys():
+                                for partName in anims:
                                     self.loadAnims(anims[partName], partName)
-                    elif (type(models)==type({})):
+                    elif type(models) == dict:
                         # then we have single-part w/ LOD
-                        sortedKeys = models.keys()
+                        sortedKeys = list(models.keys())
                         sortedKeys.sort()
                         for lodName in sortedKeys:
                             self.loadAnims(anims, lodName=lodName)
@@ -431,11 +431,10 @@ class Actor(DirectObject, NodePath):
                 part.outputValue(lineStream)
                 value = lineStream.getLine()
 
-            print ' ' * indentLevel, part.getName(), value
+            print(' '.join((' ' * indentLevel, part.getName(), value)))
 
-        for i in range(part.getNumChildren()):
-            self.__doListJoints(indentLevel + 2, part.getChild(i),
-                                isIncluded, subset)
+        for child in part.getChildren():
+            self.__doListJoints(indentLevel + 2, child, isIncluded, subset)
 
 
     def getActorInfo(self):
@@ -449,14 +448,14 @@ class Actor(DirectObject, NodePath):
                 lodName = self.__sortedLODNames[0]
 
             partInfo = []
-            for partName in partDict.keys():
+            for partName in partDict:
                 subpartDef = self.__subpartDict.get(partName, Actor.SubpartDef(partName))
                 partBundleDict = self.__partBundleDict.get(lodName)
                 partDef = partBundleDict.get(subpartDef.truePartName)
                 partBundle = partDef.getBundle()
                 animDict = partDict[partName]
                 animInfo = []
-                for animName in animDict.keys():
+                for animName in animDict:
                     file = animDict[animName].filename
                     animControl = animDict[animName].animControl
                     animInfo.append([animName, file, animControl])
@@ -478,17 +477,17 @@ class Actor(DirectObject, NodePath):
         Pretty print actor's details
         """
         for lodName, lodInfo in self.getActorInfo():
-            print 'LOD:', lodName
+            print('LOD: %s' % lodName)
             for partName, bundle, animInfo in lodInfo:
-                print '  Part:', partName
-                print '  Bundle:', repr(bundle)
+                print('  Part: %s' % partName)
+                print('  Bundle: %r' % bundle)
                 for animName, file, animControl in animInfo:
-                    print '    Anim:', animName
-                    print '      File:', file
+                    print('    Anim: %s' % animName)
+                    print('      File: %s' % file)
                     if animControl == None:
-                        print ' (not loaded)'
+                        print(' (not loaded)')
                     else:
-                        print ('      NumFrames: %d PlayRate: %0.2f' %
+                        print('      NumFrames: %d PlayRate: %0.2f' %
                                (animControl.getNumFrames(),
                                 animControl.getPlayRate()))
 
@@ -568,7 +567,7 @@ class Actor(DirectObject, NodePath):
     def __updateSortedLODNames(self):
         # Cache the sorted LOD names so we don't have to grab them
         # and sort them every time somebody asks for the list
-        self.__sortedLODNames = self.__partBundleDict.keys()
+        self.__sortedLODNames = list(self.__partBundleDict.keys())
         # Reverse sort the doing a string->int
         def sortKey(x):
             if not str(x).isdigit():
@@ -604,8 +603,8 @@ class Actor(DirectObject, NodePath):
         """
         partNames = []
         if self.__partBundleDict:
-            partNames = self.__partBundleDict.values()[0].keys()
-        return partNames + self.__subpartDict.keys()
+            partNames = list(next(iter(self.__partBundleDict.values())).keys())
+        return partNames + list(self.__subpartDict.keys())
 
     def getGeomNode(self):
         """
@@ -646,33 +645,33 @@ class Actor(DirectObject, NodePath):
         """
         # make sure we don't call this twice in a row
         # and pollute the the switches dictionary
-##         sortedKeys = self.switches.keys()
+##         sortedKeys = list(self.switches.keys())
 ##         sortedKeys.sort()
         child = self.__LODNode.find(str(lodName))
         index = self.__LODNode.node().findChild(child.node())
         self.__LODNode.node().forceSwitch(index)
 
     def printLOD(self):
-##         sortedKeys = self.switches.keys()
+##         sortedKeys = list(self.switches.keys())
 ##         sortedKeys.sort()
         sortedKeys = self.__sortedLODNames
         for eachLod in sortedKeys:
-            print "python switches for %s: in: %d, out %d" % (eachLod,
+            print("python switches for %s: in: %d, out %d" % (eachLod,
                                               self.switches[eachLod][0],
-                                              self.switches[eachLod][1])
+                                              self.switches[eachLod][1]))
 
         switchNum = self.__LODNode.node().getNumSwitches()
         for eachSwitch in range(0, switchNum):
-            print "c++ switches for %d: in: %d, out: %d" % (eachSwitch,
+            print("c++ switches for %d: in: %d, out: %d" % (eachSwitch,
                    self.__LODNode.node().getIn(eachSwitch),
-                   self.__LODNode.node().getOut(eachSwitch))
+                   self.__LODNode.node().getOut(eachSwitch)))
 
 
     def resetLOD(self):
         """
         Restore all switch distance info (usually after a useLOD call)"""
         self.__LODNode.node().clearForceSwitch()
-##         sortedKeys = self.switches.keys()
+##         sortedKeys = list(self.switches.keys())
 ##         sortedKeys.sort()
 ##         for eachLod in sortedKeys:
 ##             index = sortedKeys.index(eachLod)
@@ -699,7 +698,7 @@ class Actor(DirectObject, NodePath):
         # save the switch distance info
         self.switches[lodName] = [inDist, outDist]
         # add the switch distance info
-##         sortedKeys = self.switches.keys()
+##         sortedKeys = list(self.switches.keys())
 ##         sortedKeys.sort()
         self.__LODNode.node().setSwitch(self.getLODIndex(lodName), inDist, outDist)
 
@@ -798,7 +797,7 @@ class Actor(DirectObject, NodePath):
             lodName = lodNames[lod]
             if partName == None:
                 partBundleDict = self.__partBundleDict[lodName]
-                partNames = partBundleDict.keys()
+                partNames = list(partBundleDict.keys())
             else:
                 partNames = [partName]
 
@@ -822,7 +821,7 @@ class Actor(DirectObject, NodePath):
         If no part specified, return anim durations of first part.
         NOTE: returns info only for an arbitrary LOD
         """
-        lodName = self.__animControlDict.keys()[0]
+        lodName = next(iter(self.__animControlDict))
         controls = self.getAnimControls(animName, partName)
         if len(controls) == 0:
             return None
@@ -834,7 +833,7 @@ class Actor(DirectObject, NodePath):
         Return frame rate of given anim name and given part, unmodified
         by any play rate in effect.
         """
-        lodName = self.__animControlDict.keys()[0]
+        lodName = next(iter(self.__animControlDict))
         controls = self.getAnimControls(animName, partName)
         if len(controls) == 0:
             return None
@@ -850,7 +849,7 @@ class Actor(DirectObject, NodePath):
         """
         if self.__animControlDict:
             # use the first lod
-            lodName = self.__animControlDict.keys()[0]
+            lodName = next(iter(self.__animControlDict))
             controls = self.getAnimControls(animName, partName)
             if controls:
                 return controls[0].getPlayRate()
@@ -877,7 +876,7 @@ class Actor(DirectObject, NodePath):
         If no part specified, return anim duration of first part.
         NOTE: returns info for arbitrary LOD
         """
-        lodName = self.__animControlDict.keys()[0]
+        lodName = next(iter(self.__animControlDict))
         controls = self.getAnimControls(animName, partName)
         if len(controls) == 0:
             return None
@@ -890,7 +889,7 @@ class Actor(DirectObject, NodePath):
         return ((toFrame+1)-fromFrame) / animControl.getFrameRate()
 
     def getNumFrames(self, animName=None, partName=None):
-        lodName = self.__animControlDict.keys()[0]
+        lodName = next(iter(self.__animControlDict))
         controls = self.getAnimControls(animName, partName)
         if len(controls) == 0:
             return None
@@ -908,12 +907,12 @@ class Actor(DirectObject, NodePath):
         specified return current anim of an arbitrary part in dictionary.
         NOTE: only returns info for an arbitrary LOD
         """
-        if len(self.__animControlDict.items()) == 0:
+        if len(self.__animControlDict) == 0:
             return
 
-        lodName, animControlDict = self.__animControlDict.items()[0]
+        lodName, animControlDict = next(iter(self.__animControlDict.items()))
         if partName == None:
-            partName, animDict = animControlDict.items()[0]
+            partName, animDict = next(iter(animControlDict.items()))
         else:
             animDict = animControlDict.get(partName)
             if animDict == None:
@@ -936,9 +935,9 @@ class Actor(DirectObject, NodePath):
         actor. If part not specified return current anim of first part
         in dictionary.  NOTE: only returns info for an arbitrary LOD
         """
-        lodName, animControlDict = self.__animControlDict.items()[0]
+        lodName, animControlDict = next(iter(self.__animControlDict.items()))
         if partName == None:
-            partName, animDict = animControlDict.items()[0]
+            partName, animDict = next(iter(animControlDict.items()))
         else:
             animDict = animControlDict.get(partName)
             if animDict == None:
@@ -1420,17 +1419,15 @@ class Actor(DirectObject, NodePath):
         if mode > 0:
             # Use the 'fixed' bin instead of reordering the scene
             # graph.
-            numFrontParts = frontParts.getNumPaths()
-            for partNum in range(0, numFrontParts):
-                frontParts[partNum].setBin('fixed', mode)
+            for part in frontParts:
+                part.setBin('fixed', mode)
             return
 
         if mode == -2:
             # Turn off depth test/write on the frontParts.
-            numFrontParts = frontParts.getNumPaths()
-            for partNum in range(0, numFrontParts):
-                frontParts[partNum].setDepthWrite(0)
-                frontParts[partNum].setDepthTest(0)
+            for part in frontParts:
+                part.setDepthWrite(0)
+                part.setDepthTest(0)
 
         # Find the back part.
         backPart = root.find("**/" + backPartName)
@@ -1457,12 +1454,8 @@ class Actor(DirectObject, NodePath):
                     char = partData.partBundleNP
                     char.node().update()
                     geomNodes = char.findAllMatches("**/+GeomNode")
-                    numGeomNodes = geomNodes.getNumPaths()
-                    for nodeNum in xrange(numGeomNodes):
-                        thisGeomNode = geomNodes.getPath(nodeNum)
-                        numGeoms = thisGeomNode.node().getNumGeoms()
-                        for geomNum in xrange(numGeoms):
-                            thisGeom = thisGeomNode.node().getGeom(geomNum)
+                    for thisGeomNode in geomNodes:
+                        for thisGeom in thisGeomNode.node().getGeoms():
                             thisGeom.markBoundsStale()
                         thisGeomNode.node().markInternalBoundsStale()
         else:
@@ -1473,12 +1466,8 @@ class Actor(DirectObject, NodePath):
                     char = partData.partBundleNP
                     char.node().update()
                     geomNodes = char.findAllMatches("**/+GeomNode")
-                    numGeomNodes = geomNodes.getNumPaths()
-                    for nodeNum in xrange(numGeomNodes):
-                        thisGeomNode = geomNodes.getPath(nodeNum)
-                        numGeoms = thisGeomNode.node().getNumGeoms()
-                        for geomNum in xrange(numGeoms):
-                            thisGeom = thisGeomNode.node().getGeom(geomNum)
+                    for thisGeomNode in geomNodes:
+                        for thisGeom in thisGeomNode.node().getGeoms():
                             thisGeom.markBoundsStale()
                         thisGeomNode.node().markInternalBoundsStale()
 
@@ -1494,19 +1483,14 @@ class Actor(DirectObject, NodePath):
 
         # update all characters first
         charNodes = part.findAllMatches("**/+Character")
-        numCharNodes = charNodes.getNumPaths()
-        for charNum in range(0, numCharNodes):
-            (charNodes.getPath(charNum)).node().update()
+        for charNode in charNodes:
+            charNode.node().update()
 
         # for each geomNode, iterate through all geoms and force update
         # of bounding spheres by marking current bounds as stale
         geomNodes = part.findAllMatches("**/+GeomNode")
-        numGeomNodes = geomNodes.getNumPaths()
-        for nodeNum in range(0, numGeomNodes):
-            thisGeomNode = geomNodes.getPath(nodeNum)
-            numGeoms = thisGeomNode.node().getNumGeoms()
-            for geomNum in range(0, numGeoms):
-                thisGeom = thisGeomNode.node().getGeom(geomNum)
+        for nodeNum, thisGeomNode in enumerate(geomNodes):
+            for geomNum, thisGeom in enumerate(thisGeomNode.node().getGeoms()):
                 thisGeom.markBoundsStale()
                 assert Actor.notify.debug("fixing bounds for node %s, geom %s" % \
                                           (nodeNum, geomNum))
@@ -1517,20 +1501,18 @@ class Actor(DirectObject, NodePath):
         Show the bounds of all actor geoms
         """
         geomNodes = self.__geomNode.findAllMatches("**/+GeomNode")
-        numGeomNodes = geomNodes.getNumPaths()
 
-        for nodeNum in range(0, numGeomNodes):
-            geomNodes.getPath(nodeNum).showBounds()
+        for node in geomNodes:
+            node.showBounds()
 
     def hideAllBounds(self):
         """
         Hide the bounds of all actor geoms
         """
         geomNodes = self.__geomNode.findAllMatches("**/+GeomNode")
-        numGeomNodes = geomNodes.getNumPaths()
 
-        for nodeNum in range(0, numGeomNodes):
-            geomNodes.getPath(nodeNum).hideBounds()
+        for node in geomNodes:
+            node.hideBounds()
 
 
     # actions
@@ -1698,7 +1680,7 @@ class Actor(DirectObject, NodePath):
         if self.mergeLODBundles:
             lodName = 'common'
         elif self.switches:
-            lodName = str(self.switches.keys()[0])
+            lodName = str(next(iter(self.switches)))
         else:
             lodName = 'lodRoot'
 
@@ -1723,7 +1705,7 @@ class Actor(DirectObject, NodePath):
             lodName = 'common'
         elif not lodName:
             if self.switches:
-                lodName = str(self.switches.keys()[0])
+                lodName = str(next(iter(self.switches)))
             else:
                 lodName = 'lodRoot'
 
@@ -1777,7 +1759,7 @@ class Actor(DirectObject, NodePath):
             # If we have the __subpartsComplete flag, and no partName
             # is specified, it really means to play the animation on
             # all subparts, not on the overall Actor.
-            partName = self.__subpartDict.keys()
+            partName = list(self.__subpartDict.keys())
 
         controls = []
         # build list of lodNames and corresponding animControlDicts
@@ -1805,7 +1787,7 @@ class Actor(DirectObject, NodePath):
 
             else:
                 # Get exactly the named part or parts.
-                if isinstance(partName, types.StringTypes):
+                if isinstance(partName, str):
                     partNameList = [partName]
                 else:
                     partNameList = partName
@@ -1835,7 +1817,7 @@ class Actor(DirectObject, NodePath):
                             controls.append(anim.animControl)
             else:
                 # get the named animation(s) only.
-                if isinstance(animName, types.StringTypes):
+                if isinstance(animName, str):
                     # A single animName
                     animNameList = [animName]
                 else:
@@ -2107,7 +2089,7 @@ class Actor(DirectObject, NodePath):
             if lodName:
                 partNames = self.__partBundleDict[lodName].keys()
             else:
-                partNames = self.__partBundleDict.values()[0].keys()
+                partNames = next(iter(self.__partBundleDict.values())).keys()
 
         for partName in partNames:
             subJoints = set()
@@ -2133,9 +2115,9 @@ class Actor(DirectObject, NodePath):
             lodNames = ['common']
         elif lodName == 'all':
             reload = False
-            lodNames = self.switches.keys()
+            lodNames = list(self.switches.keys())
             lodNames.sort()
-            for i in range(0,len(lodNames)):
+            for i in range(0, len(lodNames)):
                 lodNames[i] = str(lodNames[i])
         else:
             lodNames = [lodName]
@@ -2256,20 +2238,20 @@ class Actor(DirectObject, NodePath):
         assert Actor.notify.debug("in unloadAnims: %s, part: %s, lod: %s" %
                                   (anims, partName, lodName))
 
-        if lodName == None or self.mergeLODBundles:
+        if lodName is None or self.mergeLODBundles:
             lodNames = self.__animControlDict.keys()
         else:
             lodNames = [lodName]
 
-        if (partName == None):
+        if partName is None:
             if len(lodNames) > 0:
-                partNames = self.__animControlDict[lodNames[0]].keys()
+                partNames = self.__animControlDict[next(iter(lodNames))].keys()
             else:
                 partNames = []
         else:
             partNames = [partName]
 
-        if (anims==None):
+        if anims is None:
             for lodName in lodNames:
                 for partName in partNames:
                     for animDef in self.__animControlDict[lodName][partName].values():
@@ -2400,7 +2382,7 @@ class Actor(DirectObject, NodePath):
         Copy the part bundle dictionary from another actor as this
         instance's own. NOTE: this method does not actually copy geometry
         """
-        for lodName in other.__partBundleDict.keys():
+        for lodName in other.__partBundleDict:
             # find the lod Asad
             if lodName == 'lodRoot':
                 partLod = self
@@ -2445,11 +2427,11 @@ class Actor(DirectObject, NodePath):
 
         assert(other.mergeLODBundles == self.mergeLODBundles)
 
-        for lodName in other.__animControlDict.keys():
+        for lodName in other.__animControlDict:
             self.__animControlDict[lodName] = {}
-            for partName in other.__animControlDict[lodName].keys():
+            for partName in other.__animControlDict[lodName]:
                 self.__animControlDict[lodName][partName] = {}
-                for animName in other.__animControlDict[lodName][partName].keys():
+                for animName in other.__animControlDict[lodName][partName]:
                     anim = other.__animControlDict[lodName][partName][animName]
                     anim = anim.makeCopy()
                     self.__animControlDict[lodName][partName][animName] = anim
@@ -2512,13 +2494,13 @@ class Actor(DirectObject, NodePath):
 
     def printAnimBlends(self, animName=None, partName=None, lodName=None):
         for lodName, animList in self.getAnimBlends(animName, partName, lodName):
-            print 'LOD %s:' % (lodName)
+            print('LOD %s:' % (lodName))
             for animName, blendList in animList:
 
                 list = []
                 for partName, effect in blendList:
                     list.append('%s:%.3f' % (partName, effect))
-                print '  %s: %s' % (animName, ', '.join(list))
+                print('  %s: %s' % (animName, ', '.join(list)))
 
     def osdAnimBlends(self, animName=None, partName=None, lodName=None):
         if not onScreenDebug.enabled:
@@ -2565,5 +2547,5 @@ class Actor(DirectObject, NodePath):
     def renamePartBundles(self, partName, newBundleName):
         subpartDef = self.__subpartDict.get(partName, Actor.SubpartDef(partName))
         for partBundleDict in self.__partBundleDict.values():
-            partDef=partBundleDict.get(subpartDef.truePartName)
+            partDef = partBundleDict.get(subpartDef.truePartName)
             partDef.getBundle().setName(newBundleName)

+ 1 - 1
direct/src/actor/DistributedActor.py

@@ -4,7 +4,7 @@ __all__ = ['DistributedActor']
 
 from direct.distributed import DistributedNode
 
-import Actor
+from . import Actor
 
 class DistributedActor(DistributedNode.DistributedNode, Actor.Actor):
     def __init__(self, cr):

+ 8 - 10
direct/src/cluster/ClusterClient.py

@@ -1,8 +1,8 @@
 """ClusterClient: Master for mutli-piping or PC clusters.  """
 
 from panda3d.core import *
-from ClusterMsgs import *
-from ClusterConfig import *
+from .ClusterMsgs import *
+from .ClusterConfig import *
 from direct.directnotify import DirectNotifyGlobal
 from direct.showbase import DirectObject
 from direct.task import Task
@@ -44,10 +44,10 @@ class ClusterClient(DirectObject.DirectObject):
             self.daemon.tellServer(serverConfig.serverName,
                                    serverConfig.serverDaemonPort,
                                    serverCommand)
-        print 'Begin waitForServers'
+        print('Begin waitForServers')
         if not self.daemon.waitForServers(len(configList)):
-            print 'Cluster Client, no response from servers'
-        print 'End waitForServers'
+            print('Cluster Client, no response from servers')
+        print('End waitForServers')
         self.qcm=QueuedConnectionManager()
         self.serverList = []
         self.serverQueues = []
@@ -262,9 +262,8 @@ class ClusterClient(DirectObject.DirectObject):
 
 
     def getNodePathFindCmd(self, nodePath):
-        import string
         pathString = repr(nodePath)
-        index = string.find(pathString, '/')
+        index = pathString.find('/')
         if index != -1:
             rootName = pathString[:index]
             searchString = pathString[index+1:]
@@ -273,9 +272,8 @@ class ClusterClient(DirectObject.DirectObject):
             return rootName
 
     def getNodePathName(self, nodePath):
-        import string
         pathString = repr(nodePath)
-        index = string.find(pathString, '/')
+        index = pathString.find('/')
         if index != -1:
             name = pathString[index+1:]
             return name
@@ -409,7 +407,7 @@ class ClusterClientSync(ClusterClient):
         #I probably don't need this
         self.waitForSwap = 0
         self.ready = 0
-        print "creating synced client"
+        print("creating synced client")
         self.startSwapCoordinatorTask()
 
     def startSwapCoordinatorTask(self):

+ 1 - 1
direct/src/cluster/ClusterConfig.py

@@ -1,5 +1,5 @@
 
-from ClusterClient import *
+from .ClusterClient import *
 
 # A dictionary of information for various cluster configurations.
 # Dictionary is keyed on cluster-config string

+ 2 - 2
direct/src/cluster/ClusterServer.py

@@ -1,5 +1,5 @@
 from panda3d.core import *
-from ClusterMsgs import *
+from .ClusterMsgs import *
 from direct.distributed.MsgTypes import *
 from direct.directnotify import DirectNotifyGlobal
 from direct.showbase import DirectObject
@@ -246,7 +246,7 @@ class ClusterServer(DirectObject.DirectObject):
         if (type == CLUSTER_NONE):
             pass
         elif (type == CLUSTER_EXIT):
-            print 'GOT EXIT'
+            print('GOT EXIT')
             import sys
             sys.exit()
         elif (type == CLUSTER_CAM_OFFSET):

+ 3 - 3
direct/src/controls/BattleWalker.py

@@ -2,7 +2,7 @@
 from direct.showbase.InputStateGlobal import inputState
 from direct.task.Task import Task
 from pandac.PandaModules import *
-import GravityWalker
+from . import GravityWalker
 
 BattleStrafe = 0
 
@@ -166,7 +166,7 @@ class BattleWalker(GravityWalker.GravityWalker):
             # Should fSlide be renamed slideButton?
             self.slideSpeed=.15*(turnLeft and -self.avatarControlForwardSpeed or
                                  turnRight and self.avatarControlForwardSpeed)
-            print 'slideSpeed: ', self.slideSpeed
+            print('slideSpeed: %s' % self.slideSpeed)
             self.rotationSpeed=0
             self.speed=0
 
@@ -233,7 +233,7 @@ class BattleWalker(GravityWalker.GravityWalker):
             if self.moving:
                 distance = dt * self.speed
                 slideDistance = dt * self.slideSpeed
-                print 'slideDistance: ', slideDistance
+                print('slideDistance: %s' % slideDistance)
                 rotation = dt * self.rotationSpeed
 
                 # Take a step in the direction of our previous heading.

+ 1 - 1
direct/src/controls/GhostWalker.py

@@ -15,7 +15,7 @@ animations based on walker events.
 """
 
 from direct.directnotify import DirectNotifyGlobal
-import NonPhysicsWalker
+from . import NonPhysicsWalker
 
 class GhostWalker(NonPhysicsWalker.NonPhysicsWalker):
 

+ 1 - 1
direct/src/controls/ObserverWalker.py

@@ -16,7 +16,7 @@ animations based on walker events.
 
 from panda3d.core import *
 from direct.directnotify import DirectNotifyGlobal
-import NonPhysicsWalker
+from . import NonPhysicsWalker
 
 class ObserverWalker(NonPhysicsWalker.NonPhysicsWalker):
     notify = DirectNotifyGlobal.directNotify.newCategory("ObserverWalker")

+ 2 - 2
direct/src/controls/PhysicsWalker.py

@@ -324,7 +324,7 @@ class PhysicsWalker(DirectObject.DirectObject):
             indicator.instanceTo(contactIndicatorNode)
             self.physContactIndicator=contactIndicatorNode
         else:
-            print "failed load of physics indicator"
+            print("failed load of physics indicator")
 
     def avatarPhysicsIndicator(self, task):
         #assert self.debugPrint("avatarPhysicsIndicator()")
@@ -710,7 +710,7 @@ class PhysicsWalker(DirectObject.DirectObject):
     def setPriorParentVector(self):
         assert self.debugPrint("doDeltaPos()")
 
-        print "self.__oldDt", self.__oldDt, "self.__oldPosDelta", self.__oldPosDelta
+        print("self.__oldDt %s self.__oldPosDelta %s" % (self.__oldDt, self.__oldPosDelta))
         if __debug__:
             onScreenDebug.add("__oldDt", "% 10.4f"%self.__oldDt)
             onScreenDebug.add("self.__oldPosDelta",

+ 1 - 1
direct/src/controls/TwoDWalker.py

@@ -2,7 +2,7 @@
 TwoDWalker.py is for controling the avatars in a 2D Scroller game environment.
 """
 
-from GravityWalker import *
+from .GravityWalker import *
 from panda3d.core import ConfigVariableBool
 
 

+ 1 - 1
direct/src/directbase/ThreeUpStart.py

@@ -1,5 +1,5 @@
 
-print 'ThreeUpStart: Starting up environment.'
+print('ThreeUpStart: Starting up environment.')
 
 from pandac.PandaModules import *
 

+ 1 - 1
direct/src/directdevices/DirectFastrak.py

@@ -1,7 +1,7 @@
 """ Class used to create and control radamec device """
 from math import *
 from direct.showbase.DirectObject import DirectObject
-from DirectDeviceManager import *
+from .DirectDeviceManager import *
 
 from direct.directnotify import DirectNotifyGlobal
 

+ 1 - 1
direct/src/directdevices/DirectJoybox.py

@@ -1,6 +1,6 @@
 """ Class used to create and control joybox device """
 from direct.showbase.DirectObject import DirectObject
-from DirectDeviceManager import *
+from .DirectDeviceManager import *
 from direct.directtools.DirectUtil import *
 from direct.gui import OnscreenText
 from direct.task import Task

+ 1 - 1
direct/src/directdevices/DirectRadamec.py

@@ -1,7 +1,7 @@
 """ Class used to create and control radamec device """
 from math import *
 from direct.showbase.DirectObject import DirectObject
-from DirectDeviceManager import *
+from .DirectDeviceManager import *
 
 from direct.directnotify import DirectNotifyGlobal
 

+ 4 - 4
direct/src/directnotify/DirectNotify.py

@@ -2,8 +2,8 @@
 DirectNotify module: this module contains the DirectNotify class
 """
 
-import Notifier
-import Logger
+from . import Notifier
+from . import Logger
 
 class DirectNotify:
     """
@@ -35,7 +35,7 @@ class DirectNotify:
         """
         Return list of category dictionary keys
         """
-        return (self.__categories.keys())
+        return list(self.__categories.keys())
 
     def getCategory(self, categoryName):
         """getCategory(self, string)
@@ -97,7 +97,7 @@ class DirectNotify:
             category.setInfo(1)
             category.setDebug(1)
         else:
-            print ("DirectNotify: unknown notify level: " + str(level)
+            print("DirectNotify: unknown notify level: " + str(level)
                    + " for category: " + str(categoryName))
 
 

+ 1 - 1
direct/src/directnotify/DirectNotifyGlobal.py

@@ -2,7 +2,7 @@
 
 __all__ = ['directNotify', 'giveNotify']
 
-import DirectNotify
+from . import DirectNotify
 
 directNotify = DirectNotify.DirectNotify()
 giveNotify = directNotify.giveNotify

+ 1 - 1
direct/src/directnotify/LoggerGlobal.py

@@ -1,5 +1,5 @@
 """instantiate global Logger object"""
 
-import Logger
+from . import Logger
 
 defaultLogger = Logger.Logger()

+ 2 - 2
direct/src/directnotify/Notifier.py

@@ -2,7 +2,7 @@
 Notifier module: contains methods for handling information output
 for the programmer/user
 """
-from LoggerGlobal import defaultLogger
+from .LoggerGlobal import defaultLogger
 from direct.showbase import PythonUtil
 from panda3d.core import ConfigVariableBool, NotifyCategory, StreamWriter, Notify
 import time
@@ -237,7 +237,7 @@ class Notifier:
         if self.streamWriter:
             self.streamWriter.write(string + '\n')
         else:
-            print >> sys.stderr, string
+            sys.stderr.write(string + '\n')
 
     def debugStateCall(self, obj=None, fsmMemberName='fsm',
             secondaryFsm='secondaryFSM'):

+ 4 - 3
direct/src/directnotify/RotatingLog.py

@@ -91,7 +91,7 @@ class RotatingLog:
                 self.timeLimit=time.time()+self.timeInterval
         else:
             # We'll keep writing to the old file, if available.
-            print "RotatingLog error: Unable to open new log file \"%s\"."%(path,)
+            print("RotatingLog error: Unable to open new log file \"%s\"." % (path,))
 
     def write(self, data):
         """
@@ -115,8 +115,9 @@ class RotatingLog:
     def isatty(self):
         return self.file.isatty()
 
-    def next(self):
-        return self.file.next()
+    def __next__(self):
+        return next(self.file)
+    next = __next__
 
     def read(self, size):
         return self.file.read(size)

+ 5 - 5
direct/src/directscripts/eggcacher.py

@@ -19,8 +19,8 @@ class EggCacher:
         self.pandaloader = Loader()
         self.loaderopts = LoaderOptions(LoaderOptions.LF_no_ram_cache)
         if (self.bamcache.getActive() == 0):
-            print "The model cache is not currently active."
-            print "You must set a model-cache-dir in your config file."
+            print("The model cache is not currently active.")
+            print("You must set a model-cache-dir in your config file.")
             sys.exit(1)
         self.parseArgs(args)
         files = self.scanPaths(self.paths)
@@ -39,13 +39,13 @@ class EggCacher:
             else:
                 break
         if (len(args) < 1):
-            print "Usage: eggcacher options file-or-directory"
+            print("Usage: eggcacher options file-or-directory")
             sys.exit(1)
         self.paths = args
 
     def scanPath(self, eggs, path):
         if (os.path.exists(path)==0):
-            print "No such file or directory: "+path
+            print("No such file or directory: " + path)
             return
         if (os.path.isdir(path)):
             for f in os.listdir(path):
@@ -78,7 +78,7 @@ class EggCacher:
             percent = (progress * 100) / total
             report = path
             if (self.concise): report = os.path.basename(report)
-            print "Preprocessing Models %2d%% %s" % (percent, report)
+            print("Preprocessing Models %2d%% %s" % (percent, report))
             sys.stdout.flush()
             if (cached) and (cached.hasData()==0):
                 self.pandaloader.loadSync(fn, self.loaderopts)

+ 41 - 39
direct/src/directscripts/extract_docs.py

@@ -5,6 +5,8 @@ You need to run this before invoking Doxyfile.python.
 It requires a valid makepanda installation with interrogatedb .in
 files in the lib/pandac/input directory. """
 
+from __future__ import print_function
+
 __all__ = []
 
 import os
@@ -156,61 +158,61 @@ def translated_type_name(type, scoped=True):
 
 def processElement(handle, element):
     if interrogate_element_has_comment(element):
-        print >>handle, comment(interrogate_element_comment(element))
+        print(comment(interrogate_element_comment(element)), file=handle)
 
-    print >>handle, translated_type_name(interrogate_element_type(element)),
-    print >>handle, interrogate_element_name(element) + ';'
+    print(translated_type_name(interrogate_element_type(element)), end=' ', file=handle)
+    print(interrogate_element_name(element) + ';', file=handle)
 
 def processFunction(handle, function, isConstructor = False):
-    for i_wrapper in xrange(interrogate_function_number_of_python_wrappers(function)):
+    for i_wrapper in range(interrogate_function_number_of_python_wrappers(function)):
         wrapper = interrogate_function_python_wrapper(function, i_wrapper)
         if interrogate_wrapper_has_comment(wrapper):
-            print >>handle, block_comment(interrogate_wrapper_comment(wrapper))
+            print(block_comment(interrogate_wrapper_comment(wrapper)), file=handle)
 
         if not isConstructor:
             if interrogate_function_is_method(function):
                 if not interrogate_wrapper_number_of_parameters(wrapper) > 0 or not interrogate_wrapper_parameter_is_this(wrapper, 0):
-                    print >>handle, "static",
+                    print("static", end=' ', file=handle)
 
             if interrogate_wrapper_has_return_value(wrapper):
-                print >>handle, translated_type_name(interrogate_wrapper_return_type(wrapper)),
+                print(translated_type_name(interrogate_wrapper_return_type(wrapper)), end=' ', file=handle)
             else:
                 pass#print >>handle, "void",
 
-            print >>handle, translateFunctionName(interrogate_function_name(function)) + "(",
+            print(translateFunctionName(interrogate_function_name(function)) + "(", end=' ', file=handle)
         else:
-            print >>handle, "__init__(",
+            print("__init__(", end=' ', file=handle)
 
         first = True
         for i_param in range(interrogate_wrapper_number_of_parameters(wrapper)):
             if not interrogate_wrapper_parameter_is_this(wrapper, i_param):
                 if not first:
-                    print >>handle, ",",
-                print >>handle, translated_type_name(interrogate_wrapper_parameter_type(wrapper, i_param)),
+                    print(",", end=' ', file=handle)
+                print(translated_type_name(interrogate_wrapper_parameter_type(wrapper, i_param)), end=' ', file=handle)
                 if interrogate_wrapper_parameter_has_name(wrapper, i_param):
-                    print >>handle, interrogate_wrapper_parameter_name(wrapper, i_param),
+                    print(interrogate_wrapper_parameter_name(wrapper, i_param), end=' ', file=handle)
                 first = False
 
-        print >>handle, ");"
+        print(");", file=handle)
 
 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)) ]
 
     if interrogate_type_has_comment(type):
-        print >>handle, block_comment(interrogate_type_comment(type))
+        print(block_comment(interrogate_type_comment(type)), file=handle)
 
     if interrogate_type_is_enum(type):
-        print >>handle, "enum %s {" % typename
+        print("enum %s {" % typename, file=handle)
         for i_value in range(interrogate_type_number_of_enum_values(type)):
             docstring = comment(interrogate_type_enum_value_comment(type, i_value))
             if docstring:
-                print >>handle, docstring
-            print >>handle, interrogate_type_enum_value_name(type, i_value), "=", interrogate_type_enum_value(type, i_value), ","
+                print(docstring, file=handle)
+            print(interrogate_type_enum_value_name(type, i_value), "=", interrogate_type_enum_value(type, i_value), ",", file=handle)
 
     elif interrogate_type_is_typedef(type):
         wrapped_type = translated_type_name(interrogate_type_wrapped_type(type))
-        print >>handle, "typedef %s %s;" % (wrapped_type, typename)
+        print("typedef %s %s;" % (wrapped_type, typename), file=handle)
         return
     else:
         if interrogate_type_is_struct(type):
@@ -220,39 +222,39 @@ def processType(handle, type):
         elif interrogate_type_is_union(type):
             classtype = "union"
         else:
-            print "I don't know what type %s is" % interrogate_type_true_name(type)
+            print("I don't know what type %s is" % interrogate_type_true_name(type))
             return
 
         if len(derivations) > 0:
-            print >>handle, "%s %s : public %s {" % (classtype, typename, ", public ".join(derivations))
+            print("%s %s : public %s {" % (classtype, typename, ", public ".join(derivations)), file=handle)
         else:
-            print >>handle, "%s %s {" % (classtype, typename)
-        print >>handle, "public:"
+            print("%s %s {" % (classtype, typename), file=handle)
+        print("public:", file=handle)
 
-    for i_ntype in xrange(interrogate_type_number_of_nested_types(type)):
+    for i_ntype in range(interrogate_type_number_of_nested_types(type)):
         processType(handle, interrogate_type_get_nested_type(type, i_ntype))
 
-    for i_method in xrange(interrogate_type_number_of_constructors(type)):
+    for i_method in range(interrogate_type_number_of_constructors(type)):
         processFunction(handle, interrogate_type_get_constructor(type, i_method), True)
 
-    for i_method in xrange(interrogate_type_number_of_methods(type)):
+    for i_method in range(interrogate_type_number_of_methods(type)):
         processFunction(handle, interrogate_type_get_method(type, i_method))
 
-    for i_method in xrange(interrogate_type_number_of_make_seqs(type)):
-        print >>handle, "list", translateFunctionName(interrogate_make_seq_seq_name(interrogate_type_get_make_seq(type, i_method))), "();"
+    for i_method in range(interrogate_type_number_of_make_seqs(type)):
+        print("list", translateFunctionName(interrogate_make_seq_seq_name(interrogate_type_get_make_seq(type, i_method))), "();", file=handle)
 
-    for i_element in xrange(interrogate_type_number_of_elements(type)):
+    for i_element in range(interrogate_type_number_of_elements(type)):
         processElement(handle, interrogate_type_get_element(type, i_element))
 
-    print >>handle, "};"
+    print("};", file=handle)
 
 def processModule(handle, package):
-    print >>handle, "namespace %s {" % package
+    print("namespace %s {" % package, file=handle)
 
     if package != "core":
-        print >>handle, "using namespace core;"
+        print("using namespace core;", file=handle)
 
-    for i_type in xrange(interrogate_number_of_global_types()):
+    for i_type in range(interrogate_number_of_global_types()):
         type = interrogate_get_global_type(i_type)
 
         if interrogate_type_has_module_name(type):
@@ -260,9 +262,9 @@ def processModule(handle, package):
             if "panda3d." + package == module_name:
                 processType(handle, type)
         else:
-            print "Type %s has no module name" % typename
+            print("Type %s has no module name" % typename)
 
-    for i_func in xrange(interrogate_number_of_global_functions()):
+    for i_func in range(interrogate_number_of_global_functions()):
         func = interrogate_get_global_function(i_func)
 
         if interrogate_function_has_module_name(func):
@@ -270,16 +272,16 @@ def processModule(handle, package):
             if "panda3d." + package == module_name:
                 processFunction(handle, func)
         else:
-            print "Type %s has no module name" % typename
+            print("Type %s has no module name" % typename)
 
-    print >>handle, "}"
+    print("}", file=handle)
 
 
 if __name__ == "__main__":
     handle = open("pandadoc.hpp", "w")
 
-    print >>handle, comment("Panda3D modules that are implemented in C++.")
-    print >>handle, "namespace panda3d {"
+    print(comment("Panda3D modules that are implemented in C++."), file=handle)
+    print("namespace panda3d {", file=handle)
 
     # Determine the path to the interrogatedb files
     interrogate_add_search_directory(os.path.join(os.path.dirname(pandac.__file__), "..", "..", "etc"))
@@ -295,5 +297,5 @@ if __name__ == "__main__":
             processModule(handle, module_name)
 
 
-    print >>handle, "}"
+    print("}", file=handle)
     handle.close()

+ 26 - 26
direct/src/directscripts/gendocs.py

@@ -48,7 +48,7 @@
 #
 ########################################################################
 
-import os, sys, parser, symbol, token, types, re
+import os, sys, parser, symbol, token, re
 
 ########################################################################
 #
@@ -103,7 +103,7 @@ def writeFileLines(wfile, lines):
         sys.exit("Cannot write "+wfile)
 
 def findFiles(dirlist, ext, ign, list):
-    if isinstance(dirlist, types.StringTypes):
+    if isinstance(dirlist, str):
         dirlist = [dirlist]
     for dir in dirlist:
         for file in os.listdir(dir):
@@ -195,8 +195,8 @@ class InterrogateTokenizer:
             neg = 1
             self.pos += 1
         if (self.data[self.pos].isdigit()==0):
-            print "File position "+str(self.pos)
-            print "Text: "+self.data[self.pos:self.pos+50]
+            print("File position " + str(self.pos))
+            print("Text: " + self.data[self.pos:self.pos+50])
             sys.exit("Syntax error in interrogate file format 0")
         value = 0
         while (self.data[self.pos].isdigit()):
@@ -340,20 +340,20 @@ class InterrogateDatabase:
 
 def printTree(tree, indent):
     spacing = "                                                        "[:indent]
-    if isinstance(tree, types.TupleType) and isinstance(tree[0], types.IntType):
+    if isinstance(tree, tuple) and isinstance(tree[0], int):
         if tree[0] in symbol.sym_name:
             for i in range(len(tree)):
                 if (i==0):
-                    print spacing + "(symbol." + symbol.sym_name[tree[0]] + ","
+                    print(spacing + "(symbol." + symbol.sym_name[tree[0]] + ",")
                 else:
                     printTree(tree[i], indent+1)
-            print spacing + "),"
+            print(spacing + "),")
         elif tree[0] in token.tok_name:
-            print spacing + "(token." + token.tok_name[tree[0]] + ", '" + tree[1] + "'),"
+            print(spacing + "(token." + token.tok_name[tree[0]] + ", '" + tree[1] + "'),")
         else:
-            print spacing + str(tree)
+            print(spacing + str(tree))
     else:
-        print spacing + str(tree)
+        print(spacing + str(tree))
 
 
 COMPOUND_STMT_PATTERN = (
@@ -447,7 +447,7 @@ class ParseTreeInfo:
         self.function_info = {}
         self.assign_info = {}
         self.derivs = {}
-        if isinstance(tree, types.StringType):
+        if isinstance(tree, str):
             try:
                 tree = parser.suite(tree+"\n").totuple()
                 if (tree):
@@ -455,8 +455,8 @@ class ParseTreeInfo:
                     if found:
                         self.docstring = vars["docstring"]
             except:
-                print "CAUTION --- Parse failed: "+name
-        if isinstance(tree, types.TupleType):
+                print("CAUTION --- Parse failed: " + name)
+        if isinstance(tree, tuple):
             self.extract_info(tree)
 
     def match(self, pattern, data, vars=None):
@@ -480,10 +480,10 @@ class ParseTreeInfo:
         """
         if vars is None:
             vars = {}
-        if type(pattern) is types.ListType:       # 'variables' are ['varname']
+        if type(pattern) is list:       # 'variables' are ['varname']
             vars[pattern[0]] = data
             return 1, vars
-        if type(pattern) is not types.TupleType:
+        if type(pattern) is not tuple:
             return (pattern == data), vars
         if len(data) != len(pattern):
             return 0, vars
@@ -534,7 +534,7 @@ class ParseTreeInfo:
                     classinfo.derivs[vars["classname"]] = 1
 
     def extract_tokens(self, str, tree):
-        if (isinstance(tree, types.TupleType)):
+        if (isinstance(tree, tuple)):
             if tree[0] in token.tok_name:
                 str = str + tree[1]
                 if (tree[1]==","): str=str+" "
@@ -564,7 +564,7 @@ class CodeDatabase:
         self.varExports = {}
         self.globalfn = []
         self.formattedprotos = {}
-        print "Reading C++ source files"
+        print("Reading C++ source files")
         for cxx in cxxlist:
             tokzr = InterrogateTokenizer(cxx)
             idb = InterrogateDatabase(tokzr)
@@ -583,7 +583,7 @@ class CodeDatabase:
                     self.funcExports.setdefault("pandac.PandaModules", []).append(func.pyname)
                 else:
                     self.funcs[type.scopedname+"."+func.pyname] = func
-        print "Reading Python sources files"
+        print("Reading Python sources files")
         for py in pylist:
             pyinf = ParseTreeInfo(readFile(py), py, py)
             mod = pathToModule(py)
@@ -602,7 +602,7 @@ class CodeDatabase:
                 self.varExports.setdefault(mod, []).append(var)
 
     def getClassList(self):
-        return self.goodtypes.keys()
+        return list(self.goodtypes.keys())
 
     def getGlobalFunctionList(self):
         return self.globalfn
@@ -625,7 +625,7 @@ class CodeDatabase:
                 parents.append(basetype.scopedname)
             return parents
         elif (isinstance(type, ParseTreeInfo)):
-            return type.derivs.keys()
+            return list(type.derivs.keys())
         else:
             return []
 
@@ -767,7 +767,7 @@ CLASS_RENAME_DICT = {
 ########################################################################
 
 def makeCodeDatabase(indirlist, directdirlist):
-    if isinstance(directdirlist, types.StringTypes):
+    if isinstance(directdirlist, str):
         directdirlist = [directdirlist]
     ignore = {}
     ignore["__init__.py"] = 1
@@ -820,7 +820,7 @@ def generate(pversion, indirlist, directdirlist, docdir, header, footer, urlpref
     classes = code.getClassList()[:]
     classes.sort(None, str.lower)
     xclasses = classes[:]
-    print "Generating HTML pages"
+    print("Generating HTML pages")
     for type in classes:
         body = "<h1>" + type + "</h1>\n"
         comment = code.getClassComment(type)
@@ -900,14 +900,14 @@ def generate(pversion, indirlist, directdirlist, docdir, header, footer, urlpref
 
     index = "<h1>List of Methods - Panda " + pversion + "</h1>\n"
 
-    prefixes = table.keys()
+    prefixes = list(table.keys())
     prefixes.sort(None, str.lower)
     for prefix in prefixes:
         index = index + linkTo("#"+prefix, prefix) + " "
     index = index + "<br><br>"
     for prefix in prefixes:
         index = index + '<a name="' + prefix + '">' + "\n"
-        names = table[prefix].keys()
+        names = list(table[prefix].keys())
         names.sort(None, str.lower)
         for name in names:
             line = '<b>' + name + ":</b><ul>\n"
@@ -968,9 +968,9 @@ def expandImports(indirlist, directdirlist, fixdirlist):
                 varExports = code.getVarExports(module)
                 if (len(typeExports)+len(funcExports)+len(varExports)==0):
                     result.append(line)
-                    print fixfile+" : "+module+" : no exports"
+                    print(fixfile + " : " + module + " : no exports")
                 else:
-                    print fixfile+" : "+module+" : repairing"
+                    print(fixfile + " : " + module + " : repairing")
                     for x in funcExports:
                         fn = code.getFunctionName(x)
                         if fn in used:

+ 28 - 28
direct/src/directscripts/packpanda.py

@@ -13,7 +13,7 @@
 #
 ##############################################################################
 
-import sys, os, getopt, string, shutil, py_compile, subprocess
+import sys, os, getopt, shutil, py_compile, subprocess
 
 OPTIONLIST = [
 ("dir",       1, "Name of directory containing game"),
@@ -27,14 +27,14 @@ OPTIONLIST = [
 ]
 
 def ParseFailure():
-  print ""
-  print "packpanda usage:"
-  print ""
+  print("")
+  print("packpanda usage:")
+  print("")
   for (opt, hasval, explanation) in OPTIONLIST:
     if (hasval):
-      print "  --%-10s    %s"%(opt+" x", explanation)
+      print("  --%-10s    %s"%(opt+" x", explanation))
     else:
-      print "  --%-10s    %s"%(opt+"  ", explanation)
+      print("  --%-10s    %s"%(opt+"  ", explanation))
   sys.exit(1)
 
 def ParseOptions(args):
@@ -75,7 +75,7 @@ for dir in sys.path:
         PANDA=os.path.abspath(dir)
 if (PANDA is None):
   sys.exit("Cannot locate the panda root directory in the python path (cannot locate directory containing direct and pandac).")
-print "PANDA located at "+PANDA
+print("PANDA located at "+PANDA)
 
 if (os.path.exists(os.path.join(PANDA,"..","makepanda","makepanda.py"))) and (sys.platform != "win32" or os.path.exists(os.path.join(PANDA,"..","thirdparty","win-nsis","makensis.exe"))):
   PSOURCE=os.path.abspath(os.path.join(PANDA,".."))
@@ -95,7 +95,7 @@ else:
 VER=OPTIONS["version"]
 DIR=OPTIONS["dir"]
 if (DIR==""):
-  print "You must specify the --dir option."
+  print("You must specify the --dir option.")
   ParseFailure()
 DIR=os.path.abspath(DIR)
 MYDIR=os.path.abspath(os.getcwd())
@@ -123,21 +123,21 @@ else: MAIN="main.py"
 
 def PrintFileStatus(label, file):
   if (os.path.exists(file)):
-    print "%-15s: %s"%(label, file)
+    print("%-15s: %s"%(label, file))
   else:
-    print "%-15s: %s (MISSING)"%(label, file)
+    print("%-15s: %s (MISSING)"%(label, file))
 
 PrintFileStatus("Dir", DIR)
-print "%-15s: %s"%("Name", NAME)
-print "%-15s: %s"%("Start Menu", SMDIRECTORY)
+print("%-15s: %s"%("Name", NAME))
+print("%-15s: %s"%("Start Menu", SMDIRECTORY))
 PrintFileStatus("Main", os.path.join(DIR, MAIN))
 if (sys.platform == "win32"):
   PrintFileStatus("Icon", ICON)
   PrintFileStatus("Bitmap", BITMAP)
 PrintFileStatus("License", LICENSE)
-print "%-15s: %s"%("Output", OUTFILE)
+print("%-15s: %s"%("Output", OUTFILE))
 if (sys.platform == "win32"):
-  print "%-15s: %s"%("Install Dir", INSTALLDIR)
+  print("%-15s: %s"%("Install Dir", INSTALLDIR))
 
 if (os.path.isdir(DIR)==0):
   sys.exit("Difficulty reading "+DIR+". Cannot continue.")
@@ -181,8 +181,8 @@ if (sys.platform == "win32"):
 else:
   TMPGAME=os.path.join(TMPDIR,"usr","share","games",BASENAME,"game")
   TMPETC=os.path.join(TMPDIR,"usr","share","games",BASENAME,"etc")
-print ""
-print "Copying the game to "+TMPDIR+"..."
+print("")
+print("Copying the game to "+TMPDIR+"...")
 if (os.path.exists(TMPDIR)):
     try: shutil.rmtree(TMPDIR)
     except: sys.exit("Cannot delete "+TMPDIR)
@@ -247,7 +247,7 @@ def egg2bam(file,bam):
     present = os.path.exists(bam)
     if (present): bam = "packpanda-TMP.bam";
     cmd = 'egg2bam -noabs -ps rel -pd . "'+file+'" -o "'+bam+'"'
-    print "Executing: "+cmd
+    print("Executing: "+cmd)
     if (sys.platform == "win32"):
       res = os.spawnl(os.P_WAIT, EGG2BAM, cmd)
     else:
@@ -257,7 +257,7 @@ def egg2bam(file,bam):
         os.unlink(bam)
 
 def py2pyc(file):
-    print "Compiling python "+file
+    print("Compiling python "+file)
     pyc = file[:-3]+'.pyc'
     pyo = file[:-3]+'.pyo'
     if (os.path.exists(pyc)): os.unlink(pyc)
@@ -284,24 +284,24 @@ def CompileFiles(file):
             CompileFiles(os.path.join(file, x))
 
 def DeleteFiles(file):
-    base = string.lower(os.path.basename(file))
+    base = os.path.basename(file).lower()
     if (os.path.isdir(file)):
         for pattern in OPTIONS["rmdir"]:
-            if (string.lower(pattern) == base):
-                print "Deleting "+file
+            if pattern.lower() == base:
+                print("Deleting "+file)
                 shutil.rmtree(file)
                 return
         for x in os.listdir(file):
             DeleteFiles(os.path.join(file, x))
     else:
         for ext in OPTIONS["rmext"]:
-            if (base[-(len(ext)+1):] == string.lower("."+ext)):
-                print "Deleting "+file
+            if base[-(len(ext) + 1):] == ("." + ext).lower():
+                print("Deleting "+file)
                 os.unlink(file)
                 return
 
-print ""
-print "Compiling BAM and PYC files..."
+print("")
+print("Compiling BAM and PYC files...")
 os.chdir(TMPGAME)
 CompileFiles(".")
 DeleteFiles(".")
@@ -371,9 +371,9 @@ if (sys.platform == "win32"):
     CMD=CMD+'/DPPICON="'+PPICON+'" '
     CMD=CMD+'"'+PSOURCE+'\\direct\\directscripts\\packpanda.nsi"'
 
-    print ""
-    print CMD
-    print "packing..."
+    print("")
+    print(CMD)
+    print("packing...")
     subprocess.call(CMD)
 else:
     os.chdir(MYDIR)

+ 6 - 6
direct/src/directtools/DirectCameraControl.py

@@ -1,8 +1,8 @@
 from direct.showbase.DirectObject import DirectObject
-from DirectUtil import *
-from DirectGeometry import *
-from DirectGlobals import *
-from DirectSelection import SelectionRay
+from .DirectUtil import *
+from .DirectGeometry import *
+from .DirectGlobals import *
+from .DirectSelection import SelectionRay
 from direct.interval.IntervalGlobal import Sequence, Func
 from direct.directnotify import DirectNotifyGlobal
 from direct.task import Task
@@ -233,13 +233,13 @@ class DirectCameraControl(DirectObject):
         self.updateCoaMarkerSize()
 
     def mouseFlyStartTopWin(self):
-        print "Moving mouse 2 in new window"
+        print("Moving mouse 2 in new window")
         #altIsDown = base.getAlt()
         #if altIsDown:
         #    print "Alt is down"
 
     def mouseFlyStopTopWin(self):
-        print "Stopping mouse 2 in new window"
+        print("Stopping mouse 2 in new window")
 
     def spawnXZTranslateOrHPanYZoom(self):
         # Kill any existing tasks

+ 9 - 9
direct/src/directtools/DirectGeometry.py

@@ -1,7 +1,7 @@
 
 from panda3d.core import *
-from DirectGlobals import *
-from DirectUtil import *
+from .DirectGlobals import *
+from .DirectUtil import *
 import math
 
 class LineNodePath(NodePath):
@@ -28,10 +28,10 @@ class LineNodePath(NodePath):
         ls.setColor(colorVec)
 
     def moveTo(self, *_args):
-        apply(self.lineSegs.moveTo, _args)
+        self.lineSegs.moveTo(*_args)
 
     def drawTo(self, *_args):
-        apply(self.lineSegs.drawTo, _args)
+        self.lineSegs.drawTo(*_args)
 
     def create(self, frameAccurate = 0):
         self.lineSegs.create(self.lineNode, frameAccurate)
@@ -47,13 +47,13 @@ class LineNodePath(NodePath):
         self.lineSegs.setThickness(thickness)
 
     def setColor(self, *_args):
-        apply(self.lineSegs.setColor, _args)
+        self.lineSegs.setColor(*_args)
 
     def setVertex(self, *_args):
-        apply(self.lineSegs.setVertex, _args)
+        self.lineSegs.setVertex(*_args)
 
     def setVertexColor(self, vertex, *_args):
-        apply(self.lineSegs.setVertexColor, (vertex,) + _args)
+        self.lineSegs.setVertexColor(*(vertex,) + _args)
 
     def getCurrentPosition(self):
         return self.lineSegs.getCurrentPosition()
@@ -119,9 +119,9 @@ class LineNodePath(NodePath):
         Given a list of lists of points, draw a separate line for each list
         """
         for pointList in lineList:
-            apply(self.moveTo, pointList[0])
+            self.moveTo(*pointList[0])
             for point in pointList[1:]:
-                apply(self.drawTo, point)
+                self.drawTo(*point)
 
 ##
 ## Given a point in space, and a direction, find the point of intersection

+ 2 - 2
direct/src/directtools/DirectGlobals.py

@@ -51,12 +51,12 @@ LE_CAM_MASKS = {'persp':LE_PERSP_CAM_MASK,
                  'top':LE_TOP_CAM_MASK}
 
 def LE_showInAllCam(nodePath):
-    for camName in LE_CAM_MASKS.keys():
+    for camName in LE_CAM_MASKS:
         nodePath.show(LE_CAM_MASKS[camName])
 
 def LE_showInOneCam(nodePath, thisCamName):
     LE_showInAllCam(nodePath)
-    for camName in LE_CAM_MASKS.keys():
+    for camName in LE_CAM_MASKS:
         if camName != thisCamName:
             nodePath.hide(LE_CAM_MASKS[camName])
 

+ 2 - 2
direct/src/directtools/DirectGrid.py

@@ -1,8 +1,8 @@
 
 from panda3d.core import *
 from direct.showbase.DirectObject import DirectObject
-from DirectUtil import *
-from DirectGeometry import *
+from .DirectUtil import *
+from .DirectGeometry import *
 
 class DirectGrid(NodePath, DirectObject):
     def __init__(self,gridSize=100.0,gridSpacing=5.0,planeColor=(0.5,0.5,0.5,0.5),parent = None):

+ 1 - 1
direct/src/directtools/DirectLights.py

@@ -78,7 +78,7 @@ class DirectLights(NodePath):
             light.setColor(VBase4(1))
             light.setLens(PerspectiveLens())
         else:
-            print 'Invalid light type'
+            print('Invalid light type')
             return None
         # Add the new light
         directLight = DirectLight(light, self)

+ 6 - 7
direct/src/directtools/DirectManipulation.py

@@ -1,10 +1,9 @@
 from direct.showbase.DirectObject import DirectObject
-from DirectGlobals import *
-from DirectUtil import *
-from DirectGeometry import *
-from DirectSelection import SelectionRay
+from .DirectGlobals import *
+from .DirectUtil import *
+from .DirectGeometry import *
+from .DirectSelection import SelectionRay
 from direct.task import Task
-import types
 from copy import deepcopy
 
 class DirectManipulationControl(DirectObject):
@@ -1207,7 +1206,7 @@ class ObjectHandles(NodePath, DirectObject):
         self.reparentTo(hidden)
 
     def enableHandles(self, handles):
-        if type(handles) == types.ListType:
+        if type(handles) == list:
             for handle in handles:
                 self.enableHandle(handle)
         elif handles == 'x':
@@ -1256,7 +1255,7 @@ class ObjectHandles(NodePath, DirectObject):
             self.zScaleGroup.reparentTo(self.zHandles)
 
     def disableHandles(self, handles):
-        if type(handles) == types.ListType:
+        if type(handles) == list:
             for handle in handles:
                 self.disableHandle(handle)
         elif handles == 'x':

+ 6 - 6
direct/src/directtools/DirectSelection.py

@@ -1,7 +1,7 @@
 from direct.showbase.DirectObject import DirectObject
-from DirectGlobals import *
-from DirectUtil import *
-from DirectGeometry import *
+from .DirectGlobals import *
+from .DirectUtil import *
+from .DirectGeometry import *
 
 COA_ORIGIN = 0
 COA_CENTER = 1
@@ -68,7 +68,7 @@ class SelectedNodePaths(DirectObject):
         """ Select the specified node path.  Multiselect as required """
         # Do nothing if nothing selected
         if not nodePath:
-            print 'Nothing selected!!'
+            print('Nothing selected!!')
             return None
 
         # Reset selected objects and highlight if multiSelect is false
@@ -160,7 +160,7 @@ class SelectedNodePaths(DirectObject):
             return None
 
     def getDeselectedAsList(self):
-        return self.deselectedDict.values()[:]
+        return list(self.deselectedDict.values())
 
     def getDeselectedDict(self, id):
         """
@@ -260,7 +260,7 @@ class SelectedNodePaths(DirectObject):
         return self.getDeselectedDict(id)
 
     def getNumSelected(self):
-        return len(self.selectedDict.keys())
+        return len(self.selectedDict)
 
 
 class DirectBoundingBox:

+ 17 - 16
direct/src/directtools/DirectSession.py

@@ -1,27 +1,25 @@
 import math
-import types
-import string
+import sys
 
 from panda3d.core import *
-from DirectUtil import *
+from .DirectUtil import *
 
 from direct.showbase.DirectObject import DirectObject
 from direct.task import Task
 
-from DirectGlobals import DIRECT_NO_MOD
-from DirectCameraControl import DirectCameraControl
-from DirectManipulation import DirectManipulationControl
-from DirectSelection import SelectionRay, COA_ORIGIN, SelectedNodePaths
-from DirectGrid import DirectGrid
+from .DirectGlobals import DIRECT_NO_MOD
+from .DirectCameraControl import DirectCameraControl
+from .DirectManipulation import DirectManipulationControl
+from .DirectSelection import SelectionRay, COA_ORIGIN, SelectedNodePaths
+from .DirectGrid import DirectGrid
 #from DirectGeometry import *
-from DirectLights import DirectLights
+from .DirectLights import DirectLights
 from direct.cluster.ClusterClient import createClusterClient, DummyClusterClient
 from direct.cluster.ClusterServer import ClusterServer
 ## from direct.tkpanels import Placer
 ## from direct.tkwidgets import Slider
 ## from direct.tkwidgets import SceneGraphExplorer
 from direct.gui import OnscreenText
-from direct.showbase import Loader
 from direct.interval.IntervalGlobal import *
 
 class DirectSession(DirectObject):
@@ -115,7 +113,7 @@ class DirectSession(DirectObject):
             if fastrak:
                 from direct.directdevices import DirectFastrak
                 # parse string into format device:N where N is the sensor name
-                fastrak = string.split(fastrak)
+                fastrak = fastrak.split()
                 for i in range(len(fastrak))[1:]:
                     self.fastrak.append(DirectFastrak.DirectFastrak(fastrak[0] + ':' + fastrak[i]))
 
@@ -556,12 +554,12 @@ class DirectSession(DirectObject):
                     input = input[:-7]
 
         # Deal with keyboard and mouse input
-        if input in self.hotKeyMap.keys():
+        if input in self.hotKeyMap:
             keyDesc = self.hotKeyMap[input]
             messenger.send(keyDesc[1])
-        elif input in self.speicalKeyMap.keys():
+        elif input in self.speicalKeyMap:
             messenger.send(self.speicalKeyMap[input])
-        elif input in self.directOnlyKeyMap.keys():
+        elif input in self.directOnlyKeyMap:
             if self.fIgnoreDirectOnlyKeyMap:
                 return
             keyDesc = self.directOnlyKeyMap[input]
@@ -808,7 +806,7 @@ class DirectSession(DirectObject):
 
     def isNotCycle(self, nodePath, parent):
         if nodePath == parent:
-            print 'DIRECT.reparent: Invalid parent'
+            print('DIRECT.reparent: Invalid parent')
             return 0
         elif parent.hasParent():
             return self.isNotCycle(nodePath, parent.getParent())
@@ -944,7 +942,10 @@ class DirectSession(DirectObject):
 
     def getAndSetName(self, nodePath):
         """ Prompt user for new node path name """
-        from tkSimpleDialog import askstring
+        if sys.version_info >= (3, 0):
+            from tkinter.simpledialog import askstring
+        else:
+            from tkSimpleDialog import askstring
         newName = askstring('Node Path: ' + nodePath.getName(),
                             'Enter new name:')
         if newName:

+ 1 - 1
direct/src/directtools/DirectUtil.py

@@ -1,5 +1,5 @@
 
-from DirectGlobals import *
+from .DirectGlobals import *
 
 # Routines to adjust values
 def ROUND_TO(value, divisor):

+ 2 - 2
direct/src/directutil/DeltaProfiler.py

@@ -16,11 +16,11 @@ class DeltaProfiler:
     def printDeltaTime(self, label):
         if self.active:
             deltaTime=time()-self.priorTime
-            print "%s DeltaTime %-25s to %-25s: %3.5f"%(
+            print("%s DeltaTime %-25s to %-25s: %3.5f"%(
                 self.name,
                 self.priorLabel,
                 label,
-                deltaTime)
+                deltaTime))
             self.priorLabel=label
             # The printing time is not included in the timing.
             # This is intentional.

+ 1 - 1
direct/src/directutil/DistributedLargeBlobSender.py

@@ -2,7 +2,7 @@
 
 from direct.distributed import DistributedObject
 from direct.directnotify import DirectNotifyGlobal
-import LargeBlobSenderConsts
+from . import LargeBlobSenderConsts
 
 class DistributedLargeBlobSender(DistributedObject.DistributedObject):
     """DistributedLargeBlobSender: for sending large chunks of data through

+ 1 - 1
direct/src/directutil/DistributedLargeBlobSenderAI.py

@@ -2,7 +2,7 @@
 
 from direct.distributed import DistributedObjectAI
 from direct.directnotify import DirectNotifyGlobal
-import LargeBlobSenderConsts
+from . import LargeBlobSenderConsts
 
 class DistributedLargeBlobSenderAI(DistributedObjectAI.DistributedObjectAI):
     """DistributedLargeBlobSenderAI: for sending large chunks of data through

+ 1 - 1
direct/src/directutil/MemoryLeakHelpers.py

@@ -11,7 +11,7 @@
 import gc
 gc.set_debug(gc.DEBUG_LEAK)
 gc.collect()
-print gc.garbage
+print(gc.garbage)
 
 # Inside DistributedObjectAI, you can uncomment the __del__ function to
 # see when your objects are being deleted (or not)

+ 6 - 6
direct/src/directutil/Mopath.py

@@ -29,7 +29,7 @@ class Mopath(DirectObject):
         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("Mopath: Unable to load object '%s', objectToLoad must be a file name string or a NodePath" % objectToLoad)
 
     def getMaxT(self):
         return self.maxT * self.timeScale
@@ -40,7 +40,7 @@ class Mopath(DirectObject):
             self.loadNodePath(nodePath)
             nodePath.removeNode()
         else:
-            print 'Mopath: no data in file: %s' % filename
+            print('Mopath: no data in file: %s' % filename)
 
 
     def loadNodePath(self, nodePath, fReset = 1):
@@ -55,7 +55,7 @@ class Mopath(DirectObject):
         elif (self.hprNurbsCurve != None):
             self.maxT = self.hprNurbsCurve.getMaxT()
         else:
-            print 'Mopath: no valid curves in nodePath: %s' % nodePath
+            print('Mopath: no valid curves in nodePath: %s' % nodePath)
 
 
     def reset(self):
@@ -77,7 +77,7 @@ class Mopath(DirectObject):
                 if (self.xyzNurbsCurve == None):
                     self.xyzNurbsCurve = node
                 else:
-                    print 'Mopath: got a PCT_NONE curve and an XYZ Curve in nodePath: %s' % nodePath
+                    print('Mopath: got a PCT_NONE curve and an XYZ Curve in nodePath: %s' % nodePath)
             elif (node.getCurveType() == PCTT):
                 self.tNurbsCurve.append(node)
         else:
@@ -106,7 +106,7 @@ class Mopath(DirectObject):
 
     def goTo(self, node, time):
         if (self.xyzNurbsCurve == None) and (self.hprNurbsCurve == None):
-            print 'Mopath: Mopath has no curves'
+            print('Mopath: Mopath has no curves')
             return
         time /= self.timeScale
         self.playbackTime = self.calcTime(CLAMP(time, 0.0, self.maxT))
@@ -145,7 +145,7 @@ class Mopath(DirectObject):
 
     def play(self, node, time = 0.0, loop = 0):
         if (self.xyzNurbsCurve == None) and (self.hprNurbsCurve == None):
-            print 'Mopath: Mopath has no curves'
+            print('Mopath: Mopath has no curves')
             return
         self.node = node
         self.loop = loop

+ 3 - 3
direct/src/directutil/Verify.py

@@ -52,11 +52,11 @@ def verify(assertion):
     wish to have the assertion checked, even in release (-O) code.
     """
     if not assertion:
-        print "\n\nverify failed:"
+        print("\n\nverify failed:")
         import sys
-        print "    File \"%s\", line %d"%(
+        print("    File \"%s\", line %d"%(
                 sys._getframe(1).f_code.co_filename,
-                sys._getframe(1).f_lineno)
+                sys._getframe(1).f_lineno))
         if wantVerifyPdb:
             import pdb
             pdb.set_trace()

+ 4 - 4
direct/src/distributed/AsyncRequest.py

@@ -1,7 +1,7 @@
 #from otp.ai.AIBaseGlobal import *
 from direct.directnotify import DirectNotifyGlobal
 from direct.showbase.DirectObject import DirectObject
-from ConnectionRepository import *
+from .ConnectionRepository import *
 from panda3d.core import ConfigVariableDouble, ConfigVariableInt, ConfigVariableBool
 
 ASYNC_REQUEST_DEFAULT_TIMEOUT_IN_SECONDS = 8.0
@@ -251,9 +251,9 @@ class AsyncRequest(DirectObject):
             if __debug__:
                 if _breakOnTimeout:
                     if hasattr(self, "avatarId"):
-                        print "\n\nself.avatarId =", self.avatarId
-                    print "\nself.neededObjects =", self.neededObjects
-                    print "\ntimed out after %s seconds.\n\n"%(task.delayTime,)
+                        print("\n\nself.avatarId =", self.avatarId)
+                    print("\nself.neededObjects =", self.neededObjects)
+                    print("\ntimed out after %s seconds.\n\n"%(task.delayTime,))
                     import pdb; pdb.set_trace()
             self.delete()
             return Task.done

+ 1 - 1
direct/src/distributed/CRCache.py

@@ -1,7 +1,7 @@
 """CRCache module: contains the CRCache class"""
 
 from direct.directnotify import DirectNotifyGlobal
-import DistributedObject
+from . import DistributedObject
 
 class CRCache:
     notify = DirectNotifyGlobal.directNotify.newCategory("CRCache")

+ 2 - 2
direct/src/distributed/CRDataCache.py

@@ -23,7 +23,7 @@ class CRDataCache:
             # cache is full, throw out a random doId's data
             if self._junkIndex >= len(self._doId2name2data):
                 self._junkIndex = 0
-            junkDoId = self._doId2name2data.keys()[self._junkIndex]
+            junkDoId = list(self._doId2name2data.keys())[self._junkIndex]
             self._junkIndex += 1
             for name in self._doId2name2data[junkDoId]:
                 self._doId2name2data[junkDoId][name].flush()
@@ -96,7 +96,7 @@ if __debug__:
     assert 'testCachedData2' in data
     assert data['testCachedData'].foo == 34
     assert data['testCachedData2'].bar == 45
-    for cd in data.itervalues():
+    for cd in data.values():
         cd.flush()
     del data
     dc._checkMemLeaks()

+ 6 - 6
direct/src/distributed/ClientRepository.py

@@ -1,12 +1,12 @@
 """ClientRepository module: contains the ClientRepository class"""
 
-from ClientRepositoryBase import ClientRepositoryBase
+from .ClientRepositoryBase import ClientRepositoryBase
 from direct.directnotify import DirectNotifyGlobal
-from MsgTypesCMU import *
-from PyDatagram import PyDatagram
-from PyDatagramIterator import PyDatagramIterator
+from .MsgTypesCMU import *
+from .PyDatagram import PyDatagram
+from .PyDatagramIterator import PyDatagramIterator
 from panda3d.core import UniqueIdAllocator
-import types
+
 
 class ClientRepository(ClientRepositoryBase):
     """
@@ -305,7 +305,7 @@ class ClientRepository(ClientRepositoryBase):
 
     def handleDatagram(self, di):
         if self.notify.getDebug():
-            print "ClientRepository received datagram:"
+            print("ClientRepository received datagram:")
             di.getDatagram().dumpHex(ostream)
 
         msgType = self.getMsgType()

+ 13 - 15
direct/src/distributed/ClientRepositoryBase.py

@@ -1,18 +1,16 @@
 from pandac.PandaModules import *
-from MsgTypes import *
+from .MsgTypes import *
 from direct.task import Task
 from direct.directnotify import DirectNotifyGlobal
-import CRCache
+from . import CRCache
 from direct.distributed.CRDataCache import CRDataCache
 from direct.distributed.ConnectionRepository import ConnectionRepository
 from direct.showbase import PythonUtil
-import ParentMgr
-import RelatedObjectMgr
+from . import ParentMgr
+from . import RelatedObjectMgr
 import time
-from ClockDelta import *
-from PyDatagram import PyDatagram
-from PyDatagramIterator import PyDatagramIterator
-import types
+from .ClockDelta import *
+
 
 class ClientRepositoryBase(ConnectionRepository):
     """
@@ -190,7 +188,7 @@ class ClientRepositoryBase(ConnectionRepository):
                 for dg, di in updates:
                     # non-DC updates that need to be played back in-order are
                     # stored as (msgType, (dg, di))
-                    if type(di) is types.TupleType:
+                    if type(di) is tuple:
                         msgType = dg
                         dg, di = di
                         self.replayDeferredGenerate(msgType, (dg, di))
@@ -264,7 +262,7 @@ class ClientRepositoryBase(ConnectionRepository):
             distObj.setLocation(parentId, zoneId)
             distObj.updateRequiredFields(dclass, di)
             # updateRequiredFields calls announceGenerate
-            print "New DO:%s, dclass:%s"%(doId, dclass.getName())
+            print("New DO:%s, dclass:%s"%(doId, dclass.getName()))
         return distObj
 
     def generateWithRequiredOtherFields(self, dclass, doId, di,
@@ -602,8 +600,8 @@ class ClientRepositoryBase(ConnectionRepository):
         del self._delayDeletedDOs[key]
 
     def printDelayDeletes(self):
-        print 'DelayDeletes:'
-        print '============='
-        for obj in self._delayDeletedDOs.itervalues():
-            print '%s\t%s (%s)\tdelayDeletes=%s' % (
-                obj.doId, safeRepr(obj), itype(obj), obj.getDelayDeleteNames())
+        print('DelayDeletes:')
+        print('=============')
+        for obj in self._delayDeletedDOs.values():
+            print('%s\t%s (%s)\tdelayDeletes=%s' % (
+                obj.doId, safeRepr(obj), itype(obj), obj.getDelayDeleteNames()))

+ 3 - 6
direct/src/distributed/ConnectionRepository.py

@@ -4,15 +4,12 @@ from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.distributed.DoInterestManager import DoInterestManager
 from direct.distributed.DoCollectionManager import DoCollectionManager
 from direct.showbase import GarbageReport
-from PyDatagram import PyDatagram
-from PyDatagramIterator import PyDatagramIterator
+from .PyDatagramIterator import PyDatagramIterator
 
 import types
-import imp
 import gc
 
 
-
 class ConnectionRepository(
         DoInterestManager, DoCollectionManager, CConnectionRepository):
     """
@@ -248,7 +245,7 @@ class ConnectionRepository(
         self.dclassesByNumber = {}
         self.hashVal = 0
 
-        if isinstance(dcFileNames, types.StringTypes):
+        if isinstance(dcFileNames, str):
             # If we were given a single string, make it a list.
             dcFileNames = [dcFileNames]
 
@@ -514,7 +511,7 @@ class ConnectionRepository(
             if failureCallback:
                 failureCallback(0, '', *failureArgs)
         else:
-            print "uh oh, we aren't using one of the tri-state CM variables"
+            print("uh oh, we aren't using one of the tri-state CM variables")
             failureCallback(0, '', *failureArgs)
 
     def disconnect(self):

+ 6 - 6
direct/src/distributed/DistributedCamera.py

@@ -148,8 +148,8 @@ class Fixture(NodePath, FSM):
         # if added to the dc definition of the Fixture struct and
         # saved out to the Camera file.
         lodNodes = render.findAllMatches('**/+LODNode')
-        for i in xrange(0,lodNodes.getNumPaths()):
-            lodNodes[i].node().forceSwitch(lodNodes[i].node().getHighestSwitch())
+        for lodNode in lodNodes:
+            lodNode.node().forceSwitch(lodNode.node().getHighestSwitch())
 
 
     def exitUsing(self):
@@ -183,13 +183,13 @@ class DistributedCamera(DistributedObject):
 
     def __str__(self):
         out = ''
-        for fixture in self.fixtures.itervalues():
+        for fixture in self.fixtures.values():
             out = '%s\n%s' % (out, fixture)
         return out[1:]
 
     def pack(self):
         out = ''
-        for fixture in self.fixtures.itervalues():
+        for fixture in self.fixtures.values():
             out = '%s\n%s' % (out, fixture.pack())
         return out[1:]
 
@@ -198,7 +198,7 @@ class DistributedCamera(DistributedObject):
 
         self.parent = None
 
-        for fixture in self.fixtures.itervalues():
+        for fixture in self.fixtures.values():
             fixture.cleanup()
             fixture.detachNode()
         self.fixtures = {}
@@ -215,7 +215,7 @@ class DistributedCamera(DistributedObject):
             else:
                 self.parent = self.cr.getDo(doId)
 
-            for fix in self.fixtures.itervalues():
+            for fix in self.fixtures.values():
                 fix.reparentTo(self.parent)
 
     def getCamParent(self):

+ 1 - 1
direct/src/distributed/DistributedCartesianGrid.py

@@ -15,7 +15,7 @@ if __debug__:
     from direct.directtools.DirectGeometry import *
     from direct.showbase.PythonUtil import randFloat
 
-from CartesianGridBase import CartesianGridBase
+from .CartesianGridBase import CartesianGridBase
 
 # increase this number if you want to visualize the grid lines
 # above water level

+ 2 - 2
direct/src/distributed/DistributedCartesianGridAI.py

@@ -2,8 +2,8 @@
 from pandac.PandaModules import *
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.task import Task
-from DistributedNodeAI import DistributedNodeAI
-from CartesianGridBase import CartesianGridBase
+from .DistributedNodeAI import DistributedNodeAI
+from .CartesianGridBase import CartesianGridBase
 
 class DistributedCartesianGridAI(DistributedNodeAI, CartesianGridBase):
     notify = directNotify.newCategory("DistributedCartesianGridAI")

+ 5 - 6
direct/src/distributed/DistributedNode.py

@@ -1,10 +1,9 @@
 """DistributedNode module: contains the DistributedNode class"""
 
 from panda3d.core import NodePath
-from direct.task import Task
-import GridParent
-import DistributedObject
-import types
+from . import GridParent
+from . import DistributedObject
+
 
 class DistributedNode(DistributedObject.DistributedObject, NodePath):
     """Distributed Node class:"""
@@ -77,7 +76,7 @@ class DistributedNode(DistributedObject.DistributedObject, NodePath):
     ### setParent ###
 
     def b_setParent(self, parentToken):
-        if type(parentToken) == types.StringType:
+        if type(parentToken) == str:
             self.setParentStr(parentToken)
         else:
             self.setParent(parentToken)
@@ -85,7 +84,7 @@ class DistributedNode(DistributedObject.DistributedObject, NodePath):
         self.d_setParent(parentToken)
 
     def d_setParent(self, parentToken):
-        if type(parentToken) == types.StringType:
+        if type(parentToken) == str:
             self.sendUpdate("setParentStr", [parentToken])
         else:
             self.sendUpdate("setParent", [parentToken])

+ 4 - 4
direct/src/distributed/DistributedNodeAI.py

@@ -1,7 +1,7 @@
 from pandac.PandaModules import NodePath
-import DistributedObjectAI
-import GridParent
-import types
+from . import DistributedObjectAI
+from . import GridParent
+
 
 class DistributedNodeAI(DistributedObjectAI.DistributedObjectAI, NodePath):
     def __init__(self, air, name=None):
@@ -47,7 +47,7 @@ class DistributedNodeAI(DistributedObjectAI.DistributedObjectAI, NodePath):
     ### setParent ###
 
     def b_setParent(self, parentToken):
-        if type(parentToken) == types.StringType:
+        if type(parentToken) == str:
             self.setParentStr(parentToken)
         else:
             self.setParent(parentToken)

+ 2 - 2
direct/src/distributed/DistributedNodeUD.py

@@ -1,5 +1,5 @@
 #from otp.ai.AIBaseGlobal import *
-from DistributedObjectUD import DistributedObjectUD
+from .DistributedObjectUD import DistributedObjectUD
 
 class DistributedNodeUD(DistributedObjectUD):
     def __init__(self, air, name=None):
@@ -13,7 +13,7 @@ class DistributedNodeUD(DistributedObjectUD):
                 name = self.__class__.__name__
 
     def b_setParent(self, parentToken):
-        if type(parentToken) == types.StringType:
+        if type(parentToken) == str:
             self.setParentStr(parentToken)
         else:
             self.setParent(parentToken)

+ 18 - 15
direct/src/distributed/DistributedObject.py

@@ -1,6 +1,7 @@
 """DistributedObject module: contains the DistributedObject class"""
 
-from pandac.PandaModules import *
+from panda3d.core import *
+from panda3d.direct import *
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.distributed.DistributedObjectBase import DistributedObjectBase
 from direct.showbase.PythonUtil import StackTrace
@@ -80,14 +81,11 @@ class DistributedObject(DistributedObjectBase):
                 and conditionally show generated, disabled, neverDisable,
                 or cachable"
             """
-            spaces=' '*(indent+2)
+            spaces = ' ' * (indent + 2)
             try:
-                print "%s%s:"%(
-                    ' '*indent, self.__class__.__name__)
-                print "%sfrom DistributedObject doId:%s, parent:%s, zone:%s"%(
-                    spaces,
-                    self.doId, self.parentId, self.zoneId),
-                flags=[]
+                print("%s%s:" % (' ' * indent, self.__class__.__name__))
+
+                flags = []
                 if self.activeState == ESGenerated:
                     flags.append("generated")
                 if self.activeState < ESGenerating:
@@ -96,10 +94,15 @@ class DistributedObject(DistributedObjectBase):
                     flags.append("neverDisable")
                 if self.cacheable:
                     flags.append("cacheable")
+
+                flagStr = ""
                 if len(flags):
-                    print "(%s)"%(" ".join(flags),),
-                print
-            except Exception, e: print "%serror printing status"%(spaces,), e
+                    flagStr = " (%s)" % (" ".join(flags))
+
+                print("%sfrom DistributedObject doId:%s, parent:%s, zone:%s%s" % (
+                    spaces, self.doId, self.parentId, self.zoneId, flagStr))
+            except Exception as e:
+                print("%serror printing status %s" % (spaces, e))
 
     def getAutoInterests(self):
         # returns the sub-zones under this object that are automatically
@@ -123,7 +126,7 @@ class DistributedObject(DistributedObjectBase):
                         p = DCPacker()
                         p.setUnpackData(field.getDefaultValue())
                         len = p.rawUnpackUint16()/4
-                        for i in xrange(len):
+                        for i in range(len):
                             zone = int(p.rawUnpackUint32())
                             autoInterests.add(zone)
                     autoInterests.update(autoInterests)
@@ -247,7 +250,7 @@ class DistributedObject(DistributedObjectBase):
             # we are going to crash, output the destroyDo stacktrace
             self.notify.warning('self.cr is none in _deactivateDO %d' % self.doId)
             if hasattr(self, 'destroyDoStackTrace'):
-                print self.destroyDoStackTrace
+                print(self.destroyDoStackTrace)
         self.__callbacks = {}
         self.cr.closeAutoInterests(self)
         self.setLocation(0,0)
@@ -260,7 +263,7 @@ class DistributedObject(DistributedObjectBase):
         # check for leftover cached data that was not retrieved or flushed by this object
         # this will catch typos in the data name in calls to get/setCachedData
         if hasattr(self, '_cachedData'):
-            for name, cachedData in self._cachedData.iteritems():
+            for name, cachedData in self._cachedData.items():
                 self.notify.warning('flushing unretrieved cached data: %s' % name)
                 cachedData.flush()
             del self._cachedData
@@ -398,7 +401,7 @@ class DistributedObject(DistributedObjectBase):
     def getCurrentContexts(self):
         # Returns a list of the currently outstanding contexts created
         # by getCallbackContext().
-        return self.__callbacks.keys()
+        return list(self.__callbacks.keys())
 
     def getCallback(self, context):
         # Returns the callback that was passed in to the previous

+ 18 - 16
direct/src/distributed/DistributedObjectAI.py

@@ -3,7 +3,8 @@
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.distributed.DistributedObjectBase import DistributedObjectBase
 from direct.showbase import PythonUtil
-from pandac.PandaModules import *
+from panda3d.core import *
+from panda3d.direct import *
 #from PyDatagram import PyDatagram
 #from PyDatagramIterator import PyDatagramIterator
 
@@ -56,25 +57,26 @@ class DistributedObjectAI(DistributedObjectBase):
         def status(self, indent=0):
             """
             print out doId(parentId, zoneId) className
-                and conditionally show generated, disabled, neverDisable,
-                or cachable
+                and conditionally show generated or deleted
             """
-            spaces=' '*(indent+2)
+            spaces = ' ' * (indent + 2)
             try:
-                print "%s%s:"%(
-                    ' '*indent, self.__class__.__name__)
-                print "%sfrom DistributedObject doId:%s, parent:%s, zone:%s"%(
-                    spaces,
-                    self.doId, self.parentId, self.zoneId),
-                flags=[]
+                print("%s%s:" % (' ' * indent, self.__class__.__name__))
+
+                flags = []
                 if self.__generated:
                     flags.append("generated")
                 if self.air == None:
                     flags.append("deleted")
+
+                flagStr = ""
                 if len(flags):
-                    print "(%s)"%(" ".join(flags),),
-                print
-            except Exception, e: print "%serror printing status"%(spaces,), e
+                    flagStr = " (%s)" % (" ".join(flags))
+
+                print("%sfrom DistributedObject doId:%s, parent:%s, zone:%s%s" % (
+                    spaces, self.doId, self.parentId, self.zoneId, flagStr))
+            except Exception as e:
+                print("%serror printing status %s" % (spaces, e))
 
     def getDeleteEvent(self):
         # this is sent just before we get deleted
@@ -347,16 +349,16 @@ class DistributedObjectAI(DistributedObjectBase):
             self.air.sendUpdate(self, fieldName, args)
 
     def GetPuppetConnectionChannel(self, doId):
-        return doId + (1L << 32)
+        return doId + (1 << 32)
 
     def GetAccountConnectionChannel(self, doId):
-        return doId + (3L << 32)
+        return doId + (3 << 32)
 
     def GetAccountIDFromChannelCode(self, channel):
         return channel >> 32
 
     def GetAvatarIDFromChannelCode(self, channel):
-        return channel & 0xffffffffL
+        return channel & 0xffffffff
 
     def sendUpdateToAvatarId(self, avId, fieldName, args):
         assert self.notify.debugStateCall(self)

+ 6 - 7
direct/src/distributed/DistributedObjectBase.py

@@ -22,14 +22,13 @@ class DistributedObjectBase(DirectObject):
             """
             print out "doId(parentId, zoneId) className"
             """
-            spaces=' '*(indent+2)
+            spaces = ' ' * (indent + 2)
             try:
-                print "%s%s:"%(
-                    ' '*indent, self.__class__.__name__)
-                print "%sfrom DistributedObject doId:%s, parent:%s, zone:%s"%(
-                    spaces,
-                    self.doId, self.parentId, self.zoneId),
-            except Exception, e: print "%serror printing status"%(spaces,), e
+                print("%s%s:" % (' ' * indent, self.__class__.__name__))
+                print("%sfrom DistributedObject doId:%s, parent:%s, zone:%s" % (
+                    spaces, self.doId, self.parentId, self.zoneId))
+            except Exception as e:
+                print("%serror printing status %s" % (spaces, e))
 
     def getLocation(self):
         try:

+ 1 - 1
direct/src/distributed/DistributedObjectGlobalAI.py

@@ -1,5 +1,5 @@
 
-from DistributedObjectAI import DistributedObjectAI
+from .DistributedObjectAI import DistributedObjectAI
 from direct.directnotify.DirectNotifyGlobal import directNotify
 
 

+ 1 - 1
direct/src/distributed/DistributedObjectGlobalUD.py

@@ -1,6 +1,6 @@
 
 
-from DistributedObjectUD import DistributedObjectUD
+from .DistributedObjectUD import DistributedObjectUD
 from direct.directnotify.DirectNotifyGlobal import directNotify
 
 import sys

+ 12 - 10
direct/src/distributed/DistributedObjectOV.py

@@ -40,22 +40,24 @@ class DistributedObjectOV(DistributedObjectBase):
             print out "doId(parentId, zoneId) className"
                 and conditionally show generated, disabled
             """
-            spaces=' '*(indent+2)
+            spaces = ' ' * (indent + 2)
             try:
-                print "%s%s:"%(
-                    ' '*indent, self.__class__.__name__)
-                print "%sfrom DistributedObjectOV doId:%s, parent:%s, zone:%s"%(
-                    spaces,
-                    self.doId, self.parentId, self.zoneId),
-                flags=[]
+                print("%s%s:" % (' ' * indent, self.__class__.__name__))
+
+                flags = []
                 if self.activeState == ESGenerated:
                     flags.append("generated")
                 if self.activeState < ESGenerating:
                     flags.append("disabled")
+
+                flagStr = ""
                 if len(flags):
-                    print "(%s)"%(" ".join(flags),),
-                print
-            except Exception, e: print "%serror printing status"%(spaces,), e
+                    flagStr = " (%s)" % (" ".join(flags))
+
+                print("%sfrom DistributedObjectOV doId:%s, parent:%s, zone:%s%s" % (
+                    spaces, self.doId, self.parentId, self.zoneId, flagStr))
+            except Exception as e:
+                print("%serror printing status %s" % (spaces, e))
 
 
     def getDelayDeleteCount(self):

+ 14 - 12
direct/src/distributed/DistributedObjectUD.py

@@ -54,24 +54,26 @@ class DistributedObjectUD(DistributedObjectBase):
         def status(self, indent=0):
             """
             print out doId(parentId, zoneId) className
-                and conditionally show generated, disabled, neverDisable,
-                or cachable
+                and conditionally show generated or deleted
             """
             spaces = ' ' * (indent + 2)
             try:
-                print "%s%s:" % (' ' * indent, self.__class__.__name__)
-                print ("%sfrom "
-                       "DistributedObject doId:%s, parent:%s, zone:%s" %
-                       (spaces, self.doId, self.parentId, self.zoneId)),
+                print("%s%s:" % (' ' * indent, self.__class__.__name__))
+
                 flags = []
                 if self.__generated:
                     flags.append("generated")
                 if self.air == None:
                     flags.append("deleted")
+
+                flagStr = ""
                 if len(flags):
-                    print "(%s)" % (" ".join(flags),),
-                print
-            except Exception, e: print "%serror printing status" % (spaces,), e
+                    flagStr = " (%s)" % (" ".join(flags))
+
+                print("%sfrom DistributedObject doId:%s, parent:%s, zone:%s%s" % (
+                    spaces, self.doId, self.parentId, self.zoneId, flagStr))
+            except Exception as e:
+                print("%serror printing status %s" % (spaces, e))
 
     def getDeleteEvent(self):
         # this is sent just before we get deleted
@@ -267,16 +269,16 @@ class DistributedObjectUD(DistributedObjectBase):
             self.air.sendUpdate(self, fieldName, args)
 
     def GetPuppetConnectionChannel(self, doId):
-        return doId + (1L << 32)
+        return doId + (1 << 32)
 
     def GetAccountConnectionChannel(self, doId):
-        return doId + (3L << 32)
+        return doId + (3 << 32)
 
     def GetAccountIDFromChannelCode(self, channel):
         return channel >> 32
 
     def GetAvatarIDFromChannelCode(self, channel):
-        return channel & 0xffffffffL
+        return channel & 0xffffffff
 
     def sendUpdateToAvatarId(self, avId, fieldName, args):
         assert self.notify.debugStateCall(self)

+ 3 - 3
direct/src/distributed/DistributedSmoothNode.py

@@ -1,9 +1,9 @@
 """DistributedSmoothNode module: contains the DistributedSmoothNode class"""
 
 from pandac.PandaModules import *
-from ClockDelta import *
-import DistributedNode
-import DistributedSmoothNodeBase
+from .ClockDelta import *
+from . import DistributedNode
+from . import DistributedSmoothNodeBase
 from direct.task.Task import cont
 
 # This number defines our tolerance for out-of-sync telemetry packets.

+ 2 - 2
direct/src/distributed/DistributedSmoothNodeAI.py

@@ -1,5 +1,5 @@
-import DistributedNodeAI
-import DistributedSmoothNodeBase
+from . import DistributedNodeAI
+from . import DistributedSmoothNodeBase
 
 class DistributedSmoothNodeAI(DistributedNodeAI.DistributedNodeAI,
                               DistributedSmoothNodeBase.DistributedSmoothNodeBase):

+ 1 - 1
direct/src/distributed/DistributedSmoothNodeBase.py

@@ -1,6 +1,6 @@
 """DistributedSmoothNodeBase module: contains the DistributedSmoothNodeBase class"""
 
-from ClockDelta import *
+from .ClockDelta import *
 from direct.task import Task
 from direct.showbase.PythonUtil import randFloat, Enum
 from panda3d.direct import CDistributedSmoothNodeBase

+ 14 - 14
direct/src/distributed/DoCollectionManager.py

@@ -117,29 +117,29 @@ class DoCollectionManager:
         return 1
 
     def dosByDistance(self):
-        objs = self.doId2do.values()
+        objs = list(self.doId2do.values())
         objs.sort(cmp=self._compareDistance)
         return objs
 
     def doByDistance(self):
         objs = self.dosByDistance()
         for obj in objs:
-            print '%s\t%s\t%s' % (obj.doId, self._getDistanceFromLA(obj),
-                                  obj.dclass.getName())
+            print('%s\t%s\t%s' % (obj.doId, self._getDistanceFromLA(obj),
+                                  obj.dclass.getName()))
 
     if __debug__:
         def printObjects(self):
             format="%10s %10s %10s %30s %20s"
             title=format%("parentId", "zoneId", "doId", "dclass", "name")
-            print title
-            print '-'*len(title)
+            print(title)
+            print('-'*len(title))
             for distObj in self.doId2do.values():
-                print format%(
+                print(format%(
                     distObj.__dict__.get("parentId"),
                     distObj.__dict__.get("zoneId"),
                     distObj.__dict__.get("doId"),
                     distObj.dclass.getName(),
-                    distObj.__dict__.get("name"))
+                    distObj.__dict__.get("name")))
 
     def _printObjects(self, table):
         class2count = {}
@@ -148,14 +148,14 @@ class DoCollectionManager:
             class2count.setdefault(className, 0)
             class2count[className] += 1
         count2classes = invertDictLossless(class2count)
-        counts = count2classes.keys()
+        counts = list(count2classes.keys())
         counts.sort()
         counts.reverse()
         for count in counts:
             count2classes[count].sort()
             for name in count2classes[count]:
-                print '%s %s' % (count, name)
-        print ''
+                print('%s %s' % (count, name))
+        print('')
 
     def _returnObjects(self, table):
         class2count = {}
@@ -165,7 +165,7 @@ class DoCollectionManager:
             class2count.setdefault(className, 0)
             class2count[className] += 1
         count2classes = invertDictLossless(class2count)
-        counts = count2classes.keys()
+        counts = list(count2classes.keys())
         counts.sort()
         counts.reverse()
         for count in counts:
@@ -189,12 +189,12 @@ class DoCollectionManager:
 
     def printObjectCount(self):
         # print object counts by distributed object type
-        print '==== OBJECT COUNT ===='
+        print('==== OBJECT COUNT ====')
         if self.hasOwnerView():
-            print '== doId2do'
+            print('== doId2do')
         self._printObjects(self.getDoTable(ownerView=False))
         if self.hasOwnerView():
-            print '== doId2ownerView'
+            print('== doId2ownerView')
             self._printObjects(self.getDoTable(ownerView=True))
 
     def getDoList(self, parentId, zoneId=None, classType=None):

+ 26 - 26
direct/src/distributed/DoInterestManager.py

@@ -8,10 +8,10 @@ p.s. A great deal of this code is just code moved from ClientRepository.py.
 """
 
 from pandac.PandaModules import *
-from MsgTypes import *
+from .MsgTypes import *
 from direct.showbase.PythonUtil import *
 from direct.showbase import DirectObject
-from PyDatagram import PyDatagram
+from .PyDatagram import PyDatagram
 from direct.directnotify.DirectNotifyGlobal import directNotify
 import types
 from direct.showbase.PythonUtil import report
@@ -184,8 +184,8 @@ class DoInterestManager(DirectObject.DirectObject):
         DoInterestManager._interests[handle] = InterestState(
             description, InterestState.StateActive, contextId, event, parentId, zoneIdList, self._completeEventCount)
         if self.__verbose():
-            print 'CR::INTEREST.addInterest(handle=%s, parentId=%s, zoneIdList=%s, description=%s, event=%s)' % (
-                handle, parentId, zoneIdList, description, event)
+            print('CR::INTEREST.addInterest(handle=%s, parentId=%s, zoneIdList=%s, description=%s, event=%s)' % (
+                handle, parentId, zoneIdList, description, event))
         self._sendAddInterest(handle, contextId, parentId, zoneIdList, description)
         if event:
             messenger.send(self._getAddInterestEvent(), [event])
@@ -218,8 +218,8 @@ class DoInterestManager(DirectObject.DirectObject):
         DoInterestManager._interests[handle] = InterestState(
             description, InterestState.StateActive, 0, None, parentId, zoneIdList, self._completeEventCount, True)
         if self.__verbose():
-            print 'CR::INTEREST.addInterest(handle=%s, parentId=%s, zoneIdList=%s, description=%s)' % (
-                handle, parentId, zoneIdList, description)
+            print('CR::INTEREST.addInterest(handle=%s, parentId=%s, zoneIdList=%s, description=%s)' % (
+                handle, parentId, zoneIdList, description))
         assert self.printInterestsIfDebug()
         return InterestHandle(handle)
 
@@ -266,8 +266,8 @@ class DoInterestManager(DirectObject.DirectObject):
                 if not event:
                     self._considerRemoveInterest(handle)
                 if self.__verbose():
-                    print 'CR::INTEREST.removeInterest(handle=%s, event=%s)' % (
-                        handle, event)
+                    print('CR::INTEREST.removeInterest(handle=%s, event=%s)' % (
+                        handle, event))
         else:
             DoInterestManager.notify.warning(
                 "removeInterest: handle not found: %s" % (handle))
@@ -302,7 +302,7 @@ class DoInterestManager(DirectObject.DirectObject):
                 intState.state = InterestState.StatePendingDel
                 self._considerRemoveInterest(handle)
                 if self.__verbose():
-                    print 'CR::INTEREST.removeAutoInterest(handle=%s)' % (handle)
+                    print('CR::INTEREST.removeAutoInterest(handle=%s)' % (handle))
         else:
             DoInterestManager.notify.warning(
                 "removeInterest: handle not found: %s" % (handle))
@@ -357,8 +357,8 @@ class DoInterestManager(DirectObject.DirectObject):
             DoInterestManager._interests[handle].addEvent(event)
 
             if self.__verbose():
-                print 'CR::INTEREST.alterInterest(handle=%s, parentId=%s, zoneIdList=%s, description=%s, event=%s)' % (
-                    handle, parentId, zoneIdList, description, event)
+                print('CR::INTEREST.alterInterest(handle=%s, parentId=%s, zoneIdList=%s, description=%s, event=%s)' % (
+                    handle, parentId, zoneIdList, description, event))
             self._sendAddInterest(handle, contextId, parentId, zoneIdList, description, action='modify')
             exists = True
             assert self.printInterestsIfDebug()
@@ -445,24 +445,24 @@ class DoInterestManager(DirectObject.DirectObject):
                 DoInterestManager._debug_maxDescriptionLen, len(description))
 
         def printInterestHistory(self):
-            print "***************** Interest History *************"
+            print("***************** Interest History *************")
             format = '%9s %' + str(DoInterestManager._debug_maxDescriptionLen) + 's %6s %6s %9s %s'
-            print format % (
+            print(format % (
                 "Action", "Description", "Handle", "Context", "ParentId",
-                "ZoneIdList")
+                "ZoneIdList"))
             for i in DoInterestManager._debug_interestHistory:
-                print format % tuple(i)
-            print "Note: interests with a Context of 0 do not get" \
-                " done/finished notices."
+                print(format % tuple(i))
+            print("Note: interests with a Context of 0 do not get" \
+                " done/finished notices.")
 
         def printInterestSets(self):
-            print "******************* Interest Sets **************"
+            print("******************* Interest Sets **************")
             format = '%6s %' + str(DoInterestManager._debug_maxDescriptionLen) + 's %11s %11s %8s %8s %8s'
-            print format % (
+            print(format % (
                 "Handle", "Description",
                 "ParentId", "ZoneIdList",
                 "State", "Context",
-                "Event")
+                "Event"))
             for id, state in DoInterestManager._interests.items():
                 if len(state.events) == 0:
                     event = ''
@@ -470,11 +470,11 @@ class DoInterestManager(DirectObject.DirectObject):
                     event = state.events[0]
                 else:
                     event = state.events
-                print format % (id, state.desc,
+                print(format % (id, state.desc,
                                 state.parentId, state.zoneIdList,
                                 state.state, state.context,
-                                event)
-            print "************************************************"
+                                event))
+            print("************************************************")
 
         def printInterests(self):
             self.printInterestHistory()
@@ -492,7 +492,7 @@ class DoInterestManager(DirectObject.DirectObject):
         """
         assert DoInterestManager.notify.debugCall()
         if __debug__:
-            if isinstance(zoneIdList, types.ListType):
+            if isinstance(zoneIdList, list):
                 zoneIdList.sort()
             if action is None:
                 action = 'add'
@@ -507,7 +507,7 @@ class DoInterestManager(DirectObject.DirectObject):
         datagram.addUint16(handle)
         datagram.addUint32(contextId)
         datagram.addUint32(parentId)
-        if isinstance(zoneIdList, types.ListType):
+        if isinstance(zoneIdList, list):
             vzl = list(zoneIdList)
             vzl.sort()
             uniqueElements(vzl)
@@ -585,7 +585,7 @@ class DoInterestManager(DirectObject.DirectObject):
         handle = di.getUint16()
         contextId = di.getUint32()
         if self.__verbose():
-            print 'CR::INTEREST.interestDone(handle=%s)' % handle
+            print('CR::INTEREST.interestDone(handle=%s)' % handle)
         DoInterestManager.notify.debug(
             "handleInterestDoneMessage--> Received handle %s, context %s" % (
             handle, contextId))

+ 1 - 1
direct/src/distributed/GridChild.py

@@ -106,7 +106,7 @@ class GridChild:
                 self._gridInterests[gridDoId] = [None,zoneId]
 
     def getGridInterestIds(self):
-        return self._gridInterests.keys()
+        return list(self._gridInterests.keys())
 
     def getGridInterestZoneId(self,gridDoId):
         return self._gridInterests.get(gridDoId,[None,None])[1]

+ 6 - 2
direct/src/distributed/NetMessenger.py

@@ -1,10 +1,14 @@
 
-from cPickle import dumps, loads
-
 from direct.directnotify import DirectNotifyGlobal
 from direct.distributed.PyDatagram import PyDatagram
 from direct.showbase.Messenger import Messenger
 
+import sys
+if sys.version_info >= (3, 0):
+    from pickle import dumps, loads
+else:
+    from cPickle import dumps, loads
+
 
 # Messages do not need to be in the MESSAGE_TYPES list.
 # This is just an optimization.  If the message is found

+ 2 - 2
direct/src/distributed/OldClientRepository.py

@@ -1,6 +1,6 @@
 """OldClientRepository module: contains the OldClientRepository class"""
 
-from ClientRepositoryBase import *
+from .ClientRepositoryBase import *
 
 class OldClientRepository(ClientRepositoryBase):
     """
@@ -126,7 +126,7 @@ class OldClientRepository(ClientRepositoryBase):
 
     def handleDatagram(self, di):
         if self.notify.getDebug():
-            print "ClientRepository received datagram:"
+            print("ClientRepository received datagram:")
             di.getDatagram().dumpHex(ostream)
 
         msgType = self.getMsgType()

+ 2 - 2
direct/src/distributed/ParentMgr.py

@@ -2,7 +2,7 @@
 
 from direct.directnotify import DirectNotifyGlobal
 from direct.showbase.PythonUtil import isDefaultValue
-import types
+
 
 class ParentMgr:
     # This is now used on the AI as well.
@@ -90,7 +90,7 @@ class ParentMgr:
         if isDefaultValue(token):
             self.notify.error('parent token (for %s) cannot be a default value (%s)' % (repr(parent), token))
 
-        if type(token) is types.IntType:
+        if type(token) is int:
             if token > 0xFFFFFFFF:
                 self.notify.error('parent token %s (for %s) is out of uint32 range' % (token, repr(parent)))
 

+ 6 - 8
direct/src/distributed/ServerRepository.py

@@ -5,9 +5,7 @@ from direct.distributed.MsgTypesCMU import *
 from direct.task import Task
 from direct.directnotify import DirectNotifyGlobal
 from direct.distributed.PyDatagram import PyDatagram
-from direct.distributed.PyDatagramIterator import PyDatagramIterator
-import time
-import types
+
 
 class ServerRepository:
 
@@ -153,7 +151,7 @@ class ServerRepository:
         for client in flush:
             client.connection.flush()
 
-        return task.again
+        return Task.again
 
     def setTcpHeaderSize(self, headerSize):
         """Sets the header size of TCP packets.  At the present, legal
@@ -299,7 +297,7 @@ class ServerRepository:
             retVal = self.qcl.getNewConnection(rendezvous, netAddress,
                                                newConnection)
             if not retVal:
-                return task.cont
+                return Task.cont
 
             # Crazy dereferencing
             newConnection = newConnection.p()
@@ -321,13 +319,13 @@ class ServerRepository:
             self.lastConnection = newConnection
             self.sendDoIdRange(client)
 
-        return task.cont
+        return Task.cont
 
     def readerPollUntilEmpty(self, task):
         """ continuously polls for new messages on the server """
         while self.readerPollOnce():
             pass
-        return task.cont
+        return Task.cont
 
     def readerPollOnce(self):
         """ checks for available messages to the server """
@@ -691,7 +689,7 @@ class ServerRepository:
         for client in self.clientsByConnection.values():
             if not self.qcr.isConnectionOk(client.connection):
                 self.handleClientDisconnect(client)
-        return task.cont
+        return Task.cont
 
     def sendToZoneExcept(self, zoneId, datagram, exceptionList):
         """sends a message to everyone who has interest in the

+ 1 - 1
direct/src/distributed/TimeManagerAI.py

@@ -18,6 +18,6 @@ class TimeManagerAI(DistributedObjectAI.DistributedObjectAI):
         """
         timestamp = globalClockDelta.getRealNetworkTime(bits=32)
         requesterId = self.air.getAvatarIdFromSender()
-        print "requestServerTime from %s" % (requesterId)
+        print("requestServerTime from %s" % (requesterId))
         self.sendUpdateToAvatarId(requesterId, "serverTime",
                                   [context, timestamp])

+ 4 - 1
direct/src/doc/howto.adjust

@@ -52,7 +52,10 @@ of the slider to change settings.  Click on:
 
 You can pack multiple sliders into a single panel:
 
-from Tkinter import *
+if sys.version_info >= (3, 0):
+    from tkinter import *
+else:
+    from Tkinter import *
 
 def func1(x):
    print '1:', x

+ 19 - 16
direct/src/extensions_native/CInterval_extensions.py

@@ -63,14 +63,17 @@ def popupControls(self, tl = None):
         import math
         # Don't use a regular import, to prevent ModuleFinder from picking
         # it up as a dependency when building a .p3d package.
-        import importlib
+        import importlib, sys
         EntryScale = importlib.import_module('direct.tkwidgets.EntryScale')
-        Tkinter = importlib.import_module('Tkinter')
+        if sys.version_info >= (3, 0):
+            tkinter = importlib.import_module('tkinter')
+        else:
+            tkinter = importlib.import_module('Tkinter')
 
         if tl == None:
-            tl = Tkinter.Toplevel()
+            tl = tkinter.Toplevel()
             tl.title('Interval Controls')
-        outerFrame = Tkinter.Frame(tl)
+        outerFrame = tkinter.Frame(tl)
         def entryScaleCommand(t, s=self):
             s.setT(t)
             s.pause()
@@ -79,8 +82,8 @@ def popupControls(self, tl = None):
             min = 0, max = math.floor(self.getDuration() * 100) / 100,
             command = entryScaleCommand)
         es.set(self.getT(), fCommand = 0)
-        es.pack(expand = 1, fill = Tkinter.X)
-        bf = Tkinter.Frame(outerFrame)
+        es.pack(expand = 1, fill = tkinter.X)
+        bf = tkinter.Frame(outerFrame)
         # Jump to start and end
         def toStart(s=self, es=es):
             s.setT(0.0)
@@ -88,23 +91,23 @@ def popupControls(self, tl = None):
         def toEnd(s=self):
             s.setT(s.getDuration())
             s.pause()
-        jumpToStart = Tkinter.Button(bf, text = '<<', command = toStart)
+        jumpToStart = tkinter.Button(bf, text = '<<', command = toStart)
         # Stop/play buttons
         def doPlay(s=self, es=es):
             s.resume(es.get())
 
-        stop = Tkinter.Button(bf, text = 'Stop',
+        stop = tkinter.Button(bf, text = 'Stop',
                       command = lambda s=self: s.pause())
-        play = Tkinter.Button(
+        play = tkinter.Button(
             bf, text = 'Play',
             command = doPlay)
-        jumpToEnd = Tkinter.Button(bf, text = '>>', command = toEnd)
-        jumpToStart.pack(side = Tkinter.LEFT, expand = 1, fill = Tkinter.X)
-        play.pack(side = Tkinter.LEFT, expand = 1, fill = Tkinter.X)
-        stop.pack(side = Tkinter.LEFT, expand = 1, fill = Tkinter.X)
-        jumpToEnd.pack(side = Tkinter.LEFT, expand = 1, fill = Tkinter.X)
-        bf.pack(expand = 1, fill = Tkinter.X)
-        outerFrame.pack(expand = 1, fill = Tkinter.X)
+        jumpToEnd = tkinter.Button(bf, text = '>>', command = toEnd)
+        jumpToStart.pack(side = tkinter.LEFT, expand = 1, fill = tkinter.X)
+        play.pack(side = tkinter.LEFT, expand = 1, fill = tkinter.X)
+        stop.pack(side = tkinter.LEFT, expand = 1, fill = tkinter.X)
+        jumpToEnd.pack(side = tkinter.LEFT, expand = 1, fill = tkinter.X)
+        bf.pack(expand = 1, fill = tkinter.X)
+        outerFrame.pack(expand = 1, fill = tkinter.X)
         # Add function to update slider during setT calls
         def update(t, es=es):
             es.set(t, fCommand = 0)

+ 2 - 2
direct/src/extensions_native/NodePath_extensions.py

@@ -690,7 +690,7 @@ def subdivideCollisions(self, numSolidsInLeaves):
                 # this CollisionNode doesn't need to be split
                 continue
             solids = []
-            for i in xrange(numSolids):
+            for i in range(numSolids):
                 solids.append(node.getSolid(i))
             # recursively subdivide the solids into a spatial binary tree
             solidTree = self.r_subdivideCollisions(solids, numSolidsInLeaves)
@@ -743,7 +743,7 @@ def r_subdivideCollisions(self, solids, numSolidsInLeaves):
                 midY += maxExtent
         if extentZ < (maxExtent * .75) or extentZ > (maxExtent * 1.25):
                 midZ += maxExtent
-        for i in xrange(len(solids)):
+        for i in range(len(solids)):
                 origin = origins[i]
                 x = origin.getX(); y = origin.getY(); z = origin.getZ()
                 if x < midX:

+ 1 - 2
direct/src/extensions_native/extension_native_helpers.py

@@ -1,7 +1,6 @@
-###  Tools
 __all__ = ["Dtool_ObjectToDict", "Dtool_funcToMethod"]
 
-import imp, sys, os
+import sys
 
 def Dtool_ObjectToDict(cls, name, obj):
     cls.DtoolClassDict[name] = obj

+ 1 - 1
direct/src/filter/CommonFilters.py

@@ -15,7 +15,7 @@ clunky approach.  - Josh
 
 """
 
-from FilterManager import FilterManager
+from .FilterManager import FilterManager
 from panda3d.core import LVecBase4, LPoint2
 from panda3d.core import Filename
 from panda3d.core import AuxBitplaneAttrib

+ 7 - 10
direct/src/fsm/ClassicFSM.py

@@ -10,18 +10,15 @@ existing code.  New code should use the FSM module instead.
 
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.showbase.DirectObject import DirectObject
-import types
 import weakref
 
 if __debug__:
-    _debugFsms={}
+    _debugFsms = {}
     def printDebugFsmList():
         global _debugFsms
-        keys=_debugFsms.keys()
-        keys.sort()
-        for k in keys:
-            print k, _debugFsms[k]()
-    __builtins__['debugFsmList']=printDebugFsmList
+        for k in sorted(_debugFsms.keys()):
+            print("%s %s" % (k, _debugFsms[k]()))
+    __builtins__['debugFsmList'] = printDebugFsmList
 
 class ClassicFSM(DirectObject):
     """
@@ -123,7 +120,7 @@ class ClassicFSM(DirectObject):
         self.__name = name
 
     def getStates(self):
-        return self.__states.values()
+        return list(self.__states.values())
 
     def setStates(self, states):
         """setStates(self, State[])"""
@@ -251,7 +248,7 @@ class ClassicFSM(DirectObject):
                                (self.__name))
             self.__currentState = self.__initialState
 
-        if isinstance(aStateName, types.StringType):
+        if isinstance(aStateName, str):
             aState = self.getStateNamed(aStateName)
         else:
             # Allow the caller to pass in a state in itself, not just
@@ -342,7 +339,7 @@ class ClassicFSM(DirectObject):
                                (self.__name))
             self.__currentState = self.__initialState
 
-        if isinstance(aStateName, types.StringType):
+        if isinstance(aStateName, str):
             aState = self.getStateNamed(aStateName)
         else:
             # Allow the caller to pass in a state in itself, not just

+ 5 - 5
direct/src/fsm/FSM.py

@@ -9,7 +9,7 @@ from direct.showbase.DirectObject import DirectObject
 from direct.directnotify import DirectNotifyGlobal
 from direct.showbase import PythonUtil
 from direct.stdpy.threading import RLock
-import types
+
 
 class FSMException(Exception):
     pass
@@ -238,7 +238,7 @@ class FSM(DirectObject):
 
         self.fsmLock.acquire()
         try:
-            assert isinstance(request, types.StringTypes)
+            assert isinstance(request, str)
             self.notify.debug("%s.forceTransition(%s, %s" % (
                 self.name, request, str(args)[1:]))
 
@@ -266,7 +266,7 @@ class FSM(DirectObject):
 
         self.fsmLock.acquire()
         try:
-            assert isinstance(request, types.StringTypes)
+            assert isinstance(request, str)
             self.notify.debug("%s.demand(%s, %s" % (
                 self.name, request, str(args)[1:]))
             if not self.state:
@@ -305,14 +305,14 @@ class FSM(DirectObject):
 
         self.fsmLock.acquire()
         try:
-            assert isinstance(request, types.StringTypes)
+            assert isinstance(request, str)
             self.notify.debug("%s.request(%s, %s" % (
                 self.name, request, str(args)[1:]))
 
             filter = self.getCurrentFilter()
             result = list(filter(request, args))
             if result:
-                if isinstance(result, types.StringTypes):
+                if isinstance(result, str):
                     # If the return value is a string, it's just the name
                     # of the state.  Wrap it in a tuple for consistency.
                     result = (result,) + args

+ 3 - 3
direct/src/fsm/FourState.py

@@ -6,8 +6,8 @@ __all__ = ['FourState']
 
 from direct.directnotify import DirectNotifyGlobal
 #import DistributedObject
-import ClassicFSM
-import State
+from . import ClassicFSM
+from . import State
 
 
 class FourState:
@@ -122,7 +122,7 @@ class FourState:
             }
         self.stateIndex = 0
         self.fsm = ClassicFSM.ClassicFSM('FourState',
-                           self.states.values(),
+                           list(self.states.values()),
                            # Initial State
                            names[0],
                            # Final State

+ 3 - 3
direct/src/fsm/FourStateAI.py

@@ -6,8 +6,8 @@ __all__ = ['FourStateAI']
 
 from direct.directnotify import DirectNotifyGlobal
 #import DistributedObjectAI
-import ClassicFSM
-import State
+from . import ClassicFSM
+from . import State
 from direct.task import Task
 
 
@@ -128,7 +128,7 @@ class FourStateAI:
                            [names[1]]),
             }
         self.fsm = ClassicFSM.ClassicFSM('FourState',
-                           self.states.values(),
+                           list(self.states.values()),
                            # Initial State
                            names[0],
                            # Final State

+ 20 - 21
direct/src/fsm/SampleFSM.py

@@ -2,9 +2,8 @@
 
 __all__ = ['ClassicStyle', 'NewStyle', 'ToonEyes']
 
-import FSM
+from . import FSM
 from direct.task import Task
-import string
 
 
 class ClassicStyle(FSM.FSM):
@@ -19,61 +18,61 @@ class ClassicStyle(FSM.FSM):
             }
 
     def enterRed(self):
-        print "enterRed(self, '%s', '%s')" % (self.oldState, self.newState)
+        print("enterRed(self, '%s', '%s')" % (self.oldState, self.newState))
 
     def exitRed(self):
-        print "exitRed(self, '%s', '%s')" % (self.oldState, self.newState)
+        print("exitRed(self, '%s', '%s')" % (self.oldState, self.newState))
 
     def enterYellow(self):
-        print "enterYellow(self, '%s', '%s')" % (self.oldState, self.newState)
+        print("enterYellow(self, '%s', '%s')" % (self.oldState, self.newState))
 
     def exitYellow(self):
-        print "exitYellow(self, '%s', '%s')" % (self.oldState, self.newState)
+        print("exitYellow(self, '%s', '%s')" % (self.oldState, self.newState))
 
     def enterGreen(self):
-        print "enterGreen(self, '%s', '%s')" % (self.oldState, self.newState)
+        print("enterGreen(self, '%s', '%s')" % (self.oldState, self.newState))
 
     def exitGreen(self):
-        print "exitGreen(self, '%s', '%s')" % (self.oldState, self.newState)
+        print("exitGreen(self, '%s', '%s')" % (self.oldState, self.newState))
 
 
 class NewStyle(FSM.FSM):
 
     def enterRed(self):
-        print "enterRed(self, '%s', '%s')" % (self.oldState, self.newState)
+        print("enterRed(self, '%s', '%s')" % (self.oldState, self.newState))
 
     def filterRed(self, request, args):
-        print "filterRed(self, '%s', %s)" % (request, args)
+        print("filterRed(self, '%s', %s)" % (request, args))
         if request == 'advance':
             return 'Green'
         return self.defaultFilter(request, args)
 
     def exitRed(self):
-        print "exitRed(self, '%s', '%s')" % (self.oldState, self.newState)
+        print("exitRed(self, '%s', '%s')" % (self.oldState, self.newState))
 
     def enterYellow(self):
-        print "enterYellow(self, '%s', '%s')" % (self.oldState, self.newState)
+        print("enterYellow(self, '%s', '%s')" % (self.oldState, self.newState))
 
     def filterYellow(self, request, args):
-        print "filterYellow(self, '%s', %s)" % (request, args)
+        print("filterYellow(self, '%s', %s)" % (request, args))
         if request == 'advance':
             return 'Red'
         return self.defaultFilter(request, args)
 
     def exitYellow(self):
-        print "exitYellow(self, '%s', '%s')" % (self.oldState, self.newState)
+        print("exitYellow(self, '%s', '%s')" % (self.oldState, self.newState))
 
     def enterGreen(self):
-        print "enterGreen(self, '%s', '%s')" % (self.oldState, self.newState)
+        print("enterGreen(self, '%s', '%s')" % (self.oldState, self.newState))
 
     def filterGreen(self, request, args):
-        print "filterGreen(self, '%s', %s)" % (request, args)
+        print("filterGreen(self, '%s', %s)" % (request, args))
         if request == 'advance':
             return 'Yellow'
         return self.defaultFilter(request, args)
 
     def exitGreen(self):
-        print "exitGreen(self, '%s', '%s')" % (self.oldState, self.newState)
+        print("exitGreen(self, '%s', '%s')" % (self.oldState, self.newState))
 
 
 class ToonEyes(FSM.FSM):
@@ -88,14 +87,14 @@ class ToonEyes(FSM.FSM):
     def defaultFilter(self, request, args):
         # The default filter accepts any direct state request (these
         # start with a capital letter).
-        if request[0] in string.uppercase:
+        if request[0].isupper():
             return request
 
         # Unexpected command requests are quietly ignored.
         return None
 
     def enterOpen(self):
-        print "swap in eyes open model"
+        print("swap in eyes open model")
 
     def filterOpen(self, request, args):
         if request == 'blink':
@@ -109,7 +108,7 @@ class ToonEyes(FSM.FSM):
         return Task.done
 
     def enterClosed(self):
-        print "swap in eyes closed model"
+        print("swap in eyes closed model")
 
     def filterClosed(self, request, args):
         if request == 'unblink':
@@ -117,7 +116,7 @@ class ToonEyes(FSM.FSM):
         return self.defaultFilter(request, args)
 
     def enterSurprised(self):
-        print "swap in eyes surprised model"
+        print("swap in eyes surprised model")
 
     def enterOff(self):
         taskMgr.remove(self.__unblinkName)

+ 2 - 2
direct/src/fsm/State.py

@@ -199,7 +199,7 @@ class State(DirectObject):
         self.__enterChildren(argList)
 
         if (self.__enterFunc != None):
-            apply(self.__enterFunc, argList)
+            self.__enterFunc(*argList)
 
     def exit(self, argList=[]):
         """
@@ -210,7 +210,7 @@ class State(DirectObject):
 
         # call exit function if it exists
         if (self.__exitFunc != None):
-            apply(self.__exitFunc, argList)
+            self.__exitFunc(*argList)
 
     def __str__(self):
         return "State: name = %s, enter = %s, exit = %s, trans = %s, children = %s" %\

+ 0 - 1
direct/src/fsm/StateData.py

@@ -5,7 +5,6 @@ __all__ = ['StateData']
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.showbase.DirectObject import DirectObject
 
-from direct.directnotify import DirectNotifyGlobal
 
 class StateData(DirectObject):
     """

+ 5 - 6
direct/src/fsm/StatePush.py

@@ -16,8 +16,8 @@ class PushesStateChanges:
 
     def destroy(self):
         if len(self._subscribers) != 0:
-            raise '%s object still has subscribers in destroy(): %s' % (
-                self.__class__.__name__, self._subscribers)
+            raise Exception('%s object still has subscribers in destroy(): %s' % (
+                self.__class__.__name__, self._subscribers))
         del self._subscribers
         del self._value
 
@@ -154,7 +154,7 @@ class ReceivesMultipleStateChanges:
         self._source2key = {}
 
     def destroy(self):
-        keys = self._key2source.keys()
+        keys = list(self._key2source.keys())
         for key in keys:
             self._unsubscribe(key)
         del self._key2source
@@ -202,15 +202,14 @@ class FunctionCall(ReceivesMultipleStateChanges, PushesStateChanges):
         # the value of arguments that push state
         self._bakedArgs = []
         self._bakedKargs = {}
-        for i in xrange(len(self._args)):
+        for i, arg in enumerate(self._args):
             key = i
-            arg = self._args[i]
             if isinstance(arg, PushesStateChanges):
                 self._bakedArgs.append(arg.getState())
                 self._subscribeTo(arg, key)
             else:
                 self._bakedArgs.append(self._args[i])
-        for key, arg in self._kArgs.iteritems():
+        for key, arg in self._kArgs.items():
             if isinstance(arg, PushesStateChanges):
                 self._bakedKargs[key] = arg.getState()
                 self._subscribeTo(arg, key)

+ 3 - 3
direct/src/gui/DirectButton.py

@@ -3,8 +3,8 @@
 __all__ = ['DirectButton']
 
 from panda3d.core import *
-import DirectGuiGlobals as DGG
-from DirectFrame import *
+from . import DirectGuiGlobals as DGG
+from .DirectFrame import *
 
 class DirectButton(DirectFrame):
     """
@@ -100,7 +100,7 @@ class DirectButton(DirectFrame):
     def commandFunc(self, event):
         if self['command']:
             # Pass any extra args to command
-            apply(self['command'], self['extraArgs'])
+            self['command'](*self['extraArgs'])
 
     def setClickSound(self):
         clickSound = self['clickSound']

+ 1 - 1
direct/src/gui/DirectCheckBox.py

@@ -55,5 +55,5 @@ class DirectCheckBox(DirectButton):
 
         if self['command']:
             # Pass any extra args to command
-            apply(self['command'], [self['isChecked']] + self['extraArgs'])
+            self['command'](*[self['isChecked']] + self['extraArgs'])
 

+ 3 - 3
direct/src/gui/DirectCheckButton.py

@@ -3,8 +3,8 @@
 __all__ = ['DirectCheckButton']
 
 from panda3d.core import *
-from DirectButton import *
-from DirectLabel import *
+from .DirectButton import *
+from .DirectLabel import *
 
 class DirectCheckButton(DirectButton):
     """
@@ -169,7 +169,7 @@ class DirectCheckButton(DirectButton):
 
         if self['command']:
             # Pass any extra args to command
-            apply(self['command'], [self['indicatorValue']] + self['extraArgs'])
+            self['command'](*[self['indicatorValue']] + self['extraArgs'])
 
     def setIndicatorValue(self):
         self.component('indicator').guiItem.setState(self['indicatorValue'])

+ 9 - 9
direct/src/gui/DirectDialog.py

@@ -3,9 +3,9 @@
 __all__ = ['findDialog', 'cleanupDialog', 'DirectDialog', 'OkDialog', 'OkCancelDialog', 'YesNoDialog', 'YesNoCancelDialog', 'RetryCancelDialog']
 
 from panda3d.core import *
-import DirectGuiGlobals as DGG
-from DirectFrame import *
-from DirectButton import *
+from . import DirectGuiGlobals as DGG
+from .DirectFrame import *
+from .DirectButton import *
 import types
 
 def findDialog(uniqueName):
@@ -186,8 +186,8 @@ class DirectDialog(DirectFrame):
         bindList = zip(self.buttonList, self['buttonHotKeyList'],
                        self['buttonValueList'])
         for button, hotKey, value in bindList:
-            if ((type(hotKey) == types.ListType) or
-                (type(hotKey) == types.TupleType)):
+            if ((type(hotKey) == list) or
+                (type(hotKey) == tuple)):
                 for key in hotKey:
                     button.bind('press-' + key + '-', self.buttonCommand,
                                 extraArgs = [value])
@@ -274,12 +274,12 @@ class DirectDialog(DirectFrame):
             scale = self['button_scale']
             # Can either be a Vec3 or a tuple of 3 values
             if (isinstance(scale, Vec3) or
-                (type(scale) == types.ListType) or
-                (type(scale) == types.TupleType)):
+                (type(scale) == list) or
+                (type(scale) == tuple)):
                 sx = scale[0]
                 sz = scale[2]
-            elif ((type(scale) == types.IntType) or
-                  (type(scale) == types.FloatType)):
+            elif ((type(scale) == int) or
+                  (type(scale) == float)):
                 sx = sz = scale
             else:
                 sx = sz = 1

+ 21 - 17
direct/src/gui/DirectEntry.py

@@ -3,10 +3,10 @@
 __all__ = ['DirectEntry']
 
 from panda3d.core import *
-import DirectGuiGlobals as DGG
-from DirectFrame import *
-from OnscreenText import OnscreenText
-import string,types
+from . import DirectGuiGlobals as DGG
+from .DirectFrame import *
+from .OnscreenText import OnscreenText
+import sys
 # import this to make sure it gets pulled into the publish
 import encodings.utf_8
 from direct.showbase.DirectObject import DirectObject
@@ -181,12 +181,12 @@ class DirectEntry(DirectFrame):
     def commandFunc(self, event):
         if self['command']:
             # Pass any extra args to command
-            apply(self['command'], [self.get()] + self['extraArgs'])
+            self['command'](*[self.get()] + self['extraArgs'])
 
     def failedCommandFunc(self, event):
         if self['failedCommand']:
             # Pass any extra args
-            apply(self['failedCommand'], [self.get()] + self['failedExtraArgs'])
+            self['failedCommand'](*[self.get()] + self['failedExtraArgs'])
 
     def autoCapitalizeFunc(self):
         if self['autoCapitalize']:
@@ -198,7 +198,7 @@ class DirectEntry(DirectFrame):
 
     def focusInCommandFunc(self):
         if self['focusInCommand']:
-            apply(self['focusInCommand'], self['focusInExtraArgs'])
+            self['focusInCommand'](*self['focusInExtraArgs'])
         if self['autoCapitalize']:
             self.accept(self.guiItem.getTypeEvent(), self._handleTyping)
             self.accept(self.guiItem.getEraseEvent(), self._handleErasing)
@@ -216,14 +216,13 @@ class DirectEntry(DirectFrame):
         wordSoFar = ''
         # track whether the previous character was part of a word or not
         wasNonWordChar = True
-        for i in xrange(len(name)):
-            character = name[i]
+        for i, character in enumerate(name):
             # test to see if we are between words
             # - Count characters that can't be capitalized as a break between words
             #   This assumes that string.lower and string.upper will return different
             #   values for all unicode letters.
             # - Don't count apostrophes as a break between words
-            if ((string.lower(character) == string.upper(character)) and (character != "'")):
+            if character.lower() == character.upper() and character != "'":
                 # we are between words
                 wordSoFar = ''
                 wasNonWordChar = True
@@ -232,7 +231,7 @@ class DirectEntry(DirectFrame):
                 if wasNonWordChar:
                     # first letter of a word, capitalize it unconditionally;
                     capitalize = True
-                elif (character == string.upper(character) and
+                elif (character == character.upper() and
                       len(self.autoCapitalizeAllowPrefixes) and
                       wordSoFar in self.autoCapitalizeAllowPrefixes):
                     # first letter after one of the prefixes, allow it to be capitalized
@@ -243,9 +242,9 @@ class DirectEntry(DirectFrame):
                     capitalize = True
                 if capitalize:
                     # allow this letter to remain capitalized
-                    character = string.upper(character)
+                    character = character.upper()
                 else:
-                    character = string.lower(character)
+                    character = character.lower()
                 wordSoFar += character
                 wasNonWordChar = False
             capName += character
@@ -253,7 +252,7 @@ class DirectEntry(DirectFrame):
 
     def focusOutCommandFunc(self):
         if self['focusOutCommand']:
-            apply(self['focusOutCommand'], self['focusOutExtraArgs'])
+            self['focusOutCommand'](*self['focusOutExtraArgs'])
         if self['autoCapitalize']:
             self.ignore(self.guiItem.getTypeEvent())
             self.ignore(self.guiItem.getEraseEvent())
@@ -263,11 +262,16 @@ class DirectEntry(DirectFrame):
         does not change the current cursor position.  Also see
         enterText(). """
 
-        self.unicodeText = isinstance(text, types.UnicodeType)
-        if self.unicodeText:
+        if sys.version_info >= (3, 0):
+            assert not isinstance(text, bytes)
+            self.unicodeText = True
             self.guiItem.setWtext(text)
         else:
-            self.guiItem.setText(text)
+            self.unicodeText = isinstance(text, unicode)
+            if self.unicodeText:
+                self.guiItem.setWtext(text)
+            else:
+                self.guiItem.setText(text)
 
     def get(self, plain = False):
         """ Returns the text currently showing in the typable region.

+ 4 - 4
direct/src/gui/DirectEntryScroll.py

@@ -1,10 +1,10 @@
 __all__ = ['DirectEntryScroll']
 
 from panda3d.core import *
-import DirectGuiGlobals as DGG
-from DirectScrolledFrame import *
-from DirectFrame import *
-from DirectEntry import *
+from . import DirectGuiGlobals as DGG
+from .DirectScrolledFrame import *
+from .DirectFrame import *
+from .DirectEntry import *
 
 class DirectEntryScroll(DirectFrame):
     def __init__(self, entry, parent = None, **kw):

+ 17 - 11
direct/src/gui/DirectFrame.py

@@ -3,11 +3,17 @@
 __all__ = ['DirectFrame']
 
 from panda3d.core import *
-import DirectGuiGlobals as DGG
-from DirectGuiBase import *
-from OnscreenImage import OnscreenImage
-from OnscreenGeom import OnscreenGeom
-import types
+from . import DirectGuiGlobals as DGG
+from .DirectGuiBase import *
+from .OnscreenImage import OnscreenImage
+from .OnscreenGeom import OnscreenGeom
+import sys
+
+if sys.version_info >= (3, 0):
+    stringTypes = (str,)
+else:
+    stringTypes = (str, unicode)
+
 
 class DirectFrame(DirectGuiWidget):
     DefDynGroups = ('text', 'geom', 'image')
@@ -54,7 +60,7 @@ class DirectFrame(DirectGuiWidget):
         # Determine if user passed in single string or a sequence
         if self['text'] == None:
             textList = (None,) * self['numStates']
-        elif isinstance(self['text'], types.StringTypes):
+        elif isinstance(self['text'], stringTypes):
             # If just passing in a single string, make a tuple out of it
             textList = (self['text'],) * self['numStates']
         else:
@@ -80,7 +86,7 @@ class DirectFrame(DirectGuiWidget):
                 if text == None:
                     return
                 else:
-                    from OnscreenText import OnscreenText
+                    from .OnscreenText import OnscreenText
                     self.createcomponent(
                         component, (), 'text',
                         OnscreenText,
@@ -97,7 +103,7 @@ class DirectFrame(DirectGuiWidget):
             # Passed in None
             geomList = (None,) * self['numStates']
         elif isinstance(geom, NodePath) or \
-             isinstance(geom, types.StringTypes):
+             isinstance(geom, stringTypes):
             # Passed in a single node path, make a tuple out of it
             geomList = (geom,) * self['numStates']
         else:
@@ -139,14 +145,14 @@ class DirectFrame(DirectGuiWidget):
             imageList = (None,) * self['numStates']
         elif isinstance(arg, NodePath) or \
              isinstance(arg, Texture) or \
-             isinstance(arg, types.StringTypes):
+             isinstance(arg, stringTypes):
             # Passed in a single node path, make a tuple out of it
             imageList = (arg,) * self['numStates']
         else:
             # Otherwise, hope that the user has passed in a tuple/list
             if ((len(arg) == 2) and
-                isinstance(arg[0], types.StringTypes) and
-                isinstance(arg[1], types.StringTypes)):
+                isinstance(arg[0], stringTypes) and
+                isinstance(arg[1], stringTypes)):
                 # Its a model/node pair of strings
                 imageList = (arg,) * self['numStates']
             else:

+ 19 - 19
direct/src/gui/DirectGui.py

@@ -1,9 +1,9 @@
-"""Undocumented Module"""
+""" Imports all of the DirectGUI classes. """
 
-import DirectGuiGlobals as DGG
-from OnscreenText import *
-from OnscreenGeom import *
-from OnscreenImage import *
+from . import DirectGuiGlobals as DGG
+from .OnscreenText import *
+from .OnscreenGeom import *
+from .OnscreenImage import *
 
 # MPG DirectStart should call this?
 # Set up default font
@@ -12,17 +12,17 @@ from OnscreenImage import *
 #    PGItem.getTextNode().setFont(defaultFont)
 
 # Direct Gui Classes
-from DirectFrame import *
-from DirectButton import *
-from DirectEntry import *
-from DirectEntryScroll import *
-from DirectLabel import *
-from DirectScrolledList import *
-from DirectDialog import *
-from DirectWaitBar import *
-from DirectSlider import *
-from DirectScrollBar import *
-from DirectScrolledFrame import *
-from DirectCheckButton import *
-from DirectOptionMenu import *
-from DirectRadioButton import *
+from .DirectFrame import *
+from .DirectButton import *
+from .DirectEntry import *
+from .DirectEntryScroll import *
+from .DirectLabel import *
+from .DirectScrolledList import *
+from .DirectDialog import *
+from .DirectWaitBar import *
+from .DirectSlider import *
+from .DirectScrollBar import *
+from .DirectScrolledFrame import *
+from .DirectCheckButton import *
+from .DirectOptionMenu import *
+from .DirectRadioButton import *

+ 22 - 23
direct/src/gui/DirectGuiBase.py

@@ -5,14 +5,13 @@ __all__ = ['DirectGuiBase', 'DirectGuiWidget']
 
 from panda3d.core import *
 from panda3d.direct import get_config_showbase
-import DirectGuiGlobals as DGG
-from OnscreenText import *
-from OnscreenGeom import *
-from OnscreenImage import *
+from . import DirectGuiGlobals as DGG
+from .OnscreenText import *
+from .OnscreenGeom import *
+from .OnscreenImage import *
 from direct.directtools.DirectUtil import ROUND_TO
 from direct.showbase import DirectObject
 from direct.task import Task
-import types
 
 guiObjectCollector = PStatCollector("Client::GuiObjects")
 
@@ -243,7 +242,7 @@ class DirectGuiBase(DirectObject.DirectObject):
             # Now check if anything is left over
             unusedOptions = []
             keywords = self._constructorKeywords
-            for name in keywords.keys():
+            for name in keywords:
                 used = keywords[name][1]
                 if not used:
                     # This keyword argument has not been used.  If it
@@ -350,8 +349,8 @@ class DirectGuiBase(DirectObject.DirectObject):
                 # This is one of the options of this gui item.
                 # Check it is an initialisation option.
                 if optionInfo[option][FUNCTION] is DGG.INITOPT:
-                    print 'Cannot configure initialisation option "' \
-                          + option + '" for ' + self.__class__.__name__
+                    print('Cannot configure initialisation option "' \
+                          + option + '" for ' + self.__class__.__name__)
                     break
                     #raise KeyError, \
                 #           'Cannot configure initialisation option "' \
@@ -506,7 +505,7 @@ class DirectGuiBase(DirectObject.DirectObject):
             # with corresponding keys beginning with *component*.
             alias = alias + '_'
             aliasLen = len(alias)
-            for option in keywords.keys():
+            for option in keywords:
                 if len(option) > aliasLen and option[:aliasLen] == alias:
                     newkey = component + '_' + option[aliasLen:]
                     keywords[newkey] = keywords[option]
@@ -519,7 +518,7 @@ class DirectGuiBase(DirectObject.DirectObject):
         # First, walk through the option list looking for arguments
         # than refer to this component's group.
 
-        for option in keywords.keys():
+        for option in keywords:
             # Check if this keyword argument refers to the group
             # of this component.  If so, add this to the options
             # to use when constructing the widget.  Mark the
@@ -538,7 +537,7 @@ class DirectGuiBase(DirectObject.DirectObject):
         # specific than the group arguments, above; we walk through
         # the list afterwards so they will override.
 
-        for option in keywords.keys():
+        for option in keywords:
             if len(option) > nameLen and option[:nameLen] == componentPrefix:
                 # The keyword argument refers to this component, so add
                 # this to the options to use when constructing the widget.
@@ -550,7 +549,7 @@ class DirectGuiBase(DirectObject.DirectObject):
         if widgetClass is None:
             return None
         # Get arguments for widget constructor
-        if len(widgetArgs) == 1 and type(widgetArgs[0]) == types.TupleType:
+        if len(widgetArgs) == 1 and type(widgetArgs[0]) == tuple:
             # Arguments to the constructor can be specified as either
             # multiple trailing arguments to createcomponent() or as a
             # single tuple argument.
@@ -600,7 +599,7 @@ class DirectGuiBase(DirectObject.DirectObject):
 
     def components(self):
         # Return a list of all components.
-        names = self.__componentInfo.keys()
+        names = list(self.__componentInfo.keys())
         names.sort()
         return names
 
@@ -631,8 +630,8 @@ class DirectGuiBase(DirectObject.DirectObject):
         gEvent = event + self.guiId
         if get_config_showbase().GetBool('debug-directgui-msgs', False):
             from direct.showbase.PythonUtil import StackTrace
-            print gEvent
-            print StackTrace()
+            print(gEvent)
+            print(StackTrace())
         self.accept(gEvent, command, extraArgs = extraArgs)
 
     def unbind(self, event):
@@ -944,7 +943,7 @@ class DirectGuiWidget(DirectGuiBase, NodePath):
         # Convert None, and string arguments
         if relief == None:
             relief = PGFrameStyle.TNone
-        elif isinstance(relief, types.StringTypes):
+        elif isinstance(relief, str):
             # Convert string to frame style int
             relief = DGG.FrameStyleDict[relief]
         # Set style
@@ -969,8 +968,8 @@ class DirectGuiWidget(DirectGuiBase, NodePath):
     def setFrameColor(self):
         # this might be a single color or a list of colors
         colors = self['frameColor']
-        if type(colors[0]) == types.IntType or \
-           type(colors[0]) == types.FloatType:
+        if type(colors[0]) == int or \
+           type(colors[0]) == float:
             colors = (colors,)
         for i in range(self['numStates']):
             if i >= len(colors):
@@ -985,14 +984,14 @@ class DirectGuiWidget(DirectGuiBase, NodePath):
         textures = self['frameTexture']
         if textures == None or \
            isinstance(textures, Texture) or \
-           isinstance(textures, types.StringTypes):
+           isinstance(textures, str):
             textures = (textures,) * self['numStates']
         for i in range(self['numStates']):
             if i >= len(textures):
                 texture = textures[-1]
             else:
                 texture = textures[i]
-            if isinstance(texture, types.StringTypes):
+            if isinstance(texture, str):
                 texture = loader.loadTexture(texture)
             if texture:
                 self.frameStyle[i].setTexture(texture)
@@ -1057,9 +1056,9 @@ class DirectGuiWidget(DirectGuiBase, NodePath):
 
     def printConfig(self, indent = 0):
         space = ' ' * indent
-        print space + self.guiId, '-', self.__class__.__name__
-        print space + 'Pos:   %s' % tuple(self.getPos())
-        print space + 'Scale: %s' % tuple(self.getScale())
+        print('%s%s - %s' % (space, self.guiId, self.__class__.__name__))
+        print('%sPos:   %s' % (space, tuple(self.getPos())))
+        print('%sScale: %s' % (space, tuple(self.getScale())))
         # Print out children info
         for child in self.getChildren():
             messenger.send(DGG.PRINT + child.getName(), [indent + 2])

+ 9 - 9
direct/src/gui/DirectGuiTest.py

@@ -5,8 +5,8 @@ __all__ = []
 
 if __name__ == "__main__":
     from direct.showbase.ShowBase import ShowBase
-    import DirectGuiGlobals
-    from DirectGui import *
+    from . import DirectGuiGlobals
+    from .DirectGui import *
     #from whrandom import *
     from random import *
 
@@ -18,7 +18,7 @@ if __name__ == "__main__":
 
     # Here we specify the button's command
     def dummyCmd(index):
-        print 'Button %d POW!!!!' % index
+        print('Button %d POW!!!!' % index)
 
     # Define some commands to bind to enter, exit and click events
     def shrink(db):
@@ -94,7 +94,7 @@ if __name__ == "__main__":
 
     # DIRECT ENTRY EXAMPLE
     def printEntryText(text):
-        print 'Text:', text
+        print('Text: %s' % (text))
 
     # Here we create an entry, and specify everything up front
     # CALL de1.get() and de1.set('new text') to get and set entry contents
@@ -110,7 +110,7 @@ if __name__ == "__main__":
 
     # DIRECT DIALOG EXAMPLE
     def printDialogValue(value):
-        print 'Value:', value
+        print('Value: %s' % (value))
 
     simpleDialog = YesNoDialog(text = 'Simple',
                                command = printDialogValue)
@@ -136,9 +136,9 @@ if __name__ == "__main__":
     # NOTE: There are some utility functions which help you get size
     # of a direct gui widget.  These can be used to position and scale an
     # image after you've created the entry.  scale = (width/2, 1, height/2)
-    print 'BOUNDS:', de1.getBounds()
-    print 'WIDTH:', de1.getWidth()
-    print 'HEIGHT:', de1.getHeight()
-    print 'CENTER:', de1.getCenter()
+    print('BOUNDS: %s' % de1.getBounds())
+    print('WIDTH: %s' % de1.getWidth())
+    print('HEIGHT: %s' % de1.getHeight())
+    print('CENTER: %s' % (de1.getCenter(),))
 
     base.run()

+ 1 - 1
direct/src/gui/DirectLabel.py

@@ -3,7 +3,7 @@
 __all__ = ['DirectLabel']
 
 from panda3d.core import *
-from DirectFrame import *
+from .DirectFrame import *
 
 class DirectLabel(DirectFrame):
     """

+ 6 - 8
direct/src/gui/DirectOptionMenu.py

@@ -2,13 +2,11 @@
 
 __all__ = ['DirectOptionMenu']
 
-import types
-
 from panda3d.core import *
-import DirectGuiGlobals as DGG
-from DirectButton import *
-from DirectLabel import *
-from DirectFrame import *
+from . import DirectGuiGlobals as DGG
+from .DirectButton import *
+from .DirectLabel import *
+from .DirectFrame import *
 
 class DirectOptionMenu(DirectButton):
     """
@@ -252,7 +250,7 @@ class DirectOptionMenu(DirectButton):
 
     def index(self, index):
         intIndex = None
-        if isinstance(index, types.IntType):
+        if isinstance(index, int):
             intIndex = index
         elif index in self['items']:
             i = 0
@@ -272,7 +270,7 @@ class DirectOptionMenu(DirectButton):
             self['text'] = item
             if fCommand and self['command']:
                 # Pass any extra args to command
-                apply(self['command'], [item] + self['extraArgs'])
+                self['command'](*[item] + self['extraArgs'])
 
     def get(self):
         """ Get currently selected item """

+ 4 - 4
direct/src/gui/DirectRadioButton.py

@@ -3,9 +3,9 @@
 __all__ = ['DirectRadioButton']
 
 from panda3d.core import *
-import DirectGuiGlobals as DGG
-from DirectButton import *
-from DirectLabel import *
+from . import DirectGuiGlobals as DGG
+from .DirectButton import *
+from .DirectLabel import *
 
 class DirectRadioButton(DirectButton):
     """
@@ -205,7 +205,7 @@ class DirectRadioButton(DirectButton):
 
         if self['command']:
             # Pass any extra args to command
-            apply(self['command'], self['extraArgs'])
+            self['command'](*self['extraArgs'])
 
     def setOthers(self, others):
         self['others'] = others

+ 4 - 4
direct/src/gui/DirectScrollBar.py

@@ -3,9 +3,9 @@
 __all__ = ['DirectScrollBar']
 
 from panda3d.core import *
-import DirectGuiGlobals as DGG
-from DirectFrame import *
-from DirectButton import *
+from . import DirectGuiGlobals as DGG
+from .DirectFrame import *
+from .DirectButton import *
 
 """
 import DirectScrollBar
@@ -164,5 +164,5 @@ class DirectScrollBar(DirectFrame):
         self._optionInfo['value'][DGG._OPT_VALUE] = self.guiItem.getValue()
 
         if self['command']:
-            apply(self['command'], self['extraArgs'])
+            self['command'](*self['extraArgs'])
 

+ 4 - 4
direct/src/gui/DirectScrolledFrame.py

@@ -3,9 +3,9 @@
 __all__ = ['DirectScrolledFrame']
 
 from panda3d.core import *
-import DirectGuiGlobals as DGG
-from DirectFrame import *
-from DirectScrollBar import *
+from . import DirectGuiGlobals as DGG
+from .DirectFrame import *
+from .DirectScrollBar import *
 
 """
 import DirectScrolledFrame
@@ -87,7 +87,7 @@ class DirectScrolledFrame(DirectFrame):
 
     def commandFunc(self):
         if self['command']:
-            apply(self['command'], self['extraArgs'])
+            self['command'](*self['extraArgs'])
 
     def destroy(self):
         # Destroy children of the canvas

+ 7 - 8
direct/src/gui/DirectScrolledList.py

@@ -3,11 +3,11 @@
 __all__ = ['DirectScrolledListItem', 'DirectScrolledList']
 
 from panda3d.core import *
-import DirectGuiGlobals as DGG
+from . import DirectGuiGlobals as DGG
 from direct.directnotify import DirectNotifyGlobal
 from direct.task.Task import Task
-from DirectFrame import *
-from DirectButton import *
+from .DirectFrame import *
+from .DirectButton import *
 import types
 
 
@@ -39,7 +39,7 @@ class DirectScrolledListItem(DirectButton):
 
     def select(self):
         assert self.notify.debugStateCall(self)
-        apply(self.nextCommand, self.nextCommandExtraArgs)
+        self.nextCommand(*self.nextCommandExtraArgs)
         self.parent.selectListItem(self)
 
 
@@ -251,7 +251,7 @@ class DirectScrolledList(DirectFrame):
             if item.__class__.__name__ == 'str':
                 if self['itemMakeFunction']:
                     # If there is a function to create the item
-                    item = apply(self['itemMakeFunction'], (item, i, self['itemMakeExtraArgs']))
+                    item = self['itemMakeFunction'](item, i, self['itemMakeExtraArgs'])
                 else:
                     item = DirectFrame(text = item,
                                        text_align = self['itemsAlign'],
@@ -269,7 +269,7 @@ class DirectScrolledList(DirectFrame):
 
         if self['command']:
             # Pass any extra args to command
-            apply(self['command'], self['extraArgs'])
+            self['command'](*self['extraArgs'])
         return ret
 
     def makeAllItems(self):
@@ -283,8 +283,7 @@ class DirectScrolledList(DirectFrame):
             if item.__class__.__name__ == 'str':
                 if self['itemMakeFunction']:
                     # If there is a function to create the item
-                    item = apply(self['itemMakeFunction'],
-                                 (item, i, self['itemMakeExtraArgs']))
+                    item = self['itemMakeFunction'](item, i, self['itemMakeExtraArgs'])
                 else:
                     item = DirectFrame(text = item,
                                        text_align = self['itemsAlign'],

+ 4 - 4
direct/src/gui/DirectSlider.py

@@ -3,9 +3,9 @@
 __all__ = ['DirectSlider']
 
 from panda3d.core import *
-import DirectGuiGlobals as DGG
-from DirectFrame import *
-from DirectButton import *
+from . import DirectGuiGlobals as DGG
+from .DirectFrame import *
+from .DirectButton import *
 
 """
 import DirectSlider
@@ -124,4 +124,4 @@ class DirectSlider(DirectFrame):
         self._optionInfo['value'][DGG._OPT_VALUE] = self.guiItem.getValue()
 
         if self['command']:
-            apply(self['command'], self['extraArgs'])
+            self['command'](*self['extraArgs'])

+ 3 - 3
direct/src/gui/DirectWaitBar.py

@@ -3,8 +3,8 @@
 __all__ = ['DirectWaitBar']
 
 from panda3d.core import *
-import DirectGuiGlobals as DGG
-from DirectFrame import *
+from . import DirectGuiGlobals as DGG
+from .DirectFrame import *
 import types
 
 """
@@ -93,7 +93,7 @@ class DirectWaitBar(DirectFrame):
         """Updates the bar texture, which you can set using bar['barTexture']."""
         # this must be a single texture (or a string).
         texture = self['barTexture']
-        if isinstance(texture, types.StringTypes):
+        if isinstance(texture, str):
             texture = loader.loadTexture(texture)
         if texture:
             self.barStyle.setTexture(texture)

+ 18 - 18
direct/src/gui/OnscreenGeom.py

@@ -4,7 +4,7 @@ __all__ = ['OnscreenGeom']
 
 from panda3d.core import *
 from direct.showbase.DirectObject import DirectObject
-import types
+
 
 class OnscreenGeom(DirectObject, NodePath):
     def __init__(self, geom = None,
@@ -49,25 +49,25 @@ class OnscreenGeom(DirectObject, NodePath):
 
         # Adjust pose
         # Set pos
-        if (isinstance(pos, types.TupleType) or
-            isinstance(pos, types.ListType)):
-            apply(self.setPos, pos)
+        if (isinstance(pos, tuple) or
+            isinstance(pos, list)):
+            self.setPos(*pos)
         elif isinstance(pos, VBase3):
             self.setPos(pos)
         # Hpr
-        if (isinstance(hpr, types.TupleType) or
-            isinstance(hpr, types.ListType)):
-            apply(self.setHpr, hpr)
+        if (isinstance(hpr, tuple) or
+            isinstance(hpr, list)):
+            self.setHpr(*hpr)
         elif isinstance(hpr, VBase3):
             self.setPos(hpr)
         # Scale
-        if (isinstance(scale, types.TupleType) or
-            isinstance(scale, types.ListType)):
-            apply(self.setScale, scale)
+        if (isinstance(scale, tuple) or
+            isinstance(scale, list)):
+            self.setScale(*scale)
         elif isinstance(scale, VBase3):
             self.setPos(scale)
-        elif (isinstance(scale, types.FloatType) or
-              isinstance(scale, types.IntType)):
+        elif (isinstance(scale, float) or
+              isinstance(scale, int)):
             self.setScale(scale)
 
     def setGeom(self, geom,
@@ -93,7 +93,7 @@ class OnscreenGeom(DirectObject, NodePath):
         # Assign geometry
         if isinstance(geom, NodePath):
             self.assign(geom.copyTo(parent, sort))
-        elif isinstance(geom, types.StringTypes):
+        elif isinstance(geom, str):
             self.assign(loader.loadModel(geom))
             self.reparentTo(parent, sort)
 
@@ -116,17 +116,17 @@ class OnscreenGeom(DirectObject, NodePath):
                 if (((setter == self.setPos) or
                      (setter == self.setHpr) or
                      (setter == self.setScale)) and
-                    (isinstance(value, types.TupleType) or
-                     isinstance(value, types.ListType))):
-                    apply(setter, value)
+                    (isinstance(value, tuple) or
+                     isinstance(value, list))):
+                    setter(*value)
                 else:
                     setter(value)
             except AttributeError:
-                print 'OnscreenText.configure: invalid option:', option
+                print('OnscreenText.configure: invalid option: %s' % option)
 
     # Allow index style references
     def __setitem__(self, key, value):
-        apply(self.configure, (), {key: value})
+        self.configure(*(), **{key: value})
 
     def cget(self, option):
         # Get current configuration setting.

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