Bone parenting fixed, anm2 reading, menu option for anim import
This commit is contained in:
parent
30bf326b9e
commit
c0c978af8b
@ -151,9 +151,22 @@ class ImportMSH(Operator, ImportHelper):
|
||||
maxlen=255, # Max internal buffer length, longer would be clamped.
|
||||
)
|
||||
|
||||
animation_only: BoolProperty(
|
||||
name="Import Animation Only",
|
||||
description="Import animation and append as a new action to currently selected armature.",
|
||||
default=False
|
||||
)
|
||||
|
||||
|
||||
def execute(self, context):
|
||||
with open(self.filepath, 'rb') as input_file:
|
||||
extract_scene(self.filepath, read_scene(input_file))
|
||||
scene = read_scene(input_file, self.animation_only)
|
||||
|
||||
if not self.animation_only:
|
||||
extract_scene(self.filepath, scene)
|
||||
else:
|
||||
extract_and_apply_anim(self.filepath, scene)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
def menu_func_import(self, context):
|
||||
|
@ -17,6 +17,8 @@ def extract_anim(armature: bpy.types.Armature, root_name: str) -> Animation:
|
||||
action = armature.animation_data.action
|
||||
anim = Animation();
|
||||
|
||||
root_crc = crc(root_name)
|
||||
|
||||
if not action:
|
||||
framerange = Vector((0.0,1.0))
|
||||
else:
|
||||
@ -27,9 +29,9 @@ def extract_anim(armature: bpy.types.Armature, root_name: str) -> Animation:
|
||||
|
||||
anim.end_index = num_frames - 1
|
||||
|
||||
anim.bone_frames[root_name] = ([], [])
|
||||
anim.bone_frames[root_crc] = ([], [])
|
||||
for bone in armature.data.bones:
|
||||
anim.bone_frames[bone.name] = ([], [])
|
||||
anim.bone_frames[crc(bone.name)] = ([], [])
|
||||
|
||||
for frame in range(num_frames):
|
||||
|
||||
@ -40,8 +42,8 @@ def extract_anim(armature: bpy.types.Armature, root_name: str) -> Animation:
|
||||
rframe_dummy = RotationFrame(frame, convert_rotation_space(Quaternion()))
|
||||
tframe_dummy = TranslationFrame(frame, Vector((0.0,0.0,0.0)))
|
||||
|
||||
anim.bone_frames[root_name][0].append(tframe_dummy)
|
||||
anim.bone_frames[root_name][1].append(rframe_dummy)
|
||||
anim.bone_frames[root_crc][0].append(tframe_dummy)
|
||||
anim.bone_frames[root_crc][1].append(rframe_dummy)
|
||||
|
||||
|
||||
for bone in armature.pose.bones:
|
||||
@ -56,8 +58,8 @@ def extract_anim(armature: bpy.types.Armature, root_name: str) -> Animation:
|
||||
rframe = RotationFrame(frame, convert_rotation_space(rot))
|
||||
tframe = TranslationFrame(frame, convert_vector_space(loc))
|
||||
|
||||
anim.bone_frames[bone.name][0].append(tframe)
|
||||
anim.bone_frames[bone.name][1].append(rframe)
|
||||
anim.bone_frames[crc(bone.name)][0].append(tframe)
|
||||
anim.bone_frames[crc(bone.name)][1].append(rframe)
|
||||
|
||||
|
||||
return anim
|
||||
|
@ -98,7 +98,7 @@ class Animation:
|
||||
""" Class representing 'CYCL' + 'KFR3' sections in a .msh file """
|
||||
|
||||
name: str = "fullanimation"
|
||||
bone_frames: Dict[str, Tuple[List[TranslationFrame], List[RotationFrame]]] = field(default_factory=dict)
|
||||
bone_frames: Dict[int, Tuple[List[TranslationFrame], List[RotationFrame]]] = field(default_factory=dict)
|
||||
|
||||
framerate: float = 29.97
|
||||
start_index : int = 0
|
||||
|
@ -84,6 +84,14 @@ class Reader:
|
||||
return result[0] if num == 1 else result
|
||||
|
||||
|
||||
def read_quat(self):
|
||||
rot = self.read_f32(4)
|
||||
return Quaternion((rot[3], rot[0], rot[1], rot[2]))
|
||||
|
||||
def read_vec(self):
|
||||
return Vector(self.read_f32(3))
|
||||
|
||||
|
||||
|
||||
def read_child(self):
|
||||
child = Reader(self.file, parent=self, indent=int(len(self.indent) / 2) + 1, debug=self.debug)
|
||||
|
@ -15,7 +15,7 @@ model_counter = 0
|
||||
mndx_remap = {}
|
||||
|
||||
|
||||
def read_scene(input_file) -> Scene:
|
||||
def read_scene(input_file, anim_only=False) -> Scene:
|
||||
|
||||
scene = Scene()
|
||||
scene.models = []
|
||||
@ -36,30 +36,31 @@ def read_scene(input_file) -> Scene:
|
||||
if "MSH2" in next_header:
|
||||
|
||||
with hedr.read_child() as msh2:
|
||||
|
||||
if not anim_only:
|
||||
materials_list = []
|
||||
|
||||
materials_list = []
|
||||
while (msh2.could_have_child()):
|
||||
|
||||
while (msh2.could_have_child()):
|
||||
next_header = msh2.peak_next_header()
|
||||
|
||||
next_header = msh2.peak_next_header()
|
||||
if "SINF" in next_header:
|
||||
with msh2.read_child() as sinf:
|
||||
pass
|
||||
|
||||
if "SINF" in next_header:
|
||||
with msh2.read_child() as sinf:
|
||||
pass
|
||||
elif "MATL" in next_header:
|
||||
with msh2.read_child() as matl:
|
||||
materials_list += _read_matl_and_get_materials_list(matl)
|
||||
for i,mat in enumerate(materials_list):
|
||||
scene.materials[mat.name] = mat
|
||||
|
||||
elif "MATL" in next_header:
|
||||
with msh2.read_child() as matl:
|
||||
materials_list += _read_matl_and_get_materials_list(matl)
|
||||
for i,mat in enumerate(materials_list):
|
||||
scene.materials[mat.name] = mat
|
||||
elif "MODL" in next_header:
|
||||
while ("MODL" in msh2.peak_next_header()):
|
||||
with msh2.read_child() as modl:
|
||||
scene.models.append(_read_modl(modl, materials_list))
|
||||
|
||||
elif "MODL" in next_header:
|
||||
while ("MODL" in msh2.peak_next_header()):
|
||||
with msh2.read_child() as modl:
|
||||
scene.models.append(_read_modl(modl, materials_list))
|
||||
|
||||
else:
|
||||
msh2.skip_bytes(1)
|
||||
else:
|
||||
msh2.skip_bytes(1)
|
||||
|
||||
elif "SKL2" in next_header:
|
||||
with hedr.read_child() as skl2:
|
||||
@ -68,7 +69,7 @@ def read_scene(input_file) -> Scene:
|
||||
|
||||
elif "ANM2" in next_header:
|
||||
with hedr.read_child() as anm2:
|
||||
_read_anm2(anm2, scene.models)
|
||||
scene.animation = _read_anm2(anm2)
|
||||
|
||||
else:
|
||||
hedr.skip_bytes(1)
|
||||
@ -250,9 +251,8 @@ def _read_tran(tran: Reader) -> ModelTransform:
|
||||
|
||||
tran.skip_bytes(12) #ignore scale
|
||||
|
||||
rot = tran.read_f32(4)
|
||||
xform.rotation = Quaternion((rot[3], rot[0], rot[1], rot[2]))
|
||||
xform.translation = Vector(tran.read_f32(3))
|
||||
xform.rotation = tran.read_quat()
|
||||
xform.translation = tran.read_vec()
|
||||
|
||||
print(tran.indent + "Rot: {} Loc: {}".format(str(xform.rotation), str(xform.translation)))
|
||||
|
||||
@ -381,11 +381,9 @@ def _read_segm(segm: Reader, materials_list: List[Material]) -> GeometrySegment:
|
||||
|
||||
|
||||
|
||||
def _read_anm2(anm2: Reader, models):
|
||||
def _read_anm2(anm2: Reader) -> Animation:
|
||||
|
||||
hash_dict = {}
|
||||
for model in models:
|
||||
hash_dict[crc(model.name)] = model.name
|
||||
anim = Animation()
|
||||
|
||||
while anm2.could_have_child():
|
||||
|
||||
@ -402,14 +400,26 @@ def _read_anm2(anm2: Reader, models):
|
||||
|
||||
for _ in range(num_bones):
|
||||
|
||||
kfr3.read_u32()
|
||||
bone_crc = kfr3.read_u32()
|
||||
|
||||
frames = ([],[])
|
||||
|
||||
frametype = kfr3.read_u32()
|
||||
|
||||
num_loc_frames = kfr3.read_u32()
|
||||
num_rot_frames = kfr3.read_u32()
|
||||
|
||||
kfr3.skip_bytes(16 * num_loc_frames + 20 * num_rot_frames)
|
||||
for i in range(num_loc_frames):
|
||||
frames[0].append(TranslationFrame(kfr3.read_u32(), kfr3.read_vec()))
|
||||
|
||||
for i in range(num_rot_frames):
|
||||
frames[1].append(RotationFrame(kfr3.read_u32(), kfr3.read_quat()))
|
||||
|
||||
anim.bone_frames[bone_crc] = frames
|
||||
else:
|
||||
anm2.skip_bytes(1)
|
||||
|
||||
return anim
|
||||
|
||||
|
||||
|
||||
|
@ -251,15 +251,15 @@ def _write_bln2(bln2: Writer, anim: Animation):
|
||||
bones = anim.bone_frames.keys()
|
||||
bln2.write_u32(len(bones))
|
||||
|
||||
for boneName in bones:
|
||||
bln2.write_u32(crc(boneName), 0)
|
||||
for bone_crc in bones:
|
||||
bln2.write_u32(bone_crc, 0)
|
||||
|
||||
def _write_skl2(skl2: Writer, anim: Animation):
|
||||
bones = anim.bone_frames.keys()
|
||||
skl2.write_u32(len(bones))
|
||||
|
||||
for boneName in bones:
|
||||
skl2.write_u32(crc(boneName), 0) #default values from docs
|
||||
for bone_crc in bones:
|
||||
skl2.write_u32(bone_crc, 0) #default values from docs
|
||||
skl2.write_f32(1.0, 0.0, 0.0)
|
||||
|
||||
'''
|
||||
@ -284,8 +284,8 @@ def _write_anm2(anm2: Writer, anim: Animation):
|
||||
|
||||
kfr3.write_u32(len(anim.bone_frames))
|
||||
|
||||
for boneName in anim.bone_frames:
|
||||
kfr3.write_u32(crc(boneName))
|
||||
for bone_crc in anim.bone_frames:
|
||||
kfr3.write_u32(bone_crc)
|
||||
kfr3.write_u32(0) #what is keyframe type?
|
||||
|
||||
translation_frames, rotation_frames = anim.bone_frames[boneName]
|
||||
|
@ -18,44 +18,25 @@ import os
|
||||
|
||||
|
||||
|
||||
#def import_anim(scene : Scene):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def parent_object_to_bone(obj, armature, bone_name):
|
||||
|
||||
bpy.ops.object.select_all(action='DESELECT')
|
||||
armature.select_set(True)
|
||||
bpy.context.view_layer.objects.active = armature
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
armature.data.edit_bones.active = armature.data.edit_bones[bone_name]
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
worldmat = obj.matrix_world
|
||||
|
||||
obj.parent = None
|
||||
obj.parent = armature
|
||||
obj.parent_type = 'BONE'
|
||||
obj.parent_bone = bone_name
|
||||
|
||||
bpy.ops.object.select_all(action='DESELECT')
|
||||
bpy.context.view_layer.objects.active = None
|
||||
obj.matrix_basis = Matrix()
|
||||
obj.matrix_parent_inverse = Matrix()
|
||||
|
||||
|
||||
obj.select_set(True)
|
||||
bpy.context.view_layer.objects.active = obj
|
||||
|
||||
bpy.ops.object.parent_clear(type="CLEAR_KEEP_TRANSFORM")
|
||||
bpy.context.view_layer.objects.active = None
|
||||
|
||||
|
||||
obj.select_set(True)
|
||||
armature.select_set(True)
|
||||
bpy.context.view_layer.objects.active = armature
|
||||
|
||||
bpy.ops.object.mode_set(mode='POSE')
|
||||
|
||||
armature.pose.bones[bone_name].bone.select = True
|
||||
|
||||
bpy.ops.object.parent_set(type="BONE")
|
||||
armature.pose.bones[bone_name].bone.select = False
|
||||
|
||||
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
bpy.ops.object.select_all(action='DESELECT')
|
||||
obj.matrix_world = worldmat
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user