Anim: Graph Editor - automatically lock key translation to a single axis

When moving keys in the Graph Editor animators
usually only want to move them on one axis.
While this is possible in a few ways (G+X, or G + Middle Mouse Button click),
we could default the behavior to always lock on an axis.
This was suggested by Dreamworks animators during the
Animation & Rigging module meeting.
https://devtalk.blender.org/t/2024-01-26-animation-rigging-module-meeting/33081#patch-review-decision-time-5

This PR adds an option with which the movement is
always locked to a single axis by default.
The option can be found in the Graph Editor under "View->Auto-Lock Axis".

The movement will then be restricted to the axis along
which you've moved the cursor the most.
You can still manually override the lock behavior by pressing `X` or `Y`.

I am piggybacking off the auto locking feature you get when pressing the middle mouse button.
When the new feature is enabled I call that at the start of the transformation.
Except when:
* only handles are selected
* the tweak mode has been started on a handle

This is to not snap handles, which is a behavior that has
been requested by the artists.

Pull Request: https://projects.blender.org/blender/blender/pulls/117669
This commit is contained in:
Christoph Lendenfeld 2024-02-06 23:31:09 +01:00 committed by Christoph Lendenfeld
parent 79f84775f2
commit 446b92d2ce
4 changed files with 36 additions and 2 deletions

@ -159,6 +159,7 @@ class GRAPH_MT_view(Menu):
layout.prop(st, "use_realtime_update")
layout.prop(st, "show_sliders")
layout.prop(st, "use_auto_merge_keyframes")
layout.prop(st, "autolock_translation_axis")
layout.separator()
if st.mode != 'DRIVERS':

@ -27,6 +27,7 @@
#include "UI_view2d.hh"
#include "transform.hh"
#include "transform_constraints.hh"
#include "transform_convert.hh"
#include "transform_mode.hh"
#include "transform_snap.hh"
@ -145,6 +146,24 @@ static bool graph_edit_use_local_center(TransInfo *t)
return ((t->around == V3D_AROUND_LOCAL_ORIGINS) && (graph_edit_is_translation_mode(t) == false));
}
static void enable_autolock(TransInfo *t, SpaceGraph *space_graph)
{
/* Locking the axis makes most sense for translation. We may want to enable it for scaling as
* well if artists require that. */
if (t->mode != TFM_TRANSLATION) {
return;
}
/* These flags are set when using tweak mode on handles. */
if ((space_graph->runtime.flag & SIPO_RUNTIME_FLAG_TWEAK_HANDLES_LEFT) ||
(space_graph->runtime.flag & SIPO_RUNTIME_FLAG_TWEAK_HANDLES_RIGHT))
{
return;
}
initSelectConstraint(t);
}
/**
* Get the effective selection of a triple for transform, i.e. return if the left handle, right
* handle and/or the center point should be affected by transform.
@ -367,6 +386,8 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
}
}
bool at_least_one_key_selected = false;
/* loop 2: build transdata arrays */
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
@ -405,7 +426,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
TransDataCurveHandleFlags *hdata = nullptr;
graph_bezt_get_transform_selection(t, bezt, use_handle, &sel_left, &sel_key, &sel_right);
at_least_one_key_selected |= sel_key;
if (is_prop_edit) {
bool is_sel = (sel_key || sel_left || sel_right);
/* we always select all handles for proportional editing if central handle is selected */
@ -616,6 +637,10 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
}
}
if (sipo->flag & SIPO_AUTOLOCK_AXIS && at_least_one_key_selected) {
enable_autolock(t, sipo);
}
/* cleanup temp list */
ANIM_animdata_freelist(&anim_data);
}

@ -509,7 +509,8 @@ typedef enum eGraphEdit_Flag {
SIPO_NOTRANSKEYCULL = (1 << 1),
/* don't show any keyframe handles at all */
SIPO_NOHANDLES = (1 << 2),
/* SIPO_NODRAWCFRANUM = (1 << 3), DEPRECATED */
/* Automatically lock the transform to whichever axis the cursor has moved the most. */
SIPO_AUTOLOCK_AXIS = (1 << 3),
/* show timing in seconds instead of frames */
SIPO_DRAWTIME = (1 << 4),
/* draw names of F-Curves beside the respective curves */

@ -6422,6 +6422,13 @@ static void rna_def_space_graph(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Show Handles", "Show handles of Bézier control points");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, nullptr);
prop = RNA_def_property(srna, "autolock_translation_axis", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "flag", SIPO_AUTOLOCK_AXIS);
RNA_def_property_ui_text(prop,
"Auto-Lock Key Axis",
"Automatically locks the movement of keyframes to the dominant axis");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, nullptr);
prop = RNA_def_property(srna, "use_only_selected_keyframe_handles", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "flag", SIPO_SELVHANDLESONLY);
RNA_def_property_ui_text(