Graph Editor: Auto View

Auto View automatically adjusts the view based on selection, so that the view is
always focused on the current selection.
A checkbox in the header is used to access it and it works for the following
selection methods: Toggle All, Border, Circle, Lasso, Left, Right, More, Less,
Linked, Column (so all except of single selection, in which this can be a bit
annoying)

Reviewed by @Aligorith (thanks for that :) )
This commit is contained in:
julianeisel 2015-02-06 15:45:12 +01:00
parent 31170ec19e
commit dffdde4cdc
4 changed files with 68 additions and 7 deletions

View File

@ -41,6 +41,8 @@ class GRAPH_HT_header(Header):
dopesheet_filter(layout, context)
layout.prop(st, "use_auto_view", text="Auto View")
layout.prop(st, "use_normalization", text="Normalize")
row = layout.row()
row.active = st.use_normalization

View File

@ -66,6 +66,14 @@
/* ************************************************************************** */
/* KEYFRAMES STUFF */
static void graphkeys_auto_view(bContext *C)
{
const SpaceIpo *sipo = CTX_wm_space_graph(C);
if (sipo && sipo->flag & SIPO_AUTOVIEW)
WM_operator_name_call(C, "GRAPH_OT_view_selected", WM_OP_INVOKE_DEFAULT, NULL);
}
/* ******************** Deselect All Operator ***************************** */
/* This operator works in one of three ways:
* 1) (de)select all (AKEY) - test if select all or deselect all
@ -83,7 +91,7 @@
* 2 = invert
* - do_channels: whether to affect selection status of channels
*/
static void deselect_graph_keys(bAnimContext *ac, short test, short sel, short do_channels)
static short deselect_graph_keys(bAnimContext *ac, short test, short sel, short do_channels)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
@ -142,6 +150,8 @@ static void deselect_graph_keys(bAnimContext *ac, short test, short sel, short d
/* Cleanup */
ANIM_animdata_freelist(&anim_data);
return sel;
}
/* ------------------- */
@ -150,6 +160,7 @@ static int graphkeys_deselectall_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
bAnimListElem *ale_active = NULL;
short sel;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
@ -163,9 +174,9 @@ static int graphkeys_deselectall_exec(bContext *C, wmOperator *op)
/* 'standard' behavior - check if selected, then apply relevant selection */
if (RNA_boolean_get(op->ptr, "invert"))
deselect_graph_keys(&ac, 0, SELECT_INVERT, true);
sel = deselect_graph_keys(&ac, 0, SELECT_INVERT, true);
else
deselect_graph_keys(&ac, 1, SELECT_ADD, true);
sel = deselect_graph_keys(&ac, 1, SELECT_ADD, true);
/* restore active F-Curve... */
if (ale_active) {
@ -180,6 +191,9 @@ static int graphkeys_deselectall_exec(bContext *C, wmOperator *op)
ale_active = NULL;
}
if (sel != SELECT_SUBTRACT)
graphkeys_auto_view(C);
/* set notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
@ -374,6 +388,8 @@ static int graphkeys_borderselect_exec(bContext *C, wmOperator *op)
/* apply borderselect action */
borderselect_graphkeys(&ac, &rect_fl, mode, selectmode, incl_handles, NULL);
graphkeys_auto_view(C);
/* send notifier that keyframe selection has changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
@ -461,6 +477,8 @@ static int graphkeys_lassoselect_exec(bContext *C, wmOperator *op)
MEM_freeN((void *)data_lasso.mcords);
graphkeys_auto_view(C);
/* send notifier that keyframe selection has changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
@ -491,6 +509,14 @@ void GRAPH_OT_select_lasso(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend selection instead of deselecting everything first");
}
static int graph_circle_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
if (event->type == EVT_MODAL_MAP && event->val == GESTURE_MODAL_NOP)
graphkeys_auto_view(C);
return WM_gesture_circle_modal(C, op, event);
}
static int graph_circle_select_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
@ -552,7 +578,7 @@ void GRAPH_OT_select_circle(wmOperatorType *ot)
ot->idname = "GRAPH_OT_select_circle";
ot->invoke = WM_gesture_circle_invoke;
ot->modal = WM_gesture_circle_modal;
ot->modal = graph_circle_select_modal;
ot->exec = graph_circle_select_exec;
ot->poll = graphop_visible_keyframes_poll;
ot->cancel = WM_gesture_circle_cancel;
@ -725,6 +751,8 @@ static int graphkeys_columnselect_exec(bContext *C, wmOperator *op)
else
columnselect_graph_keys(&ac, mode);
graphkeys_auto_view(C);
/* set notifier that keyframe selection has changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
@ -783,6 +811,8 @@ static int graphkeys_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
/* Cleanup */
ANIM_animdata_freelist(&anim_data);
graphkeys_auto_view(C);
/* set notifier that keyframe selection has changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
@ -807,12 +837,13 @@ void GRAPH_OT_select_linked(wmOperatorType *ot)
/* ******************** Select More/Less Operators *********************** */
/* Common code to perform selection */
static void select_moreless_graph_keys(bAnimContext *ac, short mode)
static void select_moreless_graph_keys(bContext *C, bAnimContext *ac, short mode)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
const SpaceIpo *sipo = (SpaceIpo *)ac->sl;
KeyframeEditData ked;
KeyframeEditFunc build_cb;
@ -842,6 +873,24 @@ static void select_moreless_graph_keys(bAnimContext *ac, short mode)
/* free the selmap used here */
MEM_freeN(ked.data);
ked.data = NULL;
/* only do auto view if a bezier point is selected */
if (sipo->flag & SIPO_AUTOVIEW) {
const FCurve *fcu = (FCurve *)ale->key_data;
const BezTriple *bezt;
unsigned int i;
/* only continue if F-Curve has keyframes */
if (fcu->bezt == NULL)
continue;
for (bezt = fcu->bezt, i = 0; i < fcu->totvert; bezt++, i++) {
if (BEZSELECTED(bezt)) {
graphkeys_auto_view(C);
break;
}
}
}
}
/* Cleanup */
@ -859,7 +908,7 @@ static int graphkeys_select_more_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
/* perform select changes */
select_moreless_graph_keys(&ac, SELMAP_MORE);
select_moreless_graph_keys(C, &ac, SELMAP_MORE);
/* set notifier that keyframe selection has changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
@ -893,7 +942,7 @@ static int graphkeys_select_less_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
/* perform select changes */
select_moreless_graph_keys(&ac, SELMAP_LESS);
select_moreless_graph_keys(C, &ac, SELMAP_LESS);
/* set notifier that keyframe selection has changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
@ -1008,6 +1057,8 @@ static int graphkeys_select_leftright_exec(bContext *C, wmOperator *op)
/* do the selecting now */
graphkeys_select_leftright(&ac, leftright, selectmode);
graphkeys_auto_view(C);
/* set notifier that keyframe selection (and channels too) have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | ND_ANIMCHAN | NA_SELECTED, NULL);

View File

@ -370,6 +370,8 @@ typedef enum eGraphEdit_Flag {
/* normalize curves on display */
SIPO_NORMALIZE = (1 << 14),
SIPO_NORMALIZE_FREEZE = (1 << 15),
/* automatically set view on selection */
SIPO_AUTOVIEW = (1 << 16),
} eGraphEdit_Flag;
/* SpaceIpo->mode (Graph Editor Mode) */

View File

@ -3003,6 +3003,12 @@ static void rna_def_space_graph(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Has Ghost Curves", "Graph Editor instance has some ghost curves stored");
/* auto view */
prop = RNA_def_property(srna, "use_auto_view", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SIPO_AUTOVIEW);
RNA_def_property_ui_text(prop, "Use Auto View", "Automatically adjust view based on selection");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL);
/* nromalize curves */
prop = RNA_def_property(srna, "use_normalization", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SIPO_NORMALIZE);