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.
|
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):
|
def execute(self, context):
|
||||||
with open(self.filepath, 'rb') as input_file:
|
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'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
def menu_func_import(self, context):
|
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
|
action = armature.animation_data.action
|
||||||
anim = Animation();
|
anim = Animation();
|
||||||
|
|
||||||
|
root_crc = crc(root_name)
|
||||||
|
|
||||||
if not action:
|
if not action:
|
||||||
framerange = Vector((0.0,1.0))
|
framerange = Vector((0.0,1.0))
|
||||||
else:
|
else:
|
||||||
|
@ -27,9 +29,9 @@ def extract_anim(armature: bpy.types.Armature, root_name: str) -> Animation:
|
||||||
|
|
||||||
anim.end_index = num_frames - 1
|
anim.end_index = num_frames - 1
|
||||||
|
|
||||||
anim.bone_frames[root_name] = ([], [])
|
anim.bone_frames[root_crc] = ([], [])
|
||||||
for bone in armature.data.bones:
|
for bone in armature.data.bones:
|
||||||
anim.bone_frames[bone.name] = ([], [])
|
anim.bone_frames[crc(bone.name)] = ([], [])
|
||||||
|
|
||||||
for frame in range(num_frames):
|
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()))
|
rframe_dummy = RotationFrame(frame, convert_rotation_space(Quaternion()))
|
||||||
tframe_dummy = TranslationFrame(frame, Vector((0.0,0.0,0.0)))
|
tframe_dummy = TranslationFrame(frame, Vector((0.0,0.0,0.0)))
|
||||||
|
|
||||||
anim.bone_frames[root_name][0].append(tframe_dummy)
|
anim.bone_frames[root_crc][0].append(tframe_dummy)
|
||||||
anim.bone_frames[root_name][1].append(rframe_dummy)
|
anim.bone_frames[root_crc][1].append(rframe_dummy)
|
||||||
|
|
||||||
|
|
||||||
for bone in armature.pose.bones:
|
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))
|
rframe = RotationFrame(frame, convert_rotation_space(rot))
|
||||||
tframe = TranslationFrame(frame, convert_vector_space(loc))
|
tframe = TranslationFrame(frame, convert_vector_space(loc))
|
||||||
|
|
||||||
anim.bone_frames[bone.name][0].append(tframe)
|
anim.bone_frames[crc(bone.name)][0].append(tframe)
|
||||||
anim.bone_frames[bone.name][1].append(rframe)
|
anim.bone_frames[crc(bone.name)][1].append(rframe)
|
||||||
|
|
||||||
|
|
||||||
return anim
|
return anim
|
||||||
|
|
|
@ -98,7 +98,7 @@ class Animation:
|
||||||
""" Class representing 'CYCL' + 'KFR3' sections in a .msh file """
|
""" Class representing 'CYCL' + 'KFR3' sections in a .msh file """
|
||||||
|
|
||||||
name: str = "fullanimation"
|
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
|
framerate: float = 29.97
|
||||||
start_index : int = 0
|
start_index : int = 0
|
||||||
|
|
|
@ -84,6 +84,14 @@ class Reader:
|
||||||
return result[0] if num == 1 else result
|
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):
|
def read_child(self):
|
||||||
child = Reader(self.file, parent=self, indent=int(len(self.indent) / 2) + 1, debug=self.debug)
|
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 = {}
|
mndx_remap = {}
|
||||||
|
|
||||||
|
|
||||||
def read_scene(input_file) -> Scene:
|
def read_scene(input_file, anim_only=False) -> Scene:
|
||||||
|
|
||||||
scene = Scene()
|
scene = Scene()
|
||||||
scene.models = []
|
scene.models = []
|
||||||
|
@ -37,29 +37,30 @@ def read_scene(input_file) -> Scene:
|
||||||
|
|
||||||
with hedr.read_child() as msh2:
|
with hedr.read_child() as msh2:
|
||||||
|
|
||||||
materials_list = []
|
if not anim_only:
|
||||||
|
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:
|
if "SINF" in next_header:
|
||||||
with msh2.read_child() as sinf:
|
with msh2.read_child() as sinf:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
elif "MATL" in next_header:
|
elif "MATL" in next_header:
|
||||||
with msh2.read_child() as matl:
|
with msh2.read_child() as matl:
|
||||||
materials_list += _read_matl_and_get_materials_list(matl)
|
materials_list += _read_matl_and_get_materials_list(matl)
|
||||||
for i,mat in enumerate(materials_list):
|
for i,mat in enumerate(materials_list):
|
||||||
scene.materials[mat.name] = mat
|
scene.materials[mat.name] = mat
|
||||||
|
|
||||||
elif "MODL" in next_header:
|
elif "MODL" in next_header:
|
||||||
while ("MODL" in msh2.peak_next_header()):
|
while ("MODL" in msh2.peak_next_header()):
|
||||||
with msh2.read_child() as modl:
|
with msh2.read_child() as modl:
|
||||||
scene.models.append(_read_modl(modl, materials_list))
|
scene.models.append(_read_modl(modl, materials_list))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
msh2.skip_bytes(1)
|
msh2.skip_bytes(1)
|
||||||
|
|
||||||
elif "SKL2" in next_header:
|
elif "SKL2" in next_header:
|
||||||
with hedr.read_child() as skl2:
|
with hedr.read_child() as skl2:
|
||||||
|
@ -68,7 +69,7 @@ def read_scene(input_file) -> Scene:
|
||||||
|
|
||||||
elif "ANM2" in next_header:
|
elif "ANM2" in next_header:
|
||||||
with hedr.read_child() as anm2:
|
with hedr.read_child() as anm2:
|
||||||
_read_anm2(anm2, scene.models)
|
scene.animation = _read_anm2(anm2)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
hedr.skip_bytes(1)
|
hedr.skip_bytes(1)
|
||||||
|
@ -250,9 +251,8 @@ def _read_tran(tran: Reader) -> ModelTransform:
|
||||||
|
|
||||||
tran.skip_bytes(12) #ignore scale
|
tran.skip_bytes(12) #ignore scale
|
||||||
|
|
||||||
rot = tran.read_f32(4)
|
xform.rotation = tran.read_quat()
|
||||||
xform.rotation = Quaternion((rot[3], rot[0], rot[1], rot[2]))
|
xform.translation = tran.read_vec()
|
||||||
xform.translation = Vector(tran.read_f32(3))
|
|
||||||
|
|
||||||
print(tran.indent + "Rot: {} Loc: {}".format(str(xform.rotation), str(xform.translation)))
|
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 = {}
|
anim = Animation()
|
||||||
for model in models:
|
|
||||||
hash_dict[crc(model.name)] = model.name
|
|
||||||
|
|
||||||
while anm2.could_have_child():
|
while anm2.could_have_child():
|
||||||
|
|
||||||
|
@ -402,14 +400,26 @@ def _read_anm2(anm2: Reader, models):
|
||||||
|
|
||||||
for _ in range(num_bones):
|
for _ in range(num_bones):
|
||||||
|
|
||||||
kfr3.read_u32()
|
bone_crc = kfr3.read_u32()
|
||||||
|
|
||||||
|
frames = ([],[])
|
||||||
|
|
||||||
frametype = kfr3.read_u32()
|
frametype = kfr3.read_u32()
|
||||||
|
|
||||||
num_loc_frames = kfr3.read_u32()
|
num_loc_frames = kfr3.read_u32()
|
||||||
num_rot_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()
|
bones = anim.bone_frames.keys()
|
||||||
bln2.write_u32(len(bones))
|
bln2.write_u32(len(bones))
|
||||||
|
|
||||||
for boneName in bones:
|
for bone_crc in bones:
|
||||||
bln2.write_u32(crc(boneName), 0)
|
bln2.write_u32(bone_crc, 0)
|
||||||
|
|
||||||
def _write_skl2(skl2: Writer, anim: Animation):
|
def _write_skl2(skl2: Writer, anim: Animation):
|
||||||
bones = anim.bone_frames.keys()
|
bones = anim.bone_frames.keys()
|
||||||
skl2.write_u32(len(bones))
|
skl2.write_u32(len(bones))
|
||||||
|
|
||||||
for boneName in bones:
|
for bone_crc in bones:
|
||||||
skl2.write_u32(crc(boneName), 0) #default values from docs
|
skl2.write_u32(bone_crc, 0) #default values from docs
|
||||||
skl2.write_f32(1.0, 0.0, 0.0)
|
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))
|
kfr3.write_u32(len(anim.bone_frames))
|
||||||
|
|
||||||
for boneName in anim.bone_frames:
|
for bone_crc in anim.bone_frames:
|
||||||
kfr3.write_u32(crc(boneName))
|
kfr3.write_u32(bone_crc)
|
||||||
kfr3.write_u32(0) #what is keyframe type?
|
kfr3.write_u32(0) #what is keyframe type?
|
||||||
|
|
||||||
translation_frames, rotation_frames = anim.bone_frames[boneName]
|
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):
|
def parent_object_to_bone(obj, armature, bone_name):
|
||||||
|
|
||||||
bpy.ops.object.select_all(action='DESELECT')
|
worldmat = obj.matrix_world
|
||||||
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')
|
|
||||||
|
|
||||||
|
obj.parent = None
|
||||||
|
obj.parent = armature
|
||||||
|
obj.parent_type = 'BONE'
|
||||||
|
obj.parent_bone = bone_name
|
||||||
|
|
||||||
bpy.ops.object.select_all(action='DESELECT')
|
obj.matrix_basis = Matrix()
|
||||||
bpy.context.view_layer.objects.active = None
|
obj.matrix_parent_inverse = Matrix()
|
||||||
|
|
||||||
|
obj.matrix_world = worldmat
|
||||||
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')
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue