Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Gavrilov <angavrilov@gmail.com>2019-05-29 17:47:03 +0300
committerAlexander Gavrilov <angavrilov@gmail.com>2019-05-29 17:50:39 +0300
commitb79aeb5ca10215e5b641bfc6b3202b7ac899257e (patch)
tree03746bc8f8758a338a8b01e42e6526d1fd15cdf6 /source/blender/editors/space_action
parent0721ee45873cbaa1f55b477122857e97cefe0332 (diff)
Fix T64995: box and circle select summary in Grease Pencil dopesheet.
The issue is that generic ANIM_animchannel_keyframes_loop can't handle non-FCurve keyframes, so every selection operator does its own looping over special key types, and the box and region select operators didn't have code to deal with the summary. This adds code to handle that in a similar way to other ops.
Diffstat (limited to 'source/blender/editors/space_action')
-rw-r--r--source/blender/editors/space_action/action_select.c258
1 files changed, 161 insertions, 97 deletions
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index 1371305487e..3560b0e1c7a 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -221,14 +221,78 @@ enum {
ACTKEYS_BORDERSEL_CHANNELS,
} /*eActKeys_BoxSelect_Mode*/;
+typedef struct BoxSelectData {
+ bAnimContext *ac;
+ short selectmode;
+
+ KeyframeEditData ked;
+ KeyframeEditFunc ok_cb, select_cb;
+} BoxSelectData;
+
+static void box_select_elem(
+ BoxSelectData *sel_data, bAnimListElem *ale, float xmin, float xmax, bool summary)
+{
+ bAnimContext *ac = sel_data->ac;
+
+ switch (ale->type) {
+#if 0 /* XXX: Keyframes are not currently shown here */
+ case ANIMTYPE_GPDATABLOCK: {
+ bGPdata *gpd = ale->data;
+ bGPDlayer *gpl;
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ ED_gplayer_frames_select_box(gpl, xmin, xmax, data->selectmode);
+ }
+ ale->update |= ANIM_UPDATE_DEPS;
+ break;
+ }
+#endif
+ case ANIMTYPE_GPLAYER: {
+ ED_gplayer_frames_select_box(ale->data, xmin, xmax, sel_data->selectmode);
+ ale->update |= ANIM_UPDATE_DEPS;
+ break;
+ }
+ case ANIMTYPE_MASKDATABLOCK: {
+ Mask *mask = ale->data;
+ MaskLayer *masklay;
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ ED_masklayer_frames_select_box(masklay, xmin, xmax, sel_data->selectmode);
+ }
+ break;
+ }
+ case ANIMTYPE_MASKLAYER: {
+ ED_masklayer_frames_select_box(ale->data, xmin, xmax, sel_data->selectmode);
+ break;
+ }
+ default: {
+ if (summary) {
+ break;
+ }
+
+ if (ale->type == ANIMTYPE_SUMMARY && ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ ListBase anim_data = {NULL, NULL};
+ ANIM_animdata_filter(ac, &anim_data, ANIMFILTER_DATA_VISIBLE, ac->data, ac->datatype);
+
+ for (bAnimListElem *ale2 = anim_data.first; ale2; ale2 = ale2->next) {
+ box_select_elem(sel_data, ale2, xmin, xmax, true);
+ }
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+ }
+
+ ANIM_animchannel_keyframes_loop(
+ &sel_data->ked, ac->ads, ale, sel_data->ok_cb, sel_data->select_cb, NULL);
+ }
+ }
+}
+
static void box_select_action(bAnimContext *ac, const rcti rect, short mode, short selectmode)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
- KeyframeEditData ked;
- KeyframeEditFunc ok_cb, select_cb;
+ BoxSelectData sel_data = {.ac = ac, .selectmode = selectmode};
View2D *v2d = &ac->ar->v2d;
rctf rectf;
@@ -242,17 +306,17 @@ static void box_select_action(bAnimContext *ac, const rcti rect, short mode, sho
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* get beztriple editing/validation funcs */
- select_cb = ANIM_editkeyframes_select(selectmode);
+ sel_data.select_cb = ANIM_editkeyframes_select(selectmode);
if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS)) {
- ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
+ sel_data.ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
}
else {
- ok_cb = NULL;
+ sel_data.ok_cb = NULL;
}
/* init editing data */
- memset(&ked, 0, sizeof(KeyframeEditData));
+ memset(&sel_data.ked, 0, sizeof(KeyframeEditData));
float ymax = ACHANNEL_FIRST_TOP(ac);
@@ -267,54 +331,20 @@ static void box_select_action(bAnimContext *ac, const rcti rect, short mode, sho
if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS)) {
/* if channel is mapped in NLA, apply correction */
if (adt) {
- ked.iterflags &= ~(KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP);
- ked.f1 = BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP);
- ked.f2 = BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP);
+ sel_data.ked.iterflags &= ~(KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP);
+ sel_data.ked.f1 = BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP);
+ sel_data.ked.f2 = BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP);
}
else {
- ked.iterflags |= (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP); /* for summary tracks */
- ked.f1 = rectf.xmin;
- ked.f2 = rectf.xmax;
+ sel_data.ked.iterflags |= (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP); /* for summary tracks */
+ sel_data.ked.f1 = rectf.xmin;
+ sel_data.ked.f2 = rectf.xmax;
}
}
/* perform vertical suitability check (if applicable) */
if ((mode == ACTKEYS_BORDERSEL_FRAMERANGE) || !((ymax < rectf.ymin) || (ymin > rectf.ymax))) {
- /* loop over data selecting */
- switch (ale->type) {
-#if 0 /* XXX: Keyframes are not currently shown here */
- case ANIMTYPE_GPDATABLOCK: {
- bGPdata *gpd = ale->data;
- bGPDlayer *gpl;
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- ED_gplayer_frames_select_box(gpl, rectf.xmin, rectf.xmax, selectmode);
- }
- ale->update |= ANIM_UPDATE_DEPS;
- break;
- }
-#endif
- case ANIMTYPE_GPLAYER: {
- ED_gplayer_frames_select_box(ale->data, rectf.xmin, rectf.xmax, selectmode);
- ale->update |= ANIM_UPDATE_DEPS;
- break;
- }
- case ANIMTYPE_MASKDATABLOCK: {
- Mask *mask = ale->data;
- MaskLayer *masklay;
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- ED_masklayer_frames_select_box(masklay, rectf.xmin, rectf.xmax, selectmode);
- }
- break;
- }
- case ANIMTYPE_MASKLAYER: {
- ED_masklayer_frames_select_box(ale->data, rectf.xmin, rectf.xmax, selectmode);
- break;
- }
- default: {
- ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
- break;
- }
- }
+ box_select_elem(&sel_data, ale, rectf.xmin, rectf.xmax, false);
}
}
@@ -406,6 +436,73 @@ void ACTION_OT_select_box(wmOperatorType *ot)
* original Graph Editor implementation of these to do it this way.
*/
+typedef struct RegionSelectData {
+ bAnimContext *ac;
+ short mode;
+ short selectmode;
+
+ KeyframeEditData ked;
+ KeyframeEditFunc ok_cb, select_cb;
+} RegionSelectData;
+
+static void region_select_elem(RegionSelectData *sel_data, bAnimListElem *ale, bool summary)
+{
+ bAnimContext *ac = sel_data->ac;
+
+ switch (ale->type) {
+#if 0 /* XXX: Keyframes are not currently shown here */
+ case ANIMTYPE_GPDATABLOCK: {
+ bGPdata *gpd = ale->data;
+ bGPDlayer *gpl;
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ ED_gplayer_frames_select_region(&rdata->ked, ale->data, rdata->mode, rdata->selectmode);
+ }
+ break;
+ }
+#endif
+ case ANIMTYPE_GPLAYER: {
+ ED_gplayer_frames_select_region(
+ &sel_data->ked, ale->data, sel_data->mode, sel_data->selectmode);
+ ale->update |= ANIM_UPDATE_DEPS;
+ break;
+ }
+ case ANIMTYPE_MASKDATABLOCK: {
+ Mask *mask = ale->data;
+ MaskLayer *masklay;
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ ED_masklayer_frames_select_region(
+ &sel_data->ked, masklay, sel_data->mode, sel_data->selectmode);
+ }
+ break;
+ }
+ case ANIMTYPE_MASKLAYER: {
+ ED_masklayer_frames_select_region(
+ &sel_data->ked, ale->data, sel_data->mode, sel_data->selectmode);
+ break;
+ }
+ default: {
+ if (summary) {
+ break;
+ }
+
+ if (ale->type == ANIMTYPE_SUMMARY && ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ ListBase anim_data = {NULL, NULL};
+ ANIM_animdata_filter(ac, &anim_data, ANIMFILTER_DATA_VISIBLE, ac->data, ac->datatype);
+
+ for (bAnimListElem *ale2 = anim_data.first; ale2; ale2 = ale2->next) {
+ region_select_elem(sel_data, ale2, true);
+ }
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+ }
+
+ ANIM_animchannel_keyframes_loop(
+ &sel_data->ked, ac->ads, ale, sel_data->ok_cb, sel_data->select_cb, NULL);
+ }
+ }
+}
+
static void region_select_action_keys(
bAnimContext *ac, const rctf *rectf_view, short mode, short selectmode, void *data)
{
@@ -413,8 +510,7 @@ static void region_select_action_keys(
bAnimListElem *ale;
int filter;
- KeyframeEditData ked;
- KeyframeEditFunc ok_cb, select_cb;
+ RegionSelectData sel_data = {.ac = ac, .mode = mode, .selectmode = selectmode};
View2D *v2d = &ac->ar->v2d;
rctf rectf, scaled_rectf;
@@ -427,23 +523,23 @@ static void region_select_action_keys(
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* get beztriple editing/validation funcs */
- select_cb = ANIM_editkeyframes_select(selectmode);
- ok_cb = ANIM_editkeyframes_ok(mode);
+ sel_data.select_cb = ANIM_editkeyframes_select(selectmode);
+ sel_data.ok_cb = ANIM_editkeyframes_ok(mode);
/* init editing data */
- memset(&ked, 0, sizeof(KeyframeEditData));
+ memset(&sel_data.ked, 0, sizeof(KeyframeEditData));
if (mode == BEZT_OK_CHANNEL_LASSO) {
KeyframeEdit_LassoData *data_lasso = data;
data_lasso->rectf_scaled = &scaled_rectf;
- ked.data = data_lasso;
+ sel_data.ked.data = data_lasso;
}
else if (mode == BEZT_OK_CHANNEL_CIRCLE) {
KeyframeEdit_CircleData *data_circle = data;
data_circle->rectf_scaled = &scaled_rectf;
- ked.data = data;
+ sel_data.ked.data = data;
}
else {
- ked.data = &scaled_rectf;
+ sel_data.ked.data = &scaled_rectf;
}
float ymax = ACHANNEL_FIRST_TOP(ac);
@@ -456,7 +552,7 @@ static void region_select_action_keys(
float ymin = ymax - ACHANNEL_STEP(ac);
/* compute midpoint of channel (used for testing if the key is in the region or not) */
- ked.channel_y = (ymin + ymax) / 2.0f;
+ sel_data.ked.channel_y = (ymin + ymax) / 2.0f;
/* if channel is mapped in NLA, apply correction
* - Apply to the bounds being checked, not all the keyframe points,
@@ -465,60 +561,28 @@ static void region_select_action_keys(
* will read from
*/
if (adt) {
- ked.iterflags &= ~(KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP);
- ked.f1 = BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP);
- ked.f2 = BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP);
+ sel_data.ked.iterflags &= ~(KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP);
+ sel_data.ked.f1 = BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP);
+ sel_data.ked.f2 = BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP);
}
else {
- ked.iterflags |= (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP); /* for summary tracks */
- ked.f1 = rectf.xmin;
- ked.f2 = rectf.xmax;
+ sel_data.ked.iterflags |= (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP); /* for summary tracks */
+ sel_data.ked.f1 = rectf.xmin;
+ sel_data.ked.f2 = rectf.xmax;
}
/* Update values for scaled_rectf - which is used to compute the mapping in the callbacks
* NOTE: Since summary tracks need late-binding remapping, the callbacks may overwrite these
* with the properly remapped ked.f1/f2 values, when needed
*/
- scaled_rectf.xmin = ked.f1;
- scaled_rectf.xmax = ked.f2;
+ scaled_rectf.xmin = sel_data.ked.f1;
+ scaled_rectf.xmax = sel_data.ked.f2;
scaled_rectf.ymin = ymin;
scaled_rectf.ymax = ymax;
/* perform vertical suitability check (if applicable) */
if ((mode == ACTKEYS_BORDERSEL_FRAMERANGE) || !((ymax < rectf.ymin) || (ymin > rectf.ymax))) {
- /* loop over data selecting */
- switch (ale->type) {
-#if 0 /* XXX: Keyframes are not currently shown here */
- case ANIMTYPE_GPDATABLOCK: {
- bGPdata *gpd = ale->data;
- bGPDlayer *gpl;
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- ED_gplayer_frames_select_region(&ked, ale->data, mode, selectmode);
- }
- break;
- }
-#endif
- case ANIMTYPE_GPLAYER: {
- ED_gplayer_frames_select_region(&ked, ale->data, mode, selectmode);
- ale->update |= ANIM_UPDATE_DEPS;
- break;
- }
- case ANIMTYPE_MASKDATABLOCK: {
- Mask *mask = ale->data;
- MaskLayer *masklay;
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- ED_masklayer_frames_select_region(&ked, masklay, mode, selectmode);
- }
- break;
- }
- case ANIMTYPE_MASKLAYER: {
- ED_masklayer_frames_select_region(&ked, ale->data, mode, selectmode);
- break;
- }
- default:
- ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
- break;
- }
+ region_select_elem(&sel_data, ale, false);
}
}