diff options
author | Joshua Leung <aligorith@gmail.com> | 2008-12-24 02:34:19 +0300 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2008-12-24 02:34:19 +0300 |
commit | 754590d0d857b6d362c78f28b875f98c012d444c (patch) | |
tree | 96a7043caddb51cc3b612d37166ae445caafddb0 | |
parent | e48a4db4f04abd0be13a7ba3f52c8e12af6d61d0 (diff) |
2.5 - Action Editor Select Tools
Ported the following tools
* borderselect
* invert selection
Note: while porting these, I noticed a few issues with some stuff that still needs to be cleaned up.
Events handling in scrollers won't work yet, for the useful select all in frame(-range) or select all in channel(s). We should probably review ways to expose this more clearly in the UI too.
-rw-r--r-- | source/blender/editors/animation/anim_ops.c | 1 | ||||
-rw-r--r-- | source/blender/editors/animation/keyframes_edit.c | 17 | ||||
-rw-r--r-- | source/blender/editors/include/ED_keyframes_edit.h | 3 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_intern.h | 1 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_ops.c | 5 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_select.c | 235 |
6 files changed, 248 insertions, 14 deletions
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index 4321c89f730..be3ab0502c4 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -270,7 +270,6 @@ void ED_ANIM_OT_previewrange_define(wmOperatorType *ot) RNA_def_property(ot->srna, "xmin", PROP_INT, PROP_NONE); RNA_def_property(ot->srna, "xmax", PROP_INT, PROP_NONE); /* these are not used, but are needed by borderselect gesture operator stuff */ - RNA_def_property(ot->srna, "event_type", PROP_INT, PROP_NONE); RNA_def_property(ot->srna, "ymin", PROP_INT, PROP_NONE); RNA_def_property(ot->srna, "ymax", PROP_INT, PROP_NONE); } diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c index 152d07b83f6..951e91dc55a 100644 --- a/source/blender/editors/animation/keyframes_edit.c +++ b/source/blender/editors/animation/keyframes_edit.c @@ -613,7 +613,7 @@ int fullselect_ipo_keys(Ipo *ipo) } -void borderselect_icu_key(Scene *scene, IpoCurve *icu, float xmin, float xmax, BeztEditFunc select_cb) +void borderselect_icu_key(IpoCurve *icu, float xmin, float xmax, BeztEditFunc select_cb) { /* Selects all bezier triples in the Ipocurve * between times xmin and xmax, using the selection @@ -623,18 +623,19 @@ void borderselect_icu_key(Scene *scene, IpoCurve *icu, float xmin, float xmax, B int i; /* loop through all of the bezier triples in - * the Ipocurve -- if the triple occurs between - * times xmin and xmax then select it using the selection - * function - */ + * the Ipocurve -- if the triple occurs between + * times xmin and xmax then select it using the selection + * function + */ for (i=0, bezt=icu->bezt; i<icu->totvert; i++, bezt++) { if ((bezt->vec[1][0] > xmin) && (bezt->vec[1][0] < xmax)) { - select_cb(scene, bezt); + /* scene is NULL (irrelevant here) */ + select_cb(NULL, bezt); } } } -void borderselect_ipo_key(Scene *scene, Ipo *ipo, float xmin, float xmax, short selectmode) +void borderselect_ipo_key(Ipo *ipo, float xmin, float xmax, short selectmode) { /* Selects all bezier triples in each Ipocurve of the * Ipo between times xmin and xmax, using the selection mode. @@ -660,7 +661,7 @@ void borderselect_ipo_key(Scene *scene, Ipo *ipo, float xmin, float xmax, short * function */ for (icu=ipo->curve.first; icu; icu=icu->next) { - borderselect_icu_key(scene, icu, xmin, xmax, select_cb); + borderselect_icu_key(icu, xmin, xmax, select_cb); } } diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h index d312289ca2a..1015de2e9e4 100644 --- a/source/blender/editors/include/ED_keyframes_edit.h +++ b/source/blender/editors/include/ED_keyframes_edit.h @@ -101,6 +101,9 @@ void select_icu_key(struct Scene *scene, struct IpoCurve *icu, float selx, short short is_ipo_key_selected(struct Ipo *ipo); void set_ipo_key_selection(struct Ipo *ipo, short sel); +void borderselect_ipo_key(struct Ipo *ipo, float xmin, float xmax, short selectmode); +void borderselect_icu_key(struct IpoCurve *icu, float xmin, float xmax, BeztEditFunc select_cb); + /* ************************************************ */ diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h index 3ea3e179a80..788e5df2d13 100644 --- a/source/blender/editors/space_action/action_intern.h +++ b/source/blender/editors/space_action/action_intern.h @@ -46,6 +46,7 @@ void action_header_buttons(const struct bContext *C, struct ARegion *ar); /* action_select.c */ void ED_ACT_OT_keyframes_deselectall(struct wmOperatorType *ot); +void ED_ACT_OT_keyframes_borderselect(struct wmOperatorType *ot); void ED_ACT_OT_keyframes_clickselect(struct wmOperatorType *ot); /* action_ops.c */ diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index 4fafb176a92..6d6bee90171 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -64,6 +64,7 @@ void action_operatortypes(void) /* keyframes */ WM_operatortype_append(ED_ACT_OT_keyframes_clickselect); WM_operatortype_append(ED_ACT_OT_keyframes_deselectall); + WM_operatortype_append(ED_ACT_OT_keyframes_borderselect); } /* ************************** registration - keymaps **********************************/ @@ -77,6 +78,10 @@ static void action_keymap_keyframes (ListBase *keymap) /* deselect all */ WM_keymap_add_item(keymap, "ED_ACT_OT_keyframes_deselectall", AKEY, KM_PRESS, 0, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "ED_ACT_OT_keyframes_deselectall", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1); + + /* borderselect */ + WM_keymap_add_item(keymap, "ED_ACT_OT_keyframes_borderselect", BKEY, KM_PRESS, 0, 0); } /* --------------- */ diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index 887de081de8..0a5a2969a0f 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -317,9 +317,20 @@ static void *get_nearest_action_key (bAnimContext *ac, int mval[2], float *selx, /* KEYFRAMES STUFF */ /* ******************** Deselect All Operator ***************************** */ +/* This operator works in one of three ways: + * 1) (de)select all (AKEY) - test if select all or deselect all + * 2) invert all (CTRL-IKEY) - invert selection of all keyframes + * 3) (de)select all - no testing is done; only for use internal tools as normal function... + */ /* Deselects keyframes in the action editor * - This is called by the deselect all operator, as well as other ones! + * + * - test: check if select or deselect all + * - sel: how to select keyframes + * 0 = deselect + * 1 = select + * 2 = invert */ static void deselect_action_keys (bAnimContext *ac, short test, short sel) { @@ -368,7 +379,7 @@ static void deselect_action_keys (bAnimContext *ac, short test, short sel) /* ------------------- */ -static int actkeys_deselectall_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int actkeys_deselectall_exec(bContext *C, wmOperator *op) { bAnimContext ac; @@ -377,7 +388,10 @@ static int actkeys_deselectall_invoke(bContext *C, wmOperator *op, wmEvent *even return OPERATOR_CANCELLED; /* 'standard' behaviour - check if selected, then apply relevant selection */ - deselect_action_keys(&ac, 1, 1); + if (RNA_boolean_get(op->ptr, "invert")) + deselect_action_keys(&ac, 0, 2); + else + deselect_action_keys(&ac, 1, 1); /* set notifier tha things have changed */ ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead! @@ -388,12 +402,223 @@ static int actkeys_deselectall_invoke(bContext *C, wmOperator *op, wmEvent *even void ED_ACT_OT_keyframes_deselectall (wmOperatorType *ot) { /* identifiers */ - ot->name= "Deselect All"; + ot->name= "Select All"; ot->idname= "ED_ACT_OT_keyframes_deselectall"; /* api callbacks */ - ot->invoke= actkeys_deselectall_invoke; - //ot->poll= ED_operator_areaactive; + ot->exec= actkeys_deselectall_exec; + ot->poll= ED_operator_areaactive; + + /* props */ + RNA_def_property(ot->srna, "invert", PROP_BOOLEAN, PROP_NONE); +} + +/* ******************** Border Select Operator **************************** */ +/* This operator works in one of three ways: + * 1) borderselect over keys (BKEY) - mouse over main area when initialised; will select keys in region + * 2) borderselect over horizontal scroller - mouse over horizontal scroller when initialised; will select keys in frame range + * 3) borderselect over vertical scroller - mouse over vertical scroller when initialised; will select keys in row range + */ + +static void borderselect_action (bAnimContext *ac, rcti rect, short in_scroller, short selectmode) +{ + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + View2D *v2d= &ac->ar->v2d; + BeztEditFunc select_cb; + rctf rectf; + float ymin=0, ymax=ACHANNEL_HEIGHT; + + UI_view2d_region_to_view(v2d, rect.xmin, rect.ymin+2, &rectf.xmin, &rectf.ymin); + UI_view2d_region_to_view(v2d, rect.xmax, rect.ymax-2, &rectf.xmax, &rectf.ymax); + + /* filter data */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS); + ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype); + + /* get selection editing func */ + select_cb= ANIM_editkeyframes_select(selectmode); + + /* loop over data, doing border select */ + for (ale= anim_data.first; ale; ale= ale->next) { + Object *nob= ANIM_nla_mapping_get(ac, ale); + + ymin= ymax - ACHANNEL_STEP; + + /* if action is mapped in NLA, it returns a correction */ + if (nob) { + rectf.xmin= get_action_frame(nob, rectf.xmin); + rectf.xmax= get_action_frame(nob, rectf.xmax); + } + + /* what gets selected depends on the mode (based on initial position of cursor) */ + switch (in_scroller) { + case 'h': /* all in frame(s) */ + if (ale->key_data) { + if (ale->datatype == ALE_IPO) + borderselect_ipo_key(ale->key_data, rectf.xmin, rectf.xmax, selectmode); + else if (ale->datatype == ALE_ICU) + borderselect_icu_key(ale->key_data, rectf.xmin, rectf.xmax, select_cb); + } + else if (ale->type == ANIMTYPE_GROUP) { + bActionGroup *agrp= ale->data; + bActionChannel *achan; + bConstraintChannel *conchan; + + for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) { + borderselect_ipo_key(achan->ipo, rectf.xmin, rectf.xmax, selectmode); + + for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) + borderselect_ipo_key(conchan->ipo, rectf.xmin, rectf.xmax, selectmode); + } + } + //else if (ale->type == ANIMTYPE_GPLAYER) { + // borderselect_gplayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode); + //} + break; + case 'v': /* all in channel(s) */ + if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) { + if (ale->key_data) { + if (ale->datatype == ALE_IPO) + ipo_keys_bezier_loop(ac->scene, ale->key_data, select_cb, NULL); + else if (ale->datatype == ALE_ICU) + icu_keys_bezier_loop(ac->scene, ale->key_data, select_cb, NULL); + } + else if (ale->type == ANIMTYPE_GROUP) { + bActionGroup *agrp= ale->data; + bActionChannel *achan; + bConstraintChannel *conchan; + + for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) { + ipo_keys_bezier_loop(ac->scene, achan->ipo, select_cb, NULL); + + for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) + ipo_keys_bezier_loop(ac->scene, conchan->ipo, select_cb, NULL); + } + } + //else if (ale->type == ANIMTYPE_GPLAYER) { + // select_gpencil_frames(ale->data, selectmode); + //} + } + break; + default: /* any keyframe inside region defined by region */ + if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) { + if (ale->key_data) { + if (ale->datatype == ALE_IPO) + borderselect_ipo_key(ale->key_data, rectf.xmin, rectf.xmax, selectmode); + else if (ale->datatype == ALE_ICU) + borderselect_icu_key(ale->key_data, rectf.xmin, rectf.xmax, select_cb); + } + else if (ale->type == ANIMTYPE_GROUP) { + // fixme: need a nicer way of dealing with summaries! + bActionGroup *agrp= ale->data; + bActionChannel *achan; + bConstraintChannel *conchan; + + for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) { + borderselect_ipo_key(achan->ipo, rectf.xmin, rectf.xmax, selectmode); + + for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) + borderselect_ipo_key(conchan->ipo, rectf.xmin, rectf.xmax, selectmode); + } + } + else if (ale->type == ANIMTYPE_ACT) { + // fixme: need a nicer way of dealing with summaries! + } + else if (ale->type == ANIMTYPE_OB) { + // fixme: need a nicer way of dealing with summaries! + } + //else if (ale->type == ANIMTYPE_GPLAYER) { + //// borderselect_gplayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode); + //} + } + } + + /* if action is mapped in NLA, unapply correction */ + if (nob) { + rectf.xmin= get_action_frame_inv(nob, rectf.xmin); + rectf.xmax= get_action_frame_inv(nob, rectf.xmax); + } + + ymax=ymin; + } + + /* cleanup */ + BLI_freelistN(&anim_data); +} + +/* ------------------- */ + +static int actkeys_borderselect_exec(bContext *C, wmOperator *op) +{ + bAnimContext ac; + rcti rect; + short in_scroller, selectmode; + int event; + + /* get editor data */ + if ((ANIM_animdata_get_context(C, &ac) == 0) || (ac.data == NULL)) + return OPERATOR_CANCELLED; + + /* get settings from operator */ + rect.xmin= RNA_int_get(op->ptr, "xmin"); + rect.ymin= RNA_int_get(op->ptr, "ymin"); + rect.xmax= RNA_int_get(op->ptr, "xmax"); + rect.ymax= RNA_int_get(op->ptr, "ymax"); + + in_scroller= RNA_int_get(op->ptr, "in_scroller"); + + event= RNA_int_get(op->ptr, "event_type"); + if (event == LEFTMOUSE) // FIXME... hardcoded + selectmode = SELECT_ADD; + else + selectmode = SELECT_SUBTRACT; + + borderselect_action(&ac, rect, in_scroller, selectmode); + + return OPERATOR_FINISHED; +} + +static int actkeys_borderselect_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + bAnimContext ac; + ARegion *ar; + + /* get editor data */ + if ((ANIM_animdata_get_context(C, &ac) == 0) || (ac.data == NULL)) + return OPERATOR_CANCELLED; + ar= ac.ar; + + /* check if mouse is in a scroller */ + // XXX move this to keymap level thing (boundbox checking)? + RNA_enum_set(op->ptr, "in_scroller", UI_view2d_mouse_in_scrollers(C, &ar->v2d, event->x, event->y)); + + /* now init borderselect operator to handle borderselect as per normal */ + return WM_border_select_invoke(C, op, event); +} + +void ED_ACT_OT_keyframes_borderselect(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Borderselect"; + ot->idname= "ED_ACT_OT_keyframes_borderselect"; + + /* api callbacks */ + ot->invoke= actkeys_borderselect_invoke;//WM_border_select_invoke; + ot->exec= actkeys_borderselect_exec; + ot->modal= WM_border_select_modal; + + ot->poll= ED_operator_areaactive; + + /* rna */ + RNA_def_property(ot->srna, "in_scroller", PROP_INT, PROP_NONE); // as enum instead? + RNA_def_property(ot->srna, "event_type", PROP_INT, PROP_NONE); + RNA_def_property(ot->srna, "xmin", PROP_INT, PROP_NONE); + RNA_def_property(ot->srna, "xmax", PROP_INT, PROP_NONE); + RNA_def_property(ot->srna, "ymin", PROP_INT, PROP_NONE); + RNA_def_property(ot->srna, "ymax", PROP_INT, PROP_NONE); } /* ******************** Column Select Operator **************************** */ |