diff --git a/direct/src/actor/Actor.py b/direct/src/actor/Actor.py index 53eaf3808d..60bd7df8dc 100644 --- a/direct/src/actor/Actor.py +++ b/direct/src/actor/Actor.py @@ -566,7 +566,7 @@ class Actor(DirectObject, NodePath): # and sort them every time somebody asks for the list self.__sortedLODNames = self.__partBundleDict.keys() # Reverse sort the doing a string->int - def sortFunc(x, y): + def sortKey(x): if not str(x).isdigit(): smap = {'h':3, 'm':2, @@ -574,19 +574,16 @@ class Actor(DirectObject, NodePath): 'f':0} """ - sx = smap.get(x[0],None) - sy = smap.get(y[0],None) + sx = smap.get(x[0], None) if sx is None: self.notify.error('Invalid lodName: %s' % x) - if sy is None: - self.notify.error('Invalid lodName: %s' % y) """ - return cmp(smap[y[0]], smap[x[0]]) + return smap[x[0]] else: - return cmp (int(y), int(x)) + return int(x) - self.__sortedLODNames.sort(sortFunc) + self.__sortedLODNames.sort(key=sortKey, reverse=True) def getLODNames(self): """ diff --git a/direct/src/directscripts/packpanda.nsi b/direct/src/directscripts/packpanda.nsi index dad5e4beb5..a57514c799 100755 --- a/direct/src/directscripts/packpanda.nsi +++ b/direct/src/directscripts/packpanda.nsi @@ -103,8 +103,6 @@ Section "${SMDIRECTORY}" SecCore File /r /x CVS /x Opt?-Win32 "${PSOURCE}\direct\filter\*.sha" SetOutPath $INSTDIR\direct File /r /x CVS /x Opt?-Win32 "${PSOURCE}\direct\*.py" - SetOutPath $INSTDIR - File "${PSOURCE}\panda3d.py" !else File /r /x CVS /x Opt?-Win32 "${PSOURCE}\direct\src\directscripts\*" SetOutPath $INSTDIR\direct\filter @@ -112,11 +110,15 @@ Section "${SMDIRECTORY}" SecCore SetOutPath $INSTDIR\direct File /r /x CVS /x Opt?-Win32 "${PSOURCE}\direct\src\*.py" File "${PANDA}\tmp\__init__.py" - SetOutPath $INSTDIR - File "${PSOURCE}\direct\src\ffi\panda3d.py" !endif + Delete "$INSTDIR\panda3d.py" + Delete "$INSTDIR\panda3d.pyc" + Delete "$INSTDIR\panda3d.pyo" SetOutPath $INSTDIR\pandac File /r "${PANDA}\pandac\*.py" + SetOutPath $INSTDIR\panda3d + File /r "${PANDA}\panda3d\*.py" + File /r "${PANDA}\panda3d\*.pyd" SetOutPath $INSTDIR\python File /r "${PANDA}\python\*" RMDir /r "$SMPROGRAMS\${SMDIRECTORY}" diff --git a/direct/src/extensions/EggGroupNode-extensions.py b/direct/src/extensions/EggGroupNode-extensions.py deleted file mode 100644 index 660e556a8f..0000000000 --- a/direct/src/extensions/EggGroupNode-extensions.py +++ /dev/null @@ -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 - diff --git a/direct/src/extensions/EggPrimitive-extensions.py b/direct/src/extensions/EggPrimitive-extensions.py deleted file mode 100644 index 60c5bf7392..0000000000 --- a/direct/src/extensions/EggPrimitive-extensions.py +++ /dev/null @@ -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 diff --git a/direct/src/extensions/NodePathCollection-extensions.py b/direct/src/extensions/NodePathCollection-extensions.py deleted file mode 100644 index 99a1c7fca6..0000000000 --- a/direct/src/extensions/NodePathCollection-extensions.py +++ /dev/null @@ -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 diff --git a/direct/src/extensions/OdeBody-extensions.py b/direct/src/extensions/OdeBody-extensions.py deleted file mode 100755 index 6b0f60a633..0000000000 --- a/direct/src/extensions/OdeBody-extensions.py +++ /dev/null @@ -1,6 +0,0 @@ - -def getConvertedJoint(self, index): - """ - Return a downcast joint on this body. - """ - return self.getJoint(index).convert() diff --git a/direct/src/extensions/OdeGeom-extensions.py b/direct/src/extensions/OdeGeom-extensions.py deleted file mode 100755 index 0796dc5cf7..0000000000 --- a/direct/src/extensions/OdeGeom-extensions.py +++ /dev/null @@ -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 \ No newline at end of file diff --git a/direct/src/extensions/OdeJoint-extensions.py b/direct/src/extensions/OdeJoint-extensions.py deleted file mode 100755 index 3e3eeccfc8..0000000000 --- a/direct/src/extensions/OdeJoint-extensions.py +++ /dev/null @@ -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() diff --git a/direct/src/extensions/OdeSpace-extensions.py b/direct/src/extensions/OdeSpace-extensions.py deleted file mode 100755 index f110615831..0000000000 --- a/direct/src/extensions/OdeSpace-extensions.py +++ /dev/null @@ -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 \ No newline at end of file diff --git a/direct/src/extensions/Ramfile-extensions.py b/direct/src/extensions/Ramfile-extensions.py deleted file mode 100644 index a05a666a24..0000000000 --- a/direct/src/extensions/Ramfile-extensions.py +++ /dev/null @@ -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 - diff --git a/direct/src/extensions/StreamReader-extensions.py b/direct/src/extensions/StreamReader-extensions.py deleted file mode 100644 index 792abde3a6..0000000000 --- a/direct/src/extensions/StreamReader-extensions.py +++ /dev/null @@ -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 - diff --git a/direct/src/extensions_native/EggGroupNode_extensions.py b/direct/src/extensions_native/EggGroupNode_extensions.py deleted file mode 100644 index 6c6173e66f..0000000000 --- a/direct/src/extensions_native/EggGroupNode_extensions.py +++ /dev/null @@ -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 diff --git a/direct/src/extensions_native/EggPrimitive_extensions.py b/direct/src/extensions_native/EggPrimitive_extensions.py deleted file mode 100644 index 657f99a132..0000000000 --- a/direct/src/extensions_native/EggPrimitive_extensions.py +++ /dev/null @@ -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 diff --git a/direct/src/extensions_native/NodePathCollection_extensions.py b/direct/src/extensions_native/NodePathCollection_extensions.py deleted file mode 100644 index f7f379ab32..0000000000 --- a/direct/src/extensions_native/NodePathCollection_extensions.py +++ /dev/null @@ -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 diff --git a/direct/src/extensions_native/NodePath_extensions.py b/direct/src/extensions_native/NodePath_extensions.py index c1a19f3784..7b17dc34f6 100644 --- a/direct/src/extensions_native/NodePath_extensions.py +++ b/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): """ diff --git a/direct/src/extensions_native/OdeBody_extensions.py b/direct/src/extensions_native/OdeBody_extensions.py deleted file mode 100755 index 78b71cb638..0000000000 --- a/direct/src/extensions_native/OdeBody_extensions.py +++ /dev/null @@ -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 - diff --git a/direct/src/extensions_native/OdeGeom_extensions.py b/direct/src/extensions_native/OdeGeom_extensions.py deleted file mode 100755 index e154e05e55..0000000000 --- a/direct/src/extensions_native/OdeGeom_extensions.py +++ /dev/null @@ -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 - diff --git a/direct/src/extensions_native/OdeJoint_extensions.py b/direct/src/extensions_native/OdeJoint_extensions.py deleted file mode 100755 index e113e6fdfa..0000000000 --- a/direct/src/extensions_native/OdeJoint_extensions.py +++ /dev/null @@ -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 - diff --git a/direct/src/extensions_native/OdeSpace_extensions.py b/direct/src/extensions_native/OdeSpace_extensions.py deleted file mode 100755 index 14b3c1e618..0000000000 --- a/direct/src/extensions_native/OdeSpace_extensions.py +++ /dev/null @@ -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 - diff --git a/direct/src/extensions_native/Ramfile_extensions.py b/direct/src/extensions_native/Ramfile_extensions.py deleted file mode 100644 index c05040c73e..0000000000 --- a/direct/src/extensions_native/Ramfile_extensions.py +++ /dev/null @@ -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 diff --git a/direct/src/extensions_native/StreamReader_extensions.py b/direct/src/extensions_native/StreamReader_extensions.py deleted file mode 100755 index b4111cc965..0000000000 --- a/direct/src/extensions_native/StreamReader_extensions.py +++ /dev/null @@ -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 diff --git a/direct/src/interval/FunctionInterval.py b/direct/src/interval/FunctionInterval.py index 450cb5d5de..fd46bad994 100644 --- a/direct/src/interval/FunctionInterval.py +++ b/direct/src/interval/FunctionInterval.py @@ -57,9 +57,10 @@ class FunctionInterval(Interval.Interval): self.function = function # Create a unique name for the interval if necessary - if (name == None): + if name is None: name = self.makeUniqueName(function) - assert isinstance(name, types.StringType) + assert isinstance(name, str) + # Record any arguments self.extraArgs = extraArgs self.kw = kw diff --git a/direct/src/showbase/Loader.py b/direct/src/showbase/Loader.py index 2f4b81e411..52f253d717 100644 --- a/direct/src/showbase/Loader.py +++ b/direct/src/showbase/Loader.py @@ -814,7 +814,7 @@ class Loader(DirectObject): result = [] for soundPath in soundList: # should return a valid sound obj even if musicMgr is invalid - sound = manager.getSound(soundPath) + sound = manager.getSound(soundPath, positional) result.append(sound) if gotList: diff --git a/direct/src/showbase/Messenger.py b/direct/src/showbase/Messenger.py index 44248e6a4e..6e45fb088c 100644 --- a/direct/src/showbase/Messenger.py +++ b/direct/src/showbase/Messenger.py @@ -634,7 +634,10 @@ class Messenger: functionName = method.im_class.__name__ + '.' + \ method.im_func.__name__ else: - functionName = method.__name__ + if hasattr(method, "__name__"): + functionName = method.__name__ + else: + return "" return functionName def __eventRepr(self, event): diff --git a/direct/src/showbase/PythonUtil.py b/direct/src/showbase/PythonUtil.py index 84ca4c32f6..9f18522c2e 100644 --- a/direct/src/showbase/PythonUtil.py +++ b/direct/src/showbase/PythonUtil.py @@ -60,9 +60,6 @@ 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 panda3d.core import ConfigVariableBool ScalarTypes = (types.FloatType, types.IntType, types.LongType) @@ -2462,7 +2459,8 @@ def _getDtoolSuperBase(): from pandac.PandaModules import PandaNode dtoolSuperBase = PandaNode('').__class__.__bases__[0].__bases__[0].__bases__[0] assert repr(dtoolSuperBase) == "" \ - or repr(dtoolSuperBase) == "" + or repr(dtoolSuperBase) == "" \ + or repr(dtoolSuperBase) == "" safeReprNotify = None diff --git a/dtool/src/interrogate/functionRemap.cxx b/dtool/src/interrogate/functionRemap.cxx index b6bae90ab7..ec583b082d 100644 --- a/dtool/src/interrogate/functionRemap.cxx +++ b/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. diff --git a/dtool/src/interrogate/functionRemap.h b/dtool/src/interrogate/functionRemap.h index 7ab8224ad1..db23ba0139 100644 --- a/dtool/src/interrogate/functionRemap.h +++ b/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 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; diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index dd564a91c5..2d98bbcdc8 100755 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -197,8 +197,8 @@ classNameFromCppName(const std::string &cppName, bool mangle) { bool nextCap = false; bool firstChar = true && mangle; - for (std::string::const_iterator chr = cppName.begin(); - chr != cppName.end(); + for (std::string::const_iterator chr = cppName.begin(); + chr != cppName.end(); chr++) { if ((*chr == '_' || *chr == ' ') && mangle) { nextCap = true; @@ -223,10 +223,10 @@ classNameFromCppName(const std::string &cppName, bool mangle) { className = classRenameDictionary[x]._to; } } - + if (className.empty()) { std::string text = "** ERROR ** Renaming class: " + cppName + " to empty string"; - printf("%s",text.c_str()); + printf("%s", text.c_str()); } className = checkKeyword(className); @@ -249,8 +249,8 @@ methodNameFromCppName(const std::string &cppName, const std::string &className, std::string methodName; const std::string badChars("!@#$%^&*()<>,.-=+~{}? "); bool nextCap = false; - for (std::string::const_iterator chr = origName.begin(); - chr != origName.end(); + for (std::string::const_iterator chr = origName.begin(); + chr != origName.end(); chr++) { if ((*chr == '_' || *chr == ' ') && mangle) { nextCap = true; @@ -283,7 +283,7 @@ methodNameFromCppName(const std::string &cppName, const std::string &className, } } } - + // # Mangle names that happen to be python keywords so they are not anymore methodName = checkKeyword(methodName); return methodName; @@ -302,13 +302,13 @@ std::string methodNameFromCppName(InterfaceMaker::Function *func, const std::str bool isInplaceFunction(InterfaceMaker::Function *func) { std::string wname = methodNameFromCppName(func, "", false); - + for (int x = 0; InPlaceSet[x] != NULL; x++) { if (InPlaceSet[x] == wname) { return true; } } - + return false; } @@ -344,13 +344,13 @@ get_slotted_function_def(Object *obj, Function *func, SlottedFunctionDef &def) { if (method_name == "operator -" && is_unary_op) { def._answer_location = "tp_as_number->nb_negative"; def._wrapper_type = WT_no_params; - return true; + return true; } if (method_name == "operator -") { def._answer_location = "tp_as_number->nb_subtract"; def._wrapper_type = WT_numeric_operator; - return true; + return true; } if (method_name == "operator *") { @@ -487,7 +487,7 @@ get_slotted_function_def(Object *obj, Function *func, SlottedFunctionDef &def) { return true; } } - + if (obj->_protocol_types & Object::PT_mapping) { if (func->_flags & FunctionRemap::F_getitem) { def._answer_location = "tp_as_mapping->mp_subscript"; @@ -603,7 +603,7 @@ get_valid_child_classes(std::map &answer, CPPStructTyp ++bi) { const CPPStructType::Base &base = (*bi); -// if (base._vis <= V_public) +// if (base._vis <= V_public) // can_downcast = false; CPPStructType *base_type = TypeManager::resolve_type(base._base)->as_struct_type(); if (base_type != NULL) { @@ -856,13 +856,13 @@ write_class_details(ostream &out, Object *obj) { out << "//********************************************************************\n"; out << "//*** Functions for .. " << cClassName << "\n" ; out << "//********************************************************************\n"; - + for (fi = obj->_methods.begin(); fi != obj->_methods.end(); ++fi) { Function *func = (*fi); if (func) { SlottedFunctionDef def; get_slotted_function_def(obj, func, def); - + ostringstream GetThis; GetThis << " " << cClassName << " *local_this = NULL;\n"; GetThis << " DTOOL_Call_ExtractThisPointerForType(self, &Dtool_" << ClassName << ", (void **)&local_this);\n"; @@ -903,7 +903,7 @@ write_class_details(ostream &out, Object *obj) { for (fi = obj->_constructors.begin(); fi != obj->_constructors.end(); ++fi) { Function *func = (*fi); std::string fname = "int Dtool_Init_" + ClassName + "(PyObject *self, PyObject *args, PyObject *kwds)"; - + write_function_for_name(out, obj, func, fname, "", ClassName, true, coercion_attempted); } if (coercion_attempted) { @@ -913,7 +913,7 @@ write_class_details(ostream &out, Object *obj) { for (fi = obj->_constructors.begin(); fi != obj->_constructors.end(); ++fi) { Function *func = (*fi); std::string fname = "int Dtool_InitNoCoerce_" + ClassName + "(PyObject *self, PyObject *args, PyObject *kwds)"; - + write_function_for_name(out, obj, func, fname, "", ClassName, false, coercion_attempted); } } else { @@ -931,7 +931,7 @@ write_class_details(ostream &out, Object *obj) { for (msi = obj->_make_seqs.begin(); msi != obj->_make_seqs.end(); ++msi) { write_make_seq(out, obj, ClassName, *msi); } - + CPPType *cpptype = TypeManager::resolve_type(obj->_itype._cpptype); std::map details; std::map::iterator di; @@ -945,7 +945,7 @@ write_class_details(ostream &out, Object *obj) { } { // the Cast Converter - + out << "inline void *Dtool_UpcastInterface_" << ClassName << "(PyObject *self, Dtool_PyTypedObject *requested_type) {\n"; out << " Dtool_PyTypedObject *SelfType = ((Dtool_PyInstDef *)self)->_My_Type;\n"; out << " if (SelfType != &Dtool_" << ClassName << ") {\n"; @@ -960,7 +960,7 @@ write_class_details(ostream &out, Object *obj) { for (di = details.begin(); di != details.end(); di++) { if (di->second._is_legal_py_class) { - out << " if (requested_type == &Dtool_" <second._to_class_name) << ") {\n"; + out << " if (requested_type == &Dtool_" << make_safe_name(di->second._to_class_name) << ") {\n"; out << " return " << di->second._up_cast_string << " local_this;\n"; out << " }\n"; } @@ -1100,7 +1100,7 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) { out << " PyModule_AddStringConstant(module, \"" << name2 << "\", \"" << value << "\");\n"; } } - } + } for (oi = _objects.begin(); oi != _objects.end(); ++oi) { Object *object = (*oi).second; @@ -1132,10 +1132,10 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) { if (!func->_itype.is_global() && is_function_legal(func)) { string name1 = methodNameFromCppName(func, "", false); string name2 = methodNameFromCppName(func, "", true); - out << " { \"" << name1 << "\", (PyCFunction) &" + out << " { \"" << name1 << "\", (PyCFunction) &" << func->_name << ", METH_VARARGS | METH_KEYWORDS, (char *)" << func->_name << "_comment},\n"; if (name1 != name2) { - out << " { \"" << name2 << "\", (PyCFunction) &" + out << " { \"" << name2 << "\", (PyCFunction) &" << func->_name << ", METH_VARARGS | METH_KEYWORDS, (char *)" << func->_name << "_comment},\n"; } } @@ -1149,7 +1149,7 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) { out << " {NULL, NULL, 0, NULL}\n" << "};\n\n"; - out << "struct LibraryDef " << def->library_name << "_moddef = {python_simple_funcs, BuildInstants};\n"; + out << "EXPORT_THIS struct LibraryDef " << def->library_name << "_moddef = {python_simple_funcs, BuildInstants};\n"; if (out_h != NULL) { *out_h << "extern struct LibraryDef " << def->library_name << "_moddef;\n"; } @@ -1262,11 +1262,11 @@ write_module_class(ostream &out, Object *obj) { string name1 = methodNameFromCppName(func, export_class_name, false); string name2 = methodNameFromCppName(func, export_class_name, true); - out << " { \"" << name1 << "\", (PyCFunction) &" + out << " { \"" << name1 << "\", (PyCFunction) &" << func->_name << ", METH_VARARGS | METH_KEYWORDS, (char *) " << func->_name << "_comment},\n"; ++x; if (name1 != name2) { - out << " { \"" << name2 << "\", (PyCFunction) &" + out << " { \"" << name2 << "\", (PyCFunction) &" << func->_name << ", METH_VARARGS | METH_KEYWORDS, (char *) " << func->_name << "_comment},\n"; ++x; } @@ -1292,7 +1292,7 @@ write_module_class(ostream &out, Object *obj) { if (got_copy && !got_deepcopy) { out << " { \"__deepcopy__\", (PyCFunction) &map_deepcopy_to_copy, METH_VARARGS, NULL},\n"; } - + MakeSeqs::iterator msi; for (msi = obj->_make_seqs.begin(); msi != obj->_make_seqs.end(); ++msi) { string flags = "METH_NOARGS"; @@ -1317,7 +1317,7 @@ write_module_class(ostream &out, Object *obj) { for (di = 0; di < num_derivations; di++) { TypeIndex d_type_Index = obj->_itype.get_derivation(di); if (!interrogate_type_is_unpublished(d_type_Index)) { - const InterrogateType &d_itype = idb->get_type(d_type_Index); + const InterrogateType &d_itype = idb->get_type(d_type_Index); if (is_cpp_type_legal(d_itype._cpptype)) { if (!isExportThisRun(d_itype._cpptype)) { _external_imports.insert(make_safe_name(d_itype.get_scoped_name().c_str())); @@ -1332,7 +1332,7 @@ write_module_class(ostream &out, Object *obj) { for (di = 0; di < num_derivations; di++) { TypeIndex d_type_Index = obj->_itype.get_derivation(di); if (!interrogate_type_is_unpublished(d_type_Index)) { - const InterrogateType &d_itype = idb->get_type(d_type_Index); + const InterrogateType &d_itype = idb->get_type(d_type_Index); if (is_cpp_type_legal(d_itype._cpptype)) { bases.push_back(make_safe_name(d_itype.get_scoped_name().c_str())); } @@ -1363,7 +1363,7 @@ write_module_class(ostream &out, Object *obj) { out << "}\n\n"; } break; - + case WT_one_param: case WT_numeric_operator: // PyObject *func(PyObject *self, PyObject *one) @@ -1519,7 +1519,7 @@ write_module_class(ostream &out, Object *obj) { out << "}\n\n"; } break; - + case WT_inquiry: // int func(PyObject *self) { @@ -1740,7 +1740,7 @@ write_module_class(ostream &out, Object *obj) { has_local_hash = true; } } - + int need_repr = NeedsAReprFunction(obj->_itype); if (need_repr > 0) { out << "//////////////////\n"; @@ -1825,6 +1825,7 @@ write_module_class(ostream &out, Object *obj) { out << "\n"; out << " switch (op) {\n"; + Function *compare_to_func = NULL; for (fi = obj->_methods.begin(); fi != obj->_methods.end(); ++fi) { std::set remaps; Function *func = (*fi); @@ -1852,13 +1853,18 @@ write_module_class(ostream &out, Object *obj) { out << " case Py_GT:\n"; } else if (fname == "operator >=") { out << " case Py_GE:\n"; + } else if (fname == "compare_to") { + compare_to_func = func; + continue; } else { continue; } + ostringstream forward_decl; string expected_params; bool coercion_attempted = false; write_function_forset(out, obj, func, remaps, expected_params, 2, forward_decl, false, true, coercion_attempted, args_cleanup); + out << " if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_TypeError)) {\n"; out << " PyErr_Clear();\n"; out << " }\n"; @@ -1866,12 +1872,48 @@ write_module_class(ostream &out, Object *obj) { has_local_richcompare = true; } - out << " }\n"; + out << " }\n\n"; + out << " " << args_cleanup << "\n"; out << " if (PyErr_Occurred()) {\n"; out << " return (PyObject *)NULL;\n"; out << " }\n\n"; + if (compare_to_func != NULL) { + out << "#if PY_MAJOR_VERSION >= 3\n"; + out << " // All is not lost; we still have the compare_to function to fall back onto.\n"; + out << " PyObject *result = " << compare_to_func->_name << "(self, args, kwds);\n"; + out << " if (result != NULL) {\n"; + out << " if (PyLong_Check(result)) {;\n"; + out << " long cmpval = PyLong_AsLong(result);\n"; + out << " switch (op) {\n"; + out << " case Py_LT:\n"; + out << " return PyBool_FromLong(cmpval < 0);\n"; + out << " case Py_LE:\n"; + out << " return PyBool_FromLong(cmpval <= 0);\n"; + out << " case Py_EQ:\n"; + out << " return PyBool_FromLong(cmpval == 0);\n"; + out << " case Py_NE:\n"; + out << " return PyBool_FromLong(cmpval != 0);\n"; + out << " case Py_GT:\n"; + out << " return PyBool_FromLong(cmpval > 0);\n"; + out << " case Py_GE:\n"; + out << " return PyBool_FromLong(cmpval >= 0);\n"; + out << " }\n"; + out << " }\n"; + out << " Py_DECREF(result);\n"; + out << " }\n\n"; + + out << " if (PyErr_Occurred()) {\n"; + out << " if (PyErr_ExceptionMatches(PyExc_TypeError)) {\n"; + out << " PyErr_Clear();\n"; + out << " } else {\n"; + out << " return (PyObject *)NULL;\n"; + out << " }\n"; + out << " }\n"; + out << "#endif\n\n"; + } + out << " Py_INCREF(Py_NotImplemented);\n"; out << " return Py_NotImplemented;\n"; out << "}\n\n"; @@ -1885,11 +1927,11 @@ write_module_class(ostream &out, Object *obj) { // out << " memset(Dtool_" << ClassName << ".As_PyTypeObject().tp_as_mapping,0,sizeof(PyMappingMethods));\n"; // out << " static Dtool_PyTypedObject *InheritsFrom[] = {"; - // add doc string + // add doc string if (obj->_itype.has_comment()) { out << "#ifndef NDEBUG\n"; out << " // Class documentation string\n"; - out << " Dtool_" << ClassName + out << " Dtool_" << ClassName << ".As_PyTypeObject().tp_doc =\n"; output_quoted(out, 6, obj->_itype.get_comment()); out << ";\n" @@ -1901,7 +1943,7 @@ write_module_class(ostream &out, Object *obj) { out << " Dtool_" << ClassName << ".As_PyTypeObject().tp_flags |= Py_TPFLAGS_HAVE_ITER;\n"; } if (has_local_getbuffer) { - out << "#if PY_VERSION_HEX >= 0x02060000\n"; + out << "#if PY_VERSION_HEX >= 0x02060000 && PY_VERSION_HEX < 0x03000000\n"; out << " Dtool_" << ClassName << ".As_PyTypeObject().tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER;\n"; out << "#endif"; } @@ -2243,7 +2285,7 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak if (MapSets.size() > 1) { string expected_params; - + indent(out, 2) << "int parameter_count = 1;\n"; indent(out, 2) << "if (PyTuple_Check(args)) {\n"; indent(out, 2) << " parameter_count = PyTuple_Size(args);\n"; @@ -2251,7 +2293,7 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak indent(out, 2) << " parameter_count += PyDict_Size(kwds);\n"; indent(out, 2) << " }\n"; indent(out, 2) << "}\n"; - + indent(out, 2) << "switch (parameter_count) {\n"; for (mii = MapSets.begin(); mii != MapSets.end(); mii ++) { indent(out, 2) << "case " << mii->first << ": {\n"; @@ -2264,7 +2306,7 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak indent(out, 4) << "}\n"; indent(out, 4) << "break;\n"; } - + indent(out, 2) << "default:\n"; indent(out, 4) << "{\n"; indent(out, 6) @@ -2276,8 +2318,8 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak // Python convention. int add_self = func->_has_this ? 1 : 0; size_t mic; - for (mic = 0, mii = MapSets.begin(); - mii != MapSets.end(); + for (mic = 0, mii = MapSets.begin(); + mii != MapSets.end(); ++mii, ++mic) { if (mic == MapSets.size() - 1) { if (mic == 1) { @@ -2293,16 +2335,16 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak } out << " arguments (%d given)\", parameter_count + " << add_self << ");\n"; - + if (constructor) indent(out, 6) << "return -1;\n"; else indent(out, 6) << "return (PyObject *) NULL;\n"; - + indent(out, 4) << "}\n"; indent(out, 4) << "break;\n"; indent(out, 2) << "}\n"; - + out << " if (!PyErr_Occurred()) { // Let error pass on\n"; out << " PyErr_SetString(PyExc_TypeError,\n"; out << " \"Arguments must match one of:\\n\"\n"; @@ -2319,7 +2361,7 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak if (!expected_params.empty() && FunctionComment1.empty()) { FunctionComment1 += "C++ Interface:\n"; } - + FunctionComment1 += expected_params; } else { @@ -2346,7 +2388,7 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak if (!expected_params.empty() && FunctionComment1.empty()) { FunctionComment1 += "C++ Interface:\n"; } - + FunctionComment1 += expected_params; } @@ -2401,13 +2443,13 @@ int GetParnetDepth(CPPType *type) { int deepest = 0; TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(type)), false); InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - const InterrogateType &itype = idb->get_type(type_index); + const InterrogateType &itype = idb->get_type(type_index); if (itype.is_class() || itype.is_struct()) { int num_derivations = itype.number_of_derivations(); for (int di = 0; di < num_derivations; di++) { TypeIndex d_type_Index = itype.get_derivation(di); - const InterrogateType &d_itype = idb->get_type(d_type_Index); + const InterrogateType &d_itype = idb->get_type(d_type_Index); int this_one = GetParnetDepth(d_itype._cpptype); if (this_one > deepest) { deepest = this_one; @@ -2467,10 +2509,10 @@ SortFunctionSet(std::set &remaps) { // A set is defined as all remaps that have the same number of paramaters.. /////////////////////////////////////////////////////////// void InterfaceMakerPythonNative:: -write_function_forset(ostream &out, InterfaceMaker::Object *obj, - InterfaceMaker::Function *func, - std::set &remapsin, - string &expected_params, int indent_level, +write_function_forset(ostream &out, InterfaceMaker::Object *obj, + InterfaceMaker::Function *func, + std::set &remapsin, + string &expected_params, int indent_level, ostream &forward_decl, bool is_inplace, bool coercion_allowed, bool &coercion_attempted, @@ -2490,7 +2532,7 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj, } while (pn < (int)remap->_parameters.size()) { CPPType *type = remap->_parameters[pn]._remap->get_new_type(); - + if (TypeManager::is_char_pointer(type)) { } else if (TypeManager::is_wchar_pointer(type)) { } else if (TypeManager::is_pointer_to_PyObject(type)) { @@ -2513,17 +2555,17 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj, indent(out, indent_level) << "{\n"; indent_level += 2; - indent(out, indent_level) + indent(out, indent_level) << "PyObject *coerced = NULL;\n"; - indent(out, indent_level) + indent(out, indent_level) << "PyObject **coerced_ptr = NULL;\n"; - indent(out, indent_level) + indent(out, indent_level) << "bool report_errors = false;\n"; - indent(out, indent_level) + indent(out, indent_level) << "while (true) {\n"; indent_level += 2; } - + if (remapsin.size() > 1) { // There are multiple different overloads for this number of // parameters. Sort them all into order from most-specific to @@ -2537,7 +2579,7 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj, if (remap->_has_this && !remap->_const_method) { // If it's a non-const method, we only allow a // non-const this. - indent(out, indent_level) + indent(out, indent_level) << "if (!((Dtool_PyInstDef *)self)->_is_const) {\n"; } else { indent(out, indent_level) @@ -2550,7 +2592,7 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj, write_function_instance(out, obj, func, remap, expected_params, indent_level + 2, false, forward_decl, func->_name, is_inplace, coercion_possible, coercion_attempted, args_cleanup); indent(out, indent_level + 2) << "PyErr_Clear();\n"; - indent(out, indent_level) << "}\n\n"; + indent(out, indent_level) << "}\n\n"; } } } else { @@ -2563,16 +2605,16 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj, if (remap->_has_this && !remap->_const_method) { // If it's a non-const method, we only allow a // non-const this. - indent(out, indent_level) + indent(out, indent_level) << "if (!((Dtool_PyInstDef *)self)->_is_const) {\n"; } else { indent(out, indent_level) << "{\n"; } - indent(out, indent_level + 2) + indent(out, indent_level + 2) << "// 1-" ; - remap->write_orig_prototype(out, 0); + remap->write_orig_prototype(out, 0); out << "\n" ; write_function_instance(out, obj, func, remap, expected_params, indent_level + 2, true, forward_decl, func->_name, is_inplace, coercion_possible, coercion_attempted, args_cleanup); @@ -2597,7 +2639,7 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj, << "}\n\n"; } else { indent(out, indent_level) - << "}\n\n"; + << "}\n\n"; } } } @@ -2607,38 +2649,38 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj, if (coercion_possible) { // Try again, this time with coercion enabled. - indent(out, indent_level) + indent(out, indent_level) << "if (coerced_ptr == NULL && !report_errors) {\n"; - indent(out, indent_level + 2) + indent(out, indent_level + 2) << "coerced_ptr = &coerced;\n"; - indent(out, indent_level + 2) + indent(out, indent_level + 2) << "continue;\n"; - indent(out, indent_level) + indent(out, indent_level) << "}\n"; // No dice. Go back one more time, and this time get the error // message. - indent(out, indent_level) + indent(out, indent_level) << "if (!report_errors) {\n"; - indent(out, indent_level + 2) + indent(out, indent_level + 2) << "report_errors = true;\n"; - indent(out, indent_level + 2) + indent(out, indent_level + 2) << "continue;\n"; - indent(out, indent_level) + indent(out, indent_level) << "}\n"; // We've been through three times. We're done. - indent(out, indent_level) + indent(out, indent_level) << "break;\n"; - + indent_level -= 2; - indent(out, indent_level) + indent(out, indent_level) << "}\n"; - - indent(out, indent_level) + + indent(out, indent_level) << "Py_XDECREF(coerced);\n"; indent_level -= 2; - indent(out, indent_level) + indent(out, indent_level) << "}\n"; } } @@ -2650,11 +2692,11 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj, // single instance of an overloaded function. //////////////////////////////////////////////////////////////////// void InterfaceMakerPythonNative:: -write_function_instance(ostream &out, InterfaceMaker::Object *obj, +write_function_instance(ostream &out, InterfaceMaker::Object *obj, InterfaceMaker::Function *func1, - FunctionRemap *remap, string &expected_params, - int indent_level, bool errors_fatal, - ostream &ForwardDeclrs, + FunctionRemap *remap, string &expected_params, + int indent_level, bool errors_fatal, + ostream &ForwardDeclrs, const std::string &functionnamestr, bool is_inplace, bool coercion_possible, bool &coercion_attempted, const string &args_cleanup) { @@ -2673,21 +2715,21 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, if (remap->_type == FunctionRemap::T_constructor) { is_constructor = true; } - + if (is_constructor && (remap->_flags & FunctionRemap::F_explicit_self) != 0) { // If we'll be passing "self" to the constructor, we need to // pre-initialize it here. Unfortunately, we can't pre-load the // "this" pointer, but the constructor itself can do this. - + indent(out, indent_level) << "// Pre-initialize self for the constructor\n"; CPPType *orig_type = remap->_return_type->get_orig_type(); TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(orig_type)), false); InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - const InterrogateType &itype = idb->get_type(type_index); + const InterrogateType &itype = idb->get_type(type_index); indent(out, indent_level) - << "DTool_PyInit_Finalize(self, NULL, &" + << "DTool_PyInit_Finalize(self, NULL, &" << CLASS_PREFIX << make_safe_name(itype.get_scoped_name()) << ", false, false);\n"; } @@ -2724,7 +2766,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, indent(out, indent_level) << "char *" << param_name << ";\n"; format_specifiers += "s"; parameter_list += ", &" + param_name; - + } else if (TypeManager::is_wchar_pointer(orig_type)) { out << "#if PY_MAJOR_VERSION >= 3\n"; indent(out, indent_level) << "PyObject *" << param_name << ";\n"; @@ -2742,7 +2784,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, pexpr_string = param_name + "_str"; extra_cleanup += " delete[] " + param_name + "_str;"; - + } else if (TypeManager::is_wstring(orig_type)) { out << "#if PY_MAJOR_VERSION >= 3\n"; indent(out, indent_level) << "PyObject *" << param_name << ";\n"; @@ -2893,7 +2935,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, expected_params += classNameFromCppName(obj_type->get_simple_name(), false); if (!remap->_has_this || pn != 0) { - indent(out, indent_level) + indent(out, indent_level) << "PyObject *" << param_name << ";\n"; format_specifiers += "O"; parameter_list += ", &" + param_name; @@ -2901,7 +2943,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, TypeIndex p_type_index = builder.get_type(obj_type, false); InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - const InterrogateType &p_itype = idb->get_type(p_type_index); + const InterrogateType &p_itype = idb->get_type(p_type_index); bool is_copy_constructor = false; if (is_constructor && remap->_parameters.size() == 1 && pn == 0) { @@ -2928,9 +2970,9 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, } ostringstream str; - str << "DTOOL_Call_GetPointerThisClass(" << param_name - << ", &Dtool_" << make_safe_name(p_itype.get_scoped_name()) - << ", " << pn << ", \"" + str << "DTOOL_Call_GetPointerThisClass(" << param_name + << ", &Dtool_" << make_safe_name(p_itype.get_scoped_name()) + << ", " << pn << ", \"" << method_prefix << methodNameFromCppName(func1, class_name, false) << "\", " << const_ok; if (coercion_possible && !is_copy_constructor) { @@ -2972,29 +3014,29 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, pexprs.push_back(pexpr_string); } expected_params += ")\n"; - + // If we got what claimed to be a unary operator, don't check for // parameters, since we won't be getting any anyway. if (!func1->_ifunc.is_unary_op()) { - std::string format_specifiers1 = format_specifiers + ":" + + std::string format_specifiers1 = format_specifiers + ":" + methodNameFromCppName(func1, "", false); indent(out, indent_level) << "static char *keyword_list[] = {" << keyword_list << "NULL};\n"; - if (remap->_parameters.size() == 1 || + if (remap->_parameters.size() == 1 || (remap->_has_this && remap->_parameters.size() == 2)) { indent(out, indent_level) << "// Special case to make operators work\n"; indent(out, indent_level) << "if (PyTuple_Check(args) || (kwds != NULL && PyDict_Check(kwds))) {\n"; indent(out, indent_level) - << " PyArg_ParseTupleAndKeywords(args, kwds, \"" + << " PyArg_ParseTupleAndKeywords(args, kwds, \"" << format_specifiers1 << "\", keyword_list" << parameter_list << ");\n"; indent(out, indent_level) << "} else {\n"; indent(out, indent_level) - << " PyArg_Parse(args, \"" << format_specifiers1 << "\"" + << " PyArg_Parse(args, \"" << format_specifiers1 << "\"" << parameter_list << ");\n"; indent(out, indent_level) << "}\n"; @@ -3003,7 +3045,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, } else { indent(out, indent_level) - << "if (PyArg_ParseTupleAndKeywords(args, kwds, \"" + << "if (PyArg_ParseTupleAndKeywords(args, kwds, \"" << format_specifiers1 << "\", keyword_list" << parameter_list << ")) {\n"; } @@ -3049,11 +3091,11 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, indent(out, extra_indent_level) << "}\n"; } - - if (!remap->_void_return && + + if (!remap->_void_return && remap->_return_type->new_type_is_atomic_string()) { // Treat strings as a special case. We don't want to format the - // return expression. + // return expression. if (remap->_blocking) { // With SIMPLE_THREADS, it's important that we never release the // interpreter lock. @@ -3167,7 +3209,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, extra_indent_level -= 2; indent(out, extra_indent_level) << "}\n"; } - + indent(out, indent_level) << "}\n"; } @@ -3188,7 +3230,7 @@ pack_return_value(ostream &out, int indent_level, FunctionRemap *remap, TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(orig_type)), false); InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - const InterrogateType &itype = idb->get_type(type_index); + const InterrogateType &itype = idb->get_type(type_index); indent(out, indent_level) << "return DTool_PyInit_Finalize(self, " << return_expr << ", &" << CLASS_PREFIX << make_safe_name(itype.get_scoped_name()) << ", true, false);\n"; @@ -3241,7 +3283,7 @@ pack_python_value(ostream &out, int indent_level, FunctionRemap *remap, indent(out, indent_level+2) << assign_stmt << "Py_None;\n"; indent(out, indent_level) << "} else {\n"; indent(out, indent_level+2) - << assign_stmt << "PyUnicode_FromWideChar(" + << assign_stmt << "PyUnicode_FromWideChar(" << return_expr << ", wcslen(" << return_expr << "));\n"; indent(out, indent_level) << "}\n"; @@ -3321,11 +3363,11 @@ pack_python_value(ostream &out, int indent_level, FunctionRemap *remap, indent(out, indent_level) << assign_stmt << "PyInt_FromLong(" << return_expr << ");\n"; out << "#endif\n"; - + } else if (TypeManager::is_float(type)) { indent(out, indent_level) << assign_stmt << "PyFloat_FromDouble(" << return_expr << ");\n"; - + } else if (TypeManager::is_char_pointer(type)) { indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n"; indent(out, indent_level) << " Py_INCREF(Py_None);\n"; @@ -3341,14 +3383,14 @@ pack_python_value(ostream &out, int indent_level, FunctionRemap *remap, out << "#endif\n"; indent(out, indent_level) << "}\n"; - + } else if (TypeManager::is_wchar_pointer(type)) { indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n"; indent(out, indent_level) << " Py_INCREF(Py_None);\n"; indent(out, indent_level+2) << assign_stmt << "Py_None;\n"; indent(out, indent_level) << "} else {\n"; indent(out, indent_level+2) << assign_stmt - << "PyUnicode_FromWideChar(" + << "PyUnicode_FromWideChar(" << return_expr << ", wcslen(" << return_expr << "));\n"; indent(out, indent_level) << "}\n"; @@ -3373,12 +3415,12 @@ pack_python_value(ostream &out, int indent_level, FunctionRemap *remap, } else { const_flag = "false"; } - + if (TypeManager::is_struct(orig_type) || TypeManager::is_ref_to_anything(orig_type)) { if (TypeManager::is_ref_to_anything(orig_type)) { TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(type)),false); InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - const InterrogateType &itype = idb->get_type(type_index); + const InterrogateType &itype = idb->get_type(type_index); std::string owns_memory_flag("true"); if (remap->_return_value_needs_management) { @@ -3405,7 +3447,7 @@ pack_python_value(ostream &out, int indent_level, FunctionRemap *remap, if (remap->_manage_reference_count) { TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(type)),false); InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - const InterrogateType &itype = idb->get_type(type_index); + const InterrogateType &itype = idb->get_type(type_index); if (!isExportThisRun(itype._cpptype)) { _external_imports.insert(make_safe_name(itype.get_scoped_name())); @@ -3417,7 +3459,7 @@ pack_python_value(ostream &out, int indent_level, FunctionRemap *remap, } else { TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(orig_type)),false); InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - const InterrogateType &itype = idb->get_type(type_index); + const InterrogateType &itype = idb->get_type(type_index); if (!isExportThisRun(itype._cpptype)) { _external_imports.insert(make_safe_name(itype.get_scoped_name())); @@ -3431,7 +3473,7 @@ pack_python_value(ostream &out, int indent_level, FunctionRemap *remap, } else if (TypeManager::is_struct(orig_type->as_pointer_type()->_pointing_at)) { TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(orig_type)),false); InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - const InterrogateType &itype = idb->get_type(type_index); + const InterrogateType &itype = idb->get_type(type_index); std::string owns_memory_flag("true"); if (remap->_return_value_needs_management) { @@ -3475,7 +3517,7 @@ write_make_seq(ostream &out, Object *obj, const std::string &ClassName, string num_name = methodNameFromCppName(make_seq->_num_name, ClassName, false); string element_name = methodNameFromCppName(make_seq->_element_name, ClassName, false); - out << " return make_list_for_item(self, \"" << num_name + out << " return make_list_for_item(self, \"" << num_name << "\", \"" << element_name << "\");\n"; out << "}\n"; } @@ -3499,7 +3541,7 @@ record_object(TypeIndex type_index) { } InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - const InterrogateType &itype = idb->get_type(type_index); + const InterrogateType &itype = idb->get_type(type_index); if (!is_cpp_type_legal(itype._cpptype)) { return (Object *)NULL; @@ -3518,7 +3560,7 @@ record_object(TypeIndex type_index) { object->_constructors.push_back(function); } } - + int num_methods = itype.number_of_methods(); int mi; for (mi = 0; mi < num_methods; mi++) { @@ -3527,7 +3569,7 @@ record_object(TypeIndex type_index) { object->_methods.push_back(function); } } - + int num_casts = itype.number_of_casts(); for (mi = 0; mi < num_casts; mi++) { function = record_function(itype, itype.get_cast(mi)); @@ -3535,11 +3577,11 @@ record_object(TypeIndex type_index) { object->_methods.push_back(function); } } - + int num_derivations = itype.number_of_derivations(); for (int di = 0; di < num_derivations; di++) { TypeIndex d_type_Index = itype.get_derivation(di); - idb->get_type(d_type_Index); + idb->get_type(d_type_Index); if (!interrogate_type_is_unpublished(d_type_Index)) { if (itype.derivation_has_upcast(di)) { @@ -3577,7 +3619,7 @@ record_object(TypeIndex type_index) { FunctionIndex func_index = ielement.get_setter(); record_function(itype, func_index); } - } + } object->check_protocols(); @@ -3623,9 +3665,7 @@ generate_wrappers() { for (int fi = 0; fi < num_functions; fi++) { FunctionIndex func_index = idb->get_global_function(fi); record_function(dummy_type, func_index); - } - - + } int num_manifests = idb->get_num_global_manifests(); for (int mi = 0; mi < num_manifests; mi++) { @@ -3635,7 +3675,7 @@ generate_wrappers() { FunctionIndex func_index = iman.get_getter(); record_function(dummy_type, func_index); } - } + } int num_elements = idb->get_num_global_elements(); for (int ei = 0; ei < num_elements; ei++) { @@ -3649,10 +3689,11 @@ generate_wrappers() { FunctionIndex func_index = ielement.get_setter(); record_function(dummy_type, func_index); } - } + } inside_python_native = false; -} -////////////////////////////////////////////// +} + +////////////////////////////////////////////// // Function :is_cpp_type_legal // // is the cpp object supported by by the dtool_py interface.. @@ -3770,7 +3811,7 @@ is_function_legal(Function *func) { return true; } - } + } // printf(" Function Is Marked Illegal %s\n",func->_name.c_str()); return false; @@ -3789,7 +3830,7 @@ isFunctionWithThis(Function *func) { if (remap->_has_this) { return true; } - } + } return false; } @@ -3901,7 +3942,7 @@ DoesInheritFromIsClass(const CPPStructType *inclass, const std::string &name) { return true; } } - } + } return false; } @@ -3929,22 +3970,22 @@ HasAGetKeyFunction(const InterrogateType &itype_class) { ++ii) { CPPInstance *cppinst = (*ii).second; CPPFunctionType *cppfunc = cppinst->_type->as_function_type(); - + if (cppfunc != NULL) { if (cppfunc->_parameters != NULL && - cppfunc->_return_type != NULL && + cppfunc->_return_type != NULL && TypeManager::is_integer(cppfunc->_return_type)) { if (cppfunc->_parameters->_parameters.size() == 0) { return ifunc.get_name(); } } } - } + } } } } return string(); -}; +} //////////////////////////////////////////////////////////////////////////////////////////// // Function : HasAGetClassTypeFunction @@ -3954,7 +3995,7 @@ HasAGetKeyFunction(const InterrogateType &itype_class) { bool InterfaceMakerPythonNative:: HasAGetClassTypeFunction(const InterrogateType &itype_class) { InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - + int num_methods = itype_class.number_of_methods(); int mi; for (mi = 0; mi < num_methods; mi++) { @@ -3966,7 +4007,7 @@ HasAGetClassTypeFunction(const InterrogateType &itype_class) { for (ii = ifunc._instances->begin();ii != ifunc._instances->end();++ii) { CPPInstance *cppinst = (*ii).second; CPPFunctionType *cppfunc = cppinst->_type->as_function_type(); - + if (cppfunc != NULL && cppfunc->_return_type != NULL && cppfunc->_parameters != NULL) { CPPType *ret_type = TypeManager::unwrap(cppfunc->_return_type); @@ -3977,8 +4018,7 @@ HasAGetClassTypeFunction(const InterrogateType &itype_class) { } } } - - } + } } } } @@ -4014,8 +4054,8 @@ NeedsAStrFunction(const InterrogateType &itype_class) { CPPFunctionType *cppfunc = cppinst->_type->as_function_type(); if (cppfunc != NULL) { - if (cppfunc->_parameters != NULL && - cppfunc->_return_type != NULL && + if (cppfunc->_parameters != NULL && + cppfunc->_return_type != NULL && TypeManager::is_void(cppfunc->_return_type)) { if (cppfunc->_parameters->_parameters.size() == 1) { CPPInstance *inst1 = cppfunc->_parameters->_parameters[0]; @@ -4042,7 +4082,7 @@ NeedsAStrFunction(const InterrogateType &itype_class) { } } } - } + } } } } @@ -4083,8 +4123,8 @@ NeedsAReprFunction(const InterrogateType &itype_class) { CPPFunctionType *cppfunc = cppinst->_type->as_function_type(); if (cppfunc != NULL) { - if (cppfunc->_parameters != NULL && - cppfunc->_return_type != NULL && + if (cppfunc->_parameters != NULL && + cppfunc->_return_type != NULL && TypeManager::is_void(cppfunc->_return_type)) { if (cppfunc->_parameters->_parameters.size() == 2) { CPPInstance *inst1 = cppfunc->_parameters->_parameters[0]; @@ -4103,7 +4143,7 @@ NeedsAReprFunction(const InterrogateType &itype_class) { } } } - } + } } } } @@ -4121,8 +4161,8 @@ NeedsAReprFunction(const InterrogateType &itype_class) { CPPFunctionType *cppfunc = cppinst->_type->as_function_type(); if (cppfunc != NULL) { - if (cppfunc->_parameters != NULL && - cppfunc->_return_type != NULL && + if (cppfunc->_parameters != NULL && + cppfunc->_return_type != NULL && TypeManager::is_void(cppfunc->_return_type)) { if (cppfunc->_parameters->_parameters.size() == 1) { CPPInstance *inst1 = cppfunc->_parameters->_parameters[0]; @@ -4144,7 +4184,7 @@ NeedsAReprFunction(const InterrogateType &itype_class) { } } } - } + } } } } diff --git a/dtool/src/interrogate/interrogateBuilder.cxx b/dtool/src/interrogate/interrogateBuilder.cxx index e98ef7fc87..3624de5352 100644 --- a/dtool/src/interrogate/interrogateBuilder.cxx +++ b/dtool/src/interrogate/interrogateBuilder.cxx @@ -1679,6 +1679,10 @@ get_function(CPPInstance *function, string description, InterrogateFunction &ifunction = InterrogateDatabase::get_ptr()->update_function(index); + // Not 100% sure why, but there's a case where this happens, + // in a case where a typedef shadowed an actual type. ~rdb + nassertr(&ifunction != NULL, 0); + ifunction._flags |= flags; // Also, make sure this particular signature is defined. diff --git a/dtool/src/interrogate/interrogate_module.cxx b/dtool/src/interrogate/interrogate_module.cxx index 9292f04b02..fb25057007 100644 --- a/dtool/src/interrogate/interrogate_module.cxx +++ b/dtool/src/interrogate/interrogate_module.cxx @@ -112,7 +112,7 @@ int write_python_table_native(ostream &out) { pset::iterator ii; for(ii = libraries.begin(); ii != libraries.end(); ii++) { printf("Referencing Library %s\n", (*ii).c_str()); - out << "extern LibraryDef " << *ii << "_moddef;\n"; + out << "IMPORT_THIS LibraryDef " << *ii << "_moddef;\n"; } out << "\n" diff --git a/dtool/src/interrogatedb/extension.h b/dtool/src/interrogatedb/extension.h index 53f2e6241d..0d41ef2c60 100644 --- a/dtool/src/interrogatedb/extension.h +++ b/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 EXPCL_DTOOLCONFIG ExtensionBase { public: T * _this; - PyObject * _self; }; //////////////////////////////////////////////////////////////////// @@ -52,10 +48,9 @@ class EXPCL_DTOOLCONFIG Extension : public ExtensionBase { //////////////////////////////////////////////////////////////////// template inline Extension -invoke_extension(T *ptr, PyObject *self = NULL) { +invoke_extension(T *ptr) { Extension ext; ext._this = ptr; - ext._self = self; return ext; } @@ -65,10 +60,9 @@ invoke_extension(T *ptr, PyObject *self = NULL) { //////////////////////////////////////////////////////////////////// template inline const Extension -invoke_extension(const T *ptr, PyObject *self = NULL) { +invoke_extension(const T *ptr) { Extension ext; ext._this = (T *) ptr; - ext._self = self; return ext; } diff --git a/dtool/src/interrogatedb/py_panda.cxx b/dtool/src/interrogatedb/py_panda.cxx index 786b45d15e..f0123e459e 100644 --- a/dtool/src/interrogatedb/py_panda.cxx +++ b/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; diff --git a/dtool/src/parser-inc/Python.h b/dtool/src/parser-inc/Python.h index f0c9d32511..d63928fdfe 100755 --- a/dtool/src/parser-inc/Python.h +++ b/dtool/src/parser-inc/Python.h @@ -25,4 +25,7 @@ class PyThreadState; typedef int Py_ssize_t; struct Py_buffer; +// This file defines PY_VERSION_HEX, which is used in some places. +#include "patchlevel.h" + #endif // PYTHON_H diff --git a/dtool/src/prc/streamReader.h b/dtool/src/prc/streamReader.h index e8900704cd..8d71cf6b9b 100644 --- a/dtool/src/prc/streamReader.h +++ b/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; diff --git a/makepanda/Panda3D-tpl.dmg b/makepanda/Panda3D-tpl.dmg deleted file mode 100644 index 55c6fa12a1..0000000000 Binary files a/makepanda/Panda3D-tpl.dmg and /dev/null differ diff --git a/makepanda/installpanda.py b/makepanda/installpanda.py index 1163da7a38..2f3deadd5d 100644 --- a/makepanda/installpanda.py +++ b/makepanda/installpanda.py @@ -125,7 +125,6 @@ def InstallPanda(destdir="", prefix="/usr", outputdir="built"): oscmd("mkdir -m 0755 -p "+destdir+prefix+"/bin") oscmd("mkdir -m 0755 -p "+destdir+prefix+"/include") oscmd("mkdir -m 0755 -p "+destdir+prefix+"/share/panda3d") - oscmd("mkdir -m 0755 -p "+destdir+prefix+"/share/panda3d/direct") oscmd("mkdir -m 0755 -p "+destdir+prefix+"/share/mime-info") oscmd("mkdir -m 0755 -p "+destdir+prefix+"/share/mime/packages") oscmd("mkdir -m 0755 -p "+destdir+prefix+"/share/application-registry") @@ -137,7 +136,6 @@ def InstallPanda(destdir="", prefix="/usr", outputdir="built"): oscmd("mkdir -m 0755 -p "+destdir+"/usr/local/libdata/ldconfig") else: oscmd("mkdir -m 0755 -p "+destdir+"/etc/ld.so.conf.d") - WriteFile(destdir+prefix+"/share/panda3d/direct/__init__.py", "") Configrc = ReadFile(outputdir+"/etc/Config.prc") Configrc = Configrc.replace("model-path $THIS_PRC_DIR/..", "model-path "+prefix+"/share/panda3d") if (sys.platform.startswith("freebsd")): @@ -147,13 +145,13 @@ def InstallPanda(destdir="", prefix="/usr", outputdir="built"): WriteFile(destdir+"/etc/Config.prc", Configrc) oscmd("cp "+outputdir+"/etc/Confauto.prc "+destdir+"/etc/Confauto.prc") oscmd("cp -R "+outputdir+"/include "+destdir+prefix+"/include/panda3d") - oscmd("cp -R direct/src/* "+destdir+prefix+"/share/panda3d/direct") - oscmd("cp -R "+outputdir+"/pandac "+destdir+prefix+"/share/panda3d/pandac") - oscmd("cp -R "+outputdir+"/models "+destdir+prefix+"/share/panda3d/models") - oscmd("cp direct/src/ffi/panda3d.py "+destdir+prefix+"/share/panda3d/panda3d.py") - if os.path.isdir("samples"): oscmd("cp -R samples "+destdir+prefix+"/share/panda3d/samples") - if os.path.isdir(outputdir+"/Pmw"): oscmd("cp -R "+outputdir+"/Pmw "+destdir+prefix+"/share/panda3d/Pmw") - if os.path.isdir(outputdir+"/plugins"): oscmd("cp -R "+outputdir+"/plugins "+destdir+prefix+"/share/panda3d/plugins") + oscmd("cp -R "+outputdir+"/direct "+destdir+prefix+"/share/panda3d/") + oscmd("cp -R "+outputdir+"/pandac "+destdir+prefix+"/share/panda3d/") + oscmd("cp -R "+outputdir+"/panda3d "+destdir+PPATH+"/") + oscmd("cp -R "+outputdir+"/models "+destdir+prefix+"/share/panda3d/") + if os.path.isdir("samples"): oscmd("cp -R samples "+destdir+prefix+"/share/panda3d/") + if os.path.isdir(outputdir+"/Pmw"): oscmd("cp -R "+outputdir+"/Pmw "+destdir+prefix+"/share/panda3d/") + if os.path.isdir(outputdir+"/plugins"): oscmd("cp -R "+outputdir+"/plugins "+destdir+prefix+"/share/panda3d/") WriteMimeFile(destdir+prefix+"/share/mime-info/panda3d.mime", MIME_INFO) WriteKeysFile(destdir+prefix+"/share/mime-info/panda3d.keys", MIME_INFO) WriteMimeXMLFile(destdir+prefix+"/share/mime/packages/panda3d.xml", MIME_INFO) @@ -169,7 +167,7 @@ def InstallPanda(destdir="", prefix="/usr", outputdir="built"): else: oscmd("echo '"+libdir+"/panda3d'> "+destdir+"/etc/ld.so.conf.d/panda3d.conf") oscmd("chmod +x "+destdir+"/etc/ld.so.conf.d/panda3d.conf") - oscmd("ln -s "+PEXEC+" "+destdir+prefix+"/bin/ppython") + oscmd("ln -f -s "+PEXEC+" "+destdir+prefix+"/bin/ppython") oscmd("cp "+outputdir+"/bin/* "+destdir+prefix+"/bin/") for base in os.listdir(outputdir+"/lib"): if (not base.endswith(".a")) or base == "libp3pystub.a": diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 9fbe316221..5f15299514 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -1352,29 +1352,42 @@ def CompileLink(dll, obj, opts): else: cmd += " /NOD:MSVCRT.LIB mfcs100.lib MSVCRT.lib" cmd += " /FIXED:NO /OPT:REF /STACK:4194304 /INCREMENTAL:NO " cmd += ' /OUT:' + BracketNameWithQuotes(dll) + subsystem = GetValueOption(opts, "SUBSYSTEM:") - if (subsystem): cmd += " /SUBSYSTEM:" + subsystem - if (dll.endswith(".dll")): - cmd += ' /IMPLIB:' + GetOutputDir() + '/lib/'+os.path.splitext(os.path.basename(dll))[0]+".lib" + if subsystem: + cmd += " /SUBSYSTEM:" + subsystem + + if dll.endswith(".dll"): + cmd += ' /IMPLIB:' + GetOutputDir() + '/lib/' + os.path.splitext(os.path.basename(dll))[0] + ".lib" + for (opt, dir) in LIBDIRECTORIES: - if (opt=="ALWAYS") or (opt in opts): cmd += ' /LIBPATH:' + BracketNameWithQuotes(dir) + if (opt=="ALWAYS") or (opt in opts): + cmd += ' /LIBPATH:' + BracketNameWithQuotes(dir) + for x in obj: - if (x.endswith(".dll")): + if x.endswith(".dll"): cmd += ' ' + GetOutputDir() + '/lib/' + os.path.splitext(os.path.basename(x))[0] + ".lib" - elif (x.endswith(".lib")): + elif x.endswith(".pyd"): + cmd += ' ' + os.path.splitext(x)[0] + ".lib" + elif x.endswith(".lib"): dname = os.path.splitext(os.path.basename(x))[0] + ".dll" if (GetOrigExt(x) != ".ilb" and os.path.exists(GetOutputDir()+"/bin/" + dname)): exit("Error: in makepanda, specify "+dname+", not "+x) cmd += ' ' + BracketNameWithQuotes(x) - elif (x.endswith(".def")): + elif x.endswith(".def"): cmd += ' /DEF:' + BracketNameWithQuotes(x) - elif (x.endswith(".dat")): + elif x.endswith(".dat"): pass - else: cmd += ' ' + BracketNameWithQuotes(x) + else: + cmd += ' ' + BracketNameWithQuotes(x) + if (GetOrigExt(dll)==".exe" and "NOICON" not in opts): cmd += " " + GetOutputDir() + "/tmp/pandaIcon.res" + for (opt, name) in LIBNAMES: - if (opt=="ALWAYS") or (opt in opts): cmd += " " + BracketNameWithQuotes(name) + if (opt=="ALWAYS") or (opt in opts): + cmd += " " + BracketNameWithQuotes(name) + oscmd(cmd) else: cmd = "xilink" @@ -1399,29 +1412,42 @@ def CompileLink(dll, obj, opts): else: cmd += " /NOD:MSVCRT.LIB mfcs100.lib MSVCRT.lib" cmd += " /FIXED:NO /OPT:REF /STACK:4194304 /INCREMENTAL:NO " cmd += ' /OUT:' + BracketNameWithQuotes(dll) + subsystem = GetValueOption(opts, "SUBSYSTEM:") - if (subsystem): cmd += " /SUBSYSTEM:" + subsystem - if (dll.endswith(".dll")): - cmd += ' /IMPLIB:' + GetOutputDir() + '/lib/'+os.path.splitext(os.path.basename(dll))[0]+".lib" + if subsystem: + cmd += " /SUBSYSTEM:" + subsystem + + if dll.endswith(".dll"): + cmd += ' /IMPLIB:' + GetOutputDir() + '/lib/' + os.path.splitext(os.path.basename(dll))[0] + ".lib" + for (opt, dir) in LIBDIRECTORIES: - if (opt=="ALWAYS") or (opt in opts): cmd += ' /LIBPATH:' + BracketNameWithQuotes(dir) + if (opt=="ALWAYS") or (opt in opts): + cmd += ' /LIBPATH:' + BracketNameWithQuotes(dir) + for x in obj: - if (x.endswith(".dll")): + if x.endswith(".dll"): cmd += ' ' + GetOutputDir() + '/lib/' + os.path.splitext(os.path.basename(x))[0] + ".lib" - elif (x.endswith(".lib")): + elif x.endswith(".pyd"): + cmd += ' ' + os.path.splitext(x)[0] + ".lib" + elif x.endswith(".lib"): dname = os.path.splitext(dll)[0]+".dll" if (GetOrigExt(x) != ".ilb" and os.path.exists(GetOutputDir()+"/bin/" + os.path.splitext(os.path.basename(x))[0] + ".dll")): exit("Error: in makepanda, specify "+dname+", not "+x) cmd += ' ' + BracketNameWithQuotes(x) - elif (x.endswith(".def")): + elif x.endswith(".def"): cmd += ' /DEF:' + BracketNameWithQuotes(x) - elif (x.endswith(".dat")): + elif x.endswith(".dat"): pass - else: cmd += ' ' + BracketNameWithQuotes(x) + else: + cmd += ' ' + BracketNameWithQuotes(x) + if (GetOrigExt(dll)==".exe" and "NOICON" not in opts): cmd += " " + GetOutputDir() + "/tmp/pandaIcon.res" + for (opt, name) in LIBNAMES: - if (opt=="ALWAYS") or (opt in opts): cmd += " " + BracketNameWithQuotes(name) + if (opt=="ALWAYS") or (opt in opts): + cmd += " " + BracketNameWithQuotes(name) + oscmd(cmd) if COMPILER == "GCC": @@ -1433,7 +1459,11 @@ def CompileLink(dll, obj, opts): cmd = cxx + ' -undefined dynamic_lookup' if ("BUNDLE" in opts): cmd += ' -bundle ' else: - cmd += ' -dynamiclib -install_name ' + os.path.basename(dll) + if GetOrigExt(dll) == ".pyd": + install_name = '@loader_path/../panda3d/' + os.path.basename(dll) + else: + install_name = os.path.basename(dll) + cmd += ' -dynamiclib -install_name ' + install_name cmd += ' -compatibility_version ' + MAJOR_VERSION + ' -current_version ' + VERSION cmd += ' -o ' + dll + ' -L' + GetOutputDir() + '/lib -L' + GetOutputDir() + '/tmp' else: @@ -1611,7 +1641,11 @@ def RunGenPyCode(target, inputs, opts): if (PkgSkip("PYTHON") != 0): return - cmdstr = sys.executable + " -B " + os.path.join(GetOutputDir(), "direct", "ffi", "jGenPyCode.py") + cmdstr = sys.executable + " " + if sys.version_info >= (2, 6): + cmdstr += "-B " + + cmdstr += os.path.join(GetOutputDir(), "direct", "ffi", "jGenPyCode.py") if (GENMAN): cmdstr += " -d" cmdstr += " -r" for i in inputs: @@ -1631,7 +1665,11 @@ def RunGenPyCode(target, inputs, opts): def FreezePy(target, inputs, opts): assert len(inputs) > 0 # Make sure this function isn't called before genpycode is run. - cmdstr = sys.executable + " -B " + os.path.join("direct", "src", "showutil", "pfreeze.py") + cmdstr = sys.executable + " " + if sys.version_info >= (2, 6): + cmdstr += "-B " + + cmdstr += os.path.join("direct", "src", "showutil", "pfreeze.py") src = inputs.pop(0) for i in inputs: cmdstr += " -i " + os.path.splitext(i)[0] @@ -1655,10 +1693,14 @@ def FreezePy(target, inputs, opts): def Package(target, inputs, opts): assert len(inputs) == 1 # Invoke the ppackage script. - command = sys.executable - if (GetOptimizeOption(opts) >= 4): - command += " -OO" - command += " -B direct/src/p3d/ppackage.py" + command = sys.executable + " " + if GetOptimizeOption(opts) >= 4: + command += "-OO " + + if sys.version_info >= (2, 6): + command += "-B " + + command += "direct/src/p3d/ppackage.py" if GetTarget() == "darwin": if SDK.get("MACOSX") is not None: @@ -1775,16 +1817,16 @@ def CompileAnything(target, inputs, opts, progress = None): ProgressOutput(progress, "Linking dynamic library", target) # Add version number to the dynamic library, on unix - if origsuffix==".dll" and "MODULE" not in opts and not RTDIST: + if origsuffix == ".dll" and "MODULE" not in opts and not RTDIST: tplatform = GetTarget() if tplatform == "darwin": # On Mac, libraries are named like libpanda.1.2.dylib - if tplatform.lower().endswith(".dylib"): - tplatform = tplatform[:-5] + MAJOR_VERSION + ".dylib" + if target.lower().endswith(".dylib"): + target = target[:-5] + MAJOR_VERSION + ".dylib" SetOrigExt(target, origsuffix) elif tplatform != "windows" and tplatform != "android": # On Linux, libraries are named like libpanda.so.1.2 - tplatform += "." + MAJOR_VERSION + target += "." + MAJOR_VERSION SetOrigExt(target, origsuffix) return CompileLink(target, inputs, opts) elif (origsuffix==".in"): @@ -2376,17 +2418,26 @@ CreatePandaVersionFiles() ########################################################################################## # -# Copy the "direct" tree and panda3d.py +# Copy the "direct" tree # ########################################################################################## if (PkgSkip("DIRECT")==0): CopyPythonTree(GetOutputDir() + '/direct', 'direct/src', lib2to3_fixers=['all']) ConditionalWriteFile(GetOutputDir() + '/direct/__init__.py', "") - if (GetTarget() == 'windows'): - CopyFile(GetOutputDir()+'/bin/panda3d.py', 'direct/src/ffi/panda3d.py') - else: - CopyFile(GetOutputDir()+'/lib/panda3d.py', 'direct/src/ffi/panda3d.py') + + # This file used to be copied, but would nowadays cause conflicts. + # Let's get it out of the way in case someone hasn't cleaned their build since. + if os.path.isfile(GetOutputDir() + '/bin/panda3d.py'): + os.remove(GetOutputDir() + '/bin/panda3d.py') + if os.path.isfile(GetOutputDir() + '/lib/panda3d.py'): + os.remove(GetOutputDir() + '/lib/panda3d.py') + + # Don't copy this file, which would cause conflict with our 'panda3d' module. + if os.path.isfile(GetOutputDir() + '/direct/ffi/panda3d.py'): + os.remove(GetOutputDir() + '/direct/ffi/panda3d.py') + if os.path.isfile(GetOutputDir() + '/direct/ffi/panda3d.pyc'): + os.remove(GetOutputDir() + '/direct/ffi/panda3d.pyc') ########################################################################################## # @@ -2919,11 +2970,11 @@ TargetAdd('p3pandabase_pandabase.obj', opts=OPTS, input='pandabase.cxx') OPTS=['DIR:panda/src/express', 'BUILDING:PANDAEXPRESS', 'OPENSSL', 'ZLIB'] TargetAdd('p3express_composite1.obj', opts=OPTS, input='p3express_composite1.cxx') TargetAdd('p3express_composite2.obj', opts=OPTS, input='p3express_composite2.cxx') +TargetAdd('p3express_ext_composite.obj', opts=OPTS, input='p3express_ext_composite.cxx') IGATEFILES=GetDirectoryContents('panda/src/express', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3express.in', opts=OPTS, input=IGATEFILES) -TargetAdd('libp3express.in', opts=['IMOD:pandaexpress', 'ILIB:libp3express', 'SRCDIR:panda/src/express']) +TargetAdd('libp3express.in', opts=['IMOD:core', 'ILIB:libp3express', 'SRCDIR:panda/src/express']) TargetAdd('libp3express_igate.obj', input='libp3express.in', opts=["DEPENDENCYONLY"]) -TargetAdd('p3express_virtualFileSystem_ext.obj', opts=OPTS, input='virtualFileSystem_ext.cxx') # # DIRECTORY: panda/src/downloader/ @@ -2934,7 +2985,7 @@ TargetAdd('p3downloader_composite1.obj', opts=OPTS, input='p3downloader_composit TargetAdd('p3downloader_composite2.obj', opts=OPTS, input='p3downloader_composite2.cxx') IGATEFILES=GetDirectoryContents('panda/src/downloader', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3downloader.in', opts=OPTS, input=IGATEFILES) -TargetAdd('libp3downloader.in', opts=['IMOD:pandaexpress', 'ILIB:libp3downloader', 'SRCDIR:panda/src/downloader']) +TargetAdd('libp3downloader.in', opts=['IMOD:core', 'ILIB:libp3downloader', 'SRCDIR:panda/src/downloader']) TargetAdd('libp3downloader_igate.obj', input='libp3downloader.in', opts=["DEPENDENCYONLY"]) # @@ -2943,20 +2994,14 @@ TargetAdd('libp3downloader_igate.obj', input='libp3downloader.in', opts=["DEPEND OPTS=['DIR:panda/metalibs/pandaexpress', 'BUILDING:PANDAEXPRESS', 'ZLIB'] TargetAdd('pandaexpress_pandaexpress.obj', opts=OPTS, input='pandaexpress.cxx') -TargetAdd('libpandaexpress_module.obj', input='libp3downloader.in') -TargetAdd('libpandaexpress_module.obj', input='libp3express.in') -TargetAdd('libpandaexpress_module.obj', opts=['ADVAPI', 'OPENSSL']) -TargetAdd('libpandaexpress_module.obj', opts=['IMOD:pandaexpress', 'ILIB:libpandaexpress']) - TargetAdd('libpandaexpress.dll', input='pandaexpress_pandaexpress.obj') -TargetAdd('libpandaexpress.dll', input='libpandaexpress_module.obj') TargetAdd('libpandaexpress.dll', input='p3downloader_composite1.obj') TargetAdd('libpandaexpress.dll', input='p3downloader_composite2.obj') TargetAdd('libpandaexpress.dll', input='libp3downloader_igate.obj') TargetAdd('libpandaexpress.dll', input='p3express_composite1.obj') TargetAdd('libpandaexpress.dll', input='p3express_composite2.obj') +TargetAdd('libpandaexpress.dll', input='p3express_ext_composite.obj') TargetAdd('libpandaexpress.dll', input='libp3express_igate.obj') -TargetAdd('libpandaexpress.dll', input='p3express_virtualFileSystem_ext.obj') TargetAdd('libpandaexpress.dll', input='p3pandabase_pandabase.obj') TargetAdd('libpandaexpress.dll', input=COMMON_DTOOL_LIBS) TargetAdd('libpandaexpress.dll', opts=['ADVAPI', 'WINSOCK2', 'OPENSSL', 'ZLIB', 'WINGDI', 'WINUSER']) @@ -2972,7 +3017,7 @@ if (not RUNTIME): TargetAdd('p3pipeline_contextSwitch.obj', opts=OPTS, input='contextSwitch.c') IGATEFILES=GetDirectoryContents('panda/src/pipeline', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3pipeline.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3pipeline.in', opts=['IMOD:panda', 'ILIB:libp3pipeline', 'SRCDIR:panda/src/pipeline']) + TargetAdd('libp3pipeline.in', opts=['IMOD:core', 'ILIB:libp3pipeline', 'SRCDIR:panda/src/pipeline']) TargetAdd('libp3pipeline_igate.obj', input='libp3pipeline.in', opts=["DEPENDENCYONLY"]) # @@ -2986,8 +3031,9 @@ if (not RUNTIME): IGATEFILES=GetDirectoryContents('panda/src/putil', ["*.h", "*_composite*.cxx"]) IGATEFILES.remove("test_bam.h") TargetAdd('libp3putil.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3putil.in', opts=['IMOD:panda', 'ILIB:libp3putil', 'SRCDIR:panda/src/putil']) + TargetAdd('libp3putil.in', opts=['IMOD:core', 'ILIB:libp3putil', 'SRCDIR:panda/src/putil']) TargetAdd('libp3putil_igate.obj', input='libp3putil.in', opts=["DEPENDENCYONLY"]) + TargetAdd('p3putil_typedWritable_ext.obj', opts=OPTS, input='typedWritable_ext.cxx') # # DIRECTORY: panda/src/audio/ @@ -2998,7 +3044,7 @@ if (not RUNTIME): TargetAdd('p3audio_composite1.obj', opts=OPTS, input='p3audio_composite1.cxx') IGATEFILES=["audio.h"] TargetAdd('libp3audio.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3audio.in', opts=['IMOD:panda', 'ILIB:libp3audio', 'SRCDIR:panda/src/audio']) + TargetAdd('libp3audio.in', opts=['IMOD:core', 'ILIB:libp3audio', 'SRCDIR:panda/src/audio']) TargetAdd('libp3audio_igate.obj', input='libp3audio.in', opts=["DEPENDENCYONLY"]) # @@ -3011,7 +3057,7 @@ if (not RUNTIME): TargetAdd('p3event_composite2.obj', opts=OPTS, input='p3event_composite2.cxx') IGATEFILES=GetDirectoryContents('panda/src/event', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3event.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3event.in', opts=['IMOD:panda', 'ILIB:libp3event', 'SRCDIR:panda/src/event']) + TargetAdd('libp3event.in', opts=['IMOD:core', 'ILIB:libp3event', 'SRCDIR:panda/src/event']) TargetAdd('libp3event_igate.obj', input='libp3event.in', opts=["DEPENDENCYONLY"]) # @@ -3030,7 +3076,7 @@ if (not RUNTIME): IGATEFILES.remove('lmat_ops.h') IGATEFILES.remove('cast_to_float.h') TargetAdd('libp3linmath.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3linmath.in', opts=['IMOD:panda', 'ILIB:libp3linmath', 'SRCDIR:panda/src/linmath']) + TargetAdd('libp3linmath.in', opts=['IMOD:core', 'ILIB:libp3linmath', 'SRCDIR:panda/src/linmath']) TargetAdd('libp3linmath_igate.obj', input='libp3linmath.in', opts=["DEPENDENCYONLY"]) # @@ -3043,7 +3089,7 @@ if (not RUNTIME): TargetAdd('p3mathutil_composite2.obj', opts=OPTS, input='p3mathutil_composite2.cxx') IGATEFILES=GetDirectoryContents('panda/src/mathutil', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3mathutil.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3mathutil.in', opts=['IMOD:panda', 'ILIB:libp3mathutil', 'SRCDIR:panda/src/mathutil']) + TargetAdd('libp3mathutil.in', opts=['IMOD:core', 'ILIB:libp3mathutil', 'SRCDIR:panda/src/mathutil']) TargetAdd('libp3mathutil_igate.obj', input='libp3mathutil.in', opts=["DEPENDENCYONLY"]) # @@ -3055,7 +3101,7 @@ if (not RUNTIME): TargetAdd('p3gsgbase_composite1.obj', opts=OPTS, input='p3gsgbase_composite1.cxx') IGATEFILES=GetDirectoryContents('panda/src/gsgbase', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3gsgbase.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3gsgbase.in', opts=['IMOD:panda', 'ILIB:libp3gsgbase', 'SRCDIR:panda/src/gsgbase']) + TargetAdd('libp3gsgbase.in', opts=['IMOD:core', 'ILIB:libp3gsgbase', 'SRCDIR:panda/src/gsgbase']) TargetAdd('libp3gsgbase_igate.obj', input='libp3gsgbase.in', opts=["DEPENDENCYONLY"]) # @@ -3068,8 +3114,9 @@ if (not RUNTIME): TargetAdd('p3pnmimage_composite2.obj', opts=OPTS, input='p3pnmimage_composite2.cxx') IGATEFILES=GetDirectoryContents('panda/src/pnmimage', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3pnmimage.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3pnmimage.in', opts=['IMOD:panda', 'ILIB:libp3pnmimage', 'SRCDIR:panda/src/pnmimage']) + TargetAdd('libp3pnmimage.in', opts=['IMOD:core', 'ILIB:libp3pnmimage', 'SRCDIR:panda/src/pnmimage']) TargetAdd('libp3pnmimage_igate.obj', input='libp3pnmimage.in', opts=["DEPENDENCYONLY"]) + TargetAdd('p3pnmimage_pfmFile_ext.obj', opts=OPTS, input='pfmFile_ext.cxx') # # DIRECTORY: panda/src/nativenet/ @@ -3080,7 +3127,7 @@ if (not RUNTIME): TargetAdd('p3nativenet_composite1.obj', opts=OPTS, input='p3nativenet_composite1.cxx') IGATEFILES=GetDirectoryContents('panda/src/nativenet', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3nativenet.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3nativenet.in', opts=['IMOD:panda', 'ILIB:libp3nativenet', 'SRCDIR:panda/src/nativenet']) + TargetAdd('libp3nativenet.in', opts=['IMOD:core', 'ILIB:libp3nativenet', 'SRCDIR:panda/src/nativenet']) TargetAdd('libp3nativenet_igate.obj', input='libp3nativenet.in', opts=["DEPENDENCYONLY"]) # @@ -3094,7 +3141,7 @@ if (not RUNTIME): IGATEFILES=GetDirectoryContents('panda/src/net', ["*.h", "*_composite*.cxx"]) IGATEFILES.remove("datagram_ui.h") TargetAdd('libp3net.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3net.in', opts=['IMOD:panda', 'ILIB:libp3net', 'SRCDIR:panda/src/net']) + TargetAdd('libp3net.in', opts=['IMOD:core', 'ILIB:libp3net', 'SRCDIR:panda/src/net']) TargetAdd('libp3net_igate.obj', input='libp3net.in', opts=["DEPENDENCYONLY"]) # @@ -3107,7 +3154,7 @@ if (not RUNTIME): TargetAdd('p3pstatclient_composite2.obj', opts=OPTS, input='p3pstatclient_composite2.cxx') IGATEFILES=GetDirectoryContents('panda/src/pstatclient', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3pstatclient.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3pstatclient.in', opts=['IMOD:panda', 'ILIB:libp3pstatclient', 'SRCDIR:panda/src/pstatclient']) + TargetAdd('libp3pstatclient.in', opts=['IMOD:core', 'ILIB:libp3pstatclient', 'SRCDIR:panda/src/pstatclient']) TargetAdd('libp3pstatclient_igate.obj', input='libp3pstatclient.in', opts=["DEPENDENCYONLY"]) # @@ -3121,7 +3168,7 @@ if (not RUNTIME): IGATEFILES=GetDirectoryContents('panda/src/gobj', ["*.h", "*_composite*.cxx"]) if ("cgfx_states.h" in IGATEFILES): IGATEFILES.remove("cgfx_states.h") TargetAdd('libp3gobj.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3gobj.in', opts=['IMOD:panda', 'ILIB:libp3gobj', 'SRCDIR:panda/src/gobj']) + TargetAdd('libp3gobj.in', opts=['IMOD:core', 'ILIB:libp3gobj', 'SRCDIR:panda/src/gobj']) TargetAdd('libp3gobj_igate.obj', input='libp3gobj.in', opts=["DEPENDENCYONLY"]) TargetAdd('p3gobj_geomVertexArrayData_ext.obj', opts=OPTS, input='geomVertexArrayData_ext.cxx') @@ -3135,7 +3182,7 @@ if (not RUNTIME): TargetAdd('p3pgraphnodes_composite2.obj', opts=OPTS, input='p3pgraphnodes_composite2.cxx') IGATEFILES=GetDirectoryContents('panda/src/pgraphnodes', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3pgraphnodes.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3pgraphnodes.in', opts=['IMOD:panda', 'ILIB:libp3pgraphnodes', 'SRCDIR:panda/src/pgraphnodes']) + TargetAdd('libp3pgraphnodes.in', opts=['IMOD:core', 'ILIB:libp3pgraphnodes', 'SRCDIR:panda/src/pgraphnodes']) TargetAdd('libp3pgraphnodes_igate.obj', input='libp3pgraphnodes.in', opts=["DEPENDENCYONLY"]) # @@ -3151,8 +3198,10 @@ if (not RUNTIME): TargetAdd('p3pgraph_composite4.obj', opts=OPTS, input='p3pgraph_composite4.cxx') IGATEFILES=GetDirectoryContents('panda/src/pgraph', ["*.h", "nodePath.cxx", "*_composite*.cxx"]) TargetAdd('libp3pgraph.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3pgraph.in', opts=['IMOD:panda', 'ILIB:libp3pgraph', 'SRCDIR:panda/src/pgraph']) + TargetAdd('libp3pgraph.in', opts=['IMOD:core', 'ILIB:libp3pgraph', 'SRCDIR:panda/src/pgraph']) TargetAdd('libp3pgraph_igate.obj', input='libp3pgraph.in', opts=["DEPENDENCYONLY","BIGOBJ"]) + TargetAdd('p3pgraph_nodePath_ext.obj', opts=OPTS, input='nodePath_ext.cxx') + TargetAdd('p3pgraph_nodePathCollection_ext.obj', opts=OPTS, input='nodePathCollection_ext.cxx') # # DIRECTORY: panda/src/cull/ @@ -3164,7 +3213,7 @@ if (not RUNTIME): TargetAdd('p3cull_composite2.obj', opts=OPTS, input='p3cull_composite2.cxx') IGATEFILES=GetDirectoryContents('panda/src/cull', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3cull.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3cull.in', opts=['IMOD:panda', 'ILIB:libp3cull', 'SRCDIR:panda/src/cull']) + TargetAdd('libp3cull.in', opts=['IMOD:core', 'ILIB:libp3cull', 'SRCDIR:panda/src/cull']) TargetAdd('libp3cull_igate.obj', input='libp3cull.in', opts=["DEPENDENCYONLY"]) # @@ -3179,7 +3228,7 @@ if (not RUNTIME): IGATEFILES.remove('movingPart.h') IGATEFILES.remove('animChannelFixed.h') TargetAdd('libp3chan.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3chan.in', opts=['IMOD:panda', 'ILIB:libp3chan', 'SRCDIR:panda/src/chan']) + TargetAdd('libp3chan.in', opts=['IMOD:core', 'ILIB:libp3chan', 'SRCDIR:panda/src/chan']) TargetAdd('libp3chan_igate.obj', input='libp3chan.in', opts=["DEPENDENCYONLY"]) @@ -3192,7 +3241,7 @@ if (not RUNTIME): TargetAdd('p3char_composite2.obj', opts=OPTS, input='p3char_composite2.cxx') IGATEFILES=GetDirectoryContents('panda/src/char', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3char.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3char.in', opts=['IMOD:panda', 'ILIB:libp3char', 'SRCDIR:panda/src/char']) + TargetAdd('libp3char.in', opts=['IMOD:core', 'ILIB:libp3char', 'SRCDIR:panda/src/char']) TargetAdd('libp3char_igate.obj', input='libp3char.in', opts=["DEPENDENCYONLY"]) # @@ -3205,7 +3254,7 @@ if (not RUNTIME): TargetAdd('p3dgraph_composite2.obj', opts=OPTS, input='p3dgraph_composite2.cxx') IGATEFILES=GetDirectoryContents('panda/src/dgraph', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3dgraph.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3dgraph.in', opts=['IMOD:panda', 'ILIB:libp3dgraph', 'SRCDIR:panda/src/dgraph']) + TargetAdd('libp3dgraph.in', opts=['IMOD:core', 'ILIB:libp3dgraph', 'SRCDIR:panda/src/dgraph']) TargetAdd('libp3dgraph_igate.obj', input='libp3dgraph.in', opts=["DEPENDENCYONLY"]) # @@ -3219,8 +3268,9 @@ if (not RUNTIME): IGATEFILES=GetDirectoryContents('panda/src/display', ["*.h", "*_composite*.cxx"]) IGATEFILES.remove("renderBuffer.h") TargetAdd('libp3display.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3display.in', opts=['IMOD:panda', 'ILIB:libp3display', 'SRCDIR:panda/src/display']) + TargetAdd('libp3display.in', opts=['IMOD:core', 'ILIB:libp3display', 'SRCDIR:panda/src/display']) TargetAdd('libp3display_igate.obj', input='libp3display.in', opts=["DEPENDENCYONLY"]) + TargetAdd('p3display_graphicsStateGuardian_ext.obj', opts=OPTS, input='graphicsStateGuardian_ext.cxx') if RTDIST and GetTarget() == 'darwin': OPTS=['DIR:panda/src/display'] @@ -3237,7 +3287,7 @@ if (not RUNTIME): TargetAdd('p3device_composite2.obj', opts=OPTS, input='p3device_composite2.cxx') IGATEFILES=GetDirectoryContents('panda/src/device', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3device.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3device.in', opts=['IMOD:panda', 'ILIB:libp3device', 'SRCDIR:panda/src/device']) + TargetAdd('libp3device.in', opts=['IMOD:core', 'ILIB:libp3device', 'SRCDIR:panda/src/device']) TargetAdd('libp3device_igate.obj', input='libp3device.in', opts=["DEPENDENCYONLY"]) # @@ -3249,7 +3299,7 @@ if (PkgSkip("FREETYPE")==0 and not RUNTIME): TargetAdd('p3pnmtext_composite1.obj', opts=OPTS, input='p3pnmtext_composite1.cxx') IGATEFILES=GetDirectoryContents('panda/src/pnmtext', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3pnmtext.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3pnmtext.in', opts=['IMOD:panda', 'ILIB:libp3pnmtext', 'SRCDIR:panda/src/pnmtext']) + TargetAdd('libp3pnmtext.in', opts=['IMOD:core', 'ILIB:libp3pnmtext', 'SRCDIR:panda/src/pnmtext']) TargetAdd('libp3pnmtext_igate.obj', input='libp3pnmtext.in', opts=["DEPENDENCYONLY"]) # @@ -3262,7 +3312,7 @@ if (not RUNTIME): TargetAdd('p3text_composite2.obj', opts=OPTS, input='p3text_composite2.cxx') IGATEFILES=GetDirectoryContents('panda/src/text', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3text.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3text.in', opts=['IMOD:panda', 'ILIB:libp3text', 'SRCDIR:panda/src/text']) + TargetAdd('libp3text.in', opts=['IMOD:core', 'ILIB:libp3text', 'SRCDIR:panda/src/text']) TargetAdd('libp3text_igate.obj', input='libp3text.in', opts=["DEPENDENCYONLY"]) # @@ -3274,7 +3324,7 @@ if (not RUNTIME): TargetAdd('p3movies_composite1.obj', opts=OPTS, input='p3movies_composite1.cxx') IGATEFILES=GetDirectoryContents('panda/src/movies', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3movies.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3movies.in', opts=['IMOD:panda', 'ILIB:libp3movies', 'SRCDIR:panda/src/movies']) + TargetAdd('libp3movies.in', opts=['IMOD:core', 'ILIB:libp3movies', 'SRCDIR:panda/src/movies']) TargetAdd('libp3movies_igate.obj', input='libp3movies.in', opts=["DEPENDENCYONLY"]) # @@ -3287,8 +3337,9 @@ if (not RUNTIME): TargetAdd('p3grutil_composite1.obj', opts=OPTS, input='p3grutil_composite1.cxx') TargetAdd('p3grutil_composite2.obj', opts=OPTS, input='p3grutil_composite2.cxx') IGATEFILES=GetDirectoryContents('panda/src/grutil', ["*.h", "*_composite*.cxx"]) + if 'convexHull.h' in IGATEFILES: IGATEFILES.remove('convexHull.h') TargetAdd('libp3grutil.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3grutil.in', opts=['IMOD:panda', 'ILIB:libp3grutil', 'SRCDIR:panda/src/grutil']) + TargetAdd('libp3grutil.in', opts=['IMOD:core', 'ILIB:libp3grutil', 'SRCDIR:panda/src/grutil']) TargetAdd('libp3grutil_igate.obj', input='libp3grutil.in', opts=["DEPENDENCYONLY"]) # @@ -3301,7 +3352,7 @@ if (not RUNTIME): TargetAdd('p3tform_composite2.obj', opts=OPTS, input='p3tform_composite2.cxx') IGATEFILES=GetDirectoryContents('panda/src/tform', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3tform.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3tform.in', opts=['IMOD:panda', 'ILIB:libp3tform', 'SRCDIR:panda/src/tform']) + TargetAdd('libp3tform.in', opts=['IMOD:core', 'ILIB:libp3tform', 'SRCDIR:panda/src/tform']) TargetAdd('libp3tform_igate.obj', input='libp3tform.in', opts=["DEPENDENCYONLY"]) # @@ -3314,7 +3365,7 @@ if (not RUNTIME): TargetAdd('p3collide_composite2.obj', opts=OPTS, input='p3collide_composite2.cxx') IGATEFILES=GetDirectoryContents('panda/src/collide', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3collide.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3collide.in', opts=['IMOD:panda', 'ILIB:libp3collide', 'SRCDIR:panda/src/collide']) + TargetAdd('libp3collide.in', opts=['IMOD:core', 'ILIB:libp3collide', 'SRCDIR:panda/src/collide']) TargetAdd('libp3collide_igate.obj', input='libp3collide.in', opts=["DEPENDENCYONLY"]) # @@ -3327,7 +3378,7 @@ if (not RUNTIME): TargetAdd('p3parametrics_composite2.obj', opts=OPTS, input='p3parametrics_composite2.cxx') IGATEFILES=GetDirectoryContents('panda/src/parametrics', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3parametrics.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3parametrics.in', opts=['IMOD:panda', 'ILIB:libp3parametrics', 'SRCDIR:panda/src/parametrics']) + TargetAdd('libp3parametrics.in', opts=['IMOD:core', 'ILIB:libp3parametrics', 'SRCDIR:panda/src/parametrics']) TargetAdd('libp3parametrics_igate.obj', input='libp3parametrics.in', opts=["DEPENDENCYONLY"]) # @@ -3340,7 +3391,7 @@ if (not RUNTIME): TargetAdd('p3pgui_composite2.obj', opts=OPTS, input='p3pgui_composite2.cxx') IGATEFILES=GetDirectoryContents('panda/src/pgui', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3pgui.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3pgui.in', opts=['IMOD:panda', 'ILIB:libp3pgui', 'SRCDIR:panda/src/pgui']) + TargetAdd('libp3pgui.in', opts=['IMOD:core', 'ILIB:libp3pgui', 'SRCDIR:panda/src/pgui']) TargetAdd('libp3pgui_igate.obj', input='libp3pgui.in', opts=["DEPENDENCYONLY"]) # @@ -3362,7 +3413,7 @@ if (not RUNTIME): TargetAdd('p3recorder_composite2.obj', opts=OPTS, input='p3recorder_composite2.cxx') IGATEFILES=GetDirectoryContents('panda/src/recorder', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3recorder.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3recorder.in', opts=['IMOD:panda', 'ILIB:libp3recorder', 'SRCDIR:panda/src/recorder']) + TargetAdd('libp3recorder.in', opts=['IMOD:core', 'ILIB:libp3recorder', 'SRCDIR:panda/src/recorder']) TargetAdd('libp3recorder_igate.obj', input='libp3recorder.in', opts=["DEPENDENCYONLY"]) # @@ -3381,7 +3432,7 @@ if (not RUNTIME): TargetAdd('p3dxml_composite1.obj', opts=OPTS, input='p3dxml_composite1.cxx') IGATEFILES=GetDirectoryContents('panda/src/dxml', ["*.h", "p3dxml_composite1.cxx"]) TargetAdd('libp3dxml.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3dxml.in', opts=['IMOD:panda', 'ILIB:libp3dxml', 'SRCDIR:panda/src/dxml']) + TargetAdd('libp3dxml.in', opts=['IMOD:core', 'ILIB:libp3dxml', 'SRCDIR:panda/src/dxml']) TargetAdd('libp3dxml_igate.obj', input='libp3dxml.in', opts=["DEPENDENCYONLY"]) # @@ -3395,38 +3446,7 @@ if (not RUNTIME): TargetAdd('panda_panda.obj', opts=OPTS, input='panda.cxx') - TargetAdd('libpanda_module.obj', input='libp3recorder.in') - TargetAdd('libpanda_module.obj', input='libp3pgraphnodes.in') - TargetAdd('libpanda_module.obj', input='libp3pgraph.in') - TargetAdd('libpanda_module.obj', input='libp3cull.in') - TargetAdd('libpanda_module.obj', input='libp3grutil.in') - TargetAdd('libpanda_module.obj', input='libp3chan.in') - TargetAdd('libpanda_module.obj', input='libp3pstatclient.in') - TargetAdd('libpanda_module.obj', input='libp3char.in') - TargetAdd('libpanda_module.obj', input='libp3collide.in') - TargetAdd('libpanda_module.obj', input='libp3device.in') - TargetAdd('libpanda_module.obj', input='libp3dgraph.in') - TargetAdd('libpanda_module.obj', input='libp3display.in') - TargetAdd('libpanda_module.obj', input='libp3pipeline.in') - TargetAdd('libpanda_module.obj', input='libp3event.in') - TargetAdd('libpanda_module.obj', input='libp3gobj.in') - TargetAdd('libpanda_module.obj', input='libp3gsgbase.in') - TargetAdd('libpanda_module.obj', input='libp3linmath.in') - TargetAdd('libpanda_module.obj', input='libp3mathutil.in') - TargetAdd('libpanda_module.obj', input='libp3parametrics.in') - TargetAdd('libpanda_module.obj', input='libp3pnmimage.in') - TargetAdd('libpanda_module.obj', input='libp3text.in') - TargetAdd('libpanda_module.obj', input='libp3tform.in') - TargetAdd('libpanda_module.obj', input='libp3putil.in') - TargetAdd('libpanda_module.obj', input='libp3audio.in') - TargetAdd('libpanda_module.obj', input='libp3nativenet.in') - TargetAdd('libpanda_module.obj', input='libp3net.in') - TargetAdd('libpanda_module.obj', input='libp3pgui.in') - TargetAdd('libpanda_module.obj', input='libp3movies.in') - TargetAdd('libpanda_module.obj', input='libp3dxml.in') - TargetAdd('libpanda.dll', input='panda_panda.obj') - TargetAdd('libpanda.dll', input='libpanda_module.obj') TargetAdd('libpanda.dll', input='p3recorder_composite1.obj') TargetAdd('libpanda.dll', input='p3recorder_composite2.obj') TargetAdd('libpanda.dll', input='libp3recorder_igate.obj') @@ -3478,7 +3498,6 @@ if (not RUNTIME): TargetAdd('libpanda.dll', input='p3gobj_composite1.obj') TargetAdd('libpanda.dll', input='p3gobj_composite2.obj') TargetAdd('libpanda.dll', input='libp3gobj_igate.obj') - TargetAdd('libpanda.dll', input='p3gobj_geomVertexArrayData_ext.obj') TargetAdd('libpanda.dll', input='p3gsgbase_composite1.obj') TargetAdd('libpanda.dll', input='libp3gsgbase_igate.obj') TargetAdd('libpanda.dll', input='p3linmath_composite1.obj') @@ -3521,64 +3540,122 @@ if (not RUNTIME): TargetAdd('libpanda.dll', input='libp3dtoolconfig.dll') TargetAdd('libpanda.dll', input='libp3dtool.dll') + TargetAdd('libpanda.dll', input='p3putil_typedWritable_ext.obj') + TargetAdd('libpanda.dll', input='p3pnmimage_pfmFile_ext.obj') + TargetAdd('libpanda.dll', input='p3gobj_geomVertexArrayData_ext.obj') + TargetAdd('libpanda.dll', input='p3pgraph_nodePath_ext.obj') + TargetAdd('libpanda.dll', input='p3pgraph_nodePathCollection_ext.obj') + TargetAdd('libpanda.dll', input='p3display_graphicsStateGuardian_ext.obj') + if PkgSkip("FREETYPE")==0: TargetAdd('libpanda.dll', input="p3pnmtext_composite1.obj") TargetAdd('libpanda.dll', input="libp3pnmtext_igate.obj") - TargetAdd('libpanda_module.obj', input='libp3pnmtext.in') - - TargetAdd('libpanda_module.obj', opts=OPTS) - TargetAdd('libpanda_module.obj', opts=['IMOD:panda', 'ILIB:libpanda']) TargetAdd('libpanda.dll', dep='dtool_have_freetype.dat') TargetAdd('libpanda.dll', opts=OPTS) + TargetAdd('core_module.obj', input='libp3downloader.in') + TargetAdd('core_module.obj', input='libp3express.in') + + TargetAdd('core_module.obj', input='libp3recorder.in') + TargetAdd('core_module.obj', input='libp3pgraphnodes.in') + TargetAdd('core_module.obj', input='libp3pgraph.in') + TargetAdd('core_module.obj', input='libp3cull.in') + TargetAdd('core_module.obj', input='libp3grutil.in') + TargetAdd('core_module.obj', input='libp3chan.in') + TargetAdd('core_module.obj', input='libp3pstatclient.in') + TargetAdd('core_module.obj', input='libp3char.in') + TargetAdd('core_module.obj', input='libp3collide.in') + TargetAdd('core_module.obj', input='libp3device.in') + TargetAdd('core_module.obj', input='libp3dgraph.in') + TargetAdd('core_module.obj', input='libp3display.in') + TargetAdd('core_module.obj', input='libp3pipeline.in') + TargetAdd('core_module.obj', input='libp3event.in') + TargetAdd('core_module.obj', input='libp3gobj.in') + TargetAdd('core_module.obj', input='libp3gsgbase.in') + TargetAdd('core_module.obj', input='libp3linmath.in') + TargetAdd('core_module.obj', input='libp3mathutil.in') + TargetAdd('core_module.obj', input='libp3parametrics.in') + TargetAdd('core_module.obj', input='libp3pnmimage.in') + TargetAdd('core_module.obj', input='libp3text.in') + TargetAdd('core_module.obj', input='libp3tform.in') + TargetAdd('core_module.obj', input='libp3putil.in') + TargetAdd('core_module.obj', input='libp3audio.in') + TargetAdd('core_module.obj', input='libp3nativenet.in') + TargetAdd('core_module.obj', input='libp3net.in') + TargetAdd('core_module.obj', input='libp3pgui.in') + TargetAdd('core_module.obj', input='libp3movies.in') + TargetAdd('core_module.obj', input='libp3dxml.in') + + if PkgSkip("FREETYPE")==0: + TargetAdd('core_module.obj', input='libp3pnmtext.in') + + TargetAdd('core_module.obj', opts=['IMOD:core', 'ILIB:core']) + + TargetAdd('core.pyd', input='core_module.obj') + TargetAdd('core.pyd', input=COMMON_PANDA_LIBS) + TargetAdd('core.pyd', opts=['PYTHON']) + # # DIRECTORY: panda/src/vision/ # -if (PkgSkip("VISION") ==0) and (not RUNTIME): +if (PkgSkip("VISION") == 0) and (not RUNTIME): OPTS=['DIR:panda/src/vision', 'BUILDING:VISION', 'ARTOOLKIT', 'OPENCV', 'DX9', 'DIRECTCAM', 'JPEG'] TargetAdd('p3vision_composite1.obj', opts=OPTS, input='p3vision_composite1.cxx') - IGATEFILES=GetDirectoryContents('panda/src/vision', ["*.h", "*_composite*.cxx"]) - TargetAdd('libp3vision.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3vision.in', opts=['IMOD:p3vision', 'ILIB:libp3vision', 'SRCDIR:panda/src/vision']) - TargetAdd('libp3vision_igate.obj', input='libp3vision.in', opts=["DEPENDENCYONLY"]) - - TargetAdd('libp3vision_module.obj', input='libp3vision.in') - TargetAdd('libp3vision_module.obj', opts=OPTS) - TargetAdd('libp3vision_module.obj', opts=['IMOD:p3vision', 'ILIB:libp3vision']) TargetAdd('libp3vision.dll', input='p3vision_composite1.obj') - TargetAdd('libp3vision.dll', input='libp3vision_igate.obj') - TargetAdd('libp3vision.dll', input='libp3vision_module.obj') TargetAdd('libp3vision.dll', input=COMMON_PANDA_LIBS) TargetAdd('libp3vision.dll', opts=OPTS) + OPTS=['DIR:panda/src/vision', 'ARTOOLKIT', 'OPENCV', 'DX9', 'DIRECTCAM', 'JPEG'] + IGATEFILES=GetDirectoryContents('panda/src/vision', ["*.h", "*_composite*.cxx"]) + TargetAdd('libp3vision.in', opts=OPTS, input=IGATEFILES) + TargetAdd('libp3vision.in', opts=['IMOD:vision', 'ILIB:libp3vision', 'SRCDIR:panda/src/vision']) + TargetAdd('libp3vision_igate.obj', input='libp3vision.in', opts=["DEPENDENCYONLY"]) + + TargetAdd('vision_module.obj', input='libp3vision.in') + TargetAdd('vision_module.obj', opts=OPTS) + TargetAdd('vision_module.obj', opts=['IMOD:vision', 'ILIB:vision']) + + TargetAdd('vision.pyd', input='vision_module.obj') + TargetAdd('vision.pyd', input='libp3vision_igate.obj') + TargetAdd('vision.pyd', input='libp3vision.dll') + TargetAdd('vision.pyd', input='core.pyd') + TargetAdd('vision.pyd', input=COMMON_PANDA_LIBS) + TargetAdd('vision.pyd', opts=['PYTHON']) + # # DIRECTORY: panda/src/rocket/ # -if (PkgSkip("ROCKET") ==0) and (not RUNTIME): +if (PkgSkip("ROCKET") == 0) and (not RUNTIME): OPTS=['DIR:panda/src/rocket', 'BUILDING:ROCKET', 'ROCKET'] TargetAdd('p3rocket_composite1.obj', opts=OPTS, input='p3rocket_composite1.cxx') + + TargetAdd('libp3rocket.dll', input='p3rocket_composite1.obj') + TargetAdd('libp3rocket.dll', input=COMMON_PANDA_LIBS) + TargetAdd('libp3rocket.dll', opts=OPTS) + + OPTS=['DIR:panda/src/rocket', 'ROCKET'] IGATEFILES=GetDirectoryContents('panda/src/rocket', ["rocketInputHandler.h", "rocketInputHandler.cxx", "rocketRegion.h", "rocketRegion.cxx", "rocketRegion_ext.h"]) TargetAdd('libp3rocket.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3rocket.in', opts=['IMOD:p3rocket', 'ILIB:libp3rocket', 'SRCDIR:panda/src/rocket']) + TargetAdd('libp3rocket.in', opts=['IMOD:rocket', 'ILIB:libp3rocket', 'SRCDIR:panda/src/rocket']) TargetAdd('libp3rocket_igate.obj', input='libp3rocket.in', opts=["DEPENDENCYONLY"]) - - TargetAdd('libp3rocket_module.obj', input='libp3rocket.in') - TargetAdd('libp3rocket_module.obj', opts=OPTS) - TargetAdd('libp3rocket_module.obj', opts=['IMOD:p3rocket', 'ILIB:libp3rocket']) - TargetAdd('p3rocket_rocketRegion_ext.obj', opts=OPTS, input='rocketRegion_ext.cxx') - TargetAdd('libp3rocket.dll', input='p3rocket_composite1.obj') - TargetAdd('libp3rocket.dll', input='libp3rocket_igate.obj') - TargetAdd('libp3rocket.dll', input='libp3rocket_module.obj') - TargetAdd('libp3rocket.dll', input='p3rocket_rocketRegion_ext.obj') - TargetAdd('libp3rocket.dll', input=COMMON_PANDA_LIBS) - TargetAdd('libp3rocket.dll', opts=OPTS) + TargetAdd('rocket_module.obj', input='libp3rocket.in') + TargetAdd('rocket_module.obj', opts=OPTS) + TargetAdd('rocket_module.obj', opts=['IMOD:rocket', 'ILIB:rocket']) + + TargetAdd('rocket.pyd', input='rocket_module.obj') + TargetAdd('rocket.pyd', input='libp3rocket_igate.obj') + TargetAdd('rocket.pyd', input='p3rocket_rocketRegion_ext.obj') + TargetAdd('rocket.pyd', input='libp3rocket.dll') + TargetAdd('rocket.pyd', input='core.pyd') + TargetAdd('rocket.pyd', input=COMMON_PANDA_LIBS) + TargetAdd('rocket.pyd', opts=['PYTHON', 'ROCKET']) # # DIRECTORY: panda/src/p3awesomium @@ -3586,21 +3663,27 @@ if (PkgSkip("ROCKET") ==0) and (not RUNTIME): if PkgSkip("AWESOMIUM") == 0 and not RUNTIME: OPTS=['DIR:panda/src/awesomium', 'BUILDING:PANDAAWESOMIUM', 'AWESOMIUM'] TargetAdd('pandaawesomium_composite1.obj', opts=OPTS, input='pandaawesomium_composite1.cxx') - IGATEFILES=GetDirectoryContents('panda/src/awesomium', ["*.h", "*_composite1.cxx"]) - TargetAdd('libp3awesomium.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3awesomium.in', opts=['IMOD:p3awesomium', 'ILIB:libp3awesomium', 'SRCDIR:panda/src/awesomium']) - TargetAdd('libp3awesomium_igate.obj', input='libp3awesomium.in', opts=["DEPENDENCYONLY"]) - - TargetAdd('libp3awesomium_module.obj', input='libp3awesomium.in') - TargetAdd('libp3awesomium_module.obj', opts=OPTS) - TargetAdd('libp3awesomium_module.obj', opts=['IMOD:p3awesomium', 'ILIB:libp3awesomium']) - TargetAdd('libp3awesomium.dll', input='pandaawesomium_composite1.obj') - TargetAdd('libp3awesomium.dll', input='libp3awesomium_igate.obj') - TargetAdd('libp3awesomium.dll', input='libp3awesomium_module.obj') TargetAdd('libp3awesomium.dll', input=COMMON_PANDA_LIBS) TargetAdd('libp3awesomium.dll', opts=OPTS) + OPTS=['DIR:panda/src/awesomium', 'AWESOMIUM'] + IGATEFILES=GetDirectoryContents('panda/src/awesomium', ["*.h", "*_composite1.cxx"]) + TargetAdd('libp3awesomium.in', opts=OPTS, input=IGATEFILES) + TargetAdd('libp3awesomium.in', opts=['IMOD:awesomium', 'ILIB:libp3awesomium', 'SRCDIR:panda/src/awesomium']) + TargetAdd('libp3awesomium_igate.obj', input='libp3awesomium.in', opts=["DEPENDENCYONLY"]) + + TargetAdd('awesomium_module.obj', input='libp3awesomium.in') + TargetAdd('awesomium_module.obj', opts=OPTS) + TargetAdd('awesomium_module.obj', opts=['IMOD:awesomium', 'ILIB:awesomium']) + + TargetAdd('awesomium.pyd', input='awesomium_module.obj') + TargetAdd('awesomium.pyd', input='libp3awesomium_igate.obj') + TargetAdd('awesomium.pyd', input='libp3awesomium.dll') + TargetAdd('awesomium.pyd', input='core.pyd') + TargetAdd('awesomium.pyd', input=COMMON_PANDA_LIBS) + TargetAdd('awesomium.pyd', opts=['PYTHON']) + # # DIRECTORY: panda/src/p3skel # @@ -3608,9 +3691,11 @@ if PkgSkip("AWESOMIUM") == 0 and not RUNTIME: if (PkgSkip('SKEL')==0) and (not RUNTIME): OPTS=['DIR:panda/src/skel', 'BUILDING:PANDASKEL', 'ADVAPI'] TargetAdd('p3skel_composite1.obj', opts=OPTS, input='p3skel_composite1.cxx') + + OPTS=['DIR:panda/src/skel', 'ADVAPI'] IGATEFILES=GetDirectoryContents("panda/src/skel", ["*.h", "*_composite*.cxx"]) TargetAdd('libp3skel.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3skel.in', opts=['IMOD:pandaskel', 'ILIB:libp3skel', 'SRCDIR:panda/src/skel']) + TargetAdd('libp3skel.in', opts=['IMOD:skel', 'ILIB:libp3skel', 'SRCDIR:panda/src/skel']) TargetAdd('libp3skel_igate.obj', input='libp3skel.in', opts=["DEPENDENCYONLY"]) # @@ -3619,17 +3704,20 @@ if (PkgSkip('SKEL')==0) and (not RUNTIME): if (PkgSkip('SKEL')==0) and (not RUNTIME): OPTS=['BUILDING:PANDASKEL', 'ADVAPI'] - - TargetAdd('libpandaskel_module.obj', input='libp3skel.in') - TargetAdd('libpandaskel_module.obj', opts=OPTS) - TargetAdd('libpandaskel_module.obj', opts=['IMOD:pandaskel', 'ILIB:libpandaskel']) - TargetAdd('libpandaskel.dll', input='p3skel_composite1.obj') - TargetAdd('libpandaskel.dll', input='libp3skel_igate.obj') - TargetAdd('libpandaskel.dll', input='libpandaskel_module.obj') TargetAdd('libpandaskel.dll', input=COMMON_PANDA_LIBS) TargetAdd('libpandaskel.dll', opts=OPTS) + TargetAdd('skel_module.obj', input='libp3skel.in') + TargetAdd('skel_module.obj', opts=['IMOD:skel', 'ILIB:skel']) + + TargetAdd('skel.pyd', input='skel_module.obj') + TargetAdd('skel.pyd', input='libp3skel_igate.obj') + TargetAdd('skel.pyd', input='libpandaskel.dll') + TargetAdd('skel.pyd', input='core.pyd') + TargetAdd('skel.pyd', input=COMMON_PANDA_LIBS) + TargetAdd('skel.pyd', opts=['PYTHON']) + # # DIRECTORY: panda/src/distort/ # @@ -3637,9 +3725,11 @@ if (PkgSkip('SKEL')==0) and (not RUNTIME): if (PkgSkip('PANDAFX')==0) and (not RUNTIME): OPTS=['DIR:panda/src/distort', 'BUILDING:PANDAFX'] TargetAdd('p3distort_composite1.obj', opts=OPTS, input='p3distort_composite1.cxx') + + OPTS=['DIR:panda/metalibs/pandafx', 'DIR:panda/src/distort', 'NVIDIACG'] IGATEFILES=GetDirectoryContents('panda/src/distort', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3distort.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3distort.in', opts=['IMOD:pandafx', 'ILIB:libp3distort', 'SRCDIR:panda/src/distort']) + TargetAdd('libp3distort.in', opts=['IMOD:fx', 'ILIB:libp3distort', 'SRCDIR:panda/src/distort']) TargetAdd('libp3distort_igate.obj', input='libp3distort.in', opts=["DEPENDENCYONLY"]) # @@ -3650,39 +3740,51 @@ if (PkgSkip('PANDAFX')==0) and (not RUNTIME): OPTS=['DIR:panda/metalibs/pandafx', 'DIR:panda/src/distort', 'BUILDING:PANDAFX', 'NVIDIACG'] TargetAdd('pandafx_pandafx.obj', opts=OPTS, input='pandafx.cxx') - TargetAdd('libpandafx_module.obj', input='libp3distort.in') - TargetAdd('libpandafx_module.obj', opts=OPTS) - TargetAdd('libpandafx_module.obj', opts=['IMOD:pandafx', 'ILIB:libpandafx']) - TargetAdd('libpandafx.dll', input='pandafx_pandafx.obj') - TargetAdd('libpandafx.dll', input='libpandafx_module.obj') TargetAdd('libpandafx.dll', input='p3distort_composite1.obj') - TargetAdd('libpandafx.dll', input='libp3distort_igate.obj') TargetAdd('libpandafx.dll', input=COMMON_PANDA_LIBS) TargetAdd('libpandafx.dll', opts=['ADVAPI', 'NVIDIACG']) + OPTS=['DIR:panda/metalibs/pandafx', 'DIR:panda/src/distort', 'NVIDIACG'] + TargetAdd('fx_module.obj', input='libp3distort.in') + TargetAdd('fx_module.obj', opts=OPTS) + TargetAdd('fx_module.obj', opts=['IMOD:fx', 'ILIB:fx']) + + TargetAdd('fx.pyd', input='fx_module.obj') + TargetAdd('fx.pyd', input='libp3distort_igate.obj') + TargetAdd('fx.pyd', input='libpandafx.dll') + TargetAdd('fx.pyd', input='core.pyd') + TargetAdd('fx.pyd', input=COMMON_PANDA_LIBS) + TargetAdd('fx.pyd', opts=['PYTHON']) + # # DIRECTORY: panda/src/vrpn/ # if (PkgSkip("VRPN")==0 and not RUNTIME): - OPTS=['DIR:panda/src/vrpn', 'BUILDING:VRPN', 'VRPN'] + OPTS=['DIR:panda/src/vrpn', 'BUILDING:VRPN', 'VRPN'] TargetAdd('p3vrpn_composite1.obj', opts=OPTS, input='p3vrpn_composite1.cxx') - IGATEFILES=GetDirectoryContents('panda/src/vrpn', ["*.h", "*_composite*.cxx"]) - TargetAdd('libp3vrpn.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3vrpn.in', opts=['IMOD:p3vrpn', 'ILIB:libp3vrpn', 'SRCDIR:panda/src/vrpn']) - TargetAdd('libp3vrpn_igate.obj', input='libp3vrpn.in', opts=["DEPENDENCYONLY"]) - - TargetAdd('libp3vrpn_module.obj', input='libp3vrpn.in') - TargetAdd('libp3vrpn_module.obj', opts=OPTS) - TargetAdd('libp3vrpn_module.obj', opts=['IMOD:p3vrpn', 'ILIB:libp3vrpn']) - - TargetAdd('libp3vrpn.dll', input='libp3vrpn_module.obj') TargetAdd('libp3vrpn.dll', input='p3vrpn_composite1.obj') - TargetAdd('libp3vrpn.dll', input='libp3vrpn_igate.obj') TargetAdd('libp3vrpn.dll', input=COMMON_PANDA_LIBS) TargetAdd('libp3vrpn.dll', opts=['VRPN']) + OPTS=['DIR:panda/src/vrpn', 'VRPN'] + IGATEFILES=GetDirectoryContents('panda/src/vrpn', ["*.h", "*_composite*.cxx"]) + TargetAdd('libp3vrpn.in', opts=OPTS, input=IGATEFILES) + TargetAdd('libp3vrpn.in', opts=['IMOD:vrpn', 'ILIB:libp3vrpn', 'SRCDIR:panda/src/vrpn']) + TargetAdd('libp3vrpn_igate.obj', input='libp3vrpn.in', opts=["DEPENDENCYONLY"]) + + TargetAdd('vrpn_module.obj', input='libp3vrpn.in') + TargetAdd('vrpn_module.obj', opts=OPTS) + TargetAdd('vrpn_module.obj', opts=['IMOD:vrpn', 'ILIB:vrpn']) + + TargetAdd('vrpn.pyd', input='vrpn_module.obj') + TargetAdd('vrpn.pyd', input='libp3vrpn_igate.obj') + TargetAdd('vrpn.pyd', input='libp3vrpn.dll') + TargetAdd('vrpn.pyd', input='core.pyd') + TargetAdd('vrpn.pyd', input=COMMON_PANDA_LIBS) + TargetAdd('vrpn.pyd', opts=['PYTHON']) + # # DIRECTORY: panda/src/ffmpeg # @@ -3833,18 +3935,21 @@ if PkgSkip("DX9")==0 and not RUNTIME: # if (not RUNTIME): - OPTS=['DIR:panda/src/egg', 'BUILDING:PANDAEGG', 'ZLIB', 'BISONPREFIX_eggyy', 'FLEXDASHI'] + OPTS=['DIR:panda/src/egg', 'BUILDING:PANDAEGG', 'ZLIB', 'BISONPREFIX_eggyy', 'FLEXDASHI'] CreateFile(GetOutputDir()+"/include/parser.h") TargetAdd('p3egg_parser.obj', opts=OPTS, input='parser.yxx') TargetAdd('parser.h', input='p3egg_parser.obj', opts=['DEPENDENCYONLY']) TargetAdd('p3egg_lexer.obj', opts=OPTS, input='lexer.lxx') TargetAdd('p3egg_composite1.obj', opts=OPTS, input='p3egg_composite1.cxx') TargetAdd('p3egg_composite2.obj', opts=OPTS, input='p3egg_composite2.cxx') + + OPTS=['DIR:panda/src/egg', 'ZLIB'] IGATEFILES=GetDirectoryContents('panda/src/egg', ["*.h", "*_composite*.cxx"]) if "parser.h" in IGATEFILES: IGATEFILES.remove("parser.h") TargetAdd('libp3egg.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3egg.in', opts=['IMOD:pandaegg', 'ILIB:libp3egg', 'SRCDIR:panda/src/egg']) + TargetAdd('libp3egg.in', opts=['IMOD:egg', 'ILIB:libp3egg', 'SRCDIR:panda/src/egg']) TargetAdd('libp3egg_igate.obj', input='libp3egg.in', opts=["DEPENDENCYONLY"]) + TargetAdd('p3egg_eggGroupNode_ext.obj', opts=OPTS, input='eggGroupNode_ext.cxx') # # DIRECTORY: panda/src/egg2pg/ @@ -3854,9 +3959,11 @@ if (not RUNTIME): OPTS=['DIR:panda/src/egg2pg', 'BUILDING:PANDAEGG'] TargetAdd('p3egg2pg_composite1.obj', opts=OPTS, input='p3egg2pg_composite1.cxx') TargetAdd('p3egg2pg_composite2.obj', opts=OPTS, input='p3egg2pg_composite2.cxx') + + OPTS=['DIR:panda/src/egg2pg'] IGATEFILES=['load_egg_file.h'] TargetAdd('libp3egg2pg.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3egg2pg.in', opts=['IMOD:pandaegg', 'ILIB:libp3egg2pg', 'SRCDIR:panda/src/egg2pg']) + TargetAdd('libp3egg2pg.in', opts=['IMOD:egg', 'ILIB:libp3egg2pg', 'SRCDIR:panda/src/egg2pg']) TargetAdd('libp3egg2pg_igate.obj', input='libp3egg2pg.in', opts=["DEPENDENCYONLY"]) # @@ -3905,24 +4012,31 @@ if (not RUNTIME): OPTS=['DIR:panda/metalibs/pandaegg', 'DIR:panda/src/egg', 'BUILDING:PANDAEGG'] TargetAdd('pandaegg_pandaegg.obj', opts=OPTS, input='pandaegg.cxx') - TargetAdd('libpandaegg_module.obj', input='libp3egg2pg.in') - TargetAdd('libpandaegg_module.obj', input='libp3egg.in') - TargetAdd('libpandaegg_module.obj', opts=OPTS) - TargetAdd('libpandaegg_module.obj', opts=['IMOD:pandaegg', 'ILIB:libpandaegg']) - TargetAdd('libpandaegg.dll', input='pandaegg_pandaegg.obj') - TargetAdd('libpandaegg.dll', input='libpandaegg_module.obj') TargetAdd('libpandaegg.dll', input='p3egg2pg_composite1.obj') TargetAdd('libpandaegg.dll', input='p3egg2pg_composite2.obj') - TargetAdd('libpandaegg.dll', input='libp3egg2pg_igate.obj') TargetAdd('libpandaegg.dll', input='p3egg_composite1.obj') TargetAdd('libpandaegg.dll', input='p3egg_composite2.obj') TargetAdd('libpandaegg.dll', input='p3egg_parser.obj') TargetAdd('libpandaegg.dll', input='p3egg_lexer.obj') - TargetAdd('libpandaegg.dll', input='libp3egg_igate.obj') TargetAdd('libpandaegg.dll', input=COMMON_PANDA_LIBS) TargetAdd('libpandaegg.dll', opts=['ADVAPI']) + OPTS=['DIR:panda/metalibs/pandaegg', 'DIR:panda/src/egg'] + TargetAdd('egg_module.obj', input='libp3egg2pg.in') + TargetAdd('egg_module.obj', input='libp3egg.in') + TargetAdd('egg_module.obj', opts=OPTS) + TargetAdd('egg_module.obj', opts=['IMOD:egg', 'ILIB:egg']) + + TargetAdd('egg.pyd', input='egg_module.obj') + TargetAdd('egg.pyd', input='p3egg_eggGroupNode_ext.obj') + TargetAdd('egg.pyd', input='libp3egg_igate.obj') + TargetAdd('egg.pyd', input='libp3egg2pg_igate.obj') + TargetAdd('egg.pyd', input='libpandaegg.dll') + TargetAdd('egg.pyd', input='core.pyd') + TargetAdd('egg.pyd', input=COMMON_PANDA_LIBS) + TargetAdd('egg.pyd', opts=['PYTHON']) + # # DIRECTORY: panda/src/mesadisplay/ # @@ -4065,13 +4179,16 @@ if (PkgSkip("ODE")==0 and not RUNTIME): TargetAdd('p3ode_composite1.obj', opts=OPTS, input='p3ode_composite1.cxx') TargetAdd('p3ode_composite2.obj', opts=OPTS, input='p3ode_composite2.cxx') TargetAdd('p3ode_composite3.obj', opts=OPTS, input='p3ode_composite3.cxx') + + OPTS=['DIR:panda/src/ode', 'ODE'] IGATEFILES=GetDirectoryContents('panda/src/ode', ["*.h", "*_composite*.cxx"]) IGATEFILES.remove("odeConvexGeom.h") IGATEFILES.remove("odeHeightFieldGeom.h") IGATEFILES.remove("odeHelperStructs.h") TargetAdd('libpandaode.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libpandaode.in', opts=['IMOD:pandaode', 'ILIB:libpandaode', 'SRCDIR:panda/src/ode']) + TargetAdd('libpandaode.in', opts=['IMOD:ode', 'ILIB:libpandaode', 'SRCDIR:panda/src/ode']) TargetAdd('libpandaode_igate.obj', input='libpandaode.in', opts=["DEPENDENCYONLY"]) + TargetAdd('p3ode_ext_composite.obj', opts=OPTS, input='p3ode_ext_composite.cxx') # # DIRECTORY: panda/metalibs/pandaode/ @@ -4080,28 +4197,37 @@ if (PkgSkip("ODE")==0 and not RUNTIME): OPTS=['DIR:panda/metalibs/pandaode', 'BUILDING:PANDAODE', 'ODE'] TargetAdd('pandaode_pandaode.obj', opts=OPTS, input='pandaode.cxx') - TargetAdd('libpandaode_module.obj', input='libpandaode.in') - TargetAdd('libpandaode_module.obj', opts=OPTS) - TargetAdd('libpandaode_module.obj', opts=['IMOD:pandaode', 'ILIB:libpandaode']) - TargetAdd('libpandaode.dll', input='pandaode_pandaode.obj') - TargetAdd('libpandaode.dll', input='libpandaode_module.obj') TargetAdd('libpandaode.dll', input='p3ode_composite1.obj') TargetAdd('libpandaode.dll', input='p3ode_composite2.obj') TargetAdd('libpandaode.dll', input='p3ode_composite3.obj') - TargetAdd('libpandaode.dll', input='libpandaode_igate.obj') TargetAdd('libpandaode.dll', input=COMMON_PANDA_LIBS) TargetAdd('libpandaode.dll', opts=['WINUSER', 'ODE']) + OPTS=['DIR:panda/metalibs/pandaode', 'ODE'] + TargetAdd('ode_module.obj', input='libpandaode.in') + TargetAdd('ode_module.obj', opts=OPTS) + TargetAdd('ode_module.obj', opts=['IMOD:ode', 'ILIB:ode']) + + TargetAdd('ode.pyd', input='ode_module.obj') + TargetAdd('ode.pyd', input='libpandaode_igate.obj') + TargetAdd('ode.pyd', input='p3ode_ext_composite.obj') + TargetAdd('ode.pyd', input='libpandaode.dll') + TargetAdd('ode.pyd', input='core.pyd') + TargetAdd('ode.pyd', input=COMMON_PANDA_LIBS) + TargetAdd('ode.pyd', opts=['PYTHON', 'WINUSER', 'ODE']) + # # DIRECTORY: panda/src/bullet/ # if (PkgSkip("BULLET")==0 and not RUNTIME): OPTS=['DIR:panda/src/bullet', 'BUILDING:PANDABULLET', 'BULLET'] TargetAdd('p3bullet_composite.obj', opts=OPTS, input='p3bullet_composite.cxx') + + OPTS=['DIR:panda/src/bullet', 'BULLET'] IGATEFILES=GetDirectoryContents('panda/src/bullet', ["*.h", "*_composite*.cxx"]) TargetAdd('libpandabullet.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libpandabullet.in', opts=['IMOD:pandabullet', 'ILIB:libpandabullet', 'SRCDIR:panda/src/bullet']) + TargetAdd('libpandabullet.in', opts=['IMOD:bullet', 'ILIB:libpandabullet', 'SRCDIR:panda/src/bullet']) TargetAdd('libpandabullet_igate.obj', input='libpandabullet.in', opts=["DEPENDENCYONLY"]) # @@ -4111,17 +4237,23 @@ if (PkgSkip("BULLET")==0 and not RUNTIME): OPTS=['DIR:panda/metalibs/pandabullet', 'BUILDING:PANDABULLET', 'BULLET'] TargetAdd('pandabullet_pandabullet.obj', opts=OPTS, input='pandabullet.cxx') - TargetAdd('libpandabullet_module.obj', input='libpandabullet.in') - TargetAdd('libpandabullet_module.obj', opts=OPTS) - TargetAdd('libpandabullet_module.obj', opts=['IMOD:pandabullet', 'ILIB:libpandabullet']) - TargetAdd('libpandabullet.dll', input='pandabullet_pandabullet.obj') - TargetAdd('libpandabullet.dll', input='libpandabullet_module.obj') TargetAdd('libpandabullet.dll', input='p3bullet_composite.obj') - TargetAdd('libpandabullet.dll', input='libpandabullet_igate.obj') TargetAdd('libpandabullet.dll', input=COMMON_PANDA_LIBS) TargetAdd('libpandabullet.dll', opts=['WINUSER', 'BULLET']) + OPTS=['DIR:panda/metalibs/pandabullet', 'BULLET'] + TargetAdd('bullet_module.obj', input='libpandabullet.in') + TargetAdd('bullet_module.obj', opts=OPTS) + TargetAdd('bullet_module.obj', opts=['IMOD:bullet', 'ILIB:bullet']) + + TargetAdd('bullet.pyd', input='bullet_module.obj') + TargetAdd('bullet.pyd', input='libpandabullet_igate.obj') + TargetAdd('bullet.pyd', input='libpandabullet.dll') + TargetAdd('bullet.pyd', input='core.pyd') + TargetAdd('bullet.pyd', input=COMMON_PANDA_LIBS) + TargetAdd('bullet.pyd', opts=['PYTHON', 'WINUSER', 'BULLET']) + # # DIRECTORY: panda/src/physx/ # @@ -4129,9 +4261,11 @@ if (PkgSkip("BULLET")==0 and not RUNTIME): if (PkgSkip("PHYSX")==0): OPTS=['DIR:panda/src/physx', 'BUILDING:PANDAPHYSX', 'PHYSX', 'NOPPC'] TargetAdd('p3physx_composite.obj', opts=OPTS, input='p3physx_composite.cxx') + + OPTS=['DIR:panda/src/physx', 'PHYSX', 'NOPPC'] IGATEFILES=GetDirectoryContents('panda/src/physx', ["*.h", "*_composite*.cxx"]) TargetAdd('libpandaphysx.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libpandaphysx.in', opts=['IMOD:pandaphysx', 'ILIB:libpandaphysx', 'SRCDIR:panda/src/physx']) + TargetAdd('libpandaphysx.in', opts=['IMOD:physx', 'ILIB:libpandaphysx', 'SRCDIR:panda/src/physx']) TargetAdd('libpandaphysx_igate.obj', input='libpandaphysx.in', opts=["DEPENDENCYONLY"]) # @@ -4142,17 +4276,23 @@ if (PkgSkip("PHYSX")==0): OPTS=['DIR:panda/metalibs/pandaphysx', 'BUILDING:PANDAPHYSX', 'PHYSX', 'NOPPC'] TargetAdd('pandaphysx_pandaphysx.obj', opts=OPTS, input='pandaphysx.cxx') - TargetAdd('libpandaphysx_module.obj', input='libpandaphysx.in') - TargetAdd('libpandaphysx_module.obj', opts=OPTS) - TargetAdd('libpandaphysx_module.obj', opts=['IMOD:pandaphysx', 'ILIB:libpandaphysx']) - TargetAdd('libpandaphysx.dll', input='pandaphysx_pandaphysx.obj') - TargetAdd('libpandaphysx.dll', input='libpandaphysx_module.obj') TargetAdd('libpandaphysx.dll', input='p3physx_composite.obj') - TargetAdd('libpandaphysx.dll', input='libpandaphysx_igate.obj') TargetAdd('libpandaphysx.dll', input=COMMON_PANDA_LIBS) TargetAdd('libpandaphysx.dll', opts=['WINUSER', 'PHYSX', 'NOPPC']) + OPTS=['DIR:panda/metalibs/pandaphysx', 'PHYSX', 'NOPPC'] + TargetAdd('physx_module.obj', input='libpandaphysx.in') + TargetAdd('physx_module.obj', opts=OPTS) + TargetAdd('physx_module.obj', opts=['IMOD:physx', 'ILIB:physx']) + + TargetAdd('physx.pyd', input='physx_module.obj') + TargetAdd('physx.pyd', input='libpandaphysx_igate.obj') + TargetAdd('physx.pyd', input='libpandaphysx.dll') + TargetAdd('physx.pyd', input='core.pyd') + TargetAdd('physx.pyd', input=COMMON_PANDA_LIBS) + TargetAdd('physx.pyd', opts=['PYTHON', 'WINUSER', 'PHYSX', 'NOPPC']) + # # DIRECTORY: panda/src/physics/ # @@ -4161,10 +4301,12 @@ if (PkgSkip("PANDAPHYSICS")==0) and (not RUNTIME): OPTS=['DIR:panda/src/physics', 'BUILDING:PANDAPHYSICS'] TargetAdd('p3physics_composite1.obj', opts=OPTS, input='p3physics_composite1.cxx') TargetAdd('p3physics_composite2.obj', opts=OPTS, input='p3physics_composite2.cxx') + + OPTS=['DIR:panda/src/physics'] IGATEFILES=GetDirectoryContents('panda/src/physics', ["*.h", "*_composite*.cxx"]) IGATEFILES.remove("forces.h") TargetAdd('libp3physics.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3physics.in', opts=['IMOD:pandaphysics', 'ILIB:libp3physics', 'SRCDIR:panda/src/physics']) + TargetAdd('libp3physics.in', opts=['IMOD:physics', 'ILIB:libp3physics', 'SRCDIR:panda/src/physics']) TargetAdd('libp3physics_igate.obj', input='libp3physics.in', opts=["DEPENDENCYONLY"]) # @@ -4175,6 +4317,8 @@ if (PkgSkip("PANDAPHYSICS")==0) and (PkgSkip("PANDAPARTICLESYSTEM")==0) and (not OPTS=['DIR:panda/src/particlesystem', 'BUILDING:PANDAPHYSICS'] TargetAdd('p3particlesystem_composite1.obj', opts=OPTS, input='p3particlesystem_composite1.cxx') TargetAdd('p3particlesystem_composite2.obj', opts=OPTS, input='p3particlesystem_composite2.cxx') + + OPTS=['DIR:panda/src/particlesystem'] IGATEFILES=GetDirectoryContents('panda/src/particlesystem', ["*.h", "*_composite*.cxx"]) IGATEFILES.remove('orientedParticle.h') IGATEFILES.remove('orientedParticleFactory.h') @@ -4182,7 +4326,8 @@ if (PkgSkip("PANDAPHYSICS")==0) and (PkgSkip("PANDAPARTICLESYSTEM")==0) and (not IGATEFILES.remove('emitters.h') IGATEFILES.remove('particles.h') TargetAdd('libp3particlesystem.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3particlesystem.in', opts=['IMOD:pandaphysics', 'ILIB:libp3particlesystem', 'SRCDIR:panda/src/particlesystem']) + TargetAdd('libp3particlesystem.in', opts=['IMOD:physics', 'ILIB:libp3particlesystem', 'SRCDIR:panda/src/particlesystem']) + TargetAdd('libp3particlesystem_igate.obj', input='libp3particlesystem.in', opts=["DEPENDENCYONLY"]) # # DIRECTORY: panda/metalibs/pandaphysics/ @@ -4192,23 +4337,30 @@ if (PkgSkip("PANDAPHYSICS")==0) and (not RUNTIME): OPTS=['DIR:panda/metalibs/pandaphysics', 'BUILDING:PANDAPHYSICS'] TargetAdd('pandaphysics_pandaphysics.obj', opts=OPTS, input='pandaphysics.cxx') - TargetAdd('libpandaphysics_module.obj', input='libp3physics.in') - if (PkgSkip("PANDAPARTICLESYSTEM")==0): - TargetAdd('libpandaphysics_module.obj', input='libp3particlesystem.in') - TargetAdd('libpandaphysics_module.obj', opts=OPTS) - TargetAdd('libpandaphysics_module.obj', opts=['IMOD:pandaphysics', 'ILIB:libpandaphysics']) - TargetAdd('libpandaphysics.dll', input='pandaphysics_pandaphysics.obj') - TargetAdd('libpandaphysics.dll', input='libpandaphysics_module.obj') TargetAdd('libpandaphysics.dll', input='p3physics_composite1.obj') TargetAdd('libpandaphysics.dll', input='p3physics_composite2.obj') - TargetAdd('libpandaphysics.dll', input='libp3physics_igate.obj') TargetAdd('libpandaphysics.dll', input='p3particlesystem_composite1.obj') TargetAdd('libpandaphysics.dll', input='p3particlesystem_composite2.obj') - TargetAdd('libpandaphysics.dll', input='libp3particlesystem_igate.obj') TargetAdd('libpandaphysics.dll', input=COMMON_PANDA_LIBS) TargetAdd('libpandaphysics.dll', opts=['ADVAPI']) + OPTS=['DIR:panda/metalibs/pandaphysics'] + TargetAdd('physics_module.obj', input='libp3physics.in') + if (PkgSkip("PANDAPARTICLESYSTEM")==0): + TargetAdd('physics_module.obj', input='libp3particlesystem.in') + TargetAdd('physics_module.obj', opts=OPTS) + TargetAdd('physics_module.obj', opts=['IMOD:physics', 'ILIB:physics']) + + TargetAdd('physics.pyd', input='physics_module.obj') + TargetAdd('physics.pyd', input='libp3physics_igate.obj') + if (PkgSkip("PANDAPARTICLESYSTEM")==0): + TargetAdd('physics.pyd', input='libp3particlesystem_igate.obj') + TargetAdd('physics.pyd', input='libpandaphysics.dll') + TargetAdd('physics.pyd', input='core.pyd') + TargetAdd('physics.pyd', input=COMMON_PANDA_LIBS) + TargetAdd('physics.pyd', opts=['PYTHON']) + # # DIRECTORY: panda/src/speedtree/ # @@ -4358,7 +4510,7 @@ if (PkgSkip("DIRECT")==0): if "dcParser.h" in IGATEFILES: IGATEFILES.remove("dcParser.h") if "dcmsgtypes.h" in IGATEFILES: IGATEFILES.remove('dcmsgtypes.h') TargetAdd('libp3dcparser.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3dcparser.in', opts=['IMOD:p3direct', 'ILIB:libp3dcparser', 'SRCDIR:direct/src/dcparser']) + TargetAdd('libp3dcparser.in', opts=['IMOD:direct', 'ILIB:libp3dcparser', 'SRCDIR:direct/src/dcparser']) TargetAdd('libp3dcparser_igate.obj', input='libp3dcparser.in', opts=["DEPENDENCYONLY"]) # @@ -4370,7 +4522,7 @@ if (PkgSkip("DIRECT")==0): TargetAdd('p3deadrec_composite1.obj', opts=OPTS, input='p3deadrec_composite1.cxx') IGATEFILES=GetDirectoryContents('direct/src/deadrec', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3deadrec.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3deadrec.in', opts=['IMOD:p3direct', 'ILIB:libp3deadrec', 'SRCDIR:direct/src/deadrec']) + TargetAdd('libp3deadrec.in', opts=['IMOD:direct', 'ILIB:libp3deadrec', 'SRCDIR:direct/src/deadrec']) TargetAdd('libp3deadrec_igate.obj', input='libp3deadrec.in', opts=["DEPENDENCYONLY"]) # @@ -4384,7 +4536,7 @@ if (PkgSkip("DIRECT")==0): TargetAdd('p3distributed_cDistributedSmoothNodeBase.obj', opts=OPTS, input='cDistributedSmoothNodeBase.cxx') IGATEFILES=GetDirectoryContents('direct/src/distributed', ["*.h", "*.cxx"]) TargetAdd('libp3distributed.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3distributed.in', opts=['IMOD:p3direct', 'ILIB:libp3distributed', 'SRCDIR:direct/src/distributed']) + TargetAdd('libp3distributed.in', opts=['IMOD:direct', 'ILIB:libp3distributed', 'SRCDIR:direct/src/distributed']) TargetAdd('libp3distributed_igate.obj', input='libp3distributed.in', opts=["DEPENDENCYONLY"]) # @@ -4396,7 +4548,7 @@ if (PkgSkip("DIRECT")==0): TargetAdd('p3interval_composite1.obj', opts=OPTS, input='p3interval_composite1.cxx') IGATEFILES=GetDirectoryContents('direct/src/interval', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3interval.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3interval.in', opts=['IMOD:p3direct', 'ILIB:libp3interval', 'SRCDIR:direct/src/interval']) + TargetAdd('libp3interval.in', opts=['IMOD:direct', 'ILIB:libp3interval', 'SRCDIR:direct/src/interval']) TargetAdd('libp3interval_igate.obj', input='libp3interval.in', opts=["DEPENDENCYONLY"]) # @@ -4410,7 +4562,7 @@ if (PkgSkip("DIRECT")==0): TargetAdd('p3showbase_showBase_assist.obj', opts=OPTS, input='showBase_assist.mm') IGATEFILES=GetDirectoryContents('direct/src/showbase', ["*.h", "showBase.cxx"]) TargetAdd('libp3showbase.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3showbase.in', opts=['IMOD:p3direct', 'ILIB:libp3showbase', 'SRCDIR:direct/src/showbase']) + TargetAdd('libp3showbase.in', opts=['IMOD:direct', 'ILIB:libp3showbase', 'SRCDIR:direct/src/showbase']) TargetAdd('libp3showbase_igate.obj', input='libp3showbase.in', opts=["DEPENDENCYONLY"]) # @@ -4421,16 +4573,7 @@ if (PkgSkip("DIRECT")==0): OPTS=['DIR:direct/metalibs/direct', 'BUILDING:DIRECT'] TargetAdd('p3direct_direct.obj', opts=OPTS, input='direct.cxx') - TargetAdd('libp3direct_module.obj', input='libp3dcparser.in') - TargetAdd('libp3direct_module.obj', input='libp3showbase.in') - TargetAdd('libp3direct_module.obj', input='libp3deadrec.in') - TargetAdd('libp3direct_module.obj', input='libp3interval.in') - TargetAdd('libp3direct_module.obj', input='libp3distributed.in') - TargetAdd('libp3direct_module.obj', opts=OPTS) - TargetAdd('libp3direct_module.obj', opts=['IMOD:p3direct', 'ILIB:libp3direct']) - TargetAdd('libp3direct.dll', input='p3direct_direct.obj') - TargetAdd('libp3direct.dll', input='libp3direct_module.obj') TargetAdd('libp3direct.dll', input='p3directbase_directbase.obj') TargetAdd('libp3direct.dll', input='p3dcparser_composite1.obj') TargetAdd('libp3direct.dll', input='p3dcparser_composite2.obj') @@ -4452,6 +4595,21 @@ if (PkgSkip("DIRECT")==0): TargetAdd('libp3direct.dll', input=COMMON_PANDA_LIBS) TargetAdd('libp3direct.dll', opts=['ADVAPI', 'OPENSSL', 'WINUSER', 'WINGDI']) + OPTS=['DIR:direct/metalibs/direct'] + TargetAdd('direct_module.obj', input='libp3dcparser.in') + TargetAdd('direct_module.obj', input='libp3showbase.in') + TargetAdd('direct_module.obj', input='libp3deadrec.in') + TargetAdd('direct_module.obj', input='libp3interval.in') + TargetAdd('direct_module.obj', input='libp3distributed.in') + TargetAdd('direct_module.obj', opts=OPTS) + TargetAdd('direct_module.obj', opts=['IMOD:direct', 'ILIB:direct']) + + TargetAdd('direct.pyd', input='direct_module.obj') + TargetAdd('direct.pyd', input='libp3direct.dll') + TargetAdd('direct.pyd', input='core.pyd') + TargetAdd('direct.pyd', input=COMMON_PANDA_LIBS) + TargetAdd('direct.pyd', opts=['PYTHON', 'OPENSSL', 'WINUSER', 'WINGDI']) + # # DIRECTORY: direct/src/dcparse/ # @@ -5626,19 +5784,25 @@ for VER in MAYAVERSIONS: if (PkgSkip("CONTRIB")==0 and not RUNTIME): OPTS=['DIR:contrib/src/ai', 'BUILDING:PANDAAI'] TargetAdd('p3ai_composite1.obj', opts=OPTS, input='p3ai_composite1.cxx') + TargetAdd('libpandaai.dll', input='p3ai_composite1.obj') + TargetAdd('libpandaai.dll', input=COMMON_PANDA_LIBS) + + OPTS=['DIR:contrib/src/ai'] IGATEFILES=GetDirectoryContents('contrib/src/ai', ["*.h", "*_composite*.cxx"]) TargetAdd('libpandaai.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libpandaai.in', opts=['IMOD:pandaai', 'ILIB:libpandaai', 'SRCDIR:contrib/src/ai']) + TargetAdd('libpandaai.in', opts=['IMOD:ai', 'ILIB:libpandaai', 'SRCDIR:contrib/src/ai']) TargetAdd('libpandaai_igate.obj', input='libpandaai.in', opts=["DEPENDENCYONLY"]) - TargetAdd('libpandaai_module.obj', input='libpandaai.in') - TargetAdd('libpandaai_module.obj', opts=OPTS) - TargetAdd('libpandaai_module.obj', opts=['IMOD:pandaai', 'ILIB:libpandaai']) + TargetAdd('ai_module.obj', input='libpandaai.in') + TargetAdd('ai_module.obj', opts=OPTS) + TargetAdd('ai_module.obj', opts=['IMOD:ai', 'ILIB:ai']) - TargetAdd('libpandaai.dll', input='libpandaai_module.obj') - TargetAdd('libpandaai.dll', input='p3ai_composite1.obj') - TargetAdd('libpandaai.dll', input='libpandaai_igate.obj') - TargetAdd('libpandaai.dll', input=COMMON_PANDA_LIBS) + TargetAdd('ai.pyd', input='ai_module.obj') + TargetAdd('ai.pyd', input='libpandaai_igate.obj') + TargetAdd('ai.pyd', input='libpandaai.dll') + TargetAdd('ai.pyd', input='core.pyd') + TargetAdd('ai.pyd', input=COMMON_PANDA_LIBS) + TargetAdd('ai.pyd', opts=['PYTHON']) # # Run genpycode @@ -5650,25 +5814,24 @@ if (PkgSkip("PYTHON")==0 and not RUNTIME): # split them out of libpanda and need to maintain backward # compatibility with old imports. See direct/src/ffi/panda3d.py - TargetAdd('PandaModules.py', input='libpandaexpress.dll') - TargetAdd('PandaModules.py', input='libpanda.dll') + TargetAdd('PandaModules.py', input='core.pyd') if (PkgSkip("PANDAPHYSICS")==0): - TargetAdd('PandaModules.py', input='libpandaphysics.dll') + TargetAdd('PandaModules.py', input='physics.pyd') if (PkgSkip('PANDAFX')==0): - TargetAdd('PandaModules.py', input='libpandafx.dll') + TargetAdd('PandaModules.py', input='fx.pyd') if (PkgSkip("DIRECT")==0): - TargetAdd('PandaModules.py', input='libp3direct.dll') + TargetAdd('PandaModules.py', input='direct.pyd') if (PkgSkip("VISION")==0): - TargetAdd('PandaModules.py', input='libp3vision.dll') + TargetAdd('PandaModules.py', input='vision.pyd') if (PkgSkip("SKEL")==0): - TargetAdd('PandaModules.py', input='libpandaskel.dll') - TargetAdd('PandaModules.py', input='libpandaegg.dll') + TargetAdd('PandaModules.py', input='skel.pyd') + TargetAdd('PandaModules.py', input='egg.pyd') if (PkgSkip("AWESOMIUM")==0): - TargetAdd('PandaModules.py', input='libp3awesomium.dll') + TargetAdd('PandaModules.py', input='awesomium.pyd') if (PkgSkip("ODE")==0): - TargetAdd('PandaModules.py', input='libpandaode.dll') + TargetAdd('PandaModules.py', input='ode.pyd') if (PkgSkip("VRPN")==0): - TargetAdd('PandaModules.py', input='libp3vrpn.dll') + TargetAdd('PandaModules.py', input='vrpn.pyd') # # Generate the models directory and samples directory @@ -5762,8 +5925,12 @@ for target in TARGET_LIST: DEPENDENCYQUEUE.append([CompileAnything, [name, inputs, opts], [name], deps, []]) def BuildWorker(taskqueue, donequeue): - while (1): - task = taskqueue.get() + while True: + try: + task = taskqueue.get(timeout=1) + except: + ProgressOutput(None, "Waiting for tasks...") + task = taskqueue.get() sys.stdout.flush() if (task == 0): return try: @@ -6065,41 +6232,6 @@ Info_plist = """ """ -MAC_POSTINSTALL = """#!/usr/bin/python -import os, sys, plistlib -home = os.environ['HOME'] -if not os.path.isdir(os.path.join(home, '.MacOSX')): - sys.exit() -plist = dict() -envfile = os.path.join(home, '.MacOSX', 'environment.plist') -if os.path.exists(envfile): - try: - plist = plistlib.readPlist(envfile) - except: sys.exit(0) -else: - sys.exit(0) -paths = {'PATH' : '/Developer/Tools/Panda3D', 'DYLD_LIBRARY_PATH' : '/Developer/Panda3D/lib', 'PYTHONPATH' : '/Developer/Panda3D/lib', - 'MAYA_SCRIPT_PATH' : '/Developer/Panda3D/plugins', 'MAYA_PLUG_IN_PATH' : '/Developer/Panda3D/plugins'} -for env, path in dict(paths).items(): - if env in plist: - paths = plist[env].split(':') - if '' in paths: paths.remove('') - if path in paths: paths.remove(path) - if len(paths) == 0: - del plist[env] - else: - plist[env] = ':'.join(paths) -if len(plist) == 0: - os.remove(envfile) -else: - plistlib.writePlist(plist, envfile) -""" - -MAC_POSTFLIGHT = """#!/usr/bin/env bash" -RESULT=`/usr/bin/open 'http://www.panda3d.org/wiki/index.php/Getting_Started_on_OSX'`" -exit 0 -""" - # FreeBSD pkg-descr INSTALLER_PKG_DESCR_FILE = """ Panda3D is a game engine which includes graphics, audio, I/O, collision detection, and other abilities relevant to the creation of 3D games. Panda3D is open source and free software under the revised BSD license, and can be used for both free and commercial game development at no financial cost. @@ -6203,7 +6335,12 @@ def MakeInstallerOSX(): if (RUNTIME): # Invoke the make_installer script. AddToPathEnv("DYLD_LIBRARY_PATH", GetOutputDir() + "/plugins") - oscmd(sys.executable + " -B direct/src/plugin_installer/make_installer.py --version %s" % VERSION) + cmdstr = sys.executable + " " + if sys.version_info >= (2, 6): + cmdstr += "-B " + + cmdstr += "direct/src/plugin_installer/make_installer.py --version %s" % VERSION + oscmd(cmdstr) return import compileall @@ -6211,10 +6348,8 @@ def MakeInstallerOSX(): if (os.path.exists("dstroot")): oscmd("rm -rf dstroot") if (os.path.exists("Panda3D-rw.dmg")): oscmd('rm -f Panda3D-rw.dmg') - #TODO: add postflight script - #oscmd("sed -e 's@\\$1@%s@' < direct/src/directscripts/profilepaths-osx.command >> Panda3D-tpl-rw/panda3dpaths.command" % VERSION) - oscmd("mkdir -p dstroot/base/Developer/Panda3D/lib") + oscmd("mkdir -p dstroot/base/Developer/Panda3D/panda3d") oscmd("mkdir -p dstroot/base/Developer/Panda3D/etc") oscmd("cp %s/etc/Config.prc dstroot/base/Developer/Panda3D/etc/Config.prc" % GetOutputDir()) oscmd("cp %s/etc/Confauto.prc dstroot/base/Developer/Panda3D/etc/Confauto.prc" % GetOutputDir()) @@ -6227,35 +6362,27 @@ def MakeInstallerOSX(): install_libs = [] for base in os.listdir(GetOutputDir()+"/lib"): if (not base.endswith(".a")): - install_libs.append(base) + install_libs.append("lib/"+base) + for base in os.listdir(GetOutputDir()+"/panda3d"): + if (not base.endswith(".a")): + install_libs.append("panda3d/"+base) for base in install_libs: - libname = "dstroot/base/Developer/Panda3D/lib/" + base + libname = "dstroot/base/Developer/Panda3D/" + base # We really need to specify -R in order not to follow symlinks # On OSX, just specifying -P is not enough to do that. - oscmd("cp -R -P " + GetOutputDir() + "/lib/" + base + " " + libname) + oscmd("cp -R -P " + GetOutputDir() + "/" + base + " " + libname) # Execute install_name_tool to make them reference an absolute path if (libname.endswith(".dylib") or libname.endswith(".so")) and not os.path.islink(libname): - oscmd("install_name_tool -id /Developer/Panda3D/lib/%s %s" % (base, libname), True) + oscmd("install_name_tool -id /Developer/Panda3D/%s %s" % (base, libname), True) oscmd("otool -L %s | grep .dylib > %s/tmp/otool-libs.txt" % (libname, GetOutputDir()), True) for line in open(GetOutputDir()+"/tmp/otool-libs.txt", "r"): if len(line.strip()) > 0 and not line.strip().endswith(":"): libdep = line.strip().split(" ", 1)[0] - if os.path.basename(libdep) in install_libs: + if 'lib/' + os.path.basename(libdep) in install_libs: oscmd("install_name_tool -change %s /Developer/Panda3D/lib/%s %s" % (libdep, os.path.basename(libdep), libname), True) - # Temporary script that should clean up the poison that the early 1.7.0 builds injected into environment.plist - oscmd("mkdir -p dstroot/scripts/base/") - postinstall = open("dstroot/scripts/base/postinstall", "w") - postinstall.write(MAC_POSTINSTALL) - postinstall.close() - postflight = open("dstroot/scripts/base/postflight", "w") - postflight.write(MAC_POSTFLIGHT) - postflight.close() - oscmd("chmod +x dstroot/scripts/base/postinstall") - oscmd("chmod +x dstroot/scripts/base/postflight") - oscmd("mkdir -p dstroot/tools/Developer/Tools/Panda3D") oscmd("mkdir -p dstroot/tools/Developer/Panda3D") oscmd("mkdir -p dstroot/tools/etc/paths.d") @@ -6273,26 +6400,25 @@ def MakeInstallerOSX(): for line in open(GetOutputDir()+"/tmp/otool-libs.txt", "r"): if len(line.strip()) > 0 and not line.strip().endswith(":"): libdep = line.strip().split(" ", 1)[0] - if os.path.basename(libdep) in install_libs: + if 'lib/' + os.path.basename(libdep) in install_libs: oscmd("install_name_tool -change %s /Developer/Panda3D/lib/%s %s" % (libdep, os.path.basename(libdep), binname), True) if PkgSkip("PYTHON")==0: PV = SDK["PYTHONVERSION"].replace("python", "") oscmd("mkdir -p dstroot/pythoncode/usr/bin") - oscmd("mkdir -p dstroot/pythoncode/Developer/Panda3D/lib/direct") + oscmd("mkdir -p dstroot/pythoncode/Developer/Panda3D/direct") oscmd("mkdir -p dstroot/pythoncode/Library/Python/%s/site-packages" % PV) - WriteFile("dstroot/pythoncode/Library/Python/%s/site-packages/Panda3D.pth" % PV, "/Developer/Panda3D/lib") - oscmd("cp -R %s/pandac dstroot/pythoncode/Developer/Panda3D/lib/pandac" % GetOutputDir()) - oscmd("cp -R direct/src/* dstroot/pythoncode/Developer/Panda3D/lib/direct") - oscmd("cp direct/src/ffi/panda3d.py dstroot/pythoncode/Developer/Panda3D/lib/panda3d.py") + WriteFile("dstroot/pythoncode/Library/Python/%s/site-packages/Panda3D.pth" % PV, "/Developer/Panda3D") + oscmd("cp -R %s/pandac dstroot/pythoncode/Developer/Panda3D/pandac" % GetOutputDir()) + oscmd("cp -R direct/src/* dstroot/pythoncode/Developer/Panda3D/direct") oscmd("ln -s %s dstroot/pythoncode/usr/bin/ppython" % SDK["PYTHONEXEC"]) if os.path.isdir(GetOutputDir()+"/Pmw"): - oscmd("cp -R %s/Pmw dstroot/pythoncode/Developer/Panda3D/lib/Pmw" % GetOutputDir()) - compileall.compile_dir("dstroot/pythoncode/Developer/Panda3D/lib/Pmw") - WriteFile("dstroot/pythoncode/Developer/Panda3D/lib/direct/__init__.py", "") - for base in os.listdir("dstroot/pythoncode/Developer/Panda3D/lib/direct"): + oscmd("cp -R %s/Pmw dstroot/pythoncode/Developer/Panda3D/Pmw" % GetOutputDir()) + compileall.compile_dir("dstroot/pythoncode/Developer/Panda3D/Pmw") + WriteFile("dstroot/pythoncode/Developer/Panda3D/direct/__init__.py", "") + for base in os.listdir("dstroot/pythoncode/Developer/Panda3D/direct"): if ((base != "extensions") and (base != "extensions_native")): - compileall.compile_dir("dstroot/pythoncode/Developer/Panda3D/lib/direct/"+base) + compileall.compile_dir("dstroot/pythoncode/Developer/Panda3D/direct/"+base) oscmd("mkdir -p dstroot/headers/Developer/Panda3D") oscmd("cp -R %s/include dstroot/headers/Developer/Panda3D/include" % GetOutputDir()) @@ -6301,31 +6427,6 @@ def MakeInstallerOSX(): oscmd("mkdir -p dstroot/samples/Developer/Examples/Panda3D") oscmd("cp -R samples/* dstroot/samples/Developer/Examples/Panda3D/") - # Dummy package uninstall16 which just contains a preflight script to remove /Applications/Panda3D/ . - oscmd("mkdir -p dstroot/scripts/uninstall16/") - preflight = open("dstroot/scripts/uninstall16/preflight", "w") - preflight.write( - "#!/usr/bin/python\n" - "import os, re, sys, shutil\n" - "if os.path.isdir('/Applications/Panda3D'): shutil.rmtree('/Applications/Panda3D')\n" - "bash_profile = os.path.join(os.environ['HOME'], '.bash_profile')\n" - "if not os.path.isfile(bash_profile): sys.exit(0)\n" - "pattern = re.compile('''PANDA_VERSION=[0-9][.][0-9][.][0-9]\n" - "PANDA_PATH=/Applications/Panda3D/[$A-Z.0-9_]+\n" - "if \[ -d \$PANDA_PATH \]\n" - "then(.+?)fi\n" - "''', flags = re.DOTALL | re.MULTILINE)\n" - "bpfile = open(bash_profile, 'r')\n" - "bpdata = bpfile.read()\n" - "bpfile.close()\n" - "newbpdata = pattern.sub('', bpdata)\n" - "if newbpdata == bpdata: sys.exit(0)\n" - "bpfile = open(bash_profile, 'w')\n" - "bpfile.write(newbpdata)\n" - "bpfile.close()\n") - preflight.close() - oscmd("chmod +x dstroot/scripts/uninstall16/preflight") - oscmd("chmod -R 0775 dstroot/*") DeleteCVS("dstroot") DeleteBuildFiles("dstroot") @@ -6336,7 +6437,7 @@ def MakeInstallerOSX(): oscmd("mkdir -p dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/") oscmd("mkdir -p dstroot/Panda3D/Panda3D.mpkg/Contents/Resources/en.lproj/") - pkgs = ["base", "tools", "headers", "uninstall16"] + pkgs = ["base", "tools", "headers"] if PkgSkip("PYTHON")==0: pkgs.append("pythoncode") if os.path.isdir("samples"): pkgs.append("samples") for pkg in pkgs: @@ -6348,12 +6449,8 @@ def MakeInstallerOSX(): if os.path.exists("/Developer/usr/bin/packagemaker"): cmd = '/Developer/usr/bin/packagemaker --info /tmp/Info_plist --version ' + VERSION + ' --out dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/' + pkg + '.pkg --target 10.4 --domain system --root dstroot/' + pkg + '/ --no-relocate' - if os.path.isdir("dstroot/scripts/" + pkg): - cmd += ' --scripts dstroot/scripts/' + pkg elif os.path.exists("/Applications/Xcode.app/Contents/Applications/PackageMaker.app/Contents/MacOS/PackageMaker"): cmd = '/Applications/Xcode.app/Contents/Applications/PackageMaker.app/Contents/MacOS/PackageMaker --info /tmp/Info_plist --version ' + VERSION + ' --out dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/' + pkg + '.pkg --target 10.4 --domain system --root dstroot/' + pkg + '/ --no-relocate' - if os.path.isdir("dstroot/scripts/" + pkg): - cmd += ' --scripts dstroot/scripts/' + pkg elif os.path.exists("/Developer/Tools/packagemaker"): cmd = '/Developer/Tools/packagemaker -build -f dstroot/' + pkg + '/ -p dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/' + pkg + '.pkg -i /tmp/Info_plist' else: @@ -6369,14 +6466,8 @@ def MakeInstallerOSX(): dist.write('\n') dist.write(' Panda3D\n') dist.write(' \n') - dist.write(' \n') dist.write(' %s\n' % ReadFile("doc/LICENSE")) dist.write(' \n') - dist.write(' \n') dist.write(' \n') dist.write(' \n') if PkgSkip("PYTHON")==0: @@ -6385,9 +6476,6 @@ def MakeInstallerOSX(): dist.write(' \n') dist.write(' \n') dist.write(' \n') - dist.write(' \n' % VERSION) - dist.write(' \n') - dist.write(' \n') dist.write(' \n') dist.write(' \n') dist.write(' \n') @@ -6405,7 +6493,6 @@ def MakeInstallerOSX(): dist.write(' \n') dist.write(' \n') dist.write(' \n') - dist.write(' file:./Contents/Packages/uninstall16.pkg\n') dist.write(' file:./Contents/Packages/base.pkg\n' % (GetDirectorySize("dstroot/base") // 1024)) dist.write(' file:./Contents/Packages/tools.pkg\n' % (GetDirectorySize("dstroot/tools") // 1024)) if PkgSkip("PYTHON")==0: diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index 50b079bcde..0c760d30a0 100644 --- a/makepanda/makepandacore.py +++ b/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") @@ -1549,9 +1558,14 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None, if SystemLibraryExists(libname): LibName(target_pkg, "-l" + libname) else: - have_pkg = False - if VERBOSE: - print(GetColor("cyan") + "Couldn't find library lib" + libname + GetColor()) + # Try searching in the package's LibDirectories. + lpath = [dir for ppkg, dir in LIBDIRECTORIES if pkg == ppkg] + if LibraryExists(libname, lpath): + LibName(target_pkg, "-l" + libname) + else: + have_pkg = False + if VERBOSE: + print(GetColor("cyan") + "Couldn't find library lib" + libname + GetColor()) for i in incs: incdir = None @@ -1563,17 +1577,18 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None, elif (os.path.isdir(sysroot_usr + "/PCBSD") and len(glob.glob(sysroot_usr + "/PCBSD/local/include/" + i)) > 0): incdir = sorted(glob.glob(sysroot_usr + "/PCBSD/local/include/" + i))[-1] else: - have_pkg = False # Try searching in the package's IncDirectories. for ppkg, pdir in INCDIRECTORIES: - if (pkg == ppkg and len(glob.glob(os.path.join(pdir, i))) > 0): + if pkg == ppkg and len(glob.glob(os.path.join(pdir, i))) > 0: incdir = sorted(glob.glob(os.path.join(pdir, i)))[-1] - have_pkg = True - if (incdir == None and VERBOSE and i.endswith(".h")): - print(GetColor("cyan") + "Couldn't find header file " + i + GetColor()) + + if incdir is None and i.endswith(".h"): + have_pkg = False + if VERBOSE: + print(GetColor("cyan") + "Couldn't find header file " + i + GetColor()) # Note: It's possible to specify a file instead of a dir, for the sake of checking if it exists. - if (incdir != None and os.path.isdir(incdir)): + if incdir is not None and os.path.isdir(incdir): IncDirectory(target_pkg, incdir) if (not have_pkg): @@ -2380,7 +2395,7 @@ def CopyPythonTree(dstdir, srcdir, lib2to3_fixers=[]): dstpth = os.path.join(dstdir, entry) if (os.path.isfile(srcpth)): base, ext = os.path.splitext(entry) - if (entry != ".cvsignore" and ext not in SUFFIX_INC): + if (entry != ".cvsignore" and ext not in SUFFIX_INC + ['.pyc', '.pyo']): if (NeedsBuild([dstpth], [srcpth])): WriteBinaryFile(dstpth, ReadBinaryFile(srcpth)) @@ -2412,10 +2427,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 +2443,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 +2537,7 @@ def WriteResourceFile(basename, **kwargs): ## ######################################################################## -ORIG_EXT={} +ORIG_EXT = {} def GetOrigExt(x): return ORIG_EXT[x] @@ -2556,7 +2571,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 +2587,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 +2608,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 +2684,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): diff --git a/panda/src/bullet/bulletContactResult.I b/panda/src/bullet/bulletContactResult.I index a0f20d54a6..fe78cedbe7 100644 --- a/panda/src/bullet/bulletContactResult.I +++ b/panda/src/bullet/bulletContactResult.I @@ -14,41 +14,40 @@ //////////////////////////////////////////////////////////////////// -// Function: BulletContactResult::get_node0 +// Function: BulletContact::get_node0 // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE PandaNode *BulletContact:: get_node0() const { - return _obj0 ? (PandaNode *)_obj0->getUserPointer() : NULL; + return _node0; } //////////////////////////////////////////////////////////////////// -// Function: BulletContactResult::get_node1 +// Function: BulletContact::get_node1 // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE PandaNode *BulletContact:: get_node1() const { - return _obj1 ? (PandaNode *)_obj1->getUserPointer() : NULL; + return _node1; } //////////////////////////////////////////////////////////////////// -// Function: BulletContactResult::get_manifold_point +// Function: BulletContact::get_manifold_point // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE const BulletManifoldPoint *BulletContact:: -get_manifold_point() const { +INLINE BulletManifoldPoint &BulletContact:: +get_manifold_point() { - btManifoldPoint &mp = const_cast(_mp); - return new BulletManifoldPoint(mp); + return _mp; } //////////////////////////////////////////////////////////////////// -// Function: BulletContactResult::get_idx0 +// Function: BulletContact::get_idx0 // Access: Published // Description: //////////////////////////////////////////////////////////////////// @@ -59,7 +58,7 @@ get_idx0() const { } //////////////////////////////////////////////////////////////////// -// Function: BulletContactResult::get_idx1 +// Function: BulletContact::get_idx1 // Access: Published // Description: //////////////////////////////////////////////////////////////////// @@ -70,7 +69,7 @@ get_idx1() const { } //////////////////////////////////////////////////////////////////// -// Function: BulletContactResult::get_part_id0 +// Function: BulletContact::get_part_id0 // Access: Published // Description: //////////////////////////////////////////////////////////////////// @@ -81,7 +80,7 @@ get_part_id0() const { } //////////////////////////////////////////////////////////////////// -// Function: BulletContactResult::get_part_id1 +// Function: BulletContact::get_part_id1 // Access: Published // Description: //////////////////////////////////////////////////////////////////// @@ -107,8 +106,8 @@ get_num_contacts() const { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE const BulletContact &BulletContactResult:: -get_contact(int idx) const { +INLINE BulletContact &BulletContactResult:: +get_contact(int idx) { nassertr(idx >= 0 && idx < (int)_contacts.size(), _empty); return _contacts[idx]; diff --git a/panda/src/bullet/bulletContactResult.cxx b/panda/src/bullet/bulletContactResult.cxx index 9537ac672a..b9adc65c75 100644 --- a/panda/src/bullet/bulletContactResult.cxx +++ b/panda/src/bullet/bulletContactResult.cxx @@ -14,8 +14,37 @@ #include "bulletContactResult.h" +btManifoldPoint BulletContact::_empty; BulletContact BulletContactResult::_empty; +//////////////////////////////////////////////////////////////////// +// Function: BulletContact::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +BulletContact:: +BulletContact() : _mp(_empty) { + + _node0 = NULL; + _node1 = NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: BulletContact::Copy Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +BulletContact:: +BulletContact(const BulletContact &other) : _mp(other._mp) { + + _node0 = other._node0; + _node1 = other._node1; + _part_id0 = other._part_id0; + _part_id1 = other._part_id1; + _idx0 = other._idx0; + _idx1 = other._idx1; +} + //////////////////////////////////////////////////////////////////// // Function: BulletContactResult::Constructor // Access: Protected @@ -24,9 +53,46 @@ BulletContact BulletContactResult::_empty; BulletContactResult:: BulletContactResult() : btCollisionWorld::ContactResultCallback() { +#if BT_BULLET_VERSION >= 281 + _filter_cb = NULL; + _filter_proxy = NULL; + _filter_set = false; +#endif } #if BT_BULLET_VERSION >= 281 +//////////////////////////////////////////////////////////////////// +// Function: BulletContactResult::use_filter +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void BulletContactResult:: +use_filter(btOverlapFilterCallback *cb, btBroadphaseProxy *proxy) { + + nassertv(cb); + nassertv(proxy); + + _filter_cb = cb; + _filter_proxy = proxy; + _filter_set = true; +} + +//////////////////////////////////////////////////////////////////// +// Function: BulletContactResult::needsCollision +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +bool BulletContactResult:: +needsCollision(btBroadphaseProxy *proxy0) const { + + if (_filter_set) { + return _filter_cb->needBroadphaseCollision(proxy0, _filter_proxy); + } + else { + return true; + } +} + //////////////////////////////////////////////////////////////////// // Function: BulletContactResult::addSingleResult // Access: Published @@ -37,11 +103,14 @@ addSingleResult(btManifoldPoint &mp, const btCollisionObjectWrapper *wrap0, int part_id0, int idx0, const btCollisionObjectWrapper *wrap1, int part_id1, int idx1) { + const btCollisionObject *obj0 = wrap0->getCollisionObject(); + const btCollisionObject *obj1 = wrap1->getCollisionObject(); + BulletContact contact; - contact._mp = mp; - contact._obj0 = wrap0->getCollisionObject(); - contact._obj1 = wrap1->getCollisionObject(); + contact._mp = BulletManifoldPoint(mp); + contact._node0 = obj0 ? (PandaNode *)obj0->getUserPointer() : NULL; + contact._node1 = obj1 ? (PandaNode *)obj1->getUserPointer() : NULL; contact._part_id0 = part_id0; contact._part_id1 = part_id1; contact._idx0 = idx0; @@ -64,9 +133,9 @@ addSingleResult(btManifoldPoint &mp, BulletContact contact; - contact._mp = mp; - contact._obj0 = obj0; - contact._obj1 = obj1; + contact._mp = BulletManifoldPoint(mp); + contact._node0 = obj0 ? (PandaNode *)obj0->getUserPointer() : NULL; + contact._node1 = obj1 ? (PandaNode *)obj1->getUserPointer() : NULL; contact._part_id0 = part_id0; contact._part_id1 = part_id1; contact._idx0 = idx0; diff --git a/panda/src/bullet/bulletContactResult.h b/panda/src/bullet/bulletContactResult.h index b00d879dad..6de4962ae5 100644 --- a/panda/src/bullet/bulletContactResult.h +++ b/panda/src/bullet/bulletContactResult.h @@ -28,8 +28,12 @@ //////////////////////////////////////////////////////////////////// struct EXPCL_PANDABULLET BulletContact { +public: + BulletContact(); + BulletContact(const BulletContact &other); + PUBLISHED: - INLINE const BulletManifoldPoint *get_manifold_point() const; + INLINE BulletManifoldPoint &get_manifold_point(); INLINE PandaNode *get_node0() const; INLINE PandaNode *get_node1() const; INLINE const int get_idx0() const; @@ -38,9 +42,13 @@ PUBLISHED: INLINE const int get_part_id1() const; private: - btManifoldPoint _mp; - const btCollisionObject *_obj0; - const btCollisionObject *_obj1; + static btManifoldPoint _empty; + + BulletManifoldPoint _mp; + + PT(PandaNode) _node0; + PT(PandaNode) _node1; + int _part_id0; int _part_id1; int _idx0; @@ -57,11 +65,13 @@ struct EXPCL_PANDABULLET BulletContactResult : public btCollisionWorld::ContactR PUBLISHED: INLINE int get_num_contacts() const; - INLINE const BulletContact &get_contact(int idx) const; + INLINE BulletContact &get_contact(int idx); MAKE_SEQ(get_contacts, get_num_contacts, get_contact); public: #if BT_BULLET_VERSION >= 281 + virtual bool needsCollision(btBroadphaseProxy *proxy0) const; + virtual btScalar addSingleResult(btManifoldPoint &mp, const btCollisionObjectWrapper *wrap0, int part_id0, int idx0, const btCollisionObjectWrapper *wrap1, int part_id1, int idx1); @@ -74,11 +84,21 @@ public: protected: BulletContactResult(); +#if BT_BULLET_VERSION >= 281 + void use_filter(btOverlapFilterCallback *cb, btBroadphaseProxy *proxy); +#endif + private: static BulletContact _empty; btAlignedObjectArray _contacts; +#if BT_BULLET_VERSION >= 281 + bool _filter_set; + btOverlapFilterCallback *_filter_cb; + btBroadphaseProxy *_filter_proxy; +#endif + friend class BulletWorld; }; diff --git a/panda/src/bullet/bulletHelper.cxx b/panda/src/bullet/bulletHelper.cxx index c5b591bba3..61927dc24b 100644 --- a/panda/src/bullet/bulletHelper.cxx +++ b/panda/src/bullet/bulletHelper.cxx @@ -220,9 +220,11 @@ make_geom(BulletSoftBodyNode *node, const GeomVertexFormat *format, bool two_sid if (two_sided) { for (int j=0; jm_faces); prim = new GeomTriangles(Geom::UH_stream); prim->set_shade_model(Geom::SM_uniform); for (int j=0; jadd_vertices(int(faces[j].m_n[0] - node0), - int(faces[j].m_n[1] - node0), - int(faces[j].m_n[2] - node0)); + i0 = int(faces[j].m_n[0] - node0); + i1 = int(faces[j].m_n[1] - node0); + i2 = int(faces[j].m_n[2] - node0); + + prim->add_vertices(i0, i1, i2); prim->close_primitive(); if (two_sided) { - prim->add_vertices(nodes.size() + int(faces[j].m_n[0] - node0), - nodes.size() + int(faces[j].m_n[2] - node0), - nodes.size() + int(faces[j].m_n[1] - node0)); + i0 = nodes.size() + int(faces[j].m_n[0] - node0); + i1 = nodes.size() + int(faces[j].m_n[2] - node0); + i2 = nodes.size() + int(faces[j].m_n[1] - node0); + + prim->add_vertices(i0, i1, i2); prim->close_primitive(); } } @@ -259,8 +267,10 @@ make_geom(BulletSoftBodyNode *node, const GeomVertexFormat *format, bool two_sid prim->set_shade_model(Geom::SM_uniform); for (int j=0; jadd_vertices(int(links[j].m_n[0] - node0), - int(links[j].m_n[1] - node0)); + i0 = int(links[j].m_n[0] - node0); + i1 = int(links[j].m_n[1] - node0); + + prim->add_vertices(i0, i1); prim->close_primitive(); } } diff --git a/panda/src/bullet/bulletManifoldPoint.cxx b/panda/src/bullet/bulletManifoldPoint.cxx index df43a45340..509a36b9cc 100644 --- a/panda/src/bullet/bulletManifoldPoint.cxx +++ b/panda/src/bullet/bulletManifoldPoint.cxx @@ -25,6 +25,28 @@ BulletManifoldPoint(btManifoldPoint &pt) } +//////////////////////////////////////////////////////////////////// +// Function: BulletManifoldPoint::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +BulletManifoldPoint:: +BulletManifoldPoint(const BulletManifoldPoint &other) + : _pt(other._pt) { + +} + +//////////////////////////////////////////////////////////////////// +// Function: BulletManifoldPoint::Copy Assignment +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +BulletManifoldPoint& BulletManifoldPoint:: +operator=(const BulletManifoldPoint& other) { + + return *this; +} + //////////////////////////////////////////////////////////////////// // Function: BulletManifoldPoint::get_lift_time // Access: Published diff --git a/panda/src/bullet/bulletManifoldPoint.h b/panda/src/bullet/bulletManifoldPoint.h index 95e67def6e..672a8db282 100644 --- a/panda/src/bullet/bulletManifoldPoint.h +++ b/panda/src/bullet/bulletManifoldPoint.h @@ -73,6 +73,9 @@ PUBLISHED: public: BulletManifoldPoint(btManifoldPoint &pt); + BulletManifoldPoint(const BulletManifoldPoint &other); + BulletManifoldPoint& operator=(const BulletManifoldPoint& other); + private: btManifoldPoint &_pt; }; diff --git a/panda/src/bullet/bulletSoftBodyConfig.h b/panda/src/bullet/bulletSoftBodyConfig.h index 8f2d47f052..22505c8358 100644 --- a/panda/src/bullet/bulletSoftBodyConfig.h +++ b/panda/src/bullet/bulletSoftBodyConfig.h @@ -29,7 +29,7 @@ PUBLISHED: INLINE ~BulletSoftBodyConfig(); enum CollisionFlag { - CF_rigid__vs_soft_mask = 0x000f, // RVSmask: Rigid versus soft mask + CF_rigid_vs_soft_mask = 0x000f, // RVSmask: Rigid versus soft mask CF_sdf_rigid_soft = 0x0001, // SDF_RS: SDF based rigid vs soft CF_cluster_rigid_soft = 0x0002, // CL_RS: Cluster vs convex rigid vs soft CF_soft_vs_soft_mask = 0x0030, // SVSmask: Soft versus soft mask diff --git a/panda/src/bullet/bulletSoftBodyNode.cxx b/panda/src/bullet/bulletSoftBodyNode.cxx index 631325586b..7fd660b8a6 100644 --- a/panda/src/bullet/bulletSoftBodyNode.cxx +++ b/panda/src/bullet/bulletSoftBodyNode.cxx @@ -194,22 +194,35 @@ transform_changed() { LMatrix4 m_ts = ts->get_mat(); if (!m_sync.almost_equal(m_ts)) { - _sync = ts; + // New transform for the center btTransform trans = TransformState_to_btTrans(ts); - trans *= _soft->m_initialWorldTransform.inverse(); + // Offset between current approx center and current initial transform + btVector3 pos = LVecBase3_to_btVector3(this->get_aabb().get_approx_center()); + btVector3 origin = _soft->m_initialWorldTransform.getOrigin(); + btVector3 offset = pos - origin; + + // Subtract offset to get new transform for the body + trans.setOrigin(trans.getOrigin() - offset); + + // Now apply the new transform + _soft->transform(_soft->m_initialWorldTransform.inverse()); _soft->transform(trans); if (ts->has_scale()) { - LVecBase3 scale = ts->get_scale(); - if (!scale.almost_equal(LVecBase3(1.0f, 1.0f, 1.0f))) { - for (int i=0; iset_local_scale(scale); - } - } + btVector3 current_scale = LVecBase3_to_btVector3(_sync->get_scale()); + btVector3 new_scale = LVecBase3_to_btVector3(ts->get_scale()); + + current_scale.setX(1.0 / current_scale.getX()); + current_scale.setY(1.0 / current_scale.getY()); + current_scale.setZ(1.0 / current_scale.getZ()); + + _soft->scale(current_scale); + _soft->scale(new_scale); } + + _sync = ts; } } @@ -221,7 +234,7 @@ transform_changed() { void BulletSoftBodyNode:: sync_p2b() { - transform_changed(); + //transform_changed(); Disabled for now... } //////////////////////////////////////////////////////////////////// @@ -280,22 +293,21 @@ sync_b2p() { } } - // It is ok to pass the address of a temporary object here, because - // set_bounds does not store the pointer - it makes a copy using - // volume->make_copy(). - BoundingBox bb = this->get_aabb(); - LVecBase3 pos = bb.get_approx_center(); + // Update the synchronized transform with the current + // approximate center of the soft body + LVecBase3 pos = this->get_aabb().get_approx_center(); + CPT(TransformState) ts = TransformState::make_pos(pos); NodePath np = NodePath::any_path((PandaNode *)this); LVecBase3 scale = np.get_net_transform()->get_scale(); - - CPT(TransformState) ts = TransformState::make_pos(pos); ts = ts->set_scale(scale); _sync = ts; _sync_disable = true; np.set_transform(NodePath(), ts); _sync_disable = false; +/* +*/ Thread *current_thread = Thread::get_current_thread(); this->r_mark_geom_bounds_stale(current_thread); @@ -1135,3 +1147,26 @@ append_angular_joint(BulletBodyNode *body, const LVector3 &axis, PN_stdfloat erp _soft->appendAngularJoint(as, ptr); } +//////////////////////////////////////////////////////////////////// +// Function: BulletSoftBodyNode::set_wind_velocity +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void BulletSoftBodyNode:: +set_wind_velocity(const LVector3 &velocity) { + + nassertv(!velocity.is_nan()); + _soft->setWindVelocity(LVecBase3_to_btVector3(velocity)); +} + +//////////////////////////////////////////////////////////////////// +// Function: BulletSoftBodyNode::get_wind_velocity +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +LVector3 BulletSoftBodyNode:: +get_wind_velocity() const { + + return btVector3_to_LVector3(_soft->getWindVelocity()); +} + diff --git a/panda/src/bullet/bulletSoftBodyNode.h b/panda/src/bullet/bulletSoftBodyNode.h index a9ebe075b9..a8e62d1714 100644 --- a/panda/src/bullet/bulletSoftBodyNode.h +++ b/panda/src/bullet/bulletSoftBodyNode.h @@ -96,6 +96,9 @@ PUBLISHED: void add_velocity(const LVector3 &velocity); void add_velocity(const LVector3 &velocity, int node); + void set_wind_velocity(const LVector3 &velocity); + LVector3 get_wind_velocity() const; + void set_pose(bool bvolume, bool bframe); BoundingBox get_aabb() const; diff --git a/panda/src/bullet/bulletWorld.cxx b/panda/src/bullet/bulletWorld.cxx index c570ff1e18..07a891aa4c 100644 --- a/panda/src/bullet/bulletWorld.cxx +++ b/panda/src/bullet/bulletWorld.cxx @@ -87,18 +87,21 @@ BulletWorld() { // Filter callback switch (bullet_filter_algorithm) { case FA_mask: - _world->getPairCache()->setOverlapFilterCallback(&_filter_cb1); + _filter_cb = &_filter_cb1; break; case FA_groups_mask: - _world->getPairCache()->setOverlapFilterCallback(&_filter_cb2); + _filter_cb = &_filter_cb2; break; case FA_callback: - _world->getPairCache()->setOverlapFilterCallback(&_filter_cb3); + _filter_cb = &_filter_cb3; break; default: bullet_cat.error() << "no proper filter algorithm!" << endl; + _filter_cb = NULL; } + _world->getPairCache()->setOverlapFilterCallback(_filter_cb); + // Tick callback _tick_callback_obj = NULL; @@ -712,19 +715,61 @@ sweep_test_closest(BulletShape *shape, const TransformState &from_ts, const Tran return cb; } +//////////////////////////////////////////////////////////////////// +// Function: BulletWorld::filter_test +// Access: Published +// Description: Performs a test if two bodies should collide or +// not, based on the collision filter setting. +//////////////////////////////////////////////////////////////////// +bool BulletWorld:: +filter_test(PandaNode *node0, PandaNode *node1) const { + + nassertr(node0, false); + nassertr(node1, false); + nassertr(_filter_cb, false); + + btCollisionObject *obj0 = get_collision_object(node0); + btCollisionObject *obj1 = get_collision_object(node1); + + nassertr(obj0, false); + nassertr(obj1, false); + + btBroadphaseProxy *proxy0 = obj0->getBroadphaseHandle(); + btBroadphaseProxy *proxy1 = obj1->getBroadphaseHandle(); + + nassertr(proxy0, false); + nassertr(proxy1, false); + + return _filter_cb->needBroadphaseCollision(proxy0, proxy1); +} + //////////////////////////////////////////////////////////////////// // Function: BulletWorld::contact_test // Access: Published -// Description: +// Description: Performas a test for all bodies which are +// currently in contact with the given body. +// The test returns a BulletContactResult object +// which may contain zero, one or more contacts. +// +// If the optional parameter use_filter is set to +// TRUE this test will consider filter settings. +// Otherwise all objects in contact are reported, +// no matter if they would collide or not. //////////////////////////////////////////////////////////////////// BulletContactResult BulletWorld:: -contact_test(PandaNode *node) const { +contact_test(PandaNode *node, bool use_filter) const { btCollisionObject *obj = get_collision_object(node); BulletContactResult cb; if (obj) { +#if BT_BULLET_VERSION >= 281 + if (use_filter) { + cb.use_filter(_filter_cb, obj->getBroadphaseHandle()); + } +#endif + _world->contactTest(obj, cb); } @@ -734,7 +779,10 @@ contact_test(PandaNode *node) const { //////////////////////////////////////////////////////////////////// // Function: BulletWorld::contact_pair_test // Access: Published -// Description: +// Description: Performas a test if the two bodies given as +// parameters are in contact or not. +// The test returns a BulletContactResult object +// which may contain zero or one contacts. //////////////////////////////////////////////////////////////////// BulletContactResult BulletWorld:: contact_test_pair(PandaNode *node0, PandaNode *node1) const { @@ -745,6 +793,7 @@ contact_test_pair(PandaNode *node0, PandaNode *node1) const { BulletContactResult cb; if (obj0 && obj1) { + _world->contactPairTest(obj0, obj1, cb); } @@ -806,7 +855,7 @@ set_group_collision_flag(unsigned int group1, unsigned int group2, bool enable) } //////////////////////////////////////////////////////////////////// -// Function: BulletWorld::get_collision_object +// Function: BulletWorld::get_group_collision_flag // Access: Public // Description: //////////////////////////////////////////////////////////////////// diff --git a/panda/src/bullet/bulletWorld.h b/panda/src/bullet/bulletWorld.h index 3ebfe59ce0..6a798cde7f 100644 --- a/panda/src/bullet/bulletWorld.h +++ b/panda/src/bullet/bulletWorld.h @@ -123,9 +123,11 @@ PUBLISHED: const CollideMask &mask=CollideMask::all_on(), PN_stdfloat penetration=0.0f) const; - BulletContactResult contact_test(PandaNode *node) const; + BulletContactResult contact_test(PandaNode *node, bool use_filter=false) const; BulletContactResult contact_test_pair(PandaNode *node0, PandaNode *node1) const; + bool filter_test(PandaNode *node0, PandaNode *node1) const; + // Manifolds INLINE int get_num_manifolds() const; BulletPersistentManifold *get_manifold(int idx) const; @@ -232,6 +234,7 @@ private: btFilterCallback1 _filter_cb1; btFilterCallback2 _filter_cb2; btFilterCallback3 _filter_cb3; + btOverlapFilterCallback *_filter_cb; PT(CallbackObject) _tick_callback_obj; diff --git a/panda/src/chan/partGroup.h b/panda/src/chan/partGroup.h index a32540bb86..1ba23978d9 100644 --- a/panda/src/chan/partGroup.h +++ b/panda/src/chan/partGroup.h @@ -43,7 +43,7 @@ class AnimChannelBase; // MovingPart. It defines a hierarchy of MovingParts. //////////////////////////////////////////////////////////////////// class EXPCL_PANDA_CHAN PartGroup : public TypedWritableReferenceCount, public Namable { -public: +PUBLISHED: // This enum defines bits which may be passed into check_hierarchy() // and PartBundle::bind_anim() to allow an inexact match of channel // hierarchies. This specifies conditions that we don't care about diff --git a/panda/src/cocoadisplay/Sources.pp b/panda/src/cocoadisplay/Sources.pp index 3aed55d405..0a3a5b4e44 100644 --- a/panda/src/cocoadisplay/Sources.pp +++ b/panda/src/cocoadisplay/Sources.pp @@ -17,13 +17,14 @@ cocoaGraphicsPipe.h cocoaGraphicsPipe.I \ cocoaGraphicsWindow.h cocoaGraphicsWindow.I \ cocoaGraphicsStateGuardian.h cocoaGraphicsStateGuardian.I \ - cocoaPandaView.h cocoaPandaWindowDelegate.h + cocoaPandaApp.h cocoaPandaView.h cocoaPandaWindowDelegate.h #define INCLUDED_SOURCES \ config_cocoadisplay.mm \ cocoaGraphicsPipe.mm \ cocoaGraphicsStateGuardian.mm \ cocoaGraphicsWindow.mm \ + cocoaPandaApp.mm \ cocoaPandaView.mm \ cocoaPandaWindow.mm \ cocoaPandaWindowDelegate.mm diff --git a/panda/src/cocoadisplay/cocoaGraphicsPipe.mm b/panda/src/cocoadisplay/cocoaGraphicsPipe.mm index 8a66bfd87a..8c6d86ef17 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsPipe.mm +++ b/panda/src/cocoadisplay/cocoaGraphicsPipe.mm @@ -16,6 +16,7 @@ //#include "cocoaGraphicsBuffer.h" #include "cocoaGraphicsWindow.h" #include "cocoaGraphicsStateGuardian.h" +#include "cocoaPandaApp.h" #include "config_cocoadisplay.h" #include "frameBufferProperties.h" @@ -32,7 +33,7 @@ TypeHandle CocoaGraphicsPipe::_type_handle; static void init_app() { if (NSApp == nil) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - [NSApplication sharedApplication]; + [CocoaPandaApp sharedApplication]; #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; diff --git a/panda/src/cocoadisplay/cocoaGraphicsWindow.h b/panda/src/cocoadisplay/cocoaGraphicsWindow.h index 6fdc2a4497..b50edbf173 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsWindow.h +++ b/panda/src/cocoadisplay/cocoaGraphicsWindow.h @@ -80,7 +80,9 @@ protected: private: NSImage *load_image(const Filename &filename); - ButtonHandle map_key(unsigned short keycode); + void handle_modifier(NSUInteger modifierFlags, NSUInteger mask, ButtonHandle button); + ButtonHandle map_key(unsigned short c); + ButtonHandle map_raw_key(unsigned short keycode); private: NSWindow *_window; diff --git a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm index e314fbe4a0..a5c63f3d50 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm +++ b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm @@ -1495,54 +1495,73 @@ void CocoaGraphicsWindow:: handle_key_event(NSEvent *event) { NSUInteger modifierFlags = [event modifierFlags]; - if ((modifierFlags ^ _modifier_keys) & NSAlphaShiftKeyMask) { - if (modifierFlags & NSAlphaShiftKeyMask) { - _input_devices[0].button_down(KeyboardButton::caps_lock()); - } else { - _input_devices[0].button_up(KeyboardButton::caps_lock()); - } - } + //NB. This is actually a on-off toggle, not up-down. + // Should we instead rapidly fire two successive up-down events? + handle_modifier(modifierFlags, NSAlphaShiftKeyMask, KeyboardButton::caps_lock()); - if ((modifierFlags ^ _modifier_keys) & NSShiftKeyMask) { - if (modifierFlags & NSShiftKeyMask) { - _input_devices[0].button_down(KeyboardButton::shift()); - } else { - _input_devices[0].button_up(KeyboardButton::shift()); - } - } + // Check if any of the modifier keys have changed. + handle_modifier(modifierFlags, NSShiftKeyMask, KeyboardButton::shift()); + handle_modifier(modifierFlags, NSControlKeyMask, KeyboardButton::control()); + handle_modifier(modifierFlags, NSAlternateKeyMask, KeyboardButton::alt()); + handle_modifier(modifierFlags, NSCommandKeyMask, KeyboardButton::meta()); - if ((modifierFlags ^ _modifier_keys) & NSControlKeyMask) { - if (modifierFlags & NSControlKeyMask) { - _input_devices[0].button_down(KeyboardButton::control()); - } else { - _input_devices[0].button_up(KeyboardButton::control()); - } - } - - if ((modifierFlags ^ _modifier_keys) & NSAlternateKeyMask) { - if (modifierFlags & NSAlternateKeyMask) { - _input_devices[0].button_down(KeyboardButton::alt()); - } else { - _input_devices[0].button_up(KeyboardButton::alt()); - } - } - - if ((modifierFlags ^ _modifier_keys) & NSCommandKeyMask) { - if (modifierFlags & NSCommandKeyMask) { - _input_devices[0].button_down(KeyboardButton::meta()); - } else { - _input_devices[0].button_up(KeyboardButton::meta()); - } - } - - // I'd add the help key too, but something else in Cocoa messes - // around with it. The up event is registered fine below, but - // the down event isn't, and the modifier flag gets stuck after 1 press. - // More testing is needed, but I don't think it's worth it until - // we encounter someone who requires support for the help key. + // These are not documented, but they seem to be a reliable indicator + // of the status of the left/right modifier keys. + handle_modifier(modifierFlags, 0x0002, KeyboardButton::lshift()); + handle_modifier(modifierFlags, 0x0004, KeyboardButton::rshift()); + handle_modifier(modifierFlags, 0x0001, KeyboardButton::lcontrol()); + handle_modifier(modifierFlags, 0x2000, KeyboardButton::rcontrol()); + handle_modifier(modifierFlags, 0x0020, KeyboardButton::lalt()); + handle_modifier(modifierFlags, 0x0040, KeyboardButton::ralt()); + handle_modifier(modifierFlags, 0x0008, KeyboardButton::lmeta()); + handle_modifier(modifierFlags, 0x0010, KeyboardButton::rmeta()); _modifier_keys = modifierFlags; + // Get the raw button and send it. + ButtonHandle raw_button = map_raw_key([event keyCode]); + if (raw_button != ButtonHandle::none()) { + // This is not perfect. Eventually, this whole thing should + // probably be replaced with something that uses IOKit or so. + // In particular, the flaws are: + // - OS eats unmodified F11, F12, scroll lock, pause + // - no up events for caps lock + // - no robust way to distinguish up/down for modkeys + if ([event type] == NSKeyUp) { + _input_devices[0].raw_button_up(raw_button); + + } else if ([event type] == NSFlagsChanged) { + bool down = false; + if (raw_button == KeyboardButton::lshift()) { + down = (modifierFlags & 0x0002); + } else if (raw_button == KeyboardButton::rshift()) { + down = (modifierFlags & 0x0004); + } else if (raw_button == KeyboardButton::lcontrol()) { + down = (modifierFlags & 0x0001); + } else if (raw_button == KeyboardButton::rcontrol()) { + down = (modifierFlags & 0x2000); + } else if (raw_button == KeyboardButton::lalt()) { + down = (modifierFlags & 0x0020); + } else if (raw_button == KeyboardButton::ralt()) { + down = (modifierFlags & 0x0040); + } else if (raw_button == KeyboardButton::lmeta()) { + down = (modifierFlags & 0x0008); + } else if (raw_button == KeyboardButton::rmeta()) { + down = (modifierFlags & 0x0010); + } else if (raw_button == KeyboardButton::caps_lock()) { + // Emulate down-up, annoying hack! + _input_devices[0].raw_button_down(raw_button); + } + if (down) { + _input_devices[0].raw_button_down(raw_button); + } else { + _input_devices[0].raw_button_up(raw_button); + } + } else if (![event isARepeat]) { + _input_devices[0].raw_button_down(raw_button); + } + } + // FlagsChanged events only carry modifier key information. if ([event type] == NSFlagsChanged) { return; @@ -1597,6 +1616,23 @@ handle_key_event(NSEvent *event) { } } +//////////////////////////////////////////////////////////////////// +// Function: CocoaGraphicsWindow::handle_modifier +// Access: Private +// Description: Called by handle_key_event to read the state of +// a modifier key. +//////////////////////////////////////////////////////////////////// +void CocoaGraphicsWindow:: +handle_modifier(NSUInteger modifierFlags, NSUInteger mask, ButtonHandle button) { + if ((modifierFlags ^ _modifier_keys) & mask) { + if (modifierFlags & mask) { + _input_devices[0].button_down(button); + } else { + _input_devices[0].button_up(button); + } + } +} + //////////////////////////////////////////////////////////////////// // Function: CocoaGraphicsWindow::handle_mouse_button_event // Access: Public @@ -1697,11 +1733,11 @@ handle_wheel_event(double x, double y) { //////////////////////////////////////////////////////////////////// // Function: CocoaGraphicsWindow::map_key // Access: Private -// Description: +// Description: Maps a Cocoa key character to a ButtonHandle. //////////////////////////////////////////////////////////////////// ButtonHandle CocoaGraphicsWindow:: -map_key(unsigned short keycode) { - switch (keycode) { +map_key(unsigned short c) { + switch (c) { case NSEnterCharacter: return KeyboardButton::enter(); case NSBackspaceCharacter: @@ -1713,6 +1749,11 @@ map_key(unsigned short keycode) { // BackTabCharacter is sent when shift-tab is used. return KeyboardButton::tab(); + case 16: + // No idea where this constant comes from, but it + // is sent whenever the menu key is pressed. + return KeyboardButton::menu(); + case NSUpArrowFunctionKey: return KeyboardButton::up(); case NSDownArrowFunctionKey: @@ -1824,3 +1865,124 @@ map_key(unsigned short keycode) { } return ButtonHandle::none(); } + +//////////////////////////////////////////////////////////////////// +// Function: CocoaGraphicsWindow::map_raw_key +// Access: Private +// Description: Maps a keycode to a ButtonHandle. +//////////////////////////////////////////////////////////////////// +ButtonHandle CocoaGraphicsWindow:: +map_raw_key(unsigned short keycode) { + if (keycode > 0x7f) { + return ButtonHandle::none(); + } + switch ((unsigned char) keycode) { + /* See HIToolBox/Events.h */ + case 0x00: return KeyboardButton::ascii_key('a'); + case 0x01: return KeyboardButton::ascii_key('s'); + case 0x02: return KeyboardButton::ascii_key('d'); + case 0x03: return KeyboardButton::ascii_key('f'); + case 0x04: return KeyboardButton::ascii_key('h'); + case 0x05: return KeyboardButton::ascii_key('g'); + case 0x06: return KeyboardButton::ascii_key('z'); + case 0x07: return KeyboardButton::ascii_key('x'); + case 0x08: return KeyboardButton::ascii_key('c'); + case 0x09: return KeyboardButton::ascii_key('v'); + case 0x0B: return KeyboardButton::ascii_key('b'); + case 0x0C: return KeyboardButton::ascii_key('q'); + case 0x0D: return KeyboardButton::ascii_key('w'); + case 0x0E: return KeyboardButton::ascii_key('e'); + case 0x0F: return KeyboardButton::ascii_key('r'); + case 0x10: return KeyboardButton::ascii_key('y'); + case 0x11: return KeyboardButton::ascii_key('t'); + case 0x12: return KeyboardButton::ascii_key('1'); + case 0x13: return KeyboardButton::ascii_key('2'); + case 0x14: return KeyboardButton::ascii_key('3'); + case 0x15: return KeyboardButton::ascii_key('4'); + case 0x16: return KeyboardButton::ascii_key('6'); + case 0x17: return KeyboardButton::ascii_key('5'); + case 0x18: return KeyboardButton::ascii_key('='); + case 0x19: return KeyboardButton::ascii_key('9'); + case 0x1A: return KeyboardButton::ascii_key('7'); + case 0x1B: return KeyboardButton::ascii_key('-'); + case 0x1C: return KeyboardButton::ascii_key('8'); + case 0x1D: return KeyboardButton::ascii_key('0'); + case 0x1E: return KeyboardButton::ascii_key(']'); + case 0x1F: return KeyboardButton::ascii_key('o'); + case 0x20: return KeyboardButton::ascii_key('u'); + case 0x21: return KeyboardButton::ascii_key('['); + case 0x22: return KeyboardButton::ascii_key('i'); + case 0x23: return KeyboardButton::ascii_key('p'); + case 0x24: return KeyboardButton::enter(); + case 0x25: return KeyboardButton::ascii_key('l'); + case 0x26: return KeyboardButton::ascii_key('j'); + case 0x27: return KeyboardButton::ascii_key('\''); + case 0x28: return KeyboardButton::ascii_key('k'); + case 0x29: return KeyboardButton::ascii_key(';'); + case 0x2A: return KeyboardButton::ascii_key('\\'); + case 0x2B: return KeyboardButton::ascii_key(','); + case 0x2C: return KeyboardButton::ascii_key('/'); + case 0x2D: return KeyboardButton::ascii_key('n'); + case 0x2E: return KeyboardButton::ascii_key('m'); + case 0x2F: return KeyboardButton::ascii_key('.'); + case 0x30: return KeyboardButton::tab(); + case 0x31: return KeyboardButton::ascii_key(' '); + case 0x32: return KeyboardButton::ascii_key('`'); + case 0x33: return KeyboardButton::backspace(); + case 0x35: return KeyboardButton::escape(); + case 0x36: return KeyboardButton::rmeta(); + case 0x37: return KeyboardButton::lmeta(); + case 0x38: return KeyboardButton::lshift(); + case 0x39: return KeyboardButton::caps_lock(); + case 0x3A: return KeyboardButton::lalt(); + case 0x3B: return KeyboardButton::lcontrol(); + case 0x3C: return KeyboardButton::rshift(); + case 0x3D: return KeyboardButton::ralt(); + case 0x3E: return KeyboardButton::rcontrol(); + case 0x41: return KeyboardButton::ascii_key('.'); + case 0x43: return KeyboardButton::ascii_key('*'); + case 0x45: return KeyboardButton::ascii_key('+'); + case 0x47: return KeyboardButton::num_lock(); + case 0x4B: return KeyboardButton::ascii_key('/'); + case 0x4C: return KeyboardButton::enter(); + case 0x4E: return KeyboardButton::ascii_key('-'); + case 0x51: return KeyboardButton::ascii_key('='); + case 0x52: return KeyboardButton::ascii_key('0'); + case 0x53: return KeyboardButton::ascii_key('1'); + case 0x54: return KeyboardButton::ascii_key('2'); + case 0x55: return KeyboardButton::ascii_key('3'); + case 0x56: return KeyboardButton::ascii_key('4'); + case 0x57: return KeyboardButton::ascii_key('5'); + case 0x58: return KeyboardButton::ascii_key('6'); + case 0x59: return KeyboardButton::ascii_key('7'); + case 0x5B: return KeyboardButton::ascii_key('8'); + case 0x5C: return KeyboardButton::ascii_key('9'); + case 0x60: return KeyboardButton::f5(); + case 0x61: return KeyboardButton::f6(); + case 0x62: return KeyboardButton::f7(); + case 0x63: return KeyboardButton::f3(); + case 0x64: return KeyboardButton::f8(); + case 0x65: return KeyboardButton::f9(); + case 0x67: return KeyboardButton::f11(); + case 0x69: return KeyboardButton::print_screen(); + case 0x6B: return KeyboardButton::scroll_lock(); + case 0x6D: return KeyboardButton::f10(); + case 0x6E: return KeyboardButton::menu(); + case 0x6F: return KeyboardButton::f12(); + case 0x71: return KeyboardButton::pause(); + case 0x72: return KeyboardButton::insert(); + case 0x73: return KeyboardButton::home(); + case 0x74: return KeyboardButton::page_up(); + case 0x75: return KeyboardButton::del(); + case 0x76: return KeyboardButton::f4(); + case 0x77: return KeyboardButton::end(); + case 0x78: return KeyboardButton::f2(); + case 0x79: return KeyboardButton::page_down(); + case 0x7A: return KeyboardButton::f1(); + case 0x7B: return KeyboardButton::left(); + case 0x7C: return KeyboardButton::right(); + case 0x7D: return KeyboardButton::down(); + case 0x7E: return KeyboardButton::up(); + default: return ButtonHandle::none(); + } +} diff --git a/panda/src/cocoadisplay/cocoaPandaApp.h b/panda/src/cocoadisplay/cocoaPandaApp.h new file mode 100644 index 0000000000..a15d77a543 --- /dev/null +++ b/panda/src/cocoadisplay/cocoaPandaApp.h @@ -0,0 +1,21 @@ +// Filename: cocoaPandaApp.h +// Created by: rdb (08Mar14) +// +//////////////////////////////////////////////////////////////////// +// +// 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." +// +//////////////////////////////////////////////////////////////////// + +#import + +// This class solely exists so that we can override sendEvent in order +// to prevent NSApplication from eating certain keyboard events. +@interface CocoaPandaApp : NSApplication +- (void) sendEvent: (NSEvent *) event; +@end diff --git a/panda/src/cocoadisplay/cocoaPandaApp.mm b/panda/src/cocoadisplay/cocoaPandaApp.mm new file mode 100644 index 0000000000..95efc8fe2d --- /dev/null +++ b/panda/src/cocoadisplay/cocoaPandaApp.mm @@ -0,0 +1,29 @@ +// Filename: cocoaPandaApp.mm +// Created by: rdb (08Mar14) +// +//////////////////////////////////////////////////////////////////// +// +// 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." +// +//////////////////////////////////////////////////////////////////// + +#import "cocoaPandaApp.h" + +@implementation CocoaPandaApp +- (void) sendEvent: (NSEvent *) event { + // This is a hack that allows us to receive cmd-key-up events correctly. + // Also prevent it from eating the insert/help key. + if (([event type] == NSKeyUp && ([event modifierFlags] & NSCommandKeyMask)) + ||([event type] == NSKeyDown && [event keyCode] == 0x72)) { + + [[self keyWindow] sendEvent: event]; + } else { + [super sendEvent: event]; + } +} +@end diff --git a/panda/src/cocoadisplay/p3cocoadisplay_composite1.mm b/panda/src/cocoadisplay/p3cocoadisplay_composite1.mm index fe8d7d03de..28755a66dd 100644 --- a/panda/src/cocoadisplay/p3cocoadisplay_composite1.mm +++ b/panda/src/cocoadisplay/p3cocoadisplay_composite1.mm @@ -2,6 +2,7 @@ #include "cocoaGraphicsPipe.mm" #include "cocoaGraphicsStateGuardian.mm" #include "cocoaGraphicsWindow.mm" +#include "cocoaPandaApp.mm" #include "cocoaPandaView.mm" #include "cocoaPandaWindow.mm" -#include "cocoaPandaWindowDelegate.mm" \ No newline at end of file +#include "cocoaPandaWindowDelegate.mm" diff --git a/panda/src/display/Sources.pp b/panda/src/display/Sources.pp index 99a8cca70b..b2f093957a 100644 --- a/panda/src/display/Sources.pp +++ b/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 \ diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index fb630022d4..4aea74171a 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -59,13 +59,6 @@ #include #include -#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; } @@ -996,6 +954,16 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4 & 0.0); return &t; } + case Shader::SMO_frame_time: { + PN_stdfloat time = ClockObject::get_global_clock()->get_frame_time(); + t = LMatrix4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, time, time, time, time); + return &t; + } + case Shader::SMO_frame_delta: { + PN_stdfloat dt = ClockObject::get_global_clock()->get_dt(); + t = LMatrix4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dt, dt, dt, dt); + return &t; + } case Shader::SMO_texpad_x: { Texture *tex = _target_shader->get_shader_input_texture(name); nassertr(tex != 0, &LMatrix4::zeros_mat()); @@ -2463,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))); @@ -2791,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() { @@ -2800,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() { @@ -2810,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() { @@ -2820,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() { @@ -2830,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() { diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index ce2c41bc93..d5a5f08eec 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/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); diff --git a/panda/src/display/graphicsStateGuardian_ext.cxx b/panda/src/display/graphicsStateGuardian_ext.cxx new file mode 100644 index 0000000000..2f1c2d916e --- /dev/null +++ b/panda/src/display/graphicsStateGuardian_ext.cxx @@ -0,0 +1,55 @@ +// Filename: graphicsStateGuardian_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 "graphicsStateGuardian_ext.h" +#include "textureContext.h" + +#ifdef HAVE_PYTHON + +#ifndef CPPPARSER +IMPORT_THIS struct Dtool_PyTypedObject Dtool_Texture; +#endif + +static bool traverse_callback(TextureContext *tc, void *data) { + PT(Texture) tex = tc->get_texture(); + PyObject *element = + DTool_CreatePyInstanceTyped(tex, Dtool_Texture, + true, false, tex->get_type_index()); + tex->ref(); + + PyObject *list = (PyObject *) data; + PyList_Append(list, element); + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::get_prepared_textures +// Access: Published +// Description: Returns a Python list of all of the +// currently-prepared textures within the GSG. +//////////////////////////////////////////////////////////////////// +PyObject *Extension:: +get_prepared_textures() const { + PyObject *list = PyList_New(0); + + if (list == NULL) { + return NULL; + } + + _this->traverse_prepared_textures(&traverse_callback, (void *)list); + return list; +} + +#endif diff --git a/panda/src/display/graphicsStateGuardian_ext.h b/panda/src/display/graphicsStateGuardian_ext.h new file mode 100644 index 0000000000..cc1d9a3fe5 --- /dev/null +++ b/panda/src/display/graphicsStateGuardian_ext.h @@ -0,0 +1,40 @@ +// Filename: graphicsStateGuardian_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 GRAPHICSSTATEGUARDIAN_EXT_H +#define GRAPHICSSTATEGUARDIAN_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "extension.h" +#include "graphicsStateGuardian.h" +#include "py_panda.h" + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// Ramfile, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + PyObject *get_prepared_textures() const; +}; + +#endif // HAVE_PYTHON + +#endif // GRAPHICSSTATEGUARDIAN_EXT_H diff --git a/panda/src/display/graphicsWindowInputDevice.cxx b/panda/src/display/graphicsWindowInputDevice.cxx index d1fd8b4cfb..bbf49c10ee 100644 --- a/panda/src/display/graphicsWindowInputDevice.cxx +++ b/panda/src/display/graphicsWindowInputDevice.cxx @@ -366,3 +366,25 @@ focus_lost(double time) { } _buttons_held.clear(); } + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsWindowInputDevice::raw_button_down +// Access: Public +// Description: Records that the indicated button has been depressed. +//////////////////////////////////////////////////////////////////// +void GraphicsWindowInputDevice:: +raw_button_down(ButtonHandle button, double time) { + LightMutexHolder holder(_lock); + _button_events.push_back(ButtonEvent(button, ButtonEvent::T_raw_down, time)); +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsWindowInputDevice::raw_button_up +// Access: Public +// Description: Records that the indicated button has been released. +//////////////////////////////////////////////////////////////////// +void GraphicsWindowInputDevice:: +raw_button_up(ButtonHandle button, double time) { + LightMutexHolder holder(_lock); + _button_events.push_back(ButtonEvent(button, ButtonEvent::T_raw_up, time)); +} diff --git a/panda/src/display/graphicsWindowInputDevice.h b/panda/src/display/graphicsWindowInputDevice.h index 4ded5e964b..af66662e64 100644 --- a/panda/src/display/graphicsWindowInputDevice.h +++ b/panda/src/display/graphicsWindowInputDevice.h @@ -47,27 +47,27 @@ public: static GraphicsWindowInputDevice pointer_only(GraphicsWindow *host, const string &name); static GraphicsWindowInputDevice keyboard_only(GraphicsWindow *host, const string &name); static GraphicsWindowInputDevice pointer_and_keyboard(GraphicsWindow *host, const string &name); - + INLINE GraphicsWindowInputDevice(); GraphicsWindowInputDevice(const GraphicsWindowInputDevice ©); void operator = (const GraphicsWindowInputDevice ©); ~GraphicsWindowInputDevice(); - + INLINE string get_name() const; INLINE bool has_pointer() const; INLINE bool has_keyboard() const; INLINE void set_device_index(int index); - + INLINE MouseData get_pointer() const; INLINE MouseData get_raw_pointer() const; - + INLINE void enable_pointer_events(); INLINE void disable_pointer_events(); - + void enable_pointer_mode(double speed); void disable_pointer_mode(); - + bool has_button_event() const; ButtonEvent get_button_event(); bool has_pointer_event() const; @@ -83,6 +83,8 @@ PUBLISHED: void candidate(const wstring &candidate_string, size_t highlight_start, size_t highlight_end, size_t cursor_pos); void focus_lost(double time = ClockObject::get_global_clock()->get_frame_time()); + void raw_button_down(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time()); + void raw_button_up(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time()); INLINE void set_pointer_in_window(double x, double y, double time = ClockObject::get_global_clock()->get_frame_time()); INLINE void set_pointer_out_of_window(double time = ClockObject::get_global_clock()->get_frame_time()); @@ -104,17 +106,17 @@ private: typedef pdeque ButtonEvents; LightMutex _lock; - + GraphicsWindow *_host; - + string _name; int _flags; int _device_index; int _event_sequence; - + bool _pointer_mode_enable; double _pointer_speed; - + bool _enable_pointer_events; MouseData _mouse_data; MouseData _true_mouse_data; diff --git a/panda/src/egg/Sources.pp b/panda/src/egg/Sources.pp index 49757317ae..cc68e22b52 100644 --- a/panda/src/egg/Sources.pp +++ b/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 \ diff --git a/panda/src/egg/eggGroupNode.h b/panda/src/egg/eggGroupNode.h index 7e6bc358f9..ffdfcb304c 100644 --- a/panda/src/egg/eggGroupNode.h +++ b/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); diff --git a/panda/src/egg/eggGroupNode_ext.cxx b/panda/src/egg/eggGroupNode_ext.cxx new file mode 100644 index 0000000000..457ea73ba3 --- /dev/null +++ b/panda/src/egg/eggGroupNode_ext.cxx @@ -0,0 +1,51 @@ +// Filename: eggGroupNode_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 "eggGroupNode_ext.h" + +#ifdef HAVE_PYTHON + +IMPORT_THIS struct Dtool_PyTypedObject Dtool_EggNode; + +//////////////////////////////////////////////////////////////////// +// Function: EggGroupNode::get_children +// Access: Published +// Description: Returns a Python list containing the node's children. +//////////////////////////////////////////////////////////////////// +PyObject *Extension:: +get_children() const { + EggGroupNode::iterator it; + + // Create the Python list object. + EggGroupNode::size_type len = _this->size(); + PyObject *lst = PyList_New(len); + if (lst == NULL) { + return NULL; + } + + // Fill in the list. + int i = 0; + for (it = _this->begin(); it != _this->end() && i < len; ++it) { + EggNode *node = *it; + node->ref(); + PyObject *item = + DTool_CreatePyInstanceTyped((void *)node, Dtool_EggNode, true, false, node->get_type_index()); + + PyList_SET_ITEM(lst, i++, item); + } + + return lst; +} + +#endif // HAVE_PYTHON diff --git a/panda/src/egg/eggGroupNode_ext.h b/panda/src/egg/eggGroupNode_ext.h new file mode 100644 index 0000000000..ae29cc54b4 --- /dev/null +++ b/panda/src/egg/eggGroupNode_ext.h @@ -0,0 +1,40 @@ +// Filename: eggGroupNode_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 EGGGROUPNODE_EXT_H +#define EGGGROUPNODE_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "extension.h" +#include "eggGroupNode.h" +#include "py_panda.h" + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// EggGroupNode, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + PyObject *get_children() const; +}; + +#endif // HAVE_PYTHON + +#endif // EGGGROUPNODE_EXT_H diff --git a/panda/src/egg/eggParameters.h b/panda/src/egg/eggParameters.h index 788395612c..b813fd684b 100644 --- a/panda/src/egg/eggParameters.h +++ b/panda/src/egg/eggParameters.h @@ -58,6 +58,6 @@ public: double _table_threshold; }; -extern EggParameters *egg_parameters; +extern EXPCL_PANDAEGG EggParameters *egg_parameters; #endif diff --git a/panda/src/egldisplay/eglGraphicsWindow.cxx b/panda/src/egldisplay/eglGraphicsWindow.cxx index 9e82bac2e7..7ef3efb80e 100644 --- a/panda/src/egldisplay/eglGraphicsWindow.cxx +++ b/panda/src/egldisplay/eglGraphicsWindow.cxx @@ -1215,16 +1215,19 @@ handle_keypress(XKeyEvent &event) { // Now get the raw unshifted button. ButtonHandle button = get_button(event, false); - if (button == KeyboardButton::lcontrol() || button == KeyboardButton::rcontrol()) { - _input_devices[0].button_down(KeyboardButton::control()); - } - if (button == KeyboardButton::lshift() || button == KeyboardButton::rshift()) { - _input_devices[0].button_down(KeyboardButton::shift()); - } - if (button == KeyboardButton::lalt() || button == KeyboardButton::ralt()) { - _input_devices[0].button_down(KeyboardButton::alt()); - } if (button != ButtonHandle::none()) { + if (button == KeyboardButton::lcontrol() || button == KeyboardButton::rcontrol()) { + _input_devices[0].button_down(KeyboardButton::control()); + } + if (button == KeyboardButton::lshift() || button == KeyboardButton::rshift()) { + _input_devices[0].button_down(KeyboardButton::shift()); + } + if (button == KeyboardButton::lalt() || button == KeyboardButton::ralt()) { + _input_devices[0].button_down(KeyboardButton::alt()); + } + if (button == KeyboardButton::lmeta() || button == KeyboardButton::rmeta()) { + _input_devices[0].button_down(KeyboardButton::meta()); + } _input_devices[0].button_down(button); } } @@ -1241,16 +1244,19 @@ handle_keyrelease(XKeyEvent &event) { // Now get the raw unshifted button. ButtonHandle button = get_button(event, false); - if (button == KeyboardButton::lcontrol() || button == KeyboardButton::rcontrol()) { - _input_devices[0].button_up(KeyboardButton::control()); - } - if (button == KeyboardButton::lshift() || button == KeyboardButton::rshift()) { - _input_devices[0].button_up(KeyboardButton::shift()); - } - if (button == KeyboardButton::lalt() || button == KeyboardButton::ralt()) { - _input_devices[0].button_up(KeyboardButton::alt()); - } if (button != ButtonHandle::none()) { + if (button == KeyboardButton::lcontrol() || button == KeyboardButton::rcontrol()) { + _input_devices[0].button_up(KeyboardButton::control()); + } + if (button == KeyboardButton::lshift() || button == KeyboardButton::rshift()) { + _input_devices[0].button_up(KeyboardButton::shift()); + } + if (button == KeyboardButton::lalt() || button == KeyboardButton::ralt()) { + _input_devices[0].button_up(KeyboardButton::alt()); + } + if (button == KeyboardButton::lmeta() || button == KeyboardButton::rmeta()) { + _input_devices[0].button_up(KeyboardButton::meta()); + } _input_devices[0].button_up(button); } } @@ -1636,6 +1642,8 @@ map_button(KeySym key) { return KeyboardButton::print_screen(); case XK_Pause: return KeyboardButton::pause(); + case XK_Menu: + return KeyboardButton::menu(); case XK_Shift_L: return KeyboardButton::lshift(); case XK_Shift_R: @@ -1649,8 +1657,9 @@ map_button(KeySym key) { case XK_Alt_R: return KeyboardButton::ralt(); case XK_Meta_L: + return KeyboardButton::lmeta(); case XK_Meta_R: - return KeyboardButton::meta(); + return KeyboardButton::rmeta(); case XK_Caps_Lock: return KeyboardButton::caps_lock(); case XK_Shift_Lock: diff --git a/panda/src/event/buttonEvent.cxx b/panda/src/event/buttonEvent.cxx index 3a212f34a1..774b5ec0a6 100644 --- a/panda/src/event/buttonEvent.cxx +++ b/panda/src/event/buttonEvent.cxx @@ -55,6 +55,14 @@ output(ostream &out) const { case T_move: out << "move"; break; + + case T_raw_down: + out << "raw button " << _button << " down"; + break; + + case T_raw_up: + out << "raw button " << _button << " up"; + break; } } diff --git a/panda/src/event/buttonEvent.h b/panda/src/event/buttonEvent.h index 7469de0e82..adc395d405 100644 --- a/panda/src/event/buttonEvent.h +++ b/panda/src/event/buttonEvent.h @@ -81,10 +81,17 @@ public: // from a menu. T_candidate, - // T_move is used to indicate that the mouse has moved within the + // T_move is used to indicate that the mouse has moved within the // current region. Button drag mode needs this, others may ignore // this event T_move, + + // T_raw_down is usually sent together with T_down, except that + // this is the original, untransformed scan key sent by the keyboard. + // It is not altered by modifier keys and acts as if the user is + // using the US (qwerty) keyboard layout. + T_raw_down, + T_raw_up, }; INLINE ButtonEvent(); diff --git a/panda/src/event/pythonTask.cxx b/panda/src/event/pythonTask.cxx index d841cf4b35..4ae81b5a1a 100644 --- a/panda/src/event/pythonTask.cxx +++ b/panda/src/event/pythonTask.cxx @@ -159,7 +159,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); diff --git a/panda/src/express/Sources.pp b/panda/src/express/Sources.pp index e64467fbba..dcec931471 100644 --- a/panda/src/express/Sources.pp +++ b/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 \ diff --git a/panda/src/express/memoryUsagePointers.cxx b/panda/src/express/memoryUsagePointers.cxx index 3fffa0d898..4a590f3661 100644 --- a/panda/src/express/memoryUsagePointers.cxx +++ b/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 diff --git a/panda/src/express/memoryUsagePointers.h b/panda/src/express/memoryUsagePointers.h index 7192cea41f..ceab784752 100644 --- a/panda/src/express/memoryUsagePointers.h +++ b/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(); diff --git a/panda/src/express/memoryUsagePointers_ext.cxx b/panda/src/express/memoryUsagePointers_ext.cxx new file mode 100644 index 0000000000..eee3b5d0e6 --- /dev/null +++ b/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:: +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 diff --git a/panda/src/express/memoryUsagePointers_ext.h b/panda/src/express/memoryUsagePointers_ext.h new file mode 100644 index 0000000000..3b4e9c7478 --- /dev/null +++ b/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 +// Description : This class defines the extension methods for +// VirtualFileSystem, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + PyObject *get_python_pointer(int n) const; +}; + +#endif // HAVE_PYTHON && DO_MEMORY_USAGE + +#endif // MEMORYUSAGEPOINTERS_EXT_H diff --git a/panda/src/express/p3express_ext_composite.cxx b/panda/src/express/p3express_ext_composite.cxx new file mode 100644 index 0000000000..88dd271158 --- /dev/null +++ b/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" diff --git a/panda/src/express/ramfile.h b/panda/src/express/ramfile.h index 8f3dafe8cf..d8006400a4 100644 --- a/panda/src/express/ramfile.h +++ b/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; diff --git a/panda/src/express/ramfile_ext.cxx b/panda/src/express/ramfile_ext.cxx new file mode 100644 index 0000000000..366395df8d --- /dev/null +++ b/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:: +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 + diff --git a/panda/src/express/ramfile_ext.h b/panda/src/express/ramfile_ext.h new file mode 100644 index 0000000000..8f90eb52ad --- /dev/null +++ b/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 +// Description : This class defines the extension methods for +// Ramfile, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + BLOCKING PyObject *readlines(); +}; + +#endif // HAVE_PYTHON + +#endif // RAMFILE_EXT_H diff --git a/panda/src/express/streamReader_ext.cxx b/panda/src/express/streamReader_ext.cxx new file mode 100644 index 0000000000..c0aa00f26a --- /dev/null +++ b/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:: +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 + diff --git a/panda/src/express/streamReader_ext.h b/panda/src/express/streamReader_ext.h new file mode 100644 index 0000000000..dfc2e9f0b1 --- /dev/null +++ b/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 +// Description : This class defines the extension methods for +// StreamReader, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + BLOCKING PyObject *readlines(); +}; + +#endif // HAVE_PYTHON + +#endif // STREAMREADER_EXT_H diff --git a/panda/src/express/virtualFileSystem.cxx b/panda/src/express/virtualFileSystem.cxx index 69a32bd794..c21706e335 100644 --- a/panda/src/express/virtualFileSystem.cxx +++ b/panda/src/express/virtualFileSystem.cxx @@ -514,6 +514,7 @@ make_directory(const Filename &filename) { _lock.acquire(); PT(VirtualFile) result = do_get_file(filename, OF_make_directory); _lock.release(); + nassertr_always(result != NULL, false); return result->is_directory(); } @@ -542,6 +543,7 @@ make_directory_full(const Filename &filename) { // Now make the last one, and check the return value. PT(VirtualFile) result = do_get_file(filename, OF_make_directory); _lock.release(); + nassertr_always(result != NULL, false); return result->is_directory(); } diff --git a/panda/src/express/virtualFileSystem_ext.cxx b/panda/src/express/virtualFileSystem_ext.cxx index c5981b347a..3f1c3f40f8 100644 --- a/panda/src/express/virtualFileSystem_ext.cxx +++ b/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 diff --git a/panda/src/gles2gsg/gles2gsg.h b/panda/src/gles2gsg/gles2gsg.h index ec24b6d470..490d4da778 100644 --- a/panda/src/gles2gsg/gles2gsg.h +++ b/panda/src/gles2gsg/gles2gsg.h @@ -80,12 +80,22 @@ typedef char GLchar; #define GL_DEPTH_ATTACHMENT_EXT GL_DEPTH_ATTACHMENT #define GL_COLOR_ATTACHMENT0_EXT GL_COLOR_ATTACHMENT0 #define GL_STENCIL_ATTACHMENT_EXT GL_STENCIL_ATTACHMENT +#define GL_DEPTH_STENCIL GL_DEPTH_STENCIL_OES +#define GL_DEPTH_STENCIL_EXT GL_DEPTH_STENCIL_OES +#define GL_UNSIGNED_INT_24_8_EXT GL_UNSIGNED_INT_24_8_OES +#define GL_DEPTH24_STENCIL8_EXT GL_DEPTH24_STENCIL8_OES #define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES #define GL_DEPTH_COMPONENT32 GL_DEPTH_COMPONENT32_OES #define GL_TEXTURE_3D GL_TEXTURE_3D_OES #define GL_MAX_3D_TEXTURE_SIZE GL_MAX_3D_TEXTURE_SIZE_OES #define GL_SAMPLER_3D GL_SAMPLER_3D_OES #define GL_BGRA GL_BGRA_EXT +#define GL_RED GL_RED_EXT +#define GL_RG GL_RG_EXT +#define GL_R16F GL_R16F_EXT +#define GL_RG16F GL_RG16F_EXT +#define GL_RGB16F GL_RGB16F_EXT +#define GL_RGBA16F GL_RGBA16F_EXT #undef SUPPORT_IMMEDIATE_MODE #define APIENTRY diff --git a/panda/src/glstuff/glGraphicsBuffer_src.cxx b/panda/src/glstuff/glGraphicsBuffer_src.cxx index a036d703ca..82590c816b 100644 --- a/panda/src/glstuff/glGraphicsBuffer_src.cxx +++ b/panda/src/glstuff/glGraphicsBuffer_src.cxx @@ -559,15 +559,10 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot, } if (tex) { - GLenum target = glgsg->get_texture_target(tex->get_texture_type()); - if (target == GL_TEXTURE_CUBE_MAP) { - target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer; - } - // Bind the texture to the slot. tex->set_x_size(_rb_size_x); tex->set_y_size(_rb_size_y); - if (target != GL_TEXTURE_CUBE_MAP && _rb_size_z > 1) { + if (tex->get_texture_type() != Texture::TT_cube_map && _rb_size_z > 1) { tex->set_z_size(_rb_size_z); } tex->set_pad_size(_rb_size_x - _x_size, _rb_size_y - _y_size); @@ -617,85 +612,41 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot, } } - // Create the OpenGL texture object. - TextureContext *tc = tex->prepare_now(0, glgsg->get_prepared_objects(), glgsg); - nassertv(tc != (TextureContext *)NULL); - CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); - glgsg->update_texture(tc, true); +#ifndef OPENGLES + GLenum target = glgsg->get_texture_target(tex->get_texture_type()); + if (target == GL_TEXTURE_CUBE_MAP) { + target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer; + } +#endif if (attachpoint == GL_DEPTH_ATTACHMENT_EXT) { GLCAT.debug() << "Binding texture " << *tex << " to depth attachment.\n"; -#ifndef OPENGLES - GLclampf priority = 1.0f; - glPrioritizeTextures(1, >c->_index, &priority); -#endif - if (_rb_size_z == 1) { - if (target == GL_TEXTURE_3D) { - glgsg->_glFramebufferTexture3D(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, - target, gtc->_index, 0, layer); - } else if (target == GL_TEXTURE_2D_ARRAY_EXT) { - glgsg->_glFramebufferTextureLayer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, - gtc->_index, 0, layer); - } else { - glgsg->_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, - target, gtc->_index, 0); - } - } else { - glgsg->_glFramebufferTexture(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, - gtc->_index, 0); - } + attach_tex(layer, 0, tex, GL_DEPTH_ATTACHMENT_EXT); +#ifndef OPENGLES GLint depth_size = 0; GLP(GetTexLevelParameteriv)(target, 0, GL_TEXTURE_DEPTH_SIZE, &depth_size); _fb_properties.set_depth_bits(depth_size); +#endif if (slot == RTP_depth_stencil) { GLCAT.debug() << "Binding texture " << *tex << " to stencil attachment.\n"; - if (_rb_size_z == 1) { - if (target == GL_TEXTURE_3D) { - glgsg->_glFramebufferTexture3D(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, - target, gtc->_index, 0, layer); - } else if (target == GL_TEXTURE_2D_ARRAY_EXT) { - glgsg->_glFramebufferTextureLayer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, - gtc->_index, 0, layer); - } else { - glgsg->_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, - target, gtc->_index, 0); - } - } else { - glgsg->_glFramebufferTexture(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, - gtc->_index, 0); - } + attach_tex(layer, 0, tex, GL_STENCIL_ATTACHMENT_EXT); + +#ifndef OPENGLES GLint stencil_size = 0; GLP(GetTexLevelParameteriv)(target, 0, GL_TEXTURE_STENCIL_SIZE, &stencil_size); _fb_properties.set_stencil_bits(stencil_size); +#endif } } else { GLCAT.debug() << "Binding texture " << *tex << " to color attachment.\n"; -#ifndef OPENGLES - GLclampf priority = 1.0f; - glPrioritizeTextures(1, >c->_index, &priority); -#endif - glgsg->update_texture(tc, true); - if (_rb_size_z == 1) { - if (target == GL_TEXTURE_3D) { - glgsg->_glFramebufferTexture3D(GL_FRAMEBUFFER_EXT, attachpoint, - target, gtc->_index, 0, layer); - } else if (target == GL_TEXTURE_2D_ARRAY_EXT) { - glgsg->_glFramebufferTextureLayer(GL_FRAMEBUFFER_EXT, attachpoint, - gtc->_index, 0, layer); - } else { - glgsg->_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, attachpoint, - target, gtc->_index, 0); - } - } else { - glgsg->_glFramebufferTexture(GL_FRAMEBUFFER_EXT, attachpoint, - gtc->_index, 0); - } + attach_tex(layer, 0, tex, attachpoint); + #ifndef OPENGLES if (attachpoint == GL_COLOR_ATTACHMENT0_EXT) { GLint red_size = 0, green_size = 0, blue_size = 0, alpha_size = 0; @@ -749,16 +700,16 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot, gl_format = GL_RGB10_EXT; } } else if (_fb_properties.get_color_bits() == 0) { - gl_format = GL_ALPHA8_OES; + gl_format = GL_ALPHA8_EXT; } else if (_fb_properties.get_color_bits() <= 12 && _fb_properties.get_alpha_bits() <= 4) { gl_format = GL_RGBA4_OES; } else if (_fb_properties.get_color_bits() <= 15 && _fb_properties.get_alpha_bits() == 1) { - gl_format = GL_RGB5_A1_EXT; + gl_format = GL_RGB5_A1_OES; } else if (_fb_properties.get_color_bits() <= 30 && _fb_properties.get_alpha_bits() <= 2) { - gl_format = GL_RGB10_A2_OES; + gl_format = GL_RGB10_A2_EXT; } else { gl_format = GL_RGBA8_OES; } @@ -1000,6 +951,61 @@ bind_slot_multisample(bool rb_resize, Texture **attach, RenderTexturePlane slot, glgsg->report_my_gl_errors(); } +//////////////////////////////////////////////////////////////////// +// Function: glGraphicsBuffer::attach_tex +// Access: Private +// Description: This function attaches the given texture to the +// given attachment point. +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsBuffer):: +attach_tex(int layer, int view, Texture *attach, GLenum attachpoint) { + CLP(GraphicsStateGuardian) *glgsg; + DCAST_INTO_V(glgsg, _gsg); + + // Create the OpenGL texture object. + TextureContext *tc = attach->prepare_now(view, glgsg->get_prepared_objects(), glgsg); + nassertv(tc != (TextureContext *)NULL); + CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); + glgsg->update_texture(tc, true); + +#ifndef OPENGLES + GLclampf priority = 1.0f; + glPrioritizeTextures(1, >c->_index, &priority); +#endif + +#ifndef OPENGLES + if (_rb_size_z != 1) { + // Bind all of the layers of the texture. + glgsg->_glFramebufferTexture(GL_FRAMEBUFFER_EXT, attachpoint, + gtc->_index, 0); + return; + } +#endif + + GLenum target = glgsg->get_texture_target(attach->get_texture_type()); + if (target == GL_TEXTURE_CUBE_MAP) { + target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer; + } + + switch (target) { +#ifndef OPENGLES_1 + case GL_TEXTURE_3D: + glgsg->_glFramebufferTexture3D(GL_FRAMEBUFFER_EXT, attachpoint, + target, gtc->_index, 0, layer); + break; +#endif +#ifndef OPENGLES + case GL_TEXTURE_2D_ARRAY_EXT: + glgsg->_glFramebufferTextureLayer(GL_FRAMEBUFFER_EXT, attachpoint, + gtc->_index, 0, layer); + break; +#endif + default: + glgsg->_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, attachpoint, + target, gtc->_index, 0); + } +} + //////////////////////////////////////////////////////////////////// // Function: glGraphicsBuffer::generate_mipmaps // Access: Private @@ -1129,44 +1135,13 @@ select_target_tex_page(int page, int view) { tex->set_num_views(view + 1); } - GLenum target = glgsg->get_texture_target(tex->get_texture_type()); - if (target == GL_TEXTURE_CUBE_MAP) { - target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + _bound_tex_page; - } - - // Create the OpenGL texture object. - TextureContext *tc = tex->prepare_now(view, glgsg->get_prepared_objects(), glgsg); - nassertv(tc != (TextureContext *)NULL); - CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); - glgsg->update_texture(tc, true); - if (GLCAT.is_spam()) { GLCAT.spam() << "Binding texture " << *tex << " view " << view << " to color attachment.\n"; } -#ifndef OPENGLES - GLclampf priority = 1.0f; - glPrioritizeTextures(1, >c->_index, &priority); -#endif - glgsg->update_texture(tc, true); - - if (_rb_size_z == 1) { - if (target == GL_TEXTURE_3D) { - glgsg->_glFramebufferTexture3D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, - target, gtc->_index, 0, _bound_tex_page); - } else if (target == GL_TEXTURE_2D_ARRAY_EXT) { - glgsg->_glFramebufferTextureLayer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, - gtc->_index, 0, _bound_tex_page); - } else { - glgsg->_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, - target, gtc->_index, 0); - } - } else { - glgsg->_glFramebufferTexture(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, - gtc->_index, 0); - } + attach_tex(_bound_tex_page, view, tex, GL_COLOR_ATTACHMENT0_EXT); report_my_gl_errors(); } diff --git a/panda/src/glstuff/glGraphicsBuffer_src.h b/panda/src/glstuff/glGraphicsBuffer_src.h index 21850b2cb6..bf4c0d0c51 100644 --- a/panda/src/glstuff/glGraphicsBuffer_src.h +++ b/panda/src/glstuff/glGraphicsBuffer_src.h @@ -98,6 +98,7 @@ private: RenderTexturePlane plane, GLenum attachpoint); void bind_slot_multisample(bool rb_resize, Texture **attach, RenderTexturePlane plane, GLenum attachpoint); + void attach_tex(int layer, int view, Texture *attach, GLenum attachpoint); bool check_fbo(); void generate_mipmaps(); void rebuild_bitplanes(); diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index cfeaaea617..5135fcab92 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -1106,7 +1106,7 @@ reset() { _glGetShaderInfoLog = glGetShaderInfoLog; _glGetUniformLocation = glGetUniformLocation; _glLinkProgram = glLinkProgram; - _glShaderSource = glShaderSource; + _glShaderSource = (PFNGLSHADERSOURCEPROC_P) glShaderSource; _glUseProgram = glUseProgram; _glUniform4f = glUniform4f; _glUniform1i = glUniform1i; @@ -6405,8 +6405,10 @@ get_external_image_format(Texture *tex) const { #endif case Texture::F_alpha: return GL_ALPHA; +#ifndef OPENGLES_1 case Texture::F_rg16: return GL_RG; +#endif case Texture::F_rgb: case Texture::F_rgb5: case Texture::F_rgb8: @@ -6681,8 +6683,10 @@ get_internal_image_format(Texture *tex) const { return GL_RGBA8_OES; case Texture::F_rgba12: return GL_RGBA; +#ifndef OPENGLES_1 case Texture::F_rgba16: return GL_RGBA16F_EXT; +#endif // OPENGLES_1 case Texture::F_rgba32: return GL_RGBA32F_EXT; #else @@ -6733,12 +6737,12 @@ get_internal_image_format(Texture *tex) const { return GL_R3_G3_B2; #endif -#ifdef OPENGLES +#if defined(OPENGLES_2) case Texture::F_r16: return GL_R16F_EXT; case Texture::F_rg16: return GL_RG16F_EXT; -#else +#elif !defined(OPENGLES_1) case Texture::F_r16: if (tex->get_component_type() == Texture::T_float) { return GL_R16F; @@ -6756,10 +6760,12 @@ get_internal_image_format(Texture *tex) const { case Texture::F_alpha: return GL_ALPHA; +#ifndef OPENGLES_1 case Texture::F_red: case Texture::F_green: case Texture::F_blue: return GL_RED; +#endif case Texture::F_luminance: return GL_LUMINANCE; @@ -9333,9 +9339,11 @@ upload_texture_image(CLP(TextureContext) *gtc, break; case GL_TEXTURE_2D_ARRAY: #endif +#ifndef OPENGLES_1 case GL_TEXTURE_3D: _glTexImage3D(page_target, 0, internal_format, width, height, depth, 0, external_format, component_type, NULL); break; +#endif default: GLP(TexImage2D)(page_target, 0, internal_format, width, height, 0, external_format, component_type, NULL); break; @@ -9817,10 +9825,12 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { type = Texture::T_unsigned_short; format = Texture::F_depth_component; break; +#ifndef OPENGLES case GL_DEPTH_COMPONENT32F: type = Texture::T_float; format = Texture::F_depth_component; break; +#endif case GL_DEPTH_STENCIL_EXT: case GL_DEPTH24_STENCIL8_EXT: type = Texture::T_unsigned_int_24_8; @@ -9848,10 +9858,6 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { format = Texture::F_rgba12; break; #endif - case GL_RGBA16F: - type = Texture::T_float; - format = Texture::F_rgba16; - break; case GL_RGB: case 3: @@ -9877,6 +9883,11 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { break; #endif +#ifndef OPENGLES_1 + case GL_RGBA16F: + type = Texture::T_float; + format = Texture::F_rgba16; + break; case GL_RGB16F: type = Texture::T_float; format = Texture::F_rgb16; @@ -9889,6 +9900,7 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { type = Texture::T_float; format = Texture::F_r16; break; +#endif #ifndef OPENGLES case GL_RGB16: diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index 281ab0cef9..c5abad0675 100755 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -71,14 +71,13 @@ TypeHandle CLP(ShaderContext)::_type_handle; bool CLP(ShaderContext):: parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, Shader *objShader) { Shader::ShaderArgInfo p; - p._id = arg_id; - + string basename(arg_id._name); // Split it at the underscores. vector_string pieces; tokenize(basename, pieces, "_"); - + if (pieces[0] == "mstrans") { pieces[0] = "trans"; pieces.push_back("to"); @@ -119,9 +118,9 @@ parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, Shader *objSha pieces.push_back("to"); pieces.push_back("clip"); } - - if ((pieces[0] == "mat")||(pieces[0] == "inv")|| - (pieces[0] == "tps")||(pieces[0] == "itp")) { + + if ((pieces[0] == "mat") || (pieces[0] == "inv") || + (pieces[0] == "tps") || (pieces[0] == "itp")) { if (!objShader->cp_errchk_parameter_words(p, 2)) { return false; } @@ -138,33 +137,33 @@ parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, Shader *objSha objShader->cp_report_error(p,"unrecognized matrix name"); return false; } - if (trans=="mat") { + if (trans == "mat") { pieces[0] = "trans"; - } else if (trans=="inv") { + } else if (trans == "inv") { string t = pieces[1]; pieces[1] = pieces[3]; pieces[3] = t; - } else if (trans=="tps") { + } else if (trans == "tps") { pieces[0] = "tpose"; - } else if (trans=="itp") { + } else if (trans == "itp") { string t = pieces[1]; pieces[1] = pieces[3]; pieces[3] = t; pieces[0] = "tpose"; - } + } } // Implement the transform-matrix generator. - if ((pieces[0]=="trans")|| - (pieces[0]=="tpose")|| - (pieces[0]=="row0")|| - (pieces[0]=="row1")|| - (pieces[0]=="row2")|| - (pieces[0]=="row3")|| - (pieces[0]=="col0")|| - (pieces[0]=="col1")|| - (pieces[0]=="col2")|| - (pieces[0]=="col3")) { + if ((pieces[0] == "trans") || + (pieces[0] == "tpose") || + (pieces[0] == "row0") || + (pieces[0] == "row1") || + (pieces[0] == "row2") || + (pieces[0] == "row3") || + (pieces[0] == "col0") || + (pieces[0] == "col1") || + (pieces[0] == "col2") || + (pieces[0] == "col3")) { Shader::ShaderMatSpec bind; bind._id = arg_id; @@ -174,27 +173,26 @@ parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, Shader *objSha pieces.push_back(""); // Decide whether this is a matrix or vector. - if (pieces[0]=="trans") bind._piece = Shader::SMP_whole; - else if (pieces[0]=="tpose") bind._piece = Shader::SMP_transpose; - else if (pieces[0]=="row0") bind._piece = Shader::SMP_row0; - else if (pieces[0]=="row1") bind._piece = Shader::SMP_row1; - else if (pieces[0]=="row2") bind._piece = Shader::SMP_row2; - else if (pieces[0]=="row3") bind._piece = Shader::SMP_row3; - else if (pieces[0]=="col0") bind._piece = Shader::SMP_col0; - else if (pieces[0]=="col1") bind._piece = Shader::SMP_col1; - else if (pieces[0]=="col2") bind._piece = Shader::SMP_col2; - else if (pieces[0]=="col3") bind._piece = Shader::SMP_col3; + if (pieces[0] == "trans") bind._piece = Shader::SMP_whole; + else if (pieces[0] == "tpose") bind._piece = Shader::SMP_transpose; + else if (pieces[0] == "row0") bind._piece = Shader::SMP_row0; + else if (pieces[0] == "row1") bind._piece = Shader::SMP_row1; + else if (pieces[0] == "row2") bind._piece = Shader::SMP_row2; + else if (pieces[0] == "row3") bind._piece = Shader::SMP_row3; + else if (pieces[0] == "col0") bind._piece = Shader::SMP_col0; + else if (pieces[0] == "col1") bind._piece = Shader::SMP_col1; + else if (pieces[0] == "col2") bind._piece = Shader::SMP_col2; + else if (pieces[0] == "col3") bind._piece = Shader::SMP_col3; if (!objShader->cp_parse_coord_sys(p, pieces, next, bind, true)) { return false; } if (!objShader->cp_parse_delimiter(p, pieces, next)) { return false; - } + } if (!objShader->cp_parse_coord_sys(p, pieces, next, bind, false)) { return false; } - if (!objShader->cp_parse_eol(p, pieces, next)) { return false; } @@ -223,51 +221,58 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { #if defined(HAVE_CG) && !defined(OPENGLES) _cg_context = 0; + _cg_vprofile = CG_PROFILE_UNKNOWN; + _cg_fprofile = CG_PROFILE_UNKNOWN; + _cg_gprofile = CG_PROFILE_UNKNOWN; if (s->get_language() == Shader::SL_Cg) { - // Ask the shader to compile itself for us and // to give us the resulting Cg program objects. if (!s->cg_compile_for(gsg->_shader_caps, _cg_context, _cg_vprogram, - _cg_fprogram, + _cg_fprogram, _cg_gprogram, _cg_parameter_map)) { return; } - + // Load the program. - if (_cg_vprogram != 0) { + _cg_vprofile = cgGetProgramProfile(_cg_vprogram); cgGLLoadProgram(_cg_vprogram); CGerror verror = cgGetError(); if (verror != CG_NO_ERROR) { - const char *str = (const char *)GLP(GetString)(GL_PROGRAM_ERROR_STRING_ARB); - GLCAT.error() << "Could not load Cg vertex program:" << s->get_filename(Shader::ST_vertex) << " (" << - cgGetProfileString(cgGetProgramProfile(_cg_vprogram)) << " " << str << ")\n"; + const char *str = cgGetErrorString(verror); + GLCAT.error() + << "Could not load Cg vertex program: " << s->get_filename(Shader::ST_vertex) + << " (" << cgGetProfileString(_cg_vprofile) << " " << str << ")\n"; release_resources(gsg); } } if (_cg_fprogram != 0) { + _cg_fprofile = cgGetProgramProfile(_cg_fprogram); cgGLLoadProgram(_cg_fprogram); CGerror ferror = cgGetError(); if (ferror != CG_NO_ERROR) { - const char *str = (const char *)GLP(GetString)(GL_PROGRAM_ERROR_STRING_ARB); - GLCAT.error() << "Could not load Cg fragment program:" << s->get_filename(Shader::ST_fragment) << " (" << - cgGetProfileString(cgGetProgramProfile(_cg_fprogram)) << " " << str << ")\n"; + const char *str = cgGetErrorString(ferror); + GLCAT.error() + << "Could not load Cg fragment program: " << s->get_filename(Shader::ST_fragment) + << " (" << cgGetProfileString(_cg_fprofile) << " " << str << ")\n"; release_resources(gsg); } } if (_cg_gprogram != 0) { + _cg_gprofile = cgGetProgramProfile(_cg_gprogram); cgGLLoadProgram(_cg_gprogram); CGerror gerror = cgGetError(); if (gerror != CG_NO_ERROR) { - const char *str = (const char *)GLP(GetString)(GL_PROGRAM_ERROR_STRING_ARB); - GLCAT.error() << "Could not load Cg geometry program:" << s->get_filename(Shader::ST_geometry) << " (" << - cgGetProfileString(cgGetProgramProfile(_cg_gprogram)) << " " << str << ")\n"; + const char *str = cgGetErrorString(gerror); + GLCAT.error() + << "Could not load Cg geometry program: " << s->get_filename(Shader::ST_geometry) + << " (" << cgGetProfileString(_cg_gprofile) << " " << str << ")\n"; release_resources(gsg); } } @@ -338,7 +343,7 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { } bind._arg[0] = NULL; bind._arg[1] = NULL; - + if (matrix_name == "ModelViewProjectionMatrix") { bind._func = Shader::SMF_compose; if (inverse) { @@ -418,15 +423,14 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { // them as well, to increase compatibility. // Other inputs we may support in the future: // int osg_FrameNumber - // float osg_FrameTime - // float osg_DeltaFrameTime + + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._arg[0] = NULL; + bind._arg[1] = NULL; if (param_name == "osg_ViewMatrix") { - Shader::ShaderMatSpec bind; - bind._id = arg_id; bind._piece = Shader::SMP_whole; - bind._arg[0] = NULL; - bind._arg[1] = NULL; bind._func = Shader::SMF_first; bind._part[0] = Shader::SMO_world_to_view; bind._part[1] = Shader::SMO_identity; @@ -436,11 +440,7 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { continue; } else if (param_name == "osg_InverseViewMatrix") { - Shader::ShaderMatSpec bind; - bind._id = arg_id; bind._piece = Shader::SMP_whole; - bind._arg[0] = NULL; - bind._arg[1] = NULL; bind._func = Shader::SMF_first; bind._part[0] = Shader::SMO_view_to_world; bind._part[1] = Shader::SMO_identity; @@ -448,6 +448,26 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { bind._dep[1] = Shader::SSD_NONE; s->_mat_spec.push_back(bind); continue; + + } else if (param_name == "osg_FrameTime") { + bind._piece = Shader::SMP_row3x1; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_frame_time; + bind._part[1] = Shader::SMO_identity; + bind._dep[0] = Shader::SSD_general; + bind._dep[1] = Shader::SSD_NONE; + s->_mat_spec.push_back(bind); + continue; + + } else if (param_name == "osg_DeltaFrameTime") { + bind._piece = Shader::SMP_row3x1; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_frame_delta; + bind._part[1] = Shader::SMO_identity; + bind._dep[0] = Shader::SSD_general; + bind._dep[1] = Shader::SSD_NONE; + s->_mat_spec.push_back(bind); + continue; } } @@ -455,7 +475,7 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { if (parse_and_set_short_hand_shader_vars(arg_id, s)) { continue; } - + if (param_size == 1) { switch (param_type) { #ifndef OPENGLES @@ -706,7 +726,7 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { } } } - + gsg->report_my_gl_errors(); } @@ -819,15 +839,15 @@ bind(GSG *gsg, bool reissue_parameters) { if (_cg_context != 0) { // Bind the shaders. if (_cg_vprogram != 0) { - cgGLEnableProfile(cgGetProgramProfile(_cg_vprogram)); + cgGLEnableProfile(_cg_vprofile); cgGLBindProgram(_cg_vprogram); } if (_cg_fprogram != 0) { - cgGLEnableProfile(cgGetProgramProfile(_cg_fprogram)); + cgGLEnableProfile(_cg_fprofile); cgGLBindProgram(_cg_fprogram); } if (_cg_gprogram != 0) { - cgGLEnableProfile(cgGetProgramProfile(_cg_gprogram)); + cgGLEnableProfile(_cg_gprofile); cgGLBindProgram(_cg_gprogram); } @@ -850,19 +870,22 @@ unbind(GSG *gsg) { #if defined(HAVE_CG) && !defined(OPENGLES) if (_cg_context != 0) { if (_cg_vprogram != 0) { - cgGLDisableProfile(cgGetProgramProfile(_cg_vprogram)); + cgGLUnbindProgram(_cg_vprofile); + cgGLDisableProfile(_cg_vprofile); } if (_cg_fprogram != 0) { - cgGLDisableProfile(cgGetProgramProfile(_cg_fprogram)); + cgGLUnbindProgram(_cg_fprofile); + cgGLDisableProfile(_cg_fprofile); } if (_cg_gprogram != 0) { - cgGLDisableProfile(cgGetProgramProfile(_cg_gprogram)); + cgGLUnbindProgram(_cg_gprofile); + cgGLDisableProfile(_cg_gprofile); } cg_report_errors(); } #endif - + if (_shader->get_language() == Shader::SL_GLSL) { gsg->_glUseProgram(0); } @@ -1162,12 +1185,13 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg, } } #endif - + InternalName *name = _shader->_var_spec[i]._name; int texslot = _shader->_var_spec[i]._append_uv; if (texslot >= 0 && texslot < gsg->_state_texture->get_num_on_stages()) { TextureStage *stage = gsg->_state_texture->get_on_stage(texslot); InternalName *texname = stage->get_texcoord_name(); + if (name == InternalName::get_texcoord()) { name = texname; } else if (texname != InternalName::get_texcoord()) { diff --git a/panda/src/glstuff/glShaderContext_src.h b/panda/src/glstuff/glShaderContext_src.h index 3d56e72002..cb5d1a0065 100755 --- a/panda/src/glstuff/glShaderContext_src.h +++ b/panda/src/glstuff/glShaderContext_src.h @@ -21,6 +21,10 @@ #include "shaderContext.h" #include "deletedChain.h" +#if defined(HAVE_CG) && !defined(OPENGLES) +#include +#endif + class CLP(GraphicsStateGuardian); //////////////////////////////////////////////////////////////////// @@ -57,10 +61,13 @@ private: CGprogram _cg_vprogram; CGprogram _cg_fprogram; CGprogram _cg_gprogram; + CGprofile _cg_vprofile; + CGprofile _cg_fprofile; + CGprofile _cg_gprofile; pvector _cg_parameter_map; #endif - + GLuint _glsl_program; GLuint _glsl_vshader; GLuint _glsl_fshader; diff --git a/panda/src/gobj/internalName.cxx b/panda/src/gobj/internalName.cxx index 703b12dc9e..8ee046338f 100644 --- a/panda/src/gobj/internalName.cxx +++ b/panda/src/gobj/internalName.cxx @@ -154,6 +154,25 @@ get_name() const { } } +//////////////////////////////////////////////////////////////////// +// Function: InternalName::join +// Access: Published +// Description: Like get_name, but uses a custom separator instead +// of ".". +//////////////////////////////////////////////////////////////////// +string InternalName:: +join(const string &sep) const { + if (_parent == get_root()) { + return _basename; + + } else if (_parent == (InternalName *)NULL) { + return string(); + + } else { + return _parent->join(sep) + sep + _basename; + } +} + //////////////////////////////////////////////////////////////////// // Function: InternalName::find_ancestor // Access: Published diff --git a/panda/src/gobj/internalName.h b/panda/src/gobj/internalName.h index 88ad2fdda4..7c3c42e259 100644 --- a/panda/src/gobj/internalName.h +++ b/panda/src/gobj/internalName.h @@ -53,6 +53,7 @@ PUBLISHED: INLINE InternalName *get_parent() const; string get_name() const; + string join(const string &sep) const; INLINE const string &get_basename() const; int find_ancestor(const string &basename) const; diff --git a/panda/src/gobj/shader.cxx b/panda/src/gobj/shader.cxx index 8807206409..675fbca876 100755 --- a/panda/src/gobj/shader.cxx +++ b/panda/src/gobj/shader.cxx @@ -414,23 +414,23 @@ cp_dependency(ShaderMatInput inp) { (inp == SMO_view_to_model)) { dep |= SSD_transform; } - if ((inp == SMO_texpad_x)|| - (inp == SMO_texpix_x)|| - (inp == SMO_alight_x)|| - (inp == SMO_dlight_x)|| - (inp == SMO_plight_x)|| - (inp == SMO_slight_x)|| - (inp == SMO_satten_x)|| - (inp == SMO_mat_constant_x)|| - (inp == SMO_vec_constant_x)|| - (inp == SMO_clipplane_x)|| - (inp == SMO_view_x_to_view)|| - (inp == SMO_view_to_view_x)|| - (inp == SMO_apiview_x_to_view)|| - (inp == SMO_view_to_apiview_x)|| - (inp == SMO_clip_x_to_view)|| - (inp == SMO_view_to_clip_x)|| - (inp == SMO_apiclip_x_to_view)|| + if ((inp == SMO_texpad_x) || + (inp == SMO_texpix_x) || + (inp == SMO_alight_x) || + (inp == SMO_dlight_x) || + (inp == SMO_plight_x) || + (inp == SMO_slight_x) || + (inp == SMO_satten_x) || + (inp == SMO_mat_constant_x) || + (inp == SMO_vec_constant_x) || + (inp == SMO_clipplane_x) || + (inp == SMO_view_x_to_view) || + (inp == SMO_view_to_view_x) || + (inp == SMO_apiview_x_to_view) || + (inp == SMO_view_to_apiview_x) || + (inp == SMO_clip_x_to_view) || + (inp == SMO_view_to_clip_x) || + (inp == SMO_apiclip_x_to_view) || (inp == SMO_view_to_apiclip_x)) { dep |= SSD_shaderinputs; } @@ -588,36 +588,45 @@ compile_parameter(const ShaderArgId &arg_id, } ShaderVarSpec bind; bind._id = arg_id; + bind._append_uv = -1; + if (pieces.size() == 2) { - if (pieces[1]=="position") { + if (pieces[1] == "position") { bind._name = InternalName::get_vertex(); bind._append_uv = -1; _var_spec.push_back(bind); return true; } - if (pieces[1].substr(0,8)=="texcoord") { + if (pieces[1].substr(0, 8) == "texcoord") { bind._name = InternalName::get_texcoord(); - bind._append_uv = atoi(pieces[1].c_str()+8); + if (pieces[1].size() > 8) { + bind._append_uv = atoi(pieces[1].c_str() + 8); + } _var_spec.push_back(bind); return true; } - if (pieces[1].substr(0,7)=="tangent") { + if (pieces[1].substr(0, 7) == "tangent") { bind._name = InternalName::get_tangent(); - bind._append_uv = atoi(pieces[1].c_str()+7); + if (pieces[1].size() > 7) { + bind._append_uv = atoi(pieces[1].c_str() + 7); + } _var_spec.push_back(bind); return true; } - if (pieces[1].substr(0,8)=="binormal") { + if (pieces[1].substr(0, 8) == "binormal") { bind._name = InternalName::get_binormal(); - bind._append_uv = atoi(pieces[1].c_str()+8); + if (pieces[1].size() > 8) { + bind._append_uv = atoi(pieces[1].c_str() + 8); + } _var_spec.push_back(bind); return true; } } + bind._name = InternalName::get_root(); - bind._append_uv = -1; - for (int i=1; i<(int)(pieces.size()-0); i++) + for (int i = 1; i < pieces.size(); ++i) { bind._name = bind._name->append(pieces[i]); + } _var_spec.push_back(bind); return true; } @@ -1008,7 +1017,7 @@ compile_parameter(const ShaderArgId &arg_id, // Keywords to access unusual parameters. if (pieces[0] == "sys") { - if ((!cp_errchk_parameter_words(p,2)) || + if ((!cp_errchk_parameter_words(p, 2)) || (!cp_errchk_parameter_in(p)) || (!cp_errchk_parameter_uniform(p))) { return false; @@ -1025,14 +1034,24 @@ compile_parameter(const ShaderArgId &arg_id, } bind._part[0] = SMO_pixel_size; bind._arg[0] = NULL; + } else if (pieces[1] == "windowsize") { if (!cp_errchk_parameter_float(p, 2, 2)) { return false; } bind._part[0] = SMO_window_size; bind._arg[0] = NULL; + + } else if (pieces[1] == "time") { + if (!cp_errchk_parameter_float(p, 1, 1)) { + return false; + } + bind._piece = SMP_row3x1; + bind._part[0] = SMO_frame_time; + bind._arg[0] = NULL; + } else { - cp_report_error(p,"unknown system parameter"); + cp_report_error(p, "unknown system parameter"); return false; } diff --git a/panda/src/gobj/shader.h b/panda/src/gobj/shader.h index 50249dccaa..365ee0df74 100755 --- a/panda/src/gobj/shader.h +++ b/panda/src/gobj/shader.h @@ -31,7 +31,7 @@ #include "pta_LVecBase2.h" #ifdef HAVE_CG -// I don't want to include the Cg header file into panda as a +// I don't want to include the Cg header file into panda as a // whole. Instead, I'll just excerpt some opaque declarations. typedef struct _CGcontext *CGcontext; typedef struct _CGprogram *CGprogram; @@ -41,8 +41,8 @@ typedef struct _CGparameter *CGparameter; //////////////////////////////////////////////////////////////////// // Class : Shader // Summary: The Shader class is meant to select the Shader Language, -// select the available profile, compile the shader, and -// finally compile and store the shader parameters +// select the available profile, compile the shader, and +// finally compile and store the shader parameters // in the appropriate structure. //////////////////////////////////////////////////////////////////// class EXPCL_PANDA_GOBJ Shader : public TypedWritableReferenceCount { @@ -116,11 +116,11 @@ public: SMO_pixel_size, SMO_texpad_x, SMO_texpix_x, - + SMO_attr_material, SMO_attr_color, SMO_attr_colorscale, - + SMO_alight_x, SMO_dlight_x, SMO_plight_x, @@ -129,7 +129,7 @@ public: SMO_texmat_x, SMO_plane_x, SMO_clipplane_x, - + SMO_mat_constant_x, SMO_vec_constant_x, @@ -147,7 +147,7 @@ public: SMO_apiclip_to_view, SMO_view_to_apiclip, - + SMO_view_x_to_view, SMO_view_to_view_x, @@ -162,11 +162,15 @@ public: SMO_attr_fog, SMO_attr_fogcolor, - + + SMO_frame_number, + SMO_frame_time, + SMO_frame_delta, + SMO_INVALID }; - - enum ShaderArgClass { + + enum ShaderArgClass { SAC_scalar, SAC_vector, SAC_matrix, @@ -174,28 +178,28 @@ public: SAC_array, SAC_unknown, }; - - enum ShaderArgType { - SAT_scalar, - SAT_vec1, - SAT_vec2, - SAT_vec3, - SAT_vec4, - SAT_mat1x1, - SAT_mat1x2, - SAT_mat1x3, + + enum ShaderArgType { + SAT_scalar, + SAT_vec1, + SAT_vec2, + SAT_vec3, + SAT_vec4, + SAT_mat1x1, + SAT_mat1x2, + SAT_mat1x3, SAT_mat1x4, SAT_mat2x1, - SAT_mat2x2, - SAT_mat2x3, - SAT_mat2x4, - SAT_mat3x1, - SAT_mat3x2, - SAT_mat3x3, - SAT_mat3x4, - SAT_mat4x1, - SAT_mat4x2, - SAT_mat4x3, + SAT_mat2x2, + SAT_mat2x3, + SAT_mat2x4, + SAT_mat3x1, + SAT_mat3x2, + SAT_mat3x3, + SAT_mat3x4, + SAT_mat4x1, + SAT_mat4x2, + SAT_mat4x3, SAT_mat4x4, SAT_sampler1d, SAT_sampler2d, @@ -231,20 +235,20 @@ public: }; enum ShaderStateDep { - SSD_NONE = 0, - SSD_general = 1, - SSD_transform = 2, - SSD_color = 4, - SSD_colorscale = 8, - SSD_material = 16, - SSD_shaderinputs = 32, - SSD_fog = 64, + SSD_NONE = 0x000, + SSD_general = 0x001, + SSD_transform = 0x002, + SSD_color = 0x004, + SSD_colorscale = 0x008, + SSD_material = 0x010, + SSD_shaderinputs = 0x020, + SSD_fog = 0x040, }; enum ShaderBug { SBUG_ati_draw_buffers, }; - + enum ShaderMatFunc { SMF_compose, SMF_transform_dlight, @@ -252,36 +256,36 @@ public: SMF_transform_slight, SMF_first, }; - + struct ShaderArgId { string _name; ShaderType _type; int _seqno; - }; - - struct ShaderArgInfo { + }; + + struct ShaderArgInfo { ShaderArgId _id; ShaderArgClass _class; ShaderArgClass _subclass; - ShaderArgType _type; + ShaderArgType _type; ShaderArgDir _direction; bool _varying; NotifyCategory *_cat; }; - + enum ShaderPtrType { SPT_float, SPT_double, SPT_unknown - }; - + }; + // Container structure for data of parameters ShaderPtrSpec. struct ShaderPtrData { private: PT(ReferenceCount) _pta; public: - void *_ptr; + void *_ptr; ShaderPtrType _type; bool _updated; int _size; //number of elements vec3[4]=12 @@ -340,8 +344,8 @@ public: PT(InternalName) _name; int _append_uv; }; - - struct ShaderPtrSpec { + + struct ShaderPtrSpec { ShaderArgId _id; int _dim[3]; //n_elements,rows,cols int _dep[2]; @@ -377,8 +381,8 @@ public: public: INLINE ShaderFile() {}; INLINE ShaderFile(const string &shared); - INLINE ShaderFile(const string &vertex, - const string &fragment, + INLINE ShaderFile(const string &vertex, + const string &fragment, const string &geometry, const string &tess_control, const string &tess_evaluation); @@ -405,18 +409,18 @@ public: void parse_upto(string &result, string pattern, bool include); void parse_rest(string &result); bool parse_eof(); - + void cp_report_error(ShaderArgInfo &arg, const string &msg); bool cp_errchk_parameter_words(ShaderArgInfo &arg, int len); bool cp_errchk_parameter_in(ShaderArgInfo &arg); - bool cp_errchk_parameter_ptr(ShaderArgInfo &p); + bool cp_errchk_parameter_ptr(ShaderArgInfo &p); bool cp_errchk_parameter_varying(ShaderArgInfo &arg); bool cp_errchk_parameter_uniform(ShaderArgInfo &arg); bool cp_errchk_parameter_float(ShaderArgInfo &arg, int lo, int hi); bool cp_errchk_parameter_sampler(ShaderArgInfo &arg); bool cp_parse_eol(ShaderArgInfo &arg, vector_string &pieces, int &next); - bool cp_parse_delimiter(ShaderArgInfo &arg, + bool cp_parse_delimiter(ShaderArgInfo &arg, vector_string &pieces, int &next); string cp_parse_non_delimiter(vector_string &pieces, int &next); bool cp_parse_coord_sys(ShaderArgInfo &arg, @@ -426,12 +430,12 @@ public: void cp_optimize_mat_spec(ShaderMatSpec &spec); #ifdef HAVE_CG - void cg_recurse_parameters(CGparameter parameter, - const ShaderType &type, + void cg_recurse_parameters(CGparameter parameter, + const ShaderType &type, bool &success); #endif - - bool compile_parameter(const ShaderArgId &arg_id, + + bool compile_parameter(const ShaderArgId &arg_id, const ShaderArgClass &arg_class, const ShaderArgClass &arg_subclass, const ShaderArgType &arg_type, @@ -444,7 +448,7 @@ public: #ifdef HAVE_CG private: - ShaderArgClass cg_parameter_class(CGparameter p); + ShaderArgClass cg_parameter_class(CGparameter p); ShaderArgType cg_parameter_type(CGparameter p); ShaderArgDir cg_parameter_dir(CGparameter p); @@ -456,7 +460,7 @@ private: bool cg_compile_shader(const ShaderCaps &caps); void cg_release_resources(); void cg_report_errors(); - + // Determines the appropriate cg profile settings and stores them in the active shader caps // based on any profile settings stored in the shader's header void cg_get_profile_from_header(ShaderCaps &caps); @@ -478,24 +482,24 @@ public: bool cg_compile_for(const ShaderCaps &caps, CGcontext &ctx, CGprogram &vprogram, CGprogram &fprogram, CGprogram &gprogram, pvector &map); - + #endif public: - pvector _ptr_spec; + pvector _ptr_spec; epvector _mat_spec; pvector _tex_spec; pvector _var_spec; - + bool _error_flag; CPT(ShaderFile) _text; protected: - CPT(ShaderFile) _filename; + CPT(ShaderFile) _filename; int _parse; bool _loaded; ShaderLanguage _language; - + static ShaderCaps _default_caps; static ShaderUtilization _shader_utilization; static int _shaders_generated; @@ -511,7 +515,7 @@ protected: typedef pmap Contexts; Contexts _contexts; -private: +private: void clear_prepared(PreparedGraphicsObjects *prepared_objects); Shader(); diff --git a/panda/src/gobj/textureCollection.cxx b/panda/src/gobj/textureCollection.cxx index 9fd40bc4b4..6bddb5f199 100644 --- a/panda/src/gobj/textureCollection.cxx +++ b/panda/src/gobj/textureCollection.cxx @@ -76,7 +76,7 @@ TextureCollection(PyObject *self, PyObject *sequence) { if (item == NULL) { return; } - PyObject *result = PyObject_CallMethod(self, (char *)"addTexture", (char *)"O", item); + PyObject *result = PyObject_CallMethod(self, (char *)"add_texture", (char *)"O", item); Py_DECREF(item); if (result == NULL) { // Unable to add item--probably it wasn't of the appropriate type. diff --git a/panda/src/gobj/textureStage.I b/panda/src/gobj/textureStage.I index e5ca4d94d8..cb5c6c0504 100755 --- a/panda/src/gobj/textureStage.I +++ b/panda/src/gobj/textureStage.I @@ -141,13 +141,46 @@ set_texcoord_name(const string &name) { //////////////////////////////////////////////////////////////////// // Function: TextureStage::get_texcoord_name // Access: Published -// Description: Returns the InternalName +// Description: See set_texcoord_name. The default is +// InternalName::get_texcoord(). //////////////////////////////////////////////////////////////////// INLINE InternalName *TextureStage:: get_texcoord_name() const { return _texcoord_name; } +//////////////////////////////////////////////////////////////////// +// Function: TextureStage::get_tangent_name +// Access: Published +// Description: Returns the set of tangents this texture stage will +// use. This is the same as get_texcoord_name(), +// except that the first part is "tangent". +//////////////////////////////////////////////////////////////////// +INLINE InternalName *TextureStage:: +get_tangent_name() const { + if (_texcoord_name->get_parent() == NULL) { + return InternalName::get_tangent(); + } else { + return InternalName::get_tangent_name(_texcoord_name->get_basename()); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TextureStage::get_binormal_name +// Access: Published +// Description: Returns the set of binormals this texture stage will +// use. This is the same as get_binormal_name(), +// except that the first part is "binormal". +//////////////////////////////////////////////////////////////////// +INLINE InternalName *TextureStage:: +get_binormal_name() const { + if (_texcoord_name->get_parent() == NULL) { + return InternalName::get_binormal(); + } else { + return InternalName::get_binormal_name(_texcoord_name->get_basename()); + } +} + //////////////////////////////////////////////////////////////////// // Function: TextureStage::set_mode // Access: Published diff --git a/panda/src/gobj/textureStage.cxx b/panda/src/gobj/textureStage.cxx index 28f2230c6c..f235c4e5e5 100755 --- a/panda/src/gobj/textureStage.cxx +++ b/panda/src/gobj/textureStage.cxx @@ -154,9 +154,6 @@ compare_to(const TextureStage &other) const { if (get_tex_view_offset() != other.get_tex_view_offset()) { return get_tex_view_offset() < other.get_tex_view_offset() ? -1 : 1; } - if (get_mode() != other.get_mode()) { - return get_mode() < other.get_mode() ? -1 : 1; - } if (get_mode() == M_combine) { if (get_combine_rgb_mode() != other.get_combine_rgb_mode()) { return get_combine_rgb_mode() < other.get_combine_rgb_mode() ? -1 : 1; diff --git a/panda/src/gobj/textureStage.h b/panda/src/gobj/textureStage.h index ff1734e7cf..9831124864 100644 --- a/panda/src/gobj/textureStage.h +++ b/panda/src/gobj/textureStage.h @@ -45,7 +45,7 @@ PUBLISHED: enum Mode { // Modes that pertain to the fixed-function pipeline. - + M_modulate, M_decal, M_blend, @@ -53,12 +53,12 @@ PUBLISHED: M_add, M_combine, M_blend_color_scale, - + M_modulate_glow, // When fixed-function, equivalent to modulate. M_modulate_gloss, // When fixed-function, equivalent to modulate. - + // Modes that are only relevant to shader-based rendering. - + M_normal, M_normal_height, M_glow, // Rarely used: modulate_glow is more efficient. @@ -67,7 +67,7 @@ PUBLISHED: M_selector, M_normal_gloss, }; - + enum CombineMode { CM_undefined, CM_replace, @@ -113,12 +113,14 @@ PUBLISHED: INLINE void set_texcoord_name(InternalName *name); INLINE void set_texcoord_name(const string &texcoord_name); INLINE InternalName *get_texcoord_name() const; - + INLINE InternalName *get_tangent_name() const; + INLINE InternalName *get_binormal_name() const; + INLINE void set_mode(Mode mode); INLINE Mode get_mode() const; - + INLINE bool is_fixed_function() const; - + INLINE void set_color(const LColor &color); INLINE LColor get_color() const; @@ -231,7 +233,7 @@ private: static PT(TextureStage) _default_stage; static UpdateSeq _sort_seq; - + public: // Datagram stuff static void register_with_read_factory(); @@ -272,6 +274,3 @@ EXPCL_PANDA_GOBJ ostream &operator << (ostream &out, TextureStage::CombineOperan #include "textureStage.I" #endif - - - diff --git a/panda/src/grutil/meshDrawer.I b/panda/src/grutil/meshDrawer.I index 1e22a653e9..e1aeace6e8 100644 --- a/panda/src/grutil/meshDrawer.I +++ b/panda/src/grutil/meshDrawer.I @@ -29,6 +29,7 @@ MeshDrawer() { _uv = NULL; _color = NULL; _budget = 5000; + _vdata = NULL; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/grutil/meshDrawer.cxx b/panda/src/grutil/meshDrawer.cxx index 8aeb9d7d65..e270a43786 100644 --- a/panda/src/grutil/meshDrawer.cxx +++ b/panda/src/grutil/meshDrawer.cxx @@ -110,6 +110,11 @@ void MeshDrawer::begin(NodePath camera, NodePath render) { if (_normal != NULL) delete _normal; if (_uv != NULL) delete _uv; if (_color != NULL) delete _color; + + if (_vdata == NULL) { + generator(_budget); + } + _vertex = new GeomVertexRewriter(_vdata, "vertex"); _uv = new GeomVertexRewriter(_vdata, "texcoord"); _normal = new GeomVertexRewriter(_vdata, "normal"); diff --git a/panda/src/linmath/lpoint2_ext_src.I b/panda/src/linmath/lpoint2_ext_src.I index b5716fa071..195c1b38d9 100644 --- a/panda/src/linmath/lpoint2_ext_src.I +++ b/panda/src/linmath/lpoint2_ext_src.I @@ -82,5 +82,5 @@ __getattr__(const string &attr_name) const { INLINE_LINMATH int Extension:: __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { // Upcall to LVecBase2. - return invoke_extension(_this, _self).__setattr__(self, attr_name, assign); + return invoke_extension(_this).__setattr__(self, attr_name, assign); } diff --git a/panda/src/linmath/lpoint3_ext_src.I b/panda/src/linmath/lpoint3_ext_src.I index 92178755e6..19f32de4e7 100644 --- a/panda/src/linmath/lpoint3_ext_src.I +++ b/panda/src/linmath/lpoint3_ext_src.I @@ -83,5 +83,5 @@ __getattr__(const string &attr_name) const { INLINE_LINMATH int Extension:: __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { // Upcall to LVecBase2. - return invoke_extension(_this, _self).__setattr__(self, attr_name, assign); + return invoke_extension(_this).__setattr__(self, attr_name, assign); } diff --git a/panda/src/linmath/lpoint4_ext_src.I b/panda/src/linmath/lpoint4_ext_src.I index 708150f52b..841e1271b2 100644 --- a/panda/src/linmath/lpoint4_ext_src.I +++ b/panda/src/linmath/lpoint4_ext_src.I @@ -88,5 +88,5 @@ __getattr__(const string &attr_name) const { INLINE_LINMATH int Extension:: __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { // Upcall to LVecBase4. - return invoke_extension(_this, _self).__setattr__(self, attr_name, assign); + return invoke_extension(_this).__setattr__(self, attr_name, assign); } diff --git a/panda/src/linmath/lvector2_ext_src.I b/panda/src/linmath/lvector2_ext_src.I index 39fb074fce..091c68760a 100644 --- a/panda/src/linmath/lvector2_ext_src.I +++ b/panda/src/linmath/lvector2_ext_src.I @@ -82,5 +82,5 @@ __getattr__(const string &attr_name) const { INLINE_LINMATH int Extension:: __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { // Upcall to LVecBase2. - return invoke_extension(_this, _self).__setattr__(self, attr_name, assign); + return invoke_extension(_this).__setattr__(self, attr_name, assign); } diff --git a/panda/src/linmath/lvector3_ext_src.I b/panda/src/linmath/lvector3_ext_src.I index 9706adfea3..a0046c513a 100644 --- a/panda/src/linmath/lvector3_ext_src.I +++ b/panda/src/linmath/lvector3_ext_src.I @@ -83,5 +83,5 @@ __getattr__(const string &attr_name) const { INLINE_LINMATH int Extension:: __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { // Upcall to LVecBase3. - return invoke_extension(_this, _self).__setattr__(self, attr_name, assign); + return invoke_extension(_this).__setattr__(self, attr_name, assign); } diff --git a/panda/src/linmath/lvector4_ext_src.I b/panda/src/linmath/lvector4_ext_src.I index a9ae9eb8d0..8b84439228 100644 --- a/panda/src/linmath/lvector4_ext_src.I +++ b/panda/src/linmath/lvector4_ext_src.I @@ -88,5 +88,5 @@ __getattr__(const string &attr_name) const { INLINE_LINMATH int Extension:: __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { // Upcall to LVecBase4. - return invoke_extension(_this, _self).__setattr__(self, attr_name, assign); + return invoke_extension(_this).__setattr__(self, attr_name, assign); } diff --git a/panda/src/movies/config_movies.cxx b/panda/src/movies/config_movies.cxx index a38f5976d7..dc4202c6f2 100644 --- a/panda/src/movies/config_movies.cxx +++ b/panda/src/movies/config_movies.cxx @@ -50,6 +50,11 @@ ConfigVariableList load_video_type "either the name of a module, or a space-separate list of filename " "extensions, followed by the name of the module.")); +ConfigVariableBool vorbis_enable_seek +("vorbis-enable-seek", true, + PRC_DESC("Set this to false if you're having trouble with seeking while " + "using the Ogg Vorbis decoder.")); + ConfigVariableBool vorbis_seek_lap ("vorbis-seek-lap", true, PRC_DESC("If this is set to true, the Ogg Vorbis decoder will automatically " diff --git a/panda/src/movies/config_movies.h b/panda/src/movies/config_movies.h index d0c02724d8..fa09bc6e8f 100644 --- a/panda/src/movies/config_movies.h +++ b/panda/src/movies/config_movies.h @@ -28,6 +28,7 @@ NotifyCategoryDecl(movies, EXPCL_PANDA_MOVIES, EXPTP_PANDA_MOVIES); extern ConfigVariableList load_audio_type; extern ConfigVariableList load_video_type; +extern ConfigVariableBool vorbis_enable_seek; extern ConfigVariableBool vorbis_seek_lap; extern EXPCL_PANDA_MOVIES void init_libmovies(); diff --git a/panda/src/movies/vorbisAudioCursor.cxx b/panda/src/movies/vorbisAudioCursor.cxx index a0265f10ed..2f206cbc39 100644 --- a/panda/src/movies/vorbisAudioCursor.cxx +++ b/panda/src/movies/vorbisAudioCursor.cxx @@ -33,27 +33,36 @@ VorbisAudioCursor(VorbisAudio *src, istream *stream) : _bitstream(0) { nassertv(stream != NULL); + nassertv(stream->good()); // Set up the callbacks to read via the VFS. ov_callbacks callbacks; callbacks.read_func = &cb_read_func; - callbacks.seek_func = &cb_seek_func; callbacks.close_func = &cb_close_func; callbacks.tell_func = &cb_tell_func; + if (vorbis_enable_seek) { + callbacks.seek_func = &cb_seek_func; + } else { + callbacks.seek_func = NULL; + } + if (ov_open_callbacks((void*) stream, &_ov, NULL, 0, callbacks) != 0) { movies_cat.error() << "Failed to read Ogg Vorbis file.\n"; return; } - _length = ov_time_total(&_ov, -1); + double time_total = ov_time_total(&_ov, -1); + if (time_total != OV_EINVAL) { + _length = time_total; + } vorbis_info *vi = ov_info(&_ov, -1); _audio_channels = vi->channels; _audio_rate = vi->rate; - _can_seek = (ov_seekable(&_ov) != 0); + _can_seek = vorbis_enable_seek && (ov_seekable(&_ov) != 0); _can_seek_fast = _can_seek; _is_valid = true; @@ -78,6 +87,10 @@ VorbisAudioCursor:: //////////////////////////////////////////////////////////////////// void VorbisAudioCursor:: seek(double t) { + if (!vorbis_enable_seek) { + return; + } + t = max(t, 0.0); // Use ov_time_seek_lap if cross-lapping is enabled. @@ -163,8 +176,15 @@ read_samples(int n, PN_int16 *data) { size_t VorbisAudioCursor:: cb_read_func(void *ptr, size_t size, size_t nmemb, void *datasource) { istream *stream = (istream*) datasource; + nassertr(stream != NULL, -1); stream->read((char *)ptr, size * nmemb); + + if (stream->eof()) { + // Gracefully handle EOF. + stream->clear(); + } + return stream->gcount(); } @@ -176,7 +196,12 @@ cb_read_func(void *ptr, size_t size, size_t nmemb, void *datasource) { //////////////////////////////////////////////////////////////////// int VorbisAudioCursor:: cb_seek_func(void *datasource, ogg_int64_t offset, int whence) { + if (!vorbis_enable_seek) { + return -1; + } + istream *stream = (istream*) datasource; + nassertr(stream != NULL, -1); switch (whence) { case SEEK_SET: @@ -198,6 +223,26 @@ cb_seek_func(void *datasource, ogg_int64_t offset, int whence) { } if (stream->fail()) { + // This is a fatal error and usually leads to + // a libvorbis crash. + movies_cat.error() + << "Failure to seek to byte " << offset; + + switch (whence) { + case SEEK_CUR: + movies_cat.error(false) + << " from current location!\n"; + break; + + case SEEK_END: + movies_cat.error(false) + << " from end of file!\n"; + break; + + default: + movies_cat.error(false) << "!\n"; + } + return -1; } @@ -213,6 +258,8 @@ cb_seek_func(void *datasource, ogg_int64_t offset, int whence) { int VorbisAudioCursor:: cb_close_func(void *datasource) { istream *stream = (istream*) datasource; + nassertr(stream != NULL, -1); + VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); vfs->close_read_file(stream); @@ -229,6 +276,8 @@ cb_close_func(void *datasource) { long VorbisAudioCursor:: cb_tell_func(void *datasource) { istream *stream = (istream*) datasource; + nassertr(stream != NULL, -1); + return stream->tellg(); } diff --git a/panda/src/ode/Sources.pp b/panda/src/ode/Sources.pp index 1006da1815..6d1393f815 100755 --- a/panda/src/ode/Sources.pp +++ b/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 - diff --git a/panda/src/ode/odeAMotorJoint.h b/panda/src/ode/odeAMotorJoint.h index 20bd0d3c99..c3b41a677d 100644 --- a/panda/src/ode/odeAMotorJoint.h +++ b/panda/src/ode/odeAMotorJoint.h @@ -16,7 +16,7 @@ class EXPCL_PANDAODE OdeAMotorJoint : public OdeJoint { friend class OdeJoint; -private: +public: OdeAMotorJoint(dJointID id); PUBLISHED: diff --git a/panda/src/ode/odeBallJoint.h b/panda/src/ode/odeBallJoint.h index 7fb9c104c3..be6100bf76 100644 --- a/panda/src/ode/odeBallJoint.h +++ b/panda/src/ode/odeBallJoint.h @@ -16,7 +16,7 @@ class EXPCL_PANDAODE OdeBallJoint : public OdeJoint { friend class OdeJoint; -private: +public: OdeBallJoint(dJointID id); PUBLISHED: diff --git a/panda/src/ode/odeBody.h b/panda/src/ode/odeBody.h index 51c5394d35..7a6fa3ffd7 100755 --- a/panda/src/ode/odeBody.h +++ b/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; diff --git a/panda/src/ode/odeBody_ext.I b/panda/src/ode/odeBody_ext.I new file mode 100644 index 0000000000..b3618ae4b1 --- /dev/null +++ b/panda/src/ode/odeBody_ext.I @@ -0,0 +1,26 @@ +// Filename: odeBody_ext.I +// Created by: rdb (11Dec13) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "odeJoint_ext.h" + +//////////////////////////////////////////////////////////////////// +// Function: OdeBody::get_converted_joint +// Access: Published +// Description: Equivalent to get_joint().convert() +//////////////////////////////////////////////////////////////////// +INLINE PyObject *Extension:: +get_converted_joint(int i) const { + OdeJoint j = _this->get_joint(i); + return invoke_extension(&j).convert(); +} diff --git a/panda/src/ode/odeBody_ext.h b/panda/src/ode/odeBody_ext.h new file mode 100644 index 0000000000..1331d47183 --- /dev/null +++ b/panda/src/ode/odeBody_ext.h @@ -0,0 +1,43 @@ +// Filename: odeBody_ext.h +// Created by: rdb (11Dec13) +// +//////////////////////////////////////////////////////////////////// +// +// 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 ODEBODY_EXT_H +#define ODEBODY_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "config_ode.h" +#include "odeBody.h" +#include "extension.h" +#include "py_panda.h" + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// NodePathCollection, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + INLINE PyObject *get_converted_joint(int i) const; +}; + +#include "odeBody_ext.I" + +#endif // HAVE_PYTHON + +#endif // ODEBODY_EXT_H diff --git a/panda/src/ode/odeBoxGeom.h b/panda/src/ode/odeBoxGeom.h index a4336eb93d..9991124a59 100644 --- a/panda/src/ode/odeBoxGeom.h +++ b/panda/src/ode/odeBoxGeom.h @@ -29,7 +29,7 @@ class EXPCL_PANDAODE OdeBoxGeom : public OdeGeom { friend class OdeGeom; -private: +public: OdeBoxGeom(dGeomID id); PUBLISHED: diff --git a/panda/src/ode/odeCappedCylinderGeom.h b/panda/src/ode/odeCappedCylinderGeom.h index ce56ab5816..2e48cb36c0 100755 --- a/panda/src/ode/odeCappedCylinderGeom.h +++ b/panda/src/ode/odeCappedCylinderGeom.h @@ -29,7 +29,7 @@ class EXPCL_PANDAODE OdeCappedCylinderGeom : public OdeGeom { friend class OdeGeom; -private: +public: OdeCappedCylinderGeom(dGeomID id); PUBLISHED: diff --git a/panda/src/ode/odeContactJoint.h b/panda/src/ode/odeContactJoint.h index 963996a9fc..f2edc91de2 100644 --- a/panda/src/ode/odeContactJoint.h +++ b/panda/src/ode/odeContactJoint.h @@ -17,7 +17,7 @@ class EXPCL_PANDAODE OdeContactJoint : public OdeJoint { friend class OdeJoint; -private: +public: OdeContactJoint(dJointID id); PUBLISHED: diff --git a/panda/src/ode/odeConvexGeom.h b/panda/src/ode/odeConvexGeom.h index 7a7819e7eb..bc4104855a 100755 --- a/panda/src/ode/odeConvexGeom.h +++ b/panda/src/ode/odeConvexGeom.h @@ -29,7 +29,7 @@ class EXPCL_PANDAODE OdeConvexGeom : public OdeGeom { friend class OdeGeom; -private: +public: OdeConvexGeom(dGeomID id); PUBLISHED: diff --git a/panda/src/ode/odeCylinderGeom.h b/panda/src/ode/odeCylinderGeom.h index 9d4bbbd2c7..1b847c908c 100755 --- a/panda/src/ode/odeCylinderGeom.h +++ b/panda/src/ode/odeCylinderGeom.h @@ -29,7 +29,7 @@ class EXPCL_PANDAODE OdeCylinderGeom : public OdeGeom { friend class OdeGeom; -private: +public: OdeCylinderGeom(dGeomID id); PUBLISHED: diff --git a/panda/src/ode/odeFixedJoint.h b/panda/src/ode/odeFixedJoint.h index 5c074303cb..a1d8a6d59e 100644 --- a/panda/src/ode/odeFixedJoint.h +++ b/panda/src/ode/odeFixedJoint.h @@ -16,7 +16,7 @@ class EXPCL_PANDAODE OdeFixedJoint : public OdeJoint { friend class OdeJoint; -private: +public: OdeFixedJoint(dJointID id); PUBLISHED: diff --git a/panda/src/ode/odeGeom.h b/panda/src/ode/odeGeom.h index daea43908a..dff9eddeed 100755 --- a/panda/src/ode/odeGeom.h +++ b/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); - 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; }; diff --git a/panda/src/ode/odeGeom_ext.I b/panda/src/ode/odeGeom_ext.I new file mode 100644 index 0000000000..6d1cf2bebd --- /dev/null +++ b/panda/src/ode/odeGeom_ext.I @@ -0,0 +1,47 @@ +// Filename: odeGeom_ext.I +// Created by: rdb (11Dec13) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "odeSpace_ext.h" +#include "lpoint3.h" + +#ifndef CPPPARSER +IMPORT_THIS struct Dtool_PyTypedObject Dtool_LPoint3f; +#endif + +//////////////////////////////////////////////////////////////////// +// Function: OdeGeom::get_AA_bounds +// Access: Published +// Description: A more Pythonic way of calling getAABB() +//////////////////////////////////////////////////////////////////// +INLINE PyObject *Extension:: +get_AA_bounds() const { + LPoint3f *min_point = new LPoint3f; + LPoint3f *max_point = new LPoint3f; + _this->get_AABB(*min_point, *max_point); + + PyObject *min_inst = DTool_CreatePyInstance((void*) min_point, Dtool_LPoint3f, true, false); + PyObject *max_inst = DTool_CreatePyInstance((void*) max_point, Dtool_LPoint3f, true, false); + return Py_BuildValue("NN", min_inst, max_inst); +} + +//////////////////////////////////////////////////////////////////// +// Function: OdeGeom::get_converted_space +// Access: Published +// Description: Equivalent to get_space().convert() +//////////////////////////////////////////////////////////////////// +INLINE PyObject *Extension:: +get_converted_space() const { + OdeSpace s = _this->get_space(); + return invoke_extension(&s).convert(); +} diff --git a/panda/src/ode/odeGeom_ext.cxx b/panda/src/ode/odeGeom_ext.cxx new file mode 100644 index 0000000000..c9b2cd5320 --- /dev/null +++ b/panda/src/ode/odeGeom_ext.cxx @@ -0,0 +1,133 @@ +// Filename: odeGeom_ext.cxx +// Created by: rdb (11Dec13) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "odeGeom_ext.h" + +#include "odeBoxGeom.h" +//#include "odeConvexGeom.h" +#include "odeGeom.h" +#include "odeHashSpace.h" +#include "odeCappedCylinderGeom.h" +//#include "odeHeightfieldGeom.h" +#include "odePlaneGeom.h" +#include "odeQuadTreeSpace.h" +#include "odeRayGeom.h" +#include "odeSimpleSpace.h" +#include "odeSpace.h" +#include "odeSphereGeom.h" +#include "odeTriMeshGeom.h" + +#ifdef HAVE_PYTHON + +#ifndef CPPPARSER +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeBoxGeom; +//extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeConvexGeom; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeGeom; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeHashSpace; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeCappedCylinderGeom; +//extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeHeightfieldGeom; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdePlaneGeom; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeQuadTreeSpace; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeRayGeom; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeSimpleSpace; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeSpace; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeSphereGeom; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeTriMeshGeom; +#endif + +//////////////////////////////////////////////////////////////////// +// Function: OdeGeom::convert +// Access: Published +// Description: Do a sort of pseudo-downcast on this space in +// order to expose its specialized functions. +//////////////////////////////////////////////////////////////////// +PyObject *Extension:: +convert() const { + Dtool_PyTypedObject *class_type; + TypedObject *geom; + + switch (_this->get_class()) { + case OdeGeom::GC_sphere: + geom = new OdeSphereGeom(_this->get_id()); + class_type = &Dtool_OdeSphereGeom; + break; + + case OdeGeom::GC_box: + geom = new OdeBoxGeom(_this->get_id()); + class_type = &Dtool_OdeBoxGeom; + break; + + case OdeGeom::GC_capped_cylinder: + geom = new OdeCappedCylinderGeom(_this->get_id()); + class_type = &Dtool_OdeCappedCylinderGeom; + break; + + case OdeGeom::GC_plane: + geom = new OdePlaneGeom(_this->get_id()); + class_type = &Dtool_OdePlaneGeom; + break; + + case OdeGeom::GC_ray: + geom = new OdeRayGeom(_this->get_id()); + class_type = &Dtool_OdeRayGeom; + break; + + //case OdeGeom::GC_convex: + // geom = new OdeConvexGeom(_this->get_id()); + // class_type = &Dtool_OdeConvexGeom; + // break; + + case OdeGeom::GC_tri_mesh: + geom = new OdeTriMeshGeom(_this->get_id()); + class_type = &Dtool_OdeTriMeshGeom; + break; + + //case OdeGeom::GC_heightfield: + // geom = new OdeHeightfieldGeom(_this->get_id()); + // class_type = &Dtool_OdeHeightfieldGeom; + // break; + + case OdeGeom::GC_simple_space: + geom = new OdeSimpleSpace((dSpaceID) _this->get_id()); + class_type = &Dtool_OdeSimpleSpace; + break; + + case OdeGeom::GC_hash_space: + geom = new OdeHashSpace((dSpaceID) _this->get_id()); + class_type = &Dtool_OdeHashSpace; + break; + + case OdeGeom::GC_quad_tree_space: + geom = new OdeQuadTreeSpace((dSpaceID) _this->get_id()); + class_type = &Dtool_OdeQuadTreeSpace; + break; + + default: + // This shouldn't happen, but if it does, we + // should just return a regular OdeGeom or OdeSpace. + if (_this->is_space()) { + geom = new OdeSpace((dSpaceID) _this->get_id()); + class_type = &Dtool_OdeSpace; + + } else { + geom = new OdeGeom(_this->get_id()); + class_type = &Dtool_OdeGeom; + } + } + + return DTool_CreatePyInstanceTyped((void *)geom, *class_type, + true, false, geom->get_type_index()); +} + +#endif // HAVE_PYTHON diff --git a/panda/src/ode/odeGeom_ext.h b/panda/src/ode/odeGeom_ext.h new file mode 100644 index 0000000000..7a3d1120c2 --- /dev/null +++ b/panda/src/ode/odeGeom_ext.h @@ -0,0 +1,46 @@ +// Filename: odeGeom_ext.h +// Created by: rdb (11Dec13) +// +//////////////////////////////////////////////////////////////////// +// +// 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 ODEGEOM_EXT_H +#define ODEGEOM_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "config_ode.h" +#include "odeGeom.h" +#include "extension.h" +#include "py_panda.h" + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// NodePathCollection, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + INLINE PyObject *get_AA_bounds() const; + + PyObject *convert() const; + INLINE PyObject *get_converted_space() const; +}; + +#include "odeGeom_ext.I" + +#endif // HAVE_PYTHON + +#endif // ODEGEOM_EXT_H diff --git a/panda/src/ode/odeHashSpace.h b/panda/src/ode/odeHashSpace.h index d66a99d43b..03e2983689 100755 --- a/panda/src/ode/odeHashSpace.h +++ b/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: diff --git a/panda/src/ode/odeHeightFieldGeom.h b/panda/src/ode/odeHeightFieldGeom.h index 7b648a3539..00fd6593a1 100644 --- a/panda/src/ode/odeHeightFieldGeom.h +++ b/panda/src/ode/odeHeightFieldGeom.h @@ -29,7 +29,7 @@ class EXPCL_PANDAODE OdeHeightfieldGeom : public OdeGeom { friend class OdeGeom; -private: +public: OdeHeightfieldGeom(dGeomID id); PUBLISHED: diff --git a/panda/src/ode/odeHinge2Joint.h b/panda/src/ode/odeHinge2Joint.h index dcb8e732e9..2e6e5dd487 100644 --- a/panda/src/ode/odeHinge2Joint.h +++ b/panda/src/ode/odeHinge2Joint.h @@ -16,7 +16,7 @@ class EXPCL_PANDAODE OdeHinge2Joint : public OdeJoint { friend class OdeJoint; -private: +public: OdeHinge2Joint(dJointID id); PUBLISHED: diff --git a/panda/src/ode/odeHingeJoint.h b/panda/src/ode/odeHingeJoint.h index c622d7996e..0cc9fefadc 100755 --- a/panda/src/ode/odeHingeJoint.h +++ b/panda/src/ode/odeHingeJoint.h @@ -15,7 +15,7 @@ class EXPCL_PANDAODE OdeHingeJoint : public OdeJoint { friend class OdeJoint; -private: +public: OdeHingeJoint(dJointID id); PUBLISHED: diff --git a/panda/src/ode/odeJoint.cxx b/panda/src/ode/odeJoint.cxx index b1d235efcb..8aa287e30a 100755 --- a/panda/src/ode/odeJoint.cxx +++ b/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()); } diff --git a/panda/src/ode/odeJoint.h b/panda/src/ode/odeJoint.h index b3fcead63b..0eb44b61bf 100755 --- a/panda/src/ode/odeJoint.h +++ b/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; diff --git a/panda/src/ode/odeJoint_ext.cxx b/panda/src/ode/odeJoint_ext.cxx new file mode 100644 index 0000000000..871eb09c78 --- /dev/null +++ b/panda/src/ode/odeJoint_ext.cxx @@ -0,0 +1,144 @@ +// Filename: odeJoint_ext.cxx +// Created by: rdb (11Dec13) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "odeJoint_ext.h" + +#ifdef HAVE_PYTHON + +#include "odeJoint.h" +#include "odeBallJoint.h" +#include "odeHingeJoint.h" +#include "odeSliderJoint.h" +#include "odeContactJoint.h" +#include "odeUniversalJoint.h" +#include "odeHinge2Joint.h" +#include "odeFixedJoint.h" +#include "odeNullJoint.h" +#include "odeAMotorJoint.h" +#include "odeLMotorJoint.h" +#include "odePlane2dJoint.h" + +#ifndef CPPPARSER +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeJoint; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeBallJoint; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeHingeJoint; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeSliderJoint; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeContactJoint; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeUniversalJoint; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeHinge2Joint; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeFixedJoint; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeNullJoint; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeAMotorJoint; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeLMotorJoint; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdePlane2dJoint; +#endif + +//////////////////////////////////////////////////////////////////// +// Function: OdeJoint::attach +// Access: Published +// Description: Attach two bodies together. If either body is None, +// the other will be attached to the environment. +//////////////////////////////////////////////////////////////////// +void Extension:: +attach(const OdeBody *body1, const OdeBody *body2) { + if (body1 && body2) { + _this->attach_bodies(*body1, *body2); + + } else if (body1 && !body2) { + _this->attach_body(*body1, 0); + + } else if (!body1 && body2) { + _this->attach_body(*body2, 1); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: OdeJoint::convert +// Access: Published +// Description: Do a sort of pseudo-downcast on this space in +// order to expose its specialized functions. +//////////////////////////////////////////////////////////////////// +PyObject *Extension:: +convert() const { + Dtool_PyTypedObject *class_type; + OdeJoint *joint; + + switch (_this->get_joint_type()) { + case OdeJoint::JT_ball: + joint = new OdeBallJoint(_this->get_id()); + class_type = &Dtool_OdeBallJoint; + break; + + case OdeJoint::JT_hinge: + joint = new OdeHingeJoint(_this->get_id()); + class_type = &Dtool_OdeHingeJoint; + break; + + case OdeJoint::JT_slider: + joint = new OdeSliderJoint(_this->get_id()); + class_type = &Dtool_OdeSliderJoint; + break; + + case OdeJoint::JT_contact: + joint = new OdeContactJoint(_this->get_id()); + class_type = &Dtool_OdeContactJoint; + break; + + case OdeJoint::JT_universal: + joint = new OdeUniversalJoint(_this->get_id()); + class_type = &Dtool_OdeUniversalJoint; + break; + + case OdeJoint::JT_hinge2: + joint = new OdeHinge2Joint(_this->get_id()); + class_type = &Dtool_OdeHinge2Joint; + break; + + case OdeJoint::JT_fixed: + joint = new OdeFixedJoint(_this->get_id()); + class_type = &Dtool_OdeFixedJoint; + break; + + case OdeJoint::JT_null: + joint = new OdeNullJoint(_this->get_id()); + class_type = &Dtool_OdeNullJoint; + break; + + case OdeJoint::JT_a_motor: + joint = new OdeAMotorJoint(_this->get_id()); + class_type = &Dtool_OdeAMotorJoint; + break; + + case OdeJoint::JT_l_motor: + joint = new OdeLMotorJoint(_this->get_id()); + class_type = &Dtool_OdeLMotorJoint; + break; + + case OdeJoint::JT_plane2d: + joint = new OdePlane2dJoint(_this->get_id()); + class_type = &Dtool_OdePlane2dJoint; + break; + + default: + // This shouldn't happen, but if it does, we + // should just return a regular OdeJoint. + joint = new OdeJoint(_this->get_id()); + class_type = &Dtool_OdeJoint; + } + + return DTool_CreatePyInstanceTyped((void *)joint, *class_type, + true, false, joint->get_type_index()); +} + +#endif // HAVE_PYTHON diff --git a/panda/src/ode/odeJoint_ext.h b/panda/src/ode/odeJoint_ext.h new file mode 100644 index 0000000000..48c5f20495 --- /dev/null +++ b/panda/src/ode/odeJoint_ext.h @@ -0,0 +1,43 @@ +// Filename: odeJoint_ext.h +// Created by: rdb (11Dec13) +// +//////////////////////////////////////////////////////////////////// +// +// 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 ODEJOINT_EXT_H +#define ODEJOINT_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "config_ode.h" +#include "odeJoint.h" +#include "extension.h" +#include "py_panda.h" + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// NodePathCollection, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + void attach(const OdeBody *body1, const OdeBody *body2); + + PyObject *convert() const; +}; + +#endif // HAVE_PYTHON + +#endif // ODEJOINT_EXT_H diff --git a/panda/src/ode/odeLMotorJoint.h b/panda/src/ode/odeLMotorJoint.h index 3b91cbbeb7..541afcd904 100755 --- a/panda/src/ode/odeLMotorJoint.h +++ b/panda/src/ode/odeLMotorJoint.h @@ -15,7 +15,7 @@ class EXPCL_PANDAODE OdeLMotorJoint : public OdeJoint { friend class OdeJoint; -private: +public: OdeLMotorJoint(dJointID id); PUBLISHED: diff --git a/panda/src/ode/odeNullJoint.h b/panda/src/ode/odeNullJoint.h index 94c659ab92..61f3912866 100755 --- a/panda/src/ode/odeNullJoint.h +++ b/panda/src/ode/odeNullJoint.h @@ -15,7 +15,7 @@ class EXPCL_PANDAODE OdeNullJoint : public OdeJoint { friend class OdeJoint; -private: +public: OdeNullJoint(dJointID id); PUBLISHED: diff --git a/panda/src/ode/odePlane2dJoint.h b/panda/src/ode/odePlane2dJoint.h index e70e75181d..cb9e7eb6de 100755 --- a/panda/src/ode/odePlane2dJoint.h +++ b/panda/src/ode/odePlane2dJoint.h @@ -15,7 +15,7 @@ class EXPCL_PANDAODE OdePlane2dJoint : public OdeJoint { friend class OdeJoint; -private: +public: OdePlane2dJoint(dJointID id); PUBLISHED: diff --git a/panda/src/ode/odePlaneGeom.h b/panda/src/ode/odePlaneGeom.h index 1412d472bc..5131f55f78 100755 --- a/panda/src/ode/odePlaneGeom.h +++ b/panda/src/ode/odePlaneGeom.h @@ -28,7 +28,7 @@ class EXPCL_PANDAODE OdePlaneGeom : public OdeGeom { friend class OdeGeom; -private: +public: OdePlaneGeom(dGeomID id); PUBLISHED: diff --git a/panda/src/ode/odeQuadTreeSpace.h b/panda/src/ode/odeQuadTreeSpace.h index adb05d7d09..0a57a7668f 100755 --- a/panda/src/ode/odeQuadTreeSpace.h +++ b/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: diff --git a/panda/src/ode/odeRayGeom.h b/panda/src/ode/odeRayGeom.h index d1d16b0027..d8c4f64d98 100755 --- a/panda/src/ode/odeRayGeom.h +++ b/panda/src/ode/odeRayGeom.h @@ -28,7 +28,7 @@ class EXPCL_PANDAODE OdeRayGeom : public OdeGeom { friend class OdeGeom; -private: +public: OdeRayGeom(dGeomID id); PUBLISHED: diff --git a/panda/src/ode/odeSimpleSpace.h b/panda/src/ode/odeSimpleSpace.h index af8edc03d0..63c16a8901 100755 --- a/panda/src/ode/odeSimpleSpace.h +++ b/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: diff --git a/panda/src/ode/odeSliderJoint.h b/panda/src/ode/odeSliderJoint.h index 3ee063daf2..a4d8117525 100755 --- a/panda/src/ode/odeSliderJoint.h +++ b/panda/src/ode/odeSliderJoint.h @@ -15,7 +15,7 @@ class EXPCL_PANDAODE OdeSliderJoint : public OdeJoint { friend class OdeJoint; -private: +public: OdeSliderJoint(dJointID id); PUBLISHED: diff --git a/panda/src/ode/odeSpace.cxx b/panda/src/ode/odeSpace.cxx index fecb33d877..e98086c711 100755 --- a/panda/src/ode/odeSpace.cxx +++ b/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; } - diff --git a/panda/src/ode/odeSpace.h b/panda/src/ode/odeSpace.h index e61f4aa1e2..07b6c8f5d7 100755 --- a/panda/src/ode/odeSpace.h +++ b/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 - diff --git a/panda/src/ode/odeSpace_ext.I b/panda/src/ode/odeSpace_ext.I new file mode 100644 index 0000000000..78e9aeb7c3 --- /dev/null +++ b/panda/src/ode/odeSpace_ext.I @@ -0,0 +1,58 @@ +// Filename: odeSpace_ext.I +// Created by: rdb (11Dec13) +// +//////////////////////////////////////////////////////////////////// +// +// 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." +// +//////////////////////////////////////////////////////////////////// + +/* okcircular */ +#include "odeGeom_ext.h" + +#ifndef CPPPARSER +IMPORT_THIS struct Dtool_PyTypedObject Dtool_LPoint3f; +#endif + +//////////////////////////////////////////////////////////////////// +// Function: OdeSpace::get_AA_bounds +// Access: Published +// Description: A more Pythonic way of calling getAABB() +//////////////////////////////////////////////////////////////////// +INLINE PyObject *Extension:: +get_AA_bounds() const { + LPoint3f *min_point = new LPoint3f; + LPoint3f *max_point = new LPoint3f; + _this->get_AABB(*min_point, *max_point); + + PyObject *min_inst = DTool_CreatePyInstance((void*) min_point, Dtool_LPoint3f, true, false); + PyObject *max_inst = DTool_CreatePyInstance((void*) max_point, Dtool_LPoint3f, true, false); + return Py_BuildValue("NN", min_inst, max_inst); +} + +//////////////////////////////////////////////////////////////////// +// Function: OdeSpace::get_converted_geom +// Access: Published +// Description: Equivalent to get_geom(index).convert() +//////////////////////////////////////////////////////////////////// +INLINE PyObject *Extension:: +get_converted_geom(int index) const { + OdeGeom g = _this->get_geom(index); + return invoke_extension(&g).convert(); +} + +//////////////////////////////////////////////////////////////////// +// Function: OdeSpace::get_converted_space +// Access: Published +// Description: Equivalent to get_space().convert() +//////////////////////////////////////////////////////////////////// +INLINE PyObject *Extension:: +get_converted_space() const { + OdeSpace s = _this->get_space(); + return invoke_extension(&s).convert(); +} diff --git a/panda/src/ode/odeSpace_ext.cxx b/panda/src/ode/odeSpace_ext.cxx new file mode 100644 index 0000000000..8baa7aabb1 --- /dev/null +++ b/panda/src/ode/odeSpace_ext.cxx @@ -0,0 +1,112 @@ +// Filename: odeSpace_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 "odeSpace_ext.h" +#include "config_ode.h" + +#ifdef HAVE_PYTHON + +#include "odeGeom.h" +#include "odeHashSpace.h" +#include "odeSimpleSpace.h" +#include "odeSpace.h" +#include "odeQuadTreeSpace.h" + +#ifndef CPPPARSER +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeHashSpace; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeSimpleSpace; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeSpace; +extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeQuadTreeSpace; +#endif + +PyObject *Extension::_python_callback = NULL; + +//////////////////////////////////////////////////////////////////// +// Function: OdeSpace::convert +// Access: Published +// Description: Do a sort of pseudo-downcast on this space in +// order to expose its specialized functions. +//////////////////////////////////////////////////////////////////// +PyObject *Extension:: +convert() const { + Dtool_PyTypedObject *class_type; + OdeSpace *space; + + switch (_this->get_class()) { + case OdeGeom::GC_simple_space: + space = new OdeSimpleSpace(_this->get_id()); + class_type = &Dtool_OdeSimpleSpace; + break; + + case OdeGeom::GC_hash_space: + space = new OdeHashSpace(_this->get_id()); + class_type = &Dtool_OdeHashSpace; + break; + + case OdeGeom::GC_quad_tree_space: + space = new OdeQuadTreeSpace(_this->get_id()); + class_type = &Dtool_OdeQuadTreeSpace; + break; + + default: + // This shouldn't happen, but if it does, we + // should just return a regular OdeSpace. + space = new OdeSpace(_this->get_id()); + class_type = &Dtool_OdeSpace; + } + + return DTool_CreatePyInstanceTyped((void *)space, *class_type, + true, false, space->get_type_index()); +} + +int Extension:: +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 (_this->get_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 { + _python_callback = (PyObject*) callback; + Py_XINCREF(_python_callback); + dSpaceCollide(_this->get_id(), (void*) arg, &near_callback); + Py_XDECREF(_python_callback); + return 0; + } +} + +void Extension:: +near_callback(void *data, dGeomID o1, dGeomID o2) { + OdeGeom g1 (o1); + OdeGeom g2 (o2); + PyObject* p1 = invoke_extension(&g1).convert(); + PyObject* p2 = invoke_extension(&g2).convert(); + PyObject *result = PyObject_CallFunctionObjArgs(_python_callback, (PyObject*) data, p1, p2, NULL); + 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 // HAVE_PYTHON diff --git a/panda/src/ode/odeSpace_ext.h b/panda/src/ode/odeSpace_ext.h new file mode 100644 index 0000000000..4ad3be8bca --- /dev/null +++ b/panda/src/ode/odeSpace_ext.h @@ -0,0 +1,54 @@ +// Filename: odeSpace_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 ODESPACE_EXT_H +#define ODESPACE_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "config_ode.h" +#include "odeSpace.h" +#include "extension.h" +#include "py_panda.h" + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// NodePathCollection, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + INLINE PyObject *get_AA_bounds() const; + + PyObject *convert() const; + INLINE PyObject *get_converted_geom(int index) const; + INLINE PyObject *get_converted_space() const; + + int collide(PyObject* arg, PyObject* near_callback); + +private: + static void near_callback(void*, dGeomID, dGeomID); + + static PyObject *_python_callback; +}; + +#include "odeSpace_ext.I" + +#endif // HAVE_PYTHON + +#endif // ODESPACE_EXT_H diff --git a/panda/src/ode/odeSphereGeom.h b/panda/src/ode/odeSphereGeom.h index 5b02a1ff76..2c7e3157b4 100755 --- a/panda/src/ode/odeSphereGeom.h +++ b/panda/src/ode/odeSphereGeom.h @@ -28,7 +28,7 @@ class EXPCL_PANDAODE OdeSphereGeom : public OdeGeom { friend class OdeGeom; -private: +public: OdeSphereGeom(dGeomID id); PUBLISHED: diff --git a/panda/src/ode/odeTriMeshGeom.h b/panda/src/ode/odeTriMeshGeom.h index 8a3f5943ed..ad1dfe665a 100755 --- a/panda/src/ode/odeTriMeshGeom.h +++ b/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 ©); - public: static TypeHandle get_class_type() { return _type_handle; diff --git a/panda/src/ode/odeUniversalJoint.h b/panda/src/ode/odeUniversalJoint.h index 3f79d8ec48..d4e3e4c185 100644 --- a/panda/src/ode/odeUniversalJoint.h +++ b/panda/src/ode/odeUniversalJoint.h @@ -16,7 +16,7 @@ class EXPCL_PANDAODE OdeUniversalJoint : public OdeJoint { friend class OdeJoint; -private: +public: OdeUniversalJoint(dJointID id); PUBLISHED: diff --git a/panda/src/ode/odeUtil.cxx b/panda/src/ode/odeUtil.cxx index edc2f8236c..4bb6471881 100755 --- a/panda/src/ode/odeUtil.cxx +++ b/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()); } - diff --git a/panda/src/ode/odeUtil.h b/panda/src/ode/odeUtil.h index 654b7f1008..d24844ac89 100755 --- a/panda/src/ode/odeUtil.h +++ b/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 diff --git a/panda/src/ode/odeUtil_ext.cxx b/panda/src/ode/odeUtil_ext.cxx new file mode 100644 index 0000000000..e2910881bf --- /dev/null +++ b/panda/src/ode/odeUtil_ext.cxx @@ -0,0 +1,66 @@ +// Filename: odeUtil_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 "odeUtil_ext.h" +#include "config_ode.h" +#include "odeGeom.h" +#include "odeGeom_ext.h" + +#ifdef HAVE_PYTHON + +PyObject *Extension::_python_callback = NULL; + +//////////////////////////////////////////////////////////////////// +// 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 Extension:: +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 Extension:: +near_callback(void *data, dGeomID o1, dGeomID o2) { + if (ode_cat.is_spam()) { + ode_cat.spam() + << "near_callback called, data: " << data << ", dGeomID1: " << o1 << ", dGeomID2: " << o2 << "\n"; + } + + OdeGeom g1 (o1); + OdeGeom g2 (o2); + PyObject* p1 = invoke_extension(&g1).convert(); + PyObject* p2 = invoke_extension(&g2).convert(); + PyObject* result = PyObject_CallFunctionObjArgs(_python_callback, (PyObject*) data, p1, p2, NULL); + if (!result) { + ode_cat.error() << "An error occurred while calling python function!\n"; + PyErr_Print(); + } + Py_XDECREF(p1); + Py_XDECREF(p2); +} + +#endif // HAVE_PYTHON diff --git a/panda/src/ode/odeUtil_ext.h b/panda/src/ode/odeUtil_ext.h new file mode 100644 index 0000000000..ce78b6d098 --- /dev/null +++ b/panda/src/ode/odeUtil_ext.h @@ -0,0 +1,47 @@ +// Filename: odeUtil_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 ODEUTIL_EXT_H +#define ODEUTIL_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "config_ode.h" +#include "odeUtil.h" +#include "extension.h" +#include "py_panda.h" + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// NodePathCollection, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + static int collide2(const OdeGeom &geom1, const OdeGeom &geom2, + PyObject* arg, PyObject* callback); + +private: + static void near_callback(void*, dGeomID, dGeomID); + + static PyObject *_python_callback; +}; + +#endif // HAVE_PYTHON + +#endif // ODEUTIL_EXT_H diff --git a/panda/src/ode/p3ode_ext_composite.cxx b/panda/src/ode/p3ode_ext_composite.cxx new file mode 100644 index 0000000000..02ebaec64c --- /dev/null +++ b/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" diff --git a/panda/src/particlesystem/colorInterpolationManager.h b/panda/src/particlesystem/colorInterpolationManager.h index e43ecdb2f8..41fb390f9a 100755 --- a/panda/src/particlesystem/colorInterpolationManager.h +++ b/panda/src/particlesystem/colorInterpolationManager.h @@ -27,7 +27,7 @@ // function. //////////////////////////////////////////////////////////////////// -class ColorInterpolationFunction : public TypedReferenceCount { +class EXPCL_PANDAPHYSICS ColorInterpolationFunction : public TypedReferenceCount { PUBLISHED: // virtual string get_type(); @@ -62,7 +62,7 @@ private: // the segment. //////////////////////////////////////////////////////////////////// -class ColorInterpolationFunctionConstant : public ColorInterpolationFunction { +class EXPCL_PANDAPHYSICS ColorInterpolationFunctionConstant : public ColorInterpolationFunction { PUBLISHED: INLINE LColor get_color_a() const; @@ -103,7 +103,7 @@ private: // the segment. //////////////////////////////////////////////////////////////////// -class ColorInterpolationFunctionLinear : public ColorInterpolationFunctionConstant { +class EXPCL_PANDAPHYSICS ColorInterpolationFunctionLinear : public ColorInterpolationFunctionConstant { PUBLISHED: INLINE LColor get_color_b() const; @@ -147,7 +147,7 @@ private: // the end of the segment. //////////////////////////////////////////////////////////////////// -class ColorInterpolationFunctionStepwave : public ColorInterpolationFunctionLinear { +class EXPCL_PANDAPHYSICS ColorInterpolationFunctionStepwave : public ColorInterpolationFunctionLinear { PUBLISHED: INLINE PN_stdfloat get_width_a() const; INLINE PN_stdfloat get_width_b() const; @@ -195,7 +195,7 @@ private: // cycle. //////////////////////////////////////////////////////////////////// -class ColorInterpolationFunctionSinusoid : public ColorInterpolationFunctionLinear { +class EXPCL_PANDAPHYSICS ColorInterpolationFunctionSinusoid : public ColorInterpolationFunctionLinear { PUBLISHED: INLINE PN_stdfloat get_period() const; @@ -238,7 +238,7 @@ private: // also has a function associated with it. //////////////////////////////////////////////////////////////////// -class ColorInterpolationSegment : public ReferenceCount { +class EXPCL_PANDAPHYSICS ColorInterpolationSegment : public ReferenceCount { PUBLISHED: ColorInterpolationSegment(ColorInterpolationFunction* function, const PN_stdfloat &time_begin, const PN_stdfloat &time_end, const bool is_modulated, const int id); ColorInterpolationSegment(const ColorInterpolationSegment &s); @@ -280,7 +280,7 @@ protected: // general use. //////////////////////////////////////////////////////////////////// -class ColorInterpolationManager : public ReferenceCount { +class EXPCL_PANDAPHYSICS ColorInterpolationManager : public ReferenceCount { PUBLISHED: ColorInterpolationManager(); ColorInterpolationManager(const LColor &c); diff --git a/panda/src/pgraph/Sources.pp b/panda/src/pgraph/Sources.pp index ab3d0fe9b9..d0ddb0e0df 100644 --- a/panda/src/pgraph/Sources.pp +++ b/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 \ diff --git a/panda/src/pgraph/nodePath.I b/panda/src/pgraph/nodePath.I index d7eced9bf0..c5a0ae25ee 100644 --- a/panda/src/pgraph/nodePath.I +++ b/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 diff --git a/panda/src/pgraph/nodePath.cxx b/panda/src/pgraph/nodePath.cxx index 579d1157f2..216c7deb4b 100644 --- a/panda/src/pgraph/nodePath.cxx +++ b/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 - diff --git a/panda/src/pgraph/nodePath.h b/panda/src/pgraph/nodePath.h index c12ea43ce5..4bdbba41ff 100644 --- a/panda/src/pgraph/nodePath.h +++ b/panda/src/pgraph/nodePath.h @@ -179,12 +179,10 @@ PUBLISHED: INLINE NodePath(const NodePath ©); INLINE void operator = (const NodePath ©); -#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 diff --git a/panda/src/pgraph/nodePathCollection.cxx b/panda/src/pgraph/nodePathCollection.cxx index 2cebc6fa44..bd3ddfbcc6 100644 --- a/panda/src/pgraph/nodePathCollection.cxx +++ b/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 diff --git a/panda/src/pgraph/nodePathCollection.h b/panda/src/pgraph/nodePathCollection.h index 24cfe3f208..6265f85d16 100644 --- a/panda/src/pgraph/nodePathCollection.h +++ b/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); diff --git a/panda/src/pgraph/nodePathCollection_ext.I b/panda/src/pgraph/nodePathCollection_ext.I new file mode 100644 index 0000000000..d88ba08295 --- /dev/null +++ b/panda/src/pgraph/nodePathCollection_ext.I @@ -0,0 +1,51 @@ +// Filename: nodePathCollection_ext.I +// 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 CPPPARSER +#ifdef STDFLOAT_DOUBLE +IMPORT_THIS struct Dtool_PyTypedObject Dtool_LPoint3d; +#else +IMPORT_THIS struct Dtool_PyTypedObject Dtool_LPoint3f; +#endif +#endif + +//////////////////////////////////////////////////////////////////// +// Function: Extension::get_tight_bounds +// Access: Published +// Description: Returns the tight bounds as a 2-tuple of LPoint3 +// objects. This is a convenience function for Python +// users, among which the use of calc_tight_bounds +// may be confusing. +// Returns None if calc_tight_bounds returned false. +//////////////////////////////////////////////////////////////////// +INLINE PyObject *Extension:: +get_tight_bounds() const { + LPoint3 *min_point = new LPoint3; + LPoint3 *max_point = new LPoint3; + + if (_this->calc_tight_bounds(*min_point, *max_point)) { +#ifdef STDFLOAT_DOUBLE + PyObject *min_inst = DTool_CreatePyInstance((void*) min_point, Dtool_LPoint3d, true, false); + PyObject *max_inst = DTool_CreatePyInstance((void*) max_point, Dtool_LPoint3d, true, false); +#else + PyObject *min_inst = DTool_CreatePyInstance((void*) min_point, Dtool_LPoint3f, true, false); + PyObject *max_inst = DTool_CreatePyInstance((void*) max_point, Dtool_LPoint3f, true, false); +#endif + return Py_BuildValue("NN", min_inst, max_inst); + + } else { + Py_INCREF(Py_None); + return Py_None; + } +} diff --git a/panda/src/pgraph/nodePathCollection_ext.cxx b/panda/src/pgraph/nodePathCollection_ext.cxx new file mode 100644 index 0000000000..324e746d47 --- /dev/null +++ b/panda/src/pgraph/nodePathCollection_ext.cxx @@ -0,0 +1,48 @@ +// Filename: nodePathCollection_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 "nodePathCollection_ext.h" + +#ifdef HAVE_PYTHON + +//////////////////////////////////////////////////////////////////// +// Function: NodePathCollection::__reduce__ +// Access: Published +// Description: This special Python method is implement to provide +// support for the pickle module. +//////////////////////////////////////////////////////////////////// +PyObject *Extension:: +__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 diff --git a/panda/src/pgraph/nodePathCollection_ext.h b/panda/src/pgraph/nodePathCollection_ext.h new file mode 100644 index 0000000000..96dc6f9e19 --- /dev/null +++ b/panda/src/pgraph/nodePathCollection_ext.h @@ -0,0 +1,44 @@ +// Filename: nodePathCollection_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 NODEPATHCOLLECTION_EXT_H +#define NODEPATHCOLLECTION_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "extension.h" +#include "nodePathCollection.h" +#include "py_panda.h" + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// NodePathCollection, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + PyObject *__reduce__(PyObject *self) const; + + INLINE PyObject *get_tight_bounds() const; +}; + +#include "nodePathCollection_ext.I" + +#endif // HAVE_PYTHON + +#endif // NODEPATHCOLLECTION_EXT_H diff --git a/panda/src/pgraph/nodePath_ext.I b/panda/src/pgraph/nodePath_ext.I new file mode 100644 index 0000000000..a97a29fb59 --- /dev/null +++ b/panda/src/pgraph/nodePath_ext.I @@ -0,0 +1,197 @@ +// Filename: nodePath_ext.I +// 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 CPPPARSER +#ifdef STDFLOAT_DOUBLE +IMPORT_THIS struct Dtool_PyTypedObject Dtool_LPoint3d; +#else +IMPORT_THIS struct Dtool_PyTypedObject Dtool_LPoint3f; +#endif +#endif + +//////////////////////////////////////////////////////////////////// +// Function: Extension::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 Extension:: +get_python_tag_keys(vector_string &keys) const { + nassertv_always(!_this->is_empty()); + _this->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 *Extension:: +get_tag_keys() const { + // An empty NodePath returns None + if (_this->is_empty()) { + Py_INCREF(Py_None); + return Py_None; + } + return _this->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 *Extension:: +get_python_tag_keys() const { + // An empty NodePath returns None + if (_this->is_empty()) { + Py_INCREF(Py_None); + return Py_None; + } + return _this->node()->get_python_tag_keys(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::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 Extension:: +set_python_tag(const string &key, PyObject *value) { + nassertv_always(!_this->is_empty()); + _this->node()->set_python_tag(key, value); +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::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 *Extension:: +get_python_tag(const string &key) const { + // An empty NodePath quietly returns no tags. This makes + // get_net_python_tag() easier to implement. + if (_this->is_empty()) { + Py_INCREF(Py_None); + return Py_None; + } + return _this->node()->get_python_tag(key); +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::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 Extension:: +has_python_tag(const string &key) const { + // An empty NodePath quietly has no tags. This makes has_net_python_tag() + // easier to implement. + if (_this->is_empty()) { + return false; + } + return _this->node()->has_python_tag(key); +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::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 Extension:: +clear_python_tag(const string &key) { + nassertv_always(!_this->is_empty()); + _this->node()->clear_python_tag(key); +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::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 *Extension:: +get_net_python_tag(const string &key) const { + NodePath tag_np = find_net_python_tag(key); + return invoke_extension(&tag_np).get_python_tag(key); +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::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 Extension:: +has_net_python_tag(const string &key) const { + return !find_net_python_tag(key).is_empty(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::get_tight_bounds +// Access: Published +// Description: Returns the tight bounds as a 2-tuple of LPoint3 +// objects. This is a convenience function for Python +// users, among which the use of calc_tight_bounds +// may be confusing. +// Returns None if calc_tight_bounds returned false. +//////////////////////////////////////////////////////////////////// +INLINE PyObject *Extension:: +get_tight_bounds() const { + LPoint3 *min_point = new LPoint3; + LPoint3 *max_point = new LPoint3; + + if (_this->calc_tight_bounds(*min_point, *max_point)) { +#ifdef STDFLOAT_DOUBLE + PyObject *min_inst = DTool_CreatePyInstance((void*) min_point, Dtool_LPoint3d, true, false); + PyObject *max_inst = DTool_CreatePyInstance((void*) max_point, Dtool_LPoint3d, true, false); +#else + PyObject *min_inst = DTool_CreatePyInstance((void*) min_point, Dtool_LPoint3f, true, false); + PyObject *max_inst = DTool_CreatePyInstance((void*) max_point, Dtool_LPoint3f, true, false); +#endif + return Py_BuildValue("NN", min_inst, max_inst); + + } else { + Py_INCREF(Py_None); + return Py_None; + } +} diff --git a/panda/src/pgraph/nodePath_ext.cxx b/panda/src/pgraph/nodePath_ext.cxx new file mode 100644 index 0000000000..da66754c42 --- /dev/null +++ b/panda/src/pgraph/nodePath_ext.cxx @@ -0,0 +1,232 @@ +// Filename: nodePath_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 "nodePath_ext.h" +#include "typedWritable_ext.h" + +#ifdef HAVE_PYTHON + +#ifndef CPPPARSER +extern EXPCL_PANDA_PUTIL Dtool_PyTypedObject Dtool_BamWriter; +extern EXPCL_PANDA_PUTIL Dtool_PyTypedObject Dtool_BamReader; +#endif // CPPPARSER + +//////////////////////////////////////////////////////////////////// +// Function: Extension::__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 Extension:: +__copy__() const { + if (_this->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(_this->node()->__copy__()); +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::__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 *Extension:: +__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 (_this->is_empty()) { + np_dupe = new NodePath(*_this); + } else { + np_dupe = new NodePath(_this->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; +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::__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 *Extension:: +__reduce__(PyObject *self) const { + return __reduce_persist__(self, NULL); +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::__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 *Extension:: +__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 (!_this->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 = Extension::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 = Extension::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; +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::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 Extension:: +find_net_python_tag(const string &key) const { + if (_this->is_empty()) { + return NodePath::not_found(); + } + if (has_python_tag(key)) { + return *_this; + } + NodePath parent = _this->get_parent(); + return invoke_extension(&parent).find_net_python_tag(key); +} + +//////////////////////////////////////////////////////////////////// +// 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); +} + +//////////////////////////////////////////////////////////////////// +// 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 + diff --git a/panda/src/pgraph/nodePath_ext.h b/panda/src/pgraph/nodePath_ext.h new file mode 100644 index 0000000000..c91a462bff --- /dev/null +++ b/panda/src/pgraph/nodePath_ext.h @@ -0,0 +1,63 @@ +// Filename: nodePath_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 NODEPATH_EXT_H +#define NODEPATH_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "extension.h" +#include "nodePath.h" +#include "py_panda.h" + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// NodePath, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + NodePath __copy__() const; + PyObject *__deepcopy__(PyObject *self, PyObject *memo) const; + PyObject *__reduce__(PyObject *self) const; + PyObject *__reduce_persist__(PyObject *self, PyObject *pickler) const; + + 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; + + INLINE PyObject *get_tight_bounds() const; +}; + +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 + +#include "nodePath_ext.I" + +#endif // HAVE_PYTHON + +#endif // NODEPATH_EXT_H diff --git a/panda/src/pgraphnodes/shaderGenerator.cxx b/panda/src/pgraphnodes/shaderGenerator.cxx index 1d86eaef62..14bae605fe 100644 --- a/panda/src/pgraphnodes/shaderGenerator.cxx +++ b/panda/src/pgraphnodes/shaderGenerator.cxx @@ -624,15 +624,13 @@ synthesize_shader(const RenderState *rs) { // These variables will hold the results of register allocation. - char *ntangent_vreg = 0; - char *ntangent_freg = 0; - char *nbinormal_vreg = 0; - char *nbinormal_freg = 0; - char *htangent_vreg = 0; - char *hbinormal_vreg = 0; - pvector texcoord_freg; - pvector dlightcoord_freg; - pvector slightcoord_freg; + char *tangent_freg = 0; + char *binormal_freg = 0; + string tangent_input; + string binormal_input; + pmap texcoord_fregs; + pvector dlightcoord_fregs; + pvector slightcoord_fregs; char *world_position_freg = 0; char *world_normal_freg = 0; char *eye_position_freg = 0; @@ -661,11 +659,39 @@ synthesize_shader(const RenderState *rs) { for (int i = 0; i < _num_textures; ++i) { TextureStage *stage = texture->get_on_stage(i); if (!tex_gen->has_stage(stage)) { - texcoord_freg.push_back(alloc_freg()); - text << "\t in float4 vtx_texcoord" << i << " : " << alloc_vreg() << ",\n"; - text << "\t out float4 l_texcoord" << i << " : " << texcoord_freg[i] << ",\n"; - } else { - texcoord_freg.push_back(NULL); + const InternalName *texcoord_name = stage->get_texcoord_name(); + + if (texcoord_fregs.count(texcoord_name) == 0) { + char *freg = alloc_freg(); + string tcname = texcoord_name->join("_"); + texcoord_fregs[texcoord_name] = freg; + + text << "\t in float4 vtx_" << tcname << " : " << alloc_vreg() << ",\n"; + text << "\t out float4 l_" << tcname << " : " << freg << ",\n"; + } + } + + if ((_map_index_normal == i && (_lighting || _out_aux_normal) && _auto_normal_on) || _map_index_height == i) { + const InternalName *texcoord_name = stage->get_texcoord_name(); + PT(InternalName) tangent_name = InternalName::get_tangent(); + PT(InternalName) binormal_name = InternalName::get_binormal(); + + if (texcoord_name != InternalName::get_texcoord()) { + tangent_name = tangent_name->append(texcoord_name->get_basename()); + binormal_name = binormal_name->append(texcoord_name->get_basename()); + } + tangent_input = tangent_name->join("_"); + binormal_input = binormal_name->join("_"); + + text << "\t in float4 vtx_" << tangent_input << " : " << alloc_vreg() << ",\n"; + text << "\t in float4 vtx_" << binormal_input << " : " << alloc_vreg() << ",\n"; + + if (_map_index_normal == i && (_lighting || _out_aux_normal) && _auto_normal_on) { + tangent_freg = alloc_freg(); + binormal_freg = alloc_freg(); + text << "\t out float4 l_tangent : " << tangent_freg << ",\n"; + text << "\t out float4 l_binormal : " << binormal_freg << ",\n"; + } } } if (_vertex_colors) { @@ -697,49 +723,27 @@ synthesize_shader(const RenderState *rs) { text << "\t in float4 vtx_normal : NORMAL,\n"; } if (_map_index_height >= 0) { - htangent_vreg = alloc_vreg(); - hbinormal_vreg = alloc_vreg(); - if (_map_index_normal == _map_index_height) { - ntangent_vreg = htangent_vreg; - nbinormal_vreg = hbinormal_vreg; - } - text << "\t in float4 vtx_tangent" << _map_index_height << " : " << htangent_vreg << ",\n"; - text << "\t in float4 vtx_binormal" << _map_index_height << " : " << hbinormal_vreg << ",\n"; text << "\t uniform float4 mspos_view,\n"; text << "\t out float3 l_eyevec,\n"; } if (_lighting) { - if (_map_index_normal >= 0 && _auto_normal_on) { - // If we had a height map and it used the same stage, that means we already have those inputs. - if (_map_index_normal != _map_index_height) { - ntangent_vreg = alloc_vreg(); - nbinormal_vreg = alloc_vreg(); - // NB. If we used TANGENT and BINORMAL, Cg would have them overlap with TEXCOORD6-7. - text << "\t in float4 vtx_tangent" << _map_index_normal << " : " << ntangent_vreg << ",\n"; - text << "\t in float4 vtx_binormal" << _map_index_normal << " : " << nbinormal_vreg << ",\n"; - } - ntangent_freg = alloc_freg(); - nbinormal_freg = alloc_freg(); - text << "\t out float4 l_tangent : " << ntangent_freg << ",\n"; - text << "\t out float4 l_binormal : " << nbinormal_freg << ",\n"; - } if (_shadows && _auto_shadow_on) { for (int i=0; i < (int)_dlights.size(); i++) { if (_dlights[i]->_shadow_caster) { - dlightcoord_freg.push_back(alloc_freg()); + dlightcoord_fregs.push_back(alloc_freg()); text << "\t uniform float4x4 trans_model_to_clip_of_dlight" << i << ",\n"; - text << "\t out float4 l_dlightcoord" << i << " : " << dlightcoord_freg[i] << ",\n"; + text << "\t out float4 l_dlightcoord" << i << " : " << dlightcoord_fregs[i] << ",\n"; } else { - dlightcoord_freg.push_back(NULL); + dlightcoord_fregs.push_back(NULL); } } for (int i=0; i < (int)_slights.size(); i++) { if (_slights[i]->_shadow_caster) { - slightcoord_freg.push_back(alloc_freg()); + slightcoord_fregs.push_back(alloc_freg()); text << "\t uniform float4x4 trans_model_to_clip_of_slight" << i << ",\n"; - text << "\t out float4 l_slightcoord" << i << " : " << slightcoord_freg[i] << ",\n"; + text << "\t out float4 l_slightcoord" << i << " : " << slightcoord_fregs[i] << ",\n"; } else { - slightcoord_freg.push_back(NULL); + slightcoord_fregs.push_back(NULL); } } } @@ -770,18 +774,19 @@ synthesize_shader(const RenderState *rs) { text << "\t l_eye_normal.xyz = mul((float3x3)tpose_view_to_model, vtx_normal.xyz);\n"; text << "\t l_eye_normal.w = 0;\n"; } - for (int i = 0; i < _num_textures; ++i) { - if (!tex_gen->has_stage(texture->get_on_stage(i))) { - text << "\t l_texcoord" << i << " = vtx_texcoord" << i << ";\n"; - } + pmap::const_iterator it; + for (it = texcoord_fregs.begin(); it != texcoord_fregs.end(); ++it) { + // Pass through all texcoord inputs as-is. + string tcname = it->first->join("_"); + text << "\t l_" << tcname << " = vtx_" << tcname << ";\n"; } if (_vertex_colors) { text << "\t l_color = vtx_color;\n"; } - if (_lighting && (_map_index_normal >= 0 && _auto_normal_on)) { - text << "\t l_tangent.xyz = mul((float3x3)tpose_view_to_model, vtx_tangent" << _map_index_normal << ".xyz);\n"; + if ((_lighting || _out_aux_normal) && (_map_index_normal >= 0 && _auto_normal_on)) { + text << "\t l_tangent.xyz = mul((float3x3)tpose_view_to_model, vtx_" << tangent_input << ".xyz);\n"; text << "\t l_tangent.w = 0;\n"; - text << "\t l_binormal.xyz = mul((float3x3)tpose_view_to_model, -vtx_binormal" << _map_index_normal << ".xyz);\n"; + text << "\t l_binormal.xyz = mul((float3x3)tpose_view_to_model, -vtx_" << binormal_input << ".xyz);\n"; text << "\t l_binormal.w = 0;\n"; } if (_shadows && _auto_shadow_on) { @@ -799,8 +804,8 @@ synthesize_shader(const RenderState *rs) { } if (_map_index_height >= 0) { text << "\t float3 eyedir = mspos_view.xyz - vtx_position.xyz;\n"; - text << "\t l_eyevec.x = dot(vtx_tangent" << _map_index_height << ".xyz, eyedir);\n"; - text << "\t l_eyevec.y = dot(vtx_binormal" << _map_index_height << ".xyz, eyedir);\n"; + text << "\t l_eyevec.x = dot(vtx_" << tangent_input << ".xyz, eyedir);\n"; + text << "\t l_eyevec.y = dot(vtx_" << binormal_input << ".xyz, eyedir);\n"; text << "\t l_eyevec.z = dot(vtx_normal.xyz, eyedir);\n"; text << "\t l_eyevec = normalize(l_eyevec);\n"; } @@ -826,22 +831,22 @@ synthesize_shader(const RenderState *rs) { if (_need_eye_normal) { text << "\t in float4 l_eye_normal : " << eye_normal_freg << ",\n"; } + for (it = texcoord_fregs.begin(); it != texcoord_fregs.end(); ++it) { + text << "\t in float4 l_" << it->first->join("_") << " : " << it->second << ",\n"; + } const TexMatrixAttrib *tex_matrix = DCAST(TexMatrixAttrib, rs->get_attrib_def(TexMatrixAttrib::get_class_slot())); for (int i=0; i<_num_textures; i++) { TextureStage *stage = texture->get_on_stage(i); Texture *tex = texture->get_on_texture(stage); nassertr(tex != NULL, NULL); text << "\t uniform sampler" << texture_type_as_string(tex->get_texture_type()) << " tex_" << i << ",\n"; - if (!tex_gen->has_stage(stage)) { - text << "\t in float4 l_texcoord" << i << " : " << texcoord_freg[i] << ",\n"; - } if (tex_matrix->has_stage(stage)) { text << "\t uniform float4x4 texmat_" << i << ",\n"; } } - if (_lighting && (_map_index_normal >= 0 && _auto_normal_on)) { - text << "\t in float3 l_tangent : " << ntangent_freg << ",\n"; - text << "\t in float3 l_binormal : " << nbinormal_freg << ",\n"; + if ((_lighting || _out_aux_normal) && (_map_index_normal >= 0 && _auto_normal_on)) { + text << "\t in float3 l_tangent : " << tangent_freg << ",\n"; + text << "\t in float3 l_binormal : " << binormal_freg << ",\n"; } if (_lighting) { for (int i=0; i < (int)_alights.size(); i++) { @@ -855,7 +860,7 @@ synthesize_shader(const RenderState *rs) { } else { text << "\t uniform sampler2D k_dlighttex" << i << ",\n"; } - text << "\t in float4 l_dlightcoord" << i << " : " << dlightcoord_freg[i] << ",\n"; + text << "\t in float4 l_dlightcoord" << i << " : " << dlightcoord_fregs[i] << ",\n"; } } for (int i=0; i < (int)_plights.size(); i++) { @@ -870,7 +875,7 @@ synthesize_shader(const RenderState *rs) { } else { text << "\t uniform sampler2D k_slighttex" << i << ",\n"; } - text << "\t in float4 l_slightcoord" << i << " : " << slightcoord_freg[i] << ",\n"; + text << "\t in float4 l_slightcoord" << i << " : " << slightcoord_fregs[i] << ",\n"; } } if (_need_material_props) { @@ -918,26 +923,30 @@ synthesize_shader(const RenderState *rs) { if (tex_gen != NULL && tex_gen->has_stage(stage)) { switch (tex_gen->get_mode(stage)) { case TexGenAttrib::M_world_position: - text << "\t float4 l_texcoord" << i << " = l_world_position;\n"; + text << "\t float4 texcoord" << i << " = l_world_position;\n"; break; case TexGenAttrib::M_world_normal: - text << "\t float4 l_texcoord" << i << " = l_world_normal;\n"; + text << "\t float4 texcoord" << i << " = l_world_normal;\n"; break; case TexGenAttrib::M_eye_position: - text << "\t float4 l_texcoord" << i << " = l_eye_position;\n"; + text << "\t float4 texcoord" << i << " = l_eye_position;\n"; break; case TexGenAttrib::M_eye_normal: - text << "\t float4 l_texcoord" << i << " = l_eye_normal;\n"; - text << "\t l_texcoord" << i << ".w = 1.0f;\n"; + text << "\t float4 texcoord" << i << " = l_eye_normal;\n"; + text << "\t texcoord" << i << ".w = 1.0f;\n"; break; default: pgraph_cat.error() << "Unsupported TexGenAttrib mode\n"; - text << "\t float4 l_texcoord" << i << " = float4(0, 0, 0, 0);\n"; + text << "\t float4 texcoord" << i << " = float4(0, 0, 0, 0);\n"; } + } else { + // Cg seems to be able to optimize this temporary away when appropriate. + const InternalName *texcoord_name = stage->get_texcoord_name(); + text << "\t float4 texcoord" << i << " = l_" << texcoord_name->join("_") << ";\n"; } if (tex_matrix != NULL && tex_matrix->has_stage(stage)) { - text << "\t l_texcoord" << i << " = mul(texmat_" << i << ", l_texcoord" << i << ");\n"; - text << "\t l_texcoord" << i << ".xyz /= l_texcoord" << i << ".w;\n"; + text << "\t texcoord" << i << " = mul(texmat_" << i << ", texcoord" << i << ");\n"; + text << "\t texcoord" << i << ".xyz /= texcoord" << i << ".w;\n"; } } text << "\t // Fetch all textures.\n"; @@ -945,7 +954,7 @@ synthesize_shader(const RenderState *rs) { Texture *tex = texture->get_on_texture(texture->get_on_stage(_map_index_height)); nassertr(tex != NULL, NULL); text << "\t float4 tex" << _map_index_height << " = tex" << texture_type_as_string(tex->get_texture_type()); - text << "(tex_" << _map_index_height << ", l_texcoord" << _map_index_height << "."; + text << "(tex_" << _map_index_height << ", texcoord" << _map_index_height << "."; switch (tex->get_texture_type()) { case Texture::TT_cube_map: case Texture::TT_3d_texture: @@ -985,21 +994,21 @@ synthesize_shader(const RenderState *rs) { nassertr(tex != NULL, NULL); // Parallax mapping pushes the texture coordinates of the other textures away from the camera. if (_map_index_height >= 0 && parallax_mapping_samples > 0) { - text << "\t l_texcoord" << i << ".xyz -= parallax_offset;\n"; + text << "\t texcoord" << i << ".xyz -= parallax_offset;\n"; } text << "\t float4 tex" << i << " = tex" << texture_type_as_string(tex->get_texture_type()); - text << "(tex_" << i << ", l_texcoord" << i << "."; + text << "(tex_" << i << ", texcoord" << i << "."; switch(tex->get_texture_type()) { case Texture::TT_cube_map: case Texture::TT_3d_texture: case Texture::TT_2d_texture_array: - text << "xyz"; + text << "xyz"; break; - case Texture::TT_2d_texture: + case Texture::TT_2d_texture: text << "xy"; break; - case Texture::TT_1d_texture: - text << "x"; + case Texture::TT_1d_texture: + text << "x"; break; default: break; @@ -1007,7 +1016,7 @@ synthesize_shader(const RenderState *rs) { text << ");\n"; } } - if (_lighting) { + if (_lighting || _out_aux_normal) { if (_map_index_normal >= 0 && _auto_normal_on) { text << "\t // Translate tangent-space normal in map to view-space.\n"; text << "\t float3 tsnormal = ((float3)tex" << _map_index_normal << " * 2) - 1;\n"; @@ -1242,7 +1251,7 @@ synthesize_shader(const RenderState *rs) { } else if (_flat_colors) { text << "\t result = attr_color;\n"; } else { - text << "\t result = float4(1,1,1,1);\n"; + text << "\t result = float4(1, 1, 1, 1);\n"; } } diff --git a/panda/src/pgraphnodes/shaderGenerator.h b/panda/src/pgraphnodes/shaderGenerator.h index 0c588df8a1..d08a3976a8 100644 --- a/panda/src/pgraphnodes/shaderGenerator.h +++ b/panda/src/pgraphnodes/shaderGenerator.h @@ -86,8 +86,8 @@ protected: int _vtregs_used; int _ftregs_used; void reset_register_allocator(); - INLINE char *alloc_vreg(); - INLINE char *alloc_freg(); + char *alloc_vreg(); + char *alloc_freg(); // RenderState analysis information. Created by analyze_renderstate: diff --git a/panda/src/physics/linearUserDefinedForce.h b/panda/src/physics/linearUserDefinedForce.h index 51dd6f74ce..2a65583bc7 100644 --- a/panda/src/physics/linearUserDefinedForce.h +++ b/panda/src/physics/linearUserDefinedForce.h @@ -27,7 +27,7 @@ // in the makefile when the time is right or this class // becomes needed... //////////////////////////////////////////////////////////////////// -class LinearUserDefinedForce : public LinearForce { +class EXPCL_PANDAPHYSICS LinearUserDefinedForce : public LinearForce { PUBLISHED: LinearUserDefinedForce(LVector3 (*proc)(const PhysicsObject *) = NULL, PN_stdfloat a = 1.0f, diff --git a/panda/src/physx/physxJointDriveDesc.h b/panda/src/physx/physxJointDriveDesc.h index 73bc7f80a1..991e3d051a 100644 --- a/panda/src/physx/physxJointDriveDesc.h +++ b/panda/src/physx/physxJointDriveDesc.h @@ -25,7 +25,7 @@ // Description : Used to describe drive properties for a // PhysxD6Joint. //////////////////////////////////////////////////////////////////// -class PhysxJointDriveDesc : public PhysxEnums { +class EXPCL_PANDAPHYSX PhysxJointDriveDesc : public PhysxEnums { PUBLISHED: INLINE PhysxJointDriveDesc(); diff --git a/panda/src/physx/physxJointLimitDesc.h b/panda/src/physx/physxJointLimitDesc.h index aedd83ec29..3665fa4cf7 100644 --- a/panda/src/physx/physxJointLimitDesc.h +++ b/panda/src/physx/physxJointLimitDesc.h @@ -23,7 +23,7 @@ // Class : PhysxJointLimitDesc // Description : Describes a joint limit. //////////////////////////////////////////////////////////////////// -class PhysxJointLimitDesc { +class EXPCL_PANDAPHYSX PhysxJointLimitDesc { PUBLISHED: INLINE PhysxJointLimitDesc(); diff --git a/panda/src/physx/physxJointLimitSoftDesc.h b/panda/src/physx/physxJointLimitSoftDesc.h index 52c78b7331..1d5f9c7b62 100644 --- a/panda/src/physx/physxJointLimitSoftDesc.h +++ b/panda/src/physx/physxJointLimitSoftDesc.h @@ -23,7 +23,7 @@ // Class : PhysxJointLimitSoftDesc // Description : Describes a joint limit. //////////////////////////////////////////////////////////////////// -class PhysxJointLimitSoftDesc { +class EXPCL_PANDAPHYSX PhysxJointLimitSoftDesc { PUBLISHED: INLINE PhysxJointLimitSoftDesc(); diff --git a/panda/src/physx/physxMotorDesc.h b/panda/src/physx/physxMotorDesc.h index 4ad55a1671..fd3595fba1 100644 --- a/panda/src/physx/physxMotorDesc.h +++ b/panda/src/physx/physxMotorDesc.h @@ -28,7 +28,7 @@ // - PhysxPulleyJoint // - PhysxRevoluteJoint //////////////////////////////////////////////////////////////////// -class PhysxMotorDesc { +class EXPCL_PANDAPHYSX PhysxMotorDesc { PUBLISHED: INLINE PhysxMotorDesc(); diff --git a/panda/src/physx/physxSpringDesc.h b/panda/src/physx/physxSpringDesc.h index 29d85ebcf1..f695a66c0c 100644 --- a/panda/src/physx/physxSpringDesc.h +++ b/panda/src/physx/physxSpringDesc.h @@ -25,7 +25,7 @@ // integrated, so even high spring and damper // coefficients should be robust. //////////////////////////////////////////////////////////////////// -class PhysxSpringDesc { +class EXPCL_PANDAPHYSX PhysxSpringDesc { PUBLISHED: INLINE PhysxSpringDesc(); diff --git a/panda/src/pnmimage/Sources.pp b/panda/src/pnmimage/Sources.pp index 76f67ed774..8ab8efb55b 100644 --- a/panda/src/pnmimage/Sources.pp +++ b/panda/src/pnmimage/Sources.pp @@ -12,6 +12,7 @@ #define SOURCES \ config_pnmimage.h \ pfmFile.I pfmFile.h \ + pfmFile_ext.cxx pfmFile_ext.h \ pnmbitio.h \ pnmBrush.h pnmBrush.I \ pnmFileType.h pnmFileTypeRegistry.h pnmImage.I \ @@ -36,6 +37,7 @@ #define INSTALL_HEADERS \ config_pnmimage.h \ pfmFile.I pfmFile.h \ + pfmFile_ext.cxx pfmFile_ext.h \ pnmBrush.h pnmBrush.I \ pnmFileType.h pnmFileTypeRegistry.h pnmImage.I \ pnmImage.h pnmImageHeader.I pnmImageHeader.h \ diff --git a/panda/src/pnmimage/pfmFile.cxx b/panda/src/pnmimage/pfmFile.cxx index b78a3dcbab..06e13106bd 100644 --- a/panda/src/pnmimage/pfmFile.cxx +++ b/panda/src/pnmimage/pfmFile.cxx @@ -1467,6 +1467,29 @@ copy_channel(int to_channel, const PfmFile &other, int from_channel) { } } +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::copy_channel_masked +// Access: Published +// Description: Copies just the specified channel values from the +// indicated PfmFile, but only where the other file has +// a data point. +//////////////////////////////////////////////////////////////////// +void PfmFile:: +copy_channel_masked(int to_channel, const PfmFile &other, int from_channel) { + nassertv(is_valid() && other.is_valid()); + nassertv(other._x_size == _x_size && other._y_size == _y_size); + nassertv(to_channel >= 0 && to_channel < get_num_channels() && + from_channel >= 0 && from_channel < other.get_num_channels()); + + for (int yi = 0; yi < _y_size; ++yi) { + for (int xi = 0; xi < _x_size; ++xi) { + if (other.has_point(xi, yi)) { + set_channel(xi, yi, to_channel, other.get_channel(xi, yi, from_channel)); + } + } + } +} + //////////////////////////////////////////////////////////////////// // Function: PfmFile::apply_crop // Access: Published diff --git a/panda/src/pnmimage/pfmFile.h b/panda/src/pnmimage/pfmFile.h index 723940ce5b..7f22ef79c0 100644 --- a/panda/src/pnmimage/pfmFile.h +++ b/panda/src/pnmimage/pfmFile.h @@ -95,7 +95,7 @@ PUBLISHED: BLOCKING bool calc_autocrop(int &x_begin, int &x_end, int &y_begin, int &y_end) const; BLOCKING INLINE bool calc_autocrop(LVecBase4f &range) const; BLOCKING INLINE bool calc_autocrop(LVecBase4d &range) const; - + bool is_row_empty(int y, int x_begin, int x_end) const; bool is_column_empty(int x, int y_begin, int y_end) const; @@ -121,6 +121,7 @@ PUBLISHED: BLOCKING void reverse_distort(const PfmFile &dist, PN_float32 scale_factor = 1.0); BLOCKING void merge(const PfmFile &other); BLOCKING void copy_channel(int to_channel, const PfmFile &other, int from_channel); + BLOCKING void copy_channel_masked(int to_channel, const PfmFile &other, int from_channel); BLOCKING void apply_crop(int x_begin, int x_end, int y_begin, int y_end); BLOCKING void clear_to_texcoords(int x_size, int y_size); @@ -139,6 +140,12 @@ PUBLISHED: void output(ostream &out) const; + EXTENSION(PyObject *get_points() const); + +#if PY_VERSION_HEX >= 0x02060000 + EXTENSION(int __getbuffer__(PyObject *self, Py_buffer *view, int flags) const); +#endif + public: INLINE const vector_float &get_table() const; INLINE void swap_table(vector_float &table); diff --git a/panda/src/pnmimage/pfmFile_ext.cxx b/panda/src/pnmimage/pfmFile_ext.cxx new file mode 100644 index 0000000000..c28ed79b57 --- /dev/null +++ b/panda/src/pnmimage/pfmFile_ext.cxx @@ -0,0 +1,132 @@ +// Filename: pfmFile_ext.I +// Created by: rdb (26Feb14) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "pfmFile_ext.h" + +#ifdef HAVE_PYTHON + +#ifndef CPPPARSER +IMPORT_THIS struct Dtool_PyTypedObject Dtool_LPoint2f; +IMPORT_THIS struct Dtool_PyTypedObject Dtool_LPoint3f; +IMPORT_THIS struct Dtool_PyTypedObject Dtool_LPoint4f; +#endif + +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::get_points +// Access: Published +// Description: Returns a list of all of the points. +//////////////////////////////////////////////////////////////////// +PyObject *Extension:: +get_points() const { + int num_points = _this->get_x_size() * _this->get_y_size(); + PyObject *list = PyList_New(num_points); + const vector_float &table = _this->get_table(); + + switch (_this->get_num_channels()) { + case 1: + for (int i = 0; i < num_points; ++i) { + PyList_SET_ITEM(list, i, PyFloat_FromDouble(table[i])); + } + break; + + case 2: + for (int i = 0; i < num_points; ++i) { + LPoint2f *point = (LPoint2f *) &(table[i * 2]); + PyObject *item = DTool_CreatePyInstance((void *)point, Dtool_LPoint2f, false, true); + PyList_SET_ITEM(list, i, item); + } + break; + + case 3: + for (int i = 0; i < num_points; ++i) { + LPoint3f *point = (LPoint3f *) &(table[i * 3]); + PyObject *item = DTool_CreatePyInstance((void *)point, Dtool_LPoint3f, false, true); + PyList_SET_ITEM(list, i, item); + } + break; + + case 4: + for (int i = 0; i < num_points; ++i) { + LPoint4f *point = (LPoint4f *) &(table[i * 4]); + PyObject *item = DTool_CreatePyInstance((void *)point, Dtool_LPoint4f, false, true); + PyList_SET_ITEM(list, i, item); + } + break; + + default: + Py_DECREF(list); + Py_INCREF(Py_None); + return Py_None; + } + + return list; +} + +#if PY_VERSION_HEX >= 0x02060000 +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::__getbuffer__ +// Access: Published +// Description: This is a very low-level function that returns a +// read-only multiview into the internal table of +// floating-point numbers. Use this method at your own +// risk. +//////////////////////////////////////////////////////////////////// +int Extension:: +__getbuffer__(PyObject *self, Py_buffer *view, int flags) const { + + if ((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE) { + PyErr_SetString(PyExc_BufferError, + "Object is not writable."); + return -1; + } + + // Since we have absolutely no guarantees about the lifetime + // of this object or the continued validity of the data pointer, + // we should arguably make a copy of the data. However, since + // the whole point of this method is to provide fast access to + // the underlying data, perhaps we can trust the user to handle + // the copy operation himself if he needs to. + const vector_float &table = _this->get_table(); + int channels = _this->get_num_channels(); + int num_pixels = _this->get_x_size() * _this->get_y_size(); + + if (self != NULL) { + Py_INCREF(self); + } + view->obj = self; + view->buf = (void *) &(table[0]); + view->len = 4 * table.size(); + view->readonly = 1; + view->itemsize = 4; + view->format = NULL; + if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) { + view->format = (char *) "f"; + } + view->ndim = 2; + view->shape = NULL; + if ((flags & PyBUF_ND) == PyBUF_ND) { + // If you're leaking and you know it, clap your hands! + view->shape = new Py_ssize_t[2]; + view->shape[0] = num_pixels; + view->shape[1] = channels; + } + view->strides = NULL; + view->suboffsets = NULL; + + return 0; +} + +#endif // PY_VERSION_HEX >= 0x02060000 + +#endif // HAVE_PYTHON diff --git a/panda/src/pnmimage/pfmFile_ext.h b/panda/src/pnmimage/pfmFile_ext.h new file mode 100644 index 0000000000..2018d8e394 --- /dev/null +++ b/panda/src/pnmimage/pfmFile_ext.h @@ -0,0 +1,44 @@ +// Filename: pfmFile_ext.h +// Created by: rdb (26Feb14) +// +//////////////////////////////////////////////////////////////////// +// +// 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 PFMFILE_EXT_H +#define PFMFILE_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "extension.h" +#include "pfmFile.h" +#include "py_panda.h" + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// PfmFile, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + PyObject *get_points() const; + +#if PY_VERSION_HEX >= 0x02060000 + int __getbuffer__(PyObject *self, Py_buffer *view, int flags) const; +#endif +}; + +#endif // HAVE_PYTHON + +#endif // PFMFILE_EXT_H diff --git a/panda/src/pnmtext/config_pnmtext.cxx b/panda/src/pnmtext/config_pnmtext.cxx index 0f5cd52b71..418fc1113a 100644 --- a/panda/src/pnmtext/config_pnmtext.cxx +++ b/panda/src/pnmtext/config_pnmtext.cxx @@ -27,7 +27,7 @@ ConfigureFn(config_pnmtext) { ConfigVariableDouble text_point_size ("text-point-size", 10.0f); ConfigVariableDouble text_pixels_per_unit -("text-pixels-per-unit", 30.0f); +("text-pixels-per-unit", 40.0f); ConfigVariableDouble text_scale_factor ("text-scale-factor", 2.0f); ConfigVariableBool text_native_antialias diff --git a/panda/src/putil/Sources.pp b/panda/src/putil/Sources.pp index f20e4ea9e8..6134d73f7c 100644 --- a/panda/src/putil/Sources.pp +++ b/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 \ diff --git a/panda/src/putil/keyboardButton.cxx b/panda/src/putil/keyboardButton.cxx index 6f4971c1fb..6b728096da 100644 --- a/panda/src/putil/keyboardButton.cxx +++ b/panda/src/putil/keyboardButton.cxx @@ -49,7 +49,6 @@ ascii_key(const string &ascii_equivalent) { #define DEFINE_KEYBD_BUTTON_HANDLE(KeyName) \ static ButtonHandle _##KeyName; \ ButtonHandle KeyboardButton::KeyName() { return _##KeyName; } - DEFINE_KEYBD_BUTTON_HANDLE(space) DEFINE_KEYBD_BUTTON_HANDLE(backspace) @@ -90,6 +89,7 @@ DEFINE_KEYBD_BUTTON_HANDLE(scroll_lock) DEFINE_KEYBD_BUTTON_HANDLE(num_lock) DEFINE_KEYBD_BUTTON_HANDLE(print_screen) DEFINE_KEYBD_BUTTON_HANDLE(pause) +DEFINE_KEYBD_BUTTON_HANDLE(menu) DEFINE_KEYBD_BUTTON_HANDLE(shift) DEFINE_KEYBD_BUTTON_HANDLE(control) DEFINE_KEYBD_BUTTON_HANDLE(alt) @@ -99,6 +99,8 @@ DEFINE_KEYBD_BUTTON_HANDLE(lcontrol) DEFINE_KEYBD_BUTTON_HANDLE(rcontrol) DEFINE_KEYBD_BUTTON_HANDLE(lalt) DEFINE_KEYBD_BUTTON_HANDLE(ralt) +DEFINE_KEYBD_BUTTON_HANDLE(lmeta) +DEFINE_KEYBD_BUTTON_HANDLE(rmeta) //////////////////////////////////////////////////////////////////// @@ -143,7 +145,7 @@ init_keyboard_buttons() { ButtonRegistry::ptr()->register_button(_left, "arrow_left"); ButtonRegistry::ptr()->register_button(_right, "arrow_right"); ButtonRegistry::ptr()->register_button(_up, "arrow_up"); // cannot name this 'up' since it conflicts with key-release name 'up' - ButtonRegistry::ptr()->register_button(_down, "arrow_down"); + ButtonRegistry::ptr()->register_button(_down, "arrow_down"); ButtonRegistry::ptr()->register_button(_page_up, "page_up"); ButtonRegistry::ptr()->register_button(_page_down, "page_down"); ButtonRegistry::ptr()->register_button(_home, "home"); @@ -161,6 +163,7 @@ init_keyboard_buttons() { ButtonRegistry::ptr()->register_button(_scroll_lock, "scroll_lock"); ButtonRegistry::ptr()->register_button(_print_screen, "print_screen"); ButtonRegistry::ptr()->register_button(_pause, "pause"); + ButtonRegistry::ptr()->register_button(_menu, "menu"); ButtonRegistry::ptr()->register_button(_lshift, "lshift", _shift); ButtonRegistry::ptr()->register_button(_rshift, "rshift", _shift); @@ -168,12 +171,14 @@ init_keyboard_buttons() { ButtonRegistry::ptr()->register_button(_rcontrol, "rcontrol", _control); ButtonRegistry::ptr()->register_button(_lalt, "lalt", _alt); ButtonRegistry::ptr()->register_button(_ralt, "ralt", _alt); + ButtonRegistry::ptr()->register_button(_lmeta, "lmeta", _meta); + ButtonRegistry::ptr()->register_button(_rmeta, "rmeta", _meta); // Also register all of the visible ASCII characters. for (int i = 32; i < 127; i++) { if (isgraph(i)) { ButtonHandle key; - ButtonRegistry::ptr()->register_button(key, string(1, (char)i), + ButtonRegistry::ptr()->register_button(key, string(1, (char)i), ButtonHandle::none(), i); } } diff --git a/panda/src/putil/keyboardButton.h b/panda/src/putil/keyboardButton.h index 94be8d3eed..cd74d7d023 100644 --- a/panda/src/putil/keyboardButton.h +++ b/panda/src/putil/keyboardButton.h @@ -66,6 +66,7 @@ PUBLISHED: static ButtonHandle insert(); static ButtonHandle del(); // delete is a C++ keyword. static ButtonHandle help(); + static ButtonHandle menu(); static ButtonHandle shift(); static ButtonHandle control(); @@ -84,6 +85,8 @@ PUBLISHED: static ButtonHandle rcontrol(); static ButtonHandle lalt(); static ButtonHandle ralt(); + static ButtonHandle lmeta(); + static ButtonHandle rmeta(); public: static void init_keyboard_buttons(); diff --git a/panda/src/putil/typedWritable.cxx b/panda/src/putil/typedWritable.cxx index 44c3ffa67b..b829b27126 100644 --- a/panda/src/putil/typedWritable.cxx +++ b/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 - diff --git a/panda/src/putil/typedWritable.h b/panda/src/putil/typedWritable.h index df1a4a339f..e8a0dd65d4 100644 --- a/panda/src/putil/typedWritable.h +++ b/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 - - diff --git a/panda/src/putil/typedWritable_ext.cxx b/panda/src/putil/typedWritable_ext.cxx new file mode 100644 index 0000000000..ebe5f966d5 --- /dev/null +++ b/panda/src/putil/typedWritable_ext.cxx @@ -0,0 +1,256 @@ +// Filename: typedWritable_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 "typedWritable_ext.h" + +#ifdef HAVE_PYTHON + +#ifndef CPPPARSER +extern EXPCL_PANDA_PUTIL Dtool_PyTypedObject Dtool_BamWriter; +#endif // CPPPARSER + +//////////////////////////////////////////////////////////////////// +// 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 *Extension:: +__reduce__(PyObject *self) const { + return __reduce_persist__(self, NULL); +} + +//////////////////////////////////////////////////////////////////// +// 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 *Extension:: +__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 " << _this->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 (!_this->encode_to_bam_stream(bam_stream, writer)) { + ostringstream stream; + stream << "Could not bamify object of type " << _this->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; +} + +//////////////////////////////////////////////////////////////////// +// 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 *Extension:: +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; +} + +//////////////////////////////////////////////////////////////////// +// 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); +} + +//////////////////////////////////////////////////////////////////// +// 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 diff --git a/panda/src/putil/typedWritable_ext.h b/panda/src/putil/typedWritable_ext.h new file mode 100644 index 0000000000..b42092ab33 --- /dev/null +++ b/panda/src/putil/typedWritable_ext.h @@ -0,0 +1,49 @@ +// Filename: typedWritable_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 TYPEDWRITABLE_EXT_H +#define TYPEDWRITABLE_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "extension.h" +#include "typedWritable.h" +#include "py_panda.h" + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// StreamReader, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + PyObject *__reduce__(PyObject *self) const; + PyObject *__reduce_persist__(PyObject *self, PyObject *pickler) const; + + static PyObject *find_global_decode(PyObject *this_class, const char *func_name); + +}; + +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 // HAVE_PYTHON + +#endif // TYPEDWRITABLE_EXT_H diff --git a/panda/src/tform/buttonThrower.I b/panda/src/tform/buttonThrower.I index 96e7e8434e..b5aa817858 100644 --- a/panda/src/tform/buttonThrower.I +++ b/panda/src/tform/buttonThrower.I @@ -200,6 +200,53 @@ get_move_event() const { return _move_event; } +//////////////////////////////////////////////////////////////////// +// Function: ButtonThrower::set_raw_button_down_event +// Access: Published +// Description: Like set_button_down_event, but uses the raw, +// untransformed scan key from the operating system. +// This uses buttons that are independent of the +// user's selected keyboard layout. +//////////////////////////////////////////////////////////////////// +INLINE void ButtonThrower:: +set_raw_button_down_event(const string &raw_button_down_event) { + _raw_button_down_event = raw_button_down_event; +} + +//////////////////////////////////////////////////////////////////// +// Function: ButtonThrower::get_raw_button_down_event +// Access: Published +// Description: Returns the raw_button_down_event that has been set on +// this ButtonThrower. See set_raw_button_down_event(). +//////////////////////////////////////////////////////////////////// +INLINE const string &ButtonThrower:: +get_raw_button_down_event() const { + return _raw_button_down_event; +} + +//////////////////////////////////////////////////////////////////// +// Function: ButtonThrower::set_raw_button_up_event +// Access: Published +// Description: Specifies the generic event that is generated (if +// any) each time a key or button is released. See +// set_raw_button_down_event(). +//////////////////////////////////////////////////////////////////// +INLINE void ButtonThrower:: +set_raw_button_up_event(const string &raw_button_up_event) { + _raw_button_up_event = raw_button_up_event; +} + +//////////////////////////////////////////////////////////////////// +// Function: ButtonThrower::get_raw_button_up_event +// Access: Published +// Description: Returns the raw_button_up_event that has been set on +// this ButtonThrower. See set_raw_button_up_event(). +//////////////////////////////////////////////////////////////////// +INLINE const string &ButtonThrower:: +get_raw_button_up_event() const { + return _raw_button_up_event; +} + //////////////////////////////////////////////////////////////////// // Function: ButtonThrower::set_prefix // Access: Published diff --git a/panda/src/tform/buttonThrower.cxx b/panda/src/tform/buttonThrower.cxx index b0e1d1452f..4d52caebcd 100644 --- a/panda/src/tform/buttonThrower.cxx +++ b/panda/src/tform/buttonThrower.cxx @@ -268,16 +268,16 @@ void ButtonThrower:: do_specific_event(const string &event_name, double time) { if (_specific_flag) { PT(Event) event = new Event(_prefix + event_name); - + if (_time_flag) { event->add_parameter(time); } - + ParameterList::const_iterator pi; for (pi = _parameters.begin(); pi != _parameters.end(); ++pi) { event->add_parameter(*pi); } - + throw_event(event); } } @@ -318,6 +318,14 @@ do_general_event(const ButtonEvent &button_event, const string &button_name) { case ButtonEvent::T_move: event_name = _move_event; break; + + case ButtonEvent::T_raw_down: + event_name = _raw_button_down_event; + break; + + case ButtonEvent::T_raw_up: + event_name = _raw_button_up_event; + break; } if (event_name.empty()) { // This general event is not configured. @@ -336,6 +344,8 @@ do_general_event(const ButtonEvent &button_event, const string &button_name) { case ButtonEvent::T_resume_down: case ButtonEvent::T_up: case ButtonEvent::T_repeat: + case ButtonEvent::T_raw_down: + case ButtonEvent::T_raw_up: event->add_parameter(button_name); break; @@ -405,7 +415,7 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input, do_specific_event(event_name, be._time); } do_general_event(be, event_name); - + } else { // Don't process this button; instead, pass it down to future // generations. @@ -418,7 +428,7 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input, // throw an event now (since we already missed it), but do // make sure our modifiers are up-to-date. _mods.button_down(be._button); - + } else if (be._type == ButtonEvent::T_up) { // Button up. _mods.button_up(be._button); @@ -438,6 +448,34 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input, _button_events->add_event(be); } + } else if (be._type == ButtonEvent::T_raw_down) { + // Raw button down. + if (!_throw_buttons_active || has_throw_button(be._button)) { + // Process this button. + do_specific_event("raw-" + event_name, be._time); + do_general_event(be, event_name); + + } else { + // Don't process this button; instead, pass it down to future + // generations. + _button_events->add_event(be); + } + + } else if (be._type == ButtonEvent::T_raw_up) { + // Raw button up. + if (!_throw_buttons_active || has_throw_button(be._button)) { + // Process this button. + do_specific_event("raw-" + event_name + "-up", be._time); + do_general_event(be, event_name); + } + if (_throw_buttons_active) { + // Now pass the event on to future generations. We always + // pass "up" events, even if we are intercepting this + // particular button; unless we're processing all buttons in + // which case it doesn't matter. + _button_events->add_event(be); + } + } else { // Some other kind of button event (e.g. keypress). Don't // throw an event for this, but do pass it down. diff --git a/panda/src/tform/buttonThrower.h b/panda/src/tform/buttonThrower.h index 59b19b7bbf..b779406b05 100644 --- a/panda/src/tform/buttonThrower.h +++ b/panda/src/tform/buttonThrower.h @@ -53,6 +53,10 @@ PUBLISHED: INLINE const string &get_candidate_event() const; INLINE void set_move_event(const string &move_event); INLINE const string &get_move_event() const; + INLINE void set_raw_button_down_event(const string &raw_button_down_event); + INLINE const string &get_raw_button_down_event() const; + INLINE void set_raw_button_up_event(const string &raw_button_up_event); + INLINE const string &get_raw_button_up_event() const; INLINE void set_prefix(const string &prefix); INLINE const string &get_prefix() const; @@ -61,7 +65,6 @@ PUBLISHED: INLINE void set_time_flag(bool time_flag); INLINE bool get_time_flag() const; - void add_parameter(const EventParameter &obj); int get_num_parameters() const; @@ -85,7 +88,7 @@ public: private: void do_specific_event(const string &event_name, double time); - void do_general_event(const ButtonEvent &button_event, + void do_general_event(const ButtonEvent &button_event, const string &event_name); private: @@ -95,6 +98,8 @@ private: string _keystroke_event; string _candidate_event; string _move_event; + string _raw_button_up_event; + string _raw_button_down_event; bool _specific_flag; string _prefix; bool _time_flag; diff --git a/panda/src/tform/mouseWatcher.cxx b/panda/src/tform/mouseWatcher.cxx index 58de969a8e..f0b5f9d34e 100644 --- a/panda/src/tform/mouseWatcher.cxx +++ b/panda/src/tform/mouseWatcher.cxx @@ -1539,6 +1539,12 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input, case ButtonEvent::T_move: // This is handled below. break; + + case ButtonEvent::T_raw_down: + case ButtonEvent::T_raw_up: + // These are passed through. + new_button_events.add_event(be); + break; } } } diff --git a/panda/src/tinydisplay/zline.h b/panda/src/tinydisplay/zline.h index 20914a67f9..8e162d54a4 100644 --- a/panda/src/tinydisplay/zline.h +++ b/panda/src/tinydisplay/zline.h @@ -35,6 +35,7 @@ b = p2->b << 8; #endif +#undef RGB /* from wingdi.h */ #ifdef INTERP_RGB #define RGB(x) x #define RGBPIXEL *pp = RGB_TO_PIXEL(r >> 8,g >> 8,b >> 8) @@ -105,4 +106,4 @@ #undef PUTPIXEL #undef ZZ #undef RGB -#undef RGBPIXEL +#undef RGBPIXEL diff --git a/panda/src/tinydisplay/zmath.cxx b/panda/src/tinydisplay/zmath.cxx index fba1751c3b..e71666084c 100644 --- a/panda/src/tinydisplay/zmath.cxx +++ b/panda/src/tinydisplay/zmath.cxx @@ -140,7 +140,7 @@ int Matrix_Inv(PN_stdfloat *r,PN_stdfloat *m,int n) int i,j,k,l; PN_stdfloat max,tmp,t; - /* identitée dans r */ + /* identite dans r */ for(i=0;i> 16; + + if (lparam & 0x1000000) { + // Extended keys + switch (vsc) { + case 29: return KeyboardButton::rcontrol(); + case 56: return KeyboardButton::ralt(); + case 69: return KeyboardButton::num_lock(); + case 71: return KeyboardButton::home(); + case 72: return KeyboardButton::up(); + case 73: return KeyboardButton::page_up(); + case 75: return KeyboardButton::left(); + case 77: return KeyboardButton::right(); + case 79: return KeyboardButton::end(); + case 80: return KeyboardButton::down(); + case 81: return KeyboardButton::page_down(); + case 82: return KeyboardButton::insert(); + case 83: return KeyboardButton::del(); + } + } + + if (vsc <= 83) { + static ButtonHandle raw_map[] = { + ButtonHandle::none(), + KeyboardButton::escape(), + KeyboardButton::ascii_key('1'), + KeyboardButton::ascii_key('2'), + KeyboardButton::ascii_key('3'), + KeyboardButton::ascii_key('4'), + KeyboardButton::ascii_key('5'), + KeyboardButton::ascii_key('6'), + KeyboardButton::ascii_key('7'), + KeyboardButton::ascii_key('8'), + KeyboardButton::ascii_key('9'), + KeyboardButton::ascii_key('0'), + KeyboardButton::ascii_key('-'), + KeyboardButton::ascii_key('='), + KeyboardButton::backspace(), + KeyboardButton::tab(), + KeyboardButton::ascii_key('q'), + KeyboardButton::ascii_key('w'), + KeyboardButton::ascii_key('e'), + KeyboardButton::ascii_key('r'), + KeyboardButton::ascii_key('t'), + KeyboardButton::ascii_key('y'), + KeyboardButton::ascii_key('u'), + KeyboardButton::ascii_key('i'), + KeyboardButton::ascii_key('o'), + KeyboardButton::ascii_key('p'), + KeyboardButton::ascii_key('['), + KeyboardButton::ascii_key(']'), + KeyboardButton::enter(), + KeyboardButton::lcontrol(), + KeyboardButton::ascii_key('a'), + KeyboardButton::ascii_key('s'), + KeyboardButton::ascii_key('d'), + KeyboardButton::ascii_key('f'), + KeyboardButton::ascii_key('g'), + KeyboardButton::ascii_key('h'), + KeyboardButton::ascii_key('j'), + KeyboardButton::ascii_key('k'), + KeyboardButton::ascii_key('l'), + KeyboardButton::ascii_key(';'), + KeyboardButton::ascii_key('\''), + KeyboardButton::ascii_key('`'), + KeyboardButton::lshift(), + KeyboardButton::ascii_key('\\'), + KeyboardButton::ascii_key('z'), + KeyboardButton::ascii_key('x'), + KeyboardButton::ascii_key('c'), + KeyboardButton::ascii_key('v'), + KeyboardButton::ascii_key('b'), + KeyboardButton::ascii_key('n'), + KeyboardButton::ascii_key('m'), + KeyboardButton::ascii_key(','), + KeyboardButton::ascii_key('.'), + KeyboardButton::ascii_key('/'), + KeyboardButton::rshift(), + KeyboardButton::ascii_key('*'), + KeyboardButton::lalt(), + KeyboardButton::space(), + KeyboardButton::caps_lock(), + KeyboardButton::f1(), + KeyboardButton::f2(), + KeyboardButton::f3(), + KeyboardButton::f4(), + KeyboardButton::f5(), + KeyboardButton::f6(), + KeyboardButton::f7(), + KeyboardButton::f8(), + KeyboardButton::f9(), + KeyboardButton::f10(), + KeyboardButton::pause(), + KeyboardButton::scroll_lock(), + KeyboardButton::ascii_key('7'), + KeyboardButton::ascii_key('8'), + KeyboardButton::ascii_key('9'), + KeyboardButton::ascii_key('-'), + KeyboardButton::ascii_key('4'), + KeyboardButton::ascii_key('5'), + KeyboardButton::ascii_key('6'), + KeyboardButton::ascii_key('+'), + KeyboardButton::ascii_key('1'), + KeyboardButton::ascii_key('2'), + KeyboardButton::ascii_key('3'), + KeyboardButton::ascii_key('0'), + KeyboardButton::ascii_key('.') + }; + return raw_map[vsc]; + } + + // A few additional keys don't fit well in the above table. + switch (vsc) { + case 87: return KeyboardButton::f11(); + case 88: return KeyboardButton::f12(); + case 91: return KeyboardButton::lmeta(); + case 92: return KeyboardButton::rmeta(); + case 93: return KeyboardButton::menu(); + default: return ButtonHandle::none(); + } +} + //////////////////////////////////////////////////////////////////// // Function: WinGraphicsWindow::handle_raw_input // Access: Private diff --git a/panda/src/windisplay/winGraphicsWindow.h b/panda/src/windisplay/winGraphicsWindow.h index f3d0155c1c..8519a3034c 100644 --- a/panda/src/windisplay/winGraphicsWindow.h +++ b/panda/src/windisplay/winGraphicsWindow.h @@ -131,7 +131,10 @@ private: void handle_keypress(ButtonHandle key, int x, int y, double time); void handle_keyresume(ButtonHandle key, double time); void handle_keyrelease(ButtonHandle key, double time); + void handle_raw_keypress(ButtonHandle key, double time); + void handle_raw_keyrelease(ButtonHandle key, double time); ButtonHandle lookup_key(WPARAM wparam) const; + ButtonHandle lookup_raw_key(LPARAM lparam) const; INLINE int translate_mouse(int pos) const; INLINE void set_cursor_in_window(); INLINE void set_cursor_out_of_window(); diff --git a/panda/src/x11display/x11GraphicsWindow.cxx b/panda/src/x11display/x11GraphicsWindow.cxx index 27819dbf84..ec7c79a48b 100644 --- a/panda/src/x11display/x11GraphicsWindow.cxx +++ b/panda/src/x11display/x11GraphicsWindow.cxx @@ -1392,18 +1392,26 @@ handle_keypress(XKeyEvent &event) { // Now get the raw unshifted button. ButtonHandle button = get_button(event, false); - if (button == KeyboardButton::lcontrol() || button == KeyboardButton::rcontrol()) { - _input_devices[0].button_down(KeyboardButton::control()); - } - if (button == KeyboardButton::lshift() || button == KeyboardButton::rshift()) { - _input_devices[0].button_down(KeyboardButton::shift()); - } - if (button == KeyboardButton::lalt() || button == KeyboardButton::ralt()) { - _input_devices[0].button_down(KeyboardButton::alt()); - } if (button != ButtonHandle::none()) { + if (button == KeyboardButton::lcontrol() || button == KeyboardButton::rcontrol()) { + _input_devices[0].button_down(KeyboardButton::control()); + } + if (button == KeyboardButton::lshift() || button == KeyboardButton::rshift()) { + _input_devices[0].button_down(KeyboardButton::shift()); + } + if (button == KeyboardButton::lalt() || button == KeyboardButton::ralt()) { + _input_devices[0].button_down(KeyboardButton::alt()); + } + if (button == KeyboardButton::lmeta() || button == KeyboardButton::rmeta()) { + _input_devices[0].button_down(KeyboardButton::meta()); + } _input_devices[0].button_down(button); } + + ButtonHandle raw_button = map_raw_button(event.keycode); + if (raw_button != ButtonHandle::none()) { + _input_devices[0].raw_button_down(raw_button); + } } //////////////////////////////////////////////////////////////////// @@ -1420,18 +1428,26 @@ handle_keyrelease(XKeyEvent &event) { // Now get the raw unshifted button. ButtonHandle button = get_button(event, false); - if (button == KeyboardButton::lcontrol() || button == KeyboardButton::rcontrol()) { - _input_devices[0].button_up(KeyboardButton::control()); - } - if (button == KeyboardButton::lshift() || button == KeyboardButton::rshift()) { - _input_devices[0].button_up(KeyboardButton::shift()); - } - if (button == KeyboardButton::lalt() || button == KeyboardButton::ralt()) { - _input_devices[0].button_up(KeyboardButton::alt()); - } if (button != ButtonHandle::none()) { + if (button == KeyboardButton::lcontrol() || button == KeyboardButton::rcontrol()) { + _input_devices[0].button_up(KeyboardButton::control()); + } + if (button == KeyboardButton::lshift() || button == KeyboardButton::rshift()) { + _input_devices[0].button_up(KeyboardButton::shift()); + } + if (button == KeyboardButton::lalt() || button == KeyboardButton::ralt()) { + _input_devices[0].button_up(KeyboardButton::alt()); + } + if (button == KeyboardButton::lmeta() || button == KeyboardButton::rmeta()) { + _input_devices[0].button_up(KeyboardButton::meta()); + } _input_devices[0].button_up(button); } + + ButtonHandle raw_button = map_raw_button(event.keycode); + if (raw_button != ButtonHandle::none()) { + _input_devices[0].raw_button_up(raw_button); + } } //////////////////////////////////////////////////////////////////// @@ -1815,6 +1831,8 @@ map_button(KeySym key) { return KeyboardButton::print_screen(); case XK_Pause: return KeyboardButton::pause(); + case XK_Menu: + return KeyboardButton::menu(); case XK_Shift_L: return KeyboardButton::lshift(); case XK_Shift_R: @@ -1828,8 +1846,9 @@ map_button(KeySym key) { case XK_Alt_R: return KeyboardButton::ralt(); case XK_Meta_L: + return KeyboardButton::lmeta(); case XK_Meta_R: - return KeyboardButton::meta(); + return KeyboardButton::rmeta(); case XK_Caps_Lock: return KeyboardButton::caps_lock(); case XK_Shift_Lock: @@ -1839,6 +1858,127 @@ map_button(KeySym key) { return ButtonHandle::none(); } +//////////////////////////////////////////////////////////////////// +// Function: x11GraphicsWindow::map_raw_button +// Access: Private +// Description: Maps from a single X keycode to Panda's ButtonHandle. +//////////////////////////////////////////////////////////////////// +ButtonHandle x11GraphicsWindow:: +map_raw_button(KeyCode key) { + switch (key) { + case 9: return KeyboardButton::escape(); + case 10: return KeyboardButton::ascii_key('1'); + case 11: return KeyboardButton::ascii_key('2'); + case 12: return KeyboardButton::ascii_key('3'); + case 13: return KeyboardButton::ascii_key('4'); + case 14: return KeyboardButton::ascii_key('5'); + case 15: return KeyboardButton::ascii_key('6'); + case 16: return KeyboardButton::ascii_key('7'); + case 17: return KeyboardButton::ascii_key('8'); + case 18: return KeyboardButton::ascii_key('9'); + case 19: return KeyboardButton::ascii_key('0'); + case 20: return KeyboardButton::ascii_key('-'); + case 21: return KeyboardButton::ascii_key('='); + case 22: return KeyboardButton::backspace(); + case 23: return KeyboardButton::tab(); + case 24: return KeyboardButton::ascii_key('q'); + case 25: return KeyboardButton::ascii_key('w'); + case 26: return KeyboardButton::ascii_key('e'); + case 27: return KeyboardButton::ascii_key('r'); + case 28: return KeyboardButton::ascii_key('t'); + case 29: return KeyboardButton::ascii_key('y'); + case 30: return KeyboardButton::ascii_key('u'); + case 31: return KeyboardButton::ascii_key('i'); + case 32: return KeyboardButton::ascii_key('o'); + case 33: return KeyboardButton::ascii_key('p'); + case 34: return KeyboardButton::ascii_key('['); + case 35: return KeyboardButton::ascii_key(']'); + case 36: return KeyboardButton::enter(); + case 37: return KeyboardButton::lcontrol(); + case 38: return KeyboardButton::ascii_key('a'); + case 39: return KeyboardButton::ascii_key('s'); + case 40: return KeyboardButton::ascii_key('d'); + case 41: return KeyboardButton::ascii_key('f'); + case 42: return KeyboardButton::ascii_key('g'); + case 43: return KeyboardButton::ascii_key('h'); + case 44: return KeyboardButton::ascii_key('j'); + case 45: return KeyboardButton::ascii_key('k'); + case 46: return KeyboardButton::ascii_key('l'); + case 47: return KeyboardButton::ascii_key(';'); + case 48: return KeyboardButton::ascii_key('\''); + case 49: return KeyboardButton::ascii_key('`'); + case 50: return KeyboardButton::lshift(); + case 51: return KeyboardButton::ascii_key('\\'); + case 52: return KeyboardButton::ascii_key('z'); + case 53: return KeyboardButton::ascii_key('x'); + case 54: return KeyboardButton::ascii_key('c'); + case 55: return KeyboardButton::ascii_key('v'); + case 56: return KeyboardButton::ascii_key('b'); + case 57: return KeyboardButton::ascii_key('n'); + case 58: return KeyboardButton::ascii_key('m'); + case 59: return KeyboardButton::ascii_key(','); + case 60: return KeyboardButton::ascii_key('.'); + case 61: return KeyboardButton::ascii_key('/'); + case 62: return KeyboardButton::rshift(); + case 63: return KeyboardButton::ascii_key('*'); + case 64: return KeyboardButton::lalt(); + case 65: return KeyboardButton::space(); + case 66: return KeyboardButton::caps_lock(); + case 67: return KeyboardButton::f1(); + case 68: return KeyboardButton::f2(); + case 69: return KeyboardButton::f3(); + case 70: return KeyboardButton::f4(); + case 71: return KeyboardButton::f5(); + case 72: return KeyboardButton::f6(); + case 73: return KeyboardButton::f7(); + case 74: return KeyboardButton::f8(); + case 75: return KeyboardButton::f9(); + case 76: return KeyboardButton::f10(); + case 77: return KeyboardButton::num_lock(); + case 78: return KeyboardButton::scroll_lock(); + case 79: return KeyboardButton::ascii_key('7'); + case 80: return KeyboardButton::ascii_key('8'); + case 81: return KeyboardButton::ascii_key('9'); + case 82: return KeyboardButton::ascii_key('-'); + case 83: return KeyboardButton::ascii_key('4'); + case 84: return KeyboardButton::ascii_key('5'); + case 85: return KeyboardButton::ascii_key('6'); + case 86: return KeyboardButton::ascii_key('+'); + case 87: return KeyboardButton::ascii_key('1'); + case 88: return KeyboardButton::ascii_key('2'); + case 89: return KeyboardButton::ascii_key('3'); + case 90: return KeyboardButton::ascii_key('0'); + case 91: return KeyboardButton::ascii_key('.'); + + case 95: return KeyboardButton::f11(); + case 96: return KeyboardButton::f12(); + + case 104: return KeyboardButton::enter(); + case 105: return KeyboardButton::rcontrol(); + case 106: return KeyboardButton::ascii_key('/'); + case 107: return KeyboardButton::print_screen(); + case 108: return KeyboardButton::ralt(); + + case 110: return KeyboardButton::home(); + case 111: return KeyboardButton::up(); + case 112: return KeyboardButton::page_up(); + case 113: return KeyboardButton::left(); + case 114: return KeyboardButton::right(); + case 115: return KeyboardButton::end(); + case 116: return KeyboardButton::down(); + case 117: return KeyboardButton::page_down(); + case 118: return KeyboardButton::insert(); + case 119: return KeyboardButton::del(); + + case 127: return KeyboardButton::pause(); + + case 133: return KeyboardButton::lmeta(); + case 134: return KeyboardButton::rmeta(); + case 135: return KeyboardButton::menu(); + } + return ButtonHandle::none(); +} + //////////////////////////////////////////////////////////////////// // Function: x11GraphicsWindow::get_mouse_button // Access: Private diff --git a/panda/src/x11display/x11GraphicsWindow.h b/panda/src/x11display/x11GraphicsWindow.h index d99d6fe2b1..e5f51d9cf3 100644 --- a/panda/src/x11display/x11GraphicsWindow.h +++ b/panda/src/x11display/x11GraphicsWindow.h @@ -67,6 +67,7 @@ protected: ButtonHandle get_button(XKeyEvent &key_event, bool allow_shift); ButtonHandle map_button(KeySym key); + ButtonHandle map_raw_button(KeyCode key); ButtonHandle get_mouse_button(XButtonEvent &button_event); static Bool check_event(X11_Display *display, XEvent *event, char *arg); diff --git a/pandatool/src/mayaegg/mayaToEggConverter.cxx b/pandatool/src/mayaegg/mayaToEggConverter.cxx index 64f09cdcfc..b9b979d66c 100644 --- a/pandatool/src/mayaegg/mayaToEggConverter.cxx +++ b/pandatool/src/mayaegg/mayaToEggConverter.cxx @@ -969,7 +969,6 @@ process_model_node(MayaNodeDesc *node_desc) { << "Ignoring light node " << path << "\n"; } - /* MFnLight light (dag_path, &status); if ( !status ) { @@ -977,26 +976,59 @@ process_model_node(MayaNodeDesc *node_desc) { mayaegg_cat.error() << "light extraction failed" << endl; return false; } + mayaegg_cat.debug() << "-- Light found -- tranlations in cm, rotations in rads\n"; + + mayaegg_cat.debug() << "\"" << dag_path.partialPathName() << "\" : \n"; // Get the translation/rotation/scale data - //printTransformData(dag_path, quiet); + MObject transformNode = dag_path.transform(&status); + // This node has no transform - i.e., it's the world node + if (!status && status.statusCode () == MStatus::kInvalidParameter) + return false; + MFnDagNode transform (transformNode, &status); + if (!status) { + status.perror("MFnDagNode constructor"); + return false; + } + MTransformationMatrix matrix (transform.transformationMatrix()); + MVector tl = matrix.getTranslation(MSpace::kWorld); + // Stop rediculously small values like -4.43287e-013 + if (tl.x < 0.0001) { + tl.x = 0; + } + if (tl.y < 0.0001) { + tl.y = 0; + } + if (tl.z < 0.0001) { + tl.z = 0; + } + // We swap Y and Z in the next few bits cuz Panda is Z-up by default and Maya is Y-up + mayaegg_cat.debug() << " \"translation\" : (" << tl.x << ", " << tl.z << ", " << tl.y << ")" + << endl; + double threeDoubles[3]; + MTransformationMatrix::RotationOrder rOrder; + + matrix.getRotation (threeDoubles, rOrder, MSpace::kWorld); + mayaegg_cat.debug() << " \"rotation\": (" + << threeDoubles[0] << ", " + << threeDoubles[2] << ", " + << threeDoubles[1] << ")\n"; + matrix.getScale (threeDoubles, MSpace::kWorld); + mayaegg_cat.debug() << " \"scale\" : (" + << threeDoubles[0] << ", " + << threeDoubles[2] << ", " + << threeDoubles[1] << ")\n"; // Extract some interesting Light data MColor color; - color = light.color(); - cout << " color: [" + mayaegg_cat.debug() << " \"color\" : (" << color.r << ", " << color.g << ", " - << color.b << "]\n"; + << color.b << ")\n"; color = light.shadowColor(); - cout << " shadowColor: [" - << color.r << ", " - << color.g << ", " - << color.b << "]\n"; - - cout << " intensity: " << light.intensity() << endl; - */ + mayaegg_cat.debug() << " \"intensity\" : " << light.intensity() << endl; + } else if (dag_path.hasFn(MFn::kNurbsSurface)) { EggGroup *egg_group = _tree.get_egg_group(node_desc); get_transform(node_desc, dag_path, egg_group);