object.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. from .. import constants, logger
  2. from . import base_classes, api
  3. class Object(base_classes.BaseNode):
  4. """Class that wraps an object node"""
  5. def __init__(self, node, parent=None, type=None):
  6. logger.debug("Object().__init__(%s)", node)
  7. base_classes.BaseNode.__init__(self, node, parent=parent, type=type)
  8. if self.node:
  9. self._node_setup()
  10. else:
  11. self._root_setup()
  12. @property
  13. def data(self):
  14. """
  15. :return: returns the data block of the node
  16. """
  17. return api.data(self.node)
  18. def _init_camera(self):
  19. """Initialize camera attributes"""
  20. logger.debug("Object()._init_camera()")
  21. self[constants.FAR] = api.camera.far(self.data)
  22. self[constants.NEAR] = api.camera.near(self.data)
  23. if self[constants.TYPE] == constants.PERSPECTIVE_CAMERA:
  24. self[constants.ASPECT] = api.camera.aspect(self.data)
  25. self[constants.FOV] = api.camera.fov(self.data)
  26. elif self[constants.TYPE] == constants.ORTHOGRAPHIC_CAMERA:
  27. self[constants.LEFT] = api.camera.left(self.data)
  28. self[constants.RIGHT] = api.camera.right(self.data)
  29. self[constants.TOP] = api.camera.top(self.data)
  30. self[constants.BOTTOM] = api.camera.bottom(self.data)
  31. #@TODO: need more light attributes. Some may have to come from
  32. # custom blender attributes.
  33. def _init_light(self):
  34. """Initialize light attributes"""
  35. logger.debug("Object()._init_light()")
  36. self[constants.COLOR] = api.light.color(self.data)
  37. self[constants.INTENSITY] = api.light.intensity(self.data)
  38. # Commented out because Blender's distance is not a cutoff value.
  39. #if self[constants.TYPE] != constants.DIRECTIONAL_LIGHT:
  40. # self[constants.DISTANCE] = api.light.distance(self.data)
  41. self[constants.DISTANCE] = 0;
  42. lightType = self[constants.TYPE]
  43. # TODO (abelnation): handle Area lights
  44. if lightType == constants.SPOT_LIGHT:
  45. self[constants.ANGLE] = api.light.angle(self.data)
  46. self[constants.DECAY] = api.light.falloff(self.data)
  47. elif lightType == constants.POINT_LIGHT:
  48. self[constants.DECAY] = api.light.falloff(self.data)
  49. def _init_mesh(self):
  50. """Initialize mesh attributes"""
  51. logger.debug("Object()._init_mesh()")
  52. mesh = api.object.mesh(self.node, self.options)
  53. node = self.scene.geometry(mesh)
  54. if node:
  55. self[constants.GEOMETRY] = node[constants.UUID]
  56. else:
  57. msg = "Could not find Geometry() node for %s"
  58. logger.error(msg, self.node)
  59. def _node_setup(self):
  60. """Parse common node attributes of all objects"""
  61. logger.debug("Object()._node_setup()")
  62. self[constants.NAME] = api.object.name(self.node)
  63. transform = api.object.matrix(self.node, self.options)
  64. matrix = []
  65. for col in range(0, 4):
  66. for row in range(0, 4):
  67. matrix.append(transform[row][col])
  68. self[constants.MATRIX] = matrix
  69. self[constants.VISIBLE] = api.object.visible(self.node)
  70. self[constants.TYPE] = api.object.node_type(self.node)
  71. if self.options.get(constants.MATERIALS):
  72. logger.info("Parsing materials for %s", self.node)
  73. material_names = api.object.material(self.node) #manthrax: changes for multimaterial start here
  74. if material_names:
  75. logger.info("Got material names for this object:%s",str(material_names));
  76. materialArray = [self.scene.material(objname)[constants.UUID] for objname in material_names]
  77. if len(materialArray) == 0: # If no materials.. dont export a material entry
  78. materialArray = None
  79. elif len(materialArray) == 1: # If only one material, export material UUID singly, not as array
  80. materialArray = materialArray[0]
  81. # else export array of material uuids
  82. self[constants.MATERIAL] = materialArray
  83. logger.info("Materials:%s",str(self[constants.MATERIAL]));
  84. else:
  85. logger.info("%s has no materials", self.node) #manthrax: end multimaterial
  86. # TODO (abelnation): handle Area lights
  87. casts_shadow = (constants.MESH,
  88. constants.DIRECTIONAL_LIGHT,
  89. constants.SPOT_LIGHT)
  90. if self[constants.TYPE] in casts_shadow:
  91. logger.info("Querying shadow casting for %s", self.node)
  92. self[constants.CAST_SHADOW] = \
  93. api.object.cast_shadow(self.node)
  94. if self[constants.TYPE] == constants.MESH:
  95. logger.info("Querying shadow receive for %s", self.node)
  96. self[constants.RECEIVE_SHADOW] = \
  97. api.object.receive_shadow(self.node)
  98. camera = (constants.PERSPECTIVE_CAMERA,
  99. constants.ORTHOGRAPHIC_CAMERA)
  100. # TODO (abelnation): handle Area lights
  101. lights = (constants.AMBIENT_LIGHT,
  102. constants.DIRECTIONAL_LIGHT,
  103. constants.POINT_LIGHT,
  104. constants.SPOT_LIGHT, constants.HEMISPHERE_LIGHT)
  105. if self[constants.TYPE] == constants.MESH:
  106. self._init_mesh()
  107. elif self[constants.TYPE] in camera:
  108. self._init_camera()
  109. elif self[constants.TYPE] in lights:
  110. self._init_light()
  111. no_anim = (None, False, constants.OFF)
  112. if self.options.get(constants.KEYFRAMES) not in no_anim:
  113. logger.info("Export Transform Animation for %s", self.node)
  114. if self._scene:
  115. # only when exporting scene
  116. tracks = api.object.animated_xform(self.node, self.options)
  117. merge = self._scene[constants.ANIMATION][0][constants.KEYFRAMES]
  118. for track in tracks:
  119. merge.append(track)
  120. if self.options.get(constants.HIERARCHY, False):
  121. for child in api.object.children(self.node, self.scene.valid_types):
  122. if not self.get(constants.CHILDREN):
  123. self[constants.CHILDREN] = [Object(child, parent=self)]
  124. else:
  125. self[constants.CHILDREN].append(Object(child, parent=self))
  126. if self.options.get(constants.CUSTOM_PROPERTIES, False):
  127. self[constants.USER_DATA] = api.object.custom_properties(self.node)
  128. def _root_setup(self):
  129. """Applies to a root/scene object"""
  130. logger.debug("Object()._root_setup()")
  131. self[constants.MATRIX] = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0,
  132. 1, 0, 0, 0, 0, 1]