Skip to content
Snippets Groups Projects
fbx_utils.py 44.3 KiB
Newer Older
  • Learn to ignore specific revisions
  •         # Our matrix is in local space, time to bring it in its final desired space.
            if parent:
                if is_global:
                    # Move matrix to global Blender space.
                    matrix = (parent.matrix_rest_global if rest else parent.matrix_global) * matrix
                elif parent.use_bake_space_transform(scene_data):
                    # Blender's and FBX's local space of parent may differ if we use bake_space_transform...
                    # Apply parent's *Blender* local space...
                    matrix = (parent.matrix_rest_local if rest else parent.matrix_local) * matrix
                    # ...and move it back into parent's *FBX* local space.
                    par_mat = parent.fbx_object_matrix(scene_data, rest=rest, local_space=True)
    
                    matrix = par_mat.inverted_safe() * matrix
    
    
            if self.use_bake_space_transform(scene_data):
                # If we bake the transforms we need to post-multiply inverse global transform.
                # This means that the global transform will not apply to children of this transform.
                matrix = matrix * scene_data.settings.global_matrix_inv
            if is_global:
                # In any case, pre-multiply the global matrix to get it in FBX global space!
                matrix = scene_data.settings.global_matrix * matrix
    
            return matrix
    
        def fbx_object_tx(self, scene_data, rest=False, rot_euler_compat=None):
            """
            Generate object transform data (always in local space when possible).
            """
            matrix = self.fbx_object_matrix(scene_data, rest=rest)
            loc, rot, scale = matrix.decompose()
            matrix_rot = rot.to_matrix()
            # quat -> euler, we always use 'XYZ' order, use ref rotation if given.
            if rot_euler_compat is not None:
                rot = rot.to_euler('XYZ', rot_euler_compat)
            else:
                rot = rot.to_euler('XYZ')
            return loc, rot, scale, matrix, matrix_rot
    
    
        # #### _tag dependent...
    
        def get_is_object(self):
            return self._tag == 'OB'
        is_object = property(get_is_object)
    
        def get_is_dupli(self):
            return self._tag == 'DP'
        is_dupli = property(get_is_dupli)
    
        def get_is_bone(self):
            return self._tag == 'BO'
        is_bone = property(get_is_bone)
    
        def get_type(self):
            if self._tag in {'OB', 'DP'}:
                return self.bdata.type
            return ...
        type = property(get_type)
    
        def get_armature(self):
            if self._tag == 'BO':
                return ObjectWrapper(self._ref)
            return None
        armature = property(get_armature)
    
        def get_bones(self):
            if self._tag == 'OB' and self.bdata.type == 'ARMATURE':
                return (ObjectWrapper(bo, self.bdata) for bo in self.bdata.data.bones)
            return ()
        bones = property(get_bones)
    
        def get_material_slots(self):
            if self._tag in {'OB', 'DP'}:
                return self.bdata.material_slots
            return ()
        material_slots = property(get_material_slots)
    
    
        def is_deformed_by_armature(self, arm_obj):
            if not (self.is_object and self.type == 'MESH'):
                return False
    
            if self.parent == arm_obj and self.bdata.parent_type == 'ARMATURE':
    
                return True
            for mod in self.bdata.modifiers:
                if mod.type == 'ARMATURE' and mod.object == arm_obj.bdata:
                    return True
    
    
        # #### Duplis...
    
        def dupli_list_create(self, scene, settings='PREVIEW'):
            if self._tag == 'OB':
                # Sigh, why raise exception here? :/
                try:
                    self.bdata.dupli_list_create(scene, settings)
                except:
                    pass
    
        def dupli_list_clear(self):
            if self._tag == 'OB':
                self.bdata.dupli_list_clear()
    
        def get_dupli_list(self):
            if self._tag == 'OB':
                return (ObjectWrapper(dup) for dup in self.bdata.dupli_list)
            return ()
        dupli_list = property(get_dupli_list)
    
    
    def fbx_name_class(name, cls):
        return FBX_NAME_CLASS_SEP.join((name, cls))
    
    
    
    # ##### Top-level FBX data container. #####
    
    
    # Helper sub-container gathering all exporter settings related to media (texture files).
    
    FBXExportSettingsMedia = namedtuple("FBXExportSettingsMedia", (
    
        "path_mode", "base_src", "base_dst", "subdir",
        "embed_textures", "copy_set",
    ))
    
    # Helper container gathering all exporter settings.
    
    FBXExportSettings = namedtuple("FBXExportSettings", (
    
        "report", "to_axes", "global_matrix", "global_scale",
        "bake_space_transform", "global_matrix_inv", "global_matrix_inv_transposed",
        "context_objects", "object_types", "use_mesh_modifiers",
    
        "mesh_smooth_type", "use_mesh_edges", "use_tspace",
        "use_armature_deform_only", "add_leaf_bones", "bone_correction_matrix", "bone_correction_matrix_inv",
    
        "bake_anim", "bake_anim_use_nla_strips", "bake_anim_use_all_actions", "bake_anim_step", "bake_anim_simplify_factor",
    
        "use_metadata", "media_settings", "use_custom_props",
    
    ))
    
    # Helper container gathering some data we need multiple times:
    #     * templates.
    #     * settings, scene.
    #     * objects.
    #     * object data.
    #     * skinning data (binding armature/mesh).
    #     * animations.
    
    FBXExportData = namedtuple("FBXExportData", (
    
        "templates", "templates_users", "connections",
        "settings", "scene", "objects", "animations", "frame_start", "frame_end",
        "data_empties", "data_lamps", "data_cameras", "data_meshes", "mesh_mat_indices",
    
        "data_bones", "data_leaf_bones", "data_deformers_skin", "data_deformers_shape",
    
        "data_world", "data_materials", "data_textures", "data_videos",
    ))
    
    
    # Helper container gathering all importer settings.
    FBXImportSettings = namedtuple("FBXImportSettings", (
        "report", "to_axes", "global_matrix", "global_scale",
    
        "bake_space_transform", "global_matrix_inv", "global_matrix_inv_transposed",
    
        "use_cycles", "use_image_search",
        "use_alpha_decals", "decal_offset",
    
        "use_custom_props", "use_custom_props_enum_as_string",
    
        "ignore_leaf_bones", "automatic_bone_orientation", "bone_correction_matrix", "use_prepost_rot",