|
|
|
|
@ -276,10 +276,22 @@ class LeenkxExporter:
|
|
|
|
|
if armature.animation_data:
|
|
|
|
|
action = armature.animation_data.action
|
|
|
|
|
if action:
|
|
|
|
|
return [fcurve for fcurve in action.fcurves if fcurve.data_path.startswith(path)]
|
|
|
|
|
fcurves = LeenkxExporter.get_action_fcurves(action, armature.animation_data)
|
|
|
|
|
return [fcurve for fcurve in fcurves if fcurve.data_path.startswith(path)]
|
|
|
|
|
|
|
|
|
|
return []
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def get_action_fcurves(action: bpy.types.Action, anim_data: Optional[bpy.types.AnimData] = None) -> List[bpy.types.FCurve]:
|
|
|
|
|
if bpy.app.version >= (5, 0, 0):
|
|
|
|
|
if anim_data and anim_data.action_slot:
|
|
|
|
|
from bpy_extras import anim_utils
|
|
|
|
|
channelbag = anim_utils.action_ensure_channelbag_for_slot(action, anim_data.action_slot)
|
|
|
|
|
return channelbag.fcurves if channelbag else []
|
|
|
|
|
return []
|
|
|
|
|
else:
|
|
|
|
|
return action.fcurves
|
|
|
|
|
|
|
|
|
|
def export_bone(self, armature, bone: bpy.types.Bone, o, action: bpy.types.Action):
|
|
|
|
|
rpdat = lnx.utils.get_rp()
|
|
|
|
|
bobject_ref = self.bobject_bone_array.get(bone)
|
|
|
|
|
@ -319,7 +331,7 @@ class LeenkxExporter:
|
|
|
|
|
oanim['root_motion_rot'] = action.lnx_root_motion_rot
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def calculate_anim_frame_range(action: bpy.types.Action) -> Tuple[int, int]:
|
|
|
|
|
def calculate_anim_frame_range(action: bpy.types.Action, anim_data: Optional[bpy.types.AnimData] = None) -> Tuple[int, int]:
|
|
|
|
|
"""Calculates the required frame range of the given action by
|
|
|
|
|
also taking fcurve modifiers into account.
|
|
|
|
|
|
|
|
|
|
@ -330,14 +342,16 @@ class LeenkxExporter:
|
|
|
|
|
start = frame_range[0]
|
|
|
|
|
end = frame_range[1]
|
|
|
|
|
|
|
|
|
|
fcurves = LeenkxExporter.get_action_fcurves(action, anim_data)
|
|
|
|
|
|
|
|
|
|
# Blender 4.0+ compatibility: Handle zero-length frame ranges
|
|
|
|
|
if start == end:
|
|
|
|
|
start = 1
|
|
|
|
|
end = 2
|
|
|
|
|
|
|
|
|
|
if action.fcurves:
|
|
|
|
|
if fcurves:
|
|
|
|
|
all_keyframes = []
|
|
|
|
|
for fcurve in action.fcurves:
|
|
|
|
|
for fcurve in fcurves:
|
|
|
|
|
if fcurve.keyframe_points:
|
|
|
|
|
for keyframe in fcurve.keyframe_points:
|
|
|
|
|
all_keyframes.append(keyframe.co[0])
|
|
|
|
|
@ -350,7 +364,7 @@ class LeenkxExporter:
|
|
|
|
|
|
|
|
|
|
# Take FCurve modifiers into account if they have a restricted
|
|
|
|
|
# frame range
|
|
|
|
|
for fcurve in action.fcurves:
|
|
|
|
|
for fcurve in fcurves:
|
|
|
|
|
for modifier in fcurve.modifiers:
|
|
|
|
|
if not modifier.use_restricted_range:
|
|
|
|
|
continue
|
|
|
|
|
@ -404,7 +418,7 @@ class LeenkxExporter:
|
|
|
|
|
o['object_actions'] = []
|
|
|
|
|
o['object_actions'].append('action_' + action_name + ext)
|
|
|
|
|
|
|
|
|
|
frame_range = self.calculate_anim_frame_range(action)
|
|
|
|
|
frame_range = self.calculate_anim_frame_range(action, bobject.animation_data)
|
|
|
|
|
out_anim = {
|
|
|
|
|
'begin': frame_range[0],
|
|
|
|
|
'end': frame_range[1],
|
|
|
|
|
@ -414,7 +428,8 @@ class LeenkxExporter:
|
|
|
|
|
self.export_pose_markers(out_anim, action)
|
|
|
|
|
|
|
|
|
|
unresolved_data_paths = set()
|
|
|
|
|
for fcurve in action.fcurves:
|
|
|
|
|
fcurves = self.get_action_fcurves(action, bobject.animation_data)
|
|
|
|
|
for fcurve in fcurves:
|
|
|
|
|
data_path = fcurve.data_path
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
@ -535,7 +550,7 @@ class LeenkxExporter:
|
|
|
|
|
fcurve_list = self.collect_bone_animation(armature, bone.name)
|
|
|
|
|
|
|
|
|
|
if fcurve_list and pose_bone:
|
|
|
|
|
begin_frame, end_frame = self.calculate_anim_frame_range(action)
|
|
|
|
|
begin_frame, end_frame = self.calculate_anim_frame_range(action, armature.animation_data)
|
|
|
|
|
|
|
|
|
|
out_track = {'target': "transform", 'frames': [], 'values': []}
|
|
|
|
|
o['anim'] = {'tracks': [out_track]}
|
|
|
|
|
@ -653,8 +668,8 @@ class LeenkxExporter:
|
|
|
|
|
return fov
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
def write_bone_matrices(self, scene, action):
|
|
|
|
|
begin_frame, end_frame = self.calculate_anim_frame_range(action)
|
|
|
|
|
def write_bone_matrices(self, scene, action, anim_data: Optional[bpy.types.AnimData] = None):
|
|
|
|
|
begin_frame, end_frame = self.calculate_anim_frame_range(action, anim_data)
|
|
|
|
|
if len(self.bone_tracks) > 0:
|
|
|
|
|
hidden_states = {}
|
|
|
|
|
try:
|
|
|
|
|
@ -807,7 +822,8 @@ class LeenkxExporter:
|
|
|
|
|
# if (shapeKeys.animation_data):
|
|
|
|
|
# action = shapeKeys.animation_data.action
|
|
|
|
|
# if (action):
|
|
|
|
|
# for fcurve in action.fcurves:
|
|
|
|
|
# fcurves = self.get_action_fcurves(action, shapeKeys.animation_data)
|
|
|
|
|
# for fcurve in fcurves:
|
|
|
|
|
# if ((fcurve.data_path.startswith("key_blocks[")) and (fcurve.data_path.endswith("].value"))):
|
|
|
|
|
# keyName = fcurve.data_path.strip("abcdehklopstuvy[]_.")
|
|
|
|
|
# if ((keyName[0] == "\"") or (keyName[0] == "'")):
|
|
|
|
|
@ -822,7 +838,8 @@ class LeenkxExporter:
|
|
|
|
|
# if ((not action) and (node.animation_data)):
|
|
|
|
|
# action = node.animation_data.action
|
|
|
|
|
# if (action):
|
|
|
|
|
# for fcurve in action.fcurves:
|
|
|
|
|
# fcurves = self.get_action_fcurves(action, node.animation_data)
|
|
|
|
|
# for fcurve in fcurves:
|
|
|
|
|
# if ((fcurve.data_path.startswith("data.shape_keys.key_blocks[")) and (fcurve.data_path.endswith("].value"))):
|
|
|
|
|
# keyName = fcurve.data_path.strip("abcdehklopstuvy[]_.")
|
|
|
|
|
# if ((keyName[0] == "\"") or (keyName[0] == "'")):
|
|
|
|
|
@ -1324,7 +1341,7 @@ class LeenkxExporter:
|
|
|
|
|
_bake_hidden[_obj] = False
|
|
|
|
|
_obj.hide_viewport = True
|
|
|
|
|
|
|
|
|
|
start, end = self.calculate_anim_frame_range(action)
|
|
|
|
|
start, end = self.calculate_anim_frame_range(action, skelobj.animation_data)
|
|
|
|
|
|
|
|
|
|
bake_result = bpy.ops.nla.bake(
|
|
|
|
|
frame_start=start,
|
|
|
|
|
@ -1361,7 +1378,7 @@ class LeenkxExporter:
|
|
|
|
|
boneo = {}
|
|
|
|
|
self.export_bone(skelobj, bone, boneo, action)
|
|
|
|
|
bones.append(boneo)
|
|
|
|
|
self.write_bone_matrices(bpy.context.scene, action)
|
|
|
|
|
self.write_bone_matrices(bpy.context.scene, action, skelobj.animation_data)
|
|
|
|
|
if len(bones) > 0 and 'anim' in bones[0]:
|
|
|
|
|
self.export_pose_markers(bones[0]['anim'], original_action)
|
|
|
|
|
self.export_root_motion(bones[0]['anim'], original_action)
|
|
|
|
|
|