Răsfoiți Sursa

Big commit aiding in separation of Python bindings:
* Most extension functions have been moved to C++.
* In makepanda, Python bindings are compiled into panda3d/<module>.pyd.

rdb 11 ani în urmă
părinte
comite
5f2c0a6e04
97 a modificat fișierele cu 1021 adăugiri și 1943 ștergeri
  1. 1 1
      direct/src/directnotify/DirectNotify.py
  2. 2 2
      direct/src/directnotify/Notifier.py
  3. 0 11
      direct/src/extensions/EggGroupNode-extensions.py
  4. 0 8
      direct/src/extensions/EggPrimitive-extensions.py
  5. 0 34
      direct/src/extensions/NodePathCollection-extensions.py
  6. 0 6
      direct/src/extensions/OdeBody-extensions.py
  7. 0 44
      direct/src/extensions/OdeGeom-extensions.py
  8. 0 39
      direct/src/extensions/OdeJoint-extensions.py
  9. 0 32
      direct/src/extensions/OdeSpace-extensions.py
  10. 0 15
      direct/src/extensions/Ramfile-extensions.py
  11. 0 15
      direct/src/extensions/StreamReader-extensions.py
  12. 0 16
      direct/src/extensions_native/EggGroupNode_extensions.py
  13. 0 13
      direct/src/extensions_native/EggPrimitive_extensions.py
  14. 0 31
      direct/src/extensions_native/NodePathCollection_extensions.py
  15. 0 9
      direct/src/extensions_native/NodePath_extensions.py
  16. 0 18
      direct/src/extensions_native/OdeBody_extensions.py
  17. 0 60
      direct/src/extensions_native/OdeGeom_extensions.py
  18. 0 54
      direct/src/extensions_native/OdeJoint_extensions.py
  19. 0 50
      direct/src/extensions_native/OdeSpace_extensions.py
  20. 0 16
      direct/src/extensions_native/Ramfile_extensions.py
  21. 0 16
      direct/src/extensions_native/StreamReader_extensions.py
  22. 1 1
      direct/src/showbase/Messenger.py
  23. 1 4
      direct/src/showbase/PythonUtil.py
  24. 28 18
      dtool/src/interrogate/functionRemap.cxx
  25. 2 1
      dtool/src/interrogate/functionRemap.h
  26. 177 137
      dtool/src/interrogate/interfaceMakerPythonNative.cxx
  27. 3 9
      dtool/src/interrogatedb/extension.h
  28. 3 3
      dtool/src/interrogatedb/py_panda.cxx
  29. 1 0
      dtool/src/prc/streamReader.h
  30. 260 195
      makepanda/makepanda.py
  31. 27 13
      makepanda/makepandacore.py
  32. 2 2
      panda/src/display/Sources.pp
  33. 18 51
      panda/src/display/graphicsStateGuardian.cxx
  34. 3 5
      panda/src/display/graphicsStateGuardian.h
  35. 5 2
      panda/src/egg/Sources.pp
  36. 2 0
      panda/src/egg/eggGroupNode.h
  37. 1 1
      panda/src/event/pythonTask.cxx
  38. 9 3
      panda/src/express/Sources.pp
  39. 0 73
      panda/src/express/memoryUsagePointers.cxx
  40. 1 3
      panda/src/express/memoryUsagePointers.h
  41. 72 0
      panda/src/express/memoryUsagePointers_ext.cxx
  42. 40 0
      panda/src/express/memoryUsagePointers_ext.h
  43. 4 0
      panda/src/express/p3express_ext_composite.cxx
  44. 1 0
      panda/src/express/ramfile.h
  45. 48 0
      panda/src/express/ramfile_ext.cxx
  46. 40 0
      panda/src/express/ramfile_ext.h
  47. 48 0
      panda/src/express/streamReader_ext.cxx
  48. 40 0
      panda/src/express/streamReader_ext.h
  49. 1 1
      panda/src/express/virtualFileSystem_ext.cxx
  50. 1 1
      panda/src/linmath/lpoint2_ext_src.I
  51. 1 1
      panda/src/linmath/lpoint3_ext_src.I
  52. 1 1
      panda/src/linmath/lpoint4_ext_src.I
  53. 1 1
      panda/src/linmath/lvector2_ext_src.I
  54. 1 1
      panda/src/linmath/lvector3_ext_src.I
  55. 1 1
      panda/src/linmath/lvector4_ext_src.I
  56. 14 10
      panda/src/ode/Sources.pp
  57. 1 1
      panda/src/ode/odeAMotorJoint.h
  58. 1 1
      panda/src/ode/odeBallJoint.h
  59. 3 1
      panda/src/ode/odeBody.h
  60. 1 1
      panda/src/ode/odeBoxGeom.h
  61. 1 1
      panda/src/ode/odeCappedCylinderGeom.h
  62. 1 1
      panda/src/ode/odeContactJoint.h
  63. 1 1
      panda/src/ode/odeConvexGeom.h
  64. 1 1
      panda/src/ode/odeCylinderGeom.h
  65. 1 1
      panda/src/ode/odeFixedJoint.h
  66. 6 6
      panda/src/ode/odeGeom.h
  67. 1 1
      panda/src/ode/odeHashSpace.h
  68. 1 1
      panda/src/ode/odeHeightFieldGeom.h
  69. 1 1
      panda/src/ode/odeHinge2Joint.h
  70. 1 1
      panda/src/ode/odeHingeJoint.h
  71. 1 1
      panda/src/ode/odeJoint.cxx
  72. 6 6
      panda/src/ode/odeJoint.h
  73. 1 1
      panda/src/ode/odeLMotorJoint.h
  74. 1 1
      panda/src/ode/odeNullJoint.h
  75. 1 1
      panda/src/ode/odePlane2dJoint.h
  76. 1 1
      panda/src/ode/odePlaneGeom.h
  77. 1 1
      panda/src/ode/odeQuadTreeSpace.h
  78. 1 1
      panda/src/ode/odeRayGeom.h
  79. 1 1
      panda/src/ode/odeSimpleSpace.h
  80. 1 1
      panda/src/ode/odeSliderJoint.h
  81. 12 62
      panda/src/ode/odeSpace.cxx
  82. 12 21
      panda/src/ode/odeSpace.h
  83. 1 1
      panda/src/ode/odeSphereGeom.h
  84. 1 4
      panda/src/ode/odeTriMeshGeom.h
  85. 1 1
      panda/src/ode/odeUniversalJoint.h
  86. 3 54
      panda/src/ode/odeUtil.cxx
  87. 4 14
      panda/src/ode/odeUtil.h
  88. 4 0
      panda/src/ode/p3ode_ext_composite.cxx
  89. 3 0
      panda/src/pgraph/Sources.pp
  90. 0 159
      panda/src/pgraph/nodePath.I
  91. 0 220
      panda/src/pgraph/nodePath.cxx
  92. 16 25
      panda/src/pgraph/nodePath.h
  93. 44 32
      panda/src/pgraph/nodePathCollection.cxx
  94. 5 1
      panda/src/pgraph/nodePathCollection.h
  95. 3 2
      panda/src/putil/Sources.pp
  96. 9 262
      panda/src/putil/typedWritable.cxx
  97. 6 23
      panda/src/putil/typedWritable.h

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

@@ -64,7 +64,7 @@ class DirectNotify:
         # we're running before ShowBase has finished initializing; and
         # we import it directly from libpandaexpress, in case we're
         # running before libpanda.dll is available.
-        from libpandaexpress import ConfigVariableString
+        from panda3d.core import ConfigVariableString
 
         dconfigParam = ("notify-level-" + categoryName)
         cvar = ConfigVariableString(dconfigParam, "")

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

@@ -4,7 +4,7 @@ for the programmer/user
 """
 from LoggerGlobal import defaultLogger
 from direct.showbase import PythonUtil
-from libpandaexpress import ConfigVariableBool
+from panda3d.core import ConfigVariableBool
 import time
 import types
 import sys
@@ -18,7 +18,7 @@ class Notifier:
     # with the C++ notify system.
     streamWriter = None
     if ConfigVariableBool('notify-integrate', True):
-        from libpandaexpress import StreamWriter, Notify
+        from panda3d.core import StreamWriter, Notify
         streamWriter = StreamWriter(Notify.out(), False)
         
     showTime = ConfigVariableBool('notify-timestamp', False)

+ 0 - 11
direct/src/extensions/EggGroupNode-extensions.py

@@ -1,11 +0,0 @@
-
-    # For iterating over children
-    def getChildren(self):
-        """Returns a Python list of the egg node's children."""
-        result = []
-        child = self.getFirstChild()
-        while (child != None):
-            result.append(child)
-            child = self.getNextChild()
-        return result
-    

+ 0 - 8
direct/src/extensions/EggPrimitive-extensions.py

@@ -1,8 +0,0 @@
-
-    # For iterating over vertices
-    def getVertices(self):
-        """Returns a Python list of the egg primitive's vertices."""
-        result = []
-        for i in range(self.getNumVertices()):
-            result.append(self.getVertex(i))
-        return result

+ 0 - 34
direct/src/extensions/NodePathCollection-extensions.py

@@ -1,34 +0,0 @@
-
-    """
-    NodePathCollection-extensions module: contains methods to extend
-    functionality of the NodePathCollection class
-    """
-
-    # For iterating over children
-    def asList(self):
-        """Converts a NodePathCollection into a list"""
-        if self.isEmpty():
-            return []
-        else:
-            npList = []
-            for nodePathIndex in range(self.getNumPaths()):
-                npList.append(self.getPath(nodePathIndex))
-            return npList
-
-    def getTightBounds(self):
-        from pandac import Point3
-        
-        if self.getNumPaths() == 0:
-            return (Point3.Point3(0), Point3.Point3(0))
-
-        v1, v2 = self.getPath(0).getTightBounds()
-        for i in range(1, self.getNumPaths()):
-            v1x, v2x = self.getPath(i).getTightBounds()
-            v1 = Point3.Point3(min(v1[0], v1x[0]),
-                               min(v1[1], v1x[1]),
-                               min(v1[2], v1x[2]))
-            v2 = Point3.Point3(max(v2[0], v2x[0]),
-                               max(v2[1], v2x[1]),
-                               max(v2[2], v2x[2]))
-        
-        return v1, v2

+ 0 - 6
direct/src/extensions/OdeBody-extensions.py

@@ -1,6 +0,0 @@
-
-def getConvertedJoint(self, index):
-    """
-    Return a downcast joint on this body.
-    """
-    return self.getJoint(index).convert()

+ 0 - 44
direct/src/extensions/OdeGeom-extensions.py

@@ -1,44 +0,0 @@
-
-def convert(self):
-    """
-    Do a sort of pseudo-downcast on this geom in 
-    order to expose its specialized functions.
-    """
-    if self.getGeomClass() == OdeGeom.GCSphere:
-        return self.convertToSphere()
-    elif self.getGeomClass() == OdeGeom.GCBox:
-        return self.convertToBox()
-    elif self.getGeomClass() == OdeGeom.GCCappedCylinder:
-        return self.convertToCappedCylinder()
-    elif self.getGeomClass() == OdeGeom.GCPlane:
-        return self.convertToPlane()
-    elif self.getGeomClass() == OdeGeom.GCRay:
-        return self.convertToRay()
-    # elif self.getGeomClass() == OdeGeom.GCConvex:
-    #     return self.convertToConvex()
-    # elif self.getGeomClass() == OdeGeom.GCGeomTransform:
-    #     return self.convertToGeomTransform()
-    elif self.getGeomClass() == OdeGeom.GCTriMesh:
-        return self.convertToTriMesh()
-    # elif self.getGeomClass() == OdeGeom.GCHeightfield:
-    #     return self.convertToHeightfield()
-    elif self.getGeomClass() == OdeGeom.GCSimpleSpace:
-        return self.convertToSimpleSpace()
-    elif self.getGeomClass() == OdeGeom.GCHashSpace:
-        return self.convertToHashSpace()
-    elif self.getGeomClass() == OdeGeom.GCQuadTreeSpace:
-        return self.convertToQuadTreeSpace()
-
-def getConvertedSpace(self):
-    """
-    """
-    return self.getSpace().convert()
-
-def getAABounds(self):
-    """
-    A more Pythonic way of calling getAABB().
-    """
-    min = Point3()
-    max = Point3()
-    self.getAABB(min,max)
-    return min,max

+ 0 - 39
direct/src/extensions/OdeJoint-extensions.py

@@ -1,39 +0,0 @@
-def attach(self, body1, body2):
-    """
-    Attach two bodies together.
-    If either body is None, the other will be attached to the environment.
-    """
-    if body1 and body2:
-        self.attachBodies(body1, body2)
-    elif body1 and not body2:
-        self.attachBody(body1, 0)
-    elif not body1 and body2:
-        self.attachBody(body2, 1)
-
-def convert(self):
-    """
-    Do a sort of pseudo-downcast on this joint in 
-    order to expose its specialized functions.
-    """
-    if self.getJointType() == OdeJoint.JTBall:
-        return self.convertToBall()
-    elif self.getJointType() == OdeJoint.JTHinge:
-        return self.convertToHinge()
-    elif self.getJointType() == OdeJoint.JTSlider:
-        return self.convertToSlider()
-    elif self.getJointType() == OdeJoint.JTContact:
-        return self.convertToContact()
-    elif self.getJointType() == OdeJoint.JTUniversal:
-        return self.convertToUniversal()
-    elif self.getJointType() == OdeJoint.JTHinge2:
-        return self.convertToHinge2()
-    elif self.getJointType() == OdeJoint.JTFixed:
-        return self.convertToFixed()
-    elif self.getJointType() == OdeJoint.JTNull:
-        return self.convertToNull()
-    elif self.getJointType() == OdeJoint.JTAMotor:
-        return self.convertToAMotor()
-    elif self.getJointType() == OdeJoint.JTLMotor:
-        return self.convertToLMotor()
-    elif self.getJointType() == OdeJoint.JTPlane2d:
-        return self.convertToPlane2d()

+ 0 - 32
direct/src/extensions/OdeSpace-extensions.py

@@ -1,32 +0,0 @@
-
-def convert(self):
-    """
-    Do a sort of pseudo-downcast on this space in 
-    order to expose its specialized functions.
-    """
-    if self.getClass() == OdeGeom.GCSimpleSpace:
-        return self.convertToSimpleSpace()
-    elif self.getClass() == OdeGeom.GCHashSpace:
-        return self.convertToHashSpace()
-    elif self.getClass() == OdeGeom.GCQuadTreeSpace:
-        return self.convertToQuadTreeSpace()
-
-def getConvertedGeom(self, index):
-    """
-    Return a downcast geom on this body.
-    """
-    return self.getGeom(index).convert()
-
-def getConvertedSpace(self):
-    """
-    """
-    return self.getSpace().convert()
-
-def getAABounds(self):
-    """
-    A more Pythonic way of calling getAABB()
-    """
-    min = Point3()
-    max = Point3()
-    self.getAABB(min,max)
-    return min,max

+ 0 - 15
direct/src/extensions/Ramfile-extensions.py

@@ -1,15 +0,0 @@
-
-    """
-    Ramfile-extensions module: contains methods to extend functionality
-    of the Ramfile class
-    """
-
-    def readlines(self):
-        """Reads all the lines at once and returns a list."""
-        lines = []
-        line = self.readline()
-        while line:
-            lines.append(line)
-            line = self.readline()
-        return lines
-    

+ 0 - 15
direct/src/extensions/StreamReader-extensions.py

@@ -1,15 +0,0 @@
-
-    """
-    StreamReader-extensions module: contains methods to extend functionality
-    of the StreamReader class
-    """
-
-    def readlines(self):
-        """Reads all the lines at once and returns a list."""
-        lines = []
-        line = self.readline()
-        while line:
-            lines.append(line)
-            line = self.readline()
-        return lines
-    

+ 0 - 16
direct/src/extensions_native/EggGroupNode_extensions.py

@@ -1,16 +0,0 @@
-####################################################################
-#Dtool_funcToMethod(func, class)        
-#del func
-#####################################################################
-    # For iterating over children
-def getChildren(self):
-        """Returns a Python list of the egg node's children."""
-        result = []
-        child = self.getFirstChild()
-        while (child != None):
-            result.append(child)
-            child = self.getNextChild()
-        return result
-    
-Dtool_funcToMethod(getChildren, EggGroupNode)        
-del getChildren

+ 0 - 13
direct/src/extensions_native/EggPrimitive_extensions.py

@@ -1,13 +0,0 @@
-####################################################################
-#Dtool_funcToMethod(func, class)        
-#del func
-#####################################################################
-    # For iterating over vertices
-def getVertices(self):
-        """Returns a Python list of the egg primitive's vertices."""
-        result = []
-        for i in range(self.getNumVertices()):
-            result.append(self.getVertex(i))
-        return result
-Dtool_funcToMethod(getVertices, EggPrimitive)        
-del getVertices

+ 0 - 31
direct/src/extensions_native/NodePathCollection_extensions.py

