Animation: Add channel type options to the Bake Action operator #110903
|
@ -124,7 +124,11 @@ def bake_action_iter(
|
|||
do_visual_keying=True,
|
||||
do_constraint_clear=False,
|
||||
do_parents_clear=False,
|
||||
do_clean=False
|
||||
do_clean=False,
|
||||
do_location=True,
|
||||
do_rotation=True,
|
||||
do_scale=True,
|
||||
do_bbone=True
|
||||
):
|
||||
"""
|
||||
An coroutine that bakes action for a single object.
|
||||
|
@ -148,6 +152,14 @@ def bake_action_iter(
|
|||
:type do_parents_clear: bool
|
||||
:arg do_clean: Remove redundant keyframes after baking.
|
||||
:type do_clean: bool
|
||||
:arg do_location: Bake location channels.
|
||||
:type do_location: bool
|
||||
:arg do_rotation: Bake rotation channels.
|
||||
:type do_rotation: bool
|
||||
:arg do_scale: Bake scale channels.
|
||||
:type do_scale: bool
|
||||
:arg do_bbone: Bake b-bone channels.
|
||||
:type do_bbone: bool
|
||||
|
||||
:return: an action or None
|
||||
:rtype: :class:`bpy.types.Action`
|
||||
|
@ -306,7 +318,16 @@ def bake_action_iter(
|
|||
keyframes.add_paths(path_euler, 3)
|
||||
keyframes.add_paths(path_scale, 3)
|
||||
|
||||
if pbone.bone.bbone_segments > 1:
|
||||
if do_location:
|
||||
keyframes.add_paths(path_location, 3)
|
||||
if do_rotation:
|
||||
keyframes.add_paths(path_quaternion, 4)
|
||||
keyframes.add_paths(path_axis_angle, 4)
|
||||
keyframes.add_paths(path_euler, 3)
|
||||
if do_scale:
|
||||
keyframes.add_paths(path_scale, 3)
|
||||
|
||||
|
||||
if do_bbone and pbone.bone.bbone_segments > 1:
|
||||
for prop_name, path in zip(BBONE_PROPS, paths_bbprops):
|
||||
keyframes.add_paths(path, BBONE_PROPS_LENGTHS[prop_name])
|
||||
|
||||
|
@ -315,32 +336,35 @@ def bake_action_iter(
|
|||
for (f, matrix, bbones) in pose_info:
|
||||
pbone.matrix_basis = matrix[name].copy()
|
||||
|
||||
keyframes.extend_co_values(path_location, 3, f, pbone.location)
|
||||
if do_location:
|
||||
keyframes.extend_co_values(path_location, 3, f, pbone.location)
|
||||
|
||||
if rotation_mode == 'QUATERNION':
|
||||
if quat_prev is not None:
|
||||
quat = pbone.rotation_quaternion.copy()
|
||||
quat.make_compatible(quat_prev)
|
||||
pbone.rotation_quaternion = quat
|
||||
quat_prev = quat
|
||||
del quat
|
||||
else:
|
||||
quat_prev = pbone.rotation_quaternion.copy()
|
||||
keyframes.extend_co_values(path_quaternion, 4, f, pbone.rotation_quaternion)
|
||||
elif rotation_mode == 'AXIS_ANGLE':
|
||||
keyframes.extend_co_values(path_axis_angle, 4, f, pbone.rotation_axis_angle)
|
||||
else: # euler, XYZ, ZXY etc
|
||||
if euler_prev is not None:
|
||||
euler = pbone.matrix_basis.to_euler(pbone.rotation_mode, euler_prev)
|
||||
pbone.rotation_euler = euler
|
||||
del euler
|
||||
euler_prev = pbone.rotation_euler.copy()
|
||||
keyframes.extend_co_values(path_euler, 3, f, pbone.rotation_euler)
|
||||
if do_rotation:
|
||||
if rotation_mode == 'QUATERNION':
|
||||
if quat_prev is not None:
|
||||
quat = pbone.rotation_quaternion.copy()
|
||||
quat.make_compatible(quat_prev)
|
||||
pbone.rotation_quaternion = quat
|
||||
quat_prev = quat
|
||||
del quat
|
||||
else:
|
||||
quat_prev = pbone.rotation_quaternion.copy()
|
||||
keyframes.extend_co_values(path_quaternion, 4, f, pbone.rotation_quaternion)
|
||||
elif rotation_mode == 'AXIS_ANGLE':
|
||||
keyframes.extend_co_values(path_axis_angle, 4, f, pbone.rotation_axis_angle)
|
||||
else: # euler, XYZ, ZXY etc
|
||||
if euler_prev is not None:
|
||||
euler = pbone.matrix_basis.to_euler(pbone.rotation_mode, euler_prev)
|
||||
pbone.rotation_euler = euler
|
||||
del euler
|
||||
euler_prev = pbone.rotation_euler.copy()
|
||||
keyframes.extend_co_values(path_euler, 3, f, pbone.rotation_euler)
|
||||
|
||||
keyframes.extend_co_values(path_scale, 3, f, pbone.scale)
|
||||
if do_scale:
|
||||
keyframes.extend_co_values(path_scale, 3, f, pbone.scale)
|
||||
|
||||
# Bendy Bones
|
||||
if pbone.bone.bbone_segments > 1:
|
||||
if do_bbone and pbone.bone.bbone_segments > 1:
|
||||
bbone_shape = bbones[name]
|
||||
for prop_index, prop_name in enumerate(BBONE_PROPS):
|
||||
prop_len = BBONE_PROPS_LENGTHS[prop_name]
|
||||
|
@ -375,11 +399,14 @@ def bake_action_iter(
|
|||
path_scale = "scale"
|
||||
|
||||
keyframes = KeyframesCo()
|
||||
keyframes.add_paths(path_location, 3)
|
||||
keyframes.add_paths(path_quaternion, 4)
|
||||
keyframes.add_paths(path_axis_angle, 4)
|
||||
keyframes.add_paths(path_euler, 3)
|
||||
keyframes.add_paths(path_scale, 3)
|
||||
if do_location:
|
||||
keyframes.add_paths(path_location, 3)
|
||||
if do_rotation:
|
||||
keyframes.add_paths(path_quaternion, 4)
|
||||
keyframes.add_paths(path_axis_angle, 4)
|
||||
keyframes.add_paths(path_euler, 3)
|
||||
if do_scale:
|
||||
keyframes.add_paths(path_scale, 3)
|
||||
|
||||
rotation_mode = obj.rotation_mode
|
||||
total_new_keys = len(obj_info)
|
||||
|
@ -387,28 +414,31 @@ def bake_action_iter(
|
|||
name = "Action Bake" # XXX: placeholder
|
||||
obj.matrix_basis = matrix
|
||||
|
||||
keyframes.extend_co_values(path_location, 3, f, obj.location)
|
||||
if do_location:
|
||||
keyframes.extend_co_values(path_location, 3, f, obj.location)
|
||||
|
||||
if rotation_mode == 'QUATERNION':
|
||||
if quat_prev is not None:
|
||||
quat = obj.rotation_quaternion.copy()
|
||||
quat.make_compatible(quat_prev)
|
||||
obj.rotation_quaternion = quat
|
||||
quat_prev = quat
|
||||
del quat
|
||||
else:
|
||||
quat_prev = obj.rotation_quaternion.copy()
|
||||
keyframes.extend_co_values(path_quaternion, 4, f, obj.rotation_quaternion)
|
||||
if do_rotation:
|
||||
if rotation_mode == 'QUATERNION':
|
||||
if quat_prev is not None:
|
||||
quat = obj.rotation_quaternion.copy()
|
||||
quat.make_compatible(quat_prev)
|
||||
obj.rotation_quaternion = quat
|
||||
quat_prev = quat
|
||||
del quat
|
||||
else:
|
||||
quat_prev = obj.rotation_quaternion.copy()
|
||||
keyframes.extend_co_values(path_quaternion, 4, f, obj.rotation_quaternion)
|
||||
|
||||
elif rotation_mode == 'AXIS_ANGLE':
|
||||
keyframes.extend_co_values(path_axis_angle, 4, f, obj.rotation_axis_angle)
|
||||
else: # euler, XYZ, ZXY etc
|
||||
if euler_prev is not None:
|
||||
obj.rotation_euler = matrix.to_euler(obj.rotation_mode, euler_prev)
|
||||
euler_prev = obj.rotation_euler.copy()
|
||||
keyframes.extend_co_values(path_euler, 3, f, obj.rotation_euler)
|
||||
elif rotation_mode == 'AXIS_ANGLE':
|
||||
keyframes.extend_co_values(path_axis_angle, 4, f, obj.rotation_axis_angle)
|
||||
else: # euler, XYZ, ZXY etc
|
||||
if euler_prev is not None:
|
||||
obj.rotation_euler = matrix.to_euler(obj.rotation_mode, euler_prev)
|
||||
euler_prev = obj.rotation_euler.copy()
|
||||
keyframes.extend_co_values(path_euler, 3, f, obj.rotation_euler)
|
||||
|
||||
keyframes.extend_co_values(path_scale, 3, f, obj.scale)
|
||||
if do_scale:
|
||||
keyframes.extend_co_values(path_scale, 3, f, obj.scale)
|
||||
|
||||
if is_new_action:
|
||||
keyframes.insert_keyframes_into_new_action(total_new_keys, action, name)
|
||||
|
|
|
@ -252,11 +252,27 @@ class NLA_OT_bake(Operator):
|
|||
),
|
||||
default={'POSE'},
|
||||
)
|
||||
channel_types: EnumProperty(
|
||||
name="Channels",
|
||||
description="Which channels to bake",
|
||||
options={'ENUM_FLAG'},
|
||||
items=(
|
||||
('LOCATION', "Location", "Bake location channels"),
|
||||
('ROTATION', "Rotation", "Bake rotation channels"),
|
||||
('SCALE', "Scale", "Bake scale channels"),
|
||||
('BBONE', "B-Bone", "Bake b-bone channels"),
|
||||
),
|
||||
default={'LOCATION', 'ROTATION', 'SCALE', 'BBONE'},
|
||||
)
|
||||
|
||||
def execute(self, context):
|
||||
from bpy_extras import anim_utils
|
||||
do_pose = 'POSE' in self.bake_types
|
||||
do_object = 'OBJECT' in self.bake_types
|
||||
do_location = 'LOCATION' in self.channel_types
|
||||
do_rotation = 'ROTATION' in self.channel_types
|
||||
do_scale = 'SCALE' in self.channel_types
|
||||
do_bbone = 'BBONE' in self.channel_types
|
||||
|
||||
if do_pose and self.only_selected:
|
||||
pose_bones = context.selected_pose_bones or []
|
||||
|
@ -283,6 +299,10 @@ class NLA_OT_bake(Operator):
|
|||
do_constraint_clear=self.clear_constraints,
|
||||
do_parents_clear=self.clear_parents,
|
||||
do_clean=self.clean_curves,
|
||||
do_location=do_location,
|
||||
do_rotation=do_rotation,
|
||||
do_scale=do_scale,
|
||||
do_bbone=do_bbone,
|
||||
)
|
||||
|
||||
if not any(actions):
|
||||
|
|
Loading…
Reference in New Issue
It looks like all of these
keyframes.add_paths(...)
in the conditionals are already run unconditionally on lines 314-319. Were those lines meant to be removed?