Blender  V2.93
graph_select.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2008 Blender Foundation
17  */
18 
23 #include <float.h>
24 #include <math.h>
25 #include <stdlib.h>
26 #include <string.h>
27 
28 #include "MEM_guardedalloc.h"
29 
30 #include "BLI_blenlib.h"
31 #include "BLI_lasso_2d.h"
32 #include "BLI_math.h"
33 #include "BLI_utildefines.h"
34 
35 #include "DNA_anim_types.h"
36 #include "DNA_scene_types.h"
37 #include "DNA_screen_types.h"
38 #include "DNA_space_types.h"
39 
40 #include "RNA_access.h"
41 #include "RNA_define.h"
42 
43 #include "BKE_context.h"
44 #include "BKE_fcurve.h"
45 #include "BKE_nla.h"
46 
47 #include "UI_view2d.h"
48 
49 #include "ED_anim_api.h"
50 #include "ED_keyframes_edit.h"
51 #include "ED_markers.h"
52 #include "ED_select_utils.h"
53 
54 #include "WM_api.h"
55 #include "WM_types.h"
56 
57 #include "graph_intern.h"
58 
59 /* ************************************************************************** */
60 /* KEYFRAMES STUFF */
61 
62 /* temp info for caching handle vertices close */
63 typedef struct tNearestVertInfo {
65 
66  FCurve *fcu; /* F-Curve that keyframe comes from */
67 
68  BezTriple *bezt; /* keyframe to consider */
69  FPoint *fpt; /* sample point to consider */
70 
71  short hpoint; /* the handle index that we hit (eHandleIndex) */
72  short sel; /* whether the handle is selected or not */
73  int dist; /* distance from mouse to vert */
74 
75  eAnim_ChannelType ctype; /* type of animation channel this FCurve comes from */
76 
77  float frame; /* frame that point was on when it matched (global time) */
79 
80 /* Tags for the type of graph vert that we have */
81 typedef enum eGraphVertIndex {
86 
87 /* Tolerance for absolute radius (in pixels) of the vert from the cursor to use */
88 /* TODO: perhaps this should depend a bit on the size that the user set the vertices to be? */
89 #define GVERTSEL_TOL (10 * U.pixelsize)
90 
91 /* ....... */
92 
93 /* check if its ok to select a handle */
94 /* XXX also need to check for int-values only? */
96 {
97  if (sipo->flag & SIPO_NOHANDLES) {
98  return false;
99  }
100  if ((sipo->flag & SIPO_SELVHANDLESONLY) && BEZT_ISSEL_ANY(bezt) == 0) {
101  return false;
102  }
103  return true;
104 }
105 
106 /* check if the given vertex is within bounds or not */
107 /* TODO: should we return if we hit something? */
108 static void nearest_fcurve_vert_store(ListBase *matches,
109  View2D *v2d,
110  FCurve *fcu,
112  BezTriple *bezt,
113  FPoint *fpt,
114  short hpoint,
115  const int mval[2],
116  float unit_scale,
117  float offset)
118 {
119  /* Keyframes or Samples? */
120  if (bezt) {
121  int screen_co[2], dist;
122 
123  /* convert from data-space to screen coordinates
124  * NOTE: hpoint+1 gives us 0,1,2 respectively for each handle,
125  * needed to access the relevant vertex coordinates in the 3x3
126  * 'vec' matrix
127  */
129  bezt->vec[hpoint + 1][0],
130  (bezt->vec[hpoint + 1][1] + offset) * unit_scale,
131  &screen_co[0],
132  &screen_co[1]) &&
133  /* check if distance from mouse cursor to vert in screen space is within tolerance */
134  ((dist = len_v2v2_int(mval, screen_co)) <= GVERTSEL_TOL)) {
135  tNearestVertInfo *nvi = (tNearestVertInfo *)matches->last;
136  bool replace = false;
137 
138  /* If there is already a point for the F-Curve,
139  * check if this point is closer than that was. */
140  if ((nvi) && (nvi->fcu == fcu)) {
141  /* replace if we are closer, or if equal and that one wasn't selected but we are... */
142  if ((nvi->dist > dist) || ((nvi->sel == 0) && BEZT_ISSEL_ANY(bezt))) {
143  replace = 1;
144  }
145  }
146  /* add new if not replacing... */
147  if (replace == 0) {
148  nvi = MEM_callocN(sizeof(tNearestVertInfo), "Nearest Graph Vert Info - Bezt");
149  }
150 
151  /* store values */
152  nvi->fcu = fcu;
153  nvi->ctype = ctype;
154 
155  nvi->bezt = bezt;
156  nvi->hpoint = hpoint;
157  nvi->dist = dist;
158 
159  nvi->frame = bezt->vec[1][0]; /* currently in global time... */
160 
161  nvi->sel = BEZT_ISSEL_ANY(bezt); /* XXX... should this use the individual verts instead? */
162 
163  /* add to list of matches if appropriate... */
164  if (replace == 0) {
165  BLI_addtail(matches, nvi);
166  }
167  }
168  }
169  else if (fpt) {
170  /* TODO... */
171  }
172 }
173 
174 /* helper for find_nearest_fcurve_vert() - build the list of nearest matches */
175 static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], ListBase *matches)
176 {
177  ListBase anim_data = {NULL, NULL};
178  bAnimListElem *ale;
179  int filter;
180 
181  SpaceGraph *sipo = (SpaceGraph *)ac->sl;
182  View2D *v2d = &ac->region->v2d;
183  short mapping_flag = 0;
184 
185  /* get curves to search through
186  * - if the option to only show keyframes that belong to selected F-Curves is enabled,
187  * include the 'only selected' flag...
188  */
190  if (sipo->flag &
191  SIPO_SELCUVERTSONLY) { /* FIXME: this should really be check for by the filtering code... */
193  }
194  mapping_flag |= ANIM_get_normalization_flags(ac);
195  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
196 
197  for (ale = anim_data.first; ale; ale = ale->next) {
198  FCurve *fcu = (FCurve *)ale->key_data;
199  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
200  float offset;
201  float unit_scale = ANIM_unit_mapping_get_factor(
202  ac->scene, ale->id, fcu, mapping_flag, &offset);
203 
204  /* apply NLA mapping to all the keyframes */
205  if (adt) {
206  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
207  }
208 
209  if (fcu->bezt) {
210  BezTriple *bezt1 = fcu->bezt, *prevbezt = NULL;
211  int i;
212 
213  for (i = 0; i < fcu->totvert; i++, prevbezt = bezt1, bezt1++) {
214  /* keyframe */
216  v2d,
217  fcu,
218  ale->type,
219  bezt1,
220  NULL,
222  mval,
223  unit_scale,
224  offset);
225 
226  /* handles - only do them if they're visible */
227  if (fcurve_handle_sel_check(sipo, bezt1) && (fcu->totvert > 1)) {
228  /* first handle only visible if previous segment had handles */
229  if ((!prevbezt && (bezt1->ipo == BEZT_IPO_BEZ)) ||
230  (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {
232  v2d,
233  fcu,
234  ale->type,
235  bezt1,
236  NULL,
238  mval,
239  unit_scale,
240  offset);
241  }
242 
243  /* second handle only visible if this segment is bezier */
244  if (bezt1->ipo == BEZT_IPO_BEZ) {
246  v2d,
247  fcu,
248  ale->type,
249  bezt1,
250  NULL,
252  mval,
253  unit_scale,
254  offset);
255  }
256  }
257  }
258  }
259  else if (fcu->fpt) {
260  /* TODO; do this for samples too */
261  }
262 
263  /* un-apply NLA mapping from all the keyframes */
264  if (adt) {
265  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
266  }
267  }
268 
269  /* free channels */
270  ANIM_animdata_freelist(&anim_data);
271 }
272 
273 /* helper for find_nearest_fcurve_vert() - get the best match to use */
275 {
276  tNearestVertInfo *nvi = NULL;
277  short found = 0;
278 
279  /* abort if list is empty */
280  if (BLI_listbase_is_empty(matches)) {
281  return NULL;
282  }
283 
284  /* if list only has 1 item, remove it from the list and return */
285  if (BLI_listbase_is_single(matches)) {
286  /* need to remove from the list, otherwise it gets freed and then we can't return it */
287  return BLI_pophead(matches);
288  }
289 
290  /* try to find the first selected F-Curve vert, then take the one after it */
291  for (nvi = matches->first; nvi; nvi = nvi->next) {
292  /* which mode of search are we in: find first selected, or find vert? */
293  if (found) {
294  /* Just take this vert now that we've found the selected one
295  * - We'll need to remove this from the list
296  * so that it can be returned to the original caller.
297  */
298  BLI_remlink(matches, nvi);
299  return nvi;
300  }
301 
302  /* if vert is selected, we've got what we want... */
303  if (nvi->sel) {
304  found = 1;
305  }
306  }
307 
308  /* if we're still here, this means that we failed to find anything appropriate in the first pass,
309  * so just take the first item now...
310  */
311  return BLI_pophead(matches);
312 }
313 
321 {
322  ListBase matches = {NULL, NULL};
323  tNearestVertInfo *nvi;
324 
325  /* step 1: get the nearest verts */
326  get_nearest_fcurve_verts_list(ac, mval, &matches);
327 
328  /* step 2: find the best vert */
329  nvi = get_best_nearest_fcurve_vert(&matches);
330 
331  BLI_freelistN(&matches);
332 
333  /* return the best vert found */
334  return nvi;
335 }
336 
337 /* ******************** Deselect All Operator ***************************** */
338 /* This operator works in one of three ways:
339  * 1) (de)select all (AKEY) - test if select all or deselect all
340  * 2) invert all (CTRL-IKEY) - invert selection of all keyframes
341  * 3) (de)select all - no testing is done; only for use internal tools as normal function...
342  */
343 
344 /* Deselects keyframes in the Graph Editor
345  * - This is called by the deselect all operator, as well as other ones!
346  *
347  * - test: check if select or deselect all
348  * - sel: how to select keyframes
349  * 0 = deselect
350  * 1 = select
351  * 2 = invert
352  * - do_channels: whether to affect selection status of channels
353  */
354 void deselect_graph_keys(bAnimContext *ac, bool test, short sel, bool do_channels)
355 {
356  ListBase anim_data = {NULL, NULL};
357  bAnimListElem *ale;
358  int filter;
359 
360  SpaceGraph *sipo = (SpaceGraph *)ac->sl;
361  KeyframeEditData ked = {{NULL}};
362  KeyframeEditFunc test_cb, sel_cb;
363 
364  /* determine type-based settings */
366 
367  /* filter data */
368  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
369 
370  /* init BezTriple looping data */
372 
373  /* See if we should be selecting or deselecting */
374  if (test) {
375  for (ale = anim_data.first; ale; ale = ale->next) {
376  if (ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, test_cb, NULL)) {
378  break;
379  }
380  }
381  }
382 
383  /* convert sel to selectmode, and use that to get editor */
384  sel_cb = ANIM_editkeyframes_select(sel);
385 
386  /* Now set the flags */
387  for (ale = anim_data.first; ale; ale = ale->next) {
388  FCurve *fcu = (FCurve *)ale->key_data;
389 
390  /* Keyframes First */
391  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL);
392 
393  /* affect channel selection status? */
394  if (do_channels) {
395  /* Only change selection of channel when the visibility of keyframes
396  * doesn't depend on this. */
397  if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) {
398  /* deactivate the F-Curve, and deselect if deselecting keyframes.
399  * otherwise select the F-Curve too since we've selected all the keyframes
400  */
401  if (sel == SELECT_SUBTRACT) {
402  fcu->flag &= ~FCURVE_SELECTED;
403  }
404  else {
406  }
407  }
408 
409  /* always deactivate all F-Curves if we perform batch ops for selection */
410  fcu->flag &= ~FCURVE_ACTIVE;
411  }
412  }
413 
414  /* Cleanup */
415  ANIM_animdata_freelist(&anim_data);
416 }
417 
418 /* ------------------- */
419 
421 {
422  bAnimContext ac;
423  bAnimListElem *ale_active = NULL;
424 
425  /* get editor data */
426  if (ANIM_animdata_get_context(C, &ac) == 0) {
427  return OPERATOR_CANCELLED;
428  }
429 
430  /* find active F-Curve, and preserve this for later
431  * or else it becomes annoying with the current active
432  * curve keeps fading out even while you're editing it
433  */
434  ale_active = get_active_fcurve_channel(&ac);
435 
436  /* 'standard' behavior - check if selected, then apply relevant selection */
437  const int action = RNA_enum_get(op->ptr, "action");
438  switch (action) {
439  case SEL_TOGGLE:
440  deselect_graph_keys(&ac, 1, SELECT_ADD, true);
441  break;
442  case SEL_SELECT:
443  deselect_graph_keys(&ac, 0, SELECT_ADD, true);
444  break;
445  case SEL_DESELECT:
446  deselect_graph_keys(&ac, 0, SELECT_SUBTRACT, true);
447  break;
448  case SEL_INVERT:
449  deselect_graph_keys(&ac, 0, SELECT_INVERT, true);
450  break;
451  default:
452  BLI_assert(0);
453  break;
454  }
455 
456  /* restore active F-Curve... */
457  if (ale_active) {
458  FCurve *fcu = (FCurve *)ale_active->data;
459 
460  /* all others should not be disabled, so we should be able to just set this directly...
461  * - selection needs to be set too, or else this won't work...
462  */
464 
465  MEM_freeN(ale_active);
466  ale_active = NULL;
467  }
468 
469  /* set notifier that things have changed */
471 
472  return OPERATOR_FINISHED;
473 }
474 
476 {
477  /* identifiers */
478  ot->name = "Select All";
479  ot->idname = "GRAPH_OT_select_all";
480  ot->description = "Toggle selection of all keyframes";
481 
482  /* api callbacks */
485 
486  /* flags */
488 
489  /* properties */
491 }
492 
493 /* ******************** Box Select Operator **************************** */
494 /* This operator currently works in one of three ways:
495  * -> BKEY - 1) all keyframes within region are selected (validation with BEZT_OK_REGION)
496  * -> ALT-BKEY - depending on which axis of the region was larger...
497  * -> 2) x-axis, so select all frames within frame range (validation with BEZT_OK_FRAMERANGE)
498  * -> 3) y-axis, so select all frames within channels that region included
499  * (validation with BEZT_OK_VALUERANGE).
500  *
501  * The selection backend is also reused for the Lasso and Circle select operators.
502  */
503 
504 static rctf initialize_box_select_coords(const bAnimContext *ac, const rctf *rectf_view)
505 {
506  const View2D *v2d = &ac->region->v2d;
507  rctf rectf;
508 
509  /* Convert mouse coordinates to frame ranges and
510  * channel coordinates corrected for view pan/zoom. */
511  UI_view2d_region_to_view_rctf(v2d, rectf_view, &rectf);
512  return rectf;
513 }
514 
516 {
517  ListBase anim_data = {NULL, NULL};
518 
520  if (sipo->flag & SIPO_SELCUVERTSONLY) {
522  }
523  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
524 
525  return anim_data;
526 }
527 
529  const bool incl_handles,
530  const short mode,
531  bAnimContext *ac,
532  void *data,
533  rctf *scaled_rectf,
534  KeyframeEditData *r_ked,
535  int *r_mapping_flag)
536 {
537  memset(r_ked, 0, sizeof(KeyframeEditData));
538  switch (mode) {
539  case BEZT_OK_REGION_LASSO: {
540  KeyframeEdit_LassoData *data_lasso = data;
541  data_lasso->rectf_scaled = scaled_rectf;
542  r_ked->data = data_lasso;
543  break;
544  }
545  case BEZT_OK_REGION_CIRCLE: {
546  KeyframeEdit_CircleData *data_circle = data;
547  data_circle->rectf_scaled = scaled_rectf;
548  r_ked->data = data_circle;
549  break;
550  }
551  default:
552  r_ked->data = scaled_rectf;
553  break;
554  }
555 
556  if (sipo->flag & SIPO_SELVHANDLESONLY) {
558  }
559 
560  /* Enable handles selection. (used in keyframes_edit.c > KEYFRAME_OK_CHECKS macro) */
561  if (incl_handles) {
563  *r_mapping_flag = 0;
564  }
565  else {
566  *r_mapping_flag = ANIM_UNITCONV_ONLYKEYS;
567  }
568 
569  *r_mapping_flag |= ANIM_get_normalization_flags(ac);
570 }
571 
572 /* Box Select only selects keyframes, as overshooting handles often get caught too,
573  * which means that they may be inadvertently moved as well. However, incl_handles overrides
574  * this, and allow handles to be considered independently too.
575  * Also, for convenience, handles should get same status as keyframe (if it was within bounds).
576  */
578  const rctf *rectf_view,
579  short mode,
580  short selectmode,
581  bool incl_handles,
582  void *data)
583 {
584  const rctf rectf = initialize_box_select_coords(ac, rectf_view);
585  SpaceGraph *sipo = (SpaceGraph *)ac->sl;
586  ListBase anim_data = initialize_box_select_anim_data(sipo, ac);
587  rctf scaled_rectf;
588  KeyframeEditData ked;
589  int mapping_flag;
591  sipo, incl_handles, mode, ac, data, &scaled_rectf, &ked, &mapping_flag);
592 
593  /* Get beztriple editing/validation funcs. */
594  const KeyframeEditFunc select_cb = ANIM_editkeyframes_select(selectmode);
595  const KeyframeEditFunc ok_cb = ANIM_editkeyframes_ok(mode);
596 
597  /* Try selecting the keyframes. */
598  bAnimListElem *ale = NULL;
599 
600  /* First loop over data, doing box select. try selecting keys only. */
601  for (ale = anim_data.first; ale; ale = ale->next) {
602  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
603  FCurve *fcu = (FCurve *)ale->key_data;
604  float offset;
605  const float unit_scale = ANIM_unit_mapping_get_factor(
606  ac->scene, ale->id, fcu, mapping_flag, &offset);
607 
608  /* Apply NLA mapping to all the keyframes, since it's easier than trying to
609  * guess when a callback might use something different.
610  */
611  if (adt) {
612  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, incl_handles == 0);
613  }
614 
615  scaled_rectf.xmin = rectf.xmin;
616  scaled_rectf.xmax = rectf.xmax;
617  scaled_rectf.ymin = rectf.ymin / unit_scale - offset;
618  scaled_rectf.ymax = rectf.ymax / unit_scale - offset;
619 
620  /* Set horizontal range (if applicable).
621  * NOTE: these values are only used for x-range and y-range but not region
622  * (which uses ked.data, i.e. rectf)
623  */
624  if (mode != BEZT_OK_VALUERANGE) {
625  ked.f1 = rectf.xmin;
626  ked.f2 = rectf.xmax;
627  }
628  else {
629  ked.f1 = rectf.ymin;
630  ked.f2 = rectf.ymax;
631  }
632 
633  /* Firstly, check if any keyframes will be hit by this. */
634  if (ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, ok_cb, NULL)) {
635  /* select keyframes that are in the appropriate places */
636  ANIM_fcurve_keyframes_loop(&ked, fcu, ok_cb, select_cb, NULL);
637 
638  /* Only change selection of channel when the visibility of keyframes
639  * doesn't depend on this. */
640  if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) {
641  /* select the curve too now that curve will be touched */
642  if (selectmode == SELECT_ADD) {
644  }
645  }
646  }
647 
648  /* Un-apply NLA mapping from all the keyframes. */
649  if (adt) {
650  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, incl_handles == 0);
651  }
652  }
653 
654  /* Cleanup. */
655  ANIM_animdata_freelist(&anim_data);
656 }
657 
658 /* ------------------- */
659 
660 static int graphkeys_box_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
661 {
662  bAnimContext ac;
663  if (ANIM_animdata_get_context(C, &ac) == 0) {
664  return OPERATOR_CANCELLED;
665  }
666 
667  if (RNA_boolean_get(op->ptr, "tweak")) {
668  tNearestVertInfo *under_mouse = find_nearest_fcurve_vert(&ac, event->mval);
669  bool mouse_is_over_element = under_mouse != NULL;
670  if (under_mouse) {
671  MEM_freeN(under_mouse);
672  }
673 
674  if (mouse_is_over_element) {
676  }
677  }
678 
679  return WM_gesture_box_invoke(C, op, event);
680 }
681 
683 {
684  bAnimContext ac;
685  rcti rect;
686  rctf rect_fl;
687  short mode = 0;
688 
689  /* get editor data */
690  if (ANIM_animdata_get_context(C, &ac) == 0) {
691  return OPERATOR_CANCELLED;
692  }
693 
694  const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
695  const int selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
696  if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
697  deselect_graph_keys(&ac, 1, SELECT_SUBTRACT, true);
698  }
699 
700  /* 'include_handles' from the operator specifies whether to include handles in the selection. */
701  const bool incl_handles = RNA_boolean_get(op->ptr, "include_handles");
702 
703  /* Get settings from operator. */
705 
706  /* Selection 'mode' depends on whether box_select region only matters on one axis. */
707  if (RNA_boolean_get(op->ptr, "axis_range")) {
708  /* Mode depends on which axis of the range is larger to determine which axis to use
709  * - Checking this in region-space is fine, as it's fundamentally still going to be a
710  * different rect size.
711  * - The frame-range select option is favored over the channel one (x over y),
712  * as frame-range one is often used for tweaking timing when "blocking",
713  * while channels is not that useful.
714  */
715  if ((BLI_rcti_size_x(&rect)) >= (BLI_rcti_size_y(&rect))) {
716  mode = BEZT_OK_FRAMERANGE;
717  }
718  else {
719  mode = BEZT_OK_VALUERANGE;
720  }
721  }
722  else {
723  mode = BEZT_OK_REGION;
724  }
725 
726  BLI_rctf_rcti_copy(&rect_fl, &rect);
727 
728  /* Apply box_select action. */
729  box_select_graphkeys(&ac, &rect_fl, mode, selectmode, incl_handles, NULL);
730  /* Send notifier that keyframe selection has changed. */
732 
733  return OPERATOR_FINISHED;
734 }
735 
737 {
738  /* Identifiers. */
739  ot->name = "Box Select";
740  ot->idname = "GRAPH_OT_select_box";
741  ot->description = "Select all keyframes within the specified region";
742 
743  /* API callbacks. */
748 
750 
751  /* Flags. */
753 
754  /* Properties. */
755  ot->prop = RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
757 
758  PropertyRNA *prop;
759  prop = RNA_def_boolean(ot->srna,
760  "include_handles",
761  true,
762  "Include Handles",
763  "Are handles tested individually against the selection criteria");
765 
766  prop = RNA_def_boolean(
767  ot->srna, "tweak", 0, "Tweak", "Operator has been activated using a tweak event");
769 
772 }
773 
774 /* ------------------- */
775 
777 {
778  bAnimContext ac;
779 
780  KeyframeEdit_LassoData data_lasso = {0};
781  rcti rect;
782  rctf rect_fl;
783 
784  bool incl_handles;
785 
786  /* Get editor data. */
787  if (ANIM_animdata_get_context(C, &ac) == 0) {
788  return OPERATOR_CANCELLED;
789  }
790 
791  data_lasso.rectf_view = &rect_fl;
792  data_lasso.mcoords = WM_gesture_lasso_path_to_array(C, op, &data_lasso.mcoords_len);
793  if (data_lasso.mcoords == NULL) {
794  return OPERATOR_CANCELLED;
795  }
796 
797  const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
798  const short selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
799  if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
800  deselect_graph_keys(&ac, 0, SELECT_SUBTRACT, true);
801  }
802 
803  {
804  SpaceGraph *sipo = (SpaceGraph *)ac.sl;
805  if (selectmode == SELECT_ADD) {
806  incl_handles = ((sipo->flag & SIPO_SELVHANDLESONLY) || (sipo->flag & SIPO_NOHANDLES)) == 0;
807  }
808  else {
809  incl_handles = (sipo->flag & SIPO_NOHANDLES) == 0;
810  }
811  }
812 
813  /* Get settings from operator. */
814  BLI_lasso_boundbox(&rect, data_lasso.mcoords, data_lasso.mcoords_len);
815  BLI_rctf_rcti_copy(&rect_fl, &rect);
816 
817  /* Apply box_select action. */
818  box_select_graphkeys(&ac, &rect_fl, BEZT_OK_REGION_LASSO, selectmode, incl_handles, &data_lasso);
819 
820  MEM_freeN((void *)data_lasso.mcoords);
821 
822  /* Send notifier that keyframe selection has changed. */
824 
825  return OPERATOR_FINISHED;
826 }
827 
829 {
830  /* Identifiers. */
831  ot->name = "Lasso Select";
832  ot->description = "Select keyframe points using lasso selection";
833  ot->idname = "GRAPH_OT_select_lasso";
834 
835  /* API callbacks. */
841 
842  /* Flags. */
843  ot->flag = OPTYPE_UNDO;
844 
845  /* Properties. */
848 }
849 
850 /* ------------------- */
851 
853 {
854  bAnimContext ac;
855  bool incl_handles = false;
856 
858  rctf rect_fl;
859 
860  float x = RNA_int_get(op->ptr, "x");
861  float y = RNA_int_get(op->ptr, "y");
862  float radius = RNA_int_get(op->ptr, "radius");
863 
864  /* Get editor data. */
865  if (ANIM_animdata_get_context(C, &ac) == 0) {
866  return OPERATOR_CANCELLED;
867  }
868 
869  const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"),
871  const short selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
872  if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
873  deselect_graph_keys(&ac, 0, SELECT_SUBTRACT, true);
874  }
875 
876  data.mval[0] = x;
877  data.mval[1] = y;
878  data.radius_squared = radius * radius;
879  data.rectf_view = &rect_fl;
880 
881  rect_fl.xmin = x - radius;
882  rect_fl.xmax = x + radius;
883  rect_fl.ymin = y - radius;
884  rect_fl.ymax = y + radius;
885 
886  {
887  SpaceGraph *sipo = (SpaceGraph *)ac.sl;
888  if (selectmode == SELECT_ADD) {
889  incl_handles = ((sipo->flag & SIPO_SELVHANDLESONLY) || (sipo->flag & SIPO_NOHANDLES)) == 0;
890  }
891  else {
892  incl_handles = (sipo->flag & SIPO_NOHANDLES) == 0;
893  }
894  }
895 
896  /* Apply box_select action. */
897  box_select_graphkeys(&ac, &rect_fl, BEZT_OK_REGION_CIRCLE, selectmode, incl_handles, &data);
898 
899  /* Send notifier that keyframe selection has changed. */
901 
902  return OPERATOR_FINISHED;
903 }
904 
906 {
907  ot->name = "Circle Select";
908  ot->description = "Select keyframe points using circle selection";
909  ot->idname = "GRAPH_OT_select_circle";
910 
916 
917  /* flags */
918  ot->flag = OPTYPE_UNDO;
919 
920  /* properties */
923 }
924 
925 /* ******************** Column Select Operator **************************** */
926 /* This operator works in one of four ways:
927  * - 1) select all keyframes in the same frame as a selected one (KKEY)
928  * - 2) select all keyframes in the same frame as the current frame marker (CTRL-KKEY)
929  * - 3) select all keyframes in the same frame as a selected markers (SHIFT-KKEY)
930  * - 4) select all keyframes that occur between selected markers (ALT-KKEY)
931  */
932 
933 /* defines for column-select mode */
935  {GRAPHKEYS_COLUMNSEL_KEYS, "KEYS", 0, "On Selected Keyframes", ""},
936  {GRAPHKEYS_COLUMNSEL_CFRA, "CFRA", 0, "On Current Frame", ""},
937  {GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN, "MARKERS_COLUMN", 0, "On Selected Markers", ""},
939  "MARKERS_BETWEEN",
940  0,
941  "Between Min/Max Selected Markers",
942  ""},
943  {0, NULL, 0, NULL, NULL},
944 };
945 
946 /* ------------------- */
947 
948 /* Selects all visible keyframes between the specified markers */
949 /* TODO, this is almost an _exact_ duplicate of a function of the same name in action_select.c
950  * should de-duplicate - campbell */
952 {
953  ListBase anim_data = {NULL, NULL};
954  bAnimListElem *ale;
955  int filter;
956 
957  KeyframeEditFunc ok_cb, select_cb;
958  KeyframeEditData ked = {{NULL}};
959  float min, max;
960 
961  /* get extreme markers */
962  ED_markers_get_minmax(ac->markers, 1, &min, &max);
963  min -= 0.5f;
964  max += 0.5f;
965 
966  /* get editing funcs + data */
969 
970  ked.f1 = min;
971  ked.f2 = max;
972 
973  /* filter data */
975  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
976 
977  /* select keys in-between */
978  for (ale = anim_data.first; ale; ale = ale->next) {
979  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
980 
981  if (adt) {
982  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
983  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
984  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
985  }
986  else {
987  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
988  }
989  }
990 
991  /* Cleanup */
992  ANIM_animdata_freelist(&anim_data);
993 }
994 
995 /* Selects all visible keyframes in the same frames as the specified elements */
996 static void columnselect_graph_keys(bAnimContext *ac, short mode)
997 {
998  ListBase anim_data = {NULL, NULL};
999  bAnimListElem *ale;
1000  int filter;
1001 
1002  Scene *scene = ac->scene;
1003  CfraElem *ce;
1004  KeyframeEditFunc select_cb, ok_cb;
1005  KeyframeEditData ked;
1006 
1007  /* initialize keyframe editing data */
1008  memset(&ked, 0, sizeof(KeyframeEditData));
1009 
1010  /* build list of columns */
1011  switch (mode) {
1012  case GRAPHKEYS_COLUMNSEL_KEYS: /* list of selected keys */
1014  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1015 
1016  for (ale = anim_data.first; ale; ale = ale->next) {
1018  }
1019 
1020  ANIM_animdata_freelist(&anim_data);
1021  break;
1022 
1023  case GRAPHKEYS_COLUMNSEL_CFRA: /* current frame */
1024  /* make a single CfraElem for storing this */
1025  ce = MEM_callocN(sizeof(CfraElem), "cfraElem");
1026  BLI_addtail(&ked.list, ce);
1027 
1028  ce->cfra = (float)CFRA;
1029  break;
1030 
1031  case GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN: /* list of selected markers */
1033  break;
1034 
1035  default: /* invalid option */
1036  return;
1037  }
1038 
1039  /* set up BezTriple edit callbacks */
1042 
1043  /* loop through all of the keys and select additional keyframes
1044  * based on the keys found to be selected above
1045  */
1047  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1048 
1049  for (ale = anim_data.first; ale; ale = ale->next) {
1050  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
1051 
1052  /* loop over cfraelems (stored in the KeyframeEditData->list)
1053  * - we need to do this here, as we can apply fewer NLA-mapping conversions
1054  */
1055  for (ce = ked.list.first; ce; ce = ce->next) {
1056  /* set frame for validation callback to refer to */
1058 
1059  /* select elements with frame number matching cfraelem */
1060  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
1061  }
1062  }
1063 
1064  /* free elements */
1065  BLI_freelistN(&ked.list);
1066  ANIM_animdata_freelist(&anim_data);
1067 }
1068 
1069 /* ------------------- */
1070 
1072 {
1073  bAnimContext ac;
1074  short mode;
1075 
1076  /* get editor data */
1077  if (ANIM_animdata_get_context(C, &ac) == 0) {
1078  return OPERATOR_CANCELLED;
1079  }
1080 
1081  /* action to take depends on the mode */
1082  mode = RNA_enum_get(op->ptr, "mode");
1083 
1086  }
1087  else {
1088  columnselect_graph_keys(&ac, mode);
1089  }
1090 
1091  /* set notifier that keyframe selection has changed */
1093 
1094  return OPERATOR_FINISHED;
1095 }
1096 
1098 {
1099  /* identifiers */
1100  ot->name = "Select All";
1101  ot->idname = "GRAPH_OT_select_column";
1102  ot->description = "Select all keyframes on the specified frame(s)";
1103 
1104  /* api callbacks */
1107 
1108  /* flags */
1110 
1111  /* props */
1112  ot->prop = RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", "");
1113 }
1114 
1115 /* ******************** Select Linked Operator *********************** */
1116 
1118 {
1119  bAnimContext ac;
1120 
1121  ListBase anim_data = {NULL, NULL};
1122  bAnimListElem *ale;
1123  int filter;
1124 
1127 
1128  /* get editor data */
1129  if (ANIM_animdata_get_context(C, &ac) == 0) {
1130  return OPERATOR_CANCELLED;
1131  }
1132 
1133  /* loop through all of the keys and select additional keyframes based on these */
1135  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1136 
1137  for (ale = anim_data.first; ale; ale = ale->next) {
1138  FCurve *fcu = (FCurve *)ale->key_data;
1139 
1140  /* check if anything selected? */
1142  /* select every keyframe in this curve then */
1144  }
1145  }
1146 
1147  /* Cleanup */
1148  ANIM_animdata_freelist(&anim_data);
1149 
1150  /* set notifier that keyframe selection has changed */
1152 
1153  return OPERATOR_FINISHED;
1154 }
1155 
1157 {
1158  /* identifiers */
1159  ot->name = "Select Linked";
1160  ot->idname = "GRAPH_OT_select_linked";
1161  ot->description = "Select keyframes occurring in the same F-Curves as selected ones";
1162 
1163  /* api callbacks */
1166 
1167  /* flags */
1169 }
1170 
1171 /* ******************** Select More/Less Operators *********************** */
1172 
1173 /* Common code to perform selection */
1174 static void select_moreless_graph_keys(bAnimContext *ac, short mode)
1175 {
1176  ListBase anim_data = {NULL, NULL};
1177  bAnimListElem *ale;
1178  int filter;
1179 
1180  KeyframeEditData ked;
1181  KeyframeEditFunc build_cb;
1182 
1183  /* init selmap building data */
1184  build_cb = ANIM_editkeyframes_buildselmap(mode);
1185  memset(&ked, 0, sizeof(KeyframeEditData));
1186 
1187  /* loop through all of the keys and select additional keyframes based on these */
1189  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1190 
1191  for (ale = anim_data.first; ale; ale = ale->next) {
1192  FCurve *fcu = (FCurve *)ale->key_data;
1193 
1194  /* only continue if F-Curve has keyframes */
1195  if (fcu->bezt == NULL) {
1196  continue;
1197  }
1198 
1199  /* build up map of whether F-Curve's keyframes should be selected or not */
1200  ked.data = MEM_callocN(fcu->totvert, "selmap graphEdit");
1201  ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, build_cb, NULL);
1202 
1203  /* based on this map, adjust the selection status of the keyframes */
1205 
1206  /* free the selmap used here */
1207  MEM_freeN(ked.data);
1208  ked.data = NULL;
1209  }
1210 
1211  /* Cleanup */
1212  ANIM_animdata_freelist(&anim_data);
1213 }
1214 
1215 /* ----------------- */
1216 
1218 {
1219  bAnimContext ac;
1220 
1221  /* get editor data */
1222  if (ANIM_animdata_get_context(C, &ac) == 0) {
1223  return OPERATOR_CANCELLED;
1224  }
1225 
1226  /* perform select changes */
1228 
1229  /* set notifier that keyframe selection has changed */
1231 
1232  return OPERATOR_FINISHED;
1233 }
1234 
1236 {
1237  /* identifiers */
1238  ot->name = "Select More";
1239  ot->idname = "GRAPH_OT_select_more";
1240  ot->description = "Select keyframes beside already selected ones";
1241 
1242  /* api callbacks */
1245 
1246  /* flags */
1248 }
1249 
1250 /* ----------------- */
1251 
1253 {
1254  bAnimContext ac;
1255 
1256  /* get editor data */
1257  if (ANIM_animdata_get_context(C, &ac) == 0) {
1258  return OPERATOR_CANCELLED;
1259  }
1260 
1261  /* perform select changes */
1263 
1264  /* set notifier that keyframe selection has changed */
1266 
1267  return OPERATOR_FINISHED;
1268 }
1269 
1271 {
1272  /* identifiers */
1273  ot->name = "Select Less";
1274  ot->idname = "GRAPH_OT_select_less";
1275  ot->description = "Deselect keyframes on ends of selection islands";
1276 
1277  /* api callbacks */
1280 
1281  /* flags */
1283 }
1284 
1285 /* ******************** Select Left/Right Operator ************************* */
1286 /* Select keyframes left/right of the current frame indicator */
1287 
1288 /* defines for left-right select tool */
1290  {GRAPHKEYS_LRSEL_TEST, "CHECK", 0, "Check if Select Left or Right", ""},
1291  {GRAPHKEYS_LRSEL_LEFT, "LEFT", 0, "Before Current Frame", ""},
1292  {GRAPHKEYS_LRSEL_RIGHT, "RIGHT", 0, "After Current Frame", ""},
1293  {0, NULL, 0, NULL, NULL},
1294 };
1295 
1296 /* --------------------------------- */
1297 
1298 static void graphkeys_select_leftright(bAnimContext *ac, short leftright, short select_mode)
1299 {
1300  ListBase anim_data = {NULL, NULL};
1301  bAnimListElem *ale;
1302  int filter;
1303 
1304  KeyframeEditFunc ok_cb, select_cb;
1305  KeyframeEditData ked = {{NULL}};
1306  Scene *scene = ac->scene;
1307 
1308  /* if select mode is replace, deselect all keyframes (and channels) first */
1309  if (select_mode == SELECT_REPLACE) {
1310  select_mode = SELECT_ADD;
1311 
1312  /* - deselect all other keyframes, so that just the newly selected remain
1313  * - channels aren't deselected, since we don't re-select any as a consequence
1314  */
1315  deselect_graph_keys(ac, 0, SELECT_SUBTRACT, false);
1316  }
1317 
1318  /* set callbacks and editing data */
1320  select_cb = ANIM_editkeyframes_select(select_mode);
1321 
1322  if (leftright == GRAPHKEYS_LRSEL_LEFT) {
1323  ked.f1 = MINAFRAMEF;
1324  ked.f2 = (float)(CFRA + 0.1f);
1325  }
1326  else {
1327  ked.f1 = (float)(CFRA - 0.1f);
1328  ked.f2 = MAXFRAMEF;
1329  }
1330 
1331  /* filter data */
1333  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1334 
1335  /* select keys */
1336  for (ale = anim_data.first; ale; ale = ale->next) {
1337  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
1338 
1339  if (adt) {
1340  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
1341  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
1342  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
1343  }
1344  else {
1345  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
1346  }
1347  }
1348 
1349  /* Cleanup */
1350  ANIM_animdata_freelist(&anim_data);
1351 }
1352 
1353 /* ----------------- */
1354 
1356 {
1357  bAnimContext ac;
1358  short leftright = RNA_enum_get(op->ptr, "mode");
1359  short selectmode;
1360 
1361  /* get editor data */
1362  if (ANIM_animdata_get_context(C, &ac) == 0) {
1363  return OPERATOR_CANCELLED;
1364  }
1365 
1366  /* select mode is either replace (deselect all, then add) or add/extend */
1367  if (RNA_boolean_get(op->ptr, "extend")) {
1368  selectmode = SELECT_INVERT;
1369  }
1370  else {
1371  selectmode = SELECT_REPLACE;
1372  }
1373 
1374  /* if "test" mode is set, we don't have any info to set this with */
1375  if (leftright == GRAPHKEYS_LRSEL_TEST) {
1376  return OPERATOR_CANCELLED;
1377  }
1378 
1379  /* do the selecting now */
1380  graphkeys_select_leftright(&ac, leftright, selectmode);
1381 
1382  /* set notifier that keyframe selection (and channels too) have changed */
1385 
1386  return OPERATOR_FINISHED;
1387 }
1388 
1390 {
1391  bAnimContext ac;
1392  short leftright = RNA_enum_get(op->ptr, "mode");
1393 
1394  /* get editor data */
1395  if (ANIM_animdata_get_context(C, &ac) == 0) {
1396  return OPERATOR_CANCELLED;
1397  }
1398 
1399  /* handle mode-based testing */
1400  if (leftright == GRAPHKEYS_LRSEL_TEST) {
1401  Scene *scene = ac.scene;
1402  ARegion *region = ac.region;
1403  View2D *v2d = &region->v2d;
1404  float x;
1405 
1406  /* determine which side of the current frame mouse is on */
1407  x = UI_view2d_region_to_view_x(v2d, event->mval[0]);
1408  if (x < CFRA) {
1409  RNA_enum_set(op->ptr, "mode", GRAPHKEYS_LRSEL_LEFT);
1410  }
1411  else {
1412  RNA_enum_set(op->ptr, "mode", GRAPHKEYS_LRSEL_RIGHT);
1413  }
1414  }
1415 
1416  /* perform selection */
1417  return graphkeys_select_leftright_exec(C, op);
1418 }
1419 
1421 {
1422  PropertyRNA *prop;
1423 
1424  /* identifiers */
1425  ot->name = "Select Left/Right";
1426  ot->idname = "GRAPH_OT_select_leftright";
1427  ot->description = "Select keyframes to the left or the right of the current frame";
1428 
1429  /* api callbacks */
1433 
1434  /* flags */
1436 
1437  /* id-props */
1438  ot->prop = RNA_def_enum(
1441 
1442  prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
1444 }
1445 
1446 /* ******************** Mouse-Click Select Operator *********************** */
1447 /* This operator works in one of three ways:
1448  * - 1) keyframe under mouse - no special modifiers
1449  * - 2) all keyframes on the same side of current frame indicator as mouse - ALT modifier
1450  * - 3) column select all keyframes in frame under mouse - CTRL modifier
1451  *
1452  * In addition to these basic options, the SHIFT modifier can be used to toggle the
1453  * selection mode between replacing the selection (without) and inverting the selection (with).
1454  */
1455 
1456 /* option 1) select keyframe directly under mouse */
1458  const int mval[2],
1459  eEditKeyframes_Select select_mode,
1460  const bool deselect_all,
1461  const bool curves_only,
1462  bool wait_to_deselect_others)
1463 {
1464  SpaceGraph *sipo = (SpaceGraph *)ac->sl;
1465  tNearestVertInfo *nvi;
1466  BezTriple *bezt = NULL;
1467  bool run_modal = false;
1468 
1469  /* find the beztriple that we're selecting, and the handle that was clicked on */
1470  nvi = find_nearest_fcurve_vert(ac, mval);
1471 
1472  if (select_mode != SELECT_REPLACE) {
1473  /* The modal execution to delay deselecting other items is only needed for normal click
1474  * selection, i.e. for SELECT_REPLACE. */
1475  wait_to_deselect_others = false;
1476  }
1477 
1480 
1481  const bool already_selected =
1482  (nvi != NULL) && (((nvi->hpoint == NEAREST_HANDLE_KEY) && (nvi->bezt->f2 & SELECT)) ||
1483  ((nvi->hpoint == NEAREST_HANDLE_LEFT) && (nvi->bezt->f1 & SELECT)) ||
1484  ((nvi->hpoint == NEAREST_HANDLE_RIGHT) && (nvi->bezt->f3 & SELECT)));
1485 
1486  if (wait_to_deselect_others && nvi && already_selected) {
1487  run_modal = true;
1488  }
1489  /* For replacing selection, if we have something to select, we have to clear existing selection.
1490  * The same goes if we found nothing to select, and deselect_all is true
1491  * (deselect on nothing behavior). */
1492  else if ((nvi != NULL && select_mode == SELECT_REPLACE) || (nvi == NULL && deselect_all)) {
1493  /* reset selection mode */
1494  select_mode = SELECT_ADD;
1495 
1496  /* deselect all other keyframes (+ F-Curves too) */
1497  deselect_graph_keys(ac, 0, SELECT_SUBTRACT, true);
1498 
1499  /* deselect other channels too, but only only do this if
1500  * selection of channel when the visibility of keyframes
1501  * doesn't depend on this
1502  */
1503  if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) {
1505  }
1506  }
1507 
1508  if (nvi == NULL) {
1509  return deselect_all ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
1510  }
1511 
1512  /* if points can be selected on this F-Curve */
1513  /* TODO: what about those with no keyframes? */
1514  bool something_was_selected = false;
1515  if (!curves_only && ((nvi->fcu->flag & FCURVE_PROTECTED) == 0)) {
1516  /* only if there's keyframe */
1517  if (nvi->bezt) {
1518  bezt = nvi->bezt; /* Used to check `bezt` selection is set. */
1519  if (select_mode == SELECT_INVERT) {
1520  if (nvi->hpoint == NEAREST_HANDLE_KEY) {
1521  bezt->f2 ^= SELECT;
1522  something_was_selected = (bezt->f2 & SELECT);
1523  }
1524  else if (nvi->hpoint == NEAREST_HANDLE_LEFT) {
1525  /* toggle selection */
1526  bezt->f1 ^= SELECT;
1527  something_was_selected = (bezt->f1 & SELECT);
1528  }
1529  else {
1530  /* toggle selection */
1531  bezt->f3 ^= SELECT;
1532  something_was_selected = (bezt->f3 & SELECT);
1533  }
1534  }
1535  else {
1536  if (nvi->hpoint == NEAREST_HANDLE_KEY) {
1537  bezt->f2 |= SELECT;
1538  }
1539  else if (nvi->hpoint == NEAREST_HANDLE_LEFT) {
1540  bezt->f1 |= SELECT;
1541  }
1542  else {
1543  bezt->f3 |= SELECT;
1544  }
1545  something_was_selected = true;
1546  }
1547 
1548  if (!run_modal && BEZT_ISSEL_ANY(bezt)) {
1549  const bool may_activate = !already_selected ||
1552  if (may_activate) {
1554  }
1555  }
1556  }
1557  else if (nvi->fpt) {
1558  /* TODO: need to handle sample points */
1559  }
1560  }
1561  else {
1562  KeyframeEditFunc select_cb;
1563  KeyframeEditData ked;
1564 
1565  /* initialize keyframe editing data */
1566  memset(&ked, 0, sizeof(KeyframeEditData));
1567 
1568  /* set up BezTriple edit callbacks */
1569  select_cb = ANIM_editkeyframes_select(select_mode);
1570 
1571  /* select all keyframes */
1572  ANIM_fcurve_keyframes_loop(&ked, nvi->fcu, NULL, select_cb, NULL);
1573  }
1574 
1575  /* only change selection of channel when the visibility of keyframes doesn't depend on this */
1576  if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) {
1577  /* select or deselect curve? */
1578  if (bezt) {
1579  /* take selection status from item that got hit, to prevent flip/flop on channel
1580  * selection status when shift-selecting (i.e. "SELECT_INVERT") points
1581  */
1582  if (BEZT_ISSEL_ANY(bezt)) {
1583  nvi->fcu->flag |= FCURVE_SELECTED;
1584  }
1585  else {
1586  nvi->fcu->flag &= ~FCURVE_SELECTED;
1587  }
1588  }
1589  else {
1590  /* Didn't hit any channel,
1591  * so just apply that selection mode to the curve's selection status. */
1592  if (select_mode == SELECT_INVERT) {
1593  nvi->fcu->flag ^= FCURVE_SELECTED;
1594  }
1595  else if (select_mode == SELECT_ADD) {
1596  nvi->fcu->flag |= FCURVE_SELECTED;
1597  }
1598  }
1599  }
1600 
1601  /* Set active F-Curve when something was actually selected (so not on a deselect), except when
1602  * dragging the selected keys. Needs to be called with (sipo->flag & SIPO_SELCUVERTSONLY),
1603  * otherwise the active flag won't be set T26452. */
1604  if (!run_modal && (nvi->fcu->flag & FCURVE_SELECTED) && something_was_selected) {
1605  /* NOTE: Sync the filter flags with findnearest_fcurve_vert. */
1607  ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nvi->fcu, nvi->ctype);
1608  }
1609 
1610  if (nvi->hpoint == NEAREST_HANDLE_LEFT) {
1612  }
1613  else if (nvi->hpoint == NEAREST_HANDLE_RIGHT) {
1615  }
1616 
1617  /* free temp sample data for filtering */
1618  MEM_freeN(nvi);
1619 
1620  return run_modal ? OPERATOR_RUNNING_MODAL : OPERATOR_FINISHED;
1621 }
1622 
1623 /* Option 2) Selects all the keyframes on either side of the current frame
1624  * (depends on which side the mouse is on) */
1625 /* (see graphkeys_select_leftright) */
1626 
1627 /* Option 3) Selects all visible keyframes in the same frame as the mouse click */
1629  const int mval[2],
1630  eEditKeyframes_Select select_mode,
1631  bool wait_to_deselect_others)
1632 {
1633  ListBase anim_data = {NULL, NULL};
1634  bAnimListElem *ale;
1635  int filter;
1636  bool run_modal = false;
1637 
1638  KeyframeEditFunc select_cb, ok_cb;
1639  KeyframeEditData ked;
1640  tNearestVertInfo *nvi;
1641  float selx = (float)ac->scene->r.cfra;
1642 
1643  /* find the beztriple that we're selecting, and the handle that was clicked on */
1644  nvi = find_nearest_fcurve_vert(ac, mval);
1645 
1646  /* check if anything to select */
1647  if (nvi == NULL) {
1648  return OPERATOR_CANCELLED;
1649  }
1650 
1651  /* get frame number on which elements should be selected */
1652  /* TODO: should we restrict to integer frames only? */
1653  selx = nvi->frame;
1654 
1655  if (select_mode != SELECT_REPLACE) {
1656  /* Doesn't need to deselect anything -> Pass. */
1657  }
1658  else if (wait_to_deselect_others && (nvi->bezt->f2 & SELECT)) {
1659  run_modal = true;
1660  }
1661  /* If select mode is replace (and we don't do delayed deselection on mouse release), deselect all
1662  * keyframes first. */
1663  else {
1664  /* reset selection mode to add to selection */
1665  select_mode = SELECT_ADD;
1666 
1667  /* - deselect all other keyframes, so that just the newly selected remain
1668  * - channels aren't deselected, since we don't re-select any as a consequence
1669  */
1670  deselect_graph_keys(ac, 0, SELECT_SUBTRACT, false);
1671  }
1672 
1673  /* initialize keyframe editing data */
1674  memset(&ked, 0, sizeof(KeyframeEditData));
1675 
1676  /* set up BezTriple edit callbacks */
1677  select_cb = ANIM_editkeyframes_select(select_mode);
1679 
1680  /* loop through all of the keys and select additional keyframes
1681  * based on the keys found to be selected above
1682  */
1684  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1685 
1686  for (ale = anim_data.first; ale; ale = ale->next) {
1687  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
1688 
1689  /* set frame for validation callback to refer to */
1690  if (adt) {
1692  }
1693  else {
1694  ked.f1 = selx;
1695  }
1696 
1697  /* select elements with frame number matching cfra */
1698  ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
1699  }
1700 
1701  /* free elements */
1702  MEM_freeN(nvi);
1703  BLI_freelistN(&ked.list);
1704  ANIM_animdata_freelist(&anim_data);
1705 
1706  return run_modal ? OPERATOR_RUNNING_MODAL : OPERATOR_FINISHED;
1707 }
1708 
1709 /* ------------------- */
1710 
1711 /* handle clicking */
1713 {
1714  bAnimContext ac;
1715 
1716  /* get editor data */
1717  if (ANIM_animdata_get_context(C, &ac) == 0) {
1718  return OPERATOR_CANCELLED;
1719  }
1720 
1721  /* select mode is either replace (deselect all, then add) or add/extend */
1722  const short selectmode = RNA_boolean_get(op->ptr, "extend") ? SELECT_INVERT : SELECT_REPLACE;
1723  const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
1724  /* See #WM_operator_properties_generic_select() for a detailed description of the how and why of
1725  * this. */
1726  const bool wait_to_deselect_others = RNA_boolean_get(op->ptr, "wait_to_deselect_others");
1727  int mval[2];
1728  int ret_val;
1729 
1730  mval[0] = RNA_int_get(op->ptr, "mouse_x");
1731  mval[1] = RNA_int_get(op->ptr, "mouse_y");
1732 
1733  /* figure out action to take */
1734  if (RNA_boolean_get(op->ptr, "column")) {
1735  /* select all keyframes in the same frame as the one that was under the mouse */
1736  ret_val = graphkeys_mselect_column(&ac, mval, selectmode, wait_to_deselect_others);
1737  }
1738  else if (RNA_boolean_get(op->ptr, "curves")) {
1739  /* select all keyframes in the same F-Curve as the one under the mouse */
1740  ret_val = mouse_graph_keys(&ac, mval, selectmode, deselect_all, true, wait_to_deselect_others);
1741  }
1742  else {
1743  /* select keyframe under mouse */
1744  ret_val = mouse_graph_keys(
1745  &ac, mval, selectmode, deselect_all, false, wait_to_deselect_others);
1746  }
1747 
1748  /* set notifier that keyframe selection (and also channel selection in some cases) has
1749  * changed */
1752 
1753  /* for tweak grab to work */
1754  return ret_val | OPERATOR_PASS_THROUGH;
1755 }
1756 
1758 {
1759  PropertyRNA *prop;
1760 
1761  /* identifiers */
1762  ot->name = "Select Keyframes";
1763  ot->idname = "GRAPH_OT_clickselect";
1764  ot->description = "Select keyframes by clicking on them";
1765 
1766  /* callbacks */
1771 
1772  /* flags */
1773  ot->flag = OPTYPE_UNDO;
1774 
1775  /* properties */
1777  prop = RNA_def_boolean(ot->srna,
1778  "extend",
1779  0,
1780  "Extend Select",
1781  "Toggle keyframe selection instead of leaving newly selected "
1782  "keyframes only"); /* SHIFTKEY */
1784 
1785  prop = RNA_def_boolean(ot->srna,
1786  "deselect_all",
1787  false,
1788  "Deselect On Nothing",
1789  "Deselect all when nothing under the cursor");
1791 
1792  prop = RNA_def_boolean(ot->srna,
1793  "column",
1794  0,
1795  "Column Select",
1796  "Select all keyframes that occur on the same frame as the one under "
1797  "the mouse"); /* ALTKEY */
1799 
1800  prop = RNA_def_boolean(ot->srna,
1801  "curves",
1802  0,
1803  "Only Curves",
1804  "Select all the keyframes in the curve"); /* CTRLKEY + ALTKEY */
1806 }
1807 
1808 /* ************************************************************************** */
typedef float(TangentPoint)[2]
void BKE_fcurve_active_keyframe_set(struct FCurve *fcu, const struct BezTriple *active_bezt)
int BKE_fcurve_active_keyframe_index(const struct FCurve *fcu)
@ NLATIME_CONVERT_UNMAP
Definition: BKE_nla.h:153
float BKE_nla_tweakedit_remap(struct AnimData *adt, float cframe, short mode)
Definition: nla.c:582
#define BLI_assert(a)
Definition: BLI_assert.h:58
void BLI_lasso_boundbox(struct rcti *rect, const int mcoords[][2], const unsigned int mcoords_len)
Definition: lasso_2d.c:31
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
void * BLI_pophead(ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:257
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:547
void void BLI_INLINE bool BLI_listbase_is_single(const struct ListBase *lb)
Definition: BLI_listbase.h:120
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
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:157
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:153
void BLI_rctf_rcti_copy(struct rctf *dst, const struct rcti *src)
#define UNUSED(x)
#define FCURVE_ACTIVE_KEYFRAME_NONE
@ FCURVE_ACTIVE
@ FCURVE_SELECTED
@ FCURVE_PROTECTED
#define BEZT_ISSEL_ANY(bezt)
@ BEZT_IPO_BEZ
#define CFRA
#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:508
eAnim_ChannelType
Definition: ED_anim_api.h:197
@ ANIMFILTER_FOREDIT
Definition: ED_anim_api.h:315
@ ANIMFILTER_DATA_VISIBLE
Definition: ED_anim_api.h:295
@ ANIMFILTER_CURVE_VISIBLE
Definition: ED_anim_api.h:300
@ ANIMFILTER_SELEDIT
Definition: ED_anim_api.h:318
@ ANIMFILTER_NODUPLIS
Definition: ED_anim_api.h:328
@ ANIMFILTER_SEL
Definition: ED_anim_api.h:311
@ ANIM_UNITCONV_ONLYKEYS
Definition: ED_anim_api.h:763
@ 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
#define SEL_OP_USE_PRE_DESELECT(sel_op)
@ SEL_SELECT
@ SEL_INVERT
@ SEL_DESELECT
@ SEL_TOGGLE
eSelectOp ED_select_op_modal(const eSelectOp sel_op, const bool is_first)
Definition: select_utils.c:77
eSelectOp
@ SEL_OP_SUB
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
Read Guarded memory(de)allocation.
@ PROP_SKIP_SAVE
Definition: RNA_types.h:204
#define C
Definition: RandGen.cpp:39
void UI_view2d_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.c:1659
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define NC_ANIMATION
Definition: WM_types.h:289
#define ND_KEYFRAME
Definition: WM_types.h:394
#define ND_ANIMCHAN
Definition: WM_types.h:396
#define NA_SELECTED
Definition: WM_types.h:467
void ANIM_anim_channels_select_set(bAnimContext *ac, eAnimChannels_SetFlag sel)
void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datatype, eAnimFilter_Flags filter, void *channel_data, eAnim_ChannelType channel_type)
void ANIM_animdata_freelist(ListBase *anim_data)
Definition: anim_deps.c:425
AnimData * ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale)
Definition: anim_draw.c:178
void ANIM_nla_mapping_apply_fcurve(AnimData *adt, FCurve *fcu, bool restore, bool only_keys)
Definition: anim_draw.c:257
float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short flag, float *r_offset)
Definition: anim_draw.c:453
short ANIM_get_normalization_flags(bAnimContext *ac)
Definition: anim_draw.c:285
bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
Definition: anim_filter.c:405
size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, eAnimFilter_Flags filter_mode, void *data, eAnimCont_Types datatype)
Definition: anim_filter.c:3442
void ED_markers_make_cfra_list(ListBase *markers, ListBase *lb, short only_sel)
Definition: anim_markers.c:330
void ED_markers_get_minmax(ListBase *markers, short sel, float *r_first, float *r_last)
Definition: anim_markers.c:199
#define SELECT
Scene scene
@ GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN
Definition: graph_intern.h:75
@ GRAPHKEYS_COLUMNSEL_KEYS
Definition: graph_intern.h:72
@ GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN
Definition: graph_intern.h:74
@ GRAPHKEYS_COLUMNSEL_CFRA
Definition: graph_intern.h:73
@ GRAPHKEYS_LRSEL_TEST
Definition: graph_intern.h:65
@ GRAPHKEYS_LRSEL_RIGHT
Definition: graph_intern.h:67
@ GRAPHKEYS_LRSEL_LEFT
Definition: graph_intern.h:66
struct bAnimListElem * get_active_fcurve_channel(struct bAnimContext *ac)
Definition: graph_utils.c:104
bool graphop_visible_keyframes_poll(struct bContext *C)
Definition: graph_utils.c:131
void GRAPH_OT_select_box(wmOperatorType *ot)
Definition: graph_select.c:736
static int graphkeys_box_select_exec(bContext *C, wmOperator *op)
Definition: graph_select.c:682
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:108
static rctf initialize_box_select_coords(const bAnimContext *ac, const rctf *rectf_view)
Definition: graph_select.c:504
static int graphkeys_clickselect_exec(bContext *C, wmOperator *op)
static const EnumPropertyItem prop_graphkeys_leftright_select_types[]
static void box_select_graphkeys(bAnimContext *ac, const rctf *rectf_view, short mode, short selectmode, bool incl_handles, void *data)
Definition: graph_select.c:577
static void graphkeys_select_leftright(bAnimContext *ac, short leftright, short select_mode)
void GRAPH_OT_select_lasso(wmOperatorType *ot)
Definition: graph_select.c:828
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:274
void deselect_graph_keys(bAnimContext *ac, bool test, short sel, bool do_channels)
Definition: graph_select.c:354
static tNearestVertInfo * find_nearest_fcurve_vert(bAnimContext *ac, const int mval[2])
Definition: graph_select.c:320
static int graphkeys_select_leftright_exec(bContext *C, wmOperator *op)
static int graphkeys_lassoselect_exec(bContext *C, wmOperator *op)
Definition: graph_select.c:776
void GRAPH_OT_select_circle(wmOperatorType *ot)
Definition: graph_select.c:905
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)
void GRAPH_OT_select_more(wmOperatorType *ot)
struct tNearestVertInfo tNearestVertInfo
static int graphkeys_deselectall_exec(bContext *C, wmOperator *op)
Definition: graph_select.c:420
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:528
#define GVERTSEL_TOL
Definition: graph_select.c:89
void GRAPH_OT_select_linked(wmOperatorType *ot)
static void markers_selectkeys_between(bAnimContext *ac)
Definition: graph_select.c:951
static int graph_circle_select_exec(bContext *C, wmOperator *op)
Definition: graph_select.c:852
void GRAPH_OT_select_leftright(wmOperatorType *ot)
static int graphkeys_box_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: graph_select.c:660
static ListBase initialize_box_select_anim_data(const SpaceGraph *sipo, bAnimContext *ac)
Definition: graph_select.c:515
eGraphVertIndex
Definition: graph_select.c:81
@ NEAREST_HANDLE_LEFT
Definition: graph_select.c:82
@ NEAREST_HANDLE_KEY
Definition: graph_select.c:83
@ NEAREST_HANDLE_RIGHT
Definition: graph_select.c:84
static bool fcurve_handle_sel_check(SpaceGraph *sipo, BezTriple *bezt)
Definition: graph_select.c:95
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:475
static const EnumPropertyItem prop_column_select_types[]
Definition: graph_select.c:934
static void columnselect_graph_keys(bAnimContext *ac, short mode)
Definition: graph_select.c:996
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:175
static int graphkeys_columnselect_exec(bContext *C, wmOperator *op)
void GRAPH_OT_select_less(wmOperatorType *ot)
DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
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:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6308
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:6413
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3481
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1512
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3771
#define min(a, b)
Definition: sort.c:51
float vec[3][3]
float cfra
Definition: BKE_fcurve.h:56
struct CfraElem * next
Definition: BKE_fcurve.h:55
FPoint * fpt
BezTriple * bezt
short flag
unsigned int totvert
struct FCurve * fcu
eKeyframeIterFlags iterflags
void * last
Definition: DNA_listBase.h:47
void * first
Definition: DNA_listBase.h:47
struct RenderData r
SpaceGraph_Runtime runtime
ListBase * markers
Definition: ED_anim_api.h:105
struct ARegion * region
Definition: ED_anim_api.h:89
struct Scene * scene
Definition: ED_anim_api.h:97
short datatype
Definition: ED_anim_api.h:75
void * data
Definition: ED_anim_api.h:73
struct SpaceLink * sl
Definition: ED_anim_api.h:87
struct bAnimListElem * next
Definition: ED_anim_api.h:135
void * key_data
Definition: ED_anim_api.h:154
struct ID * id
Definition: ED_anim_api.h:168
float xmax
Definition: DNA_vec_types.h:85
float xmin
Definition: DNA_vec_types.h:85
float ymax
Definition: DNA_vec_types.h:86
float ymin
Definition: DNA_vec_types.h:86
BezTriple * bezt
Definition: graph_select.c:68
eAnim_ChannelType ctype
Definition: graph_select.c:75
struct tNearestVertInfo * prev
Definition: graph_select.c:64
struct tNearestVertInfo * next
Definition: graph_select.c:64
int mval[2]
Definition: WM_types.h:583
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:768
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:760
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
PropertyRNA * prop
Definition: WM_types.h:814
struct PointerRNA * ptr
float max
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition: wm_files.c:3156
bool WM_gesture_is_modal_first(const wmGesture *gesture)
Definition: wm_gesture.c:124
void WM_gesture_box_cancel(bContext *C, wmOperator *op)
int WM_gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_circle_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void WM_gesture_circle_cancel(bContext *C, wmOperator *op)
int WM_gesture_box_modal(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event)
void WM_gesture_lasso_cancel(bContext *C, wmOperator *op)
int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const int(* WM_gesture_lasso_path_to_array(bContext *UNUSED(C), wmOperator *op, int *r_mcoords_len))[2]
void WM_operator_properties_border_to_rcti(struct wmOperator *op, rcti *rect)
void WM_operator_properties_gesture_box(wmOperatorType *ot)
void WM_operator_properties_select_operation_simple(wmOperatorType *ot)
void WM_operator_properties_generic_select(wmOperatorType *ot)
void WM_operator_properties_gesture_lasso(wmOperatorType *ot)
void WM_operator_properties_gesture_circle(wmOperatorType *ot)
void WM_operator_properties_select_all(wmOperatorType *ot)
int WM_generic_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: wm_operators.c:905
int WM_generic_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
Definition: wm_operators.c:838