/* option 1) select keyframe directly under mouse */ static void actkeys_mselect_single(bAnimContext *ac, bAnimListElem *ale, short select_mode, float selx) { KeyframeEditData ked = {{NULL}}; KeyframeEditFunc select_cb, ok_cb; /* get functions for selecting keyframes */ select_cb = ANIM_editkeyframes_select(select_mode); ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAME); ked.f1 = selx; /* select the nominated keyframe on the given frame */ if (ale->type == ANIMTYPE_GPLAYER) ED_gpencil_select_frame(ale->data, selx, select_mode); else if (ale->type == ANIMTYPE_MASKLAYER) ED_mask_select_frame(ale->data, selx, select_mode); else { if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK) && (ale->type == ANIMTYPE_SUMMARY) && (ale->datatype == ALE_ALL)) { ListBase anim_data = {NULL, NULL}; int filter; filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); for (ale = anim_data.first; ale; ale = ale->next) { if (ale->type == ANIMTYPE_GPLAYER) ED_gpencil_select_frame(ale->data, selx, select_mode); else if (ale->type == ANIMTYPE_MASKLAYER) ED_mask_select_frame(ale->data, selx, select_mode); } } else { ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL); } } }
/* option 1) select keyframe directly under mouse */ static void actkeys_mselect_single (bAnimContext *ac, bAnimListElem *ale, short select_mode, float selx) { KeyframeEditData ked= {{NULL}}; KeyframeEditFunc select_cb, ok_cb; /* get functions for selecting keyframes */ select_cb= ANIM_editkeyframes_select(select_mode); ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAME); ked.f1= selx; /* select the nominated keyframe on the given frame */ if (ale->type == ANIMTYPE_GPLAYER) select_gpencil_frame(ale->data, selx, select_mode); else ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL); }
/* option 4) select all keyframes in same channel */ static void actkeys_mselect_channel_only(bAnimContext *ac, bAnimListElem *ale, short select_mode) { KeyframeEditFunc select_cb; /* get functions for selecting keyframes */ select_cb = ANIM_editkeyframes_select(select_mode); /* select all keyframes in this channel */ if (ale->type == ANIMTYPE_GPLAYER) { ED_gpencil_select_frames(ale->data, select_mode); } else if (ale->type == ANIMTYPE_MASKLAYER) { ED_mask_select_frames(ale->data, select_mode); } else { if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK) && (ale->type == ANIMTYPE_SUMMARY) && (ale->datatype == ALE_ALL)) { ListBase anim_data = {NULL, NULL}; int filter; filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); for (ale = anim_data.first; ale; ale = ale->next) { if (ale->type == ANIMTYPE_GPLAYER) { ED_gpencil_select_frames(ale->data, select_mode); } else if (ale->type == ANIMTYPE_MASKLAYER) { ED_mask_select_frames(ale->data, select_mode); } } ANIM_animdata_freelist(&anim_data); } else { ANIM_animchannel_keyframes_loop(NULL, ac->ads, ale, NULL, select_cb, NULL); } } }
static void region_select_action_keys(bAnimContext *ac, const rctf *rectf_view, short mode, short selectmode, void *data) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; KeyframeEditData ked; KeyframeEditFunc ok_cb, select_cb; View2D *v2d = &ac->ar->v2d; rctf rectf, scaled_rectf; float ymin = 0, ymax = (float)(-ACHANNEL_HEIGHT_HALF(ac)); /* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */ UI_view2d_region_to_view_rctf(v2d, rectf_view, &rectf); /* filter data */ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); 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); /* init editing data */ memset(&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; } else if (mode == BEZT_OK_CHANNEL_CIRCLE) { KeyframeEdit_CircleData *data_circle = data; data_circle->rectf_scaled = &scaled_rectf; ked.data = data; } else { ked.data = &scaled_rectf; } /* loop over data, doing region select */ for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ANIM_nla_mapping_get(ac, ale); /* get new vertical minimum extent of channel */ 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 + ACHANNEL_HEIGHT_HALF(ac); /* if channel is mapped in NLA, apply correction * - Apply to the bounds being checked, not all the keyframe points, * to avoid having scaling everything * - Save result to the scaled_rect, which is all that these operators * 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); } else { ked.iterflags |= (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP); /* for summary tracks */ ked.f1 = rectf.xmin; 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.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); 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; } } /* set minimum extent to be the maximum of the next channel */ ymax = ymin; } /* cleanup */ ANIM_animdata_freelist(&anim_data); }
static void borderselect_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; View2D *v2d = &ac->ar->v2d; rctf rectf; float ymin = 0, ymax = (float)(-ACHANNEL_HEIGHT_HALF(ac)); /* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */ 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_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* get beztriple editing/validation funcs */ select_cb = ANIM_editkeyframes_select(selectmode); if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS)) ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE); else ok_cb = NULL; /* init editing data */ memset(&ked, 0, sizeof(KeyframeEditData)); /* loop over data, doing border select */ for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ANIM_nla_mapping_get(ac, ale); /* get new vertical minimum extent of channel */ ymin = ymax - ACHANNEL_STEP(ac); /* set horizontal range (if applicable) */ 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); } else { ked.iterflags |= (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP); /* for summary tracks */ ked.f1 = rectf.xmin; 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_border(gpl, rectf.xmin, rectf.xmax, selectmode); } break; } #endif case ANIMTYPE_GPLAYER: ED_gplayer_frames_select_border(ale->data, rectf.xmin, rectf.xmax, selectmode); break; case ANIMTYPE_MASKDATABLOCK: { Mask *mask = ale->data; MaskLayer *masklay; for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { ED_masklayer_frames_select_border(masklay, rectf.xmin, rectf.xmax, selectmode); } break; } case ANIMTYPE_MASKLAYER: ED_masklayer_frames_select_border(ale->data, rectf.xmin, rectf.xmax, selectmode); break; default: ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL); break; } } /* set minimum extent to be the maximum of the next channel */ ymax = ymin; } /* cleanup */ ANIM_animdata_freelist(&anim_data); }
static void borderselect_action (bAnimContext *ac, rcti rect, short mode, short selectmode) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; KeyframeEditData ked; KeyframeEditFunc ok_cb, select_cb; View2D *v2d= &ac->ar->v2d; rctf rectf; float ymin=0, ymax=(float)(-ACHANNEL_HEIGHT_HALF); /* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */ 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_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* get beztriple editing/validation funcs */ select_cb= ANIM_editkeyframes_select(selectmode); if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS)) ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE); else ok_cb= NULL; /* init editing data */ memset(&ked, 0, sizeof(KeyframeEditData)); /* loop over data, doing border select */ for (ale= anim_data.first; ale; ale= ale->next) { AnimData *adt= ANIM_nla_mapping_get(ac, ale); /* get new vertical minimum extent of channel */ ymin= ymax - ACHANNEL_STEP; /* set horizontal range (if applicable) */ if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS)) { /* if channel is mapped in NLA, apply correction */ if (adt) { ked.f1= BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP); ked.f2= BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP); } else { ked.f1= rectf.xmin; 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 */ if (ale->type == ANIMTYPE_GPLAYER) borderselect_gplayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode); else ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL); } /* set minimum extent to be the maximum of the next channel */ ymax=ymin; } /* cleanup */ BLI_freelistN(&anim_data); }