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 /source/blender/editors/animation/keyframes_edit.c | |
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".
Diffstat (limited to 'source/blender/editors/animation/keyframes_edit.c')
-rw-r--r-- | source/blender/editors/animation/keyframes_edit.c | 135 |
1 files changed, 132 insertions, 3 deletions
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; +} + |