Dont include bone in exported anim if its not keyed or in preserved skel...

This commit is contained in:
Will Snyder 2022-01-13 12:52:30 -08:00
parent 7244446dd9
commit c314592d48
5 changed files with 55 additions and 18 deletions

View File

@ -14,9 +14,29 @@ from .msh_model_gather import *
from .crc import to_crc from .crc import to_crc
def extract_anim(armature: bpy.types.Armature, root_name: str) -> Animation: def extract_anim(armature: bpy.types.Armature, root_name: str) -> Animation:
action = armature.animation_data.action 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(); anim = Animation();
root_crc = to_crc(root_name) 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] = ([], []) anim.bone_frames[root_crc] = ([], [])
for bone in armature.data.bones: 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): 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: for bone in armature.pose.bones:
if bone.name not in keyable_bones:
continue
transform = bone.matrix transform = bone.matrix
if bone.parent: if bone.parent:

View File

@ -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: if "box" in name or "cube" in name or "cuboid" in name:
return CollisionPrimitiveShape.BOX 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): 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 """ """ 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] = [] bones: List[Model] = []
for bone in obj.data.bones: for bone in armature.data.bones:
model = Model() model = Model()
transform = bone.matrix_local transform = bone.matrix_local
@ -382,11 +384,16 @@ def expand_armature(obj: bpy.types.Object) -> List[Model]:
if bone.parent: if bone.parent:
transform = bone.parent.matrix_local.inverted() @ transform transform = bone.parent.matrix_local.inverted() @ transform
model.parent = bone.parent.name 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: else:
model.parent = obj.parent.name for child_obj in armature.children:
for child_obj in obj.children: if child_obj.vertex_groups and not get_is_model_hidden(child_obj) and not child_obj.parent_bone:
if child_obj.vertex_groups and not get_is_model_hidden(obj) and not obj.parent_bone:
model.parent = child_obj.name model.parent = child_obj.name
break
if not model.parent and armature.parent:
model.parent = armature.parent.name
local_translation, local_rotation, _ = transform.decompose() local_translation, local_rotation, _ = transform.decompose()

View File

@ -9,7 +9,7 @@ from mathutils import Vector, Matrix
def inject_dummy_data(model : Model): 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 model.hidden = True
dummy_seg = GeometrySegment() dummy_seg = GeometrySegment()

View File

@ -30,14 +30,20 @@ def save_scene(output_file, scene: Scene):
with msh2.create_child("MODL") as modl: with msh2.create_child("MODL") as modl:
_write_modl(modl, model, index, material_index, model_index) _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: 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: with hedr.create_child("SKL2") as skl2:
_write_skl2(skl2, scene.animation) _write_skl2(skl2, scene.animation)
with hedr.create_child("BLN2") as bln2: with hedr.create_child("BLN2") as bln2:
_write_bln2(bln2, scene.animation) _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) _write_anm2(anm2, scene.animation)
with hedr.create_child("CL1L"): with hedr.create_child("CL1L"):

View File

@ -113,14 +113,7 @@ def required_skeleton_to_armature(required_skeleton : List[Model], model_map : D
armature_obj = bpy.data.objects.new("skeleton", armature) armature_obj = bpy.data.objects.new("skeleton", armature)
bpy.context.view_layer.active_layer_collection.collection.objects.link(armature_obj) 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]) bones_set = set([model.name for model in required_skeleton])
armature_obj.select_set(True) armature_obj.select_set(True)
@ -200,7 +193,7 @@ def extract_required_skeleton(scene: Scene) -> List[Model]:
model_dict[model.name] = model model_dict[model.name] = model
#if to_crc(model.name) in scene.skeleton: #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: if model.model_type == ModelType.BONE:
skeleton_hashes.add(to_crc(model.name)) 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 # Create the armature if skel is non-empty
armature = None if not skel else required_skeleton_to_armature(skel, model_map, scene) 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 If an armature was created, we need to do a few extra