diff options
author | Joshua Leung <aligorith@gmail.com> | 2010-02-07 14:50:03 +0300 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2010-02-07 14:50:03 +0300 |
commit | 20fb4e3367a4a544e15fa7c556868a37966356de (patch) | |
tree | 210d314df871e2122592e8a0eeeb4416cfcf1d3f | |
parent | 7d2c4384e275a1ff5ab289b859d6e75a29645115 (diff) |
DopeSheet and Graph Editors: Select More/Less Operators
This commit introduces the Select More/Less Operators (Ctrl +/-) for keyframes. This works like the ones for curves, by only selecting/deselecting keyframes lying in the same F-Curve. Inter F-Curve selection is not done by this operator. That is the job for another one.
This is especially useful for F-Curves set in the 0-1-0 pattern (i.e. 3 keyframes forming localised peaks), where the peaks can be selected by clicking on them individually, and immediately surrounding '0' values are selected too using "Select More".
-rw-r--r-- | release/scripts/ui/space_dopesheet.py | 4 | ||||
-rw-r--r-- | release/scripts/ui/space_graph.py | 4 | ||||
-rw-r--r-- | source/blender/editors/animation/keyframes_edit.c | 135 | ||||
-rw-r--r-- | source/blender/editors/include/ED_keyframes_edit.h | 25 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_intern.h | 2 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_ops.c | 7 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_select.c | 112 | ||||
-rw-r--r-- | source/blender/editors/space_graph/graph_intern.h | 2 | ||||
-rw-r--r-- | source/blender/editors/space_graph/graph_ops.c | 6 | ||||
-rw-r--r-- | source/blender/editors/space_graph/graph_select.c | 112 |
10 files changed, 405 insertions, 4 deletions
diff --git a/release/scripts/ui/space_dopesheet.py b/release/scripts/ui/space_dopesheet.py index 4416f3128a8..2bd0300c465 100644 --- a/release/scripts/ui/space_dopesheet.py +++ b/release/scripts/ui/space_dopesheet.py @@ -119,6 +119,10 @@ class DOPESHEET_MT_select(bpy.types.Menu): layout.operator("action.select_column", text="Columns on Selected Markers").mode = 'MARKERS_COLUMN' layout.operator("action.select_column", text="Between Selected Markers").mode = 'MARKERS_BETWEEN' + layout.separator() + layout.operator("action.select_more") + layout.operator("action.select_less") + class DOPESHEET_MT_channel(bpy.types.Menu): bl_label = "Channel" diff --git a/release/scripts/ui/space_graph.py b/release/scripts/ui/space_graph.py index e4752877c2f..511ab06d0da 100644 --- a/release/scripts/ui/space_graph.py +++ b/release/scripts/ui/space_graph.py @@ -122,6 +122,10 @@ class GRAPH_MT_select(bpy.types.Menu): layout.operator("graph.select_column", text="Columns on Selected Markers").mode = 'MARKERS_COLUMN' layout.operator("graph.select_column", text="Between Selected Markers").mode = 'MARKERS_BETWEEN' + layout.separator() + layout.operator("graph.select_more") + layout.operator("graph.select_less") + class GRAPH_MT_channel(bpy.types.Menu): bl_label = "Channel" diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c index 912b51a0b4d..c1b2e474d52 100644 --- a/source/blender/editors/animation/keyframes_edit.c +++ b/source/blender/editors/animation/keyframes_edit.c @@ -90,19 +90,22 @@ short ANIM_fcurve_keys_bezier_loop(BeztEditData *bed, FCurve *fcu, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb) { BezTriple *bezt; - int b; /* sanity check */ if (ELEM(NULL, fcu, fcu->bezt)) return 0; + /* set the F-Curve into the editdata so that it can be accessed */ + bed->fcu= fcu; + bed->curIndex= 0; + /* if function to apply to bezier curves is set, then loop through executing it on beztriples */ if (bezt_cb) { /* if there's a validation func, include that check in the loop * (this is should be more efficient than checking for it in every loop) */ if (bezt_ok) { - for (b=0, bezt=fcu->bezt; b < fcu->totvert; b++, bezt++) { + for (bed->curIndex=0, bezt=fcu->bezt; bed->curIndex < fcu->totvert; bed->curIndex++, bezt++) { /* Only operate on this BezTriple if it fullfills the criteria of the validation func */ if (bezt_ok(bed, bezt)) { /* Exit with return-code '1' if function returns positive @@ -113,7 +116,7 @@ short ANIM_fcurve_keys_bezier_loop(BeztEditData *bed, FCurve *fcu, BeztEditFunc } } else { - for (b=0, bezt=fcu->bezt; b < fcu->totvert; b++, bezt++) { + for (bed->curIndex=0, bezt=fcu->bezt; bed->curIndex < fcu->totvert; bed->curIndex++, bezt++) { /* Exit with return-code '1' if function returns positive * This is useful if finding if some BezTriple satisfies a condition. */ @@ -121,6 +124,10 @@ short ANIM_fcurve_keys_bezier_loop(BeztEditData *bed, FCurve *fcu, BeztEditFunc } } } + + /* unset the F-Curve from the editdata now that it's done */ + bed->fcu= NULL; + bed->curIndex= 0; /* if fcu_cb (F-Curve post-editing callback) has been specified then execute it */ if (fcu_cb) @@ -786,6 +793,8 @@ static short set_bezier_vector(BeztEditData *bed, BezTriple *bezt) } /* Queries if the handle should be set to 'free' or 'align' */ +// NOTE: this was used for the 'toggle free/align' option +// currently this isn't used, but may be restored later static short bezier_isfree(BeztEditData *bed, BezTriple *bezt) { if ((bezt->f1 & SELECT) && (bezt->h1)) return 1; @@ -951,3 +960,123 @@ BeztEditFunc ANIM_editkeyframes_select(short selectmode) return select_bezier_add; } } + +/* ******************************************* */ +/* Selection Maps */ + +/* Selection maps are simply fancy names for char arrays that store on/off + * info for whether the selection status. The main purpose for these is to + * allow extra info to be tagged to the keyframes without influencing their + * values or having to be removed later. + */ + +/* ----------- */ + +static short selmap_build_bezier_more(BeztEditData *bed, BezTriple *bezt) +{ + FCurve *fcu= bed->fcu; + char *map= bed->data; + int i= bed->curIndex; + + /* if current is selected, just make sure it stays this way */ + if (BEZSELECTED(bezt)) { + map[i]= 1; + return 0; + } + + /* if previous is selected, that means that selection should extend across */ + if (i > 0) { + BezTriple *prev= bezt - 1; + + if (BEZSELECTED(prev)) { + map[i]= 1; + return 0; + } + } + + /* if next is selected, that means that selection should extend across */ + if (i < (fcu->totvert-1)) { + BezTriple *next= bezt + 1; + + if (BEZSELECTED(next)) { + map[i]= 1; + return 0; + } + } + + return 0; +} + +static short selmap_build_bezier_less(BeztEditData *bed, BezTriple *bezt) +{ + FCurve *fcu= bed->fcu; + char *map= bed->data; + int i= bed->curIndex; + + /* if current is selected, check the left/right keyframes + * since it might need to be deselected (but otherwise no) + */ + if (BEZSELECTED(bezt)) { + /* if previous is not selected, we're on the tip of an iceberg */ + if (i > 0) { + BezTriple *prev= bezt - 1; + + if (BEZSELECTED(prev) == 0) + return 0; + } + else if (i == 0) { + /* current keyframe is selected at an endpoint, so should get deselected */ + return 0; + } + + /* if next is not selected, we're on the tip of an iceberg */ + if (i < (fcu->totvert-1)) { + BezTriple *next= bezt + 1; + + if (BEZSELECTED(next) == 0) + return 0; + } + else if (i == (fcu->totvert-1)) { + /* current keyframe is selected at an endpoint, so should get deselected */ + return 0; + } + + /* if we're still here, that means that keyframe should remain untouched */ + map[i]= 1; + } + + return 0; +} + +/* Get callback for building selection map */ +BeztEditFunc ANIM_editkeyframes_buildselmap(short mode) +{ + switch (mode) { + case SELMAP_LESS: /* less */ + return selmap_build_bezier_less; + + case SELMAP_MORE: /* more */ + default: + return selmap_build_bezier_more; + } +} + +/* ----------- */ + +/* flush selection map values to the given beztriple */ +short bezt_selmap_flush(BeztEditData *bed, BezTriple *bezt) +{ + char *map= bed->data; + short on= map[bed->curIndex]; + + /* select or deselect based on whether the map allows it or not */ + if (on) { + BEZ_SEL(bezt); + } + else { + BEZ_DESEL(bezt); + } + + return 0; +} + diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h index 9e29d747d4a..675dde0ae0d 100644 --- a/source/blender/editors/include/ED_keyframes_edit.h +++ b/source/blender/editors/include/ED_keyframes_edit.h @@ -58,7 +58,7 @@ typedef enum eEditKeyframes_Validate { /* ------------ */ -/* select tools */ +/* select modes */ typedef enum eEditKeyframes_Select { SELECT_REPLACE = (1<<0), SELECT_ADD = (1<<1), @@ -66,6 +66,12 @@ typedef enum eEditKeyframes_Select { SELECT_INVERT = (1<<4), } eEditKeyframes_Select; +/* "selection map" building modes */ +typedef enum eEditKeyframes_SelMap { + SELMAP_MORE = 0, + SELMAP_LESS, +} eEditKeyframes_SelMap; + /* snapping tools */ typedef enum eEditKeyframes_Snap { SNAP_KEYS_CURFRAME = 1, @@ -91,11 +97,16 @@ typedef enum eEditKeyframes_Mirror { /* --- Generic Properties for Bezier Edit Tools ----- */ typedef struct BeztEditData { + /* generic properties/data access */ ListBase list; /* temp list for storing custom list of data to check */ struct Scene *scene; /* pointer to current scene - many tools need access to cfra/etc. */ void *data; /* pointer to custom data - usually 'Object' but also 'rectf', but could be other types too */ float f1, f2; /* storage of times/values as 'decimals' */ int i1, i2; /* storage of times/values/flags as 'whole' numbers */ + + /* current iteration data */ + struct FCurve *fcu; /* F-Curve that is being iterated over */ + int curIndex; /* index of current keyframe being iterated over */ } BeztEditData; /* ------- Function Pointer Typedefs ---------------- */ @@ -143,6 +154,18 @@ BeztEditFunc ANIM_editkeyframes_handles(short mode); BeztEditFunc ANIM_editkeyframes_ipo(short mode); BeztEditFunc ANIM_editkeyframes_keytype(short mode); +/* -------- BezTriple Callbacks (Selection Map) ---------- */ + +/* Get a callback to populate the selection settings map + * requires: bed->custom = char[] of length fcurve->totvert + */ +BeztEditFunc ANIM_editkeyframes_buildselmap(short mode); + +/* Change the selection status of the keyframe based on the map entry for this vert + * requires: bed->custom = char[] of length fcurve->totvert + */ +short bezt_selmap_flush(BeztEditData *bed, struct BezTriple *bezt); + /* ----------- BezTriple Callback (Assorted Utilities) ---------- */ /* used to calculate the the average location of all relevant BezTriples by summing their locations */ diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h index 166004a5742..cf708bb7140 100644 --- a/source/blender/editors/space_action/action_intern.h +++ b/source/blender/editors/space_action/action_intern.h @@ -56,6 +56,8 @@ void action_header_buttons(const struct bContext *C, struct ARegion *ar); void ACTION_OT_select_all_toggle(struct wmOperatorType *ot); void ACTION_OT_select_border(struct wmOperatorType *ot); void ACTION_OT_select_column(struct wmOperatorType *ot); +void ACTION_OT_select_more(struct wmOperatorType *ot); +void ACTION_OT_select_less(struct wmOperatorType *ot); void ACTION_OT_clickselect(struct wmOperatorType *ot); /* defines for left-right select tool */ diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index 7792247fe81..a36021553c8 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -67,6 +67,8 @@ void action_operatortypes(void) WM_operatortype_append(ACTION_OT_select_all_toggle); WM_operatortype_append(ACTION_OT_select_border); WM_operatortype_append(ACTION_OT_select_column); + WM_operatortype_append(ACTION_OT_select_more); + WM_operatortype_append(ACTION_OT_select_less); /* editing */ WM_operatortype_append(ACTION_OT_snap); @@ -122,6 +124,11 @@ static void action_keymap_keyframes (wmKeyConfig *keyconf, wmKeyMap *keymap) RNA_enum_set(WM_keymap_add_item(keymap, "ACTION_OT_select_column", KKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_MARKERS_COLUMN); RNA_enum_set(WM_keymap_add_item(keymap, "ACTION_OT_select_column", KKEY, KM_PRESS, KM_ALT, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_MARKERS_BETWEEN); + /* select more/less */ + WM_keymap_add_item(keymap, "ACTION_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "ACTION_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0); + + /* action_edit.c */ /* snap - current frame to selected keys */ // TODO: maybe since this is called jump, we're better to have it on <something>-J? diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index be74da0718e..1939057b654 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -574,6 +574,118 @@ void ACTION_OT_select_column (wmOperatorType *ot) RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", ""); } +/* ******************** Select More/Less Operators *********************** */ + +/* Common code to perform selection */ +static void select_moreless_action_keys (bAnimContext *ac, short mode) +{ + ListBase anim_data= {NULL, NULL}; + bAnimListElem *ale; + int filter; + + BeztEditData bed; + BeztEditFunc build_cb; + + + /* init selmap building data */ + build_cb= ANIM_editkeyframes_buildselmap(mode); + memset(&bed, 0, sizeof(BeztEditData)); + + /* loop through all of the keys and select additional keyframes based on these */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + for (ale= anim_data.first; ale; ale= ale->next) { + FCurve *fcu= (FCurve *)ale->key_data; + + /* only continue if F-Curve has keyframes */ + if (fcu->bezt == NULL) + continue; + + /* build up map of whether F-Curve's keyframes should be selected or not */ + bed.data= MEM_callocN(fcu->totvert, "selmap actEdit more"); + ANIM_fcurve_keys_bezier_loop(&bed, fcu, NULL, build_cb, NULL); + + /* based on this map, adjust the selection status of the keyframes */ + ANIM_fcurve_keys_bezier_loop(&bed, fcu, NULL, bezt_selmap_flush, NULL); + + /* free the selmap used here */ + MEM_freeN(bed.data); + bed.data= NULL; + } + + /* Cleanup */ + BLI_freelistN(&anim_data); +} + +/* ----------------- */ + +static int actkeys_select_more_exec (bContext *C, wmOperator *op) +{ + bAnimContext ac; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* perform select changes */ + select_moreless_action_keys(&ac, SELMAP_MORE); + + /* set notifier that keyframe selection has changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL); + + return OPERATOR_FINISHED; +} + +void ACTION_OT_select_more (wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select More"; + ot->idname= "ACTION_OT_select_more"; + ot->description = "Select keyframes beside already selected ones."; + + /* api callbacks */ + ot->exec= actkeys_select_more_exec; + ot->poll= ED_operator_action_active; + + /* flags */ + ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/; +} + +/* ----------------- */ + +static int actkeys_select_less_exec (bContext *C, wmOperator *op) +{ + bAnimContext ac; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* perform select changes */ + select_moreless_action_keys(&ac, SELMAP_LESS); + + /* set notifier that keyframe selection has changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL); + + return OPERATOR_FINISHED; +} + +void ACTION_OT_select_less (wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Less"; + ot->idname= "ACTION_OT_select_less"; + ot->description = "Deselect keyframes on ends of selection islands."; + + /* api callbacks */ + ot->exec= actkeys_select_less_exec; + ot->poll= ED_operator_action_active; + + /* flags */ + ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/; +} + /* ******************** Mouse-Click Select Operator *********************** */ /* This operator works in one of three ways: * - 1) keyframe under mouse - no special modifiers diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h index ec6f38c93b7..a42944f0b35 100644 --- a/source/blender/editors/space_graph/graph_intern.h +++ b/source/blender/editors/space_graph/graph_intern.h @@ -63,6 +63,8 @@ void graph_header_buttons(const bContext *C, struct ARegion *ar); void GRAPH_OT_select_all_toggle(struct wmOperatorType *ot); void GRAPH_OT_select_border(struct wmOperatorType *ot); void GRAPH_OT_select_column(struct wmOperatorType *ot); +void GRAPH_OT_select_more(struct wmOperatorType *ot); +void GRAPH_OT_select_less(struct wmOperatorType *ot); void GRAPH_OT_clickselect(struct wmOperatorType *ot); /* defines for left-right select tool */ diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 7be2d7b3e4b..648a162890d 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -237,6 +237,8 @@ void graphedit_operatortypes(void) WM_operatortype_append(GRAPH_OT_select_all_toggle); WM_operatortype_append(GRAPH_OT_select_border); WM_operatortype_append(GRAPH_OT_select_column); + WM_operatortype_append(GRAPH_OT_select_more); + WM_operatortype_append(GRAPH_OT_select_less); /* editing */ WM_operatortype_append(GRAPH_OT_snap); @@ -310,6 +312,10 @@ static void graphedit_keymap_keyframes (wmKeyConfig *keyconf, wmKeyMap *keymap) RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN); RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, KM_ALT, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN); + /* select more/less */ + WM_keymap_add_item(keymap, "GRAPH_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0); + /* graph_edit.c */ /* snap - current frame to selected keys */ diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index b90d5a48d9a..872b688bea1 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -549,6 +549,118 @@ void GRAPH_OT_select_column (wmOperatorType *ot) RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", ""); } +/* ******************** Select More/Less Operators *********************** */ + +/* Common code to perform selection */ +static void select_moreless_graph_keys (bAnimContext *ac, short mode) +{ + ListBase anim_data= {NULL, NULL}; + bAnimListElem *ale; + int filter; + + BeztEditData bed; + BeztEditFunc build_cb; + + + /* init selmap building data */ + build_cb= ANIM_editkeyframes_buildselmap(mode); + memset(&bed, 0, sizeof(BeztEditData)); + + /* loop through all of the keys and select additional keyframes based on these */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + for (ale= anim_data.first; ale; ale= ale->next) { + FCurve *fcu= (FCurve *)ale->key_data; + + /* only continue if F-Curve has keyframes */ + if (fcu->bezt == NULL) + continue; + + /* build up map of whether F-Curve's keyframes should be selected or not */ + bed.data= MEM_callocN(fcu->totvert, "selmap graphEdit"); + ANIM_fcurve_keys_bezier_loop(&bed, fcu, NULL, build_cb, NULL); + + /* based on this map, adjust the selection status of the keyframes */ + ANIM_fcurve_keys_bezier_loop(&bed, fcu, NULL, bezt_selmap_flush, NULL); + + /* free the selmap used here */ + MEM_freeN(bed.data); + bed.data= NULL; + } + + /* Cleanup */ + BLI_freelistN(&anim_data); +} + +/* ----------------- */ + +static int graphkeys_select_more_exec (bContext *C, wmOperator *op) +{ + bAnimContext ac; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* perform select changes */ + select_moreless_graph_keys(&ac, SELMAP_MORE); + + /* set notifier that keyframe selection has changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL); + + return OPERATOR_FINISHED; +} + +void GRAPH_OT_select_more (wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select More"; + ot->idname= "GRAPH_OT_select_more"; + ot->description = "Select keyframes beside already selected ones."; + + /* api callbacks */ + ot->exec= graphkeys_select_more_exec; + ot->poll= graphop_visible_keyframes_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/; +} + +/* ----------------- */ + +static int graphkeys_select_less_exec (bContext *C, wmOperator *op) +{ + bAnimContext ac; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* perform select changes */ + select_moreless_graph_keys(&ac, SELMAP_LESS); + + /* set notifier that keyframe selection has changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL); + + return OPERATOR_FINISHED; +} + +void GRAPH_OT_select_less (wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Less"; + ot->idname= "GRAPH_OT_select_less"; + ot->description = "Deselect keyframes on ends of selection islands."; + + /* api callbacks */ + ot->exec= graphkeys_select_less_exec; + ot->poll= graphop_visible_keyframes_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/; +} + /* ******************** Mouse-Click Select Operator *********************** */ /* This operator works in one of three ways: * - 1) keyframe under mouse - no special modifiers |