Browse Source

*** empty log message ***

Joe Shochet 25 years ago
parent
commit
87d951c0c5

+ 79 - 47
direct/src/ffi/FFIExternalObject.py

@@ -4,9 +4,11 @@ import TypedObject
 
 
 WrapperClassMap = {}
 WrapperClassMap = {}
 
 
+DowncastMap = {}
+
 # For testing, you can turn verbose and debug on
 # For testing, you can turn verbose and debug on
-# FFIConstants.notify.setVerbose(1)
-# FFIConstants.notify.setDebug(1)
+FFIConstants.notify.setVerbose(1)
+FFIConstants.notify.setDebug(1)
 
 
 
 
 # Register a python class in the type map if it is a typed object
 # Register a python class in the type map if it is a typed object
@@ -30,39 +32,66 @@ class FFIExternalObject:
         # Base destructor in case you do not define one
         # Base destructor in case you do not define one
         pass
         pass
 
 
-    def getDowncastFunctions(self, thisClass, baseClass, chain):
-        if (thisClass == baseClass):
-            # Found it, return true
-            return 1
+    def getLineage(self, thisClass, targetBaseClass):
+        # Recursively determine the path in the heirarchy tree from thisClass
+        # to the targetBaseClass
+        return self.getLineageInternal(thisClass, targetBaseClass, [thisClass])
+
+    def getLineageInternal(self, thisClass, targetBaseClass, chain):
+        # Recursively determine the path in the heirarchy tree from thisClass
+        # to the targetBaseClass
+        FFIConstants.notify.debug('getLineageInternal: checking %s to %s'
+                                  % (thisClass.__name__, targetBaseClass.__name__))
+        if (targetBaseClass in thisClass.__bases__):
+            # Found a link
+            return chain + [targetBaseClass]
         elif (len(thisClass.__bases__) == 0):
         elif (len(thisClass.__bases__) == 0):
-            # Not here, return 0
+            # No possible links
             return 0
             return 0
         else:
         else:
-            # Look recursively in the classes thisClass inherits from
+            # recurse
             for base in thisClass.__bases__:
             for base in thisClass.__bases__:
-                # If it finds it, append the base class's downcast function
-                # to the chain if it has one
-                if self.getDowncastFunctions(base, baseClass, chain):
-                    downcastFuncName = ('downcastTo' + thisClass.__name__
-                                        + 'From' + base.__name__)
-                    # Look over this classes global modules dictionaries
-                    # for the downcast function name
-                    for globmod in self.__class__.__CModuleDowncasts__:
-                        if globmod.__dict__.has_key(downcastFuncName):
-                            func = globmod.__dict__[downcastFuncName]
-                            FFIConstants.notify.debug('Found downcast function %s in %s'
-                                                      % (downcastFuncName, globmod.__name__))
-                            chain.append(func)
-                            return chain
-                        else:
-                            FFIConstants.notify.debug('Did not find downcast function %s in %s'
-                                                      % (downcastFuncName, globmod.__name__))
-                    # In any case, return the chain
-                    return chain
-                # Probably went up the wrong tree and did not find the rootClass
-                else:
-                    return []
+                res = self.getLineageInternal(base, targetBaseClass, chain+[base])
+                if res:
+                    # Actually, we want them in the reverse order
+                    res.reverse()
+                    FFIConstants.notify.debug('getLineageInternal: found path: ' + `res`)
+                    return res
+            # Not found anywhere
+            return 0
 
 
+    def getDowncastFunctions(self, thisClass, baseClass):
+        FFIConstants.notify.debug(
+            'getDowncastFunctions: Looking for downcast function from %s to %s'
+            % (baseClass.__name__, thisClass.__name__))
+        lineage = self.getLineage(thisClass, baseClass)
+        # Start with an empty list of downcast functions
+        downcastFunctionList = []
+
+        # If it could not find the baseClass anywhere in the lineage, return empty
+        if not lineage:
+            return []
+
+        # Walk along the lineage looking for downcast functions from class to class+1
+        for i in range((len(lineage) - 1)):
+            fromClass = lineage[i]
+            toClass = lineage[i+1]
+            downcastFuncName = ('downcastTo' + toClass.__name__
+                                + 'From' + fromClass.__name__)
+            # Look over this classes global modules dictionaries
+            # for the downcast function name
+            for globmod in fromClass.__CModuleDowncasts__:
+                if globmod.__dict__.has_key(downcastFuncName):
+                    func = globmod.__dict__[downcastFuncName]
+                    FFIConstants.notify.debug(
+                        'getDowncastFunctions: Found downcast function %s in %s'
+                        % (downcastFuncName, globmod.__name__))
+                    downcastFunctionList.append(func)
+                else:
+                    FFIConstants.notify.debug(
+                        'getDowncastFunctions: Did not find downcast function %s in %s'
+                        % (downcastFuncName, globmod.__name__))
+        return downcastFunctionList
         
         
     def setPointer(self):
     def setPointer(self):
         if (self.this == 0):
         if (self.this == 0):
