From c314592d489dd8ba1c512d25cb3f4f9eb3ccbe65 Mon Sep 17 00:00:00 2001 From: Will Snyder Date: Thu, 13 Jan 2022 12:52:30 -0800 Subject: [PATCH] Dont include bone in exported anim if its not keyed or in preserved skel... --- addons/io_scene_swbf_msh/msh_anim_gather.py | 26 ++++++++++++++++++- addons/io_scene_swbf_msh/msh_model_gather.py | 19 +++++++++----- .../io_scene_swbf_msh/msh_model_utilities.py | 2 +- addons/io_scene_swbf_msh/msh_scene_save.py | 8 +++++- addons/io_scene_swbf_msh/msh_to_blend.py | 18 ++++++------- 5 files changed, 55 insertions(+), 18 deletions(-) diff --git a/addons/io_scene_swbf_msh/msh_anim_gather.py b/addons/io_scene_swbf_msh/msh_anim_gather.py index 52fc6c4..8a4c613 100644 --- a/addons/io_scene_swbf_msh/msh_anim_gather.py +++ b/addons/io_scene_swbf_msh/msh_anim_gather.py @@ -14,9 +14,29 @@ from .msh_model_gather import * from .crc import to_crc + + def extract_anim(armature: bpy.types.Armature, root_name: str) -> Animation: action = armature.animation_data.action + + # Set of bones to include in SKL2/animation stuff + keyable_bones : Set[str] = set() + + msh_skel = armature.data.swbf_msh_skel + + has_preserved_skel = len(msh_skel) > 0 + + if has_preserved_skel: + for bone in msh_skel: + #print("Adding {} from preserved skel to exported skeleton".format(bone.name)) + keyable_bones.add(bone.name) + elif action: + for group in action.groups: + #print("Adding {} from action groups to exported skeleton".format(group.name)) + keyable_bones.add(group.name) + + anim = Animation(); root_crc = to_crc(root_name) @@ -33,7 +53,8 @@ def extract_anim(armature: bpy.types.Armature, root_name: str) -> Animation: anim.bone_frames[root_crc] = ([], []) for bone in armature.data.bones: - anim.bone_frames[to_crc(bone.name)] = ([], []) + if bone.name in keyable_bones: + anim.bone_frames[to_crc(bone.name)] = ([], []) for frame in range(num_frames): @@ -50,6 +71,9 @@ def extract_anim(armature: bpy.types.Armature, root_name: str) -> Animation: for bone in armature.pose.bones: + if bone.name not in keyable_bones: + continue + transform = bone.matrix if bone.parent: diff --git a/addons/io_scene_swbf_msh/msh_model_gather.py b/addons/io_scene_swbf_msh/msh_model_gather.py index 1eade29..90361d6 100644 --- a/addons/io_scene_swbf_msh/msh_model_gather.py +++ b/addons/io_scene_swbf_msh/msh_model_gather.py @@ -311,7 +311,8 @@ def get_collision_primitive_shape(obj: bpy.types.Object) -> CollisionPrimitiveSh if "box" in name or "cube" in name or "cuboid" in name: return CollisionPrimitiveShape.BOX - raise RuntimeError(f"Object '{obj.name}' has no primitive type specified in it's name!") + return CollisionPrimitiveShape.BOX + #raise RuntimeError(f"Object '{obj.name}' has no primitive type specified in it's name!") def check_for_bad_lod_suffix(obj: bpy.types.Object): """ Checks if the object has an LOD suffix that is known to be ignored by """ @@ -371,10 +372,11 @@ def select_objects(export_target: str) -> List[bpy.types.Object]: -def expand_armature(obj: bpy.types.Object) -> List[Model]: +def expand_armature(armature: bpy.types.Object) -> List[Model]: + bones: List[Model] = [] - for bone in obj.data.bones: + for bone in armature.data.bones: model = Model() transform = bone.matrix_local @@ -382,11 +384,16 @@ def expand_armature(obj: bpy.types.Object) -> List[Model]: if bone.parent: transform = bone.parent.matrix_local.inverted() @ transform model.parent = bone.parent.name + # If the bone has no parent_bone: + # set model parent to SKIN object if there is one + # set model parent to armature parent if there is one else: - model.parent = obj.parent.name - for child_obj in obj.children: - if child_obj.vertex_groups and not get_is_model_hidden(obj) and not obj.parent_bone: + for child_obj in armature.children: + if child_obj.vertex_groups and not get_is_model_hidden(child_obj) and not child_obj.parent_bone: model.parent = child_obj.name + break + if not model.parent and armature.parent: + model.parent = armature.parent.name local_translation, local_rotation, _ = transform.decompose() diff --git a/addons/io_scene_swbf_msh/msh_model_utilities.py b/addons/io_scene_swbf_msh/msh_model_utilities.py index afc692a..1b8d314 100644 --- a/addons/io_scene_swbf_msh/msh_model_utilities.py +++ b/addons/io_scene_swbf_msh/msh_model_utilities.py @@ -9,7 +9,7 @@ from mathutils import Vector, Matrix def inject_dummy_data(model : Model): - """ Adds a triangle and material to the scene root when exporting skeletons to satisfy ZenAsset. """ + """ Adds a triangle and material to the model (scene root). Needed to export zenasst-compatible skeletons. """ model.hidden = True dummy_seg = GeometrySegment() diff --git a/addons/io_scene_swbf_msh/msh_scene_save.py b/addons/io_scene_swbf_msh/msh_scene_save.py index ccc7587..098aa89 100644 --- a/addons/io_scene_swbf_msh/msh_scene_save.py +++ b/addons/io_scene_swbf_msh/msh_scene_save.py @@ -30,14 +30,20 @@ def save_scene(output_file, scene: Scene): with msh2.create_child("MODL") as modl: _write_modl(modl, model, index, material_index, model_index) + # Contrary to earlier belief, anim/skel info does not need to be exported for animated models + # BUT, unless a model is a BONE, it wont animate! + # This is not necessary when exporting animations. When exporting animations, the following + # chunks are necessary and the animated models can be marked as NULLs if scene.animation is not None: + # Seems as though SKL2 is wholly unneccessary from SWBF's perspective (for models and anims), + # but it is there in all stock models/anims with hedr.create_child("SKL2") as skl2: _write_skl2(skl2, scene.animation) with hedr.create_child("BLN2") as bln2: _write_bln2(bln2, scene.animation) - with hedr.create_child("ANM2") as anm2: #simple for now + with hedr.create_child("ANM2") as anm2: _write_anm2(anm2, scene.animation) with hedr.create_child("CL1L"): diff --git a/addons/io_scene_swbf_msh/msh_to_blend.py b/addons/io_scene_swbf_msh/msh_to_blend.py index 7701138..bde5682 100644 --- a/addons/io_scene_swbf_msh/msh_to_blend.py +++ b/addons/io_scene_swbf_msh/msh_to_blend.py @@ -113,14 +113,7 @@ def required_skeleton_to_armature(required_skeleton : List[Model], model_map : D armature_obj = bpy.data.objects.new("skeleton", armature) bpy.context.view_layer.active_layer_collection.collection.objects.link(armature_obj) - - preserved = armature_obj.data.swbf_msh_skel - for model in required_skeleton: - if to_crc(model.name) in msh_scene.skeleton: - entry = preserved.add() - entry.name = model.name - - + bones_set = set([model.name for model in required_skeleton]) armature_obj.select_set(True) @@ -200,7 +193,7 @@ def extract_required_skeleton(scene: Scene) -> List[Model]: model_dict[model.name] = model #if to_crc(model.name) in scene.skeleton: - print("Skel model {} of type {} has parent {}".format(model.name, model.model_type, model.parent)) + # print("Skel model {} of type {} has parent {}".format(model.name, model.model_type, model.parent)) if model.model_type == ModelType.BONE: skeleton_hashes.add(to_crc(model.name)) @@ -436,6 +429,13 @@ def extract_scene(filepath: str, scene: Scene): # Create the armature if skel is non-empty armature = None if not skel else required_skeleton_to_armature(skel, model_map, scene) + if armature is not None: + preserved = armature.data.swbf_msh_skel + for model in scene.models: + if to_crc(model.name) in scene.skeleton: + entry = preserved.add() + entry.name = model.name + ''' If an armature was created, we need to do a few extra