@@ -1,31 +0,0 @@
-#####################################################################
-
-# For iterating over children
-def asList(self):
-    """Converts a NodePathCollection into a list"""
-    print "Warning: NodePathCollection.asList() is no longer needed and deprecated.  Iterate on the collection directly instead."
-    return list(self)
-        
-Dtool_funcToMethod(asList, NodePathCollection)        
-del asList
-#####################################################################3333      
-
-def getTightBounds(self):
-    from pandac.PandaModules import Point3
-    
-    if self.getNumPaths() == 0:
-        return (Point3(0), Point3(0))
-    v1, v2 = self.getPath(0).getTightBounds()
-    for i in range(1, self.getNumPaths()):
-        v1x, v2x = self.getPath(i).getTightBounds()
-        v1 = Point3(min(v1[0], v1x[0]),
-                    min(v1[1], v1x[1]),
-                    min(v1[2], v1x[2]))
-        v2 = Point3(max(v2[0], v2x[0]),
-                    max(v2[1], v2x[1]),
-                    max(v2[2], v2x[2]))
-    return v1, v2
-    
-Dtool_funcToMethod(getTightBounds, NodePathCollection)        
-del getTightBounds
-#####################################################################3333      

+ 0 - 9
direct/src/extensions_native/NodePath_extensions.py

@@ -154,15 +154,6 @@ def getAncestry(self):
 Dtool_funcToMethod(getAncestry, NodePath)
 del getAncestry
 #####################################################################