@@ -96,24 +125,27 @@ class FFIExternalObject:
         else:
         else:
             return None
             return None
         
         
-    def downcast(self, specificClass):
-        FFIConstants.notify.debug('downcasting from %s to %s' % \
-            (self.__class__.__name__, specificClass.__name__))
-        downcastChain = self.getDowncastFunctions(specificClass, self.__class__, [])
-        FFIConstants.notify.debug('downcast chain: ' + `downcastChain`)
-        newObject = self
-        if (downcastChain == None):
-            return newObject
-        elif (downcastChain == 1):
-            return newObject
-        elif (downcastChain == 0):
-            return newObject
+    def downcast(self, toClass):
+        fromClass = self.__class__
+        FFIConstants.notify.debug('downcast: downcasting from %s to %s' % \
+            (fromClass.__name__, toClass.__name__))
+
+        # Check the cache to see if we have looked this up before
+        if DowncastMap.has_key((fromClass, toClass)):
+            downcastChain = DowncastMap[(fromClass, toClass)]
+            FFIConstants.notify.debug('downcast: found cached downcast chain: ' + `downcastChain`)            
         else:
         else:
-            for downcastFunc in downcastChain:
-                FFIConstants.notify.debug('downcasting %s using %s' % \
-                    (newObject.__class__.__name__, downcastFunc))
-                newObject = downcastFunc(newObject)
-            return newObject
+            downcastChain = self.getDowncastFunctions(toClass, fromClass)
+            FFIConstants.notify.debug('downcast: computed downcast chain: ' + `downcastChain`)
+            # Store it for next time
+            DowncastMap[(fromClass, toClass)] = downcastChain
+            
+        newObject = self
+        for downcastFunc in downcastChain:
+            FFIConstants.notify.debug('downcast: downcasting %s using %s' % \
+                                      (newObject.__class__.__name__, downcastFunc))
+            newObject = downcastFunc(newObject)
+        return newObject
 
 
     def compareTo(self, other):
     def compareTo(self, other):
         # By default, we compare the C++ pointers
         # By default, we compare the C++ pointers

+ 1 - 1
direct/src/ffi/FFIInterrogateDatabase.py

@@ -721,7 +721,7 @@ class FFIInterrogateDatabase:
         # Output all the imports based on this list of functions
         # Output all the imports based on this list of functions
         outputGlobalFileImports(downcastFile, self.environment.downcastFunctions, CModuleName)
         outputGlobalFileImports(downcastFile, self.environment.downcastFunctions, CModuleName)
         for type in self.environment.downcastFunctions:
         for type in self.environment.downcastFunctions:
-            type.generateGlobalCode(downcastFile)
+            type.generateGlobalDowncastCode(downcastFile)
             
             
         FFIConstants.notify.info( 'Generating global value code...')
         FFIConstants.notify.info( 'Generating global value code...')
         globalFile = constructGlobalFile(codeDir, CModuleName)
         globalFile = constructGlobalFile(codeDir, CModuleName)

+ 9 - 9
direct/src/ffi/FFIRename.py

@@ -31,18 +31,18 @@ methodRenameDictionary = {
     'operator-'   : '__sub__',
     'operator-'   : '__sub__',
     'operator*'   : '__mul__',
     'operator*'   : '__mul__',
     'operator/'   : '__div__',
     'operator/'   : '__div__',
-    'operator+='  : 'addEqual',
-    'operator-='  : 'subtractEqual',
-    'operator*='  : 'multiplyEqual',
-    'operator/='  : 'divEqual',
+    'operator+='  : '__iadd__',
+    'operator-='  : '__isub__',
+    'operator*='  : '__imul__',
+    'operator/='  : '__idiv__',
     'operator,'   : 'concatenate',
     'operator,'   : 'concatenate',
-    'operator|='  : 'bitwiseOrEqual',
-    'operator&='  : 'bitwiseAndEqual',
-    'operator^='  : 'bitwiseXorEqual',
+    'operator|='  : '__ior__',
+    'operator&='  : '__iand__',
+    'operator^='  : '__ixor__',
     'operator~='  : 'bitwiseNotEqual',
     'operator~='  : 'bitwiseNotEqual',
     'operator->'  : 'dereference',
     'operator->'  : 'dereference',
-    'operator<<=' : 'leftShiftEqual',
-    'operator>>=' : 'rightShiftEqual',
+    'operator<<=' : '__ilshift__',
+    'operator>>=' : '__irshift__',
     'print'       : 'Cprint'
     'print'       : 'Cprint'
     }
     }
     
     

