EntityTypeRegistry.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. """EntityTypeRegistry module: contains the EntityTypeRegistry class"""
  2. from pandac.PandaModules import *
  3. from direct.directnotify import DirectNotifyGlobal
  4. import types
  5. import AttribDesc
  6. import EntityTypeDesc
  7. from direct.showbase.PythonUtil import mostDerivedLast
  8. class EntityTypeRegistry:
  9. notify = DirectNotifyGlobal.directNotify.newCategory('EntityTypeRegistry')
  10. def __init__(self, entityTypeModule):
  11. """pass in a module that contains EntityTypeDesc classes"""
  12. self.entTypeModule = entityTypeModule
  13. # compute the hash of the source modules as of the time of creation
  14. hv = HashVal()
  15. import EntityTypes
  16. reload(EntityTypes)
  17. reload(self.entTypeModule)
  18. hv.hashFile(Filename.fromOsSpecific(EntityTypes.__file__))
  19. s = str(hv.asHex())
  20. s += '.'
  21. hv.hashFile(Filename.fromOsSpecific(self.entTypeModule.__file__))
  22. s += str(hv.asHex())
  23. self.hashStr = s
  24. # get a list of the EntityTypeDesc classes in the type module
  25. classes = []
  26. for key, value in entityTypeModule.__dict__.items():
  27. if type(value) is types.ClassType:
  28. if issubclass(value, EntityTypeDesc.EntityTypeDesc):
  29. classes.append(value)
  30. self.entTypeName2typeDesc = {}
  31. # create an instance of each EntityType class with a typename
  32. # make sure that derived classes come after bases
  33. mostDerivedLast(classes)
  34. for c in classes:
  35. if c.__dict__.has_key('type'):
  36. if self.entTypeName2typeDesc.has_key(c.type):
  37. # a more-derived class is replacing a less-derived class
  38. # to implement a particular entity type
  39. EntityTypeRegistry.notify.info(
  40. "replacing %s with %s for entity type '%s'" %
  41. (self.entTypeName2typeDesc[c.type].__class__,
  42. c, c.type))
  43. self.entTypeName2typeDesc[c.type] = c()
  44. # create mapping of entity output types to list of concrete entity
  45. # typenames with that output type
  46. self.output2typeNames = {}
  47. for typename, typeDesc in self.entTypeName2typeDesc.items():
  48. if typeDesc.isConcrete():
  49. if hasattr(typeDesc, 'output'):
  50. outputType = typeDesc.output
  51. self.output2typeNames.setdefault(outputType, [])
  52. self.output2typeNames[outputType].append(typename)
  53. # create list of permanent entity typenames (entity types that cannot
  54. # be inserted or removed in the editor)
  55. self.permanentTypeNames = []
  56. for typename, typeDesc in self.entTypeName2typeDesc.items():
  57. if typeDesc.isPermanent():
  58. assert typeDesc.isConcrete()
  59. self.permanentTypeNames.append(typename)
  60. # create mapping of entity typename (abstract or concrete) to list
  61. # of entity typenames are concrete and are of that type or derive
  62. # from that type
  63. self.typeName2derivedTypeNames = {}
  64. for typename, typeDesc in self.entTypeName2typeDesc.items():
  65. typenames = []
  66. for tn, td in self.entTypeName2typeDesc.items():
  67. if td.isConcrete():
  68. if issubclass(td.__class__, typeDesc.__class__):
  69. typenames.append(tn)
  70. self.typeName2derivedTypeNames[typename] = typenames
  71. def getTypeDesc(self, entTypeName):
  72. """returns EntityTypeDesc instance for concrete Entity type"""
  73. assert entTypeName in self.entTypeName2typeDesc,\
  74. "unknown entity type '%s'" % entTypeName
  75. # the table has descriptors for abstract entity types, but I don't
  76. # think there's any need for anyone outside this class to access them
  77. assert self.entTypeName2typeDesc[entTypeName].isConcrete(),\
  78. "entity type '%s' is abstract" % entTypeName
  79. return self.entTypeName2typeDesc[entTypeName]
  80. def getTypeNamesFromOutputType(self, outputType):
  81. """return Entity typenames for Entity types with particular output"""
  82. return self.output2typeNames.get(outputType, [])
  83. def getDerivedTypeNames(self, entTypeName):
  84. """return Entity typenames that are of or derive from an entity type,
  85. which may be concrete or abstract"""
  86. assert entTypeName in self.typeName2derivedTypeNames,\
  87. "unknown entity type '%s'" % entTypeName
  88. return self.typeName2derivedTypeNames[entTypeName]
  89. def isDerivedAndBase(self, entType, baseEntType):
  90. return entType in self.getDerivedTypeNames(baseEntType)
  91. def getPermanentTypeNames(self):
  92. return self.permanentTypeNames
  93. def getHashStr(self):
  94. return self.hashStr
  95. def __hash__(self):
  96. # THIS IS NOT GUARANTEED TO PRODUCE THE SAME VALUE ACROSS DIFFERENT
  97. # MACHINES; use getHashStr instead
  98. return hash(repr(self))
  99. def __repr__(self):
  100. # this is used to produce a hash value
  101. return str(self.entTypeName2typeDesc)