When exporting, if an object has a parent bone with the same name, add its geometry to the parent bone's model and discard the object itself.
This commit is contained in:
		@@ -24,50 +24,62 @@ def gather_models(apply_modifiers: bool, export_target: str, skeleton_only: bool
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    models_list: List[Model] = []
 | 
					    models_list: List[Model] = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    armature_found = None
 | 
					    # Composite bones are bones which have geometry.  
 | 
				
			||||||
 | 
					    # If a child object has the same name, it will take said child's geometry.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for uneval_obj in select_objects(export_target):
 | 
					    # Pure bones are just bones and after all objects are explored the only
 | 
				
			||||||
        if uneval_obj.type in SKIPPED_OBJECT_TYPES and uneval_obj.name not in parents:
 | 
					    # entries remaining in this dict will be bones without geometry.  
 | 
				
			||||||
 | 
					    pure_bones_from_armature = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    objects_to_export = select_objects(export_target)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for uneval_obj in objects_to_export:
 | 
				
			||||||
 | 
					        if uneval_obj.type == "ARMATURE":
 | 
				
			||||||
 | 
					            armature_found = uneval_obj.evaluated_get(depsgraph) if apply_modifiers else uneval_obj
 | 
				
			||||||
 | 
					            pure_bones_from_armature = expand_armature(armature_found)
 | 
				
			||||||
 | 
					            break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for uneval_obj in objects_to_export:
 | 
				
			||||||
 | 
					        if uneval_obj.type == "ARMATURE" or (uneval_obj.type in SKIPPED_OBJECT_TYPES and uneval_obj.name not in parents):
 | 
				
			||||||
            continue
 | 
					            continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if apply_modifiers:
 | 
					        obj = uneval_obj.evaluated_get(depsgraph) if apply_modifiers else uneval_obj
 | 
				
			||||||
            obj = uneval_obj.evaluated_get(depsgraph)
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            obj = uneval_obj 
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        check_for_bad_lod_suffix(obj)
 | 
					        check_for_bad_lod_suffix(obj)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if obj.type == "ARMATURE":
 | 
					        # Test for a mesh object that is actually a BONE (shares name with bone_parent)
 | 
				
			||||||
            models_list += expand_armature(obj)
 | 
					        # If so, we inject geometry into the BONE while not modifying it's transform/name
 | 
				
			||||||
            armature_found = obj
 | 
					        if obj.parent_bone and obj.parent_bone in pure_bones_from_armature:
 | 
				
			||||||
            continue
 | 
					            model = pure_bones_from_armature[obj.parent_bone]
 | 
				
			||||||
 | 
					            # Since we found a composite bone, removed it from the dict of pure bones
 | 
				
			||||||
        model = Model()
 | 
					            pure_bones_from_armature.pop(obj.parent_bone)
 | 
				
			||||||
        model.name = obj.name
 | 
					 | 
				
			||||||
        model.model_type = get_model_type(obj, skeleton_only)
 | 
					 | 
				
			||||||
        model.hidden = get_is_model_hidden(obj)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        transform = obj.matrix_local
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if obj.parent_bone:
 | 
					 | 
				
			||||||
            model.parent = obj.parent_bone
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # matrix_local, when called on an armature child also parented to a bone, appears to be broken.
 | 
					 | 
				
			||||||
            # At the very least, the results contradict the docs...  
 | 
					 | 
				
			||||||
            armature_relative_transform = obj.parent.matrix_world.inverted() @ obj.matrix_world
 | 
					 | 
				
			||||||
            transform = obj.parent.data.bones[obj.parent_bone].matrix_local.inverted() @ armature_relative_transform 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            if obj.parent is not None:
 | 
					            model = Model()
 | 
				
			||||||
                if obj.parent.type == "ARMATURE":
 | 
					            model.name = obj.name
 | 
				
			||||||
                    model.parent = obj.parent.parent.name if obj.parent.parent else ""
 | 
					            model.model_type = get_model_type(obj, skeleton_only)
 | 
				
			||||||
                    transform = obj.parent.matrix_local @ transform
 | 
					            model.hidden = get_is_model_hidden(obj)
 | 
				
			||||||
                else:
 | 
					 | 
				
			||||||
                    model.parent = obj.parent.name
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        local_translation, local_rotation, _ = transform.decompose()
 | 
					            transform = obj.matrix_local
 | 
				
			||||||
        model.transform.rotation = convert_rotation_space(local_rotation)  
 | 
					
 | 
				
			||||||
        model.transform.translation = convert_vector_space(local_translation)
 | 
					            if obj.parent_bone:
 | 
				
			||||||
 | 
					                model.parent = obj.parent_bone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                # matrix_local, when called on an armature child also parented to a bone, appears to be broken.
 | 
				
			||||||
 | 
					                # At the very least, the results contradict the docs...  
 | 
				
			||||||
 | 
					                armature_relative_transform = obj.parent.matrix_world.inverted() @ obj.matrix_world
 | 
				
			||||||
 | 
					                transform = obj.parent.data.bones[obj.parent_bone].matrix_local.inverted() @ armature_relative_transform 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                if obj.parent is not None:
 | 
				
			||||||
 | 
					                    if obj.parent.type == "ARMATURE":
 | 
				
			||||||
 | 
					                        model.parent = obj.parent.parent.name if obj.parent.parent else ""
 | 
				
			||||||
 | 
					                        transform = obj.parent.matrix_local @ transform
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        model.parent = obj.parent.name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            local_translation, local_rotation, _ = transform.decompose()
 | 
				
			||||||
 | 
					            model.transform.rotation = convert_rotation_space(local_rotation)  
 | 
				
			||||||
 | 
					            model.transform.translation = convert_vector_space(local_translation)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if obj.type in MESH_OBJECT_TYPES:
 | 
					        if obj.type in MESH_OBJECT_TYPES:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -92,9 +104,11 @@ def gather_models(apply_modifiers: bool, export_target: str, skeleton_only: bool
 | 
				
			|||||||
        if get_is_collision_primitive(obj):
 | 
					        if get_is_collision_primitive(obj):
 | 
				
			||||||
            model.collisionprimitive = get_collision_primitive(obj)
 | 
					            model.collisionprimitive = get_collision_primitive(obj)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
        models_list.append(model)
 | 
					        models_list.append(model)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # We removed all composite bones after looking through the objects,
 | 
				
			||||||
 | 
					    # so the bones left are all pure and we add them all here.
 | 
				
			||||||
 | 
					    models_list += pure_bones_from_armature.values()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (models_list, armature_found)
 | 
					    return (models_list, armature_found)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -371,11 +385,17 @@ def select_objects(export_target: str) -> List[bpy.types.Object]:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def expand_armature(armature: bpy.types.Object) -> List[Model]:
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def expand_armature(armature: bpy.types.Object) -> Dict[str, Model]:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    proper_BONES = get_real_BONES(armature)
 | 
					    proper_BONES = get_real_BONES(armature)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bones: List[Model] = []
 | 
					    bones: Dict[str, Model] = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for bone in armature.data.bones:
 | 
					    for bone in armature.data.bones:
 | 
				
			||||||
        model = Model()
 | 
					        model = Model()
 | 
				
			||||||
@@ -390,7 +410,7 @@ def expand_armature(armature: bpy.types.Object) -> List[Model]:
 | 
				
			|||||||
        #   set model parent to armature parent if there is one
 | 
					        #   set model parent to armature parent if there is one
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            bone_world_matrix = armature.matrix_world @ transform
 | 
					            bone_world_matrix = get_bone_world_matrix(armature, bone.name)
 | 
				
			||||||
            parent_obj = None
 | 
					            parent_obj = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for child_obj in armature.original.children:
 | 
					            for child_obj in armature.original.children:
 | 
				
			||||||
@@ -418,6 +438,6 @@ def expand_armature(armature: bpy.types.Object) -> List[Model]:
 | 
				
			|||||||
        model.transform.rotation = convert_rotation_space(local_rotation)
 | 
					        model.transform.rotation = convert_rotation_space(local_rotation)
 | 
				
			||||||
        model.transform.translation = convert_vector_space(local_translation)
 | 
					        model.transform.translation = convert_vector_space(local_translation)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bones.append(model)
 | 
					        bones[bone.name] = model
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return bones
 | 
					    return bones
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,6 +12,14 @@ from .msh_model_utilities import *
 | 
				
			|||||||
from .crc import *
 | 
					from .crc import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_bone_world_matrix(armature: bpy.types.Object, bone_name: str) -> Matrix:
 | 
				
			||||||
 | 
					    if bone_name in armature.data.bones:
 | 
				
			||||||
 | 
					        return armature.matrix_world @ armature.data.bones[bone_name].matrix_local
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def has_preserved_skeleton(armature : bpy.types.Armature):
 | 
					def has_preserved_skeleton(armature : bpy.types.Armature):
 | 
				
			||||||
    return len(armature.data.swbf_msh_skel) > 0
 | 
					    return len(armature.data.swbf_msh_skel) > 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user