Anim: Add "replace" mix mode to the Action Constraint
The available mix modes on the Action Constraint only allowed *combining* the Action's transforms with the input transforms, but unlike most other constraints lacked a way to completely override/replace those transforms. This PR adds a "Replace" mix mode to the Action Constraint, bringing it in line with most of the other constraints already in Blender.  ---- Test file: [action_constraint_replace_mode.blend](/attachments/fc3417a8-b60a-4212-9840-5b59191e9ed9) - The small bone at the top is the action constraint target (translating it right-left triggers the action constraint). - Both two-bone chains are set up with action constraints. The base bones of each chain additionally have a copy location constraint to the small sideways bone, placed before the action constraint in their constraint stack. - The chain on the left has the default mix mode, which allows you to manipulate the bones on top of what the action constraint does, and allows the copy location constraint on the base bone to work. - The bones on the right have the new "Replace" mix mode, and therefore manipulating them does not affect the final constrained transformation, and the copy location on the base bone is overridden by the action constraint. Pull Request: https://projects.blender.org/blender/blender/pulls/138316
This commit is contained in:
committed by
Nathan Vegdahl
parent
e4e49e1634
commit
8a984f4f4e
@@ -460,6 +460,47 @@ class ActionConstraintTest(AbstractConstraintTests):
|
||||
con.action_slot,
|
||||
"Assigning an Action with a virgin slot should automatically select that slot")
|
||||
|
||||
def test_mix_modes(self):
|
||||
owner = bpy.context.scene.objects["Action.owner"]
|
||||
target = bpy.context.scene.objects["Action.target"]
|
||||
|
||||
action = bpy.data.actions.new("Slotted")
|
||||
slot = action.slots.new('OBJECT', "Slot")
|
||||
layer = action.layers.new(name="Layer")
|
||||
strip = layer.strips.new(type='KEYFRAME')
|
||||
strip.key_insert(slot, "location", 0, 2.0, 0.0)
|
||||
strip.key_insert(slot, "location", 0, 7.0, 10.0)
|
||||
|
||||
con = owner.constraints["Action"]
|
||||
con.action = action
|
||||
con.action_slot = slot
|
||||
con.transform_channel = 'LOCATION_X'
|
||||
con.min = -1.0
|
||||
con.max = 1.0
|
||||
con.frame_start = 0
|
||||
con.frame_end = 10
|
||||
|
||||
# Set the constrained object's location to something other than [0,0,0],
|
||||
# so we can verify that it's actually replaced/mixed as appropriate to
|
||||
# the mix mode.
|
||||
owner.location = (2.0, 3.0, 4.0)
|
||||
|
||||
con.mix_mode = 'REPLACE'
|
||||
self.matrix_test("Action.owner", Matrix((
|
||||
(1.0, 0.0, 0.0, 4.5),
|
||||
(0.0, 1.0, 0.0, 0.0),
|
||||
(0.0, 0.0, 1.0, 0.0),
|
||||
(0.0, 0.0, 0.0, 1.0)
|
||||
)))
|
||||
|
||||
con.mix_mode = 'BEFORE_SPLIT'
|
||||
self.matrix_test("Action.owner", Matrix((
|
||||
(1.0, 0.0, 0.0, 6.5),
|
||||
(0.0, 1.0, 0.0, 3.0),
|
||||
(0.0, 0.0, 1.0, 4.0),
|
||||
(0.0, 0.0, 0.0, 1.0)
|
||||
)))
|
||||
|
||||
|
||||
def main():
|
||||
global args
|
||||
|
||||
Reference in New Issue
Block a user