mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-29 08:15:18 -04:00
*** empty log message ***
This commit is contained in:
parent
1f4c504b42
commit
0901fd9c20
@ -3,10 +3,6 @@
|
||||
from DirectNotifyGlobal import *
|
||||
notify = directNotify.newCategory("FFI")
|
||||
|
||||
# This is the name of the file that the global functions and values
|
||||
# will be stored
|
||||
globalModuleName = 'PandaGlobals'
|
||||
|
||||
# This is the name of the file that the importing code will be stored
|
||||
importModuleName = 'PandaModules'
|
||||
|
||||
|
@ -2,8 +2,12 @@ import FFIConstants
|
||||
|
||||
class FFIEnvironment:
|
||||
def __init__(self):
|
||||
self.reset()
|
||||
|
||||
def reset(self):
|
||||
self.types = {}
|
||||
self.globalFunctions = []
|
||||
self.downcastFunctions = []
|
||||
self.globalValues = []
|
||||
self.manifests = []
|
||||
|
||||
@ -20,6 +24,8 @@ class FFIEnvironment:
|
||||
|
||||
def addGlobalFunction(self, typeDescriptor):
|
||||
self.globalFunctions.append(typeDescriptor)
|
||||
def addDowncastFunction(self, typeDescriptor):
|
||||
self.downcastFunctions.append(typeDescriptor)
|
||||
def addGlobalValue(self, typeDescriptor):
|
||||
self.globalValues.append(typeDescriptor)
|
||||
def addManifest(self, typeDescriptor):
|
||||
|
@ -4,26 +4,19 @@ import TypedObject
|
||||
|
||||
WrapperClassMap = {}
|
||||
|
||||
# For testing, you can turn verbose and debug on
|
||||
FFIConstants.notify.setVerbose(1)
|
||||
FFIConstants.notify.setDebug(1)
|
||||
|
||||
|
||||
def getDowncastFunctions(thisClass, baseClass, chain):
|
||||
if (thisClass == baseClass):
|
||||
# Found it, return true
|
||||
return 1
|
||||
elif (len(thisClass.__bases__) == 0):
|
||||
# Not here, return 0
|
||||
return 0
|
||||
else:
|
||||
# Look recursively in the classes thisClass inherits from
|
||||
for base in thisClass.__bases__:
|
||||
# If it finds it, append the base class's downcast function
|
||||
# to the chain if it has one
|
||||
if getDowncastFunctions(base, baseClass, chain):
|
||||
downcastFuncName = 'downcastTo' + thisClass.__name__
|
||||
if base.__dict__.has_key(downcastFuncName):
|
||||
FFIConstants.notify.debug('Found downcast function %s in %s' % (downcastFuncName, base.__name__))
|
||||
chain.append(base.__dict__[downcastFuncName])
|
||||
return chain
|
||||
# Register a python class in the type map if it is a typed object
|
||||
# The type map is used for upcasting and downcasting through
|
||||
# the panda inheritance chain
|
||||
def registerInTypeMap(pythonClass):
|
||||
if issubclass(pythonClass, TypedObject.TypedObject):
|
||||
typeIndex = pythonClass.getClassType().getIndex()
|
||||
WrapperClassMap[typeIndex] = pythonClass
|
||||
|
||||
|
||||
|
||||
class FFIExternalObject:
|
||||
@ -32,23 +25,52 @@ class FFIExternalObject:
|
||||
self.userManagesMemory = 0
|
||||
# Start with a null this pointer
|
||||
self.this = 0
|
||||
|
||||
|
||||
def getDowncastFunctions(self, thisClass, baseClass, chain):
|
||||
if (thisClass == baseClass):
|
||||
# Found it, return true
|
||||
return 1
|
||||
elif (len(thisClass.__bases__) == 0):
|
||||
# Not here, return 0
|
||||
return 0
|
||||
else:
|
||||
# Look recursively in the classes thisClass inherits from
|
||||
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 []
|
||||
|
||||
|
||||
def asExactType(self):
|
||||
return self.getType()
|
||||
|
||||
def isTypedObject(self):
|
||||
return isinstance(self, TypedObject.TypedObject)
|
||||
|
||||
def setPointer(self):
|
||||
if (self.this == 0):
|
||||
# Null pointer, return None
|
||||
return None
|
||||
# If it is not a typed object, our work is done, just return the object
|
||||
if (not self.isTypedObject()):
|
||||
if (not isinstance(self, TypedObject.TypedObject)):
|
||||
return self
|
||||
# Ok, it is a typed object. See what type it really is and downcast
|
||||
# to that type (if necessary)
|
||||
exactWrapperClass = self.wrapperClassForTypeHandle(self.asExactType())
|
||||
exactWrapperClass = self.wrapperClassForTypeHandle(self.getType())
|
||||
# We do not need to downcast if we already have the same class
|
||||
if (exactWrapperClass and (exactWrapperClass != self.__class__)):
|
||||
# Create a new wrapper class instance
|
||||
@ -71,16 +93,10 @@ class FFIExternalObject:
|
||||
else:
|
||||
return None
|
||||
|
||||
def registerInTypeMap(self):
|
||||
global WrapperClassMap
|
||||
if self.isTypedObject():
|
||||
typeIndex = self.__class__.getClassType().getIndex()
|
||||
WrapperClassMap[typeIndex] = self.__class__
|
||||
|
||||
def downcast(self, specificClass):
|
||||
FFIConstants.notify.debug('downcasting from %s to %s' % \
|
||||
(self.__class__.__name__, specificClass.__name__))
|
||||
downcastChain = getDowncastFunctions(specificClass, self.__class__, [])
|
||||
downcastChain = self.getDowncastFunctions(specificClass, self.__class__, [])
|
||||
FFIConstants.notify.debug('downcast chain: ' + `downcastChain`)
|
||||
newObject = self
|
||||
if (downcastChain == None):
|
||||
@ -124,7 +140,4 @@ class FFIExternalObject:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -21,26 +21,30 @@ FFIConstants.notify.info('Importing interrogate library: ' + FFIConstants.Interr
|
||||
# to be dependent on the name of the interrogate library in this code
|
||||
exec('from ' + FFIConstants.InterrogateModuleName + ' import *')
|
||||
|
||||
# Import all the C++ modules
|
||||
for CModuleName in FFIConstants.CodeModuleNameList:
|
||||
FFIConstants.notify.info('Importing code library: ' + CModuleName)
|
||||
exec('import ' + CModuleName)
|
||||
|
||||
def constructGlobalFile(codeDir):
|
||||
def constructGlobalFile(codeDir, CModuleName):
|
||||
"""
|
||||
Open a file that will hold the global values and functions code
|
||||
"""
|
||||
file = open(os.path.join(codeDir, FFIConstants.globalModuleName + '.py'), 'w')
|
||||
file = open(os.path.join(codeDir, CModuleName + 'Globals' + '.py'), 'w')
|
||||
return file
|
||||
|
||||
def constructImportFile(codeDir):
|
||||
|
||||
def constructDowncastFile(codeDir, CModuleName):
|
||||
"""
|
||||
Open a file that will hold the global values and functions code
|
||||
"""
|
||||
file = open(os.path.join(codeDir, FFIConstants.importModuleName + '.py'), 'w')
|
||||
file = open(os.path.join(codeDir, CModuleName + 'Downcasts' + '.py'), 'w')
|
||||
return file
|
||||
|
||||
def outputGlobalFileImports(file, methodList):
|
||||
|
||||
def constructImportFile(codeDir, CModuleName):
|
||||
"""
|
||||
Open a file that will hold the global values and functions code
|
||||
"""
|
||||
file = open(os.path.join(codeDir, CModuleName + 'Modules' + '.py'), 'w')
|
||||
return file
|
||||
|
||||
def outputGlobalFileImports(file, methodList, CModuleName):
|
||||
# Print the standard header
|
||||
file.write(FFIConstants.generatedHeader)
|
||||
|
||||
@ -48,15 +52,34 @@ def outputGlobalFileImports(file, methodList):
|
||||
file.write('import types\n')
|
||||
|
||||
# Import the C modules
|
||||
for CModuleName in FFIConstants.CodeModuleNameList:
|
||||
CModuleList = []
|
||||
for method in methodList:
|
||||
if (not (method.typeDescriptor.moduleName in CModuleList)):
|
||||
CModuleList.append(method.typeDescriptor.moduleName)
|
||||
for CModuleName in CModuleList:
|
||||
file.write('import ' + CModuleName + '\n')
|
||||
|
||||
moduleList = []
|
||||
for method in methodList:
|
||||
returnType = method.typeDescriptor.returnType.recursiveTypeDescriptor()
|
||||
if (not (returnType.foreignTypeName in moduleList)):
|
||||
returnTypeName = returnType.foreignTypeName
|
||||
if (not (returnTypeName in moduleList)):
|
||||
if (returnType.__class__ == FFITypes.ClassTypeDescriptor):
|
||||
moduleList.append(returnType.foreignTypeName)
|
||||
moduleList.append(returnTypeName)
|
||||
|
||||
# Look at all the arguments
|
||||
argTypes = method.typeDescriptor.argumentTypes
|
||||
for argType in argTypes:
|
||||
# Get the real return type (not derived)
|
||||
argType = argType.typeDescriptor.recursiveTypeDescriptor()
|
||||
argTypeName = argType.foreignTypeName
|
||||
# Do not put our own module in the import list
|
||||
# Do not put modules already in the list (like a set)
|
||||
if (not (argTypeName in moduleList)):
|
||||
# If this is a class (not a primitive), put it on the list
|
||||
if (argType.__class__ == FFITypes.ClassTypeDescriptor):
|
||||
moduleList.append(argTypeName)
|
||||
|
||||
|
||||
for moduleName in moduleList:
|
||||
file.write('import ' + moduleName + '\n')
|
||||
@ -64,7 +87,7 @@ def outputGlobalFileImports(file, methodList):
|
||||
file.write('\n')
|
||||
|
||||
|
||||
def outputImportFileImports(file, typeList):
|
||||
def outputImportFileImports(file, typeList, CModuleName):
|
||||
"""
|
||||
This is the file that we will import to get all the panda modules
|
||||
"""
|
||||
@ -76,10 +99,8 @@ def outputImportFileImports(file, typeList):
|
||||
file.write('import ' + FFIConstants.InterrogateModuleName + '\n')
|
||||
file.write('\n')
|
||||
|
||||
file.write('# Import the C modules\n')
|
||||
for CModuleName in FFIConstants.CodeModuleNameList:
|
||||
file.write('import ' + CModuleName + '\n')
|
||||
file.write('\n')
|
||||
file.write('# Import the C module\n')
|
||||
file.write('import ' + CModuleName + '\n')
|
||||
|
||||
# Filter out only the class and enum type descriptors (not const, pointers, etc)
|
||||
classTypeList = []
|
||||
@ -96,12 +117,9 @@ def outputImportFileImports(file, typeList):
|
||||
classTypeList.sort(FFIOverload.inheritanceLevelSort)
|
||||
|
||||
moduleList = []
|
||||
for type in classTypeList:
|
||||
for type in classTypeList:
|
||||
moduleList.append(type.foreignTypeName)
|
||||
|
||||
file.write('import FFIExternalObject\n')
|
||||
file.write('\n')
|
||||
|
||||
file.write('# Import enums into the global name space\n')
|
||||
for type in enumTypeList:
|
||||
file.write('from ' + type.enumName + ' import *\n')
|
||||
@ -113,25 +131,28 @@ def outputImportFileImports(file, typeList):
|
||||
file.write('\n')
|
||||
|
||||
file.write('# Import the global module file into our name space\n')
|
||||
file.write('from ' + FFIConstants.globalModuleName + ' import *\n')
|
||||
file.write('from ' + CModuleName + 'Globals' + ' import *\n')
|
||||
file.write('\n')
|
||||
|
||||
file.write('# Now generate the classes\n')
|
||||
file.write('# Generate the classes\n')
|
||||
for moduleName in moduleList:
|
||||
file.write(moduleName + '.generateClass_' + moduleName + '()\n')
|
||||
file.write('\n')
|
||||
|
||||
file.write('# Now put the classes in the wrapper class map\n')
|
||||
for moduleName in moduleList:
|
||||
file.write('obj = ' + moduleName + '.' + moduleName + '(None)\n')
|
||||
file.write('obj.registerInTypeMap()\n')
|
||||
file.write('\n')
|
||||
|
||||
file.write('# Now copy the classes into our own namespace\n')
|
||||
file.write('# Copy the classes into our own namespace\n')
|
||||
for moduleName in moduleList:
|
||||
file.write(moduleName + ' = ' + moduleName + '.' + moduleName + '\n')
|
||||
file.write('\n')
|
||||
|
||||
file.write('# Put the classes in the wrapper class map\n')
|
||||
file.write('from FFIExternalObject import registerInTypeMap\n')
|
||||
file.write('\n')
|
||||
for moduleName in moduleList:
|
||||
file.write('registerInTypeMap(' + moduleName + ')\n')
|
||||
file.write('\n')
|
||||
|
||||
|
||||
|
||||
def generateStaticClass(codeDir):
|
||||
"""
|
||||
Create a file that will hold the static class definition
|
||||
@ -472,6 +493,10 @@ class FFIInterrogateDatabase:
|
||||
built into the class they are being downcast from. For instance, a method
|
||||
downcastToNode(ptrBoundedObject) will appear in Node's list of methods
|
||||
but should be compiled into BoundedObject's class
|
||||
UPDATE: These are no longer compiled into the from-class. That was
|
||||
preventing the libraries from being independent since the from class
|
||||
now had knowledge of the to class which is potentially in a library
|
||||
downstream. Now these functions are just global functions
|
||||
"""
|
||||
numFuncs = interrogate_type_number_of_derivations(typeIndex)
|
||||
for i in range(numFuncs):
|
||||
@ -481,15 +506,21 @@ class FFIInterrogateDatabase:
|
||||
funcIndex = interrogate_type_get_downcast(typeIndex, i)
|
||||
typeDescs = self.constructFunctionTypeDescriptors(funcIndex)
|
||||
for typeDesc in typeDescs:
|
||||
funcSpec = FFISpecs.MethodSpecification()
|
||||
funcSpec = FFISpecs.GlobalFunctionSpecification()
|
||||
funcSpec.name = FFIRename.methodNameFromCppName(
|
||||
interrogate_function_name(funcIndex))
|
||||
funcSpec.typeDescriptor = typeDesc
|
||||
funcSpec.index = funcIndex
|
||||
# Here we look for the class in the first argument
|
||||
fromClass = typeDesc.argumentTypes[0].typeDescriptor.recursiveTypeDescriptor()
|
||||
|
||||
# Append the from class name on the method to uniquify it now
|
||||
# that these are global methods
|
||||
funcSpec.name = funcSpec.name + 'From' + fromClass.foreignTypeName
|
||||
|
||||
# Append this funcSpec to that class's downcast methods
|
||||
fromClass.downcastMethods.append(funcSpec)
|
||||
# fromClass.downcastMethods.append(funcSpec)
|
||||
self.environment.addDowncastFunction(funcSpec)
|
||||
|
||||
def constructConstructorSpecifications(self, typeIndex):
|
||||
funcSpecs = []
|
||||
@ -532,8 +563,14 @@ class FFIInterrogateDatabase:
|
||||
def addEnvironmentTypes(self):
|
||||
for descriptor in self.typeIndexMap.values():
|
||||
self.environment.addType(descriptor, descriptor.foreignTypeName)
|
||||
|
||||
def functionInCModule(self, funcIndex, CModuleName):
|
||||
if interrogate_function_has_module_name(funcIndex):
|
||||
moduleName = 'lib' + interrogate_function_module_name(funcIndex)
|
||||
return (moduleName == CModuleName)
|
||||
|
||||
|
||||
def constructGlobal(self, globalIndex):
|
||||
def constructGlobal(self, globalIndex, CModuleName):
|
||||
# We really do not need the descriptor for the value, just
|
||||
# the getter and setter
|
||||
# typeIndex = interrogate_element_type(globalIndex)
|
||||
@ -541,12 +578,18 @@ class FFIInterrogateDatabase:
|
||||
|
||||
if interrogate_element_has_getter(globalIndex):
|
||||
getterIndex = interrogate_element_getter(globalIndex)
|
||||
# If this function is not in this Cmodule just return
|
||||
if not self.functionInCModule(getterIndex, CModuleName):
|
||||
return None
|
||||
getter = self.constructGlobalFunction(getterIndex)
|
||||
else:
|
||||
getter = None
|
||||
|
||||
if interrogate_element_has_setter(globalIndex):
|
||||
setterIndex = interrogate_element_setter(globalIndex)
|
||||
# If this function is not in this Cmodule just return
|
||||
if not self.functionInCModule(setterIndex, CModuleName):
|
||||
return None
|
||||
setter = self.constructGlobalFunction(setterIndex)
|
||||
else:
|
||||
setter = None
|
||||
@ -570,21 +613,23 @@ class FFIInterrogateDatabase:
|
||||
funcSpec.index = globalIndex
|
||||
return funcSpec
|
||||
|
||||
def addGlobalFunctions(self):
|
||||
def addGlobalFunctions(self, CModuleName):
|
||||
numGlobals = interrogate_number_of_global_functions()
|
||||
for i in range(numGlobals):
|
||||
funcIndex = interrogate_get_global_function(i)
|
||||
newGlob = self.constructGlobalFunction(funcIndex)
|
||||
if newGlob:
|
||||
self.environment.addGlobalFunction(newGlob)
|
||||
if self.functionInCModule(funcIndex, CModuleName):
|
||||
newGlob = self.constructGlobalFunction(funcIndex)
|
||||
if newGlob:
|
||||
self.environment.addGlobalFunction(newGlob)
|
||||
|
||||
"""
|
||||
# Take all the global functions that have a Panda Class as their
|
||||
# first argument and make them class methods on that class
|
||||
# For example the global function
|
||||
# get_distance(node1, node2)
|
||||
# becomes:
|
||||
# node1.getDistance(node2)
|
||||
|
||||
|
||||
# Functions that do not get moved will be stored here temporarily
|
||||
tempGlobalFunctions = []
|
||||
for funcSpec in self.environment.globalFunctions:
|
||||
@ -602,15 +647,17 @@ class FFIInterrogateDatabase:
|
||||
else:
|
||||
# Copy this function into the temp list
|
||||
tempGlobalFunctions.append(funcSpec)
|
||||
# Now copy the temp list back over the real list
|
||||
# Copy the temp list back over the real list
|
||||
self.environment.globalFunctions = tempGlobalFunctions
|
||||
"""
|
||||
|
||||
def addGlobalValues(self):
|
||||
def addGlobalValues(self, CModuleName):
|
||||
numGlobals = interrogate_number_of_globals()
|
||||
for i in range(numGlobals):
|
||||
globalIndex = interrogate_get_global(i)
|
||||
newGlob = self.constructGlobal(globalIndex)
|
||||
self.environment.addGlobalValue(newGlob)
|
||||
newGlob = self.constructGlobal(globalIndex, CModuleName)
|
||||
if newGlob:
|
||||
self.environment.addGlobalValue(newGlob)
|
||||
|
||||
|
||||
def constructManifest(self, manifestIndex):
|
||||
@ -656,18 +703,50 @@ class FFIInterrogateDatabase:
|
||||
FFIConstants.notify.info( 'Generating static class...')
|
||||
generateStaticClass(codeDir)
|
||||
|
||||
# Import all the C++ modules
|
||||
for CModuleName in FFIConstants.CodeModuleNameList:
|
||||
self.generateCodeLib(codeDir, extensionsDir, CModuleName)
|
||||
|
||||
# For convenience, output a file that imports all the c module files
|
||||
file = open(os.path.join(codeDir, FFIConstants.importModuleName + '.py'), 'w')
|
||||
for CModuleName in FFIConstants.CodeModuleNameList:
|
||||
file.write('from ' + CModuleName + 'Modules import *\n')
|
||||
file.close()
|
||||
|
||||
FFIConstants.notify.info( 'Compiling code...')
|
||||
compileall.compile_dir(codeDir)
|
||||
|
||||
def generateCodeLib(self, codeDir, extensionsDir, CModuleName):
|
||||
# Reset the environment so we are clean from any old modules
|
||||
self.environment.reset()
|
||||
|
||||
FFIConstants.notify.info('==================================================')
|
||||
FFIConstants.notify.info('Importing code library: ' + CModuleName)
|
||||
exec('import ' + CModuleName)
|
||||
|
||||
self.updateBindings(CModuleName)
|
||||
|
||||
FFIConstants.notify.info( 'Generating type code...')
|
||||
for type in self.environment.types.values():
|
||||
# Do not generate code for nested types at the top level
|
||||
if (not type.isNested):
|
||||
type.generateGlobalCode(codeDir, extensionsDir)
|
||||
|
||||
|
||||
FFIConstants.notify.info( 'Generating global downcast code...')
|
||||
downcastFile = constructDowncastFile(codeDir, CModuleName)
|
||||
# Output all the imports based on this list of functions
|
||||
outputGlobalFileImports(downcastFile, self.environment.downcastFunctions, CModuleName)
|
||||
for type in self.environment.downcastFunctions:
|
||||
type.generateGlobalCode(downcastFile)
|
||||
|
||||
FFIConstants.notify.info( 'Generating global value code...')
|
||||
globalFile = constructGlobalFile(codeDir)
|
||||
globalFile = constructGlobalFile(codeDir, CModuleName)
|
||||
|
||||
# Make a list of all the global functions. This includes the normal
|
||||
# global functions as well as the getters and setters on all the
|
||||
# global values. This list is used to figure out what files to import
|
||||
# Only include the global functions from the current C module
|
||||
globalFunctions = self.environment.globalFunctions
|
||||
for globalValue in self.environment.globalValues:
|
||||
if globalValue.getter:
|
||||
@ -675,7 +754,7 @@ class FFIInterrogateDatabase:
|
||||
if globalValue.setter:
|
||||
globalFunctions.append(globalValue.setter)
|
||||
# Output all the imports based on this list of functions
|
||||
outputGlobalFileImports(globalFile, globalFunctions)
|
||||
outputGlobalFileImports(globalFile, globalFunctions, CModuleName)
|
||||
|
||||
FFIConstants.notify.info( 'Generating global value code...')
|
||||
for type in self.environment.globalValues:
|
||||
@ -692,21 +771,17 @@ class FFIInterrogateDatabase:
|
||||
globalFile.close()
|
||||
|
||||
FFIConstants.notify.info( 'Generating import code...')
|
||||
importFile = constructImportFile(codeDir)
|
||||
outputImportFileImports(importFile, self.environment.types.values())
|
||||
importFile = constructImportFile(codeDir, CModuleName)
|
||||
outputImportFileImports(importFile, self.environment.types.values(), CModuleName)
|
||||
|
||||
FFIConstants.notify.info( 'Compiling code...')
|
||||
compileall.compile_dir(codeDir)
|
||||
|
||||
|
||||
def updateBindings(self):
|
||||
def updateBindings(self, CModuleName):
|
||||
FFIConstants.notify.info( 'Updating Bindings')
|
||||
FFIConstants.notify.info( 'Adding Types...')
|
||||
self.addTypes()
|
||||
FFIConstants.notify.info( 'Adding global values...')
|
||||
self.addGlobalValues()
|
||||
self.addGlobalValues(CModuleName)
|
||||
FFIConstants.notify.info( 'Adding global functions...')
|
||||
self.addGlobalFunctions()
|
||||
self.addGlobalFunctions(CModuleName)
|
||||
FFIConstants.notify.info( 'Adding manifests symbols...')
|
||||
self.addManifestSymbols()
|
||||
FFIConstants.notify.info( 'Adding environment types...')
|
||||
|
@ -235,29 +235,35 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
|
||||
"""
|
||||
Return a list of all the C modules this class references
|
||||
"""
|
||||
moduleList = []
|
||||
for method in (self.constructors + [self.destructor] + self.instanceMethods
|
||||
+ self.upcastMethods + self.downcastMethods
|
||||
+ self.staticMethods + self.globalMethods):
|
||||
if method:
|
||||
if (not (method.typeDescriptor.moduleName in moduleList)):
|
||||
moduleList.append(method.typeDescriptor.moduleName)
|
||||
|
||||
# Now look at all the methods that we might inherit if we are at
|
||||
# a multiple inheritance node and get their C modules
|
||||
if (len(self.parentTypes) >= 2):
|
||||
for parentType in self.parentTypes:
|
||||
for method in parentType.instanceMethods:
|
||||
if (not (method.typeDescriptor.moduleName in moduleList)):
|
||||
moduleList.append(method.typeDescriptor.moduleName)
|
||||
for method in parentType.upcastMethods:
|
||||
if (not (method.typeDescriptor.moduleName in moduleList)):
|
||||
moduleList.append(method.typeDescriptor.moduleName)
|
||||
for method in parentType.globalMethods:
|
||||
if (not (method.typeDescriptor.moduleName in moduleList)):
|
||||
moduleList.append(method.typeDescriptor.moduleName)
|
||||
|
||||
return moduleList
|
||||
try:
|
||||
# Prevent from doing the work twice
|
||||
# if CModules is already defined, just return it
|
||||
return self.CModules
|
||||
except:
|
||||
# Otherwise, it must be our first time through, do the real work
|
||||
self.CModules = []
|
||||
for method in (self.constructors + [self.destructor] + self.instanceMethods
|
||||
+ self.upcastMethods + self.downcastMethods
|
||||
+ self.staticMethods + self.globalMethods):
|
||||
if method:
|
||||
if (not (method.typeDescriptor.moduleName in self.CModules)):
|
||||
self.CModules.append(method.typeDescriptor.moduleName)
|
||||
|
||||
# Now look at all the methods that we might inherit if we are at
|
||||
# a multiple inheritance node and get their C modules
|
||||
if (len(self.parentTypes) >= 2):
|
||||
for parentType in self.parentTypes:
|
||||
for method in parentType.instanceMethods:
|
||||
if (not (method.typeDescriptor.moduleName in self.CModules)):
|
||||
self.CModules.append(method.typeDescriptor.moduleName)
|
||||
for method in parentType.upcastMethods:
|
||||
if (not (method.typeDescriptor.moduleName in self.CModules)):
|
||||
self.CModules.append(method.typeDescriptor.moduleName)
|
||||
for method in parentType.globalMethods:
|
||||
if (not (method.typeDescriptor.moduleName in self.CModules)):
|
||||
self.CModules.append(method.typeDescriptor.moduleName)
|
||||
|
||||
return self.CModules
|
||||
|
||||
|
||||
def getReturnTypeModules(self):
|
||||
@ -586,6 +592,7 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
|
||||
indent(file, 0, '# Import all the C modules this class uses\n')
|
||||
for moduleName in self.getCModules():
|
||||
indent(file, 0, 'import ' + moduleName + '\n')
|
||||
indent(file, 0, 'import ' + moduleName + 'Downcasts\n')
|
||||
indent(file, 0, '\n')
|
||||
indent(file, 0, 'import FFIExternalObject\n')
|
||||
|
||||
@ -637,7 +644,12 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
|
||||
# that we will call later
|
||||
if (nesting==0):
|
||||
indent(file, nesting, '# Delay the definition of this class until all the imports are done\n')
|
||||
indent(file, nesting, '# Make sure we only define this class once\n')
|
||||
indent(file, nesting, 'classDefined = 0\n')
|
||||
indent(file, nesting, 'def generateClass_' + self.foreignTypeName + '():\n')
|
||||
indent(file, nesting, ' if classDefined: return\n')
|
||||
indent(file, nesting, ' global classDefined\n')
|
||||
indent(file, nesting, ' classDefined = 1\n')
|
||||
# Start the class definition indented a space to account for the function
|
||||
indent(file, nesting, ' class ' + self.foreignTypeName)
|
||||
else:
|
||||
@ -655,13 +667,22 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
|
||||
file.write(parentTypeName + '.' + parentTypeName)
|
||||
file.write(', ')
|
||||
file.write('FFIExternalObject.FFIExternalObject):\n')
|
||||
|
||||
# Store the class C modules for the class so they do not
|
||||
# get garbage collected before we do
|
||||
# TODO: this did not appear to work
|
||||
indent(file, nesting+1, '__CModules__ = [')
|
||||
for moduleName in self.getCModules():
|
||||
file.write(moduleName + ',')
|
||||
file.write(']\n')
|
||||
|
||||
|
||||
# Store the downcast function modules so the FFIExternalObject
|
||||
# can index into them to find the downcast functions
|
||||
indent(file, nesting+1, '__CModuleDowncasts__ = [')
|
||||
for moduleName in self.getCModules():
|
||||
file.write(moduleName + 'Downcasts,')
|
||||
file.write(']\n')
|
||||
|
||||
|
||||
def outputClassFooter(self, file):
|
||||
indent(file, 0, " # When this class gets defined, put it in this module's namespace\n")
|
||||
@ -744,8 +765,7 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
|
||||
if userManagesMemory:
|
||||
indent(file, nesting, 'returnObject.userManagesMemory = 1\n')
|
||||
if needsDowncast:
|
||||
indent(file, nesting, 'downcastObject = returnObject.setPointer()\n')
|
||||
indent(file, nesting, 'return downcastObject\n')
|
||||
indent(file, nesting, 'return returnObject.setPointer()\n')
|
||||
else:
|
||||
indent(file, nesting, 'return returnObject\n')
|
||||
|
||||
|
@ -109,6 +109,5 @@ else:
|
||||
# Ok, now we can start generating code
|
||||
import FFIInterrogateDatabase
|
||||
db = FFIInterrogateDatabase.FFIInterrogateDatabase()
|
||||
db.updateBindings()
|
||||
db.generateCode(outputDir, extensionsDir)
|
||||
|
||||
|
@ -42,12 +42,13 @@ class ShowBase:
|
||||
self.dataRoot = NodePath(NamedNode('dataRoot'), DataRelation.getClassType())
|
||||
self.dataUnused = NodePath(NamedNode('dataUnused'), DataRelation.getClassType())
|
||||
self.pipe = makeGraphicsPipe()
|
||||
self.win = self.pipe.makeGraphicsWindow(self.renderTop.node(),
|
||||
self.camera.node(),
|
||||
self.dataRoot.node(),
|
||||
self.initialState)
|
||||
self.win = makeGraphicsWindow(self.pipe,
|
||||
self.renderTop.node(),
|
||||
self.camera.node(),
|
||||
self.dataRoot.node(),
|
||||
self.initialState)
|
||||
|
||||
self.render2d = NodePath(self.win.setupPanda2d())
|
||||
self.render2d = NodePath(setupPanda2d(self.win))
|
||||
# This is a list of cams associated with the display region's cameras
|
||||
self.camList = []
|
||||
for camera in self.cameraList:
|
||||
@ -105,13 +106,13 @@ class ShowBase:
|
||||
self.eventMgr.shutdown()
|
||||
|
||||
def toggleBackface(self):
|
||||
self.initialState.toggleBackface()
|
||||
toggleBackface(self.initialState)
|
||||
|
||||
def toggleTexture(self):
|
||||
self.initialState.toggleTexture()
|
||||
toggleTexture(self.initialState)
|
||||
|
||||
def toggleWireframe(self):
|
||||
self.initialState.toggleWireframe()
|
||||
toggleWireframe(self.initialState)
|
||||
|
||||
def disableMouse(self):
|
||||
self.drive.reparentTo(self.dataUnused)
|
||||
|
@ -8,20 +8,22 @@ exit = -1
|
||||
done = 0
|
||||
cont = 1
|
||||
|
||||
# Store the global clock
|
||||
globalClock = ClockObject.getGlobalClock()
|
||||
|
||||
def getTimeFrame():
|
||||
# WARNING: If you are testing tasks without an igloop,
|
||||
# you must manually tick the clock
|
||||
|
||||
# Ask for the time last frame
|
||||
t = ClockObject.getGlobalClock().getTime()
|
||||
t = globalClock.getTime()
|
||||
|
||||
# Set the clock to have last frame's time in case we were
|
||||
# Paused at the prompt for a long time
|
||||
ClockObject.getGlobalClock().setTime(t)
|
||||
globalClock.setTime(t)
|
||||
|
||||
# Get the new frame count
|
||||
f = ClockObject.getGlobalClock().getFrameCount()
|
||||
f = globalClock.getFrameCount()
|
||||
|
||||
return t, f
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user