Blender  V3.3
graph_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_lasso_2d.h"
17 #include "BLI_math.h"
18 #include "BLI_utildefines.h"
19 
20 #include "DNA_anim_types.h"
21 #include "DNA_scene_types.h"
22 #include "DNA_screen_types.h"
23 #include "DNA_space_types.h"
24 
25 #include "RNA_access.h"
26 #include "RNA_define.h"
27 
28 #include "BKE_context.h"
29 #include "BKE_fcurve.h"
30 #include "BKE_nla.h"
31 
32 #include "UI_view2d.h"
33 
34 #include "ED_anim_api.h"
35 #include "ED_keyframes_edit.h"
36 #include "ED_markers.h"
37 #include "ED_select_utils.h"
38 
39 #include "WM_api.h"
40 #include "WM_types.h"
41 
42 #include "graph_intern.h"
43 
44 /* -------------------------------------------------------------------- */
48 /* temp info for caching handle vertices close */
49 typedef struct tNearestVertInfo {
51 
52  FCurve *fcu; /* F-Curve that keyframe comes from */
53 
54  BezTriple *bezt; /* keyframe to consider */
55  FPoint *fpt; /* sample point to consider */
56 
57  short hpoint; /* the handle index that we hit (eHandleIndex) */
58  short sel; /* whether the handle is selected or not */
59  int dist; /* distance from mouse to vert */
60 
61  eAnim_ChannelType ctype; /* type of animation channel this FCurve comes from */
62 
63  float frame; /* frame that point was on when it matched (global time) */
65 
66 /* Tags for the type of graph vert that we have */
67 typedef enum eGraphVertIndex {
72 
73 /* Tolerance for absolute radius (in pixels) of the vert from the cursor to use */
74 /* TODO: perhaps this should depend a bit on the size that the user set the vertices to be? */
75 #define GVERTSEL_TOL (10 * U.pixelsize)
76 
77 /* ....... */
78 
79 /* check if its ok to select a handle */
80 /* XXX also need to check for int-values only? */
82 {
83  if (sipo->flag & SIPO_NOHANDLES) {
84  return false;
85  }
86  if ((sipo->flag & SIPO_SELVHANDLESONLY) && BEZT_ISSEL_ANY(bezt) == 0) {
87  return false;
88  }
89  return true;
90 }
91 
92 /* check if the given vertex is within bounds or not */
93 /* TODO: should we return if we hit something? */
94 static void nearest_fcurve_vert_store(ListBase *matches,
95  View2D *v2d,
96  FCurve *fcu,
98  BezTriple *bezt,
99  FPoint *fpt,
100  short hpoint,
101  const int mval[2],
102  float unit_scale,
103  float offset)
104 {
105  /* Keyframes or Samples? */
106  if (bezt) {
107  int screen_co[2], dist;
108 
109  /* convert from data-space to screen coordinates
110  * NOTE: hpoint+1 gives us 0,1,2 respectively for each handle,
111  * needed to access the relevant vertex coordinates in the 3x3
112  * 'vec' matrix
113  */
115  bezt->vec[hpoint + 1][0],
116  (bezt->vec[hpoint + 1][1] + offset) * unit_scale,
117  &screen_co[0],
118  &screen_co[1]) &&
119  /* check if distance from mouse cursor to vert in screen space is within tolerance */
120  ((dist = len_v2v2_int(mval, screen_co)) <= GVERTSEL_TOL)) {
121  tNearestVertInfo *nvi = (tNearestVertInfo *)matches->last;
122  bool replace = false;
123 
124  /* If there is already a point for the F-Curve,
125  * check if this point is closer than that was. */
126  if ((nvi) && (nvi->fcu == fcu)) {
127  /* replace if we are closer, or if equal and that one wasn't selected but we are... */
128  if ((nvi->dist > dist) || ((nvi->sel == 0) && BEZT_ISSEL_ANY(bezt))) {
129  replace = 1;
130  }
131  }
132  /* add new if not replacing... */
133  if (replace == 0) {
134  nvi = MEM_callocN(sizeof(tNearestVertInfo), "Nearest Graph Vert Info - Bezt");
135  }
136 
137  /* store values */
138  nvi->fcu = fcu;
139  nvi->ctype = ctype;
140 
141  nvi->bezt = bezt;
142  nvi->hpoint = hpoint;
143  nvi->dist = dist;
144 
145  nvi->frame = bezt->vec[1][0]; /* currently in global time... */
146 
147  nvi->sel = BEZT_ISSEL_ANY(bezt); /* XXX... should this use the individual verts instead? */
148 
149  /* add to list of matches if appropriate... */
150  if (replace == 0) {
151  BLI_addtail(matches, nvi);
152  }
153  }
154  }
155  else if (fpt) {
156  /* TODO: support #FPoint. */
157  }
158 }
159 
160 /* helper for find_nearest_fcurve_vert() - build the list of nearest matches */
161 static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], ListBase *matches)
162 {
163  ListBase anim_data = {NULL, NULL};
164  bAnimListElem *ale;
165  int filter;
166 
167  SpaceGraph *sipo = (SpaceGraph *)ac->sl;
168  View2D *v2d = &ac->region->v2d;
169  short mapping_flag = 0;
170 
171  /* get curves to search through
172  * - if the option to only show keyframes that belong to selected F-Curves is enabled,
173  * include the 'only selected' flag...
174  */
177  if (sipo->flag &
178  SIPO_SELCUVERTSONLY) { /* FIXME: this should really be check for by the filtering code... */
180  }
181  mapping_flag |= ANIM_get_normalization_flags(ac);
182  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
183 
184  for (ale = anim_data.first; ale; ale = ale->next) {
185  FCurve *fcu = (FCurve *)ale->key_data;
186  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
187  float offset;
188  float unit_scale = ANIM_unit_mapping_get_factor(
189  ac->scene, ale->id, fcu, mapping_flag, &offset);
190 
191  /* apply NLA mapping to all the keyframes */
192  if (adt) {
193  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
194  }
195 
196  if (fcu->bezt) {
197  BezTriple *bezt1 = fcu->bezt, *prevbezt = NULL;
198  int i;
199 
200  for (i = 0; i < fcu->totvert; i++, prevbezt = bezt1, bezt1++) {
201  /* keyframe */
203  v2d,
204  fcu,
205  ale->type,
206  bezt1,
207  NULL,
209  mval,
210  unit_scale,
211  offset);
212 
213  /* handles - only do them if they're visible */
214  if (fcurve_handle_sel_check(sipo, bezt1) && (fcu->totvert > 1)) {
215  /* first handle only visible if previous segment had handles */
216  if ((!prevbezt && (bezt1->ipo == BEZT_IPO_BEZ)) ||
217  (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {
219  v2d,
220  fcu,
221  ale->type,
222  bezt1,
223  NULL,
225  mval,
226  unit_scale,
227  offset);
228  }
229 
230  /* second handle only visible if this segment is bezier */
231  if (bezt1->ipo == BEZT_IPO_BEZ) {
233  v2d,
234  fcu,
235  ale->type,
236  bezt1,
237  NULL,
239  mval,
240  unit_scale,
241  offset);
242  }
243  }
244  }
245  }
246  else if (fcu->fpt) {
247  /* TODO: do this for samples too. */
248  }
249 
250  /* un-apply NLA mapping from all the keyframes */
251  if (adt) {
252  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
253  }
254  }
255 
256  /* free channels */
257  ANIM_animdata_freelist(&anim_data);
258 }
259 
260 /* helper for find_nearest_fcurve_vert() - get the best match to use */
262 {
263  tNearestVertInfo *nvi = NULL;
264  short found = 0;
265 
266  /* abort if list is empty */
267  if (BLI_listbase_is_empty(matches)) {
268  return NULL;
269  }
270 
271  /* if list only has 1 item, remove it from the list and return */
272  if (BLI_listbase_is_single(matches)) {
273  /* need to remove from the list, otherwise it gets freed and then we can't return it */
274  return BLI_pophead(matches);
275  }
276 
277  /* try to find the first selected F-Curve vert, then take the one after it */
278  for (nvi = matches->first; nvi; nvi = nvi->next) {
279  /* which mode of search are we in: find first selected, or find vert? */
280  if (found) {
281  /* Just take this vert now that we've found the selected one
282  * - We'll need to remove this from the list
283  * so that it can be returned to the original caller.
284  */
285  BLI_remlink(matches, nvi);
286  return nvi;
287  }
288 
289  /* if vert is selected, we've got what we want... */
290  if (nvi->sel) {
291  found = 1;
292  }
293  }
294 
295  /* if we're still here, this means that we failed to find anything appropriate in the first pass,
296  * so just take the first item now...
297  */
298  return BLI_pophead(matches);
299 }
300 
308 {
309  ListBase matches = {NULL, NULL};
310  tNearestVertInfo *nvi;
311 
312  /* step 1: get the nearest verts */
313  get_nearest_fcurve_verts_list(ac, mval, &matches);
314 
315  /* step 2: find the best vert */
316  nvi = get_best_nearest_fcurve_vert(&matches);
317 
318  BLI_freelistN(&matches);
319 
320  /* return the best vert found */
321  return nvi;
322 }
323 
326 /* -------------------------------------------------------------------- */
335 void deselect_graph_keys(bAnimContext *ac, bool test, short sel, bool do_channels)
336 {
337  ListBase anim_data = {NULL, NULL};
338  bAnimListElem *ale;
339  int filter;
340 
341  SpaceGraph *sipo = (SpaceGraph *)ac->sl;
342  KeyframeEditData ked = {{NULL}};
343  KeyframeEditFunc test_cb, sel_cb;
344 
345  /* determine type-based settings */
348 
349  /* filter data */
350  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
351 
352  /* init BezTriple looping data */
354 
355  /* See if we should be selecting or deselecting */
356  if (test) {
357  for (ale = anim_data.first; ale; ale = ale->next) {
358  if (ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, test_cb, NULL)) {
360  break;
361  }
362  }
363  }
364 
365  /* convert sel to selectmode, and use that to get editor */
366  sel_cb = ANIM_editkeyframes_select(sel);
367 
368  /* Now set the flags */
369  for (ale = anim_data.first; ale; ale = ale->next) {
370  FCurve *fcu = (FCurve *)ale->key_data;
371 
372  /* Keyframes First */
373  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL);
374 
375  /* affect channel selection status? */
376  if (do_channels) {
377  /* Only change selection of channel when the visibility of keyframes
378  * doesn't depend on this. */
379  if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) {
380  /* deactivate the F-Curve, and deselect if deselecting keyframes.
381  * otherwise select the F-Curve too since we've selected all the keyframes
382  */
383  if (sel == SELECT_SUBTRACT) {
384  fcu->flag &= ~FCURVE_SELECTED;
385  }
386  else {
388  }
389  }
390 
391  /* always deactivate all F-Curves if we perform batch ops for selection */
392  fcu->flag &= ~FCURVE_ACTIVE;
393  }
394  }
395 
396  /* Cleanup */
397  ANIM_animdata_freelist(&anim_data);
398 }
399 
400 /* ------------------- */
401 
403 {
404  bAnimContext ac;
405  bAnimListElem *ale_active = NULL;
406 
407  /* get editor data */
408  if (ANIM_animdata_get_context(C, &ac) == 0) {
409  return OPERATOR_CANCELLED;
410  }
411 
412  /* find active F-Curve, and preserve this for later
413  * or else it becomes annoying with the current active
414  * curve keeps fading out even while you're editing it
415  */
416  ale_active = get_active_fcurve_channel(&ac);
417 
418  /* 'standard' behavior - check if selected, then apply relevant selection */
419  const int action = RNA_enum_get(op->ptr, "action");
420  switch (action) {
421  case SEL_TOGGLE:
422  deselect_graph_keys(&ac, 1, SELECT_ADD, true);
423  break;
424  case SEL_SELECT:
425  deselect_graph_keys(&ac, 0, SELECT_ADD, true);
426  break;
427  case SEL_DESELECT:
428  deselect_graph_keys(&ac, 0, SELECT_SUBTRACT, true);
429  break;
430  case SEL_INVERT:
431  deselect_graph_keys(&ac, 0, SELECT_INVERT, true);
432  break;
433  default:
434  BLI_assert(0);
435  break;
436  }
437 
438  /* restore active F-Curve... */
439  if (ale_active) {
440  FCurve *fcu = (FCurve *)ale_active->data;
441 
442  /* all others should not be disabled, so we should be able to just set this directly...
443  * - selection needs to be set too, or else this won't work...
444  */
446 
447  MEM_freeN(ale_active);
448  ale_active = NULL;
449  }
450 
451  /* set notifier that things have changed */
453 
454  return OPERATOR_FINISHED;
455 }
456 
458 {
459  /* identifiers */
460  ot->name = "Select All";
461  ot->idname = "GRAPH_OT_select_all";
462  ot->description = "Toggle selection of all keyframes";
463 
464  /* api callbacks */
467 
468  /* flags */
470 
471  /* properties */
473 }
474 
477 /* -------------------------------------------------------------------- */
490 static rctf initialize_box_select_coords(const bAnimContext *ac, const rctf *rectf_view)
491 {
492  const View2D *v2d = &ac->region->v2d;
493  rctf rectf;
494 
495  /* Convert mouse coordinates to frame ranges and
496  * channel coordinates corrected for view pan/zoom. */
497  UI_view2d_region_to_view_rctf(v2d, rectf_view, &rectf);
498  return rectf;
499 }
500 
502 {
505  if (sipo->flag & SIPO_SELCUVERTSONLY) {
507  }
508  return filter;
509 }
510 
512 {
513  ListBase anim_data = {NULL, NULL};
514  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
515  return anim_data;
516 }
517 
519  const bool incl_handles,
520  const short mode,
521  bAnimContext *ac,
522  void *data,
523  rctf *scaled_rectf,
524  KeyframeEditData *r_ked,
525  int *r_mapping_flag)
526 {
527  memset(r_ked, 0, sizeof(KeyframeEditData));
528  switch (mode) {
529  case BEZT_OK_REGION_LASSO: {
530  KeyframeEdit_LassoData *data_lasso = data;
531  data_lasso->rectf_scaled = scaled_rectf;
532  r_ked->data = data_lasso;
533  break;
534  }
535  case BEZT_OK_REGION_CIRCLE: {
536  KeyframeEdit_CircleData *data_circle = data;
537  data_circle->rectf_scaled = scaled_rectf;
538  r_ked->data = data_circle;
539  break;
540  }
541  default:
542  r_ked->data = scaled_rectf;
543  break;
544  }
545 
546  if (sipo->flag & SIPO_SELVHANDLESONLY) {
548  }
549 
550  /* Enable handles selection. (used in keyframes_edit.c > KEYFRAME_OK_CHECKS macro) */
551  if (incl_handles) {
553  *r_mapping_flag = 0;
554  }
555  else {
556  *r_mapping_flag = ANIM_UNITCONV_ONLYKEYS;
557  }
558 
559  *r_mapping_flag |= ANIM_get_normalization_flags(ac);
560 }
561 
572  const rctf *rectf_view,
573  short mode,
574  short selectmode,
575  bool incl_handles,
576  void *data)
577 {
578  const rctf rectf = initialize_box_select_coords(ac, rectf_view);
579  SpaceGraph *sipo = (SpaceGraph *)ac->sl;
582  rctf scaled_rectf;
583  KeyframeEditData ked;
584  int mapping_flag;
586  sipo, incl_handles, mode, ac, data, &scaled_rectf, &ked, &mapping_flag);
587 
588  /* Get beztriple editing/validation funcs. */
589  const KeyframeEditFunc select_cb = ANIM_editkeyframes_select(selectmode);
590  const KeyframeEditFunc ok_cb = ANIM_editkeyframes_ok(mode);
591 
592  /* Try selecting the keyframes. */
593  bAnimListElem *ale = NULL;
594 
595  /* This variable will be set to true if any key is selected or deselected. */
596  bool any_key_selection_changed = false;
597 
598  /* First loop over data, doing box select. try selecting keys only. */
599  for (ale = anim_data.first; ale; ale = ale->next) {
600  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
601  FCurve *fcu = (FCurve *)ale->key_data;
602  float offset;
603  const float unit_scale = ANIM_unit_mapping_get_factor(
604  ac->scene, ale->id, fcu, mapping_flag, &offset);
605 
606  /* Apply NLA mapping to all the keyframes, since it's easier than trying to
607  * guess when a callback might use something different.
608  */
609  if (adt) {
610  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, incl_handles == 0);
611  }
612 
613  scaled_rectf.xmin = rectf.xmin;
614  scaled_rectf.xmax = rectf.xmax;
615  scaled_rectf.ymin = rectf.ymin / unit_scale - offset;
616  scaled_rectf.ymax = rectf.ymax / unit_scale - offset;
617 
618  /* Set horizontal range (if applicable).
619  * NOTE: these values are only used for x-range and y-range but not region
620  * (which uses ked.data, i.e. rectf)
621  */
622  if (mode != BEZT_OK_VALUERANGE) {
623  ked.f1 = rectf.xmin;
624  ked.f2 = rectf.xmax;
625  }
626  else {
627  ked.f1 = rectf.ymin;
628  ked.f2 = rectf.ymax;
629  }
630 
631  /* Firstly, check if any keyframes will be hit by this. */
632  if (ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, ok_cb, NULL)) {
633  /* select keyframes that are in the appropriate places */
634  ANIM_fcurve_keyframes_loop(&ked, fcu, ok_cb, select_cb, NULL);
635  any_key_selection_changed = true;
636  /* Only change selection of channel when the visibility of keyframes
637  * doesn't depend on this. */
638  if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) {
639  /* select the curve too now that curve will be touched */
640  if (selectmode == SELECT_ADD) {
642  }
643  }
644  }
645 
646  /* Un-apply NLA mapping from all the keyframes. */
647  if (adt) {
648  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, incl_handles == 0);
649  }
650  }
651 
652  /* Cleanup. */
653  ANIM_animdata_freelist(&anim_data);
654 
655  return any_key_selection_changed;
656 }
657 
663 {
665 }
666 
667 #define ABOVE 1
668 #define INSIDE 0
669 #define BELOW -1
671  FCurve *fcu, const rctf *rectf, const float offset, const float unit_scale, const float eval_x)
672 {
673  const float fcurve_y = (evaluate_fcurve(fcu, eval_x) + offset) * unit_scale;
674  return fcurve_y < rectf->ymin ? BELOW : fcurve_y <= rectf->ymax ? INSIDE : ABOVE;
675 }
676 
677 /* Checks whether the given rectangle intersects the given fcurve's calculated curve (i.e. not
678  * only keyframes, but also all the interpolated values). This is done by sampling the curve at
679  * different points between the xmin and the xmax of the rectangle.
680  */
682  const float offset, const float unit_scale, const rctf *rectf, AnimData *adt, FCurve *fcu)
683 {
684  /* 30 sampling points. This worked well in tests. */
685  int num_steps = 30;
686 
687  /* Remap the range at which to evaluate the fcurves. This enables us to avoid remapping
688  * the keys themselves. */
689  const float mapped_max = BKE_nla_tweakedit_remap(adt, rectf->xmax, NLATIME_CONVERT_UNMAP);
690  const float mapped_min = BKE_nla_tweakedit_remap(adt, rectf->xmin, NLATIME_CONVERT_UNMAP);
691  const float eval_step = (mapped_max - mapped_min) / num_steps;
692 
693  /* Sample points on the given fcurve in the interval defined by the
694  * mapped_min and mapped_max of the selected rectangle.
695  * For each point, check if it is inside of the selection box. If it is, then select
696  * all the keyframes of the curve, the curve, and stop the loop.
697  */
698  struct {
699  float eval_x;
700  int zone;
701  } cur, prev;
702 
703  prev.eval_x = mapped_min;
704  prev.zone = rectf_curve_zone_y(fcu, rectf, offset, unit_scale, prev.eval_x);
705  if (prev.zone == INSIDE) {
706  return true;
707  }
708 
709  while (num_steps--) {
710  cur.eval_x = prev.eval_x + eval_step;
711  cur.zone = rectf_curve_zone_y(fcu, rectf, offset, unit_scale, cur.eval_x);
712  if (cur.zone != prev.zone) {
713  return true;
714  }
715 
716  prev = cur;
717  }
718  return false;
719 }
720 #undef ABOVE
721 #undef INSIDE
722 #undef BELOW
723 
732  const rctf *rectf_view,
733  const short mode,
734  const short selectmode,
735  const bool incl_handles,
736  void *data)
737 {
738  const SpaceGraph *sipo = (SpaceGraph *)ac->sl;
741  rctf scaled_rectf;
742  KeyframeEditData ked;
743  int mapping_flag;
745  sipo, incl_handles, mode, ac, data, &scaled_rectf, &ked, &mapping_flag);
746 
747  FCurve *last_selected_curve = NULL;
748 
749  /* Go through all the curves and try selecting them. This function is only called
750  * if no keyframe is in the selection area, so we only have to check if the curve
751  * intersects the area in order to check if the selection/deselection must happen.
752  */
753 
754  LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
755  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
756  FCurve *fcu = (FCurve *)ale->key_data;
757  float offset;
758  const float unit_scale = ANIM_unit_mapping_get_factor(
759  ac->scene, ale->id, fcu, mapping_flag, &offset);
760 
761  const rctf rectf = initialize_box_select_coords(ac, rectf_view);
762 
763  /* scaled_rectf is declared at the top of the block because it is required by the
764  * initialize_box_select_key_editing_data function (which does
765  * data_xxx->rectf_scaled = scaled_rectf). The below assignment therefore modifies the
766  * data we use to iterate over the curves (ked).
767  */
768  scaled_rectf.xmin = rectf.xmin;
769  scaled_rectf.xmax = rectf.xmax;
770  scaled_rectf.ymin = rectf.ymin / unit_scale - offset;
771  scaled_rectf.ymax = rectf.ymax / unit_scale - offset;
772 
773  const KeyframeEditFunc select_cb = ANIM_editkeyframes_select(selectmode);
774  if (rectf_curve_intersection(offset, unit_scale, &rectf, adt, fcu)) {
775  if ((selectmode & SELECT_ADD) || (selectmode & SELECT_REPLACE)) {
776  fcu->flag |= FCURVE_SELECTED;
777  last_selected_curve = fcu;
778  }
779  else {
780  fcu->flag &= ~FCURVE_SELECTED;
781  }
782  ANIM_fcurve_keyframes_loop(&ked, fcu, ok_bezier_always_ok, select_cb, NULL);
783  }
784  }
785 
786  /* Make sure that one of the selected curves is active in the end. */
787  if (last_selected_curve != NULL) {
789  ac, ac->data, ac->datatype, filter, last_selected_curve, ANIMTYPE_FCURVE);
790  }
791 
792  ANIM_animdata_freelist(&anim_data);
793 }
794 
795 /* ------------------- */
796 
797 static int graphkeys_box_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
798 {
799  bAnimContext ac;
800  if (ANIM_animdata_get_context(C, &ac) == 0) {
801  return OPERATOR_CANCELLED;
802  }
803 
804  if (RNA_boolean_get(op->ptr, "tweak")) {
805  int mval[2];
806  WM_event_drag_start_mval(event, ac.region, mval);
807  tNearestVertInfo *under_mouse = find_nearest_fcurve_vert(&ac, mval);
808  bool mouse_is_over_element = under_mouse != NULL;
809  if (under_mouse) {
810  MEM_freeN(under_mouse);
811  }
812 
813  if (mouse_is_over_element) {
815  }
816  }
817 
818  return WM_gesture_box_invoke(C, op, event);
819 }
820 
822 {
823  bAnimContext ac;
824  rcti rect;
825  rctf rect_fl;
826  short mode = 0;
827 
828  /* get editor data */
829  if (ANIM_animdata_get_context(C, &ac) == 0) {
830  return OPERATOR_CANCELLED;
831  }
832 
833  const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
834  const int selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
835  if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
836  deselect_graph_keys(&ac, 1, SELECT_SUBTRACT, true);
837  }
838 
839  /* 'include_handles' from the operator specifies whether to include handles in the selection. */
840  const bool incl_handles = RNA_boolean_get(op->ptr, "include_handles");
841 
842  /* Get settings from operator. */
844 
845  /* Selection 'mode' depends on whether box_select region only matters on one axis. */
846  if (RNA_boolean_get(op->ptr, "axis_range")) {
847  /* Mode depends on which axis of the range is larger to determine which axis to use
848  * - Checking this in region-space is fine, as it's fundamentally still going to be a
849  * different rect size.
850  * - The frame-range select option is favored over the channel one (x over y),
851  * as frame-range one is often used for tweaking timing when "blocking",
852  * while channels is not that useful.
853  */
854  if (BLI_rcti_size_x(&rect) >= BLI_rcti_size_y(&rect)) {
855  mode = BEZT_OK_FRAMERANGE;
856  }
857  else {
858  mode = BEZT_OK_VALUERANGE;
859  }
860  }
861  else {
862  mode = BEZT_OK_REGION;
863  }
864 
865  BLI_rctf_rcti_copy(&rect_fl, &rect);
866 
867  /* Apply box_select action. */
868  const bool any_key_selection_changed = box_select_graphkeys(
869  &ac, &rect_fl, mode, selectmode, incl_handles, NULL);
870  const bool use_curve_selection = RNA_boolean_get(op->ptr, "use_curve_selection");
871  if (use_curve_selection && !any_key_selection_changed) {
872  box_select_graphcurves(&ac, &rect_fl, mode, selectmode, incl_handles, NULL);
873  }
874  /* Send notifier that keyframe selection has changed. */
876 
877  return OPERATOR_FINISHED;
878 }
879 
881 {
882  /* Identifiers. */
883  ot->name = "Box Select";
884  ot->idname = "GRAPH_OT_select_box";
885  ot->description = "Select all keyframes within the specified region";
886 
887  /* API callbacks. */
892 
894 
895  /* Flags. */
897 
898  /* Properties. */
899  ot->prop = RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
901 
902  PropertyRNA *prop;
903  prop = RNA_def_boolean(ot->srna,
904  "include_handles",
905  true,
906  "Include Handles",
907  "Are handles tested individually against the selection criteria");
909 
910  prop = RNA_def_boolean(
911  ot->srna, "tweak", 0, "Tweak", "Operator has been activated using a click-drag event");
913 
914  prop = RNA_def_boolean(
915  ot->srna,
916  "use_curve_selection",
917  1,
918  "Select Curves",
919  "Allow selecting all the keyframes of a curve by selecting the calculated fcurve");
921 
924 }
925 
926 /* ------------------- */
927 
929 {
930  bAnimContext ac;
931 
932  KeyframeEdit_LassoData data_lasso = {0};
933  rcti rect;
934  rctf rect_fl;
935 
936  bool incl_handles;
937 
938  /* Get editor data. */
939  if (ANIM_animdata_get_context(C, &ac) == 0) {
940  return OPERATOR_CANCELLED;
941  }
942 
943  data_lasso.rectf_view = &rect_fl;
944  data_lasso.mcoords = WM_gesture_lasso_path_to_array(C, op, &data_lasso.mcoords_len);
945  if (data_lasso.mcoords == NULL) {
946  return OPERATOR_CANCELLED;
947  }
948 
949  const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
950  const short selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
951  if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
952  deselect_graph_keys(&ac, 0, SELECT_SUBTRACT, true);
953  }
954 
955  {
956  SpaceGraph *sipo = (SpaceGraph *)ac.sl;
957  if (selectmode == SELECT_ADD) {
958  incl_handles = ((sipo->flag & SIPO_SELVHANDLESONLY) || (sipo->flag & SIPO_NOHANDLES)) == 0;
959  }
960  else {
961  incl_handles = (sipo->flag & SIPO_NOHANDLES) == 0;
962  }
963  }
964 
965  /* Get settings from operator. */
966  BLI_lasso_boundbox(&rect, data_lasso.mcoords, data_lasso.mcoords_len);
967  BLI_rctf_rcti_copy(&rect_fl, &rect);
968 
969  /* Apply box_select action. */
970  const bool any_key_selection_changed = box_select_graphkeys(
971  &ac, &rect_fl, BEZT_OK_REGION_LASSO, selectmode, incl_handles, &data_lasso);
972  const bool use_curve_selection = RNA_boolean_get(op->ptr, "use_curve_selection");
973  if (use_curve_selection && !any_key_selection_changed) {
975  &ac, &rect_fl, BEZT_OK_REGION_LASSO, selectmode, incl_handles, &data_lasso);
976  }
977 
978  MEM_freeN((void *)data_lasso.mcoords);
979 
980  /* Send notifier that keyframe selection has changed. */
982 
983  return OPERATOR_FINISHED;
984 }
985 
987 {
988  /* Identifiers. */
989  ot->name = "Lasso Select";
990  ot->description = "Select keyframe points using lasso selection";
991  ot->idname = "GRAPH_OT_select_lasso";
992 
993  /* API callbacks. */
999 
1000  /* Flags. */
1002 
1003  /* Properties. */
1006  PropertyRNA *prop = RNA_def_boolean(
1007  ot->srna,
1008  "use_curve_selection",
1009  1,
1010  "Select Curves",
1011  "Allow selecting all the keyframes of a curve by selecting the curve itself");
1013 }
1014 
1015 /* ------------------- */
1016 
1018 {
1019  bAnimContext ac;
1020  bool incl_handles = false;
1021 
1023  rctf rect_fl;
1024 
1025  float x = RNA_int_get(op->ptr, "x");
1026  float y = RNA_int_get(op->ptr, "y");
1027  float radius = RNA_int_get(op->ptr, "radius");
1028 
1029  /* Get editor data. */
1030  if (ANIM_animdata_get_context(C, &ac) == 0) {
1031  return OPERATOR_CANCELLED;
1032  }
1033 
1034  const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"),
1036  const short selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
1037  if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
1038  deselect_graph_keys(&ac, 0, SELECT_SUBTRACT, true);
1039  }
1040 
1041  data.mval[0] = x;
1042  data.mval[1] = y;
1043  data.radius_squared = radius * radius;
1044  data.rectf_view = &rect_fl;
1045 
1046  rect_fl.xmin = x - radius;
1047  rect_fl.xmax = x + radius;
1048  rect_fl.ymin = y - radius;
1049  rect_fl.ymax = y + radius;
1050 
1051  {
1052  SpaceGraph *sipo = (SpaceGraph *)ac.sl;
1053  if (selectmode == SELECT_ADD) {
1054  incl_handles = ((sipo->flag & SIPO_SELVHANDLESONLY) || (sipo->flag & SIPO_NOHANDLES)) == 0;
1055  }
1056  else {
1057  incl_handles = (sipo->flag & SIPO_NOHANDLES) == 0;
1058  }
1059  }
1060 
1061  /* Apply box_select action. */
1062  const bool any_key_selection_changed = box_select_graphkeys(
1063  &ac, &rect_fl, BEZT_OK_REGION_CIRCLE, selectmode, incl_handles, &data);
1064  const bool use_curve_selection = RNA_boolean_get(op->ptr, "use_curve_selection");
1065  if (use_curve_selection && !any_key_selection_changed) {
1066  box_select_graphcurves(&ac, &rect_fl, BEZT_OK_REGION_CIRCLE, selectmode, incl_handles, &data);
1067  }
1068 
1069  /* Send notifier that keyframe selection has changed. */
1071 
1072  return OPERATOR_FINISHED;
1073 }
1074 
1076 {
1077  ot->name = "Circle Select";
1078  ot->description = "Select keyframe points using circle selection";
1079  ot->idname = "GRAPH_OT_select_circle";
1080 
1087 
1088  /* flags */
1089  ot->flag = OPTYPE_UNDO;
1090 
1091  /* properties */
1094  PropertyRNA *prop = RNA_def_boolean(
1095  ot->srna,
1096  "use_curve_selection",
1097  1,
1098  "Select Curves",
1099  "Allow selecting all the keyframes of a curve by selecting the curve itself");
1101 }
1102 
1105 /* -------------------------------------------------------------------- */
1115 /* defines for column-select mode */
1117  {GRAPHKEYS_COLUMNSEL_KEYS, "KEYS", 0, "On Selected Keyframes", ""},
1118  {GRAPHKEYS_COLUMNSEL_CFRA, "CFRA", 0, "On Current Frame", ""},
1119  {GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN, "MARKERS_COLUMN", 0, "On Selected Markers", ""},
1121  "MARKERS_BETWEEN",
1122  0,
1123  "Between Min/Max Selected Markers",
1124  ""},
1125  {0, NULL, 0, NULL, NULL},
1126 };
1127 
1128 /* ------------------- */
1129 
1130 /* Selects all visible keyframes between the specified markers */
1131 /* TODO(campbell): this is almost an _exact_ duplicate of a function of the same name in
1132  * action_select.c should de-duplicate. */
1134 {
1135  ListBase anim_data = {NULL, NULL};
1136  bAnimListElem *ale;
1137  int filter;
1138 
1139  KeyframeEditFunc ok_cb, select_cb;
1140  KeyframeEditData ked = {{NULL}};
1141  float min, max;
1142 
1143  /* get extreme markers */
1144  ED_markers_get_minmax(ac->markers, 1, &min, &max);
1145  min -= 0.5f;
1146  max += 0.5f;
1147 
1148  /* get editing funcs + data */
1151 
1152  ked.f1 = min;
1153  ked.f2 = max;
1154 
1155  /* filter data */
1158  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1159 
1160  /* select keys in-between */
1161  for (ale = anim_data.first; ale; ale = ale->next) {
1162  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
1163 
1164  if (adt) {
1165  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
1166  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
1167  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
1168  }
1169  else {
1170  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
1171  }
1172  }
1173 
1174  /* Cleanup */
1175  ANIM_animdata_freelist(&anim_data);
1176 }
1177 
1178 /* Selects all visible keyframes in the same frames as the specified elements */
1179 static void columnselect_graph_keys(bAnimContext *ac, short mode)
1180 {
1181  ListBase anim_data = {NULL, NULL};
1182  bAnimListElem *ale;
1183  int filter;
1184 
1185  Scene *scene = ac->scene;
1186  CfraElem *ce;
1187  KeyframeEditFunc select_cb, ok_cb;
1188  KeyframeEditData ked;
1189 
1190  /* initialize keyframe editing data */
1191  memset(&ked, 0, sizeof(KeyframeEditData));
1192 
1193  /* build list of columns */
1194  switch (mode) {
1195  case GRAPHKEYS_COLUMNSEL_KEYS: /* list of selected keys */
1198  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1199 
1200  for (ale = anim_data.first; ale; ale = ale->next) {
1202  }
1203 
1204  ANIM_animdata_freelist(&anim_data);
1205  break;
1206 
1207  case GRAPHKEYS_COLUMNSEL_CFRA: /* current frame */
1208  /* make a single CfraElem for storing this */
1209  ce = MEM_callocN(sizeof(CfraElem), "cfraElem");
1210  BLI_addtail(&ked.list, ce);
1211 
1212  ce->cfra = (float)scene->r.cfra;
1213  break;
1214 
1215  case GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN: /* list of selected markers */
1217  break;
1218 
1219  default: /* invalid option */
1220  return;
1221  }
1222 
1223  /* set up BezTriple edit callbacks */
1226 
1227  /* loop through all of the keys and select additional keyframes
1228  * based on the keys found to be selected above
1229  */
1232  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1233 
1234  for (ale = anim_data.first; ale; ale = ale->next) {
1235  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
1236 
1237  /* loop over cfraelems (stored in the KeyframeEditData->list)
1238  * - we need to do this here, as we can apply fewer NLA-mapping conversions
1239  */
1240  for (ce = ked.list.first; ce; ce = ce->next) {
1241  /* set frame for validation callback to refer to */
1243 
1244  /* select elements with frame number matching cfraelem */
1245  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
1246  }
1247  }
1248 
1249  /* free elements */
1250  BLI_freelistN(&ked.list);
1251  ANIM_animdata_freelist(&anim_data);
1252 }
1253 
1254 /* ------------------- */
1255 
1257 {
1258  bAnimContext ac;
1259  short mode;
1260 
1261  /* get editor data */
1262  if (ANIM_animdata_get_context(C, &ac) == 0) {
1263  return OPERATOR_CANCELLED;
1264  }
1265 
1266  /* action to take depends on the mode */
1267  mode = RNA_enum_get(op->ptr, "mode");
1268 
1271  }
1272  else {
1273  columnselect_graph_keys(&ac, mode);
1274  }
1275 
1276  /* set notifier that keyframe selection has changed */
1278 
1279  return OPERATOR_FINISHED;
1280 }
1281 
1283 {
1284  /* identifiers */
1285  ot->name = "Select All";
1286  ot->idname = "GRAPH_OT_select_column";
1287  ot->description = "Select all keyframes on the specified frame(s)";
1288 
1289  /* api callbacks */
1292 
1293  /* flags */
1295 
1296  /* props */
1297  ot->prop = RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", "");
1298 }
1299 
1302 /* -------------------------------------------------------------------- */
1307 {
1308  bAnimContext ac;
1309 
1310  ListBase anim_data = {NULL, NULL};
1311  bAnimListElem *ale;
1312  int filter;
1313 
1316 
1317  /* get editor data */
1318  if (ANIM_animdata_get_context(C, &ac) == 0) {
1319  return OPERATOR_CANCELLED;
1320  }
1321 
1322  /* loop through all of the keys and select additional keyframes based on these */
1325  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1326 
1327  for (ale = anim_data.first; ale; ale = ale->next) {
1328  FCurve *fcu = (FCurve *)ale->key_data;
1329 
1330  /* check if anything selected? */
1331  if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, ok_cb, NULL)) {
1332  /* select every keyframe in this curve then */
1333  ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, sel_cb, NULL);
1334  }
1335  }
1336 
1337  /* Cleanup */
1338  ANIM_animdata_freelist(&anim_data);
1339 
1340  /* set notifier that keyframe selection has changed */
1342 
1343  return OPERATOR_FINISHED;
1344 }
1345 
1347 {
1348  /* identifiers */
1349  ot->name = "Select Linked";
1350  ot->idname = "GRAPH_OT_select_linked";
1351  ot->description = "Select keyframes occurring in the same F-Curves as selected ones";
1352 
1353  /* api callbacks */
1356 
1357  /* flags */
1359 }
1360 
1363 /* -------------------------------------------------------------------- */
1367 /* Common code to perform selection */
1368 static void select_moreless_graph_keys(bAnimContext *ac, short mode)
1369 {
1370  ListBase anim_data = {NULL, NULL};
1371  bAnimListElem *ale;
1372  int filter;
1373 
1374  KeyframeEditData ked;
1375  KeyframeEditFunc build_cb;
1376 
1377  /* init selmap building data */
1378  build_cb = ANIM_editkeyframes_buildselmap(mode);
1379  memset(&ked, 0, sizeof(KeyframeEditData));
1380 
1381  /* loop through all of the keys and select additional keyframes based on these */
1384  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1385 
1386  for (ale = anim_data.first; ale; ale = ale->next) {
1387  FCurve *fcu = (FCurve *)ale->key_data;
1388 
1389  /* only continue if F-Curve has keyframes */
1390  if (fcu->bezt == NULL) {
1391  continue;
1392  }
1393 
1394  /* build up map of whether F-Curve's keyframes should be selected or not */
1395  ked.data = MEM_callocN(fcu->totvert, "selmap graphEdit");
1396  ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, build_cb, NULL);
1397 
1398  /* based on this map, adjust the selection status of the keyframes */
1400 
1401  /* free the selmap used here */
1402  MEM_freeN(ked.data);
1403  ked.data = NULL;
1404  }
1405 
1406  /* Cleanup */
1407  ANIM_animdata_freelist(&anim_data);
1408 }
1409 
1410 /* ----------------- */
1411 
1413 {
1414  bAnimContext ac;
1415 
1416  /* get editor data */
1417  if (ANIM_animdata_get_context(C, &ac) == 0) {
1418  return OPERATOR_CANCELLED;
1419  }
1420 
1421  /* perform select changes */
1423 
1424  /* set notifier that keyframe selection has changed */
1426 
1427  return OPERATOR_FINISHED;
1428 }
1429 
1431 {
1432  /* identifiers */
1433  ot->name = "Select More";
1434  ot->idname = "GRAPH_OT_select_more";
1435  ot->description = "Select keyframes beside already selected ones";
1436 
1437  /* api callbacks */
1440 
1441  /* flags */
1443 }
1444 
1445 /* ----------------- */
1446 
1448 {
1449  bAnimContext ac;
1450 
1451  /* get editor data */
1452  if (ANIM_animdata_get_context(C, &ac) == 0) {
1453  return OPERATOR_CANCELLED;
1454  }
1455 
1456  /* perform select changes */
1458 
1459  /* set notifier that keyframe selection has changed */
1461 
1462  return OPERATOR_FINISHED;
1463 }
1464 
1466 {
1467  /* identifiers */
1468  ot->name = "Select Less";
1469  ot->idname = "GRAPH_OT_select_less";
1470  ot->description = "Deselect keyframes on ends of selection islands";
1471 
1472  /* api callbacks */
1475 
1476  /* flags */
1478 }
1479 
1482 /* -------------------------------------------------------------------- */
1488 /* defines for left-right select tool */
1490  {GRAPHKEYS_LRSEL_TEST, "CHECK", 0, "Check if Select Left or Right", ""},
1491  {GRAPHKEYS_LRSEL_LEFT, "LEFT", 0, "Before Current Frame", ""},
1492  {GRAPHKEYS_LRSEL_RIGHT, "RIGHT", 0, "After Current Frame", ""},
1493  {0, NULL, 0, NULL, NULL},
1494 };
1495 
1496 /* --------------------------------- */
1497 
1498 static void graphkeys_select_leftright(bAnimContext *ac, short leftright, short select_mode)
1499 {
1500  ListBase anim_data = {NULL, NULL};
1501  bAnimListElem *ale;
1502  int filter;
1503 
1504  KeyframeEditFunc ok_cb, select_cb;
1505  KeyframeEditData ked = {{NULL}};
1506  Scene *scene = ac->scene;
1507 
1508  /* if select mode is replace, deselect all keyframes (and channels) first */
1509  if (select_mode == SELECT_REPLACE) {
1510  select_mode = SELECT_ADD;
1511 
1512  /* - deselect all other keyframes, so that just the newly selected remain
1513  * - channels aren't deselected, since we don't re-select any as a consequence
1514  */
1515  deselect_graph_keys(ac, 0, SELECT_SUBTRACT, false);
1516  }
1517 
1518  /* set callbacks and editing data */
1520  select_cb = ANIM_editkeyframes_select(select_mode);
1521 
1522  if (leftright == GRAPHKEYS_LRSEL_LEFT) {
1523  ked.f1 = MINAFRAMEF;
1524  ked.f2 = (float)(scene->r.cfra + 0.1f);
1525  }
1526  else {
1527  ked.f1 = (float)(scene->r.cfra - 0.1f);
1528  ked.f2 = MAXFRAMEF;
1529  }
1530 
1531  /* filter data */
1533  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1534 
1535  /* select keys */
1536  for (ale = anim_data.first; ale; ale = ale->next) {
1537  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
1538 
1539  if (adt) {
1540  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
1541  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
1542  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
1543  }
1544  else {
1545  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
1546  }
1547  }
1548 
1549  /* Cleanup */
1550  ANIM_animdata_freelist(&anim_data);
1551 }
1552 
1553 /* ----------------- */
1554 
1556 {
1557  bAnimContext ac;
1558  short leftright = RNA_enum_get(op->ptr, "mode");
1559  short selectmode;
1560 
1561  /* get editor data */
1562  if (ANIM_animdata_get_context(C, &ac) == 0) {
1563  return OPERATOR_CANCELLED;
1564  }
1565 
1566  /* select mode is either replace (deselect all, then add) or add/extend */
1567  if (RNA_boolean_get(op->ptr, "extend")) {
1568  selectmode = SELECT_INVERT;
1569  }
1570  else {
1571  selectmode = SELECT_REPLACE;
1572  }
1573 
1574  /* if "test" mode is set, we don't have any info to set this with */
1575  if (leftright == GRAPHKEYS_LRSEL_TEST) {
1576  return OPERATOR_CANCELLED;
1577  }
1578 
1579  /* do the selecting now */
1580  graphkeys_select_leftright(&ac, leftright, selectmode);
1581 
1582  /* set notifier that keyframe selection (and channels too) have changed */
1585 
1586  return OPERATOR_FINISHED;
1587 }
1588 
1590 {
1591  bAnimContext ac;
1592  short leftright = RNA_enum_get(op->ptr, "mode");
1593 
1594  /* get editor data */
1595  if (ANIM_animdata_get_context(C, &ac) == 0) {
1596  return OPERATOR_CANCELLED;
1597  }
1598 
1599  /* handle mode-based testing */
1600  if (leftright == GRAPHKEYS_LRSEL_TEST) {
1601  Scene *scene = ac.scene;
1602  ARegion *region = ac.region;
1603  View2D *v2d = &region->v2d;
1604  float x;
1605 
1606  /* determine which side of the current frame mouse is on */
1607  x = UI_view2d_region_to_view_x(v2d, event->mval[0]);
1608  if (x < scene->r.cfra) {
1609  RNA_enum_set(op->ptr, "mode", GRAPHKEYS_LRSEL_LEFT);
1610  }
1611  else {
1612  RNA_enum_set(op->ptr, "mode", GRAPHKEYS_LRSEL_RIGHT);
1613  }
1614  }
1615 
1616  /* perform selection */
1617  return graphkeys_select_leftright_exec(C, op);
1618 }
1619 
1621 {
1622  PropertyRNA *prop;
1623 
1624  /* identifiers */
1625  ot->name = "Select Left/Right";
1626  ot->idname = "GRAPH_OT_select_leftright";
1627  ot->description = "Select keyframes to the left or the right of the current frame";
1628 
1629  /* api callbacks */
1633 
1634  /* flags */
1636 
1637  /* id-props */
1638  ot->prop = RNA_def_enum(
1641 
1642  prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
1644 }
1645 
1648 /* -------------------------------------------------------------------- */
1660 /* option 1) select keyframe directly under mouse */
1662  const int mval[2],
1663  eEditKeyframes_Select select_mode,
1664  const bool deselect_all,
1665  const bool curves_only,
1666  bool wait_to_deselect_others)
1667 {
1668  SpaceGraph *sipo = (SpaceGraph *)ac->sl;
1669  tNearestVertInfo *nvi;
1670  BezTriple *bezt = NULL;
1671  bool run_modal = false;
1672 
1673  /* find the beztriple that we're selecting, and the handle that was clicked on */
1674  nvi = find_nearest_fcurve_vert(ac, mval);
1675 
1676  if (select_mode != SELECT_REPLACE) {
1677  /* The modal execution to delay deselecting other items is only needed for normal click
1678  * selection, i.e. for SELECT_REPLACE. */
1679  wait_to_deselect_others = false;
1680  }
1681 
1684 
1685  const bool already_selected =
1686  (nvi != NULL) && (((nvi->hpoint == NEAREST_HANDLE_KEY) && (nvi->bezt->f2 & SELECT)) ||
1687  ((nvi->hpoint == NEAREST_HANDLE_LEFT) && (nvi->bezt->f1 & SELECT)) ||
1688  ((nvi->hpoint == NEAREST_HANDLE_RIGHT) && (nvi->bezt->f3 & SELECT)));
1689 
1690  if (wait_to_deselect_others && nvi && already_selected) {
1691  run_modal = true;
1692  }
1693  /* For replacing selection, if we have something to select, we have to clear existing selection.
1694  * The same goes if we found nothing to select, and deselect_all is true
1695  * (deselect on nothing behavior). */
1696  else if ((nvi != NULL && select_mode == SELECT_REPLACE) || (nvi == NULL && deselect_all)) {
1697  /* reset selection mode */
1698  select_mode = SELECT_ADD;
1699 
1700  /* deselect all other keyframes (+ F-Curves too) */
1701  deselect_graph_keys(ac, 0, SELECT_SUBTRACT, true);
1702 
1703  /* Deselect other channels too, but only do this if selection of channel
1704  * when the visibility of keyframes doesn't depend on this. */
1705  if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) {
1707  }
1708  }
1709 
1710  if (nvi == NULL) {
1711  return deselect_all ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
1712  }
1713 
1714  /* if points can be selected on this F-Curve */
1715  /* TODO: what about those with no keyframes? */
1716  bool something_was_selected = false;
1717  if (!curves_only && ((nvi->fcu->flag & FCURVE_PROTECTED) == 0)) {
1718  /* only if there's keyframe */
1719  if (nvi->bezt) {
1720  bezt = nvi->bezt; /* Used to check `bezt` selection is set. */
1721  if (select_mode == SELECT_INVERT) {
1722  if (nvi->hpoint == NEAREST_HANDLE_KEY) {
1723  bezt->f2 ^= SELECT;
1724  something_was_selected = (bezt->f2 & SELECT);
1725  }
1726  else if (nvi->hpoint == NEAREST_HANDLE_LEFT) {
1727  /* toggle selection */
1728  bezt->f1 ^= SELECT;
1729  something_was_selected = (bezt->f1 & SELECT);
1730  }
1731  else {
1732  /* toggle selection */
1733  bezt->f3 ^= SELECT;
1734  something_was_selected = (bezt->f3 & SELECT);
1735  }
1736  }
1737  else {
1738  if (nvi->hpoint == NEAREST_HANDLE_KEY) {
1739  bezt->f2 |= SELECT;
1740  }
1741  else if (nvi->hpoint == NEAREST_HANDLE_LEFT) {
1742  bezt->f1 |= SELECT;
1743  }
1744  else {
1745  bezt->f3 |= SELECT;
1746  }
1747  something_was_selected = true;
1748  }
1749 
1750  if (!run_modal && BEZT_ISSEL_ANY(bezt)) {
1751  const bool may_activate = !already_selected ||
1754  if (may_activate) {
1755  BKE_fcurve_active_keyframe_set(nvi->fcu, bezt);
1756  }
1757  }
1758  }
1759  else if (nvi->fpt) {
1760  /* TODO: need to handle sample points */
1761  }
1762  }
1763  else {
1764  KeyframeEditFunc select_cb;
1765  KeyframeEditData ked;
1766 
1767  /* initialize keyframe editing data */
1768  memset(&ked, 0, sizeof(KeyframeEditData));
1769 
1770  /* set up BezTriple edit callbacks */
1771  select_cb = ANIM_editkeyframes_select(select_mode);
1772 
1773  /* select all keyframes */
1774  ANIM_fcurve_keyframes_loop(&ked, nvi->fcu, NULL, select_cb, NULL);
1775  }
1776 
1777  /* only change selection of channel when the visibility of keyframes doesn't depend on this */
1778  if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) {
1779  /* select or deselect curve? */
1780  if (bezt) {
1781  /* take selection status from item that got hit, to prevent flip/flop on channel
1782  * selection status when shift-selecting (i.e. "SELECT_INVERT") points
1783  */
1784  if (BEZT_ISSEL_ANY(bezt)) {
1785  nvi->fcu->flag |= FCURVE_SELECTED;
1786  }
1787  else {
1788  nvi->fcu->flag &= ~FCURVE_SELECTED;
1789  }
1790  }
1791  else {
1792  /* Didn't hit any channel,
1793  * so just apply that selection mode to the curve's selection status. */
1794  if (select_mode == SELECT_INVERT) {
1795  nvi->fcu->flag ^= FCURVE_SELECTED;
1796  }
1797  else if (select_mode == SELECT_ADD) {
1798  nvi->fcu->flag |= FCURVE_SELECTED;
1799  }
1800  }
1801  }
1802 
1803  /* Set active F-Curve when something was actually selected (so not on a deselect), except when
1804  * dragging the selected keys. Needs to be called with (sipo->flag & SIPO_SELCUVERTSONLY),
1805  * otherwise the active flag won't be set T26452. */
1806  if (!run_modal && (nvi->fcu->flag & FCURVE_SELECTED) && something_was_selected) {
1807  /* NOTE: Sync the filter flags with findnearest_fcurve_vert. */
1810  ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nvi->fcu, nvi->ctype);
1811  }
1812 
1813  if (nvi->hpoint == NEAREST_HANDLE_LEFT) {
1815  }
1816  else if (nvi->hpoint == NEAREST_HANDLE_RIGHT) {
1818  }
1819 
1820  /* free temp sample data for filtering */
1821  MEM_freeN(nvi);
1822 
1823  return run_modal ? OPERATOR_RUNNING_MODAL : OPERATOR_FINISHED;
1824 }
1825 
1826 /* Option 2) Selects all the keyframes on either side of the current frame
1827  * (depends on which side the mouse is on) */
1828 /* (see graphkeys_select_leftright) */
1829 
1830 /* Option 3) Selects all visible keyframes in the same frame as the mouse click */
1832  const int mval[2],
1833  eEditKeyframes_Select select_mode,
1834  bool wait_to_deselect_others)
1835 {
1836  ListBase anim_data = {NULL, NULL};
1837  bAnimListElem *ale;
1838  int filter;
1839  bool run_modal = false;
1840 
1841  KeyframeEditFunc select_cb, ok_cb;
1842  KeyframeEditData ked;
1843  tNearestVertInfo *nvi;
1844 
1845  /* find the beztriple that we're selecting, and the handle that was clicked on */
1846  nvi = find_nearest_fcurve_vert(ac, mval);
1847 
1848  /* check if anything to select */
1849  if (nvi == NULL) {
1850  return OPERATOR_CANCELLED;
1851  }
1852 
1853  /* get frame number on which elements should be selected */
1854  /* TODO: should we restrict to integer frames only? */
1855  const float selx = nvi->frame;
1856 
1857  if (select_mode != SELECT_REPLACE) {
1858  /* Doesn't need to deselect anything -> Pass. */
1859  }
1860  else if (wait_to_deselect_others && (nvi->bezt->f2 & SELECT)) {
1861  run_modal = true;
1862  }
1863  /* If select mode is replace (and we don't do delayed deselection on mouse release), deselect all
1864  * keyframes first. */
1865  else {
1866  /* reset selection mode to add to selection */
1867  select_mode = SELECT_ADD;
1868 
1869  /* - deselect all other keyframes, so that just the newly selected remain
1870  * - channels aren't deselected, since we don't re-select any as a consequence
1871  */
1872  deselect_graph_keys(ac, 0, SELECT_SUBTRACT, false);
1873  }
1874 
1875  /* initialize keyframe editing data */
1876  memset(&ked, 0, sizeof(KeyframeEditData));
1877 
1878  /* set up BezTriple edit callbacks */
1879  select_cb = ANIM_editkeyframes_select(select_mode);
1881 
1882  /* loop through all of the keys and select additional keyframes
1883  * based on the keys found to be selected above
1884  */
1887  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1888 
1889  for (ale = anim_data.first; ale; ale = ale->next) {
1890  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
1891 
1892  /* set frame for validation callback to refer to */
1893  if (adt) {
1895  }
1896  else {
1897  ked.f1 = selx;
1898  }
1899 
1900  /* select elements with frame number matching cfra */
1901  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
1902  }
1903 
1904  /* free elements */
1905  MEM_freeN(nvi);
1906  BLI_freelistN(&ked.list);
1907  ANIM_animdata_freelist(&anim_data);
1908 
1909  return run_modal ? OPERATOR_RUNNING_MODAL : OPERATOR_FINISHED;
1910 }
1911 
1914 /* -------------------------------------------------------------------- */
1919 {
1920  bAnimContext ac;
1921 
1922  /* get editor data */
1923  if (ANIM_animdata_get_context(C, &ac) == 0) {
1924  return OPERATOR_CANCELLED;
1925  }
1926 
1927  /* select mode is either replace (deselect all, then add) or add/extend */
1928  const short selectmode = RNA_boolean_get(op->ptr, "extend") ? SELECT_INVERT : SELECT_REPLACE;
1929  const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
1930  /* See #WM_operator_properties_generic_select() for a detailed description of the how and why of
1931  * this. */
1932  const bool wait_to_deselect_others = RNA_boolean_get(op->ptr, "wait_to_deselect_others");
1933  int mval[2];
1934  int ret_val;
1935 
1936  mval[0] = RNA_int_get(op->ptr, "mouse_x");
1937  mval[1] = RNA_int_get(op->ptr, "mouse_y");
1938 
1939  /* figure out action to take */
1940  if (RNA_boolean_get(op->ptr, "column")) {
1941  /* select all keyframes in the same frame as the one that was under the mouse */
1942  ret_val = graphkeys_mselect_column(&ac, mval, selectmode, wait_to_deselect_others);
1943  }
1944  else if (RNA_boolean_get(op->ptr, "curves")) {
1945  /* select all keyframes in the same F-Curve as the one under the mouse */
1946  ret_val = mouse_graph_keys(&ac, mval, selectmode, deselect_all, true, wait_to_deselect_others);
1947  }
1948  else {
1949  /* select keyframe under mouse */
1950  ret_val = mouse_graph_keys(
1951  &ac, mval, selectmode, deselect_all, false, wait_to_deselect_others);
1952  }
1953 
1954  /* set notifier that keyframe selection (and also channel selection in some cases) has
1955  * changed */
1958 
1959  /* for tweak grab to work */
1960  return ret_val | OPERATOR_PASS_THROUGH;
1961 }
1962 
1964 {
1965  PropertyRNA *prop;
1966 
1967  /* identifiers */
1968  ot->name = "Select Keyframes";
1969  ot->idname = "GRAPH_OT_clickselect";
1970  ot->description = "Select keyframes by clicking on them";
1971 
1972  /* callbacks */
1977 
1978  /* flags */
1979  ot->flag = OPTYPE_UNDO;
1980 
1981  /* properties */
1983 
1984  /* Key-map: Enable with `Shift`. */
1985  prop = RNA_def_boolean(ot->srna,
1986  "extend",
1987  0,
1988  "Extend Select",
1989  "Toggle keyframe selection instead of leaving newly selected "
1990  "keyframes only");
1992 
1993  prop = RNA_def_boolean(ot->srna,
1994  "deselect_all",
1995  false,
1996  "Deselect On Nothing",
1997  "Deselect all when nothing under the cursor");
1999 
2000  /* Key-map: Enable with `Alt`. */
2001  prop = RNA_def_boolean(ot->srna,
2002  "column",
2003  0,
2004  "Column Select",
2005  "Select all keyframes that occur on the same frame as the one under "
2006  "the mouse");
2008 
2009  /* Key-map: Enable with `Ctrl-Atl`. */
2010  prop = RNA_def_boolean(
2011  ot->srna, "curves", 0, "Only Curves", "Select all the keyframes in the curve");
2013 }
2014 
typedef float(TangentPoint)[2]
void BKE_fcurve_active_keyframe_set(struct FCurve *fcu, const struct BezTriple *active_bezt)
float evaluate_fcurve(struct FCurve *fcu, float evaltime)
Definition: fcurve.c:2135
int BKE_fcurve_active_keyframe_index(const struct FCurve *fcu)
@ 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
void BLI_lasso_boundbox(struct rcti *rect, const int mcoords[][2], unsigned int mcoords_len)
Definition: lasso_2d.c:15
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
void * BLI_pophead(ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:221
#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 void BLI_INLINE bool BLI_listbase_is_single(const struct ListBase *lb)
Definition: BLI_listbase.h:265
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
MINLINE float len_v2v2_int(const int v1[2], const int v2[2])
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 FCURVE_ACTIVE_KEYFRAME_NONE
@ FCURVE_ACTIVE
@ FCURVE_SELECTED
@ FCURVE_PROTECTED
#define BEZT_ISSEL_ANY(bezt)
@ BEZT_IPO_BEZ
#define MAXFRAMEF
#define MINAFRAMEF
@ SIPO_SELCUVERTSONLY
@ SIPO_SELVHANDLESONLY
@ SIPO_NOHANDLES
@ SIPO_RUNTIME_FLAG_TWEAK_HANDLES_RIGHT
@ SIPO_RUNTIME_FLAG_TWEAK_HANDLES_LEFT
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
@ ACHANNEL_SETFLAG_CLEAR
Definition: ED_anim_api.h:550
eAnim_ChannelType
Definition: ED_anim_api.h:189
@ ANIMTYPE_FCURVE
Definition: ED_anim_api.h:199
@ ANIMFILTER_FOREDIT
Definition: ED_anim_api.h:312
@ ANIMFILTER_DATA_VISIBLE
Definition: ED_anim_api.h:292
@ ANIMFILTER_CURVE_VISIBLE
Definition: ED_anim_api.h:297
@ ANIMFILTER_SELEDIT
Definition: ED_anim_api.h:315
@ ANIMFILTER_NODUPLIS
Definition: ED_anim_api.h:325
@ ANIMFILTER_FCURVESONLY
Definition: ED_anim_api.h:328
@ ANIMFILTER_SEL
Definition: ED_anim_api.h:308
@ ANIM_UNITCONV_ONLYKEYS
Definition: ED_anim_api.h:934
@ KEYFRAME_OK_KEY
@ KEYFRAME_OK_H1
@ KEYFRAME_OK_H2
@ BEZT_OK_FRAMERANGE
@ BEZT_OK_FRAME
@ BEZT_OK_VALUERANGE
@ BEZT_OK_SELECTED
@ BEZT_OK_REGION_LASSO
@ BEZT_OK_REGION_CIRCLE
@ BEZT_OK_REGION
@ KEYFRAME_ITER_HANDLES_DEFAULT_INVISIBLE
@ KEYFRAME_ITER_INCL_HANDLES
short(* KeyframeEditFunc)(KeyframeEditData *ked, struct BezTriple *bezt)
@ SELMAP_MORE
@ SELMAP_LESS
eEditKeyframes_Select
@ SELECT_INVERT
@ SELECT_SUBTRACT
@ SELECT_REPLACE
@ SELECT_ADD
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_region_to_view_rctf(const struct View2D *v2d, const struct rctf *rect_src, struct rctf *rect_dst) ATTR_NONNULL()
bool UI_view2d_view_to_region_clip(const struct View2D *v2d, float x, float y, int *r_region_x, int *r_region_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
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
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
float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short flag, float *r_offset)
Definition: anim_draw.c:485
short ANIM_get_normalization_flags(bAnimContext *ac)
Definition: anim_draw.c:318
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
#define SELECT
Scene scene
@ GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN
Definition: graph_intern.h:82
@ GRAPHKEYS_COLUMNSEL_KEYS
Definition: graph_intern.h:79
@ GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN
Definition: graph_intern.h:81
@ GRAPHKEYS_COLUMNSEL_CFRA
Definition: graph_intern.h:80
@ GRAPHKEYS_LRSEL_TEST
Definition: graph_intern.h:72
@ GRAPHKEYS_LRSEL_RIGHT
Definition: graph_intern.h:74
@ GRAPHKEYS_LRSEL_LEFT
Definition: graph_intern.h:73
struct bAnimListElem * get_active_fcurve_channel(struct bAnimContext *ac)
Definition: graph_utils.c:81
bool graphop_visible_keyframes_poll(struct bContext *C)
Definition: graph_utils.c:111
#define INSIDE
Definition: graph_select.c:668
void GRAPH_OT_select_box(wmOperatorType *ot)
Definition: graph_select.c:880
static int graphkeys_box_select_exec(bContext *C, wmOperator *op)
Definition: graph_select.c:821
void GRAPH_OT_select_column(wmOperatorType *ot)
static void nearest_fcurve_vert_store(ListBase *matches, View2D *v2d, FCurve *fcu, eAnim_ChannelType ctype, BezTriple *bezt, FPoint *fpt, short hpoint, const int mval[2], float unit_scale, float offset)
Definition: graph_select.c:94
#define BELOW
Definition: graph_select.c:669
static rctf initialize_box_select_coords(const bAnimContext *ac, const rctf *rectf_view)
Definition: graph_select.c:490
static int rectf_curve_zone_y(FCurve *fcu, const rctf *rectf, const float offset, const float unit_scale, const float eval_x)
Definition: graph_select.c:670
static int graphkeys_clickselect_exec(bContext *C, wmOperator *op)
static const EnumPropertyItem prop_graphkeys_leftright_select_types[]
static void graphkeys_select_leftright(bAnimContext *ac, short leftright, short select_mode)
void GRAPH_OT_select_lasso(wmOperatorType *ot)
Definition: graph_select.c:986
static int graphkeys_select_leftright_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static tNearestVertInfo * get_best_nearest_fcurve_vert(ListBase *matches)
Definition: graph_select.c:261
static void box_select_graphcurves(bAnimContext *ac, const rctf *rectf_view, const short mode, const short selectmode, const bool incl_handles, void *data)
Definition: graph_select.c:731
void deselect_graph_keys(bAnimContext *ac, bool test, short sel, bool do_channels)
Definition: graph_select.c:335
#define ABOVE
Definition: graph_select.c:667
static tNearestVertInfo * find_nearest_fcurve_vert(bAnimContext *ac, const int mval[2])
Definition: graph_select.c:307
static int graphkeys_select_leftright_exec(bContext *C, wmOperator *op)
static int graphkeys_lassoselect_exec(bContext *C, wmOperator *op)
Definition: graph_select.c:928
void GRAPH_OT_select_circle(wmOperatorType *ot)
void GRAPH_OT_clickselect(wmOperatorType *ot)
static int graphkeys_mselect_column(bAnimContext *ac, const int mval[2], eEditKeyframes_Select select_mode, bool wait_to_deselect_others)
static int initialize_animdata_selection_filter(const SpaceGraph *sipo)
Definition: graph_select.c:501
void GRAPH_OT_select_more(wmOperatorType *ot)
struct tNearestVertInfo tNearestVertInfo
static int graphkeys_deselectall_exec(bContext *C, wmOperator *op)
Definition: graph_select.c:402
static short ok_bezier_always_ok(KeyframeEditData *UNUSED(ked), BezTriple *UNUSED(bezt))
Definition: graph_select.c:662
static int graphkeys_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
static int mouse_graph_keys(bAnimContext *ac, const int mval[2], eEditKeyframes_Select select_mode, const bool deselect_all, const bool curves_only, bool wait_to_deselect_others)
static void initialize_box_select_key_editing_data(const SpaceGraph *sipo, const bool incl_handles, const short mode, bAnimContext *ac, void *data, rctf *scaled_rectf, KeyframeEditData *r_ked, int *r_mapping_flag)
Definition: graph_select.c:518
#define GVERTSEL_TOL
Definition: graph_select.c:75
static bool box_select_graphkeys(bAnimContext *ac, const rctf *rectf_view, short mode, short selectmode, bool incl_handles, void *data)
Definition: graph_select.c:571
void GRAPH_OT_select_linked(wmOperatorType *ot)
static void markers_selectkeys_between(bAnimContext *ac)
static int graph_circle_select_exec(bContext *C, wmOperator *op)
static bool rectf_curve_intersection(const float offset, const float unit_scale, const rctf *rectf, AnimData *adt, FCurve *fcu)
Definition: graph_select.c:681
void GRAPH_OT_select_leftright(wmOperatorType *ot)
static int graphkeys_box_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: graph_select.c:797
static ListBase initialize_box_select_anim_data(const int filter, bAnimContext *ac)
Definition: graph_select.c:511
eGraphVertIndex
Definition: graph_select.c:67
@ NEAREST_HANDLE_LEFT
Definition: graph_select.c:68
@ NEAREST_HANDLE_KEY
Definition: graph_select.c:69
@ NEAREST_HANDLE_RIGHT
Definition: graph_select.c:70
static bool fcurve_handle_sel_check(SpaceGraph *sipo, BezTriple *bezt)
Definition: graph_select.c:81
static int graphkeys_select_less_exec(bContext *C, wmOperator *UNUSED(op))
static void select_moreless_graph_keys(bAnimContext *ac, short mode)
void GRAPH_OT_select_all(wmOperatorType *ot)
Definition: graph_select.c:457
static const EnumPropertyItem prop_column_select_types[]
static void columnselect_graph_keys(bAnimContext *ac, short mode)
static int graphkeys_select_more_exec(bContext *C, wmOperator *UNUSED(op))
static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], ListBase *matches)
Definition: graph_select.c:161
static int graphkeys_columnselect_exec(bContext *C, wmOperator *op)
void GRAPH_OT_select_less(wmOperatorType *ot)
DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
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_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:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
SymEdge< T > * prev(const SymEdge< T > *se)
Definition: delaunay_2d.cc:105
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
float vec[3][3]
uint8_t f2
float cfra
Definition: BKE_fcurve.h:40
struct CfraElem * next
Definition: BKE_fcurve.h:39
FPoint * fpt
BezTriple * bezt
short flag
unsigned int totvert
struct FCurve * fcu
eKeyframeIterFlags iterflags
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
struct RenderData r
SpaceGraph_Runtime runtime
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
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 ID * id
Definition: ED_anim_api.h:160
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
BezTriple * bezt
Definition: graph_select.c:54
eAnim_ChannelType ctype
Definition: graph_select.c:61
struct tNearestVertInfo * prev
Definition: graph_select.c:50
struct tNearestVertInfo * next
Definition: graph_select.c:50
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