+ 10 - 2
direct/src/ffi/FFISpecs.py

@@ -132,6 +132,13 @@ class GlobalFunctionSpecification(FunctionSpecification):
         self.outputHeader(file)
         self.outputHeader(file)
         self.outputBody(file)
         self.outputBody(file)
         self.outputFooter(file)
         self.outputFooter(file)
+
+    # Use generateCode when creating a global (non-class) function
+    def generateGlobalDowncastCode(self, file):
+        self.outputHeader(file)
+        self.outputBody(file, 0) # no downcast
+        self.outputFooter(file)
+
     # Use generateMethodCode when creating a global->class function
     # Use generateMethodCode when creating a global->class function
     def generateMethodCode(self, methodClass, file, nesting):
     def generateMethodCode(self, methodClass, file, nesting):
         self.outputMethodHeader(methodClass, file, nesting)
         self.outputMethodHeader(methodClass, file, nesting)
@@ -149,7 +156,8 @@ class GlobalFunctionSpecification(FunctionSpecification):
             if (i < (len(argTypes)-1)):
             if (i < (len(argTypes)-1)):
                 file.write(', ')
                 file.write(', ')
         file.write('):\n')
         file.write('):\n')
-    def outputBody(self, file):
+        
+    def outputBody(self, file, needsDowncast=1):
         # The method body will look something like
         # The method body will look something like
         #     returnValue = PandaGlobal.method(arg)
         #     returnValue = PandaGlobal.method(arg)
         #     returnObject = NodePath()
         #     returnObject = NodePath()
@@ -167,7 +175,7 @@ class GlobalFunctionSpecification(FunctionSpecification):
                 file.write(', ')
                 file.write(', ')
         file.write(')\n')
         file.write(')\n')
         returnType = self.typeDescriptor.returnType.recursiveTypeDescriptor()
         returnType = self.typeDescriptor.returnType.recursiveTypeDescriptor()
-        returnType.generateReturnValueWrapper(file, self.typeDescriptor.userManagesMemory, 1, 1)
+        returnType.generateReturnValueWrapper(file, self.typeDescriptor.userManagesMemory, needsDowncast, 1)
         
         
     def outputFooter(self, file):
     def outputFooter(self, file):
         indent(file, 0, '\n')
         indent(file, 0, '\n')

+ 3 - 0
direct/src/showbase/ShowBase.py

@@ -158,6 +158,7 @@ class ShowBase:
         self.trackball.reparentTo(self.dataUnused)
         self.trackball.reparentTo(self.dataUnused)
         self.mouse2cam.reparentTo(self.dataUnused)
         self.mouse2cam.reparentTo(self.dataUnused)
         self.mouseInterface = None
         self.mouseInterface = None
+        self.mouseInterfaceNode = None
 
 
     def setMouseOnArc(self, newArc):
     def setMouseOnArc(self, newArc):
         self.mouse2cam.node().setArc(newArc)
         self.mouse2cam.node().setArc(newArc)
@@ -170,6 +171,7 @@ class ShowBase:
         self.trackball.reparentTo(self.dataUnused)
         self.trackball.reparentTo(self.dataUnused)
         # Update the mouseInterface to point to the drive
         # Update the mouseInterface to point to the drive
         self.mouseInterface = self.drive
         self.mouseInterface = self.drive
+        self.mouseInterfaceNode = self.mouseInterface.getBottomNode()
         self.drive.node().reset()
         self.drive.node().reset()
         self.drive.reparentTo(self.mouseWatcher)
         self.drive.reparentTo(self.mouseWatcher)
         # Hookup the drive to the camera
         # Hookup the drive to the camera
@@ -185,6 +187,7 @@ class ShowBase:
         self.drive.reparentTo(self.dataUnused)
         self.drive.reparentTo(self.dataUnused)
         # Update the mouseInterface to point to the trackball
         # Update the mouseInterface to point to the trackball
         self.mouseInterface = self.trackball
         self.mouseInterface = self.trackball
+        self.mouseInterfaceNode = self.mouseInterface.getBottomNode()
         # Hookup the trackball to the camera
         # Hookup the trackball to the camera
         self.trackball.reparentTo(self.mouseWatcher)
         self.trackball.reparentTo(self.mouseWatcher)
         self.mouse2cam.reparentTo(self.trackball)
         self.mouse2cam.reparentTo(self.trackball)