Blender  V2.93
action_select.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2008 Blender Foundation
17  */
18 
23 #include <float.h>
24 #include <math.h>
25 #include <stdlib.h>
26 #include <string.h>
27 
28 #include "MEM_guardedalloc.h"
29 
30 #include "BLI_blenlib.h"
31 #include "BLI_dlrbTree.h"
32 #include "BLI_lasso_2d.h"
33 #include "BLI_utildefines.h"
34 
35 #include "DNA_anim_types.h"
36 #include "DNA_gpencil_types.h"
37 #include "DNA_mask_types.h"
38 #include "DNA_object_types.h"
39 #include "DNA_scene_types.h"
40 
41 #include "RNA_access.h"
42 #include "RNA_define.h"
43 
44 #include "BKE_context.h"
45 #include "BKE_fcurve.h"
46 #include "BKE_gpencil.h"
47 #include "BKE_nla.h"
48 
49 #include "UI_interface.h"
50 #include "UI_view2d.h"
51 
52 #include "ED_anim_api.h"
53 #include "ED_gpencil.h"
54 #include "ED_keyframes_draw.h"
55 #include "ED_keyframes_edit.h"
56 #include "ED_markers.h"
57 #include "ED_mask.h"
58 #include "ED_screen.h"
59 #include "ED_select_utils.h"
60 
61 #include "WM_api.h"
62 #include "WM_types.h"
63 
64 #include "action_intern.h"
65 
66 /* ************************************************************************** */
67 /* KEYFRAMES STUFF */
68 
70  int filter,
71  float region_x,
72  float region_y)
73 {
74  View2D *v2d = &ac->region->v2d;
75 
76  float view_x, view_y;
77  int channel_index;
78  UI_view2d_region_to_view(v2d, region_x, region_y, &view_x, &view_y);
80  0, ACHANNEL_STEP(ac), 0, ACHANNEL_FIRST_TOP(ac), view_x, view_y, NULL, &channel_index);
81 
82  ListBase anim_data = {NULL, NULL};
83  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
84 
85  bAnimListElem *ale = BLI_findlink(&anim_data, channel_index);
86  if (ale != NULL) {
87  BLI_remlink(&anim_data, ale);
88  ale->next = ale->prev = NULL;
89  }
90  ANIM_animdata_freelist(&anim_data);
91 
92  return ale;
93 }
94 
96  DLRBT_Tree *anim_keys,
97  bAnimListElem *ale)
98 {
99  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
100 
101  bDopeSheet *ads = NULL;
103  ads = ac->data;
104  }
105 
106  if (ale->key_data) {
107  switch (ale->datatype) {
108  case ALE_SCE: {
109  Scene *scene = (Scene *)ale->key_data;
110  scene_to_keylist(ads, scene, anim_keys, 0);
111  break;
112  }
113  case ALE_OB: {
114  Object *ob = (Object *)ale->key_data;
115  ob_to_keylist(ads, ob, anim_keys, 0);
116  break;
117  }
118  case ALE_ACT: {
119  bAction *act = (bAction *)ale->key_data;
120  action_to_keylist(adt, act, anim_keys, 0);
121  break;
122  }
123  case ALE_FCURVE: {
124  FCurve *fcu = (FCurve *)ale->key_data;
125  fcurve_to_keylist(adt, fcu, anim_keys, 0);
126  break;
127  }
128  }
129  }
130  else if (ale->type == ANIMTYPE_SUMMARY) {
131  /* dopesheet summary covers everything */
132  summary_to_keylist(ac, anim_keys, 0);
133  }
134  else if (ale->type == ANIMTYPE_GROUP) {
135  /* TODO: why don't we just give groups key_data too? */
136  bActionGroup *agrp = (bActionGroup *)ale->data;
137  agroup_to_keylist(adt, agrp, anim_keys, 0);
138  }
139  else if (ale->type == ANIMTYPE_GPLAYER) {
140  /* TODO: why don't we just give gplayers key_data too? */
141  bGPDlayer *gpl = (bGPDlayer *)ale->data;
142  gpl_to_keylist(ads, gpl, anim_keys);
143  }
144  else if (ale->type == ANIMTYPE_MASKLAYER) {
145  /* TODO: why don't we just give masklayers key_data too? */
146  MaskLayer *masklay = (MaskLayer *)ale->data;
147  mask_to_keylist(ads, masklay, anim_keys);
148  }
149 }
150 
152  bAnimListElem *ale,
153  float region_x,
154  float *r_selx,
155  float *r_frame,
156  bool *r_found,
157  bool *r_is_selected)
158 {
159  *r_found = false;
160 
161  View2D *v2d = &ac->region->v2d;
162 
163  DLRBT_Tree anim_keys;
164  BLI_dlrbTree_init(&anim_keys);
165  actkeys_list_element_to_keylist(ac, &anim_keys, ale);
166 
167  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
168 
169  /* standard channel height (to allow for some slop) */
170  float key_hsize = ACHANNEL_HEIGHT(ac) * 0.8f;
171  /* half-size (for either side), but rounded up to nearest int (for easier targeting) */
172  key_hsize = roundf(key_hsize / 2.0f);
173 
174  float xmin = UI_view2d_region_to_view_x(v2d, region_x - (int)key_hsize);
175  float xmax = UI_view2d_region_to_view_x(v2d, region_x + (int)key_hsize);
176 
177  for (ActKeyColumn *ak = anim_keys.root; ak; ak = (ak->cfra < xmin) ? ak->right : ak->left) {
178  if (IN_RANGE(ak->cfra, xmin, xmax)) {
179  /* set the frame to use, and apply inverse-correction for NLA-mapping
180  * so that the frame will get selected by the selection functions without
181  * requiring to map each frame once again...
182  */
183  *r_selx = BKE_nla_tweakedit_remap(adt, ak->cfra, NLATIME_CONVERT_UNMAP);
184  *r_frame = ak->cfra;
185  *r_found = true;
186  *r_is_selected = (ak->sel & SELECT) != 0;
187  break;
188  }
189  }
190 
191  /* cleanup temporary lists */
192  BLI_dlrbTree_free(&anim_keys);
193 }
194 
196  int filter,
197  float region_x,
198  float region_y,
199  bAnimListElem **r_ale,
200  float *r_selx,
201  float *r_frame,
202  bool *r_found,
203  bool *r_is_selected)
204 
205 {
206  *r_found = false;
207  *r_ale = actkeys_find_list_element_at_position(ac, filter, region_x, region_y);
208 
209  if (*r_ale != NULL) {
211  ac, *r_ale, region_x, r_selx, r_frame, r_found, r_is_selected);
212  }
213 }
214 
215 static bool actkeys_is_key_at_position(bAnimContext *ac, float region_x, float region_y)
216 {
217  bAnimListElem *ale;
218  float selx, frame;
219  bool found;
220  bool is_selected;
221 
224  ac, filter, region_x, region_y, &ale, &selx, &frame, &found, &is_selected);
225 
226  if (ale != NULL) {
227  MEM_freeN(ale);
228  }
229  return found;
230 }
231 
232 /* ******************** Deselect All Operator ***************************** */
233 /* This operator works in one of three ways:
234  * 1) (de)select all (AKEY) - test if select all or deselect all
235  * 2) invert all (CTRL-IKEY) - invert selection of all keyframes
236  * 3) (de)select all - no testing is done; only for use internal tools as normal function...
237  */
238 
239 /* Deselects keyframes in the action editor
240  * - This is called by the deselect all operator, as well as other ones!
241  *
242  * - test: check if select or deselect all
243  * - sel: how to select keyframes (SELECT_*)
244  */
245 static void deselect_action_keys(bAnimContext *ac, short test, short sel)
246 {
247  ListBase anim_data = {NULL, NULL};
248  bAnimListElem *ale;
249  int filter;
250 
251  KeyframeEditData ked = {{NULL}};
252  KeyframeEditFunc test_cb, sel_cb;
253 
254  /* determine type-based settings */
257  }
258  else {
259  filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ |
261  }
262 
263  /* filter data */
264  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
265 
266  /* init BezTriple looping data */
268 
269  /* See if we should be selecting or deselecting */
270  if (test) {
271  for (ale = anim_data.first; ale; ale = ale->next) {
272  if (ale->type == ANIMTYPE_GPLAYER) {
274  sel = SELECT_SUBTRACT;
275  break;
276  }
277  }
278  else if (ale->type == ANIMTYPE_MASKLAYER) {
280  sel = SELECT_SUBTRACT;
281  break;
282  }
283  }
284  else {
285  if (ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, test_cb, NULL)) {
286  sel = SELECT_SUBTRACT;
287  break;
288  }
289  }
290  }
291  }
292 
293  /* convert sel to selectmode, and use that to get editor */
294  sel_cb = ANIM_editkeyframes_select(sel);
295 
296  /* Now set the flags */
297  for (ale = anim_data.first; ale; ale = ale->next) {
298  if (ale->type == ANIMTYPE_GPLAYER) {
300  ale->update |= ANIM_UPDATE_DEPS;
301  }
302  else if (ale->type == ANIMTYPE_MASKLAYER) {
304  }
305  else {
306  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL);
307  }
308  }
309 
310  /* Cleanup */
311  ANIM_animdata_update(ac, &anim_data);
312  ANIM_animdata_freelist(&anim_data);
313 }
314 
315 /* ------------------- */
316 
318 {
319  bAnimContext ac;
320 
321  /* get editor data */
322  if (ANIM_animdata_get_context(C, &ac) == 0) {
323  return OPERATOR_CANCELLED;
324  }
325 
326  /* 'standard' behavior - check if selected, then apply relevant selection */
327  const int action = RNA_enum_get(op->ptr, "action");
328  switch (action) {
329  case SEL_TOGGLE:
331  break;
332  case SEL_SELECT:
334  break;
335  case SEL_DESELECT:
337  break;
338  case SEL_INVERT:
340  break;
341  default:
342  BLI_assert(0);
343  break;
344  }
345 
346  /* set notifier that keyframe selection have changed */
348  if (ac.datatype == ANIMCONT_GPENCIL) {
350  }
351  return OPERATOR_FINISHED;
352 }
353 
355 {
356  /* identifiers */
357  ot->name = "Select All";
358  ot->idname = "ACTION_OT_select_all";
359  ot->description = "Toggle selection of all keyframes";
360 
361  /* api callbacks */
364 
365  /* flags */
367 
368  /* properties */
370 }
371 
372 /* ******************** Box Select Operator **************************** */
382 /* defines for box_select mode */
383 enum {
387 } /*eActKeys_BoxSelect_Mode*/;
388 
389 typedef struct BoxSelectData {
391  short selectmode;
392 
396 
397 static void box_select_elem(
398  BoxSelectData *sel_data, bAnimListElem *ale, float xmin, float xmax, bool summary)
399 {
400  bAnimContext *ac = sel_data->ac;
401 
402  switch (ale->type) {
403 #if 0 /* XXX: Keyframes are not currently shown here */
404  case ANIMTYPE_GPDATABLOCK: {
405  bGPdata *gpd = ale->data;
406  bGPDlayer *gpl;
407  for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
408  ED_gpencil_layer_frames_select_box(gpl, xmin, xmax, data->selectmode);
409  }
410  ale->update |= ANIM_UPDATE_DEPS;
411  break;
412  }
413 #endif
414  case ANIMTYPE_GPLAYER: {
415  ED_gpencil_layer_frames_select_box(ale->data, xmin, xmax, sel_data->selectmode);
416  ale->update |= ANIM_UPDATE_DEPS;
417  break;
418  }
419  case ANIMTYPE_MASKDATABLOCK: {
420  Mask *mask = ale->data;
421  MaskLayer *masklay;
422  for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
423  ED_masklayer_frames_select_box(masklay, xmin, xmax, sel_data->selectmode);
424  }
425  break;
426  }
427  case ANIMTYPE_MASKLAYER: {
428  ED_masklayer_frames_select_box(ale->data, xmin, xmax, sel_data->selectmode);
429  break;
430  }
431  default: {
432  if (summary) {
433  break;
434  }
435 
437  ListBase anim_data = {NULL, NULL};
438  ANIM_animdata_filter(ac, &anim_data, ANIMFILTER_DATA_VISIBLE, ac->data, ac->datatype);
439 
440  LISTBASE_FOREACH (bAnimListElem *, ale2, &anim_data) {
441  box_select_elem(sel_data, ale2, xmin, xmax, true);
442  }
443 
444  ANIM_animdata_update(ac, &anim_data);
445  ANIM_animdata_freelist(&anim_data);
446  }
447 
449  &sel_data->ked, ac->ads, ale, sel_data->ok_cb, sel_data->select_cb, NULL);
450  }
451  }
452 }
453 
454 static void box_select_action(bAnimContext *ac, const rcti rect, short mode, short selectmode)
455 {
456  ListBase anim_data = {NULL, NULL};
457  bAnimListElem *ale;
458  int filter;
459 
460  BoxSelectData sel_data = {.ac = ac, .selectmode = selectmode};
461  View2D *v2d = &ac->region->v2d;
462  rctf rectf;
463 
464  /* Convert mouse coordinates to frame ranges and channel
465  * coordinates corrected for view pan/zoom. */
466  UI_view2d_region_to_view(v2d, rect.xmin, rect.ymin + 2, &rectf.xmin, &rectf.ymin);
467  UI_view2d_region_to_view(v2d, rect.xmax, rect.ymax - 2, &rectf.xmax, &rectf.ymax);
468 
469  /* filter data */
471  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
472 
473  /* get beztriple editing/validation funcs */
474  sel_data.select_cb = ANIM_editkeyframes_select(selectmode);
475 
478  }
479  else {
480  sel_data.ok_cb = NULL;
481  }
482 
483  /* init editing data */
484  memset(&sel_data.ked, 0, sizeof(KeyframeEditData));
485 
486  float ymax = ACHANNEL_FIRST_TOP(ac);
487 
488  /* loop over data, doing box select */
489  for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac)) {
490  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
491 
492  /* get new vertical minimum extent of channel */
493  float ymin = ymax - ACHANNEL_STEP(ac);
494 
495  /* set horizontal range (if applicable) */
497  /* if channel is mapped in NLA, apply correction */
498  if (adt) {
500  sel_data.ked.f1 = BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP);
501  sel_data.ked.f2 = BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP);
502  }
503  else {
504  sel_data.ked.iterflags |= (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP); /* for summary tracks */
505  sel_data.ked.f1 = rectf.xmin;
506  sel_data.ked.f2 = rectf.xmax;
507  }
508  }
509 
510  /* perform vertical suitability check (if applicable) */
511  if ((mode == ACTKEYS_BORDERSEL_FRAMERANGE) || !((ymax < rectf.ymin) || (ymin > rectf.ymax))) {
512  box_select_elem(&sel_data, ale, rectf.xmin, rectf.xmax, false);
513  }
514  }
515 
516  /* cleanup */
517  ANIM_animdata_update(ac, &anim_data);
518  ANIM_animdata_freelist(&anim_data);
519 }
520 
521 /* ------------------- */
522 
523 static int actkeys_box_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
524 {
525  bAnimContext ac;
526  if (ANIM_animdata_get_context(C, &ac) == 0) {
527  return OPERATOR_CANCELLED;
528  }
529 
530  bool tweak = RNA_boolean_get(op->ptr, "tweak");
531  if (tweak && actkeys_is_key_at_position(&ac, event->mval[0], event->mval[1])) {
533  }
534 
535  return WM_gesture_box_invoke(C, op, event);
536 }
537 
539 {
540  bAnimContext ac;
541  rcti rect;
542  short mode = 0;
543 
544  /* get editor data */
545  if (ANIM_animdata_get_context(C, &ac) == 0) {
546  return OPERATOR_CANCELLED;
547  }
548 
549  const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
550  const int selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
551  if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
553  }
554 
555  /* get settings from operator */
557 
558  /* selection 'mode' depends on whether box_select region only matters on one axis */
559  if (RNA_boolean_get(op->ptr, "axis_range")) {
560  /* Mode depends on which axis of the range is larger to determine which axis to use:
561  * - checking this in region-space is fine,
562  * as it's fundamentally still going to be a different rect size.
563  * - the frame-range select option is favored over the channel one (x over y),
564  * as frame-range one is often used for tweaking timing when "blocking",
565  * while channels is not that useful...
566  */
567  if (BLI_rcti_size_x(&rect) >= BLI_rcti_size_y(&rect)) {
569  }
570  else {
572  }
573  }
574  else {
576  }
577 
578  /* apply box_select action */
579  box_select_action(&ac, rect, mode, selectmode);
580 
581  /* set notifier that keyframe selection have changed */
583  if (ac.datatype == ANIMCONT_GPENCIL) {
585  }
586  return OPERATOR_FINISHED;
587 }
588 
590 {
591  /* identifiers */
592  ot->name = "Box Select";
593  ot->idname = "ACTION_OT_select_box";
594  ot->description = "Select all keyframes within the specified region";
595 
596  /* api callbacks */
601 
603 
604  /* flags */
606 
607  /* rna */
608  ot->prop = RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
609 
610  /* properties */
613 
615  ot->srna, "tweak", 0, "Tweak", "Operator has been activated using a tweak event");
617 }
618 
619 /* ******************** Region Select Operators ***************************** */
620 /* "Region Select" operators include the Lasso and Circle Select operators.
621  * These two ended up being lumped together, as it was easier in the
622  * original Graph Editor implementation of these to do it this way.
623  */
624 
625 typedef struct RegionSelectData {
627  short mode;
628  short selectmode;
629 
633 
634 static void region_select_elem(RegionSelectData *sel_data, bAnimListElem *ale, bool summary)
635 {
636  bAnimContext *ac = sel_data->ac;
637 
638  switch (ale->type) {
639 #if 0 /* XXX: Keyframes are not currently shown here */
640  case ANIMTYPE_GPDATABLOCK: {
641  bGPdata *gpd = ale->data;
642  bGPDlayer *gpl;
643  for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
644  ED_gpencil_layer_frames_select_region(&rdata->ked, ale->data, rdata->mode, rdata->selectmode);
645  }
646  break;
647  }
648 #endif
649  case ANIMTYPE_GPLAYER: {
651  &sel_data->ked, ale->data, sel_data->mode, sel_data->selectmode);
652  ale->update |= ANIM_UPDATE_DEPS;
653  break;
654  }
655  case ANIMTYPE_MASKDATABLOCK: {
656  Mask *mask = ale->data;
657  MaskLayer *masklay;
658  for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
660  &sel_data->ked, masklay, sel_data->mode, sel_data->selectmode);
661  }
662  break;
663  }
664  case ANIMTYPE_MASKLAYER: {
666  &sel_data->ked, ale->data, sel_data->mode, sel_data->selectmode);
667  break;
668  }
669  default: {
670  if (summary) {
671  break;
672  }
673 
675  ListBase anim_data = {NULL, NULL};
676  ANIM_animdata_filter(ac, &anim_data, ANIMFILTER_DATA_VISIBLE, ac->data, ac->datatype);
677 
678  LISTBASE_FOREACH (bAnimListElem *, ale2, &anim_data) {
679  region_select_elem(sel_data, ale2, true);
680  }
681 
682  ANIM_animdata_update(ac, &anim_data);
683  ANIM_animdata_freelist(&anim_data);
684  }
685 
687  &sel_data->ked, ac->ads, ale, sel_data->ok_cb, sel_data->select_cb, NULL);
688  }
689  }
690 }
691 
693  bAnimContext *ac, const rctf *rectf_view, short mode, short selectmode, void *data)
694 {
695  ListBase anim_data = {NULL, NULL};
696  bAnimListElem *ale;
697  int filter;
698 
699  RegionSelectData sel_data = {.ac = ac, .mode = mode, .selectmode = selectmode};
700  View2D *v2d = &ac->region->v2d;
701  rctf rectf, scaled_rectf;
702 
703  /* Convert mouse coordinates to frame ranges and channel
704  * coordinates corrected for view pan/zoom. */
705  UI_view2d_region_to_view_rctf(v2d, rectf_view, &rectf);
706 
707  /* filter data */
709  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
710 
711  /* get beztriple editing/validation funcs */
712  sel_data.select_cb = ANIM_editkeyframes_select(selectmode);
713  sel_data.ok_cb = ANIM_editkeyframes_ok(mode);
714 
715  /* init editing data */
716  memset(&sel_data.ked, 0, sizeof(KeyframeEditData));
717  if (mode == BEZT_OK_CHANNEL_LASSO) {
718  KeyframeEdit_LassoData *data_lasso = data;
719  data_lasso->rectf_scaled = &scaled_rectf;
720  sel_data.ked.data = data_lasso;
721  }
722  else if (mode == BEZT_OK_CHANNEL_CIRCLE) {
723  KeyframeEdit_CircleData *data_circle = data;
724  data_circle->rectf_scaled = &scaled_rectf;
725  sel_data.ked.data = data;
726  }
727  else {
728  sel_data.ked.data = &scaled_rectf;
729  }
730 
731  float ymax = ACHANNEL_FIRST_TOP(ac);
732 
733  /* loop over data, doing region select */
734  for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac)) {
735  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
736 
737  /* get new vertical minimum extent of channel */
738  float ymin = ymax - ACHANNEL_STEP(ac);
739 
740  /* compute midpoint of channel (used for testing if the key is in the region or not) */
741  sel_data.ked.channel_y = (ymin + ymax) / 2.0f;
742 
743  /* if channel is mapped in NLA, apply correction
744  * - Apply to the bounds being checked, not all the keyframe points,
745  * to avoid having scaling everything
746  * - Save result to the scaled_rect, which is all that these operators
747  * will read from
748  */
749  if (adt) {
751  sel_data.ked.f1 = BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP);
752  sel_data.ked.f2 = BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP);
753  }
754  else {
755  sel_data.ked.iterflags |= (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP); /* for summary tracks */
756  sel_data.ked.f1 = rectf.xmin;
757  sel_data.ked.f2 = rectf.xmax;
758  }
759 
760  /* Update values for scaled_rectf - which is used to compute the mapping in the callbacks
761  * NOTE: Since summary tracks need late-binding remapping, the callbacks may overwrite these
762  * with the properly remapped ked.f1/f2 values, when needed
763  */
764  scaled_rectf.xmin = sel_data.ked.f1;
765  scaled_rectf.xmax = sel_data.ked.f2;
766  scaled_rectf.ymin = ymin;
767  scaled_rectf.ymax = ymax;
768 
769  /* perform vertical suitability check (if applicable) */
770  if ((mode == ACTKEYS_BORDERSEL_FRAMERANGE) || !((ymax < rectf.ymin) || (ymin > rectf.ymax))) {
771  region_select_elem(&sel_data, ale, false);
772  }
773  }
774 
775  /* cleanup */
776  ANIM_animdata_update(ac, &anim_data);
777  ANIM_animdata_freelist(&anim_data);
778 }
779 
780 /* ----------------------------------- */
781 
783 {
784  bAnimContext ac;
785 
786  KeyframeEdit_LassoData data_lasso;
787  rcti rect;
788  rctf rect_fl;
789 
790  /* get editor data */
791  if (ANIM_animdata_get_context(C, &ac) == 0) {
792  return OPERATOR_CANCELLED;
793  }
794 
795  data_lasso.rectf_view = &rect_fl;
796  data_lasso.mcoords = WM_gesture_lasso_path_to_array(C, op, &data_lasso.mcoords_len);
797  if (data_lasso.mcoords == NULL) {
798  return OPERATOR_CANCELLED;
799  }
800 
801  const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
802  const int selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
803  if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
805  }
806 
807  /* get settings from operator */
808  BLI_lasso_boundbox(&rect, data_lasso.mcoords, data_lasso.mcoords_len);
809  BLI_rctf_rcti_copy(&rect_fl, &rect);
810 
811  /* apply box_select action */
812  region_select_action_keys(&ac, &rect_fl, BEZT_OK_CHANNEL_LASSO, selectmode, &data_lasso);
813 
814  MEM_freeN((void *)data_lasso.mcoords);
815 
816  /* send notifier that keyframe selection has changed */
818  if (ac.datatype == ANIMCONT_GPENCIL) {
820  }
821  return OPERATOR_FINISHED;
822 }
823 
825 {
826  /* identifiers */
827  ot->name = "Lasso Select";
828  ot->description = "Select keyframe points using lasso selection";
829  ot->idname = "ACTION_OT_select_lasso";
830 
831  /* api callbacks */
837 
838  /* flags */
839  ot->flag = OPTYPE_UNDO;
840 
841  /* properties */
844 }
845 
846 /* ------------------- */
847 
849 {
850  bAnimContext ac;
851 
853  rctf rect_fl;
854 
855  float x = RNA_int_get(op->ptr, "x");
856  float y = RNA_int_get(op->ptr, "y");
857  float radius = RNA_int_get(op->ptr, "radius");
858 
859  /* get editor data */
860  if (ANIM_animdata_get_context(C, &ac) == 0) {
861  return OPERATOR_CANCELLED;
862  }
863 
864  const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"),
866  const short selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
867  if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
869  }
870 
871  data.mval[0] = x;
872  data.mval[1] = y;
873  data.radius_squared = radius * radius;
874  data.rectf_view = &rect_fl;
875 
876  rect_fl.xmin = x - radius;
877  rect_fl.xmax = x + radius;
878  rect_fl.ymin = y - radius;
879  rect_fl.ymax = y + radius;
880 
881  /* apply region select action */
882  region_select_action_keys(&ac, &rect_fl, BEZT_OK_CHANNEL_CIRCLE, selectmode, &data);
883 
884  /* send notifier that keyframe selection has changed */
886  if (ac.datatype == ANIMCONT_GPENCIL) {
888  }
889  return OPERATOR_FINISHED;
890 }
891 
893 {
894  ot->name = "Circle Select";
895  ot->description = "Select keyframe points using circle selection";
896  ot->idname = "ACTION_OT_select_circle";
897 
903 
904  /* flags */
905  ot->flag = OPTYPE_UNDO;
906 
907  /* properties */
910 }
911 
912 /* ******************** Column Select Operator **************************** */
913 /* This operator works in one of four ways:
914  * - 1) select all keyframes in the same frame as a selected one (KKEY)
915  * - 2) select all keyframes in the same frame as the current frame marker (CTRL-KKEY)
916  * - 3) select all keyframes in the same frame as a selected markers (SHIFT-KKEY)
917  * - 4) select all keyframes that occur between selected markers (ALT-KKEY)
918  */
919 
920 /* defines for column-select mode */
922  {ACTKEYS_COLUMNSEL_KEYS, "KEYS", 0, "On Selected Keyframes", ""},
923  {ACTKEYS_COLUMNSEL_CFRA, "CFRA", 0, "On Current Frame", ""},
924  {ACTKEYS_COLUMNSEL_MARKERS_COLUMN, "MARKERS_COLUMN", 0, "On Selected Markers", ""},
926  "MARKERS_BETWEEN",
927  0,
928  "Between Min/Max Selected Markers",
929  ""},
930  {0, NULL, 0, NULL, NULL},
931 };
932 
933 /* ------------------- */
934 
935 /* Selects all visible keyframes between the specified markers */
936 /* TODO, this is almost an _exact_ duplicate of a function of the same name in graph_select.c
937  * should de-duplicate - campbell */
939 {
940  ListBase anim_data = {NULL, NULL};
941  bAnimListElem *ale;
942  int filter;
943 
944  KeyframeEditFunc ok_cb, select_cb;
945  KeyframeEditData ked = {{NULL}};
946  float min, max;
947 
948  /* get extreme markers */
949  ED_markers_get_minmax(ac->markers, 1, &min, &max);
950  min -= 0.5f;
951  max += 0.5f;
952 
953  /* get editing funcs + data */
956 
957  ked.f1 = min;
958  ked.f2 = max;
959 
960  /* filter data */
961  filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ |
963  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
964 
965  /* select keys in-between */
966  for (ale = anim_data.first; ale; ale = ale->next) {
967  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
968 
969  if (adt) {
970  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
971  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
972  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
973  }
974  else if (ale->type == ANIMTYPE_GPLAYER) {
976  ale->update |= ANIM_UPDATE_DEPS;
977  }
978  else if (ale->type == ANIMTYPE_MASKLAYER) {
980  }
981  else {
982  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
983  }
984  }
985 
986  /* Cleanup */
987  ANIM_animdata_update(ac, &anim_data);
988  ANIM_animdata_freelist(&anim_data);
989 }
990 
991 /* Selects all visible keyframes in the same frames as the specified elements */
992 static void columnselect_action_keys(bAnimContext *ac, short mode)
993 {
994  ListBase anim_data = {NULL, NULL};
995  bAnimListElem *ale;
996  int filter;
997 
998  Scene *scene = ac->scene;
999  CfraElem *ce;
1000  KeyframeEditFunc select_cb, ok_cb;
1001  KeyframeEditData ked = {{NULL}};
1002 
1003  /* build list of columns */
1004  switch (mode) {
1005  case ACTKEYS_COLUMNSEL_KEYS: /* list of selected keys */
1006  if (ac->datatype == ANIMCONT_GPENCIL) {
1008  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1009 
1010  for (ale = anim_data.first; ale; ale = ale->next) {
1011  ED_gpencil_layer_make_cfra_list(ale->data, &ked.list, 1);
1012  }
1013  }
1014  else {
1015  filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/);
1016  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1017 
1018  for (ale = anim_data.first; ale; ale = ale->next) {
1020  }
1021  }
1022  ANIM_animdata_freelist(&anim_data);
1023  break;
1024 
1025  case ACTKEYS_COLUMNSEL_CFRA: /* current frame */
1026  /* make a single CfraElem for storing this */
1027  ce = MEM_callocN(sizeof(CfraElem), "cfraElem");
1028  BLI_addtail(&ked.list, ce);
1029 
1030  ce->cfra = (float)CFRA;
1031  break;
1032 
1033  case ACTKEYS_COLUMNSEL_MARKERS_COLUMN: /* list of selected markers */
1035  break;
1036 
1037  default: /* invalid option */
1038  return;
1039  }
1040 
1041  /* set up BezTriple edit callbacks */
1044 
1045  /* loop through all of the keys and select additional keyframes
1046  * based on the keys found to be selected above
1047  */
1050  }
1051  else {
1052  filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/);
1053  }
1054  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1055 
1056  for (ale = anim_data.first; ale; ale = ale->next) {
1057  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
1058 
1059  /* loop over cfraelems (stored in the KeyframeEditData->list)
1060  * - we need to do this here, as we can apply fewer NLA-mapping conversions
1061  */
1062  for (ce = ked.list.first; ce; ce = ce->next) {
1063  /* set frame for validation callback to refer to */
1064  if (adt) {
1066  }
1067  else {
1068  ked.f1 = ce->cfra;
1069  }
1070 
1071  /* select elements with frame number matching cfraelem */
1072  if (ale->type == ANIMTYPE_GPLAYER) {
1074  ale->update |= ANIM_UPDATE_DEPS;
1075  }
1076  else if (ale->type == ANIMTYPE_MASKLAYER) {
1078  }
1079  else {
1080  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
1081  }
1082  }
1083  }
1084 
1085  /* free elements */
1086  BLI_freelistN(&ked.list);
1087 
1088  ANIM_animdata_update(ac, &anim_data);
1089  ANIM_animdata_freelist(&anim_data);
1090 }
1091 
1092 /* ------------------- */
1093 
1095 {
1096  bAnimContext ac;
1097  short mode;
1098 
1099  /* get editor data */
1100  if (ANIM_animdata_get_context(C, &ac) == 0) {
1101  return OPERATOR_CANCELLED;
1102  }
1103 
1104  /* action to take depends on the mode */
1105  mode = RNA_enum_get(op->ptr, "mode");
1106 
1107  if (mode == ACTKEYS_COLUMNSEL_MARKERS_BETWEEN) {
1109  }
1110  else {
1111  columnselect_action_keys(&ac, mode);
1112  }
1113 
1114  /* set notifier that keyframe selection have changed */
1116  if (ac.datatype == ANIMCONT_GPENCIL) {
1118  }
1119  return OPERATOR_FINISHED;
1120 }
1121 
1123 {
1124  /* identifiers */
1125  ot->name = "Select All";
1126  ot->idname = "ACTION_OT_select_column";
1127  ot->description = "Select all keyframes on the specified frame(s)";
1128 
1129  /* api callbacks */
1132 
1133  /* flags */
1135 
1136  /* props */
1137  ot->prop = RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", "");
1138 }
1139 
1140 /* ******************** Select Linked Operator *********************** */
1141 
1143 {
1144  bAnimContext ac;
1145 
1146  ListBase anim_data = {NULL, NULL};
1147  bAnimListElem *ale;
1148  int filter;
1149 
1152 
1153  /* get editor data */
1154  if (ANIM_animdata_get_context(C, &ac) == 0) {
1155  return OPERATOR_CANCELLED;
1156  }
1157 
1158  /* loop through all of the keys and select additional keyframes based on these */
1159  filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ |
1161  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1162 
1163  for (ale = anim_data.first; ale; ale = ale->next) {
1164  FCurve *fcu = (FCurve *)ale->key_data;
1165 
1166  /* check if anything selected? */
1167  if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, ok_cb, NULL)) {
1168  /* select every keyframe in this curve then */
1169  ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, sel_cb, NULL);
1170  }
1171  }
1172 
1173  /* Cleanup */
1174  ANIM_animdata_freelist(&anim_data);
1175 
1176  /* set notifier that keyframe selection has changed */
1178  if (ac.datatype == ANIMCONT_GPENCIL) {
1180  }
1181  return OPERATOR_FINISHED;
1182 }
1183 
1185 {
1186  /* identifiers */
1187  ot->name = "Select Linked";
1188  ot->idname = "ACTION_OT_select_linked";
1189  ot->description = "Select keyframes occurring in the same F-Curves as selected ones";
1190 
1191  /* api callbacks */
1194 
1195  /* flags */
1197 }
1198 
1199 /* ******************** Select More/Less Operators *********************** */
1200 
1201 /* Common code to perform selection */
1202 static void select_moreless_action_keys(bAnimContext *ac, short mode)
1203 {
1204  ListBase anim_data = {NULL, NULL};
1205  bAnimListElem *ale;
1206  int filter;
1207 
1208  KeyframeEditData ked = {{NULL}};
1209  KeyframeEditFunc build_cb;
1210 
1211  /* init selmap building data */
1212  build_cb = ANIM_editkeyframes_buildselmap(mode);
1213 
1214  /* loop through all of the keys and select additional keyframes based on these */
1215  filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ |
1217  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1218 
1219  for (ale = anim_data.first; ale; ale = ale->next) {
1220 
1221  /* TODO: other types. */
1222  if (ale->datatype != ALE_FCURVE) {
1223  continue;
1224  }
1225 
1226  /* only continue if F-Curve has keyframes */
1227  FCurve *fcu = (FCurve *)ale->key_data;
1228  if (fcu->bezt == NULL) {
1229  continue;
1230  }
1231 
1232  /* build up map of whether F-Curve's keyframes should be selected or not */
1233  ked.data = MEM_callocN(fcu->totvert, "selmap actEdit more");
1234  ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, build_cb, NULL);
1235 
1236  /* based on this map, adjust the selection status of the keyframes */
1238 
1239  /* free the selmap used here */
1240  MEM_freeN(ked.data);
1241  ked.data = NULL;
1242  }
1243 
1244  /* Cleanup */
1245  ANIM_animdata_freelist(&anim_data);
1246 }
1247 
1248 /* ----------------- */
1249 
1251 {
1252  bAnimContext ac;
1253 
1254  /* get editor data */
1255  if (ANIM_animdata_get_context(C, &ac) == 0) {
1256  return OPERATOR_CANCELLED;
1257  }
1258 
1259  /* perform select changes */
1261 
1262  /* set notifier that keyframe selection has changed */
1264  if (ac.datatype == ANIMCONT_GPENCIL) {
1266  }
1267  return OPERATOR_FINISHED;
1268 }
1269 
1271 {
1272  /* identifiers */
1273  ot->name = "Select More";
1274  ot->idname = "ACTION_OT_select_more";
1275  ot->description = "Select keyframes beside already selected ones";
1276 
1277  /* api callbacks */
1280 
1281  /* flags */
1283 }
1284 
1285 /* ----------------- */
1286 
1288 {
1289  bAnimContext ac;
1290 
1291  /* get editor data */
1292  if (ANIM_animdata_get_context(C, &ac) == 0) {
1293  return OPERATOR_CANCELLED;
1294  }
1295 
1296  /* perform select changes */
1298 
1299  /* set notifier that keyframe selection has changed */
1301  if (ac.datatype == ANIMCONT_GPENCIL) {
1303  }
1304  return OPERATOR_FINISHED;
1305 }
1306 
1308 {
1309  /* identifiers */
1310  ot->name = "Select Less";
1311  ot->idname = "ACTION_OT_select_less";
1312  ot->description = "Deselect keyframes on ends of selection islands";
1313 
1314  /* api callbacks */
1317 
1318  /* flags */
1320 }
1321 
1322 /* ******************** Select Left/Right Operator ************************* */
1323 /* Select keyframes left/right of the current frame indicator */
1324 
1325 /* defines for left-right select tool */
1327  {ACTKEYS_LRSEL_TEST, "CHECK", 0, "Check if Select Left or Right", ""},
1328  {ACTKEYS_LRSEL_LEFT, "LEFT", 0, "Before Current Frame", ""},
1329  {ACTKEYS_LRSEL_RIGHT, "RIGHT", 0, "After Current Frame", ""},
1330  {0, NULL, 0, NULL, NULL},
1331 };
1332 
1333 /* --------------------------------- */
1334 
1335 static void actkeys_select_leftright(bAnimContext *ac, short leftright, short select_mode)
1336 {
1337  ListBase anim_data = {NULL, NULL};
1338  bAnimListElem *ale;
1339  int filter;
1340 
1341  KeyframeEditFunc ok_cb, select_cb;
1342  KeyframeEditData ked = {{NULL}};
1343  Scene *scene = ac->scene;
1344 
1345  /* if select mode is replace, deselect all keyframes (and channels) first */
1346  if (select_mode == SELECT_REPLACE) {
1347  select_mode = SELECT_ADD;
1348 
1349  /* - deselect all other keyframes, so that just the newly selected remain
1350  * - channels aren't deselected, since we don't re-select any as a consequence
1351  */
1353  }
1354 
1355  /* set callbacks and editing data */
1357  select_cb = ANIM_editkeyframes_select(select_mode);
1358 
1359  if (leftright == ACTKEYS_LRSEL_LEFT) {
1360  ked.f1 = MINAFRAMEF;
1361  ked.f2 = (float)(CFRA + 0.1f);
1362  }
1363  else {
1364  ked.f1 = (float)(CFRA - 0.1f);
1365  ked.f2 = MAXFRAMEF;
1366  }
1367 
1368  /* filter data */
1371  }
1372  else {
1373  filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ |
1375  }
1376  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1377 
1378  /* select keys */
1379  for (ale = anim_data.first; ale; ale = ale->next) {
1380  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
1381 
1382  if (adt) {
1383  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
1384  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
1385  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
1386  }
1387  else if (ale->type == ANIMTYPE_GPLAYER) {
1388  ED_gpencil_layer_frames_select_box(ale->data, ked.f1, ked.f2, select_mode);
1389  ale->update |= ANIM_UPDATE_DEPS;
1390  }
1391  else if (ale->type == ANIMTYPE_MASKLAYER) {
1392  ED_masklayer_frames_select_box(ale->data, ked.f1, ked.f2, select_mode);
1393  }
1394  else {
1395  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
1396  }
1397  }
1398 
1399  /* Sync marker support */
1400  if (select_mode == SELECT_ADD) {
1401  SpaceAction *saction = (SpaceAction *)ac->sl;
1402 
1403  if ((saction) && (saction->flag & SACTION_MARKERS_MOVE)) {
1405  TimeMarker *marker;
1406 
1407  for (marker = markers->first; marker; marker = marker->next) {
1408  if (((leftright == ACTKEYS_LRSEL_LEFT) && (marker->frame < CFRA)) ||
1409  ((leftright == ACTKEYS_LRSEL_RIGHT) && (marker->frame >= CFRA))) {
1410  marker->flag |= SELECT;
1411  }
1412  else {
1413  marker->flag &= ~SELECT;
1414  }
1415  }
1416  }
1417  }
1418 
1419  /* Cleanup */
1420  ANIM_animdata_update(ac, &anim_data);
1421  ANIM_animdata_freelist(&anim_data);
1422 }
1423 
1424 /* ----------------- */
1425 
1427 {
1428  bAnimContext ac;
1429  short leftright = RNA_enum_get(op->ptr, "mode");
1430  short selectmode;
1431 
1432  /* get editor data */
1433  if (ANIM_animdata_get_context(C, &ac) == 0) {
1434  return OPERATOR_CANCELLED;
1435  }
1436 
1437  /* select mode is either replace (deselect all, then add) or add/extend */
1438  if (RNA_boolean_get(op->ptr, "extend")) {
1439  selectmode = SELECT_INVERT;
1440  }
1441  else {
1442  selectmode = SELECT_REPLACE;
1443  }
1444 
1445  /* if "test" mode is set, we don't have any info to set this with */
1446  if (leftright == ACTKEYS_LRSEL_TEST) {
1447  return OPERATOR_CANCELLED;
1448  }
1449 
1450  /* do the selecting now */
1451  actkeys_select_leftright(&ac, leftright, selectmode);
1452 
1453  /* set notifier that keyframe selection (and channels too) have changed */
1456 
1457  return OPERATOR_FINISHED;
1458 }
1459 
1461 {
1462  bAnimContext ac;
1463  short leftright = RNA_enum_get(op->ptr, "mode");
1464 
1465  /* get editor data */
1466  if (ANIM_animdata_get_context(C, &ac) == 0) {
1467  return OPERATOR_CANCELLED;
1468  }
1469 
1470  /* handle mode-based testing */
1471  if (leftright == ACTKEYS_LRSEL_TEST) {
1472  Scene *scene = ac.scene;
1473  ARegion *region = ac.region;
1474  View2D *v2d = &region->v2d;
1475  float x;
1476 
1477  /* determine which side of the current frame mouse is on */
1478  x = UI_view2d_region_to_view_x(v2d, event->mval[0]);
1479  if (x < CFRA) {
1480  RNA_enum_set(op->ptr, "mode", ACTKEYS_LRSEL_LEFT);
1481  }
1482  else {
1483  RNA_enum_set(op->ptr, "mode", ACTKEYS_LRSEL_RIGHT);
1484  }
1485  }
1486 
1487  /* perform selection */
1488  return actkeys_select_leftright_exec(C, op);
1489 }
1490 
1492 {
1493  PropertyRNA *prop;
1494 
1495  /* identifiers */
1496  ot->name = "Select Left/Right";
1497  ot->idname = "ACTION_OT_select_leftright";
1498  ot->description = "Select keyframes to the left or the right of the current frame";
1499 
1500  /* api callbacks */
1504 
1505  /* flags */
1507 
1508  /* properties */
1509  ot->prop = RNA_def_enum(
1512 
1513  prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
1515 }
1516 
1517 /* ******************** Mouse-Click Select Operator *********************** */
1518 /* This operator works in one of three ways:
1519  * - 1) keyframe under mouse - no special modifiers
1520  * - 2) all keyframes on the same side of current frame indicator as mouse - ALT modifier
1521  * - 3) column select all keyframes in frame under mouse - CTRL modifier
1522  * - 4) all keyframes in channel under mouse - CTRL+ALT modifiers
1523  *
1524  * In addition to these basic options, the SHIFT modifier can be used to toggle the
1525  * selection mode between replacing the selection (without) and inverting the selection (with).
1526  */
1527 
1528 /* ------------------- */
1529 
1530 /* option 1) select keyframe directly under mouse */
1532  bAnimListElem *ale,
1533  short select_mode,
1534  float selx)
1535 {
1536  KeyframeEditData ked = {{NULL}};
1537  KeyframeEditFunc select_cb, ok_cb;
1538 
1539  /* get functions for selecting keyframes */
1540  select_cb = ANIM_editkeyframes_select(select_mode);
1542  ked.f1 = selx;
1543  ked.iterflags |= KED_F1_NLA_UNMAP;
1544 
1545  /* select the nominated keyframe on the given frame */
1546  if (ale->type == ANIMTYPE_GPLAYER) {
1547  ED_gpencil_select_frame(ale->data, selx, select_mode);
1548  ale->update |= ANIM_UPDATE_DEPS;
1549  }
1550  else if (ale->type == ANIMTYPE_MASKLAYER) {
1551  ED_mask_select_frame(ale->data, selx, select_mode);
1552  }
1553  else {
1555  (ale->datatype == ALE_ALL)) {
1556  ListBase anim_data = {NULL, NULL};
1557  int filter;
1558 
1559  filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ |
1561  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1562 
1563  for (ale = anim_data.first; ale; ale = ale->next) {
1564  if (ale->type == ANIMTYPE_GPLAYER) {
1565  ED_gpencil_select_frame(ale->data, selx, select_mode);
1566  ale->update |= ANIM_UPDATE_DEPS;
1567  }
1568  else if (ale->type == ANIMTYPE_MASKLAYER) {
1569  ED_mask_select_frame(ale->data, selx, select_mode);
1570  }
1571  }
1572 
1573  ANIM_animdata_update(ac, &anim_data);
1574  ANIM_animdata_freelist(&anim_data);
1575  }
1576  else {
1577  ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
1578  }
1579  }
1580 }
1581 
1582 /* Option 2) Selects all the keyframes on either side of the current frame
1583  * (depends on which side the mouse is on) */
1584 /* (see actkeys_select_leftright) */
1585 
1586 /* Option 3) Selects all visible keyframes in the same frame as the mouse click */
1587 static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float selx)
1588 {
1589  ListBase anim_data = {NULL, NULL};
1590  bAnimListElem *ale;
1591  int filter;
1592 
1593  KeyframeEditFunc select_cb, ok_cb;
1594  KeyframeEditData ked = {{NULL}};
1595 
1596  /* set up BezTriple edit callbacks */
1597  select_cb = ANIM_editkeyframes_select(select_mode);
1599 
1600  /* loop through all of the keys and select additional keyframes
1601  * based on the keys found to be selected above
1602  */
1604  filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ |
1606  }
1607  else {
1609  }
1610  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1611 
1612  for (ale = anim_data.first; ale; ale = ale->next) {
1613  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
1614 
1615  /* set frame for validation callback to refer to */
1616  if (adt) {
1618  }
1619  else {
1620  ked.f1 = selx;
1621  }
1622 
1623  /* select elements with frame number matching cfra */
1624  if (ale->type == ANIMTYPE_GPLAYER) {
1625  ED_gpencil_select_frame(ale->key_data, selx, select_mode);
1626  ale->update |= ANIM_UPDATE_DEPS;
1627  }
1628  else if (ale->type == ANIMTYPE_MASKLAYER) {
1629  ED_mask_select_frame(ale->key_data, selx, select_mode);
1630  }
1631  else {
1632  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
1633  }
1634  }
1635 
1636  /* free elements */
1637  BLI_freelistN(&ked.list);
1638 
1639  ANIM_animdata_update(ac, &anim_data);
1640  ANIM_animdata_freelist(&anim_data);
1641 }
1642 
1643 /* option 4) select all keyframes in same channel */
1644 static void actkeys_mselect_channel_only(bAnimContext *ac, bAnimListElem *ale, short select_mode)
1645 {
1646  KeyframeEditFunc select_cb;
1647 
1648  /* get functions for selecting keyframes */
1649  select_cb = ANIM_editkeyframes_select(select_mode);
1650 
1651  /* select all keyframes in this channel */
1652  if (ale->type == ANIMTYPE_GPLAYER) {
1653  ED_gpencil_select_frames(ale->data, select_mode);
1654  ale->update = ANIM_UPDATE_DEPS;
1655  }
1656  else if (ale->type == ANIMTYPE_MASKLAYER) {
1657  ED_mask_select_frames(ale->data, select_mode);
1658  }
1659  else {
1661  (ale->datatype == ALE_ALL)) {
1662  ListBase anim_data = {NULL, NULL};
1663  int filter;
1664 
1665  filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ |
1667  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1668 
1669  for (ale = anim_data.first; ale; ale = ale->next) {
1670  if (ale->type == ANIMTYPE_GPLAYER) {
1671  ED_gpencil_select_frames(ale->data, select_mode);
1672  ale->update |= ANIM_UPDATE_DEPS;
1673  }
1674  else if (ale->type == ANIMTYPE_MASKLAYER) {
1675  ED_mask_select_frames(ale->data, select_mode);
1676  }
1677  }
1678 
1679  ANIM_animdata_update(ac, &anim_data);
1680  ANIM_animdata_freelist(&anim_data);
1681  }
1682  else {
1683  ANIM_animchannel_keyframes_loop(NULL, ac->ads, ale, NULL, select_cb, NULL);
1684  }
1685  }
1686 }
1687 
1688 /* ------------------- */
1689 
1691  const int mval[2],
1692  short select_mode,
1693  const bool deselect_all,
1694  const bool column,
1695  const bool same_channel,
1696  bool wait_to_deselect_others)
1697 {
1699 
1700  bAnimListElem *ale = NULL;
1701  bool found = false;
1702  bool is_selected = false;
1703  float frame = 0.0f; /* frame of keyframe under mouse - NLA corrections not applied/included */
1704  float selx = 0.0f; /* frame of keyframe under mouse */
1705  int ret_value = OPERATOR_FINISHED;
1706 
1708  ac, filter, mval[0], mval[1], &ale, &selx, &frame, &found, &is_selected);
1709 
1710  if (select_mode != SELECT_REPLACE) {
1711  wait_to_deselect_others = false;
1712  }
1713 
1714  /* For replacing selection, if we have something to select, we have to clear existing selection.
1715  * The same goes if we found nothing to select, and deselect_all is true
1716  * (deselect on nothing behavior). */
1717  if ((select_mode == SELECT_REPLACE && found) || (!found && deselect_all)) {
1718  /* reset selection mode for next steps */
1719  select_mode = SELECT_ADD;
1720 
1721  /* Rather than deselecting others, users may want to drag to box-select (drag from empty space)
1722  * or tweak-translate an already selected item. If these cases may apply, delay deselection. */
1723  if (wait_to_deselect_others && (!found || is_selected)) {
1724  ret_value = OPERATOR_RUNNING_MODAL;
1725  }
1726  else {
1727  /* deselect all keyframes */
1729 
1730  /* highlight channel clicked on */
1732  /* deselect all other channels first */
1734 
1735  /* Highlight Action-Group or F-Curve? */
1736  if (ale != NULL && ale->data) {
1737  if (ale->type == ANIMTYPE_GROUP) {
1738  bActionGroup *agrp = ale->data;
1739 
1740  agrp->flag |= AGRP_SELECTED;
1742  }
1743  else if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
1744  FCurve *fcu = ale->data;
1745 
1746  fcu->flag |= FCURVE_SELECTED;
1747  ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type);
1748  }
1749  }
1750  }
1751  else if (ac->datatype == ANIMCONT_GPENCIL) {
1752  /* deselect all other channels first */
1754 
1755  /* Highlight GPencil Layer */
1756  if (ale != NULL && ale->data != NULL && ale->type == ANIMTYPE_GPLAYER) {
1757  bGPdata *gpd = (bGPdata *)ale->id;
1758  bGPDlayer *gpl = ale->data;
1759 
1760  gpl->flag |= GP_LAYER_SELECT;
1761  /* Update other layer status. */
1762  if (BKE_gpencil_layer_active_get(gpd) != gpl) {
1763  BKE_gpencil_layer_active_set(gpd, gpl);
1764  BKE_gpencil_layer_autolock_set(gpd, false);
1766  }
1767  }
1768  }
1769  else if (ac->datatype == ANIMCONT_MASK) {
1770  /* deselect all other channels first */
1772 
1773  if (ale != NULL && ale->data != NULL && ale->type == ANIMTYPE_MASKLAYER) {
1774  MaskLayer *masklay = ale->data;
1775 
1776  masklay->flag |= MASK_LAYERFLAG_SELECT;
1777  }
1778  }
1779  }
1780  }
1781 
1782  /* only select keyframes if we clicked on a valid channel and hit something */
1783  if (ale != NULL) {
1784  if (found) {
1785  /* apply selection to keyframes */
1786  if (column) {
1787  /* select all keyframes in the same frame as the one we hit on the active channel
1788  * [T41077]: "frame" not "selx" here (i.e. no NLA corrections yet) as the code here
1789  * does that itself again as it needs to work on multiple data-blocks.
1790  */
1791  actkeys_mselect_column(ac, select_mode, frame);
1792  }
1793  else if (same_channel) {
1794  /* select all keyframes in the active channel */
1795  actkeys_mselect_channel_only(ac, ale, select_mode);
1796  }
1797  else {
1798  /* select the nominated keyframe on the given frame */
1799  actkeys_mselect_single(ac, ale, select_mode, selx);
1800  }
1801  }
1802 
1803  /* flush tagged updates
1804  * NOTE: We temporarily add this channel back to the list so that this can happen
1805  */
1806  ListBase anim_data = {ale, ale};
1807  ANIM_animdata_update(ac, &anim_data);
1808 
1809  /* free this channel */
1810  MEM_freeN(ale);
1811  }
1812 
1813  return ret_value;
1814 }
1815 
1816 /* handle clicking */
1818 {
1819  bAnimContext ac;
1820  int ret_value;
1821 
1822  /* get editor data */
1823  if (ANIM_animdata_get_context(C, &ac) == 0) {
1824  return OPERATOR_CANCELLED;
1825  }
1826 
1827  /* get useful pointers from animation context data */
1828  /* region = ac.region; */ /* UNUSED */
1829 
1830  /* select mode is either replace (deselect all, then add) or add/extend */
1831  const short selectmode = RNA_boolean_get(op->ptr, "extend") ? SELECT_INVERT : SELECT_REPLACE;
1832  const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
1833  const bool wait_to_deselect_others = RNA_boolean_get(op->ptr, "wait_to_deselect_others");
1834  int mval[2];
1835 
1836  /* column selection */
1837  const bool column = RNA_boolean_get(op->ptr, "column");
1838  const bool channel = RNA_boolean_get(op->ptr, "channel");
1839 
1840  mval[0] = RNA_int_get(op->ptr, "mouse_x");
1841  mval[1] = RNA_int_get(op->ptr, "mouse_y");
1842 
1843  /* select keyframe(s) based upon mouse position*/
1844  ret_value = mouse_action_keys(
1845  &ac, mval, selectmode, deselect_all, column, channel, wait_to_deselect_others);
1846 
1847  /* set notifier that keyframe selection (and channels too) have changed */
1850 
1851  /* for tweak grab to work */
1852  return ret_value | OPERATOR_PASS_THROUGH;
1853 }
1854 
1856 {
1857  PropertyRNA *prop;
1858 
1859  /* identifiers */
1860  ot->name = "Select Keyframes";
1861  ot->idname = "ACTION_OT_clickselect";
1862  ot->description = "Select keyframes by clicking on them";
1863 
1864  /* callbacks */
1869 
1870  /* flags */
1871  ot->flag = OPTYPE_UNDO;
1872 
1873  /* properties */
1875  prop = RNA_def_boolean(
1876  ot->srna,
1877  "extend",
1878  0,
1879  "Extend Select",
1880  "Toggle keyframe selection instead of leaving newly selected keyframes only"); /* SHIFTKEY */
1882 
1883  prop = RNA_def_boolean(ot->srna,
1884  "deselect_all",
1885  false,
1886  "Deselect On Nothing",
1887  "Deselect all when nothing under the cursor");
1889 
1890  prop = RNA_def_boolean(
1891  ot->srna,
1892  "column",
1893  0,
1894  "Column Select",
1895  "Select all keyframes that occur on the same frame as the one under the mouse"); /* ALTKEY */
1897 
1898  prop = RNA_def_boolean(
1899  ot->srna,
1900  "channel",
1901  0,
1902  "Only Channel",
1903  "Select all the keyframes in the channel under the mouse"); /* CTRLKEY + ALTKEY */
1905 }
1906 
1907 /* ************************************************************************** */
typedef float(TangentPoint)[2]
void BKE_gpencil_layer_active_set(struct bGPdata *gpd, struct bGPDlayer *active)
Definition: gpencil.c:1698
struct bGPDlayer * BKE_gpencil_layer_active_get(struct bGPdata *gpd)
Definition: gpencil.c:1650
void BKE_gpencil_layer_autolock_set(struct bGPdata *gpd, const bool unlock)
Definition: gpencil.c:1725
@ NLATIME_CONVERT_UNMAP
Definition: BKE_nla.h:153
float BKE_nla_tweakedit_remap(struct AnimData *adt, float cframe, short mode)
Definition: nla.c:582
#define BLI_assert(a)
Definition: BLI_assert.h:58
void BLI_dlrbTree_init(DLRBT_Tree *tree)
Definition: DLRB_tree.c:40
void BLI_dlrbTree_free(DLRBT_Tree *tree)
Definition: DLRB_tree.c:66
void BLI_lasso_boundbox(struct rcti *rect, const int mcoords[][2], const unsigned int mcoords_len)
Definition: lasso_2d.c:31
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:547
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:157
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:153
void BLI_rctf_rcti_copy(struct rctf *dst, const struct rcti *src)
#define IN_RANGE(a, b, c)
#define UNUSED(x)
#define ELEM(...)
@ AGRP_SELECTED
@ SACTION_MARKERS_MOVE
@ FCURVE_SELECTED
@ GP_LAYER_SELECT
@ MASK_LAYERFLAG_SELECT
Object is a sort of wrapper for general info.
#define CFRA
#define MAXFRAMEF
#define MINAFRAMEF
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
@ ACHANNEL_SETFLAG_CLEAR
Definition: ED_anim_api.h:508
#define ACHANNEL_HEIGHT(ac)
Definition: ED_anim_api.h:429
@ ANIMTYPE_SUMMARY
Definition: ED_anim_api.h:202
@ ANIMTYPE_NLACURVE
Definition: ED_anim_api.h:210
@ ANIMTYPE_GROUP
Definition: ED_anim_api.h:206
@ ANIMTYPE_GPLAYER
Definition: ED_anim_api.h:241
@ ANIMTYPE_MASKDATABLOCK
Definition: ED_anim_api.h:243
@ ANIMTYPE_MASKLAYER
Definition: ED_anim_api.h:244
@ ANIMTYPE_FCURVE
Definition: ED_anim_api.h:207
@ ANIMTYPE_GPDATABLOCK
Definition: ED_anim_api.h:240
#define ACHANNEL_FIRST_TOP(ac)
Definition: ED_anim_api.h:427
@ ALE_SCE
Definition: ED_anim_api.h:264
@ ALE_FCURVE
Definition: ED_anim_api.h:258
@ ALE_ALL
Definition: ED_anim_api.h:263
@ ALE_ACT
Definition: ED_anim_api.h:266
@ ALE_OB
Definition: ED_anim_api.h:265
@ ANIM_UPDATE_DEPS
Definition: ED_anim_api.h:275
@ ANIMCONT_MASK
Definition: ED_anim_api.h:125
@ ANIMCONT_TIMELINE
Definition: ED_anim_api.h:126
@ ANIMCONT_DOPESHEET
Definition: ED_anim_api.h:120
@ ANIMCONT_ACTION
Definition: ED_anim_api.h:117
@ ANIMCONT_GPENCIL
Definition: ED_anim_api.h:119
#define ACHANNEL_STEP(ac)
Definition: ED_anim_api.h:431
@ ANIMFILTER_DATA_VISIBLE
Definition: ED_anim_api.h:295
@ ANIMFILTER_LIST_VISIBLE
Definition: ED_anim_api.h:298
@ ANIMFILTER_LIST_CHANNELS
Definition: ED_anim_api.h:303
@ ANIMFILTER_NODUPLIS
Definition: ED_anim_api.h:328
@ BEZT_OK_CHANNEL_CIRCLE
@ BEZT_OK_FRAMERANGE
@ BEZT_OK_FRAME
@ BEZT_OK_SELECTED
@ BEZT_OK_CHANNEL_LASSO
@ KED_F1_NLA_UNMAP
@ KED_F2_NLA_UNMAP
short(* KeyframeEditFunc)(KeyframeEditData *ked, struct BezTriple *bezt)
@ SELMAP_MORE
@ SELMAP_LESS
@ SELECT_INVERT
@ SELECT_SUBTRACT
@ SELECT_REPLACE
@ SELECT_ADD
void ED_masklayer_frame_select_set(struct MaskLayer *mask_layer, short mode)
void ED_mask_select_frames(struct MaskLayer *mask_layer, short select_mode)
void ED_masklayer_frames_select_region(struct KeyframeEditData *ked, struct MaskLayer *mask_layer, short tool, short select_mode)
void ED_masklayer_frames_select_box(struct MaskLayer *mask_layer, float min, float max, short select_mode)
void ED_mask_select_frame(struct MaskLayer *mask_layer, int selx, short select_mode)
bool ED_masklayer_frame_select_check(struct MaskLayer *mask_layer)
bool ED_operator_action_active(struct bContext *C)
Definition: screen_ops.c:282
#define SEL_OP_USE_PRE_DESELECT(sel_op)
@ SEL_SELECT
@ SEL_INVERT
@ SEL_DESELECT
@ SEL_TOGGLE
eSelectOp ED_select_op_modal(const eSelectOp sel_op, const bool is_first)
Definition: select_utils.c:77
eSelectOp
@ SEL_OP_SUB
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
Read Guarded memory(de)allocation.
@ PROP_SKIP_SAVE
Definition: RNA_types.h:204
#define C
Definition: RandGen.cpp:39
void UI_view2d_listview_view_to_cell(float columnwidth, float rowheight, float startx, float starty, float viewx, float viewy, int *column, int *row)
Definition: view2d.c:1623
void UI_view2d_region_to_view_rctf(const struct View2D *v2d, const struct rctf *rect_src, struct rctf *rect_dst) ATTR_NONNULL()
void UI_view2d_region_to_view(const struct View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
float UI_view2d_region_to_view_x(const struct View2D *v2d, float x)
Definition: view2d.c:1659
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define ND_DATA
Definition: WM_types.h:408
#define NC_ANIMATION
Definition: WM_types.h:289
#define NA_EDITED
Definition: WM_types.h:462
#define NC_GPENCIL
Definition: WM_types.h:300
#define ND_KEYFRAME
Definition: WM_types.h:394
#define ND_ANIMCHAN
Definition: WM_types.h:396
#define NA_SELECTED
Definition: WM_types.h:467
@ ACTKEYS_LRSEL_TEST
Definition: action_intern.h:67
@ ACTKEYS_LRSEL_LEFT
Definition: action_intern.h:68
@ ACTKEYS_LRSEL_RIGHT
Definition: action_intern.h:69
@ ACTKEYS_COLUMNSEL_CFRA
Definition: action_intern.h:75
@ ACTKEYS_COLUMNSEL_MARKERS_BETWEEN
Definition: action_intern.h:77
@ ACTKEYS_COLUMNSEL_MARKERS_COLUMN
Definition: action_intern.h:76
@ ACTKEYS_COLUMNSEL_KEYS
Definition: action_intern.h:74
static void deselect_action_keys(bAnimContext *ac, short test, short sel)
static bool actkeys_is_key_at_position(bAnimContext *ac, float region_x, float region_y)
static int actkeys_box_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void ACTION_OT_select_column(wmOperatorType *ot)
static void box_select_elem(BoxSelectData *sel_data, bAnimListElem *ale, float xmin, float xmax, bool summary)
struct BoxSelectData BoxSelectData
void ACTION_OT_select_less(wmOperatorType *ot)
static void actkeys_mselect_channel_only(bAnimContext *ac, bAnimListElem *ale, short select_mode)
static int actkeys_clickselect_exec(bContext *C, wmOperator *op)
static int actkeys_box_select_exec(bContext *C, wmOperator *op)
static void actkeys_list_element_to_keylist(bAnimContext *ac, DLRBT_Tree *anim_keys, bAnimListElem *ale)
Definition: action_select.c:95
static int actkeys_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
static int actkeys_columnselect_exec(bContext *C, wmOperator *op)
static void region_select_action_keys(bAnimContext *ac, const rctf *rectf_view, short mode, short selectmode, void *data)
static int action_circle_select_exec(bContext *C, wmOperator *op)
static const EnumPropertyItem prop_actkeys_leftright_select_types[]
static void actkeys_select_leftright(bAnimContext *ac, short leftright, short select_mode)
static void region_select_elem(RegionSelectData *sel_data, bAnimListElem *ale, bool summary)
static void actkeys_find_key_at_position(bAnimContext *ac, int filter, float region_x, float region_y, bAnimListElem **r_ale, float *r_selx, float *r_frame, bool *r_found, bool *r_is_selected)
static int actkeys_select_leftright_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int actkeys_lassoselect_exec(bContext *C, wmOperator *op)
static int mouse_action_keys(bAnimContext *ac, const int mval[2], short select_mode, const bool deselect_all, const bool column, const bool same_channel, bool wait_to_deselect_others)
void ACTION_OT_select_all(wmOperatorType *ot)
static bAnimListElem * actkeys_find_list_element_at_position(bAnimContext *ac, int filter, float region_x, float region_y)
Definition: action_select.c:69
static int actkeys_deselectall_exec(bContext *C, wmOperator *op)
void ACTION_OT_select_lasso(wmOperatorType *ot)
void ACTION_OT_select_leftright(wmOperatorType *ot)
static void markers_selectkeys_between(bAnimContext *ac)
static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float selx)
static void columnselect_action_keys(bAnimContext *ac, short mode)
static void select_moreless_action_keys(bAnimContext *ac, short mode)
static void actkeys_mselect_single(bAnimContext *ac, bAnimListElem *ale, short select_mode, float selx)
static void box_select_action(bAnimContext *ac, const rcti rect, short mode, short selectmode)
@ ACTKEYS_BORDERSEL_ALLKEYS
@ ACTKEYS_BORDERSEL_CHANNELS
@ ACTKEYS_BORDERSEL_FRAMERANGE
void ACTION_OT_select_linked(wmOperatorType *ot)
static void actkeys_find_key_in_list_element(bAnimContext *ac, bAnimListElem *ale, float region_x, float *r_selx, float *r_frame, bool *r_found, bool *r_is_selected)
static int actkeys_select_leftright_exec(bContext *C, wmOperator *op)
void ACTION_OT_select_box(wmOperatorType *ot)
struct RegionSelectData RegionSelectData
void ACTION_OT_select_circle(wmOperatorType *ot)
void ACTION_OT_clickselect(wmOperatorType *ot)
static const EnumPropertyItem prop_column_select_types[]
static int actkeys_select_less_exec(bContext *C, wmOperator *UNUSED(op))
static int actkeys_select_more_exec(bContext *C, wmOperator *UNUSED(op))
void ACTION_OT_select_more(wmOperatorType *ot)
void ANIM_anim_channels_select_set(bAnimContext *ac, eAnimChannels_SetFlag sel)
void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datatype, eAnimFilter_Flags filter, void *channel_data, eAnim_ChannelType channel_type)
void ANIM_animdata_freelist(ListBase *anim_data)
Definition: anim_deps.c:425
void ANIM_animdata_update(bAnimContext *ac, ListBase *anim_data)
Definition: anim_deps.c:330
AnimData * ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale)
Definition: anim_draw.c:178
void ANIM_nla_mapping_apply_fcurve(AnimData *adt, FCurve *fcu, bool restore, bool only_keys)
Definition: anim_draw.c:257
bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
Definition: anim_filter.c:405
size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, eAnimFilter_Flags filter_mode, void *data, eAnimCont_Types datatype)
Definition: anim_filter.c:3442
void ED_markers_make_cfra_list(ListBase *markers, ListBase *lb, short only_sel)
Definition: anim_markers.c:330
void ED_markers_get_minmax(ListBase *markers, short sel, float *r_first, float *r_last)
Definition: anim_markers.c:199
ListBase * ED_animcontext_get_markers(const bAnimContext *ac)
Definition: anim_markers.c:109
#define SELECT
Scene scene
void ED_gpencil_layer_frame_select_set(bGPDlayer *gpl, short mode)
void ED_gpencil_select_frames(bGPDlayer *gpl, short select_mode)
void ED_gpencil_select_frame(bGPDlayer *gpl, int selx, short select_mode)
void ED_gpencil_layer_frames_select_region(KeyframeEditData *ked, bGPDlayer *gpl, short tool, short select_mode)
void ED_gpencil_layer_frames_select_box(bGPDlayer *gpl, float min, float max, short select_mode)
void ED_gpencil_layer_make_cfra_list(bGPDlayer *gpl, ListBase *elems, bool onlysel)
bool ED_gpencil_layer_frame_select_check(bGPDlayer *gpl)
DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
const vector< Marker > & markers
void scene_to_keylist(bDopeSheet *ads, Scene *sce, DLRBT_Tree *keys, int saction_flag)
void agroup_to_keylist(AnimData *adt, bActionGroup *agrp, DLRBT_Tree *keys, int saction_flag)
void mask_to_keylist(bDopeSheet *UNUSED(ads), MaskLayer *masklay, DLRBT_Tree *keys)
void action_to_keylist(AnimData *adt, bAction *act, DLRBT_Tree *keys, int saction_flag)
void summary_to_keylist(bAnimContext *ac, DLRBT_Tree *keys, int saction_flag)
void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, int saction_flag)
void gpl_to_keylist(bDopeSheet *UNUSED(ads), bGPDlayer *gpl, DLRBT_Tree *keys)
void fcurve_to_keylist(AnimData *adt, FCurve *fcu, DLRBT_Tree *keys, int saction_flag)
short bezt_selmap_flush(KeyframeEditData *ked, BezTriple *bezt)
KeyframeEditFunc ANIM_editkeyframes_select(short selectmode)
short bezt_to_cfraelem(KeyframeEditData *ked, BezTriple *bezt)
KeyframeEditFunc ANIM_editkeyframes_buildselmap(short mode)
short ANIM_animchannel_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, bAnimListElem *ale, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
short ANIM_fcurve_keyframes_loop(KeyframeEditData *ked, FCurve *fcu, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
KeyframeEditFunc ANIM_editkeyframes_ok(short mode)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6308
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:6413
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3481
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1512
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3771
#define min(a, b)
Definition: sort.c:51
KeyframeEditFunc select_cb
KeyframeEditFunc ok_cb
KeyframeEditData ked
bAnimContext * ac
float cfra
Definition: BKE_fcurve.h:56
struct CfraElem * next
Definition: BKE_fcurve.h:55
void * root
Definition: BLI_dlrbTree.h:69
BezTriple * bezt
short flag
unsigned int totvert
eKeyframeIterFlags iterflags
void * first
Definition: DNA_listBase.h:47
struct MaskLayer * next
KeyframeEditFunc ok_cb
bAnimContext * ac
KeyframeEditFunc select_cb
KeyframeEditData ked
unsigned int flag
struct TimeMarker * next
ListBase * markers
Definition: ED_anim_api.h:105
struct ARegion * region
Definition: ED_anim_api.h:89
struct Scene * scene
Definition: ED_anim_api.h:97
struct bDopeSheet * ads
Definition: ED_anim_api.h:92
short datatype
Definition: ED_anim_api.h:75
void * data
Definition: ED_anim_api.h:73
struct SpaceLink * sl
Definition: ED_anim_api.h:87
struct bAnimListElem * next
Definition: ED_anim_api.h:135
void * key_data
Definition: ED_anim_api.h:154
struct bAnimListElem * prev
Definition: ED_anim_api.h:135
struct ID * id
Definition: ED_anim_api.h:168
struct bGPDlayer * next
ListBase layers
float xmax
Definition: DNA_vec_types.h:85
float xmin
Definition: DNA_vec_types.h:85
float ymax
Definition: DNA_vec_types.h:86
float ymin
Definition: DNA_vec_types.h:86
int ymin
Definition: DNA_vec_types.h:80
int ymax
Definition: DNA_vec_types.h:80
int xmin
Definition: DNA_vec_types.h:79
int xmax
Definition: DNA_vec_types.h:79
int mval[2]
Definition: WM_types.h:583
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:768
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:760
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
PropertyRNA * prop
Definition: WM_types.h:814
struct PointerRNA * ptr
float max
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
void WM_main_add_notifier(unsigned int type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition: wm_files.c:3156
bool WM_gesture_is_modal_first(const wmGesture *gesture)
Definition: wm_gesture.c:124
void WM_gesture_box_cancel(bContext *C, wmOperator *op)
int WM_gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_circle_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void WM_gesture_circle_cancel(bContext *C, wmOperator *op)
int WM_gesture_box_modal(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event)
void WM_gesture_lasso_cancel(bContext *C, wmOperator *op)
int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const int(* WM_gesture_lasso_path_to_array(bContext *UNUSED(C), wmOperator *op, int *r_mcoords_len))[2]
void WM_operator_properties_border_to_rcti(struct wmOperator *op, rcti *rect)
void WM_operator_properties_gesture_box(wmOperatorType *ot)
void WM_operator_properties_select_operation_simple(wmOperatorType *ot)
void WM_operator_properties_generic_select(wmOperatorType *ot)
void WM_operator_properties_gesture_lasso(wmOperatorType *ot)
void WM_operator_properties_gesture_circle(wmOperatorType *ot)
void WM_operator_properties_select_all(wmOperatorType *ot)
int WM_generic_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: wm_operators.c:905
int WM_generic_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
Definition: wm_operators.c:838