Blender  V3.3
action_select.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2008 Blender Foundation. */
3 
8 #include <float.h>
9 #include <math.h>
10 #include <stdlib.h>
11 #include <string.h>
12 
13 #include "MEM_guardedalloc.h"
14 
15 #include "BLI_blenlib.h"
16 #include "BLI_dlrbTree.h"
17 #include "BLI_lasso_2d.h"
18 #include "BLI_utildefines.h"
19 
20 #include "DNA_anim_types.h"
21 #include "DNA_gpencil_types.h"
22 #include "DNA_mask_types.h"
23 #include "DNA_object_types.h"
24 #include "DNA_scene_types.h"
25 
26 #include "RNA_access.h"
27 #include "RNA_define.h"
28 
29 #include "BKE_context.h"
30 #include "BKE_fcurve.h"
31 #include "BKE_gpencil.h"
32 #include "BKE_nla.h"
33 
34 #include "UI_interface.h"
35 #include "UI_view2d.h"
36 
37 #include "ED_anim_api.h"
38 #include "ED_gpencil.h"
39 #include "ED_keyframes_edit.h"
40 #include "ED_keyframes_keylist.h"
41 #include "ED_markers.h"
42 #include "ED_mask.h"
43 #include "ED_screen.h"
44 #include "ED_select_utils.h"
45 
46 #include "WM_api.h"
47 #include "WM_types.h"
48 
49 #include "action_intern.h"
50 
51 /* ************************************************************************** */
52 /* KEYFRAMES STUFF */
53 
55  int filter,
56  float region_x,
57  float region_y)
58 {
59  View2D *v2d = &ac->region->v2d;
60 
61  float view_x, view_y;
62  int channel_index;
63  UI_view2d_region_to_view(v2d, region_x, region_y, &view_x, &view_y);
65  0, ACHANNEL_STEP(ac), 0, ACHANNEL_FIRST_TOP(ac), view_x, view_y, NULL, &channel_index);
66 
67  ListBase anim_data = {NULL, NULL};
68  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
69 
70  bAnimListElem *ale = BLI_findlink(&anim_data, channel_index);
71  if (ale != NULL) {
72  BLI_remlink(&anim_data, ale);
73  ale->next = ale->prev = NULL;
74  }
75  ANIM_animdata_freelist(&anim_data);
76 
77  return ale;
78 }
79 
81  struct AnimKeylist *keylist,
82  bAnimListElem *ale)
83 {
84  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
85 
86  bDopeSheet *ads = NULL;
88  ads = ac->data;
89  }
90 
91  if (ale->key_data) {
92  switch (ale->datatype) {
93  case ALE_SCE: {
94  Scene *scene = (Scene *)ale->key_data;
95  scene_to_keylist(ads, scene, keylist, 0);
96  break;
97  }
98  case ALE_OB: {
99  Object *ob = (Object *)ale->key_data;
100  ob_to_keylist(ads, ob, keylist, 0);
101  break;
102  }
103  case ALE_ACT: {
104  bAction *act = (bAction *)ale->key_data;
105  action_to_keylist(adt, act, keylist, 0);
106  break;
107  }
108  case ALE_FCURVE: {
109  FCurve *fcu = (FCurve *)ale->key_data;
110  fcurve_to_keylist(adt, fcu, keylist, 0);
111  break;
112  }
113  }
114  }
115  else if (ale->type == ANIMTYPE_SUMMARY) {
116  /* dopesheet summary covers everything */
117  summary_to_keylist(ac, keylist, 0);
118  }
119  else if (ale->type == ANIMTYPE_GROUP) {
120  /* TODO: why don't we just give groups key_data too? */
121  bActionGroup *agrp = (bActionGroup *)ale->data;
122  agroup_to_keylist(adt, agrp, keylist, 0);
123  }
124  else if (ale->type == ANIMTYPE_GPLAYER) {
125  /* TODO: why don't we just give gplayers key_data too? */
126  bGPDlayer *gpl = (bGPDlayer *)ale->data;
127  gpl_to_keylist(ads, gpl, keylist);
128  }
129  else if (ale->type == ANIMTYPE_MASKLAYER) {
130  /* TODO: why don't we just give masklayers key_data too? */
131  MaskLayer *masklay = (MaskLayer *)ale->data;
132  mask_to_keylist(ads, masklay, keylist);
133  }
134 }
135 
137  bAnimListElem *ale,
138  float region_x,
139  float *r_selx,
140  float *r_frame,
141  bool *r_found,
142  bool *r_is_selected)
143 {
144  *r_found = false;
145 
146  View2D *v2d = &ac->region->v2d;
147 
148  struct AnimKeylist *keylist = ED_keylist_create();
149  actkeys_list_element_to_keylist(ac, keylist, ale);
151 
152  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
153 
154  /* standard channel height (to allow for some slop) */
155  float key_hsize = ACHANNEL_HEIGHT(ac) * 0.8f;
156  /* half-size (for either side), but rounded up to nearest int (for easier targeting) */
157  key_hsize = roundf(key_hsize / 2.0f);
158 
159  const Range2f range = {UI_view2d_region_to_view_x(v2d, region_x - (int)key_hsize),
160  UI_view2d_region_to_view_x(v2d, region_x + (int)key_hsize)};
161  const ActKeyColumn *ak = ED_keylist_find_any_between(keylist, range);
162  if (ak) {
163 
164  /* set the frame to use, and apply inverse-correction for NLA-mapping
165  * so that the frame will get selected by the selection functions without
166  * requiring to map each frame once again...
167  */
169  *r_frame = ak->cfra;
170  *r_found = true;
171  *r_is_selected = (ak->sel & SELECT) != 0;
172  }
173 
174  /* cleanup temporary lists */
175  ED_keylist_free(keylist);
176 }
177 
179  int filter,
180  float region_x,
181  float region_y,
182  bAnimListElem **r_ale,
183  float *r_selx,
184  float *r_frame,
185  bool *r_found,
186  bool *r_is_selected)
187 
188 {
189  *r_found = false;
190  *r_ale = actkeys_find_list_element_at_position(ac, filter, region_x, region_y);
191 
192  if (*r_ale != NULL) {
194  ac, *r_ale, region_x, r_selx, r_frame, r_found, r_is_selected);
195  }
196 }
197 
198 static bool actkeys_is_key_at_position(bAnimContext *ac, float region_x, float region_y)
199 {
200  bAnimListElem *ale;
201  float selx, frame;
202  bool found;
203  bool is_selected;
204 
207  ac, filter, region_x, region_y, &ale, &selx, &frame, &found, &is_selected);
208 
209  if (ale != NULL) {
210  MEM_freeN(ale);
211  }
212  return found;
213 }
214 
215 /* ******************** Deselect All Operator ***************************** */
216 /* This operator works in one of three ways:
217  * 1) (de)select all (AKEY) - test if select all or deselect all
218  * 2) invert all (CTRL-IKEY) - invert selection of all keyframes
219  * 3) (de)select all - no testing is done; only for use internal tools as normal function...
220  */
221 
222 /* Deselects keyframes in the action editor
223  * - This is called by the deselect all operator, as well as other ones!
224  *
225  * - test: check if select or deselect all
226  * - sel: how to select keyframes (SELECT_*)
227  */
228 static void deselect_action_keys(bAnimContext *ac, short test, short sel)
229 {
230  ListBase anim_data = {NULL, NULL};
231  bAnimListElem *ale;
232  int filter;
233 
234  KeyframeEditData ked = {{NULL}};
235  KeyframeEditFunc test_cb, sel_cb;
236 
237  /* determine type-based settings */
239 
240  /* filter data */
241  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
242 
243  /* init BezTriple looping data */
245 
246  /* See if we should be selecting or deselecting */
247  if (test) {
248  for (ale = anim_data.first; ale; ale = ale->next) {
249  if (ale->type == ANIMTYPE_GPLAYER) {
251  sel = SELECT_SUBTRACT;
252  break;
253  }
254  }
255  else if (ale->type == ANIMTYPE_MASKLAYER) {
257  sel = SELECT_SUBTRACT;
258  break;
259  }
260  }
261  else {
262  if (ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, test_cb, NULL)) {
263  sel = SELECT_SUBTRACT;
264  break;
265  }
266  }
267  }
268  }
269 
270  /* convert sel to selectmode, and use that to get editor */
271  sel_cb = ANIM_editkeyframes_select(sel);
272 
273  /* Now set the flags */
274  for (ale = anim_data.first; ale; ale = ale->next) {
275  if (ale->type == ANIMTYPE_GPLAYER) {
277  ale->update |= ANIM_UPDATE_DEPS;
278  }
279  else if (ale->type == ANIMTYPE_MASKLAYER) {
281  }
282  else {
283  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL);
284  }
285  }
286 
287  /* Cleanup */
288  ANIM_animdata_update(ac, &anim_data);
289  ANIM_animdata_freelist(&anim_data);
290 }
291 
292 /* ------------------- */
293 
295 {
296  bAnimContext ac;
297 
298  /* get editor data */
299  if (ANIM_animdata_get_context(C, &ac) == 0) {
300  return OPERATOR_CANCELLED;
301  }
302 
303  /* 'standard' behavior - check if selected, then apply relevant selection */
304  const int action = RNA_enum_get(op->ptr, "action");
305  switch (action) {
306  case SEL_TOGGLE:
308  break;
309  case SEL_SELECT:
311  break;
312  case SEL_DESELECT:
314  break;
315  case SEL_INVERT:
317  break;
318  default:
319  BLI_assert(0);
320  break;
321  }
322 
323  /* set notifier that keyframe selection have changed */
327  }
328  return OPERATOR_FINISHED;
329 }
330 
332 {
333  /* identifiers */
334  ot->name = "Select All";
335  ot->idname = "ACTION_OT_select_all";
336  ot->description = "Toggle selection of all keyframes";
337 
338  /* api callbacks */
341 
342  /* flags */
344 
345  /* properties */
347 }
348 
349 /* ******************** Box Select Operator **************************** */
359 /* defines for box_select mode */
360 enum {
364 } /*eActKeys_BoxSelect_Mode*/;
365 
366 typedef struct BoxSelectData {
368  short selectmode;
369 
373 
374 static void box_select_elem(
375  BoxSelectData *sel_data, bAnimListElem *ale, float xmin, float xmax, bool summary)
376 {
377  bAnimContext *ac = sel_data->ac;
378 
379  switch (ale->type) {
380 #if 0 /* XXX: Keyframes are not currently shown here */
381  case ANIMTYPE_GPDATABLOCK: {
382  bGPdata *gpd = ale->data;
383  bGPDlayer *gpl;
384  for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
385  ED_gpencil_layer_frames_select_box(gpl, xmin, xmax, data->selectmode);
386  }
387  ale->update |= ANIM_UPDATE_DEPS;
388  break;
389  }
390 #endif
391  case ANIMTYPE_GPLAYER: {
392  ED_gpencil_layer_frames_select_box(ale->data, xmin, xmax, sel_data->selectmode);
393  ale->update |= ANIM_UPDATE_DEPS;
394  break;
395  }
396  case ANIMTYPE_MASKDATABLOCK: {
397  Mask *mask = ale->data;
398  MaskLayer *masklay;
399  for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
400  ED_masklayer_frames_select_box(masklay, xmin, xmax, sel_data->selectmode);
401  }
402  break;
403  }
404  case ANIMTYPE_MASKLAYER: {
405  ED_masklayer_frames_select_box(ale->data, xmin, xmax, sel_data->selectmode);
406  break;
407  }
408  default: {
409  if (summary) {
410  break;
411  }
412 
413  if (ale->type == ANIMTYPE_SUMMARY) {
414  ListBase anim_data = {NULL, NULL};
415  ANIM_animdata_filter(ac, &anim_data, ANIMFILTER_DATA_VISIBLE, ac->data, ac->datatype);
416 
417  LISTBASE_FOREACH (bAnimListElem *, ale2, &anim_data) {
418  box_select_elem(sel_data, ale2, xmin, xmax, true);
419  }
420 
421  ANIM_animdata_update(ac, &anim_data);
422  ANIM_animdata_freelist(&anim_data);
423  }
424 
427  &sel_data->ked, ac->ads, ale, sel_data->ok_cb, sel_data->select_cb, NULL);
428  }
429  }
430  }
431 }
432 
433 static void box_select_action(bAnimContext *ac, const rcti rect, short mode, short selectmode)
434 {
435  ListBase anim_data = {NULL, NULL};
436  bAnimListElem *ale;
437  int filter;
438 
439  BoxSelectData sel_data = {.ac = ac, .selectmode = selectmode};
440  View2D *v2d = &ac->region->v2d;
441  rctf rectf;
442 
443  /* Convert mouse coordinates to frame ranges and channel
444  * coordinates corrected for view pan/zoom. */
445  UI_view2d_region_to_view(v2d, rect.xmin, rect.ymin + 2, &rectf.xmin, &rectf.ymin);
446  UI_view2d_region_to_view(v2d, rect.xmax, rect.ymax - 2, &rectf.xmax, &rectf.ymax);
447 
448  /* filter data */
450  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
451 
452  /* Get beztriple editing/validation funcs. */
453  sel_data.select_cb = ANIM_editkeyframes_select(selectmode);
454 
457  }
458  else {
459  sel_data.ok_cb = NULL;
460  }
461 
462  /* init editing data */
463  memset(&sel_data.ked, 0, sizeof(KeyframeEditData));
464 
465  float ymax = ACHANNEL_FIRST_TOP(ac);
466 
467  /* loop over data, doing box select */
468  for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac)) {
469  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
470 
471  /* get new vertical minimum extent of channel */
472  float ymin = ymax - ACHANNEL_STEP(ac);
473 
474  /* set horizontal range (if applicable) */
476  /* if channel is mapped in NLA, apply correction */
477  if (adt) {
479  sel_data.ked.f1 = BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP);
480  sel_data.ked.f2 = BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP);
481  }
482  else {
483  sel_data.ked.iterflags |= (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP); /* for summary tracks */
484  sel_data.ked.f1 = rectf.xmin;
485  sel_data.ked.f2 = rectf.xmax;
486  }
487  }
488 
489  /* perform vertical suitability check (if applicable) */
490  if ((mode == ACTKEYS_BORDERSEL_FRAMERANGE) || !((ymax < rectf.ymin) || (ymin > rectf.ymax))) {
491  box_select_elem(&sel_data, ale, rectf.xmin, rectf.xmax, false);
492  }
493  }
494 
495  /* cleanup */
496  ANIM_animdata_update(ac, &anim_data);
497  ANIM_animdata_freelist(&anim_data);
498 }
499 
500 /* ------------------- */
501 
502 static int actkeys_box_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
503 {
504  bAnimContext ac;
505  if (ANIM_animdata_get_context(C, &ac) == 0) {
506  return OPERATOR_CANCELLED;
507  }
508 
509  bool tweak = RNA_boolean_get(op->ptr, "tweak");
510  if (tweak) {
511  int mval[2];
512  WM_event_drag_start_mval(event, ac.region, mval);
513  if (actkeys_is_key_at_position(&ac, mval[0], mval[1])) {
515  }
516  }
517 
518  return WM_gesture_box_invoke(C, op, event);
519 }
520 
522 {
523  bAnimContext ac;
524  rcti rect;
525  short mode = 0;
526 
527  /* get editor data */
528  if (ANIM_animdata_get_context(C, &ac) == 0) {
529  return OPERATOR_CANCELLED;
530  }
531 
532  const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
533  const int selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
534  if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
536  }
537 
538  /* get settings from operator */
540 
541  /* selection 'mode' depends on whether box_select region only matters on one axis */
542  if (RNA_boolean_get(op->ptr, "axis_range")) {
543  /* Mode depends on which axis of the range is larger to determine which axis to use:
544  * - checking this in region-space is fine,
545  * as it's fundamentally still going to be a different rect size.
546  * - the frame-range select option is favored over the channel one (x over y),
547  * as frame-range one is often used for tweaking timing when "blocking",
548  * while channels is not that useful...
549  */
550  if (BLI_rcti_size_x(&rect) >= BLI_rcti_size_y(&rect)) {
552  }
553  else {
555  }
556  }
557  else {
559  }
560 
561  /* apply box_select action */
562  box_select_action(&ac, rect, mode, selectmode);
563 
564  /* set notifier that keyframe selection have changed */
568  }
569  return OPERATOR_FINISHED;
570 }
571 
573 {
574  /* identifiers */
575  ot->name = "Box Select";
576  ot->idname = "ACTION_OT_select_box";
577  ot->description = "Select all keyframes within the specified region";
578 
579  /* api callbacks */
584 
586 
587  /* flags */
589 
590  /* rna */
591  ot->prop = RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
592 
593  /* properties */
596 
598  ot->srna, "tweak", 0, "Tweak", "Operator has been activated using a click-drag event");
600 }
601 
602 /* ******************** Region Select Operators ***************************** */
603 /* "Region Select" operators include the Lasso and Circle Select operators.
604  * These two ended up being lumped together, as it was easier in the
605  * original Graph Editor implementation of these to do it this way.
606  */
607 
608 typedef struct RegionSelectData {
610  short mode;
611  short selectmode;
612 
616 
617 static void region_select_elem(RegionSelectData *sel_data, bAnimListElem *ale, bool summary)
618 {
619  bAnimContext *ac = sel_data->ac;
620 
621  switch (ale->type) {
622 #if 0 /* XXX: Keyframes are not currently shown here */
623  case ANIMTYPE_GPDATABLOCK: {
624  bGPdata *gpd = ale->data;
625  bGPDlayer *gpl;
626  for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
627  ED_gpencil_layer_frames_select_region(&rdata->ked, ale->data, rdata->mode, rdata->selectmode);
628  }
629  break;
630  }
631 #endif
632  case ANIMTYPE_GPLAYER: {
634  &sel_data->ked, ale->data, sel_data->mode, sel_data->selectmode);
635  ale->update |= ANIM_UPDATE_DEPS;
636  break;
637  }
638  case ANIMTYPE_MASKDATABLOCK: {
639  Mask *mask = ale->data;
640  MaskLayer *masklay;
641  for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
643  &sel_data->ked, masklay, sel_data->mode, sel_data->selectmode);
644  }
645  break;
646  }
647  case ANIMTYPE_MASKLAYER: {
649  &sel_data->ked, ale->data, sel_data->mode, sel_data->selectmode);
650  break;
651  }
652  default: {
653  if (summary) {
654  break;
655  }
656 
657  if (ale->type == ANIMTYPE_SUMMARY) {
658  ListBase anim_data = {NULL, NULL};
659  ANIM_animdata_filter(ac, &anim_data, ANIMFILTER_DATA_VISIBLE, ac->data, ac->datatype);
660 
661  LISTBASE_FOREACH (bAnimListElem *, ale2, &anim_data) {
662  region_select_elem(sel_data, ale2, true);
663  }
664 
665  ANIM_animdata_update(ac, &anim_data);
666  ANIM_animdata_freelist(&anim_data);
667  }
668 
671  &sel_data->ked, ac->ads, ale, sel_data->ok_cb, sel_data->select_cb, NULL);
672  }
673  }
674  }
675 }
676 
678  bAnimContext *ac, const rctf *rectf_view, short mode, short selectmode, void *data)
679 {
680  ListBase anim_data = {NULL, NULL};
681  bAnimListElem *ale;
682  int filter;
683 
684  RegionSelectData sel_data = {.ac = ac, .mode = mode, .selectmode = selectmode};
685  View2D *v2d = &ac->region->v2d;
686  rctf rectf, scaled_rectf;
687 
688  /* Convert mouse coordinates to frame ranges and channel
689  * coordinates corrected for view pan/zoom. */
690  UI_view2d_region_to_view_rctf(v2d, rectf_view, &rectf);
691 
692  /* filter data */
694  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
695 
696  /* Get beztriple editing/validation funcs. */
697  sel_data.select_cb = ANIM_editkeyframes_select(selectmode);
698  sel_data.ok_cb = ANIM_editkeyframes_ok(mode);
699 
700  /* init editing data */
701  memset(&sel_data.ked, 0, sizeof(KeyframeEditData));
702  if (mode == BEZT_OK_CHANNEL_LASSO) {
703  KeyframeEdit_LassoData *data_lasso = data;
704  data_lasso->rectf_scaled = &scaled_rectf;
705  sel_data.ked.data = data_lasso;
706  }
707  else if (mode == BEZT_OK_CHANNEL_CIRCLE) {
708  KeyframeEdit_CircleData *data_circle = data;
709  data_circle->rectf_scaled = &scaled_rectf;
710  sel_data.ked.data = data;
711  }
712  else {
713  sel_data.ked.data = &scaled_rectf;
714  }
715 
716  float ymax = ACHANNEL_FIRST_TOP(ac);
717 
718  /* loop over data, doing region select */
719  for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac)) {
720  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
721 
722  /* get new vertical minimum extent of channel */
723  float ymin = ymax - ACHANNEL_STEP(ac);
724 
725  /* compute midpoint of channel (used for testing if the key is in the region or not) */
726  sel_data.ked.channel_y = (ymin + ymax) / 2.0f;
727 
728  /* if channel is mapped in NLA, apply correction
729  * - Apply to the bounds being checked, not all the keyframe points,
730  * to avoid having scaling everything
731  * - Save result to the scaled_rect, which is all that these operators
732  * will read from
733  */
734  if (adt) {
736  sel_data.ked.f1 = BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP);
737  sel_data.ked.f2 = BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP);
738  }
739  else {
740  sel_data.ked.iterflags |= (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP); /* for summary tracks */
741  sel_data.ked.f1 = rectf.xmin;
742  sel_data.ked.f2 = rectf.xmax;
743  }
744 
745  /* Update values for scaled_rectf - which is used to compute the mapping in the callbacks
746  * NOTE: Since summary tracks need late-binding remapping, the callbacks may overwrite these
747  * with the properly remapped ked.f1/f2 values, when needed
748  */
749  scaled_rectf.xmin = sel_data.ked.f1;
750  scaled_rectf.xmax = sel_data.ked.f2;
751  scaled_rectf.ymin = ymin;
752  scaled_rectf.ymax = ymax;
753 
754  /* perform vertical suitability check (if applicable) */
755  if ((mode == ACTKEYS_BORDERSEL_FRAMERANGE) || !((ymax < rectf.ymin) || (ymin > rectf.ymax))) {
756  region_select_elem(&sel_data, ale, false);
757  }
758  }
759 
760  /* cleanup */
761  ANIM_animdata_update(ac, &anim_data);
762  ANIM_animdata_freelist(&anim_data);
763 }
764 
765 /* ----------------------------------- */
766 
768 {
769  bAnimContext ac;
770 
771  KeyframeEdit_LassoData data_lasso;
772  rcti rect;
773  rctf rect_fl;
774 
775  /* get editor data */
776  if (ANIM_animdata_get_context(C, &ac) == 0) {
777  return OPERATOR_CANCELLED;
778  }
779 
780  data_lasso.rectf_view = &rect_fl;
781  data_lasso.mcoords = WM_gesture_lasso_path_to_array(C, op, &data_lasso.mcoords_len);
782  if (data_lasso.mcoords == NULL) {
783  return OPERATOR_CANCELLED;
784  }
785 
786  const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
787  const int selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
788  if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
790  }
791 
792  /* get settings from operator */
793  BLI_lasso_boundbox(&rect, data_lasso.mcoords, data_lasso.mcoords_len);
794  BLI_rctf_rcti_copy(&rect_fl, &rect);
795 
796  /* apply box_select action */
797  region_select_action_keys(&ac, &rect_fl, BEZT_OK_CHANNEL_LASSO, selectmode, &data_lasso);
798 
799  MEM_freeN((void *)data_lasso.mcoords);
800 
801  /* send notifier that keyframe selection has changed */
805  }
806  return OPERATOR_FINISHED;
807 }
808 
810 {
811  /* identifiers */
812  ot->name = "Lasso Select";
813  ot->description = "Select keyframe points using lasso selection";
814  ot->idname = "ACTION_OT_select_lasso";
815 
816  /* api callbacks */
822 
823  /* flags */
825 
826  /* properties */
829 }
830 
831 /* ------------------- */
832 
834 {
835  bAnimContext ac;
836 
838  rctf rect_fl;
839 
840  float x = RNA_int_get(op->ptr, "x");
841  float y = RNA_int_get(op->ptr, "y");
842  float radius = RNA_int_get(op->ptr, "radius");
843 
844  /* get editor data */
845  if (ANIM_animdata_get_context(C, &ac) == 0) {
846  return OPERATOR_CANCELLED;
847  }
848 
849  const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"),
851  const short selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
852  if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
854  }
855 
856  data.mval[0] = x;
857  data.mval[1] = y;
858  data.radius_squared = radius * radius;
859  data.rectf_view = &rect_fl;
860 
861  rect_fl.xmin = x - radius;
862  rect_fl.xmax = x + radius;
863  rect_fl.ymin = y - radius;
864  rect_fl.ymax = y + radius;
865 
866  /* apply region select action */
867  region_select_action_keys(&ac, &rect_fl, BEZT_OK_CHANNEL_CIRCLE, selectmode, &data);
868 
869  /* send notifier that keyframe selection has changed */
873  }
874  return OPERATOR_FINISHED;
875 }
876 
878 {
879  ot->name = "Circle Select";
880  ot->description = "Select keyframe points using circle selection";
881  ot->idname = "ACTION_OT_select_circle";
882 
889 
890  /* flags */
891  ot->flag = OPTYPE_UNDO;
892 
893  /* properties */
896 }
897 
898 /* ******************** Column Select Operator **************************** */
899 /* This operator works in one of four ways:
900  * - 1) select all keyframes in the same frame as a selected one (KKEY)
901  * - 2) select all keyframes in the same frame as the current frame marker (CTRL-KKEY)
902  * - 3) select all keyframes in the same frame as a selected markers (SHIFT-KKEY)
903  * - 4) select all keyframes that occur between selected markers (ALT-KKEY)
904  */
905 
906 /* defines for column-select mode */
908  {ACTKEYS_COLUMNSEL_KEYS, "KEYS", 0, "On Selected Keyframes", ""},
909  {ACTKEYS_COLUMNSEL_CFRA, "CFRA", 0, "On Current Frame", ""},
910  {ACTKEYS_COLUMNSEL_MARKERS_COLUMN, "MARKERS_COLUMN", 0, "On Selected Markers", ""},
912  "MARKERS_BETWEEN",
913  0,
914  "Between Min/Max Selected Markers",
915  ""},
916  {0, NULL, 0, NULL, NULL},
917 };
918 
919 /* ------------------- */
920 
921 /* Selects all visible keyframes between the specified markers */
922 /* TODO(campbell): this is almost an _exact_ duplicate of a function of the same name in
923  * graph_select.c should de-duplicate. */
925 {
926  ListBase anim_data = {NULL, NULL};
927  bAnimListElem *ale;
928  int filter;
929 
930  KeyframeEditFunc ok_cb, select_cb;
931  KeyframeEditData ked = {{NULL}};
932  float min, max;
933 
934  /* get extreme markers */
935  ED_markers_get_minmax(ac->markers, 1, &min, &max);
936  min -= 0.5f;
937  max += 0.5f;
938 
939  /* get editing funcs + data */
942 
943  ked.f1 = min;
944  ked.f2 = max;
945 
946  /* filter data */
948  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
949 
950  /* select keys in-between */
951  for (ale = anim_data.first; ale; ale = ale->next) {
952  switch (ale->type) {
953  case ANIMTYPE_GPLAYER:
955  ale->update |= ANIM_UPDATE_DEPS;
956  break;
957 
958  case ANIMTYPE_MASKLAYER:
960  break;
961 
962  case ANIMTYPE_FCURVE: {
963  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
964  if (adt) {
965  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
966  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
967  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
968  }
969  else {
970  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
971  }
972  break;
973  }
974 
975  default:
976  BLI_assert_msg(false, "Keys cannot be selected into this animation type.");
977  }
978  }
979 
980  /* Cleanup */
981  ANIM_animdata_update(ac, &anim_data);
982  ANIM_animdata_freelist(&anim_data);
983 }
984 
985 /* Selects all visible keyframes in the same frames as the specified elements */
986 static void columnselect_action_keys(bAnimContext *ac, short mode)
987 {
988  ListBase anim_data = {NULL, NULL};
989  bAnimListElem *ale;
990  int filter;
991 
992  Scene *scene = ac->scene;
993  CfraElem *ce;
994  KeyframeEditFunc select_cb, ok_cb;
995  KeyframeEditData ked = {{NULL}};
996 
997  /* build list of columns */
998  switch (mode) {
999  case ACTKEYS_COLUMNSEL_KEYS: /* list of selected keys */
1000  if (ac->datatype == ANIMCONT_GPENCIL) {
1002  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1003 
1004  for (ale = anim_data.first; ale; ale = ale->next) {
1005  ED_gpencil_layer_make_cfra_list(ale->data, &ked.list, 1);
1006  }
1007  }
1008  else {
1010  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1011 
1012  for (ale = anim_data.first; ale; ale = ale->next) {
1013  if (ale->datatype == ALE_GPFRAME) {
1014  ED_gpencil_layer_make_cfra_list(ale->data, &ked.list, 1);
1015  }
1016  else {
1018  }
1019  }
1020  }
1021  ANIM_animdata_freelist(&anim_data);
1022  break;
1023 
1024  case ACTKEYS_COLUMNSEL_CFRA: /* current frame */
1025  /* make a single CfraElem for storing this */
1026  ce = MEM_callocN(sizeof(CfraElem), "cfraElem");
1027  BLI_addtail(&ked.list, ce);
1028 
1029  ce->cfra = (float)scene->r.cfra;
1030  break;
1031 
1032  case ACTKEYS_COLUMNSEL_MARKERS_COLUMN: /* list of selected markers */
1034  break;
1035 
1036  default: /* invalid option */
1037  return;
1038  }
1039 
1040  /* set up BezTriple edit callbacks */
1043 
1044  /* loop through all of the keys and select additional keyframes
1045  * based on the keys found to be selected above
1046  */
1048  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1049 
1050  for (ale = anim_data.first; ale; ale = ale->next) {
1051  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
1052 
1053  /* loop over cfraelems (stored in the KeyframeEditData->list)
1054  * - we need to do this here, as we can apply fewer NLA-mapping conversions
1055  */
1056  for (ce = ked.list.first; ce; ce = ce->next) {
1057  /* set frame for validation callback to refer to */
1058  if (adt) {
1060  }
1061  else {
1062  ked.f1 = ce->cfra;
1063  }
1064 
1065  /* select elements with frame number matching cfraelem */
1066  if (ale->type == ANIMTYPE_GPLAYER) {
1068  ale->update |= ANIM_UPDATE_DEPS;
1069  }
1070  else if (ale->type == ANIMTYPE_MASKLAYER) {
1072  }
1073  else {
1074  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
1075  }
1076  }
1077  }
1078 
1079  /* free elements */
1080  BLI_freelistN(&ked.list);
1081 
1082  ANIM_animdata_update(ac, &anim_data);
1083  ANIM_animdata_freelist(&anim_data);
1084 }
1085 
1086 /* ------------------- */
1087 
1089 {
1090  bAnimContext ac;
1091  short mode;
1092 
1093  /* get editor data */
1094  if (ANIM_animdata_get_context(C, &ac) == 0) {
1095  return OPERATOR_CANCELLED;
1096  }
1097 
1098  /* action to take depends on the mode */
1099  mode = RNA_enum_get(op->ptr, "mode");
1100 
1101  if (mode == ACTKEYS_COLUMNSEL_MARKERS_BETWEEN) {
1103  }
1104  else {
1105  columnselect_action_keys(&ac, mode);
1106  }
1107 
1108  /* set notifier that keyframe selection have changed */
1112  }
1113  return OPERATOR_FINISHED;
1114 }
1115 
1117 {
1118  /* identifiers */
1119  ot->name = "Select All";
1120  ot->idname = "ACTION_OT_select_column";
1121  ot->description = "Select all keyframes on the specified frame(s)";
1122 
1123  /* api callbacks */
1126 
1127  /* flags */
1129 
1130  /* props */
1131  ot->prop = RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", "");
1132 }
1133 
1134 /* ******************** Select Linked Operator *********************** */
1135 
1137 {
1138  bAnimContext ac;
1139 
1140  ListBase anim_data = {NULL, NULL};
1141  bAnimListElem *ale;
1142  int filter;
1143 
1146 
1147  /* get editor data */
1148  if (ANIM_animdata_get_context(C, &ac) == 0) {
1149  return OPERATOR_CANCELLED;
1150  }
1151 
1152  /* loop through all of the keys and select additional keyframes based on these */
1155  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1156 
1157  for (ale = anim_data.first; ale; ale = ale->next) {
1158  FCurve *fcu = (FCurve *)ale->key_data;
1159 
1160  /* check if anything selected? */
1161  if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, ok_cb, NULL)) {
1162  /* select every keyframe in this curve then */
1163  ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, sel_cb, NULL);
1164  }
1165  }
1166 
1167  /* Cleanup */
1168  ANIM_animdata_freelist(&anim_data);
1169 
1170  /* set notifier that keyframe selection has changed */
1174  }
1175  return OPERATOR_FINISHED;
1176 }
1177 
1179 {
1180  /* identifiers */
1181  ot->name = "Select Linked";
1182  ot->idname = "ACTION_OT_select_linked";
1183  ot->description = "Select keyframes occurring in the same F-Curves as selected ones";
1184 
1185  /* api callbacks */
1188 
1189  /* flags */
1191 }
1192 
1193 /* ******************** Select More/Less Operators *********************** */
1194 
1195 /* Common code to perform selection */
1196 static void select_moreless_action_keys(bAnimContext *ac, short mode)
1197 {
1198  ListBase anim_data = {NULL, NULL};
1199  bAnimListElem *ale;
1200  int filter;
1201 
1202  KeyframeEditData ked = {{NULL}};
1203  KeyframeEditFunc build_cb;
1204 
1205  /* init selmap building data */
1206  build_cb = ANIM_editkeyframes_buildselmap(mode);
1207 
1208  /* loop through all of the keys and select additional keyframes based on these */
1211  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1212 
1213  for (ale = anim_data.first; ale; ale = ale->next) {
1214 
1215  /* TODO: other types. */
1216  if (ale->datatype != ALE_FCURVE) {
1217  continue;
1218  }
1219 
1220  /* only continue if F-Curve has keyframes */
1221  FCurve *fcu = (FCurve *)ale->key_data;
1222  if (fcu->bezt == NULL) {
1223  continue;
1224  }
1225 
1226  /* build up map of whether F-Curve's keyframes should be selected or not */
1227  ked.data = MEM_callocN(fcu->totvert, "selmap actEdit more");
1228  ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, build_cb, NULL);
1229 
1230  /* based on this map, adjust the selection status of the keyframes */
1232 
1233  /* free the selmap used here */
1234  MEM_freeN(ked.data);
1235  ked.data = NULL;
1236  }
1237 
1238  /* Cleanup */
1239  ANIM_animdata_freelist(&anim_data);
1240 }
1241 
1242 /* ----------------- */
1243 
1245 {
1246  bAnimContext ac;
1247 
1248  /* get editor data */
1249  if (ANIM_animdata_get_context(C, &ac) == 0) {
1250  return OPERATOR_CANCELLED;
1251  }
1252 
1253  /* perform select changes */
1255 
1256  /* set notifier that keyframe selection has changed */
1260  }
1261  return OPERATOR_FINISHED;
1262 }
1263 
1265 {
1266  /* identifiers */
1267  ot->name = "Select More";
1268  ot->idname = "ACTION_OT_select_more";
1269  ot->description = "Select keyframes beside already selected ones";
1270 
1271  /* api callbacks */
1274 
1275  /* flags */
1277 }
1278 
1279 /* ----------------- */
1280 
1282 {
1283  bAnimContext ac;
1284 
1285  /* get editor data */
1286  if (ANIM_animdata_get_context(C, &ac) == 0) {
1287  return OPERATOR_CANCELLED;
1288  }
1289 
1290  /* perform select changes */
1292 
1293  /* set notifier that keyframe selection has changed */
1297  }
1298  return OPERATOR_FINISHED;
1299 }
1300 
1302 {
1303  /* identifiers */
1304  ot->name = "Select Less";
1305  ot->idname = "ACTION_OT_select_less";
1306  ot->description = "Deselect keyframes on ends of selection islands";
1307 
1308  /* api callbacks */
1311 
1312  /* flags */
1314 }
1315 
1316 /* ******************** Select Left/Right Operator ************************* */
1317 /* Select keyframes left/right of the current frame indicator */
1318 
1319 /* defines for left-right select tool */
1321  {ACTKEYS_LRSEL_TEST, "CHECK", 0, "Check if Select Left or Right", ""},
1322  {ACTKEYS_LRSEL_LEFT, "LEFT", 0, "Before Current Frame", ""},
1323  {ACTKEYS_LRSEL_RIGHT, "RIGHT", 0, "After Current Frame", ""},
1324  {0, NULL, 0, NULL, NULL},
1325 };
1326 
1327 /* --------------------------------- */
1328 
1329 static void actkeys_select_leftright(bAnimContext *ac, short leftright, short select_mode)
1330 {
1331  ListBase anim_data = {NULL, NULL};
1332  bAnimListElem *ale;
1333  int filter;
1334 
1335  KeyframeEditFunc ok_cb, select_cb;
1336  KeyframeEditData ked = {{NULL}};
1337  Scene *scene = ac->scene;
1338 
1339  /* if select mode is replace, deselect all keyframes (and channels) first */
1340  if (select_mode == SELECT_REPLACE) {
1341  select_mode = SELECT_ADD;
1342 
1343  /* - deselect all other keyframes, so that just the newly selected remain
1344  * - channels aren't deselected, since we don't re-select any as a consequence
1345  */
1347  }
1348 
1349  /* set callbacks and editing data */
1351  select_cb = ANIM_editkeyframes_select(select_mode);
1352 
1353  if (leftright == ACTKEYS_LRSEL_LEFT) {
1354  ked.f1 = MINAFRAMEF;
1355  ked.f2 = (float)(scene->r.cfra + 0.1f);
1356  }
1357  else {
1358  ked.f1 = (float)(scene->r.cfra - 0.1f);
1359  ked.f2 = MAXFRAMEF;
1360  }
1361 
1362  /* filter data */
1364  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1365 
1366  /* select keys */
1367  for (ale = anim_data.first; ale; ale = ale->next) {
1368  switch (ale->type) {
1369  case ANIMTYPE_GPLAYER:
1370  ED_gpencil_layer_frames_select_box(ale->data, ked.f1, ked.f2, select_mode);
1371  ale->update |= ANIM_UPDATE_DEPS;
1372  break;
1373 
1374  case ANIMTYPE_MASKLAYER:
1375  ED_masklayer_frames_select_box(ale->data, ked.f1, ked.f2, select_mode);
1376  break;
1377 
1378  case ANIMTYPE_FCURVE: {
1379  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
1380  if (adt) {
1381  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
1382  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
1383  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
1384  }
1385  else {
1386  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
1387  }
1388  break;
1389  }
1390 
1391  default:
1392  BLI_assert_msg(false, "Keys cannot be selected into this animation type.");
1393  }
1394  }
1395 
1396  /* Sync marker support */
1397  if (select_mode == SELECT_ADD) {
1398  SpaceAction *saction = (SpaceAction *)ac->sl;
1399 
1400  if ((saction) && (saction->flag & SACTION_MARKERS_MOVE)) {
1402  TimeMarker *marker;
1403 
1404  for (marker = markers->first; marker; marker = marker->next) {
1405  if (((leftright == ACTKEYS_LRSEL_LEFT) && (marker->frame < scene->r.cfra)) ||
1406  ((leftright == ACTKEYS_LRSEL_RIGHT) && (marker->frame >= scene->r.cfra))) {
1407  marker->flag |= SELECT;
1408  }
1409  else {
1410  marker->flag &= ~SELECT;
1411  }
1412  }
1413  }
1414  }
1415 
1416  /* Cleanup */
1417  ANIM_animdata_update(ac, &anim_data);
1418  ANIM_animdata_freelist(&anim_data);
1419 }
1420 
1421 /* ----------------- */
1422 
1424 {
1425  bAnimContext ac;
1426  short leftright = RNA_enum_get(op->ptr, "mode");
1427  short selectmode;
1428 
1429  /* get editor data */
1430  if (ANIM_animdata_get_context(C, &ac) == 0) {
1431  return OPERATOR_CANCELLED;
1432  }
1433 
1434  /* select mode is either replace (deselect all, then add) or add/extend */
1435  if (RNA_boolean_get(op->ptr, "extend")) {
1436  selectmode = SELECT_INVERT;
1437  }
1438  else {
1439  selectmode = SELECT_REPLACE;
1440  }
1441 
1442  /* if "test" mode is set, we don't have any info to set this with */
1443  if (leftright == ACTKEYS_LRSEL_TEST) {
1444  return OPERATOR_CANCELLED;
1445  }
1446 
1447  /* do the selecting now */
1448  actkeys_select_leftright(&ac, leftright, selectmode);
1449 
1450  /* set notifier that keyframe selection (and channels too) have changed */
1453 
1454  return OPERATOR_FINISHED;
1455 }
1456 
1458 {
1459  bAnimContext ac;
1460  short leftright = RNA_enum_get(op->ptr, "mode");
1461 
1462  /* get editor data */
1463  if (ANIM_animdata_get_context(C, &ac) == 0) {
1464  return OPERATOR_CANCELLED;
1465  }
1466 
1467  /* handle mode-based testing */
1468  if (leftright == ACTKEYS_LRSEL_TEST) {
1469  Scene *scene = ac.scene;
1470  ARegion *region = ac.region;
1471  View2D *v2d = &region->v2d;
1472  float x;
1473 
1474  /* determine which side of the current frame mouse is on */
1475  x = UI_view2d_region_to_view_x(v2d, event->mval[0]);
1476  if (x < scene->r.cfra) {
1477  RNA_enum_set(op->ptr, "mode", ACTKEYS_LRSEL_LEFT);
1478  }
1479  else {
1480  RNA_enum_set(op->ptr, "mode", ACTKEYS_LRSEL_RIGHT);
1481  }
1482  }
1483 
1484  /* perform selection */
1485  return actkeys_select_leftright_exec(C, op);
1486 }
1487 
1489 {
1490  PropertyRNA *prop;
1491 
1492  /* identifiers */
1493  ot->name = "Select Left/Right";
1494  ot->idname = "ACTION_OT_select_leftright";
1495  ot->description = "Select keyframes to the left or the right of the current frame";
1496 
1497  /* api callbacks */
1501 
1502  /* flags */
1504 
1505  /* properties */
1506  ot->prop = RNA_def_enum(
1509 
1510  prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
1512 }
1513 
1514 /* ******************** Mouse-Click Select Operator *********************** */
1515 /* This operator works in one of three ways:
1516  * - 1) keyframe under mouse - no special modifiers
1517  * - 2) all keyframes on the same side of current frame indicator as mouse - ALT modifier
1518  * - 3) column select all keyframes in frame under mouse - CTRL modifier
1519  * - 4) all keyframes in channel under mouse - CTRL+ALT modifiers
1520  *
1521  * In addition to these basic options, the SHIFT modifier can be used to toggle the
1522  * selection mode between replacing the selection (without) and inverting the selection (with).
1523  */
1524 
1525 /* ------------------- */
1526 
1527 /* option 1) select keyframe directly under mouse */
1529  bAnimListElem *ale,
1530  short select_mode,
1531  float selx)
1532 {
1533  KeyframeEditData ked = {{NULL}};
1534  KeyframeEditFunc select_cb, ok_cb;
1535 
1536  /* get functions for selecting keyframes */
1537  select_cb = ANIM_editkeyframes_select(select_mode);
1539  ked.f1 = selx;
1540  ked.iterflags |= KED_F1_NLA_UNMAP;
1541 
1542  /* select the nominated keyframe on the given frame */
1543  if (ale->type == ANIMTYPE_GPLAYER) {
1544  ED_gpencil_select_frame(ale->data, selx, select_mode);
1545  ale->update |= ANIM_UPDATE_DEPS;
1546  }
1547  else if (ale->type == ANIMTYPE_MASKLAYER) {
1548  ED_mask_select_frame(ale->data, selx, select_mode);
1549  }
1550  else {
1551  if (ale->type == ANIMTYPE_SUMMARY && ale->datatype == ALE_ALL) {
1552  ListBase anim_data = {NULL, NULL};
1553  int filter;
1554 
1556  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1557 
1558  /* Loop over all keys that are represented by this summary key. */
1559  LISTBASE_FOREACH (bAnimListElem *, ale2, &anim_data) {
1560  if (ale2->type == ANIMTYPE_GPLAYER) {
1561  ED_gpencil_select_frame(ale2->data, selx, select_mode);
1562  ale2->update |= ANIM_UPDATE_DEPS;
1563  }
1564  else if (ale2->type == ANIMTYPE_MASKLAYER) {
1565  ED_mask_select_frame(ale2->data, selx, select_mode);
1566  }
1567  }
1568 
1569  ANIM_animdata_update(ac, &anim_data);
1570  ANIM_animdata_freelist(&anim_data);
1571  }
1572 
1574  ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
1575  }
1576  }
1577 }
1578 
1579 /* Option 2) Selects all the keyframes on either side of the current frame
1580  * (depends on which side the mouse is on) */
1581 /* (see actkeys_select_leftright) */
1582 
1583 /* Option 3) Selects all visible keyframes in the same frame as the mouse click */
1584 static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float selx)
1585 {
1586  ListBase anim_data = {NULL, NULL};
1587  bAnimListElem *ale;
1588  int filter;
1589 
1590  KeyframeEditFunc select_cb, ok_cb;
1591  KeyframeEditData ked = {{NULL}};
1592 
1593  /* set up BezTriple edit callbacks */
1594  select_cb = ANIM_editkeyframes_select(select_mode);
1596 
1597  /* loop through all of the keys and select additional keyframes
1598  * based on the keys found to be selected above
1599  */
1601  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1602 
1603  for (ale = anim_data.first; ale; ale = ale->next) {
1604  /* select elements with frame number matching cfra */
1605  if (ale->type == ANIMTYPE_GPLAYER) {
1606  ED_gpencil_select_frame(ale->data, selx, select_mode);
1607  ale->update |= ANIM_UPDATE_DEPS;
1608  }
1609  else if (ale->type == ANIMTYPE_MASKLAYER) {
1610  ED_mask_select_frame(ale->data, selx, select_mode);
1611  }
1612  else {
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  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
1624  }
1625  }
1626 
1627  /* free elements */
1628  BLI_freelistN(&ked.list);
1629 
1630  ANIM_animdata_update(ac, &anim_data);
1631  ANIM_animdata_freelist(&anim_data);
1632 }
1633 
1634 /* option 4) select all keyframes in same channel */
1635 static void actkeys_mselect_channel_only(bAnimContext *ac, bAnimListElem *ale, short select_mode)
1636 {
1637  KeyframeEditFunc select_cb;
1638 
1639  /* get functions for selecting keyframes */
1640  select_cb = ANIM_editkeyframes_select(select_mode);
1641 
1642  /* select all keyframes in this channel */
1643  if (ale->type == ANIMTYPE_GPLAYER) {
1644  ED_gpencil_select_frames(ale->data, select_mode);
1645  ale->update = ANIM_UPDATE_DEPS;
1646  }
1647  else if (ale->type == ANIMTYPE_MASKLAYER) {
1648  ED_mask_select_frames(ale->data, select_mode);
1649  }
1650  else {
1651  if (ale->type == ANIMTYPE_SUMMARY && ale->datatype == ALE_ALL) {
1652  ListBase anim_data = {NULL, NULL};
1653  int filter;
1654 
1656  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1657 
1658  LISTBASE_FOREACH (bAnimListElem *, ale2, &anim_data) {
1659  if (ale2->type == ANIMTYPE_GPLAYER) {
1660  ED_gpencil_select_frames(ale2->data, select_mode);
1661  ale2->update |= ANIM_UPDATE_DEPS;
1662  }
1663  else if (ale2->type == ANIMTYPE_MASKLAYER) {
1664  ED_mask_select_frames(ale2->data, select_mode);
1665  }
1666  }
1667 
1668  ANIM_animdata_update(ac, &anim_data);
1669  ANIM_animdata_freelist(&anim_data);
1670  }
1671 
1673  ANIM_animchannel_keyframes_loop(NULL, ac->ads, ale, NULL, select_cb, NULL);
1674  }
1675  }
1676 }
1677 
1678 /* ------------------- */
1679 
1681  const int mval[2],
1682  short select_mode,
1683  const bool deselect_all,
1684  const bool column,
1685  const bool same_channel,
1686  bool wait_to_deselect_others)
1687 {
1689 
1690  bAnimListElem *ale = NULL;
1691  bool found = false;
1692  bool is_selected = false;
1693  float frame = 0.0f; /* frame of keyframe under mouse - NLA corrections not applied/included */
1694  float selx = 0.0f; /* frame of keyframe under mouse */
1695  int ret_value = OPERATOR_FINISHED;
1696 
1698  ac, filter, mval[0], mval[1], &ale, &selx, &frame, &found, &is_selected);
1699 
1700  if (select_mode != SELECT_REPLACE) {
1701  wait_to_deselect_others = false;
1702  }
1703 
1704  /* For replacing selection, if we have something to select, we have to clear existing selection.
1705  * The same goes if we found nothing to select, and deselect_all is true
1706  * (deselect on nothing behavior). */
1707  if ((select_mode == SELECT_REPLACE && found) || (!found && deselect_all)) {
1708  /* reset selection mode for next steps */
1709  select_mode = SELECT_ADD;
1710 
1711  /* Rather than deselecting others, users may want to drag to box-select (drag from empty space)
1712  * or tweak-translate an already selected item. If these cases may apply, delay deselection. */
1713  if (wait_to_deselect_others && (!found || is_selected)) {
1714  ret_value = OPERATOR_RUNNING_MODAL;
1715  }
1716  else {
1717  /* deselect all keyframes */
1719 
1720  /* highlight channel clicked on */
1722  /* deselect all other channels first */
1724 
1725  /* Highlight Action-Group or F-Curve? */
1726  if (ale != NULL && ale->data) {
1727  if (ale->type == ANIMTYPE_GROUP) {
1728  bActionGroup *agrp = ale->data;
1729 
1730  agrp->flag |= AGRP_SELECTED;
1732  }
1733  else if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
1734  FCurve *fcu = ale->data;
1735 
1736  fcu->flag |= FCURVE_SELECTED;
1737  ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type);
1738  }
1739  else if (ale->type == ANIMTYPE_GPLAYER) {
1740  bGPdata *gpd = (bGPdata *)ale->id;
1741  bGPDlayer *gpl = ale->data;
1742 
1744  }
1745  }
1746  }
1747  else if (ac->datatype == ANIMCONT_GPENCIL) {
1748  /* deselect all other channels first */
1750 
1751  /* Highlight GPencil Layer */
1752  if (ale != NULL && ale->data != NULL && ale->type == ANIMTYPE_GPLAYER) {
1753  bGPdata *gpd = (bGPdata *)ale->id;
1754  bGPDlayer *gpl = ale->data;
1755 
1757  }
1758  }
1759  else if (ac->datatype == ANIMCONT_MASK) {
1760  /* deselect all other channels first */
1762 
1763  if (ale != NULL && ale->data != NULL && ale->type == ANIMTYPE_MASKLAYER) {
1764  MaskLayer *masklay = ale->data;
1765 
1766  masklay->flag |= MASK_LAYERFLAG_SELECT;
1767  }
1768  }
1769  }
1770  }
1771 
1772  /* only select keyframes if we clicked on a valid channel and hit something */
1773  if (ale != NULL) {
1774  if (found) {
1775  /* apply selection to keyframes */
1776  if (column) {
1777  /* select all keyframes in the same frame as the one we hit on the active channel
1778  * [T41077]: "frame" not "selx" here (i.e. no NLA corrections yet) as the code here
1779  * does that itself again as it needs to work on multiple data-blocks.
1780  */
1781  actkeys_mselect_column(ac, select_mode, frame);
1782  }
1783  else if (same_channel) {
1784  /* select all keyframes in the active channel */
1785  actkeys_mselect_channel_only(ac, ale, select_mode);
1786  }
1787  else {
1788  /* select the nominated keyframe on the given frame */
1789  actkeys_mselect_single(ac, ale, select_mode, selx);
1790  }
1791  }
1792 
1793  /* flush tagged updates
1794  * NOTE: We temporarily add this channel back to the list so that this can happen
1795  */
1796  ListBase anim_data = {ale, ale};
1797  ANIM_animdata_update(ac, &anim_data);
1798 
1799  /* free this channel */
1800  MEM_freeN(ale);
1801  }
1802 
1803  return ret_value;
1804 }
1805 
1806 /* handle clicking */
1808 {
1809  bAnimContext ac;
1810  int ret_value;
1811 
1812  /* get editor data */
1813  if (ANIM_animdata_get_context(C, &ac) == 0) {
1814  return OPERATOR_CANCELLED;
1815  }
1816 
1817  /* get useful pointers from animation context data */
1818  /* region = ac.region; */ /* UNUSED */
1819 
1820  /* select mode is either replace (deselect all, then add) or add/extend */
1821  const short selectmode = RNA_boolean_get(op->ptr, "extend") ? SELECT_INVERT : SELECT_REPLACE;
1822  const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
1823  const bool wait_to_deselect_others = RNA_boolean_get(op->ptr, "wait_to_deselect_others");
1824  int mval[2];
1825 
1826  /* column selection */
1827  const bool column = RNA_boolean_get(op->ptr, "column");
1828  const bool channel = RNA_boolean_get(op->ptr, "channel");
1829 
1830  mval[0] = RNA_int_get(op->ptr, "mouse_x");
1831  mval[1] = RNA_int_get(op->ptr, "mouse_y");
1832 
1833  /* Select keyframe(s) based upon mouse position. */
1834  ret_value = mouse_action_keys(
1835  &ac, mval, selectmode, deselect_all, column, channel, wait_to_deselect_others);
1836 
1837  /* set notifier that keyframe selection (and channels too) have changed */
1840 
1841  /* for tweak grab to work */
1842  return ret_value | OPERATOR_PASS_THROUGH;
1843 }
1844 
1846 {
1847  PropertyRNA *prop;
1848 
1849  /* identifiers */
1850  ot->name = "Select Keyframes";
1851  ot->idname = "ACTION_OT_clickselect";
1852  ot->description = "Select keyframes by clicking on them";
1853 
1854  /* callbacks */
1859 
1860  /* flags */
1861  ot->flag = OPTYPE_UNDO;
1862 
1863  /* properties */
1865  /* Key-map: Enable with `Shift`. */
1866  prop = RNA_def_boolean(
1867  ot->srna,
1868  "extend",
1869  0,
1870  "Extend Select",
1871  "Toggle keyframe selection instead of leaving newly selected keyframes only");
1873 
1874  prop = RNA_def_boolean(ot->srna,
1875  "deselect_all",
1876  false,
1877  "Deselect On Nothing",
1878  "Deselect all when nothing under the cursor");
1880 
1881  /* Key-map: Enable with `Alt`. */
1882  prop = RNA_def_boolean(
1883  ot->srna,
1884  "column",
1885  0,
1886  "Column Select",
1887  "Select all keyframes that occur on the same frame as the one under the mouse");
1889 
1890  /* Key-map: Enable with `Ctrl-Alt`. */
1891  prop = RNA_def_boolean(ot->srna,
1892  "channel",
1893  0,
1894  "Only Channel",
1895  "Select all the keyframes in the channel under the mouse");
1897 }
1898 
1899 /* ************************************************************************** */
typedef float(TangentPoint)[2]
@ NLATIME_CONVERT_UNMAP
Definition: BKE_nla.h:357
float BKE_nla_tweakedit_remap(struct AnimData *adt, float cframe, short mode)
Definition: nla.c:642
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
void BLI_lasso_boundbox(struct rcti *rect, const int mcoords[][2], unsigned int mcoords_len)
Definition: lasso_2d.c:15
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
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:190
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:186
void BLI_rctf_rcti_copy(struct rctf *dst, const struct rcti *src)
#define UNUSED(x)
#define ELEM(...)
@ AGRP_SELECTED
@ SACTION_MARKERS_MOVE
@ FCURVE_SELECTED
@ MASK_LAYERFLAG_SELECT
Object is a sort of wrapper for general info.
#define MAXFRAMEF
#define MINAFRAMEF
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
@ ACHANNEL_SETFLAG_CLEAR
Definition: ED_anim_api.h:550
#define ACHANNEL_HEIGHT(ac)
Definition: ED_anim_api.h:440
@ ANIMTYPE_SUMMARY
Definition: ED_anim_api.h:194
@ ANIMTYPE_NLACURVE
Definition: ED_anim_api.h:202
@ ANIMTYPE_GROUP
Definition: ED_anim_api.h:198
@ ANIMTYPE_GPLAYER
Definition: ED_anim_api.h:233
@ ANIMTYPE_MASKDATABLOCK
Definition: ED_anim_api.h:235
@ ANIMTYPE_MASKLAYER
Definition: ED_anim_api.h:236
@ ANIMTYPE_FCURVE
Definition: ED_anim_api.h:199
@ ANIMTYPE_GPDATABLOCK
Definition: ED_anim_api.h:232
#define ACHANNEL_FIRST_TOP(ac)
Definition: ED_anim_api.h:438
@ ALE_SCE
Definition: ED_anim_api.h:256
@ ALE_GPFRAME
Definition: ED_anim_api.h:251
@ ALE_FCURVE
Definition: ED_anim_api.h:250
@ ALE_ALL
Definition: ED_anim_api.h:255
@ ALE_ACT
Definition: ED_anim_api.h:258
@ ALE_OB
Definition: ED_anim_api.h:257
@ ANIM_UPDATE_DEPS
Definition: ED_anim_api.h:268
@ ANIMCONT_MASK
Definition: ED_anim_api.h:112
@ ANIMCONT_TIMELINE
Definition: ED_anim_api.h:113
@ ANIMCONT_DOPESHEET
Definition: ED_anim_api.h:107
@ ANIMCONT_ACTION
Definition: ED_anim_api.h:104
@ ANIMCONT_GPENCIL
Definition: ED_anim_api.h:106
#define ACHANNEL_STEP(ac)
Definition: ED_anim_api.h:442
@ ANIMFILTER_DATA_VISIBLE
Definition: ED_anim_api.h:292
@ ANIMFILTER_LIST_VISIBLE
Definition: ED_anim_api.h:295
@ ANIMFILTER_LIST_CHANNELS
Definition: ED_anim_api.h:300
@ ANIMFILTER_NODUPLIS
Definition: ED_anim_api.h:325
@ ANIMFILTER_FCURVESONLY
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
bool ED_masklayer_frame_select_check(const struct MaskLayer *mask_layer)
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_operator_action_active(struct bContext *C)
Definition: screen_ops.c:297
eSelectOp ED_select_op_modal(eSelectOp sel_op, bool is_first)
Definition: select_utils.c:59
#define SEL_OP_USE_PRE_DESELECT(sel_op)
const char * ED_select_circle_get_name(struct wmOperatorType *ot, PointerRNA *ptr)
@ SEL_SELECT
@ SEL_INVERT
@ SEL_DESELECT
@ SEL_TOGGLE
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 GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_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:218
#define C
Definition: RandGen.cpp:25
void UI_view2d_listview_view_to_cell(float columnwidth, float rowheight, float startx, float starty, float viewx, float viewy, int *r_column, int *r_row)
Definition: view2d.cc:1619
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.cc:1655
@ OPTYPE_DEPENDS_ON_CURSOR
Definition: WM_types.h:184
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define NC_ANIMATION
Definition: WM_types.h:338
#define ND_KEYFRAME
Definition: WM_types.h:442
#define ND_ANIMCHAN
Definition: WM_types.h:444
#define NA_SELECTED
Definition: WM_types.h:528
@ ACTKEYS_LRSEL_TEST
Definition: action_intern.h:58
@ ACTKEYS_LRSEL_LEFT
Definition: action_intern.h:59
@ ACTKEYS_LRSEL_RIGHT
Definition: action_intern.h:60
@ ACTKEYS_COLUMNSEL_CFRA
Definition: action_intern.h:66
@ ACTKEYS_COLUMNSEL_MARKERS_BETWEEN
Definition: action_intern.h:68
@ ACTKEYS_COLUMNSEL_MARKERS_COLUMN
Definition: action_intern.h:67
@ ACTKEYS_COLUMNSEL_KEYS
Definition: action_intern.h:65
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 int actkeys_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
@ ACTKEYS_BORDERSEL_ALLKEYS
@ ACTKEYS_BORDERSEL_CHANNELS
@ ACTKEYS_BORDERSEL_FRAMERANGE
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:54
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 actkeys_list_element_to_keylist(bAnimContext *ac, struct AnimKeylist *keylist, bAnimListElem *ale)
Definition: action_select.c:80
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)
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:397
void ANIM_animdata_update(bAnimContext *ac, ListBase *anim_data)
Definition: anim_deps.c:302
AnimData * ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale)
Definition: anim_draw.c:216
void ANIM_nla_mapping_apply_fcurve(AnimData *adt, FCurve *fcu, bool restore, bool only_keys)
Definition: anim_draw.c:291
bool ANIM_animdata_can_have_greasepencil(const eAnimCont_Types type)
Definition: anim_filter.c:417
bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
Definition: anim_filter.c:379
size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, eAnimFilter_Flags filter_mode, void *data, eAnimCont_Types datatype)
Definition: anim_filter.c:3447
void ED_markers_make_cfra_list(ListBase *markers, ListBase *lb, short only_sel)
Definition: anim_markers.c:296
void ED_markers_get_minmax(ListBase *markers, short sel, float *r_first, float *r_last)
Definition: anim_markers.c:169
ListBase * ED_animcontext_get_markers(const bAnimContext *ac)
Definition: anim_markers.c:93
#define SELECT
Scene scene
void ED_gpencil_layer_frame_select_set(bGPDlayer *gpl, short mode)
void ED_gpencil_set_active_channel(bGPdata *gpd, bGPDlayer *gpl)
void ED_gpencil_select_frames(bGPDlayer *gpl, short select_mode)
bool ED_gpencil_layer_frame_select_check(const bGPDlayer *gpl)
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)
DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
const vector< Marker > & markers
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 fcurve_to_keylist(AnimData *adt, FCurve *fcu, AnimKeylist *keylist, const int saction_flag)
AnimKeylist * ED_keylist_create()
void scene_to_keylist(bDopeSheet *ads, Scene *sce, AnimKeylist *keylist, const int saction_flag)
void mask_to_keylist(bDopeSheet *UNUSED(ads), MaskLayer *masklay, AnimKeylist *keylist)
const ActKeyColumn * ED_keylist_find_any_between(const AnimKeylist *keylist, const Range2f frame_range)
void ob_to_keylist(bDopeSheet *ads, Object *ob, AnimKeylist *keylist, const int saction_flag)
void summary_to_keylist(bAnimContext *ac, AnimKeylist *keylist, const int saction_flag)
void ED_keylist_prepare_for_direct_access(AnimKeylist *keylist)
void ED_keylist_free(AnimKeylist *keylist)
void action_to_keylist(AnimData *adt, bAction *act, AnimKeylist *keylist, const int saction_flag)
void gpl_to_keylist(bDopeSheet *UNUSED(ads), bGPDlayer *gpl, AnimKeylist *keylist)
void agroup_to_keylist(AnimData *adt, bActionGroup *agrp, AnimKeylist *keylist, const int saction_flag)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4910
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:5015
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
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:3783
#define min(a, b)
Definition: sort.c:35
KeyframeEditFunc select_cb
KeyframeEditFunc ok_cb
KeyframeEditData ked
bAnimContext * ac
float cfra
Definition: BKE_fcurve.h:40
struct CfraElem * next
Definition: BKE_fcurve.h:39
BezTriple * bezt
short flag
unsigned int totvert
eKeyframeIterFlags iterflags
void * first
Definition: DNA_listBase.h:31
struct MaskLayer * next
KeyframeEditFunc ok_cb
bAnimContext * ac
KeyframeEditFunc select_cb
KeyframeEditData ked
struct RenderData r
unsigned int flag
struct TimeMarker * next
ListBase * markers
Definition: ED_anim_api.h:92
struct ARegion * region
Definition: ED_anim_api.h:76
struct Scene * scene
Definition: ED_anim_api.h:84
struct bDopeSheet * ads
Definition: ED_anim_api.h:79
short datatype
Definition: ED_anim_api.h:62
void * data
Definition: ED_anim_api.h:60
struct SpaceLink * sl
Definition: ED_anim_api.h:74
struct bAnimListElem * next
Definition: ED_anim_api.h:127
void * key_data
Definition: ED_anim_api.h:146
struct bAnimListElem * prev
Definition: ED_anim_api.h:127
struct ID * id
Definition: ED_anim_api.h:160
struct bGPDlayer * next
ListBase layers
float xmax
Definition: DNA_vec_types.h:69
float xmin
Definition: DNA_vec_types.h:69
float ymax
Definition: DNA_vec_types.h:70
float ymin
Definition: DNA_vec_types.h:70
int ymin
Definition: DNA_vec_types.h:64
int ymax
Definition: DNA_vec_types.h:64
int xmin
Definition: DNA_vec_types.h:63
int xmax
Definition: DNA_vec_types.h:63
int mval[2]
Definition: WM_types.h:684
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:935
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:927
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
PropertyRNA * prop
Definition: WM_types.h:981
const char *(* get_name)(struct wmOperatorType *, struct PointerRNA *)
Definition: WM_types.h:960
struct PointerRNA * ptr
float max
void WM_event_drag_start_mval(const wmEvent *event, const ARegion *region, int r_mval[2])
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition: wm_files.c:3479
bool WM_gesture_is_modal_first(const wmGesture *gesture)
Definition: wm_gesture.c:108
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:962
int WM_generic_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
Definition: wm_operators.c:903