-def getTightBounds(self):
-        from pandac.PandaModules import Point3
-        v1 = Point3(0)
-        v2 = Point3(0)
-        self.calcTightBounds(v1, v2)
-        return v1, v2
-Dtool_funcToMethod(getTightBounds, NodePath)
-del getTightBounds
-#####################################################################
 
 def pPrintString(self, other = None):
         """

+ 0 - 18
direct/src/extensions_native/OdeBody_extensions.py

@@ -1,18 +0,0 @@
-####################################################################
-#Dtool_funcToMethod(func, class)
-#del func
-#####################################################################
-
-"""
-OdeBody-extensions module: contains methods to extend functionality
-of the OdeBody classe
-"""
-
-def getConvertedJoint(self, index):
-    """
-    Return a downcast joint on this body.
-    """
-    return self.getJoint(index).convert()
-Dtool_funcToMethod(getConvertedJoint, OdeBody)
-del getConvertedJoint
-

+ 0 - 60
direct/src/extensions_native/OdeGeom_extensions.py

@@ -1,60 +0,0 @@
-####################################################################
-#Dtool_funcToMethod(func, class)
-#del func
-#####################################################################
-
-"""
-OdeGeom-extensions module: contains methods to extend functionality
-of the OdeGeom class
-"""
-
-def convert(self):
-    """
-    Do a sort of pseudo-downcast on this geom in 
-    order to expose its specialized functions.
-    """
-    if self.getClass() == OdeGeom.GCSphere:
-        return self.convertToSphere()
-    elif self.getClass() == OdeGeom.GCBox:
-        return self.convertToBox()
-    elif self.getClass() == OdeGeom.GCCappedCylinder:
-        return self.convertToCappedCylinder()
-    elif self.getClass() == OdeGeom.GCPlane:
-        return self.convertToPlane()
-    elif self.getClass() == OdeGeom.GCRay:
-        return self.convertToRay()
-    # elif self.getClass() == OdeGeom.GCConvex:
-    #     return self.convertToConvex()
-    # elif self.getClass() == OdeGeom.GCGeomTransform:
-    #     return self.convertToGeomTransform()
-    elif self.getClass() == OdeGeom.GCTriMesh:
-        return self.convertToTriMesh()
-    # elif self.getClass() == OdeGeom.GCHeightfield:
-    #     return self.convertToHeightfield()
-    elif self.getClass() == OdeGeom.GCSimpleSpace:
-        return self.convertToSimpleSpace()
-    elif self.getClass() == OdeGeom.GCHashSpace:
-        return self.convertToHashSpace()
-    elif self.getClass() == OdeGeom.GCQuadTreeSpace:
-        return self.convertToQuadTreeSpace()
-Dtool_funcToMethod(convert, OdeGeom)
-del convert
-
-def getConvertedSpace(self):
-    """
-    """
-    return self.getSpace().convert()
-Dtool_funcToMethod(getConvertedSpace, OdeGeom)
-del getConvertedSpace
-
-def getAABounds(self):
-    """
-    A more Pythonic way of calling getAABB()
-    """
-    min = Point3()
-    max = Point3()
-    self.getAABB(min,max)
-    return min,max
-Dtool_funcToMethod(getAABounds, OdeGeom)
-del getAABounds
-

+ 0 - 54
direct/src/extensions_native/OdeJoint_extensions.py

@@ -1,54 +0,0 @@
-####################################################################
-#Dtool_funcToMethod(func, class)
-#del func
-#####################################################################
-
-"""
-OdeJoint-extensions module: contains methods to extend functionality
-of the OdeJoint class
-"""
-
-def attach(self, body1, body2):
-    """
-    Attach two bodies together.
-    If either body is None, the other will be attached to the environment.
-    """
-    if body1 and body2:
-        self.attachBodies(body1, body2)
-    elif body1 and not body2:
-        self.attachBody(body1, 0)
-    elif not body1 and body2:
-        self.attachBody(body2, 1)
-Dtool_funcToMethod(attach, OdeJoint)
-del attach
-
-def convert(self):
-    """
-    Do a sort of pseudo-downcast on this joint in 
-    order to expose its specialized functions.
-    """
-    if self.getJointType() == OdeJoint.JTBall:
-        return self.convertToBall()
-    elif self.getJointType() == OdeJoint.JTHinge:
-        return self.convertToHinge()
-    elif self.getJointType() == OdeJoint.JTSlider:
-        return self.convertToSlider()
-    elif self.getJointType() == OdeJoint.JTContact:
-        return self.convertToContact()
-    elif self.getJointType() == OdeJoint.JTUniversal:
-        return self.convertToUniversal()
-    elif self.getJointType() == OdeJoint.JTHinge2:
-        return self.convertToHinge2()
-    elif self.getJointType() == OdeJoint.JTFixed:
-        return self.convertToFixed()
-    elif self.getJointType() == OdeJoint.JTNull:
-        return self.convertToNull()
-    elif self.getJointType() == OdeJoint.JTAMotor:
-        return self.convertToAMotor()
-    elif self.getJointType() == OdeJoint.JTLMotor:
-        return self.convertToLMotor()
-    elif self.getJointType() == OdeJoint.JTPlane2d:
-        return self.convertToPlane2d()
-Dtool_funcToMethod(convert, OdeJoint)
-del convert
-

+ 0 - 50
direct/src/extensions_native/OdeSpace_extensions.py

@@ -1,50 +0,0 @@
-####################################################################
-#Dtool_funcToMethod(func, class)
-#del func
-#####################################################################
-
-"""
-OdeSpace-extensions module: contains methods to extend functionality
-of the OdeSpace classe
-"""
-
-def convert(self):
-    """
-    Do a sort of pseudo-downcast on this space in 
-    order to expose its specialized functions.
-    """
-    if self.getClass() == OdeGeom.GCSimpleSpace:
-        return self.convertToSimpleSpace()
-    elif self.getClass() == OdeGeom.GCHashSpace:
-        return self.convertToHashSpace()
-    elif self.getClass() == OdeGeom.GCQuadTreeSpace:
-        return self.convertToQuadTreeSpace()
-Dtool_funcToMethod(convert, OdeSpace)
-del convert
-
-def getConvertedGeom(self, index):
-    """
-    Return a downcast geom on this space.
-    """
-    return self.getGeom(index).convert()
-Dtool_funcToMethod(getConvertedGeom, OdeSpace)
-del getConvertedGeom
-
-def getConvertedSpace(self):
-    """
-    """
-    return self.getSpace().convert()
-Dtool_funcToMethod(getConvertedSpace, OdeSpace)
-del getConvertedSpace
-
-def getAABounds(self):
-    """
-    A more Pythonic way of calling getAABB()
-    """
-    min = Point3()
-    max = Point3()
-    self.getAABB(min,max)
-    return min,max
-Dtool_funcToMethod(getAABounds, OdeSpace)
-del getAABounds
-

+ 0 - 16
direct/src/extensions_native/Ramfile_extensions.py

@@ -1,16 +0,0 @@
-"""
-Ramfile_extensions module: contains methods to extend functionality
-of the Ramfile class
-"""
-
-def readlines(self):
-    """Reads all the lines at once and returns a list."""
-    lines = []
-    line = self.readline()
-    while line:
-        lines.append(line)
-        line = self.readline()
-    return lines
-
-Dtool_funcToMethod(readlines, Ramfile)
-del readlines    

+ 0 - 16
direct/src/extensions_native/StreamReader_extensions.py

@@ -1,16 +0,0 @@
-"""
-StreamReader_extensions module: contains methods to extend functionality
-of the StreamReader class
-"""
-
-def readlines(self):
-    """Reads all the lines at once and returns a list."""
-    lines = []
-    line = self.readline()
-    while line:
-        lines.append(line)
-        line = self.readline()
-    return lines
-    
-Dtool_funcToMethod(readlines, StreamReader)        
-del readlines

+ 1 - 1
direct/src/showbase/Messenger.py

@@ -7,7 +7,7 @@ from PythonUtil import *
 from direct.directnotify import DirectNotifyGlobal
 import types
 
-from libpandaexpress import ConfigVariableBool
+from panda3d.core import ConfigVariableBool
 
 # If using the Toontown ActiveX launcher, this must be set true.
 # Also, Panda must be compiled with SIMPLE_THREADS or no HAVE_THREADS

+ 1 - 4
direct/src/showbase/PythonUtil.py

@@ -60,10 +60,7 @@ import bisect
 __report_indent = 3
 
 from direct.directutil import Verify
-# Don't import libpandaexpressModules, which doesn't get built until
-# genPyCode.
-import direct.extensions_native.extension_native_helpers
-from libpandaexpress import ConfigVariableBool
+from panda3d.core import ConfigVariableBool
 
 ScalarTypes = (types.FloatType, types.IntType, types.LongType)
 

+ 28 - 18
dtool/src/interrogate/functionRemap.cxx

@@ -14,7 +14,7 @@
 
 #include "functionRemap.h"
 #include "typeManager.h"
-#include "interrogate.h" 
+#include "interrogate.h"
 #include "parameterRemap.h"
 #include "parameterRemapThis.h"
 #include "interfaceMaker.h"
@@ -324,7 +324,6 @@ make_wrapper_entry(FunctionIndex function_index) {
       _flags |= F_explicit_self;
     }
   }
-      
 
   if (!_void_return) {
     iwrapper._flags |= InterrogateFunctionWrapper::F_has_return;
@@ -340,15 +339,15 @@ make_wrapper_entry(FunctionIndex function_index) {
   if (_return_value_needs_management) {
     iwrapper._flags |= InterrogateFunctionWrapper::F_caller_manages;
     FunctionIndex destructor = _return_value_destructor;
-    
+
     if (destructor != 0) {
       iwrapper._return_value_destructor = destructor;
-      
+
     } else {
       // We don't need to report this warning, since the FFI code
       // understands that if the destructor function is zero, it
       // should use the regular class destructor.
-      
+
       //          nout << "Warning!  Destructor for " 
       //               << *_return_type->get_orig_type()
       //               << " is unavailable.\n"
@@ -397,8 +396,12 @@ get_call_str(const string &container, const vector_string &pexprs) const {
 
     // If this function is marked as having an extension function,
     // call that instead.
-    if (_extension && !container.empty()) {
-      call << "invoke_extension(" << container << ").";
+    if (_extension) {
+      if (!container.empty()) {
+        call << "invoke_extension(" << container << ").";
+      } else {
+        call << "Extension<" << _cpptype->get_local_name(&parser) << ">::";
+      }
 
       call << _cppfunc->get_local_name();
       call << "(";
@@ -413,7 +416,7 @@ get_call_str(const string &container, const vector_string &pexprs) const {
         // If we have a "this" parameter, the calling convention is also
         // a bit different.
         call << "(" << container << ")->" << _cppfunc->get_local_name();
-        
+
       } else {
         call << _cppfunc->get_local_name(&parser);
       }
@@ -465,7 +468,7 @@ get_parameter_expr(int n, const vector_string &pexprs) const {
 ////////////////////////////////////////////////////////////////////
 bool FunctionRemap::
 setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_maker) {
-  _function_signature = 
+  _function_signature =
     TypeManager::get_function_signature(_cppfunc, _num_default_parameters);
   _expression = ifunc._expression;
 
@@ -519,7 +522,7 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
       _parameters.push_back(param);
       _first_true_parameter = 1;
     }
-      
+
     // Also check the name of the function.  If it's one of the
     // assignment-style operators, flag it as such.
     if (fname == "operator =" ||
@@ -611,7 +614,7 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
     }
   }
 
-  if (_return_type == (ParameterRemap *)NULL || 
+  if (_return_type == (ParameterRemap *)NULL ||
       !_return_type->is_valid()) {
     // If our return type isn't something we can deal with, treat the
     // function as if it returns NULL.
@@ -621,25 +624,25 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
     _return_type = interface_maker->remap_parameter(_cpptype, void_type);
     assert(_return_type != (ParameterRemap *)NULL);
   }
-  
+
   // Do we need to manage the return value?
-  _return_value_needs_management = 
+  _return_value_needs_management =
     _return_type->return_value_needs_management();
-  _return_value_destructor = 
+  _return_value_destructor =
     _return_type->get_return_value_destructor();
-  
+
   // Should we manage a reference count?
   CPPType *return_type = _return_type->get_new_type();
   return_type = TypeManager::resolve_type(return_type, _cppscope);
   CPPType *return_meat_type = TypeManager::unwrap_pointer(return_type);
-  
+
   if (manage_reference_counts &&
       TypeManager::is_reference_count_pointer(return_type) &&
       !TypeManager::has_protected_destructor(return_meat_type)) {
     // Yes!
     _manage_reference_count = true;
     _return_value_needs_management = true;
-    
+
     // This is problematic, because we might not have the class in
     // question fully defined here, particularly if the class is
     // defined in some other library.
@@ -709,11 +712,18 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
 
         _flags |= F_releasebuffer;
       }
+
+    } else if (fname == "compare_to" ) {
+      if (_has_this && _parameters.size() == 2 &&
+          TypeManager::is_integer(_return_type->get_new_type())) {
+        // It receives one parameter, and returns an integer.
+        _flags |= F_compare_to;
+      }
     }
 
   } else if (_type == T_constructor) {
     if (!_has_this && _parameters.size() == 1) {
-      if (TypeManager::unwrap(_parameters[0]._remap->get_orig_type()) == 
+      if (TypeManager::unwrap(_parameters[0]._remap->get_orig_type()) ==
           TypeManager::unwrap(_return_type->get_orig_type())) {
         // If this is the only parameter, and it's the same as the
         // "this" type, this is a copy constructor.

+ 2 - 1
dtool/src/interrogate/functionRemap.h

@@ -90,6 +90,7 @@ public:
     F_iter             = 0x0100,
     F_getbuffer        = 0x0200,
     F_releasebuffer    = 0x0400,
+    F_compare_to       = 0x0800,
   };
 
   typedef vector<Parameter> Parameters;
@@ -113,7 +114,7 @@ public:
   string _reported_name;
   string _wrapper_name;
   FunctionWrapperIndex _wrapper_index;
-  
+
   bool _return_value_needs_management;
   FunctionIndex _return_value_destructor;
   bool _manage_reference_count;

Fișier diff suprimat deoarece este prea mare
+ 177 - 137
dtool/src/interrogate/interfaceMakerPythonNative.cxx


+ 3 - 9
dtool/src/interrogatedb/extension.h

@@ -17,10 +17,7 @@
 
 #include "dtoolbase.h"
 
-struct _object;
-typedef struct _object PyObject;
-
-////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////
 //       Class : ExtensionBase
 // Description : This is where all extensions should derive from.
 //               It defines the _self and _this members that can
@@ -30,7 +27,6 @@ template<class T>
 class EXPCL_DTOOLCONFIG ExtensionBase {
 public:
   T * _this;
-  PyObject * _self;
 };
 
 ////////////////////////////////////////////////////////////////////
@@ -52,10 +48,9 @@ class EXPCL_DTOOLCONFIG Extension : public ExtensionBase<T> {
 ////////////////////////////////////////////////////////////////////
 template<class T>
 inline Extension<T>
-invoke_extension(T *ptr, PyObject *self = NULL) {
+invoke_extension(T *ptr) {
   Extension<T> ext;
   ext._this = ptr;
-  ext._self = self;
   return ext;
 }
 
@@ -65,10 +60,9 @@ invoke_extension(T *ptr, PyObject *self = NULL) {
 ////////////////////////////////////////////////////////////////////
 template<class T>
 inline const Extension<T>
-invoke_extension(const T *ptr, PyObject *self = NULL) {
+invoke_extension(const T *ptr) {
   Extension<T> ext;
   ext._this = (T *) ptr;
-  ext._self = self;
   return ext;
 }
 

+ 3 - 3
dtool/src/interrogatedb/py_panda.cxx

@@ -49,7 +49,7 @@ bool DtoolCanThisBeAPandaInstance(PyObject *self) {
 ////////////////////////////////////////////////////////////////////////
 void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject *classdef, void **answer) {
   if (DtoolCanThisBeAPandaInstance(self)) {
-    *answer = ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self,classdef);
+    *answer = ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self, classdef);
   } else {
     *answer = NULL;
   }
@@ -298,7 +298,7 @@ void *DTOOL_Call_GetPointerThis(PyObject *self) {
 // this function relies on the behavior of typed objects in the panda system.
 //
 ////////////////////////////////////////////////////////////////////////
-PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject & known_class_type, bool memory_rules, bool is_const, int RunTimeType) {     
+PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject & known_class_type, bool memory_rules, bool is_const, int RunTimeType) {
   if (local_this_in == NULL) {
     // Let's not be stupid..
     PyErr_SetString(PyExc_TypeError, "C Function Return Null 'this'");
@@ -339,7 +339,7 @@ PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject &
   // if we get this far .. just wrap the thing in the known type ??
   //    better than aborting...I guess....
   /////////////////////////////////////////////////////
-  Dtool_PyInstDef * self = (Dtool_PyInstDef *) known_class_type.As_PyTypeObject().tp_new(&known_class_type.As_PyTypeObject(), NULL, NULL);
+  Dtool_PyInstDef *self = (Dtool_PyInstDef *) known_class_type.As_PyTypeObject().tp_new(&known_class_type.As_PyTypeObject(), NULL, NULL);
   if (self != NULL) {
     self->_ptr_to_object = local_this_in;
     self->_memory_rules = memory_rules;

+ 1 - 0
dtool/src/prc/streamReader.h

@@ -70,6 +70,7 @@ PUBLISHED:
   BLOCKING size_t extract_bytes(unsigned char *into, size_t size);
 
   BLOCKING string readline();
+  EXTENSION(BLOCKING PyObject *readlines());
 
 private:
   istream *_in;

Fișier diff suprimat deoarece este prea mare
+ 260 - 195
makepanda/makepanda.py


+ 27 - 13
makepanda/makepandacore.py

@@ -9,13 +9,15 @@
 ##
 ########################################################################
 
-import sys,os,time,stat,string,re,getopt,fnmatch,threading,signal,shutil,platform,glob,getpass,signal,thread
+import sys,os,time,stat,string,re,getopt,fnmatch,threading,signal,shutil,platform,glob,getpass,signal
 from distutils import sysconfig
 
 if sys.version_info >= (3, 0):
     import pickle
+    import _thread as thread
 else:
     import cPickle as pickle
+    import thread
 
 SUFFIX_INC = [".cxx",".c",".h",".I",".yxx",".lxx",".mm",".rc",".r"]
 SUFFIX_DLL = [".dll",".dlo",".dle",".dli",".dlm",".mll",".exe",".pyd",".ocx"]
@@ -694,11 +696,16 @@ def CxxGetIncludes(path):
     except:
         exit("Cannot open source file \""+path+"\" for reading.")
     include = []
-    for line in sfile:
-        match = CxxIncludeRegex.match(line,0)
-        if (match):
-            incname = match.group(1)
-            include.append(incname)
+    try:
+        for line in sfile:
+            match = CxxIncludeRegex.match(line,0)
+            if (match):
+                incname = match.group(1)
+                include.append(incname)
+    except:
+        print("Failed to determine dependencies of \""+path+"\".")
+        raise
+
     sfile.close()
     CXXINCLUDECACHE[path] = [date, include]
     return include
@@ -1062,6 +1069,8 @@ def MakeBuildTree():
     MakeDirectory(OUTPUTDIR + "/models/gui")
     MakeDirectory(OUTPUTDIR + "/pandac")
     MakeDirectory(OUTPUTDIR + "/pandac/input")
+    MakeDirectory(OUTPUTDIR + "/panda3d")
+    CreateFile(OUTPUTDIR + "/panda3d/__init__.py")
 
     if GetTarget() == 'android':
         MakeDirectory(OUTPUTDIR + "/libs")
@@ -2412,10 +2421,10 @@ def ParsePandaVersion(fn):
         f = open(fn, "r")
         pattern = re.compile('^[ \t]*[#][ \t]*define[ \t]+PANDA_VERSION[ \t]+([0-9]+)[ \t]+([0-9]+)[ \t]+([0-9]+)')
         for line in f:
-            match = pattern.match(line,0)
+            match = pattern.match(line, 0)
             if (match):
                 f.close()
-                return match.group(1)+"."+match.group(2)+"."+match.group(3)
+                return match.group(1) + "." + match.group(2) + "." + match.group(3)
         f.close()
     except: pass
     return "0.0.0"
@@ -2428,7 +2437,7 @@ def ParsePluginVersion(fn):
             match = pattern.match(line,0)
             if (match):
                 f.close()
-                return match.group(1)+"."+match.group(2)+"."+match.group(3)
+                return match.group(1) + "." + match.group(2) + "." + match.group(3)
         f.close()
     except: pass
     return "0.0.0"
@@ -2522,7 +2531,7 @@ def WriteResourceFile(basename, **kwargs):
 ##
 ########################################################################
 
-ORIG_EXT={}
+ORIG_EXT = {}
 
 def GetOrigExt(x):
     return ORIG_EXT[x]
@@ -2556,7 +2565,7 @@ def CalcLocation(fn, ipath):
         if (fn.endswith(".res")):   return OUTPUTDIR+"/tmp/"+fn
         if (fn.endswith(".tlb")):   return OUTPUTDIR+"/tmp/"+fn
         if (fn.endswith(".dll")):   return OUTPUTDIR+"/bin/"+fn[:-4]+dllext+".dll"
-        if (fn.endswith(".pyd")):   return OUTPUTDIR+"/bin/"+fn[:-4]+dllext+".pyd"
+        if (fn.endswith(".pyd")):   return OUTPUTDIR+"/panda3d/"+fn[:-4]+dllext+".pyd"
         if (fn.endswith(".ocx")):   return OUTPUTDIR+"/plugins/"+fn[:-4]+dllext+".ocx"
         if (fn.endswith(".mll")):   return OUTPUTDIR+"/plugins/"+fn[:-4]+dllext+".mll"
         if (fn.endswith(".dlo")):   return OUTPUTDIR+"/plugins/"+fn[:-4]+dllext+".dlo"
@@ -2572,7 +2581,7 @@ def CalcLocation(fn, ipath):
         if (fn.endswith(".plist")): return CxxFindSource(fn, ipath)
         if (fn.endswith(".obj")):   return OUTPUTDIR+"/tmp/"+fn[:-4]+".o"
         if (fn.endswith(".dll")):   return OUTPUTDIR+"/lib/"+fn[:-4]+".dylib"
-        if (fn.endswith(".pyd")):   return OUTPUTDIR+"/lib/"+fn[:-4]+".so"
+        if (fn.endswith(".pyd")):   return OUTPUTDIR+"/panda3d/"+fn[:-4]+".so"
         if (fn.endswith(".mll")):   return OUTPUTDIR+"/plugins/"+fn
         if (fn.endswith(".exe")):   return OUTPUTDIR+"/bin/"+fn[:-4]
         if (fn.endswith(".lib")):   return OUTPUTDIR+"/lib/"+fn[:-4]+".a"
@@ -2593,7 +2602,7 @@ def CalcLocation(fn, ipath):
     else:
         if (fn.endswith(".obj")):   return OUTPUTDIR+"/tmp/"+fn[:-4]+".o"
         if (fn.endswith(".dll")):   return OUTPUTDIR+"/lib/"+fn[:-4]+".so"
-        if (fn.endswith(".pyd")):   return OUTPUTDIR+"/lib/"+fn[:-4]+".so"
+        if (fn.endswith(".pyd")):   return OUTPUTDIR+"/panda3d/"+fn[:-4]+".so"
         if (fn.endswith(".mll")):   return OUTPUTDIR+"/plugins/"+fn
         if (fn.endswith(".plugin")):return OUTPUTDIR+"/plugins/"+fn[:-7]+dllext+".so"
         if (fn.endswith(".exe")):   return OUTPUTDIR+"/bin/"+fn[:-4]
@@ -2669,6 +2678,11 @@ def TargetAdd(target, dummy=0, opts=0, input=0, dep=0, ipath=0, winrc=0):
     if (ipath == 0): ipath = []
     if (type(input) == str): input = [input]
     if (type(dep) == str): dep = [dep]
+
+    if os.path.splitext(target)[1] == '.pyd' and PkgSkip("PYTHON"):
+        # It makes no sense to build Python modules with python disabled.
+        return
+
     full = FindLocation(target, [OUTPUTDIR + "/include"])
 
     if (full not in TARGET_TABLE):

+ 2 - 2
panda/src/display/Sources.pp

@@ -27,8 +27,8 @@
     graphicsDevice.h graphicsDevice.I \
     graphicsPipe.I graphicsPipe.h  \
     graphicsPipeSelection.I graphicsPipeSelection.h \
-    graphicsStateGuardian.I \
-    graphicsStateGuardian.h \
+    graphicsStateGuardian.I graphicsStateGuardian.h \
+    graphicsStateGuardian_ext.cxx graphicsStateGuardian_ext.h \
     graphicsThreadingModel.I graphicsThreadingModel.h \
     graphicsWindow.I graphicsWindow.h \
     graphicsWindowInputDevice.I  \

+ 18 - 51
panda/src/display/graphicsStateGuardian.cxx

@@ -59,13 +59,6 @@
 #include <algorithm>
 #include <limits.h>
 
-#ifdef HAVE_PYTHON
-#include "py_panda.h"
-#ifndef CPPPARSER
-IMPORT_THIS struct Dtool_PyTypedObject Dtool_Texture;
-#endif
-#endif  // HAVE_PYTHON
-
 PStatCollector GraphicsStateGuardian::_vertex_buffer_switch_pcollector("Vertex buffer switch:Vertex");
 PStatCollector GraphicsStateGuardian::_index_buffer_switch_pcollector("Vertex buffer switch:Index");
 PStatCollector GraphicsStateGuardian::_load_vertex_buffer_pcollector("Draw:Transfer data:Vertex buffer");
@@ -247,10 +240,10 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
   // The default is no shader support.
   _auto_detect_shader_model = SM_00;
   _shader_model = SM_00;
-  
+
   _gamma = 1.0f;
   _texture_quality_override = Texture::QL_default;
-  
+
   _shader_generator = NULL;
 }
 
@@ -435,41 +428,6 @@ void GraphicsStateGuardian::
 restore_gamma() {
 }
 
-#ifdef HAVE_PYTHON
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsStateGuardian::get_prepared_textures
-//       Access: Published
-//  Description: Returns a Python list of all of the
-//               currently-prepared textures within the GSG.
-////////////////////////////////////////////////////////////////////
-PyObject *GraphicsStateGuardian::
-get_prepared_textures() const {
-  ReMutexHolder holder(_prepared_objects->_lock);
-  size_t num_textures = _prepared_objects->_prepared_textures.size();
-  PyObject *list = PyList_New(num_textures);
-
-  size_t i = 0;
-  PreparedGraphicsObjects::Textures::const_iterator ti;
-  for (ti = _prepared_objects->_prepared_textures.begin();
-       ti != _prepared_objects->_prepared_textures.end();
-       ++ti) {
-    PT(Texture) tex = (*ti)->get_texture();
-
-    PyObject *element = 
-      DTool_CreatePyInstanceTyped(tex, Dtool_Texture,
-                                  true, false, tex->get_type_index());
-    tex->ref();
-
-    nassertr(i < num_textures, NULL);
-    PyList_SetItem(list, i, element);
-    ++i;
-  }
-  nassertr(i == num_textures, NULL);
-
-  return list;
-}
-#endif  // HAVE_PYTHON
-
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::traverse_prepared_textures
 //       Access: Public
@@ -485,7 +443,7 @@ traverse_prepared_textures(GraphicsStateGuardian::TextureCallback *func,
   for (ti = _prepared_objects->_prepared_textures.begin();
        ti != _prepared_objects->_prepared_textures.end();
        ++ti) {
-    bool result = (*func)(*ti,callback_arg);
+    bool result = (*func)(*ti, callback_arg);
     if (!result) {
       return;
     }
@@ -2473,11 +2431,11 @@ determine_target_texture() {
            target_tex_gen != (TexGenAttrib *)NULL);
   _target_texture = target_texture;
   _target_tex_gen = target_tex_gen;
-  
+
   if (_has_texture_alpha_scale) {
     PT(TextureStage) stage = get_alpha_scale_texture_stage();
     PT(Texture) texture = TexturePool::get_alpha_scale_map();
-    
+
     _target_texture = DCAST(TextureAttrib, _target_texture->add_on_stage(stage, texture));
     _target_tex_gen = DCAST(TexGenAttrib, _target_tex_gen->add_stage
                                (stage, TexGenAttrib::M_constant, LTexCoord3(_current_color_scale[3], 0.0f, 0.0f)));
@@ -2801,6 +2759,9 @@ string GraphicsStateGuardian::get_driver_renderer() {
 //     Function: GraphicsStateGuardian::get_driver_version
 //       Access: Public, Virtual
 //  Description: Returns driver version
+//               This has an implementation-defined meaning, and may
+//               be "0" if the particular graphics implementation
+//               does not provide a way to query this information.
 ////////////////////////////////////////////////////////////////////
 string GraphicsStateGuardian::
 get_driver_version() {
@@ -2810,7 +2771,10 @@ get_driver_version() {
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_driver_version_major
 //       Access: Public, Virtual
-//  Description: Returns major version of the video driver
+//  Description: Returns major version of the video driver.
+//               This has an implementation-defined meaning, and may
+//               be -1 if the particular graphics implementation
+//               does not provide a way to query this information.
 ////////////////////////////////////////////////////////////////////
 int GraphicsStateGuardian::
 get_driver_version_major() {
@@ -2820,7 +2784,10 @@ get_driver_version_major() {
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_driver_version_minor
 //       Access: Public, Virtual
-//  Description: Returns the minor version of the video driver
+//  Description: Returns the minor version of the video driver.
+//               This has an implementation-defined meaning, and may
+//               be -1 if the particular graphics implementation
+//               does not provide a way to query this information.
 ////////////////////////////////////////////////////////////////////
 int GraphicsStateGuardian::
 get_driver_version_minor() {
@@ -2830,7 +2797,7 @@ get_driver_version_minor() {
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_driver_shader_version_major
 //       Access: Public, Virtual
-//  Description: Returns the major version of the shader model
+//  Description: Returns the major version of the shader model.
 ////////////////////////////////////////////////////////////////////
 int GraphicsStateGuardian::
 get_driver_shader_version_major() {
@@ -2840,7 +2807,7 @@ get_driver_shader_version_major() {
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_driver_shader_version_minor
 //       Access: Public, Virtual
-//  Description: Returns the minor version of the shader model
+//  Description: Returns the minor version of the shader model.
 ////////////////////////////////////////////////////////////////////
 int GraphicsStateGuardian::
 get_driver_shader_version_minor() {

+ 3 - 5
panda/src/display/graphicsStateGuardian.h

@@ -46,9 +46,9 @@
 #include "occlusionQueryContext.h"
 #include "stencilRenderStates.h"
 #include "loader.h"
-#include "textureAttrib.h"
-#include "texGenAttrib.h"
 #include "shaderAttrib.h"
+#include "texGenAttrib.h"
+#include "textureAttrib.h"
 
 class DrawableRegion;
 class GraphicsEngine;
@@ -179,9 +179,7 @@ PUBLISHED:
   INLINE void set_texture_quality_override(Texture::QualityLevel quality_level);
   INLINE Texture::QualityLevel get_texture_quality_override() const;
 
-#ifdef HAVE_PYTHON
-  PyObject *get_prepared_textures() const;
-#endif
+  EXTENSION(PyObject *get_prepared_textures() const);
   typedef bool TextureCallback(TextureContext *tc, void *callback_arg);
   void traverse_prepared_textures(TextureCallback *func, void *callback_arg);
 

+ 5 - 2
panda/src/egg/Sources.pp

@@ -24,6 +24,7 @@
      eggCurve.I eggCurve.h eggData.I eggData.h  \
      eggExternalReference.I eggExternalReference.h  \
      eggFilenameNode.I eggFilenameNode.h eggGroup.I eggGroup.h  \
+     eggGroupNode_ext.h \
      eggGroupNode.I eggGroupNode.h eggGroupUniquifier.h  \
      eggLine.I eggLine.h \
      eggMaterial.I eggMaterial.h eggMaterialCollection.I  \
@@ -69,7 +70,8 @@
      eggCompositePrimitive.cxx \
      eggCoordinateSystem.cxx  \
      eggCurve.cxx eggData.cxx eggExternalReference.cxx  \
-     eggFilenameNode.cxx eggGroup.cxx eggGroupNode.cxx  \
+     eggFilenameNode.cxx eggGroup.cxx  \
+     eggGroupNode_ext.cxx eggGroupNode.cxx  \
      eggGroupUniquifier.cxx eggLine.cxx eggMaterial.cxx  \
      eggMaterialCollection.cxx \
      eggMesher.cxx \
@@ -106,7 +108,8 @@
     eggCoordinateSystem.I eggCoordinateSystem.h eggCurve.I \
     eggCurve.h eggData.I eggData.h eggExternalReference.I \
     eggExternalReference.h eggFilenameNode.I eggFilenameNode.h \
-    eggGroup.I eggGroup.h eggGroupNode.I eggGroupNode.h \
+    eggGroup.I eggGroup.h \
+    eggGroupNode_ext.h eggGroupNode.I eggGroupNode.h \
     eggGroupUniquifier.h \
     eggLine.I eggLine.h \
     eggMaterial.I \

+ 2 - 0
panda/src/egg/eggGroupNode.h

@@ -113,6 +113,8 @@ PUBLISHED:
   EggNode *get_first_child();
   EggNode *get_next_child();
 
+  EXTENSION(PyObject *get_children() const);
+
   EggNode *add_child(EggNode *node);
   PT(EggNode) remove_child(EggNode *node);
   void steal_children(EggGroupNode &other);

+ 1 - 1
panda/src/event/pythonTask.cxx

@@ -158,7 +158,7 @@ get_args() {
     }
 
     this->ref();
-    PyObject *self = 
+    PyObject *self =
       DTool_CreatePyInstanceTyped(this, Dtool_TypedReferenceCount,
                                   true, false, get_type_index());
     PyTuple_SET_ITEM(with_task, num_args, self);

+ 9 - 3
panda/src/express/Sources.pp

@@ -6,7 +6,7 @@
   #define TARGET p3express
   #define USE_PACKAGES zlib openssl tar
   
-  #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
+  #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx $[TARGET]_ext_composite.cxx
 
   #define SOURCES \
     buffer.I buffer.h \
@@ -31,6 +31,7 @@
     memoryUsage.I memoryUsage.h \
     memoryUsagePointerCounts.I memoryUsagePointerCounts.h \
     memoryUsagePointers.I memoryUsagePointers.h \
+    memoryUsagePointers_ext.h \
     multifile.I multifile.h \
     namable.I \
     namable.h \
@@ -51,10 +52,11 @@
     pta_int.h \
     pta_uchar.h pta_double.h pta_float.h \
     pta_stdfloat.h \
-    ramfile.I ramfile.h \
+    ramfile.I ramfile.h ramfile_ext.h \
     referenceCount.I referenceCount.h \
     subStream.I subStream.h subStreamBuf.h \
     subfileInfo.h subfileInfo.I \
+    streamReader_ext.h \
     temporaryFile.h temporaryFile.I \
     threadSafePointerTo.I threadSafePointerTo.h \
     threadSafePointerToBase.I threadSafePointerToBase.h \
@@ -70,7 +72,7 @@
     virtualFileMountSystem.h virtualFileMountSystem.I \
     virtualFileSimple.h virtualFileSimple.I \
     virtualFileSystem.h virtualFileSystem.I \
-    virtualFileSystem_ext.h virtualFileSystem_ext.cxx \
+    virtualFileSystem_ext.h \
     weakPointerCallback.I weakPointerCallback.h \
     weakPointerTo.I weakPointerTo.h \
     weakPointerToBase.I weakPointerToBase.h \
@@ -92,6 +94,7 @@
     fileReference.cxx \
     hashGeneratorBase.cxx hashVal.cxx \
     memoryInfo.cxx memoryUsage.cxx memoryUsagePointerCounts.cxx \
+    memoryUsagePointers_ext.cxx \
     memoryUsagePointers.cxx multifile.cxx \
     namable.cxx \
     nodePointerTo.cxx \
@@ -109,8 +112,10 @@
     profileTimer.cxx \
     pta_int.cxx \
     pta_uchar.cxx pta_double.cxx pta_float.cxx \
+    ramfile_ext.cxx \
     ramfile.cxx \
     referenceCount.cxx \
+    streamReader_ext.cxx \
     subStream.cxx subStreamBuf.cxx \
     subfileInfo.cxx \
     temporaryFile.cxx \
@@ -125,6 +130,7 @@
     virtualFileMountRamdisk.cxx \
     virtualFileMountSystem.cxx \
     virtualFileSimple.cxx virtualFileSystem.cxx \
+    virtualFileSystem_ext.cxx \
     weakPointerCallback.cxx \
     weakPointerTo.cxx \
     weakPointerToBase.cxx \

+ 0 - 73
panda/src/express/memoryUsagePointers.cxx

@@ -20,20 +20,6 @@
 #include "referenceCount.h"
 #include "typedReferenceCount.h"
 
-#ifdef HAVE_PYTHON
-// Pick up a few declarations so we can create Python wrappers in
-// get_python_pointer(), below.
-
-#include "py_panda.h"  
-
-#ifndef CPPPARSER
-extern EXPCL_PANDAEXPRESS Dtool_PyTypedObject Dtool_TypedObject;
-extern EXPCL_PANDAEXPRESS Dtool_PyTypedObject Dtool_TypedReferenceCount;
-extern EXPCL_PANDAEXPRESS Dtool_PyTypedObject Dtool_ReferenceCount;
-#endif  // CPPPARSER
-
-#endif  // HAVE_PYTHON
-
 ////////////////////////////////////////////////////////////////////
 //     Function: MemoryUsagePointers::Constructor
 //       Access: Published
@@ -151,65 +137,6 @@ get_age(int n) const {
   return _entries[n]._age;
 }
 
-#ifdef HAVE_PYTHON
-////////////////////////////////////////////////////////////////////
-//     Function: MemoryUsagePointers::get_python_pointer
-//       Access: Published
-//  Description: Returns the nth object, represented as a Python
-//               object of the appropriate type.  Reference counting
-//               will be properly set on the Python object.
-//
-//               get_typed_pointer() is almost as good as this, but
-//               (a) it does not set the reference count, and (b) it
-//               does not work for objects that do not inherit from
-//               TypedObject.  This will work for any object whose
-//               type is known, which has a Python representation.
-////////////////////////////////////////////////////////////////////
-PyObject *MemoryUsagePointers::
-get_python_pointer(int n) const {
-  nassertr(n >= 0 && n < get_num_pointers(), NULL);
-  TypedObject *typed_ptr = _entries[n]._typed_ptr;
-  ReferenceCount *ref_ptr = _entries[n]._ref_ptr;
-
-  bool memory_rules = false;
-  if (ref_ptr != (ReferenceCount *)NULL) {
-    memory_rules = true;
-    ref_ptr->ref();
-  }
-
-  if (typed_ptr != (TypedObject *)NULL) {
-    return DTool_CreatePyInstanceTyped(typed_ptr, Dtool_TypedObject,
-                                       memory_rules, false, 
-                                       typed_ptr->get_type_index());
-  }
-
-  if (ref_ptr == (ReferenceCount *)NULL) {
-    return Py_BuildValue("");
-  }
-
-  TypeHandle type = _entries[n]._type;
-  if (type != TypeHandle::none()) {
-    // Use TypedReferenceCount if we have it.
-    if (type.is_derived_from(TypedReferenceCount::get_class_type())) {
-      TypedReferenceCount *typed_ref_ptr = (TypedReferenceCount *)ref_ptr;
-      
-      return DTool_CreatePyInstanceTyped(typed_ref_ptr, Dtool_TypedReferenceCount,
-                                         memory_rules, false, 
-                                         type.get_index());
-    }
-
-    // Otherwise, trust that there is a downcast path to the actual type.
-    return DTool_CreatePyInstanceTyped(ref_ptr, Dtool_ReferenceCount,
-                                       memory_rules, false, 
-                                       type.get_index());
-  }
-
-  // If worse comes to worst, just return a ReferenceCount wrapper.
-  return DTool_CreatePyInstance(ref_ptr, Dtool_ReferenceCount, 
-                                memory_rules, false);
-}
-#endif
-
 ////////////////////////////////////////////////////////////////////
 //     Function: MemoryUsagePointers::clear
 //       Access: Published

+ 1 - 3
panda/src/express/memoryUsagePointers.h

@@ -67,9 +67,7 @@ PUBLISHED:
   string get_type_name(int n) const;
   double get_age(int n) const;
 
-#ifdef HAVE_PYTHON
-  PyObject *get_python_pointer(int n) const;
-#endif
+  EXTENSION(PyObject *get_python_pointer(int n) const);
 
   void clear();
 

+ 72 - 0
panda/src/express/memoryUsagePointers_ext.cxx

@@ -0,0 +1,72 @@
+// Filename: memoryUsagePointers_ext.cxx
+// Created by:  rdb (10Dec13)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "memoryUsagePointers_ext.h"
+
+#if defined(HAVE_PYTHON) && defined(DO_MEMORY_USAGE)
+
+#ifndef CPPPARSER
+extern EXPCL_PANDAEXPRESS Dtool_PyTypedObject Dtool_TypedObject;
+extern EXPCL_PANDAEXPRESS Dtool_PyTypedObject Dtool_TypedReferenceCount;
+extern EXPCL_PANDAEXPRESS Dtool_PyTypedObject Dtool_ReferenceCount;
+#endif  // CPPPARSER
+
+////////////////////////////////////////////////////////////////////
+//     Function: MemoryUsagePointers::get_python_pointer
+//       Access: Published
+//  Description: Returns the nth object, represented as a Python
+//               object of the appropriate type.  Reference counting
+//               will be properly set on the Python object.
+//
+//               get_typed_pointer() is almost as good as this, but
+//               (a) it does not set the reference count, and (b) it
+//               does not work for objects that do not inherit from
+//               TypedObject.  This will work for any object whose
+//               type is known, which has a Python representation.
+////////////////////////////////////////////////////////////////////
+PyObject *Extension<MemoryUsagePointers>::
+get_python_pointer(int n) const {
+  TypedObject *typed_ptr = _this->get_typed_pointer(n);
+  ReferenceCount *ref_ptr = _this->get_pointer(n);
+
+  bool memory_rules = false;
+  if (ref_ptr != (ReferenceCount *)NULL) {
+    memory_rules = true;
+    ref_ptr->ref();
+  }
+
+  if (typed_ptr != (TypedObject *)NULL) {
+    return DTool_CreatePyInstanceTyped(typed_ptr, Dtool_TypedObject,
+                                       memory_rules, false,
+                                       typed_ptr->get_type_index());
+  }
+
+  if (ref_ptr == (ReferenceCount *)NULL) {
+    return Py_BuildValue("");
+  }
+
+  TypeHandle type = _this->get_type(n);
+  if (type != TypeHandle::none()) {
+    // Trust that there is a downcast path to the actual type.
+    return DTool_CreatePyInstanceTyped(ref_ptr, Dtool_ReferenceCount,
+                                       memory_rules, false,
+                                       type.get_index());
+  }
+
+  // If worse comes to worst, just return a ReferenceCount wrapper.
+  return DTool_CreatePyInstance(ref_ptr, Dtool_ReferenceCount,
+                                memory_rules, false);
+}
+
+#endif  // HAVE_PYTHON && DO_MEMORY_USAGE

+ 40 - 0
panda/src/express/memoryUsagePointers_ext.h

@@ -0,0 +1,40 @@
+// Filename: memoryUsagePointers_ext.h
+// Created by:  rdb (10Dec13)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef MEMORYUSAGEPOINTERS_EXT_H
+#define MEMORYUSAGEPOINTERS_EXT_H
+
+#include "dtoolbase.h"
+
+#if defined(HAVE_PYTHON) && defined(DO_MEMORY_USAGE)
+
+#include "extension.h"
+#include "memoryUsagePointers.h"
+#include "py_panda.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : Extension<MemoryUsagePointers>
+// Description : This class defines the extension methods for
+//               VirtualFileSystem, which are called instead of
+//               any C++ methods with the same prototype.
+////////////////////////////////////////////////////////////////////
+template<>
+class Extension<MemoryUsagePointers> : public ExtensionBase<MemoryUsagePointers> {
+public:
+  PyObject *get_python_pointer(int n) const;
+};
+
+#endif  // HAVE_PYTHON && DO_MEMORY_USAGE
+
+#endif  // MEMORYUSAGEPOINTERS_EXT_H

+ 4 - 0
panda/src/express/p3express_ext_composite.cxx

@@ -0,0 +1,4 @@
+#include "memoryUsagePointers_ext.cxx"
+#include "ramfile_ext.cxx"
+#include "streamReader_ext.cxx"
+#include "virtualFileSystem_ext.cxx"

+ 1 - 0
panda/src/express/ramfile.h

@@ -32,6 +32,7 @@ PUBLISHED:
   INLINE size_t tell() const;
   string read(size_t length);
   string readline();
+  EXTENSION(PyObject *readlines());
 
   INLINE const string &get_data() const;
   INLINE size_t get_data_size() const;

+ 48 - 0
panda/src/express/ramfile_ext.cxx

@@ -0,0 +1,48 @@
+// Filename: ramfile_ext.cxx
+// Created by:  rdb (10Dec13)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "ramfile_ext.h"
+
+#ifdef HAVE_PYTHON
+
+////////////////////////////////////////////////////////////////////
+//     Function: Ramfile::readlines
+//       Access: Published
+//  Description: Reads all the lines at once and returns a list.
+//               Also see the documentation for readline().
+////////////////////////////////////////////////////////////////////
+PyObject *Extension<Ramfile>::
+readlines() {
+  PyObject *lst = PyList_New(0);
+  if (lst == NULL) {
+    return NULL;
+  }
+
+  string line = _this->readline();
+  while (!line.empty()) {
+#if PY_MAJOR_VERSION >= 3
+    PyObject *py_line = PyBytes_FromStringAndSize(line.data(), line.size());
+#else
+    PyObject *py_line = PyString_FromStringAndSize(line.data(), line.size());
+#endif
+
+    PyList_Append(lst, py_line);
+    Py_DECREF(py_line);
+  }
+
+  return lst;
+}
+
+#endif
+

+ 40 - 0
panda/src/express/ramfile_ext.h

@@ -0,0 +1,40 @@
+// Filename: ramfile_ext.h
+// Created by:  rdb (10Dec13)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef RAMFILE_EXT_H
+#define RAMFILE_EXT_H
+
+#include "dtoolbase.h"
+
+#ifdef HAVE_PYTHON
+
+#include "extension.h"
+#include "ramfile.h"
+#include "py_panda.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : Extension<Ramfile>
+// Description : This class defines the extension methods for
+//               Ramfile, which are called instead of
+//               any C++ methods with the same prototype.
+////////////////////////////////////////////////////////////////////
+template<>
+class Extension<Ramfile> : public ExtensionBase<Ramfile> {
+public:
+  BLOCKING PyObject *readlines();
+};
+
+#endif  // HAVE_PYTHON
+
+#endif  // RAMFILE_EXT_H

+ 48 - 0
panda/src/express/streamReader_ext.cxx

@@ -0,0 +1,48 @@
+// Filename: streamReader_ext.cxx
+// Created by:  rdb (09Dec13)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "streamReader_ext.h"
+
+#ifdef HAVE_PYTHON
+
+////////////////////////////////////////////////////////////////////
+//     Function: StreamReader::readlines
+//       Access: Published
+//  Description: Reads all the lines at once and returns a list.
+//               Also see the documentation for readline().
+////////////////////////////////////////////////////////////////////
+PyObject *Extension<StreamReader>::
+readlines() {
+  PyObject *lst = PyList_New(0);
+  if (lst == NULL) {
+    return NULL;
+  }
+
+  string line = _this->readline();
+  while (!line.empty()) {
+#if PY_MAJOR_VERSION >= 3
+    PyObject *py_line = PyBytes_FromStringAndSize(line.data(), line.size());
+#else
+    PyObject *py_line = PyString_FromStringAndSize(line.data(), line.size());
+#endif
+
+    PyList_Append(lst, py_line);
+    Py_DECREF(py_line);
+  }
+
+  return lst;
+}
+
+#endif
+

+ 40 - 0
panda/src/express/streamReader_ext.h

@@ -0,0 +1,40 @@
+// Filename: streamReader_ext.h
+// Created by:  rdb (09Dec13)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef STREAMREADER_EXT_H
+#define STREAMREADER_EXT_H
+
+#include "dtoolbase.h"
+
+#ifdef HAVE_PYTHON
+
+#include "extension.h"
+#include "streamReader.h"
+#include "py_panda.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : Extension<StreamReader>
+// Description : This class defines the extension methods for
+//               StreamReader, which are called instead of
+//               any C++ methods with the same prototype.
+////////////////////////////////////////////////////////////////////
+template<>
+class Extension<StreamReader> : public ExtensionBase<StreamReader> {
+public:
+  BLOCKING PyObject *readlines();
+};
+
+#endif  // HAVE_PYTHON
+
+#endif  // STREAMREADER_EXT_H

+ 1 - 1
panda/src/express/virtualFileSystem_ext.cxx

@@ -79,4 +79,4 @@ write_file(const Filename &filename, PyObject *data, bool auto_wrap) {
   return PyBool_FromLong(result);
 }
 
-#endif  // HAVE_PYTHOS
+#endif  // HAVE_PYTHON

+ 1 - 1
panda/src/linmath/lpoint2_ext_src.I

@@ -82,5 +82,5 @@ __getattr__(const string &attr_name) const {
 INLINE_LINMATH int Extension<FLOATNAME(LPoint2)>::
 __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
   // Upcall to LVecBase2.
-  return invoke_extension<FLOATNAME(LVecBase2)>(_this, _self).__setattr__(self, attr_name, assign);
+  return invoke_extension<FLOATNAME(LVecBase2)>(_this).__setattr__(self, attr_name, assign);
 }

+ 1 - 1
panda/src/linmath/lpoint3_ext_src.I

@@ -83,5 +83,5 @@ __getattr__(const string &attr_name) const {
 INLINE_LINMATH int Extension<FLOATNAME(LPoint3)>::
 __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
   // Upcall to LVecBase2.
-  return invoke_extension<FLOATNAME(LVecBase3)>(_this, _self).__setattr__(self, attr_name, assign);
+  return invoke_extension<FLOATNAME(LVecBase3)>(_this).__setattr__(self, attr_name, assign);
 }

+ 1 - 1
panda/src/linmath/lpoint4_ext_src.I

@@ -88,5 +88,5 @@ __getattr__(const string &attr_name) const {
 INLINE_LINMATH int Extension<FLOATNAME(LPoint4)>::
 __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
   // Upcall to LVecBase4.
-  return invoke_extension<FLOATNAME(LVecBase4)>(_this, _self).__setattr__(self, attr_name, assign);
+  return invoke_extension<FLOATNAME(LVecBase4)>(_this).__setattr__(self, attr_name, assign);
 }

+ 1 - 1
panda/src/linmath/lvector2_ext_src.I

@@ -82,5 +82,5 @@ __getattr__(const string &attr_name) const {
 INLINE_LINMATH int Extension<FLOATNAME(LVector2)>::
 __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
   // Upcall to LVecBase2.
-  return invoke_extension<FLOATNAME(LVecBase2)>(_this, _self).__setattr__(self, attr_name, assign);
+  return invoke_extension<FLOATNAME(LVecBase2)>(_this).__setattr__(self, attr_name, assign);
 }

+ 1 - 1
panda/src/linmath/lvector3_ext_src.I

@@ -83,5 +83,5 @@ __getattr__(const string &attr_name) const {
 INLINE_LINMATH int Extension<FLOATNAME(LVector3)>::
 __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
   // Upcall to LVecBase3.
-  return invoke_extension<FLOATNAME(LVecBase3)>(_this, _self).__setattr__(self, attr_name, assign);
+  return invoke_extension<FLOATNAME(LVecBase3)>(_this).__setattr__(self, attr_name, assign);
 }

+ 1 - 1
panda/src/linmath/lvector4_ext_src.I

@@ -88,5 +88,5 @@ __getattr__(const string &attr_name) const {
 INLINE_LINMATH int Extension<FLOATNAME(LVector4)>::
 __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
   // Upcall to LVecBase4.
-  return invoke_extension<FLOATNAME(LVecBase4)>(_this, _self).__setattr__(self, attr_name, assign);
+  return invoke_extension<FLOATNAME(LVecBase4)>(_this).__setattr__(self, attr_name, assign);
 }

+ 14 - 10
panda/src/ode/Sources.pp

@@ -12,18 +12,21 @@
   #define USE_PACKAGES ode
     
   #define COMBINED_SOURCES $[TARGET]_composite1.cxx \
-    $[TARGET]_composite2.cxx $[TARGET]_composite3.cxx
+    $[TARGET]_composite2.cxx $[TARGET]_composite3.cxx \
+    $[TARGET]_ext_composite.cxx
 
   #define SOURCES \
     ode_includes.h config_ode.h \
     odeWorld.I odeWorld.h \
     odeMass.I odeMass.h \
-    odeBody.I odeBody.h \
+    odeBody.I odeBody.h odeBody_ext.h \
     odeJointGroup.I odeJointGroup.h \
-    odeJoint.I odeJoint.h \
-    odeUtil.h \
+    odeJoint.I odeJoint.h odeJoint_ext.h \
+    odeUtil.h odeUtil_ext.h \
     odeSpace.I odeSpace.h \
+    odeSpace_ext.I odeSpace_ext.h \
     odeGeom.I odeGeom.h \
+    odeGeom_ext.I odeGeom_ext.h \
     odeSurfaceParameters.I odeSurfaceParameters.h \
     odeContactGeom.I odeContactGeom.h \
     odeContact.I odeContact.h \
@@ -55,11 +58,13 @@
 
   #define INCLUDED_SOURCES \
     config_ode.cxx \
-    odeWorld.cxx odeMass.cxx odeBody.cxx \
-    odeJointGroup.cxx odeJoint.cxx \
-    odeUtil.cxx \
-    odeSpace.cxx \
-    odeGeom.cxx \
+    odeWorld.cxx odeMass.cxx \
+    odeBody.cxx odeBody_ext.cxx \
+    odeJointGroup.cxx \
+    odeJoint.cxx odeJoint_ext.cxx \
+    odeUtil.cxx odeUtil_ext.cxx \
+    odeSpace.cxx odeSpace_ext.cxx \
+    odeGeom.cxx odeGeom_ext.cxx \
     odeSurfaceParameters.cxx \
     odeContactGeom.cxx odeContact.cxx \
     odeAMotorJoint.cxx odeBallJoint.cxx \
@@ -118,4 +123,3 @@
   #define IGATESCAN all
 
 #end lib_target
-

+ 1 - 1
panda/src/ode/odeAMotorJoint.h

@@ -16,7 +16,7 @@
 class EXPCL_PANDAODE OdeAMotorJoint : public OdeJoint {
   friend class OdeJoint;
 
-private:
+public:
   OdeAMotorJoint(dJointID id);
 
 PUBLISHED:

+ 1 - 1
panda/src/ode/odeBallJoint.h

@@ -16,7 +16,7 @@
 class EXPCL_PANDAODE OdeBallJoint : public OdeJoint {
   friend class OdeJoint;
 
-private:
+public:
   OdeBallJoint(dJointID id);
 
 PUBLISHED:

+ 3 - 1
panda/src/ode/odeBody.h

@@ -39,7 +39,7 @@ class EXPCL_PANDAODE OdeBody : public TypedObject {
   friend class OdeGeom;
   friend class OdeCollisionEntry;
 
-protected:
+public:
   OdeBody(dBodyID id);
 
 PUBLISHED:
@@ -140,6 +140,8 @@ PUBLISHED:
   INLINE int get_num_joints() const;
   OdeJoint get_joint(int index) const;
   MAKE_SEQ(get_joints, get_num_joints, get_joint);
+  EXTENSION(INLINE PyObject *get_converted_joint(int i) const);
+
   INLINE void enable();
   INLINE void disable();
   INLINE int is_enabled() const;

+ 1 - 1
panda/src/ode/odeBoxGeom.h

@@ -29,7 +29,7 @@
 class EXPCL_PANDAODE OdeBoxGeom : public OdeGeom {
   friend class OdeGeom;
 
-private:
+public:
   OdeBoxGeom(dGeomID id);
 
 PUBLISHED:

+ 1 - 1
panda/src/ode/odeCappedCylinderGeom.h

@@ -29,7 +29,7 @@
 class EXPCL_PANDAODE OdeCappedCylinderGeom : public OdeGeom {
   friend class OdeGeom;
 
-private:
+public:
   OdeCappedCylinderGeom(dGeomID id);
 
 PUBLISHED:

+ 1 - 1
panda/src/ode/odeContactJoint.h

@@ -17,7 +17,7 @@
 class EXPCL_PANDAODE OdeContactJoint : public OdeJoint {
   friend class OdeJoint;
 
-private:
+public:
   OdeContactJoint(dJointID id);
 
 PUBLISHED:

+ 1 - 1
panda/src/ode/odeConvexGeom.h

@@ -29,7 +29,7 @@
 class EXPCL_PANDAODE OdeConvexGeom : public OdeGeom {
   friend class OdeGeom;
 
-private:
+public:
   OdeConvexGeom(dGeomID id);
 
 PUBLISHED:

+ 1 - 1
panda/src/ode/odeCylinderGeom.h

@@ -29,7 +29,7 @@
 class EXPCL_PANDAODE OdeCylinderGeom : public OdeGeom {
   friend class OdeGeom;
 
-private:
+public:
   OdeCylinderGeom(dGeomID id);
 
 PUBLISHED:

+ 1 - 1
panda/src/ode/odeFixedJoint.h

@@ -16,7 +16,7 @@
 class EXPCL_PANDAODE OdeFixedJoint : public OdeJoint {
   friend class OdeJoint;
 
-private:
+public:
   OdeFixedJoint(dJointID id);
 
 PUBLISHED:

+ 6 - 6
panda/src/ode/odeGeom.h

@@ -50,7 +50,7 @@ class EXPCL_PANDAODE OdeGeom : public TypedObject {
   friend class OdeUtil;
   friend class OdeCollisionEntry;
 
-protected:
+public:
   OdeGeom(dGeomID id);
 
 PUBLISHED:
@@ -87,6 +87,7 @@ PUBLISHED:
   INLINE LMatrix3f get_rotation() const;
   INLINE LQuaternionf get_quaternion() const;
   INLINE void get_AABB(LVecBase3f &min, LVecBase3f &max) const;
+  EXTENSION(INLINE PyObject *get_AA_bounds() const);
   INLINE int is_space();
   INLINE int get_class() const;
   INLINE void set_category_bits(const BitMask32 &bits);
@@ -109,21 +110,22 @@ PUBLISHED:
   INLINE LPoint3f get_offset_position() const;
   INLINE LMatrix3f get_offset_rotation() const;
   INLINE LQuaternionf get_offset_quaternion() const;
-  
+
   //int get_surface_type() ;
   //int get_collide_id() ;
   //int set_collide_id( int collide_id);
   //void set_surface_type( int surface_type);
-  
-  //int test_collide_id( int collide_id);
 
+  //int test_collide_id( int collide_id);
 
   OdeSpace get_space() const;
+  EXTENSION(INLINE PyObject *get_converted_space() const);
 
   virtual void write(ostream &out = cout, unsigned int indent=0) const;
   operator bool () const;
   INLINE int compare_to(const OdeGeom &other) const;
 
+  EXTENSION(PyObject *convert() const);
   OdeBoxGeom convert_to_box() const;
   OdeCappedCylinderGeom convert_to_capped_cylinder() const;
   // OdeConvexGeom convert_to_convex() const;
@@ -136,8 +138,6 @@ PUBLISHED:
   OdeSimpleSpace convert_to_simple_space() const;
   OdeHashSpace convert_to_hash_space() const;
   OdeQuadTreeSpace convert_to_quad_tree_space() const;
-  
-  
 
 public:
   INLINE static int get_geom_class() { return -1; };

+ 1 - 1
panda/src/ode/odeHashSpace.h

@@ -31,7 +31,7 @@ class EXPCL_PANDAODE OdeHashSpace : public OdeSpace {
   friend class OdeSpace;
   friend class OdeGeom;
 
-private:
+public:
   OdeHashSpace(dSpaceID id);
 
 PUBLISHED:

+ 1 - 1
panda/src/ode/odeHeightFieldGeom.h

@@ -29,7 +29,7 @@
 class EXPCL_PANDAODE OdeHeightfieldGeom : public OdeGeom {
   friend class OdeGeom;
 
-private:
+public:
   OdeHeightfieldGeom(dGeomID id);
 
 PUBLISHED:

+ 1 - 1
panda/src/ode/odeHinge2Joint.h

@@ -16,7 +16,7 @@
 class EXPCL_PANDAODE OdeHinge2Joint : public OdeJoint {
   friend class OdeJoint;
 
-private:
+public:
   OdeHinge2Joint(dJointID id);
 
 PUBLISHED:

+ 1 - 1
panda/src/ode/odeHingeJoint.h

@@ -15,7 +15,7 @@
 class EXPCL_PANDAODE OdeHingeJoint : public OdeJoint {
   friend class OdeJoint;
 
-private:
+public:
   OdeHingeJoint(dJointID id);
 
 PUBLISHED:

+ 1 - 1
panda/src/ode/odeJoint.cxx

@@ -52,7 +52,7 @@ destroy() {
 void OdeJoint::
 attach_bodies(const OdeBody &body1, const OdeBody &body2) {
   nassertv(_id);
-  nassertv(body1.get_id() != 0 && body2.get_id() != 0);
+  nassertv(body1.get_id() != 0 || body2.get_id() != 0);
   dJointAttach(_id, body1.get_id(), body2.get_id());
 }
 

+ 6 - 6
panda/src/ode/odeJoint.h

@@ -32,7 +32,7 @@ PUBLISHED:
 };
 
 // Strange, we should be forced to include this by get_body()
-class OdeBody; 
+class OdeBody;
 
 class OdeBallJoint;
 class OdeHingeJoint;
@@ -48,7 +48,7 @@ class OdePlane2dJoint;
 
 ////////////////////////////////////////////////////////////////////
 //       Class : OdeJoint
-// Description : 
+// Description :
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDAODE OdeJoint : public TypedObject {
   friend class OdeBody;
@@ -56,8 +56,6 @@ class EXPCL_PANDAODE OdeJoint : public TypedObject {
 
 public:
   OdeJoint();
-
-protected:
   OdeJoint(dJointID id);
 
 PUBLISHED:
@@ -78,7 +76,7 @@ PUBLISHED:
   void destroy();
   INLINE bool is_empty() const;
   INLINE dJointID get_id() const;
-  
+
   /* INLINE void set_data(void *data); */
   /* INLINE void *get_data(); */
   INLINE int get_joint_type() const;
@@ -86,7 +84,8 @@ PUBLISHED:
   INLINE void set_feedback(OdeJointFeedback *);
   INLINE void set_feedback(bool flag = true);
   INLINE OdeJointFeedback *get_feedback();
-   
+
+  EXTENSION(void attach(const OdeBody *body1, const OdeBody *body2));
   void attach_bodies(const OdeBody &body1, const OdeBody &body2);
   void attach_body(const OdeBody &body, int index);
   void detach();
@@ -96,6 +95,7 @@ PUBLISHED:
   INLINE bool operator == (const OdeJoint &other) const;
   operator bool () const;
 
+  EXTENSION(PyObject *convert() const);
   OdeBallJoint convert_to_ball() const;
   OdeHingeJoint convert_to_hinge() const;
   OdeSliderJoint convert_to_slider() const;

+ 1 - 1
panda/src/ode/odeLMotorJoint.h

@@ -15,7 +15,7 @@
 class EXPCL_PANDAODE OdeLMotorJoint : public OdeJoint {
   friend class OdeJoint;
 
-private:
+public:
   OdeLMotorJoint(dJointID id);
 
 PUBLISHED:

+ 1 - 1
panda/src/ode/odeNullJoint.h

@@ -15,7 +15,7 @@
 class EXPCL_PANDAODE OdeNullJoint : public OdeJoint {
   friend class OdeJoint;
 
-private:
+public:
   OdeNullJoint(dJointID id);
 
 PUBLISHED:

+ 1 - 1
panda/src/ode/odePlane2dJoint.h

@@ -15,7 +15,7 @@
 class EXPCL_PANDAODE OdePlane2dJoint : public OdeJoint {
   friend class OdeJoint;
 
-private:
+public:
   OdePlane2dJoint(dJointID id);
 
 PUBLISHED:

+ 1 - 1
panda/src/ode/odePlaneGeom.h

@@ -28,7 +28,7 @@
 class EXPCL_PANDAODE OdePlaneGeom : public OdeGeom {
   friend class OdeGeom;
 
-private:
+public:
   OdePlaneGeom(dGeomID id);
 
 PUBLISHED:

+ 1 - 1
panda/src/ode/odeQuadTreeSpace.h

@@ -30,7 +30,7 @@ class EXPCL_PANDAODE OdeQuadTreeSpace : public OdeSpace {
   friend class OdeSpace;
   friend class OdeGeom;
 
-private:
+public:
   OdeQuadTreeSpace(dSpaceID id);
 
 PUBLISHED:

+ 1 - 1
panda/src/ode/odeRayGeom.h

@@ -28,7 +28,7 @@
 class EXPCL_PANDAODE OdeRayGeom : public OdeGeom {
   friend class OdeGeom;
 
-private:
+public:
   OdeRayGeom(dGeomID id);
 
 PUBLISHED:

+ 1 - 1
panda/src/ode/odeSimpleSpace.h

@@ -30,7 +30,7 @@ class EXPCL_PANDAODE OdeSimpleSpace : public OdeSpace {
   friend class OdeSpace;
   friend class OdeGeom;
 
-private:
+public:
   OdeSimpleSpace(dSpaceID id);
 
 PUBLISHED:

+ 1 - 1
panda/src/ode/odeSliderJoint.h

@@ -15,7 +15,7 @@
 class EXPCL_PANDAODE OdeSliderJoint : public OdeJoint {
   friend class OdeJoint;
 
-private:
+public:
   OdeSliderJoint(dJointID id);
 
 PUBLISHED:

+ 12 - 62
panda/src/ode/odeSpace.cxx

@@ -17,23 +17,12 @@
 
 #include "throw_event.h"
 
-#ifdef HAVE_PYTHON
-  #include "py_panda.h"
-  #include "typedReferenceCount.h"
-  #ifndef CPPPARSER
-    extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeGeom;
-  #endif
-#endif
-
 TypeHandle OdeSpace::_type_handle;
 // this data is used in auto_collide
 const int OdeSpace::MAX_CONTACTS = 16; 
 OdeWorld* OdeSpace::_static_auto_collide_world; 
 OdeSpace* OdeSpace::_static_auto_collide_space; 
 dJointGroupID OdeSpace::_static_auto_collide_joint_group; 
-#ifdef HAVE_PYTHON
-PyObject* OdeSpace::_python_callback = NULL;
-#endif
 
 OdeSpace::
 OdeSpace(dSpaceID id) : 
@@ -142,23 +131,23 @@ auto_callback(void *data, dGeomID o1, dGeomID o2) {
   dBodyID b2 = dGeomGetBody(o2);
 
   dContact contact[OdeSpace::MAX_CONTACTS];
-      
+
   int surface1 = _static_auto_collide_space->get_surface_type(o1);
   int surface2 = _static_auto_collide_space->get_surface_type(o2);
-  
+
   nassertv(_static_auto_collide_world != NULL);
   sSurfaceParams collide_params;
   collide_params = _static_auto_collide_world->get_surface(surface1, surface2);
-  
+
   for (i=0; i < OdeSpace::MAX_CONTACTS; i++) {
-    contact[i].surface.mode = collide_params.colparams.mode; 
-    contact[i].surface.mu = collide_params.colparams.mu; 
-    contact[i].surface.mu2 = collide_params.colparams.mu2; 
-    contact[i].surface.bounce = collide_params.colparams.bounce; 
-    contact[i].surface.bounce_vel = collide_params.colparams.bounce_vel; 
-    contact[i].surface.soft_cfm = collide_params.colparams.soft_cfm; 
+    contact[i].surface.mode = collide_params.colparams.mode;
+    contact[i].surface.mu = collide_params.colparams.mu;
+    contact[i].surface.mu2 = collide_params.colparams.mu2;
+    contact[i].surface.bounce = collide_params.colparams.bounce;
+    contact[i].surface.bounce_vel = collide_params.colparams.bounce_vel;
+    contact[i].surface.soft_cfm = collide_params.colparams.soft_cfm;
   }
-  
+
   static int numc = 0;
   numc = dCollide(o1, o2, OdeSpace::MAX_CONTACTS, &contact[0].geom, sizeof(dContact));
 
@@ -177,7 +166,7 @@ auto_callback(void *data, dGeomID o1, dGeomID o2) {
       entry->_num_contacts = numc;
       entry->_contact_geoms = new OdeContactGeom[numc];
     }
-    
+
     for(i=0; i < numc; i++) {
       dJointID c = dJointCreateContact(_static_auto_collide_world->get_id(), _static_auto_collide_joint_group, contact + i);
       if ((_static_auto_collide_space->get_collide_id(o1) >= 0) && (_static_auto_collide_space->get_collide_id(o2) >= 0)) {
@@ -188,51 +177,13 @@ auto_callback(void *data, dGeomID o1, dGeomID o2) {
       }
     }
     _static_auto_collide_world->set_dampen_on_bodies(b1, b2, collide_params.dampen);
-    
+
     if (!_static_auto_collide_space->_collision_event.empty()) {
       throw_event(_static_auto_collide_space->_collision_event, EventParameter(entry));
     }
   }
 }
 
-#ifdef HAVE_PYTHON
-int OdeSpace::
-collide(PyObject* arg, PyObject* callback) {
-  nassertr(callback != NULL, -1);
-  if (!PyCallable_Check(callback)) {
-    PyErr_Format(PyExc_TypeError, "'%s' object is not callable", callback->ob_type->tp_name);
-    return -1;
-  } else if (_id == NULL) {
-    // Well, while we're in the mood of python exceptions, let's make this one too.
-    PyErr_Format(PyExc_TypeError, "OdeSpace is not valid!");
-    return -1;
-  } else {
-    OdeSpace::_python_callback = (PyObject*) callback;
-    Py_XINCREF(OdeSpace::_python_callback);
-    dSpaceCollide(_id, (void*) arg, &near_callback);
-    Py_XDECREF(OdeSpace::_python_callback);
-    return 0;
-  }
-}
-
-void OdeSpace::
-near_callback(void *data, dGeomID o1, dGeomID o2) {
-  OdeGeom *g1 = new OdeGeom(o1);
-  OdeGeom *g2 = new OdeGeom(o2);
-  PyObject *p1 = DTool_CreatePyInstanceTyped(g1, Dtool_OdeGeom, true, false, g1->get_type_index());
-  PyObject *p2 = DTool_CreatePyInstanceTyped(g2, Dtool_OdeGeom, true, false, g2->get_type_index());
-  PyObject *result = PyEval_CallFunction(_python_callback, "OOO", (PyObject*) data, p1, p2);
-  if (!result) {
-    odespace_cat.error() << "An error occurred while calling python function!\n";
-    PyErr_Print();
-  } else {
-    Py_DECREF(result);
-  }
-  Py_XDECREF(p2);
-  Py_XDECREF(p1);
-}
-#endif
-
 OdeSimpleSpace OdeSpace::
 convert_to_simple_space() const {
   nassertr(_id != 0, OdeSimpleSpace((dSpaceID)0));
@@ -309,4 +260,3 @@ get_collide_id(dGeomID id) {
   }
   return 0;
 }
-

+ 12 - 21
panda/src/ode/odeSpace.h

@@ -26,11 +26,6 @@
 
 #include "ode_includes.h"
 
-#ifdef HAVE_PYTHON
-  #include "py_panda.h"
-  #include "Python.h"
-#endif
-
 class OdeGeom;
 class OdeTriMeshGeom;
 class OdeSimpleSpace;
@@ -39,15 +34,15 @@ class OdeQuadTreeSpace;
 
 ////////////////////////////////////////////////////////////////////
 //       Class : OdeSpace
-// Description : 
+// Description :
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDAODE OdeSpace : public TypedObject {
   friend class OdeGeom;
   static const int MAX_CONTACTS;
 
-protected:
+public:
   OdeSpace(dSpaceID id);
-  
+
 PUBLISHED:
   virtual ~OdeSpace();
   void destroy();
@@ -59,6 +54,7 @@ PUBLISHED:
   int query(const OdeSpace& space) const;
   INLINE int get_num_geoms() const;
   INLINE void get_AABB(LVecBase3f &min, LVecBase3f &max) const;
+  EXTENSION(INLINE PyObject *get_AA_bounds() const);
   INLINE int is_space();
   INLINE int get_class() const;
   INLINE void set_category_bits(const BitMask32 &bits);
@@ -78,7 +74,7 @@ PUBLISHED:
   void clean();
   OdeGeom get_geom(int i); // Not INLINE because of forward declaration
   //static int get_surface_type(OdeSpace * self, dGeomID o1);
-  
+
   INLINE OdeSpace get_space() const;
 
   virtual void write(ostream &out = cout, unsigned int indent=0) const;
@@ -87,11 +83,13 @@ PUBLISHED:
   OdeSimpleSpace convert_to_simple_space() const;
   OdeHashSpace convert_to_hash_space() const;
   OdeQuadTreeSpace convert_to_quad_tree_space() const;
-  
+
+  EXTENSION(PyObject *convert() const);
+  EXTENSION(INLINE PyObject *get_converted_geom(int i) const);
+  EXTENSION(INLINE PyObject *get_converted_space() const);
+
   void auto_collide();
-#ifdef HAVE_PYTHON
-  int collide(PyObject* arg, PyObject* near_callback);
-#endif
+  EXTENSION(int collide(PyObject* arg, PyObject* near_callback));
   int set_collide_id(int collide_id, dGeomID id);
   int set_collide_id(OdeGeom& geom, int collide_id);
   void set_surface_type( int surface_type, dGeomID id);
@@ -106,17 +104,11 @@ PUBLISHED:
 
 public:
   static void auto_callback(void*, dGeomID, dGeomID);
-#ifdef HAVE_PYTHON
-  static void near_callback(void*, dGeomID, dGeomID);
-#endif
-  
+
   INLINE dSpaceID get_id() const;
   static OdeWorld* _static_auto_collide_world;
   static OdeSpace* _static_auto_collide_space;
   static dJointGroupID _static_auto_collide_joint_group;
-#ifdef HAVE_PYTHON
-  static PyObject* _python_callback;
-#endif
   static int contactCount;
   string _collision_event;
 
@@ -153,4 +145,3 @@ private:
 #include "odeSpace.I"
 
 #endif
-

+ 1 - 1
panda/src/ode/odeSphereGeom.h

@@ -28,7 +28,7 @@
 class EXPCL_PANDAODE OdeSphereGeom : public OdeGeom {
   friend class OdeGeom;
 
-private:
+public:
   OdeSphereGeom(dGeomID id);
 
 PUBLISHED:

+ 1 - 4
panda/src/ode/odeTriMeshGeom.h

@@ -29,7 +29,7 @@
 class EXPCL_PANDAODE OdeTriMeshGeom : public OdeGeom {
   friend class OdeGeom;
 
-private:
+public:
   OdeTriMeshGeom(dGeomID id);
 
 PUBLISHED:
@@ -56,9 +56,6 @@ public:
   INLINE dTriMeshDataID get_tri_mesh_data_id() const;
   INLINE dTriMeshDataID get_data_id() const;
 
-private:
-  void operator = (const OdeTriMeshGeom &copy);
-
 public:
   static TypeHandle get_class_type() {
     return _type_handle;

+ 1 - 1
panda/src/ode/odeUniversalJoint.h

@@ -16,7 +16,7 @@
 class EXPCL_PANDAODE OdeUniversalJoint : public OdeJoint {
   friend class OdeJoint;
 
-private:
+public:
   OdeUniversalJoint(dJointID id);
 
 PUBLISHED:

+ 3 - 54
panda/src/ode/odeUtil.cxx

@@ -14,20 +14,8 @@
 
 #include "odeUtil.h"
 
-#ifdef HAVE_PYTHON
-  #include "py_panda.h"
-  #include "typedReferenceCount.h"
-  #ifndef CPPPARSER
-    extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeGeom;
-  #endif
-#endif
-
 dReal OdeUtil::OC_infinity = dInfinity;
 
-#ifdef HAVE_PYTHON
-PyObject* OdeUtil::_python_callback = NULL;
-#endif
-
 ////////////////////////////////////////////////////////////////////
 //     Function: OdeUtil::get_connecting_joint
 //       Access: Public, Static
@@ -47,7 +35,7 @@ get_connecting_joint(const OdeBody &body1, const OdeBody &body2) {
 OdeJointCollection OdeUtil::
 get_connecting_joint_list(const OdeBody &body1, const OdeBody &body2) {
   const int max_possible_joints = min(body1.get_num_joints(), body1.get_num_joints());
-  
+
   dJointID *joint_list = (dJointID *)PANDA_MALLOC_ARRAY(max_possible_joints * sizeof(dJointID));
   int num_joints = dConnectingJointList(body1.get_id(), body2.get_id(),
           joint_list);
@@ -55,7 +43,7 @@ get_connecting_joint_list(const OdeBody &body1, const OdeBody &body2) {
   for (int i = 0; i < num_joints; i++) {
     joints.add_joint(OdeJoint(joint_list[i]));
   }
-  
+
   PANDA_FREE_ARRAY(joint_list);
   return joints;
 }
@@ -113,51 +101,12 @@ collide(const OdeGeom &geom1, const OdeGeom &geom2, const short int max_contacts
   for (int i = 0; i < num_contacts; i++) {
     entry->_contact_geoms[i] = contact_list[i];
   }
-  
+
   PANDA_FREE_ARRAY(contact_list);
   return entry;
 }
 
-#ifdef HAVE_PYTHON
-////////////////////////////////////////////////////////////////////
-//     Function: OdeUtil::collide2
-//       Access: Public, Static
-//  Description: Calls the callback for all potentially intersecting
-//               pairs that contain one geom from geom1 and one geom
-//               from geom2.
-////////////////////////////////////////////////////////////////////
-int OdeUtil::
-collide2(const OdeGeom &geom1, const OdeGeom &geom2, PyObject* arg, PyObject* callback) {
-  nassertr(callback != NULL, -1);
-  if (!PyCallable_Check(callback)) {
-    PyErr_Format(PyExc_TypeError, "'%s' object is not callable", callback->ob_type->tp_name);
-    return -1;
-  } else {
-    _python_callback = (PyObject*) callback;
-    Py_XINCREF(_python_callback);
-    dSpaceCollide2(geom1.get_id(), geom2.get_id(), (void*) arg, &near_callback);
-    Py_XDECREF(_python_callback);
-    return 0;
-  }
-}
-
-void OdeUtil::
-near_callback(void *data, dGeomID o1, dGeomID o2) {
-  ode_cat.spam() << "near_callback called, data: " << data << ", dGeomID1: " << o1 << ", dGeomID2: " << o2 << "\n";
-  OdeGeom g1 (o1);
-  OdeGeom g2 (o2);
-  PyObject* p1 = DTool_CreatePyInstanceTyped(&g1, Dtool_OdeGeom, true, false, g1.get_type_index());
-  PyObject* p2 = DTool_CreatePyInstanceTyped(&g2, Dtool_OdeGeom, true, false, g2.get_type_index());
-  PyObject* result = PyEval_CallFunction(_python_callback, "OOO", (PyObject*) data, p1, p2);
-  if (!result) {
-    ode_cat.error() << "An error occurred while calling python function!\n";
-    PyErr_Print();
-  }
-}
-#endif
-
 OdeGeom OdeUtil::
 space_to_geom(const OdeSpace &space) {
   return OdeGeom((dGeomID)space.get_id());
 }
-

+ 4 - 14
panda/src/ode/odeUtil.h

@@ -23,10 +23,6 @@
 #include "odeJointCollection.h"
 #include "odeCollisionEntry.h"
 
-#ifdef HAVE_PYTHON
-  #include "py_panda.h"
-#endif
-
 class OdeBody;
 class OdeJoint;
 class OdeGeom;
@@ -48,10 +44,10 @@ PUBLISHED:
                                      const int joint_type);
   static PT(OdeCollisionEntry) collide(const OdeGeom &geom1, const OdeGeom &geom2,
                                       const short int max_contacts = 150);
-#ifdef HAVE_PYTHON
-  static int collide2(const OdeGeom &geom1, const OdeGeom &geom2,
-                      PyObject* arg, PyObject* callback);
-#endif
+
+  EXTENSION(static int collide2(const OdeGeom &geom1, const OdeGeom &geom2,
+                                PyObject* arg, PyObject* callback));
+
   static OdeGeom space_to_geom(const OdeSpace &space);
 
   static dReal OC_infinity;
@@ -62,12 +58,6 @@ PUBLISHED:
   static int rand_get_seed() {return dRandGetSeed();};
 
   static void rand_set_seed(int s) {dRandSetSeed(s);};
-  
-private:
-#ifdef HAVE_PYTHON
-  static void near_callback(void*, dGeomID, dGeomID);
-  static PyObject* _python_callback;
-#endif
 };
 
 #endif

+ 4 - 0
panda/src/ode/p3ode_ext_composite.cxx

@@ -0,0 +1,4 @@
+#include "odeGeom_ext.cxx"
+#include "odeJoint_ext.cxx"
+#include "odeSpace_ext.cxx"
+#include "odeUtil_ext.cxx"

+ 3 - 0
panda/src/pgraph/Sources.pp

@@ -72,7 +72,10 @@
     modelPool.I modelPool.h \
     modelRoot.I modelRoot.h \
     nodePath.I nodePath.h nodePath.cxx \
+    nodePath_ext.I nodePath_ext.h nodePath_ext.cxx \
     nodePathCollection.I nodePathCollection.h \
+    nodePathCollection_ext.I nodePathCollection_ext.h \
+    nodePathCollection_ext.cxx \
     nodePathComponent.I nodePathComponent.h \
     occluderEffect.I occluderEffect.h \
     occluderNode.I occluderNode.h \

+ 0 - 159
panda/src/pgraph/nodePath.I

@@ -2197,57 +2197,6 @@ get_tag_keys(vector_string &keys) const {
   node()->get_tag_keys(keys);
 }
 
-#ifdef HAVE_PYTHON
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::get_python_tag_keys
-//       Access: Published
-//  Description: Fills the given vector up with the
-//               list of Python tags on this PandaNode.
-//
-//               It is the user's responsibility to ensure that the
-//               keys vector is empty before making this call;
-//               otherwise, the new files will be appended to it.
-////////////////////////////////////////////////////////////////////
-INLINE void NodePath::
-get_python_tag_keys(vector_string &keys) const {
-  nassertv_always(!is_empty());
-  node()->get_python_tag_keys(keys);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Filename::get_tag_keys
-//       Access: Published
-//  Description: This variant on get_tag_keys returns a Python list
-//               of strings. Returns None if the NodePath is empty.
-////////////////////////////////////////////////////////////////////
-INLINE PyObject *NodePath::
-get_tag_keys() const {
-  // An empty NodePath returns None
-  if (is_empty()) {
-    Py_INCREF(Py_None);
-    return Py_None;
-  }
-  return node()->get_tag_keys();
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Filename::get_python_tag_keys
-//       Access: Published
-//  Description: This variant on get_python_tag_keys returns a
-//               Python list of strings.
-//               Returns None if the NodePath is empty.
-////////////////////////////////////////////////////////////////////
-INLINE PyObject *NodePath::
-get_python_tag_keys() const {
-  // An empty NodePath returns None
-  if (is_empty()) {
-    Py_INCREF(Py_None);
-    return Py_None;
-  }
-  return node()->get_python_tag_keys();
-}
-#endif  // HAVE_PYTHON
-
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePath::has_tag
 //       Access: Published
@@ -2305,114 +2254,6 @@ has_net_tag(const string &key) const {
   return !find_net_tag(key).is_empty();
 }
 
-#ifdef HAVE_PYTHON 
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_python_tag
-//       Access: Published
-//  Description: Associates an arbitrary Python object with a
-//               user-defined key which is stored on the node.  This
-//               object has no meaning to Panda; but it is stored
-//               indefinitely on the node until it is requested again.
-//
-//               Each unique key stores a different Python object.
-//               There is no effective limit on the number of
-//               different keys that may be stored or on the nature of
-//               any one key's object.
-////////////////////////////////////////////////////////////////////
-INLINE void NodePath::
-set_python_tag(const string &key, PyObject *value) {
-  nassertv_always(!is_empty());
-  node()->set_python_tag(key, value);
-}
-#endif  // HAVE_PYTHON
-
-#ifdef HAVE_PYTHON 
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::get_python_tag
-//       Access: Published
-//  Description: Retrieves the Python object that was previously
-//               set on this node for the particular key, if any.  If
-//               no object has been previously set, returns None.
-//               See also get_net_python_tag().
-////////////////////////////////////////////////////////////////////
-INLINE PyObject *NodePath::
-get_python_tag(const string &key) const {
-  // An empty NodePath quietly returns no tags.  This makes
-  // get_net_python_tag() easier to implement.
-  if (is_empty()) {
-    Py_INCREF(Py_None);
-    return Py_None;
-  }
-  return node()->get_python_tag(key);
-}
-#endif  // HAVE_PYTHON
-
-#ifdef HAVE_PYTHON 
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::has_python_tag
-//       Access: Published
-//  Description: Returns true if a Python object has been defined on
-//               this node for the particular key (even if that value
-//               is the empty string), or false if no value has been
-//               set.  See also has_net_python_tag().
-////////////////////////////////////////////////////////////////////
-INLINE bool NodePath::
-has_python_tag(const string &key) const {
-  // An empty NodePath quietly has no tags.  This makes has_net_python_tag()
-  // easier to implement.
-  if (is_empty()) {
-    return false;
-  }
-  return node()->has_python_tag(key);
-}
-#endif  // HAVE_PYTHON
-
-#ifdef HAVE_PYTHON 
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::clear_python_tag
-//       Access: Published
-//  Description: Removes the Python object defined for this key on this
-//               particular node.  After a call to clear_python_tag(),
-//               has_python_tag() will return false for the indicated
-//               key.
-////////////////////////////////////////////////////////////////////
-INLINE void NodePath::
-clear_python_tag(const string &key) {
-  nassertv_always(!is_empty());
-  node()->clear_python_tag(key);
-}
-#endif  // HAVE_PYTHON
-
-#ifdef HAVE_PYTHON 
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::get_net_python_tag
-//       Access: Published
-//  Description: Returns the Python object that has been defined on
-//               this node, or the nearest ancestor node, for the
-//               indicated key.  If no value has been defined for the
-//               indicated key on any ancestor node, returns None.
-//               See also get_python_tag().
-////////////////////////////////////////////////////////////////////
-INLINE PyObject *NodePath::
-get_net_python_tag(const string &key) const {
-  return find_net_python_tag(key).get_python_tag(key);
-}
-#endif  // HAVE_PYTHON
-
-#ifdef HAVE_PYTHON 
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::has_net_python_tag
-//       Access: Published
-//  Description: Returns true if the indicated Python object has been
-//               defined on this node or on any ancestor node, or
-//               false otherwise.  See also has_python_tag().
-////////////////////////////////////////////////////////////////////
-INLINE bool NodePath::
-has_net_python_tag(const string &key) const {
-  return !find_net_python_tag(key).is_empty();
-}
-#endif  // HAVE_PYTHON
-
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePath::list_tags
 //       Access: Published

+ 0 - 220
panda/src/pgraph/nodePath.cxx

@@ -177,166 +177,6 @@ NodePath(const NodePath &parent, PandaNode *child_node,
   _backup_key = 0;
 }
 
-#ifdef HAVE_PYTHON
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::__copy__
-//       Access: Published
-//  Description: A special Python method that is invoked by
-//               copy.copy(node).  Unlike the NodePath copy
-//               constructor, this makes a duplicate copy of the
-//               underlying PandaNode (but shares children, instead of
-//               copying them or omitting them).
-////////////////////////////////////////////////////////////////////
-NodePath NodePath::
-__copy__() const {
-  if (is_empty()) {
-    // Invoke the copy constructor if we have no node.
-    return *this;
-  }
-
-  // If we do have a node, duplicate it, and wrap it in a new
-  // NodePath.
-  return NodePath(node()->__copy__());
-}
-#endif  // HAVE_PYTHON
-
-#ifdef HAVE_PYTHON
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::__deepcopy__
-//       Access: Published
-//  Description: A special Python method that is invoked by
-//               copy.deepcopy(np).  This calls copy_to() unless the
-//               NodePath is already present in the provided
-//               dictionary.
-////////////////////////////////////////////////////////////////////
-PyObject *NodePath::
-__deepcopy__(PyObject *self, PyObject *memo) const {
-  IMPORT_THIS struct Dtool_PyTypedObject Dtool_NodePath;
-
-  // Borrowed reference.
-  PyObject *dupe = PyDict_GetItem(memo, self);
-  if (dupe != NULL) {
-    // Already in the memo dictionary.
-    Py_INCREF(dupe);
-    return dupe;
-  }
-
-  NodePath *np_dupe;
-  if (is_empty()) {
-    np_dupe = new NodePath(*this);
-  } else {
-    np_dupe = new NodePath(copy_to(NodePath()));
-  }
-
-  dupe = DTool_CreatePyInstance((void *)np_dupe, Dtool_NodePath,
-                                true, false);
-  if (PyDict_SetItem(memo, self, dupe) != 0) {
-    Py_DECREF(dupe);
-    return NULL;
-  }
-
-  return dupe;
-}
-#endif  // HAVE_PYTHON
-
-#ifdef HAVE_PYTHON
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::__reduce__
-//       Access: Published
-//  Description: This special Python method is implement to provide
-//               support for the pickle module.
-//
-//               This hooks into the native pickle and cPickle
-//               modules, but it cannot properly handle
-//               self-referential BAM objects.
-////////////////////////////////////////////////////////////////////
-PyObject *NodePath::
-__reduce__(PyObject *self) const {
-  return __reduce_persist__(self, NULL);
-}
-#endif  // HAVE_PYTHON
-
-#ifdef HAVE_PYTHON
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::__reduce_persist__
-//       Access: Published
-//  Description: This special Python method is implement to provide
-//               support for the pickle module.
-//
-//               This is similar to __reduce__, but it provides
-//               additional support for the missing persistent-state
-//               object needed to properly support self-referential
-//               BAM objects written to the pickle stream.  This hooks
-//               into the pickle and cPickle modules implemented in
-//               direct/src/stdpy.
-////////////////////////////////////////////////////////////////////
-PyObject *NodePath::
-__reduce_persist__(PyObject *self, PyObject *pickler) const {
-  // We should return at least a 2-tuple, (Class, (args)): the
-  // necessary class object whose constructor we should call
-  // (e.g. this), and the arguments necessary to reconstruct this
-  // object.
-
-  BamWriter *writer = NULL;
-  if (pickler != NULL) {
-    PyObject *py_writer = PyObject_GetAttrString(pickler, "bamWriter");
-    if (py_writer == NULL) {
-      // It's OK if there's no bamWriter.
-      PyErr_Clear();
-    } else {
-      DTOOL_Call_ExtractThisPointerForType(py_writer, &Dtool_BamWriter, (void **)&writer);
-      Py_DECREF(py_writer);
-    }
-  }
-
-  // We have a non-empty NodePath.
-
-  string bam_stream;
-  if (!encode_to_bam_stream(bam_stream, writer)) {
-    ostringstream stream;
-    stream << "Could not bamify " << this;
-    string message = stream.str();
-    PyErr_SetString(PyExc_TypeError, message.c_str());
-    return NULL;
-  }
-
-  // Start by getting this class object.
-  PyObject *this_class = PyObject_Type(self);
-  if (this_class == NULL) {
-    return NULL;
-  }
-
-  PyObject *func;
-  if (writer != NULL) {
-    // The modified pickle support: call the "persistent" version of
-    // this function, which receives the unpickler itself as an
-    // additional parameter.
-    func = TypedWritable::find_global_decode(this_class, "py_decode_NodePath_from_bam_stream_persist");
-    if (func == NULL) {
-      PyErr_SetString(PyExc_TypeError, "Couldn't find py_decode_NodePath_from_bam_stream_persist()");
-      Py_DECREF(this_class);
-      return NULL;
-    }
-
-  } else {
-    // The traditional pickle support: call the non-persistent version
-    // of this function.
-
-    func = TypedWritable::find_global_decode(this_class, "py_decode_NodePath_from_bam_stream");
-    if (func == NULL) {
-      PyErr_SetString(PyExc_TypeError, "Couldn't find py_decode_NodePath_from_bam_stream()");
-      Py_DECREF(this_class);
-      return NULL;
-    }
-  }
-
-  PyObject *result = Py_BuildValue("(O(s#))", func, bam_stream.data(), bam_stream.size());
-  Py_DECREF(func);
-  Py_DECREF(this_class);
-  return result;
-}
-#endif  // HAVE_PYTHON
-
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePath::operator bool
 //       Access: Published
@@ -6908,27 +6748,6 @@ find_net_tag(const string &key) const {
   return get_parent().find_net_tag(key);
 }
 
-#ifdef HAVE_PYTHON 
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::find_net_python_tag
-//       Access: Published
-//  Description: Returns the lowest ancestor of this node that
-//               contains a tag definition with the indicated key, if
-//               any, or an empty NodePath if no ancestor of this node
-//               contains this tag definition.  See set_python_tag().
-////////////////////////////////////////////////////////////////////
-NodePath NodePath::
-find_net_python_tag(const string &key) const {
-  if (is_empty()) {
-    return NodePath::not_found();
-  }
-  if (has_python_tag(key)) {
-    return *this;
-  }
-  return get_parent().find_net_python_tag(key);
-}
-#endif  // HAVE_PYTHON
-
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePath::write_bam_file
 //       Access: Published
@@ -8053,42 +7872,3 @@ r_find_all_materials(PandaNode *node, const RenderState *state,
   }
 }
 
-#ifdef HAVE_PYTHON
-////////////////////////////////////////////////////////////////////
-//     Function: py_decode_NodePath_from_bam_stream
-//       Access: Published
-//  Description: This wrapper is defined as a global function to suit
-//               pickle's needs.
-////////////////////////////////////////////////////////////////////
-NodePath
-py_decode_NodePath_from_bam_stream(const string &data) {
-  return py_decode_NodePath_from_bam_stream_persist(NULL, data);
-}
-#endif  // HAVE_PYTHON
-
-
-#ifdef HAVE_PYTHON
-////////////////////////////////////////////////////////////////////
-//     Function: py_decode_NodePath_from_bam_stream_persist
-//       Access: Published
-//  Description: This wrapper is defined as a global function to suit
-//               pickle's needs.
-////////////////////////////////////////////////////////////////////
-NodePath
-py_decode_NodePath_from_bam_stream_persist(PyObject *unpickler, const string &data) {
-  BamReader *reader = NULL;
-  if (unpickler != NULL) {
-    PyObject *py_reader = PyObject_GetAttrString(unpickler, "bamReader");
-    if (py_reader == NULL) {
-      // It's OK if there's no bamReader.
-      PyErr_Clear();
-    } else {
-      DTOOL_Call_ExtractThisPointerForType(py_reader, &Dtool_BamReader, (void **)&reader);
-      Py_DECREF(py_reader);
-    }
-  }
-
-  return NodePath::decode_from_bam_stream(data, reader);
-}
-#endif  // HAVE_PYTHON
-

+ 16 - 25
panda/src/pgraph/nodePath.h

@@ -179,12 +179,10 @@ PUBLISHED:
   INLINE NodePath(const NodePath &copy);
   INLINE void operator = (const NodePath &copy);
 
-#ifdef HAVE_PYTHON
-  NodePath __copy__() const;
-  PyObject *__deepcopy__(PyObject *self, PyObject *memo) const;
-  PyObject *__reduce__(PyObject *self) const;
-  PyObject *__reduce_persist__(PyObject *self, PyObject *pickler) const;
-#endif
+  EXTENSION(NodePath __copy__() const);
+  EXTENSION(PyObject *__deepcopy__(PyObject *self, PyObject *memo) const);
+  EXTENSION(PyObject *__reduce__(PyObject *self) const);
+  EXTENSION(PyObject *__reduce_persist__(PyObject *self, PyObject *pickler) const);
 
   INLINE static NodePath not_found();
   INLINE static NodePath removed();
@@ -881,6 +879,8 @@ PUBLISHED:
   bool calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
                          Thread *current_thread = Thread::get_current_thread()) const;
 
+  EXTENSION(PyObject *get_tight_bounds() const);
+
   //  void analyze() const;
 
   int flatten_light();
@@ -898,18 +898,16 @@ PUBLISHED:
   INLINE bool has_net_tag(const string &key) const;
   NodePath find_net_tag(const string &key) const;
 
-#ifdef HAVE_PYTHON
-  INLINE PyObject *get_tag_keys() const;
-  INLINE void set_python_tag(const string &key, PyObject *value);
-  INLINE PyObject *get_python_tag(const string &key) const;
-  INLINE void get_python_tag_keys(vector_string &keys) const;
-  INLINE PyObject *get_python_tag_keys() const;
-  INLINE bool has_python_tag(const string &key) const;
-  INLINE void clear_python_tag(const string &key);
-  INLINE PyObject *get_net_python_tag(const string &key) const;
-  INLINE bool has_net_python_tag(const string &key) const;
-  NodePath find_net_python_tag(const string &key) const;
-#endif  // HAVE_PYTHON
+  EXTENSION(INLINE PyObject *get_tag_keys() const);
+  EXTENSION(INLINE void set_python_tag(const string &key, PyObject *value));
+  EXTENSION(INLINE PyObject *get_python_tag(const string &key) const);
+  EXTENSION(INLINE void get_python_tag_keys(vector_string &keys) const);
+  EXTENSION(INLINE PyObject *get_python_tag_keys() const);
+  EXTENSION(INLINE bool has_python_tag(const string &key) const);
+  EXTENSION(INLINE void clear_python_tag(const string &key));
+  EXTENSION(INLINE PyObject *get_net_python_tag(const string &key) const);
+  EXTENSION(INLINE bool has_net_python_tag(const string &key) const);
+  EXTENSION(NodePath find_net_python_tag(const string &key) const);
 
   INLINE void list_tags() const;
 
@@ -1015,13 +1013,6 @@ private:
 
 INLINE ostream &operator << (ostream &out, const NodePath &node_path);
 
-#ifdef HAVE_PYTHON
-BEGIN_PUBLISH
-NodePath py_decode_NodePath_from_bam_stream(const string &data);
-NodePath py_decode_NodePath_from_bam_stream_persist(PyObject *unpickler, const string &data);
-END_PUBLISH
-#endif
-
 #include "nodePath.I"
 
 #endif

+ 44 - 32
panda/src/pgraph/nodePathCollection.cxx

@@ -96,37 +96,6 @@ NodePathCollection(PyObject *self, PyObject *sequence) {
 }
 #endif  // HAVE_PYTHON
 
-#ifdef HAVE_PYTHON
-////////////////////////////////////////////////////////////////////
-//     Function: NodePathCollection::__reduce__
-//       Access: Published
-//  Description: This special Python method is implement to provide
-//               support for the pickle module.
-////////////////////////////////////////////////////////////////////
-PyObject *NodePathCollection::
-__reduce__(PyObject *self) const {
-  // Here we will return a 4-tuple: (Class, (args), None, iterator),
-  // where iterator is an iterator that will yield successive
-  // NodePaths.
-
-  // We should return at least a 2-tuple, (Class, (args)): the
-  // necessary class object whose constructor we should call
-  // (e.g. this), and the arguments necessary to reconstruct this
-  // object.
-
-  PyObject *this_class = PyObject_Type(self);
-  if (this_class == NULL) {
-    return NULL;
-  }
-
-  // Since a NodePathCollection is itself an iterator, we can simply
-  // pass it as the fourth tuple component.
-  PyObject *result = Py_BuildValue("(O()OO)", this_class, Py_None, self);
-  Py_DECREF(this_class);
-  return result;
-}
-#endif  // HAVE_PYTHON
-
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePathCollection::add_path
 //       Access: Published
@@ -490,7 +459,7 @@ get_collide_mask() const {
 //       Access: Published
 //  Description: Recursively applies the indicated CollideMask to the
 //               into_collide_masks for all nodes at this level and
-//               below.  Only nodes 
+//               below.
 //
 //               The default is to change all bits, but if
 //               bits_to_change is not all bits on, then only the bits
@@ -506,6 +475,49 @@ set_collide_mask(CollideMask new_mask, CollideMask bits_to_change,
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: NodePathCollection::calc_tight_bounds
+//       Access: Published
+//  Description: Calculates the minimum and maximum vertices of all
+//               Geoms at these NodePath's bottom nodes and below
+//               This is a tight bounding box; it will generally be
+//               tighter than the bounding volume returned by
+//               get_bounds() (but it is more expensive to compute).
+//
+//               The return value is true if any points are within the
+//               bounding volume, or false if none are.
+////////////////////////////////////////////////////////////////////
+bool NodePathCollection::
+calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point) const {
+  bool have_bounds = false;
+
+  for (int i = 0; i < get_num_paths(); i++) {
+    LPoint3 tmp_min;
+    LPoint3 tmp_max;
+
+    if (get_path(i).is_empty()) {
+      continue;
+    }
+
+    if (get_path(i).calc_tight_bounds(tmp_min, tmp_max)) {
+      if (!have_bounds) {
+        min_point = tmp_min;
+        max_point = tmp_max;
+        have_bounds = true;
+      } else {
+        min_point.set(min(min_point._v(0), tmp_min._v(0)),
+                      min(min_point._v(1), tmp_min._v(1)),
+                      min(min_point._v(2), tmp_min._v(2)));
+        max_point.set(max(max_point._v(0), tmp_max._v(0)),
+                      max(max_point._v(1), tmp_max._v(1)),
+                      max(max_point._v(2), tmp_max._v(2)));
+      }
+    }
+  }
+
+  return have_bounds;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePathCollection::set_texture
 //       Access: Published

+ 5 - 1
panda/src/pgraph/nodePathCollection.h

@@ -35,7 +35,7 @@ PUBLISHED:
 
 #ifdef HAVE_PYTHON
   NodePathCollection(PyObject *self, PyObject *sequence);
-  PyObject *__reduce__(PyObject *self) const;
+  EXTENSION(PyObject *__reduce__(PyObject *self) const);
 #endif
 
   void add_path(const NodePath &node_path);
@@ -77,6 +77,10 @@ PUBLISHED:
   void set_collide_mask(CollideMask new_mask, CollideMask bits_to_change = CollideMask::all_on(),
                         TypeHandle node_type = TypeHandle::none());
 
+  bool calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point) const;
+
+  EXTENSION(PyObject *get_tight_bounds() const);
+
   void set_texture(Texture *tex, int priority = 0);
   void set_texture(TextureStage *stage, Texture *tex, int priority = 0);
   void set_texture_off(int priority = 0);

+ 3 - 2
panda/src/putil/Sources.pp

@@ -64,7 +64,8 @@
     sparseArray.I sparseArray.h \
     string_utils.I string_utils.N string_utils.h \
     timedCycle.I timedCycle.h typedWritable.I \
-    typedWritable.h typedWritableReferenceCount.I \
+    typedWritable.h typedWritable_ext.h typedWritable_ext.cxx \
+    typedWritableReferenceCount.I \
     typedWritableReferenceCount.h updateSeq.I updateSeq.h \
     uniqueIdAllocator.h \
     vector_typedWritable.h \
@@ -174,7 +175,7 @@
     sparseArray.I sparseArray.h \
     string_utils.I string_utils.h \
     timedCycle.I timedCycle.h typedWritable.I \
-    typedWritable.h typedWritableReferenceCount.I \
+    typedWritable.h typedWritable_ext.h typedWritableReferenceCount.I \
     typedWritableReferenceCount.h updateSeq.I updateSeq.h \
     uniqueIdAllocator.h \
     vector_typedWritable.h \

+ 9 - 262
panda/src/putil/typedWritable.cxx

@@ -25,13 +25,6 @@ LightMutex TypedWritable::_bam_writers_lock;
 TypeHandle TypedWritable::_type_handle;
 TypedWritable* const TypedWritable::Null = (TypedWritable*)0L;
 
-#ifdef HAVE_PYTHON
-#include "py_panda.h"  
-#ifndef CPPPARSER
-extern EXPCL_PANDA_PUTIL Dtool_PyTypedObject Dtool_BamWriter;
-#endif  // CPPPARSER
-#endif  // HAVE_PYTHON
-
 ////////////////////////////////////////////////////////////////////
 //     Function: TypedWritable::Destructor
 //       Access: Public, Virtual
@@ -156,115 +149,6 @@ as_reference_count() {
   return NULL;
 }
 
-#ifdef HAVE_PYTHON
-////////////////////////////////////////////////////////////////////
-//     Function: TypedWritable::__reduce__
-//       Access: Published
-//  Description: This special Python method is implement to provide
-//               support for the pickle module.
-//
-//               This hooks into the native pickle and cPickle
-//               modules, but it cannot properly handle
-//               self-referential BAM objects.
-////////////////////////////////////////////////////////////////////
-PyObject *TypedWritable::
-__reduce__(PyObject *self) const {
-  return __reduce_persist__(self, NULL);
-}
-#endif  // HAVE_PYTHON
-
-#ifdef HAVE_PYTHON
-////////////////////////////////////////////////////////////////////
-//     Function: TypedWritable::__reduce_persist__
-//       Access: Published
-//  Description: This special Python method is implement to provide
-//               support for the pickle module.
-//
-//               This is similar to __reduce__, but it provides
-//               additional support for the missing persistent-state
-//               object needed to properly support self-referential
-//               BAM objects written to the pickle stream.  This hooks
-//               into the pickle and cPickle modules implemented in
-//               direct/src/stdpy.
-////////////////////////////////////////////////////////////////////
-PyObject *TypedWritable::
-__reduce_persist__(PyObject *self, PyObject *pickler) const {
-  // We should return at least a 2-tuple, (Class, (args)): the
-  // necessary class object whose constructor we should call
-  // (e.g. this), and the arguments necessary to reconstruct this
-  // object.
-
-  // Check that we have a decode_from_bam_stream python method.  If not,
-  // we can't use this interface.
-  PyObject *method = PyObject_GetAttrString(self, "decode_from_bam_stream");
-  if (method == NULL) {
-    ostringstream stream;
-    stream << "Cannot pickle objects of type " << get_type() << "\n";
-    string message = stream.str();
-    PyErr_SetString(PyExc_TypeError, message.c_str());
-    return NULL;
-  }
-  Py_DECREF(method);
-
-  BamWriter *writer = NULL;
-  if (pickler != NULL) {
-    PyObject *py_writer = PyObject_GetAttrString(pickler, "bamWriter");
-    if (py_writer == NULL) {
-      // It's OK if there's no bamWriter.
-      PyErr_Clear();
-    } else {
-      DTOOL_Call_ExtractThisPointerForType(py_writer, &Dtool_BamWriter, (void **)&writer);
-      Py_DECREF(py_writer);
-    }
-  }
-
-  // First, streamify the object, if possible.
-  string bam_stream;
-  if (!encode_to_bam_stream(bam_stream, writer)) {
-    ostringstream stream;
-    stream << "Could not bamify object of type " << get_type() << "\n";
-    string message = stream.str();
-    PyErr_SetString(PyExc_TypeError, message.c_str());
-    return NULL;
-  }
-
-  // Start by getting this class object.
-  PyObject *this_class = PyObject_Type(self);
-  if (this_class == NULL) {
-    return NULL;
-  }
-
-  PyObject *func;
-  if (writer != NULL) {
-    // The modified pickle support: call the "persistent" version of
-    // this function, which receives the unpickler itself as an
-    // additional parameter.
-    func = find_global_decode(this_class, "py_decode_TypedWritable_from_bam_stream_persist");
-    if (func == NULL) {
-      PyErr_SetString(PyExc_TypeError, "Couldn't find py_decode_TypedWritable_from_bam_stream_persist()");
-      Py_DECREF(this_class);
-      return NULL;
-    }
-
-  } else {
-    // The traditional pickle support: call the non-persistent version
-    // of this function.
-
-    func = find_global_decode(this_class, "py_decode_TypedWritable_from_bam_stream");
-    if (func == NULL) {
-      PyErr_SetString(PyExc_TypeError, "Couldn't find py_decode_TypedWritable_from_bam_stream()");
-      Py_DECREF(this_class);
-      return NULL;
-    }
-  }
-
-  PyObject *result = Py_BuildValue("(O(Os#))", func, this_class, bam_stream.data(), bam_stream.size());
-  Py_DECREF(func);
-  Py_DECREF(this_class);
-  return result;
-}
-#endif  // HAVE_PYTHON
-
 ////////////////////////////////////////////////////////////////////
 //     Function: TypedWritable::encode_to_bam_stream
 //       Access: Published
@@ -291,10 +175,10 @@ encode_to_bam_stream(string &data, BamWriter *writer) const {
     if (!dout.open(stream)) {
       return false;
     }
-    
+
     if (writer == NULL) {
       // Create our own writer.
-    
+
       if (!dout.write_header(_bam_header)) {
         return false;
       }
@@ -303,7 +187,7 @@ encode_to_bam_stream(string &data, BamWriter *writer) const {
       if (!writer.init()) {
         return false;
       }
-      
+
       if (!writer.write_object(this)) {
         return false;
       }
@@ -361,12 +245,11 @@ decode_raw_from_bam_stream(TypedWritable *&ptr, ReferenceCount *&ref_ptr,
 
   if (reader == NULL) {
     // Create a local reader.
-  
     string head;
     if (!din.read_header(head, _bam_header.size())) {
       return false;
     }
-    
+
     if (head != _bam_header) {
       return false;
     }
@@ -375,15 +258,15 @@ decode_raw_from_bam_stream(TypedWritable *&ptr, ReferenceCount *&ref_ptr,
     if (!reader.init()) {
       return false;
     }
-    
+
     if (!reader.read_object(ptr, ref_ptr)) {
       return false;
     }
-    
+
     if (!reader.resolve()) {
       return false;
     }
-    
+
     if (ref_ptr == NULL) {
       // Can't support non-reference-counted objects.
       return false;
@@ -400,12 +283,12 @@ decode_raw_from_bam_stream(TypedWritable *&ptr, ReferenceCount *&ref_ptr,
       reader->set_source(NULL);
       return false;
     }
-    
+
     if (!reader->resolve()) {
       reader->set_source(NULL);
       return false;
     }
-    
+
     if (ref_ptr == NULL) {
       // Can't support non-reference-counted objects.
       reader->set_source(NULL);
@@ -425,139 +308,3 @@ decode_raw_from_bam_stream(TypedWritable *&ptr, ReferenceCount *&ref_ptr,
   ref_ptr->unref();
   return true;
 }
-
-#ifdef HAVE_PYTHON
-////////////////////////////////////////////////////////////////////
-//     Function: TypedWritable::find_global_decode
-//       Access: Public, Static
-//  Description: This is a support function for __reduce__().  It
-//               searches for the global function
-//               py_decode_TypedWritable_from_bam_stream() in this
-//               class's module, or in the module for any base class.
-//               (It's really looking for the libpanda module, but we
-//               can't be sure what name that module was loaded under,
-//               so we search upwards this way.)
-//
-//               Returns: new reference on success, or NULL on failure.
-////////////////////////////////////////////////////////////////////
-PyObject *TypedWritable::
-find_global_decode(PyObject *this_class, const char *func_name) {
-  PyObject *module_name = PyObject_GetAttrString(this_class, "__module__");
-  if (module_name != NULL) {
-    // borrowed reference
-    PyObject *sys_modules = PyImport_GetModuleDict();
-    if (sys_modules != NULL) {
-      // borrowed reference
-      PyObject *module = PyDict_GetItem(sys_modules, module_name);
-      if (module != NULL){ 
-        PyObject *func = PyObject_GetAttrString(module, (char *)func_name);
-        if (func != NULL) {
-          Py_DECREF(module_name);
-          return func;
-        }
-      }
-    }
-  }
-  Py_DECREF(module_name);
-
-  PyObject *bases = PyObject_GetAttrString(this_class, "__bases__");
-  if (bases != NULL) {
-    if (PySequence_Check(bases)) {
-      Py_ssize_t size = PySequence_Size(bases);
-      for (Py_ssize_t i = 0; i < size; ++i) {
-        PyObject *base = PySequence_GetItem(bases, i);
-        if (base != NULL) {
-          PyObject *func = find_global_decode(base, func_name);
-          Py_DECREF(base);
-          if (func != NULL) {
-            Py_DECREF(bases);
-            return func;
-          }
-        }
-      }
-    }
-    Py_DECREF(bases);
-  }
-
-  return NULL;
-}
-#endif  // HAVE_PYTHON
-
-#ifdef HAVE_PYTHON
-////////////////////////////////////////////////////////////////////
-//     Function: py_decode_TypedWritable_from_bam_stream
-//       Access: Published
-//  Description: This wrapper is defined as a global function to suit
-//               pickle's needs.
-//
-//               This hooks into the native pickle and cPickle
-//               modules, but it cannot properly handle
-//               self-referential BAM objects.
-////////////////////////////////////////////////////////////////////
-PyObject *
-py_decode_TypedWritable_from_bam_stream(PyObject *this_class, const string &data) {
-  return py_decode_TypedWritable_from_bam_stream_persist(NULL, this_class, data);
-}
-#endif  // HAVE_PYTHON
-
-
-#ifdef HAVE_PYTHON
-////////////////////////////////////////////////////////////////////
-//     Function: py_decode_TypedWritable_from_bam_stream_persist
-//       Access: Published
-//  Description: This wrapper is defined as a global function to suit
-//               pickle's needs.
-//
-//               This is similar to
-//               py_decode_TypedWritable_from_bam_stream, but it
-//               provides additional support for the missing
-//               persistent-state object needed to properly support
-//               self-referential BAM objects written to the pickle
-//               stream.  This hooks into the pickle and cPickle
-//               modules implemented in direct/src/stdpy.
-////////////////////////////////////////////////////////////////////
-PyObject *
-py_decode_TypedWritable_from_bam_stream_persist(PyObject *pickler, PyObject *this_class, const string &data) {
-
-  PyObject *py_reader = NULL;
-  if (pickler != NULL) {
-    py_reader = PyObject_GetAttrString(pickler, "bamReader");
-    if (py_reader == NULL) {
-      // It's OK if there's no bamReader.
-      PyErr_Clear();
-    }
-  }
-
-  // We need the function PandaNode::decode_from_bam_stream or
-  // TypedWritableReferenceCount::decode_from_bam_stream, which
-  // invokes the BamReader to reconstruct this object.  Since we use
-  // the specific object's class as the pointer, we get the particular
-  // instance of decode_from_bam_stream appropriate to this class.
-
-  PyObject *func = PyObject_GetAttrString(this_class, "decode_from_bam_stream");
-  if (func == NULL) {
-    return NULL;
-  }
-
-  PyObject *result;
-  if (py_reader != NULL){
-    result = PyObject_CallFunction(func, (char *)"(s#O)", data.data(), data.size(), py_reader);
-    Py_DECREF(py_reader);
-  } else {
-    result = PyObject_CallFunction(func, (char *)"(s#)", data.data(), data.size());
-  }
-
-  if (result == NULL) {
-    return NULL;
-  }
-
-  if (result == Py_None) {
-    Py_DECREF(result);
-    PyErr_SetString(PyExc_ValueError, "Could not unpack bam stream");
-    return NULL;
-  }    
-
-  return result;
-}
-#endif  // HAVE_PYTHON
-

+ 6 - 23
panda/src/putil/typedWritable.h

@@ -12,8 +12,8 @@
 //
 ////////////////////////////////////////////////////////////////////
 
-#ifndef __TYPED_WRITABLE_
-#define __TYPED_WRITABLE_
+#ifndef TYPEDWRITABLE_H
+#define TYPEDWRITABLE_H
 
 #include "typedObject.h"
 #include "vector_typedWritable.h"
@@ -31,10 +31,9 @@ class ReferenceCount;
 //       Class : TypedWritable
 // Description : Base class for objects that can be written to and
 //               read from Bam files.
-//               
+//
 //               See also TypedObject for detailed instructions.
 ////////////////////////////////////////////////////////////////////
-
 class EXPCL_PANDA_PUTIL TypedWritable : public TypedObject {
 public:
   static TypedWritable* const Null;
@@ -60,23 +59,16 @@ PUBLISHED:
   INLINE void mark_bam_modified();
   INLINE UpdateSeq get_bam_modified() const;
 
-#ifdef HAVE_PYTHON
-  PyObject *__reduce__(PyObject *self) const;
-  PyObject *__reduce_persist__(PyObject *self, PyObject *pickler) const;
-#endif
+  EXTENSION(PyObject *__reduce__(PyObject *self) const);
+  EXTENSION(PyObject *__reduce_persist__(PyObject *self, PyObject *pickler) const);
 
   INLINE string encode_to_bam_stream() const;
   bool encode_to_bam_stream(string &data, BamWriter *writer = NULL) const;
-  static bool decode_raw_from_bam_stream(TypedWritable *&ptr, 
+  static bool decode_raw_from_bam_stream(TypedWritable *&ptr,
                                          ReferenceCount *&ref_ptr,
                                          const string &data,
                                          BamReader *reader = NULL);
 
-public:
-#ifdef HAVE_PYTHON
-  static PyObject *find_global_decode(PyObject *this_class, const char *func_name);
-#endif
-
 private:
   // We may need to store a list of the BamWriter(s) that have a
   // reference to this object, so that we can remove the object from
@@ -111,15 +103,6 @@ private:
   friend class BamWriter;
 };
 
-#ifdef HAVE_PYTHON
-BEGIN_PUBLISH
-PyObject *py_decode_TypedWritable_from_bam_stream(PyObject *this_class, const string &data);
-PyObject *py_decode_TypedWritable_from_bam_stream_persist(PyObject *unpickler, PyObject *this_class, const string &data);
-END_PUBLISH
-#endif
-
 #include "typedWritable.I"
 
 #endif
-
-

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff