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:
parent
7cfa101d42
commit
5692a60907
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue