Blender  V3.3
graph_edit.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
10 #include <float.h>
11 #include <math.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #ifdef WITH_AUDASPACE
16 # include <AUD_Special.h>
17 #endif
18 
19 #include "MEM_guardedalloc.h"
20 
21 #include "BLI_blenlib.h"
22 #include "BLI_math.h"
23 #include "BLI_utildefines.h"
24 
25 #include "DNA_anim_types.h"
26 #include "DNA_scene_types.h"
27 
28 #include "RNA_access.h"
29 #include "RNA_define.h"
30 #include "RNA_enum_types.h"
31 #include "RNA_prototypes.h"
32 
33 #include "BLT_translation.h"
34 
35 #include "BKE_animsys.h"
36 #include "BKE_context.h"
37 #include "BKE_fcurve.h"
38 #include "BKE_global.h"
39 #include "BKE_nla.h"
40 #include "BKE_report.h"
41 
42 #include "DEG_depsgraph_build.h"
43 
44 #include "UI_interface.h"
45 #include "UI_view2d.h"
46 
47 #include "ED_anim_api.h"
48 #include "ED_keyframes_edit.h"
49 #include "ED_keyframing.h"
50 #include "ED_markers.h"
51 #include "ED_screen.h"
52 #include "ED_transform.h"
53 
54 #include "WM_api.h"
55 #include "WM_types.h"
56 
57 #include "graph_intern.h"
58 
59 /* -------------------------------------------------------------------- */
63 /* Mode defines for insert keyframes tool. */
70 
71 /* RNA mode types for insert keyframes tool. */
74  "ALL",
75  0,
76  "All Channels",
77  "Insert a keyframe on all visible and editable F-Curves using each curve's current value"},
79  "SEL",
80  0,
81  "Only Selected Channels",
82  "Insert a keyframe on selected F-Curves using each curve's current value"},
84  "CURSOR_ACTIVE",
85  0,
86  "Active Channels at Cursor",
87  "Insert a keyframe for the active F-Curve at the cursor point"},
89  "CURSOR_SEL",
90  0,
91  "Selected Channels at Cursor",
92  "Insert a keyframe for selected F-Curves at the cursor point"},
93  {0, NULL, 0, NULL, NULL},
94 };
95 
96 /* This function is responsible for snapping keyframes to frame-times. */
98 {
99  ListBase anim_data = {NULL, NULL};
100  ListBase nla_cache = {NULL, NULL};
101  bAnimListElem *ale;
102  int filter;
103  size_t num_items;
104 
105  ReportList *reports = ac->reports;
106  SpaceGraph *sipo = (SpaceGraph *)ac->sl;
107  Scene *scene = ac->scene;
109  eInsertKeyFlags flag = 0;
110 
111  /* Filter data. */
114  if (mode & GRAPHKEYS_INSERTKEY_SEL) {
116  }
117  else if (mode & GRAPHKEYS_INSERTKEY_ACTIVE) {
119  }
120 
121  num_items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
122  if (num_items == 0) {
123  if (mode & GRAPHKEYS_INSERTKEY_ACTIVE) {
124  BKE_report(reports,
125  RPT_ERROR,
126  "No active F-Curve to add a keyframe to. Select an editable F-Curve first");
127  }
128  else if (mode & GRAPHKEYS_INSERTKEY_SEL) {
129  BKE_report(reports, RPT_ERROR, "No selected F-Curves to add keyframes to");
130  }
131  else {
132  BKE_report(reports, RPT_ERROR, "No channels to add keyframes to");
133  }
134 
135  return;
136  }
137 
138  /* Init key-framing flag. */
139  flag = ANIM_get_keyframing_flags(scene, true);
140 
141  /* Insert keyframes. */
142  if (mode & GRAPHKEYS_INSERTKEY_CURSOR) {
143  for (ale = anim_data.first; ale; ale = ale->next) {
144  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
145  FCurve *fcu = (FCurve *)ale->key_data;
146 
147  short mapping_flag = ANIM_get_normalization_flags(ac);
148  float offset;
149  float unit_scale = ANIM_unit_mapping_get_factor(
150  ac->scene, ale->id, ale->key_data, mapping_flag, &offset);
151 
152  float x, y;
153 
154  /* perform time remapping for x-coordinate (if necessary) */
155  if ((sipo) && (sipo->mode == SIPO_MODE_DRIVERS)) {
156  x = sipo->cursorTime;
157  }
158  else if (adt) {
160  }
161  else {
162  x = (float)scene->r.cfra;
163  }
164 
165  /* Normalize units of cursor's value. */
166  if (sipo) {
167  y = (sipo->cursorVal / unit_scale) - offset;
168  }
169  else {
170  y = 0.0f;
171  }
172 
173  /* Insert keyframe directly into the F-Curve. */
174  insert_vert_fcurve(fcu, x, y, ts->keyframe_type, 0);
175 
176  ale->update |= ANIM_UPDATE_DEFAULT;
177  }
178  }
179  else {
181  ac->depsgraph, (float)scene->r.cfra);
182  for (ale = anim_data.first; ale; ale = ale->next) {
183  FCurve *fcu = (FCurve *)ale->key_data;
184 
185  /* Read value from property the F-Curve represents, or from the curve only?
186  *
187  * - ale->id != NULL:
188  * Typically, this means that we have enough info to try resolving the path.
189  * - ale->owner != NULL:
190  * If this is set, then the path may not be resolvable from the ID alone,
191  * so it's easier for now to just read the F-Curve directly.
192  * (TODO: add the full-blown PointerRNA relative parsing case here... (Joshua Leung 2015))
193  * - fcu->driver != NULL:
194  * If this is set, then it's a driver. If we don't check for this, we'd end
195  * up adding the keyframes on a new F-Curve in the action data instead.
196  */
197  if (ale->id && !ale->owner && !fcu->driver) {
199  reports,
200  ale->id,
201  NULL,
202  ((fcu->grp) ? (fcu->grp->name) : (NULL)),
203  fcu->rna_path,
204  fcu->array_index,
205  &anim_eval_context,
206  ts->keyframe_type,
207  &nla_cache,
208  flag);
209  }
210  else {
211  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
212 
213  /* Adjust current frame for NLA-mapping. */
214  float cfra = (float)scene->r.cfra;
215  if ((sipo) && (sipo->mode == SIPO_MODE_DRIVERS)) {
216  cfra = sipo->cursorTime;
217  }
218  else if (adt) {
220  }
221 
222  const float curval = evaluate_fcurve_only_curve(fcu, cfra);
223  insert_vert_fcurve(fcu, cfra, curval, ts->keyframe_type, 0);
224  }
225 
226  ale->update |= ANIM_UPDATE_DEFAULT;
227  }
228  }
229 
231 
232  ANIM_animdata_update(ac, &anim_data);
233  ANIM_animdata_freelist(&anim_data);
234 }
235 
236 /* ------------------- */
237 
239 {
240  bAnimContext ac;
242 
243  /* Get editor data. */
244  if (ANIM_animdata_get_context(C, &ac) == 0) {
245  return OPERATOR_CANCELLED;
246  }
247 
248  /* Which channels to affect? */
249  mode = RNA_enum_get(op->ptr, "type");
250 
251  /* Insert keyframes. */
252  insert_graph_keys(&ac, mode);
253 
254  /* Set notifier that keyframes have changed. */
256 
257  return OPERATOR_FINISHED;
258 }
259 
261 {
262  /* Identifiers */
263  ot->name = "Insert Keyframes";
264  ot->idname = "GRAPH_OT_keyframe_insert";
265  ot->description = "Insert keyframes for the specified channels";
266 
267  /* API callbacks */
271 
272  /* Flags */
274 
275  /* Id-props */
276  ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_insertkey_types, 0, "Type", "");
277 }
278 
281 /* -------------------------------------------------------------------- */
286 {
287  bAnimContext ac;
288  bAnimListElem *ale;
289  AnimData *adt;
290  FCurve *fcu;
291  float frame, val;
292 
293  /* Get animation context. */
294  if (ANIM_animdata_get_context(C, &ac) == 0) {
295  return OPERATOR_CANCELLED;
296  }
297 
298  /* Get active F-Curve 'anim-list-element'. */
299  ale = get_active_fcurve_channel(&ac);
300  if (ELEM(NULL, ale, ale->data)) {
301  if (ale) {
302  MEM_freeN(ale);
303  }
304  return OPERATOR_CANCELLED;
305  }
306  fcu = ale->data;
307 
308  /* When there are F-Modifiers on the curve, only allow adding
309  * keyframes if these will be visible after doing so...
310  */
311  if (BKE_fcurve_is_keyframable(fcu)) {
312  ListBase anim_data;
313  ToolSettings *ts = ac.scene->toolsettings;
314 
315  short mapping_flag = ANIM_get_normalization_flags(&ac);
316  float scale, offset;
317 
318  /* Preserve selection? */
319  if (RNA_boolean_get(op->ptr, "extend") == false) {
320  /* Deselect all keyframes first,
321  * so that we can immediately start manipulating the newly added one(s)
322  * - only affect the keyframes themselves, as we don't want channels popping in and out. */
323  deselect_graph_keys(&ac, false, SELECT_SUBTRACT, false);
324  }
325 
326  /* Get frame and value from props. */
327  frame = RNA_float_get(op->ptr, "frame");
328  val = RNA_float_get(op->ptr, "value");
329 
330  /* Apply inverse NLA-mapping to frame to get correct time in un-scaled action. */
331  adt = ANIM_nla_mapping_get(&ac, ale);
332  frame = BKE_nla_tweakedit_remap(adt, frame, NLATIME_CONVERT_UNMAP);
333 
334  /* Apply inverse unit-mapping to value to get correct value for F-Curves. */
336  ac.scene, ale->id, fcu, mapping_flag | ANIM_UNITCONV_RESTORE, &offset);
337 
338  val = val * scale - offset;
339 
340  /* Insert keyframe on the specified frame + value. */
341  insert_vert_fcurve(fcu, frame, val, ts->keyframe_type, 0);
342 
343  ale->update |= ANIM_UPDATE_DEPS;
344 
345  BLI_listbase_clear(&anim_data);
346  BLI_addtail(&anim_data, ale);
347 
348  ANIM_animdata_update(&ac, &anim_data);
349  }
350  else {
351  /* Warn about why this can't happen. */
352  if (fcu->fpt) {
353  BKE_report(op->reports, RPT_ERROR, "Keyframes cannot be added to sampled F-Curves");
354  }
355  else if (fcu->flag & FCURVE_PROTECTED) {
356  BKE_report(op->reports, RPT_ERROR, "Active F-Curve is not editable");
357  }
358  else {
359  BKE_report(op->reports, RPT_ERROR, "Remove F-Modifiers from F-Curve to add keyframes");
360  }
361  }
362 
363  /* Free temp data. */
364  MEM_freeN(ale);
365 
366  /* Set notifier that keyframes have changed. */
368 
369  /* Done */
370  return OPERATOR_FINISHED;
371 }
372 
374 {
375  bAnimContext ac;
376  ARegion *region;
377  View2D *v2d;
378  int mval[2];
379  float x, y;
380 
381  /* Get animation context. */
382  if (ANIM_animdata_get_context(C, &ac) == 0) {
383  return OPERATOR_CANCELLED;
384  }
385 
386  /* Store mouse coordinates in View2D space, into the operator's properties. */
387  region = ac.region;
388  v2d = &region->v2d;
389 
390  mval[0] = (event->xy[0] - region->winrct.xmin);
391  mval[1] = (event->xy[1] - region->winrct.ymin);
392 
393  UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
394 
395  RNA_float_set(op->ptr, "frame", x);
396  RNA_float_set(op->ptr, "value", y);
397 
398  /* Run exec now. */
399  return graphkeys_click_insert_exec(C, op);
400 }
401 
403 {
404  PropertyRNA *prop;
405 
406  /* Identifiers */
407  ot->name = "Click-Insert Keyframes";
408  ot->idname = "GRAPH_OT_click_insert";
409  ot->description = "Insert new keyframe at the cursor position for the active F-Curve";
410 
411  /* API callbacks */
415 
416  /* Flags */
418 
419  /* Properties */
421  "frame",
422  1.0f,
423  -FLT_MAX,
424  FLT_MAX,
425  "Frame Number",
426  "Frame to insert keyframe on",
427  0,
428  100);
430  ot->srna, "value", 1.0f, -FLT_MAX, FLT_MAX, "Value", "Value for keyframe on", 0, 100);
431 
432  prop = RNA_def_boolean(ot->srna,
433  "extend",
434  false,
435  "Extend",
436  "Extend selection instead of deselecting everything first");
438 }
439 
442 /* -------------------------------------------------------------------- */
448 static short copy_graph_keys(bAnimContext *ac)
449 {
450  ListBase anim_data = {NULL, NULL};
451  int filter, ok = 0;
452 
453  /* Clear buffer first. */
455 
456  /* Filter data
457  * - First time we try to filter more strictly, allowing only selected channels
458  * to allow copying animation between channels.
459  */
462 
463  if (ANIM_animdata_filter(ac, &anim_data, filter | ANIMFILTER_SEL, ac->data, ac->datatype) == 0) {
464  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
465  }
466 
467  /* Copy keyframes. */
468  ok = copy_animedit_keys(ac, &anim_data);
469 
470  /* Clean up. */
471  ANIM_animdata_freelist(&anim_data);
472 
473  return ok;
474 }
475 
477  const eKeyPasteOffset offset_mode,
478  const eKeyMergeMode merge_mode,
479  bool flip)
480 {
481  ListBase anim_data = {NULL, NULL};
482  int filter;
483 
484  /* Filter data
485  * - First time we try to filter more strictly, allowing only selected channels
486  * to allow copying animation between channels
487  * - Second time, we loosen things up if nothing was found the first time, allowing
488  * users to just paste keyframes back into the original curve again T31670.
489  */
492 
493  if (ANIM_animdata_filter(ac, &anim_data, filter | ANIMFILTER_SEL, ac->data, ac->datatype) == 0) {
494  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
495  }
496 
497  /* Paste keyframes. */
498  const eKeyPasteError ok = paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode, flip);
499 
500  /* Clean up. */
501  ANIM_animdata_freelist(&anim_data);
502 
503  return ok;
504 }
505 
506 /* ------------------- */
507 
509 {
510  bAnimContext ac;
511 
512  /* Get editor data. */
513  if (ANIM_animdata_get_context(C, &ac) == 0) {
514  return OPERATOR_CANCELLED;
515  }
516 
517  /* Copy keyframes. */
518  if (copy_graph_keys(&ac)) {
519  BKE_report(op->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer");
520  return OPERATOR_CANCELLED;
521  }
522 
523  /* Just return - no operator needed here (no changes). */
524  return OPERATOR_FINISHED;
525 }
526 
528 {
529  /* Identifiers */
530  ot->name = "Copy Keyframes";
531  ot->idname = "GRAPH_OT_copy";
532  ot->description = "Copy selected keyframes to the copy/paste buffer";
533 
534  /* API callbacks */
537 
538  /* Flags */
540 }
541 
543 {
544  bAnimContext ac;
545 
546  const eKeyPasteOffset offset_mode = RNA_enum_get(op->ptr, "offset");
547  const eKeyMergeMode merge_mode = RNA_enum_get(op->ptr, "merge");
548  const bool flipped = RNA_boolean_get(op->ptr, "flipped");
549 
550  /* Get editor data. */
551  if (ANIM_animdata_get_context(C, &ac) == 0) {
552  return OPERATOR_CANCELLED;
553  }
554 
555  /* Ac.reports by default will be the global reports list, which won't show warnings. */
556  ac.reports = op->reports;
557 
558  const eKeyPasteError kf_empty = paste_graph_keys(&ac, offset_mode, merge_mode, flipped);
559  switch (kf_empty) {
560  case KEYFRAME_PASTE_OK:
561  break;
562 
564  BKE_report(op->reports, RPT_ERROR, "No selected F-Curves to paste into");
565  return OPERATOR_CANCELLED;
566 
568  BKE_report(op->reports, RPT_ERROR, "No data in buffer to paste");
569  return OPERATOR_CANCELLED;
570  }
571 
572  /* Set notifier that keyframes have changed. */
574 
575  return OPERATOR_FINISHED;
576 }
577 
579  wmOperatorType *UNUSED(op),
580  PointerRNA *ptr)
581 {
582  /* Custom description if the 'flipped' option is used. */
583  if (RNA_boolean_get(ptr, "flipped")) {
584  return BLI_strdup(TIP_("Paste keyframes from mirrored bones if they exist"));
585  }
586 
587  /* Use the default description in the other cases. */
588  return NULL;
589 }
590 
592 {
593  PropertyRNA *prop;
594 
595  /* Identifiers */
596  ot->name = "Paste Keyframes";
597  ot->idname = "GRAPH_OT_paste";
598  ot->description =
599  "Paste keyframes from copy/paste buffer for the selected channels, starting on the current "
600  "frame";
601 
602  /* API callbacks */
603 
604  // ot->invoke = WM_operator_props_popup; /* better wait for graph redo panel */
608 
609  /* Flags */
611 
612  /* Props */
614  "offset",
617  "Offset",
618  "Paste time offset of keys");
620  "merge",
623  "Type",
624  "Method of merging pasted keys and existing");
625  prop = RNA_def_boolean(
626  ot->srna, "flipped", false, "Flipped", "Paste keyframes from mirrored bones if they exist");
628 }
629 
632 /* -------------------------------------------------------------------- */
637 {
638  ListBase anim_data = {NULL, NULL};
639  bAnimListElem *ale;
640  int filter;
641  bool changed = false;
642 
643  /* Filter data. */
646  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
647 
648  /* Loop through filtered data and delete selected keys. */
649  for (ale = anim_data.first; ale; ale = ale->next) {
650  changed |= duplicate_fcurve_keys((FCurve *)ale->key_data);
651 
652  ale->update |= ANIM_UPDATE_DEFAULT;
653  }
654 
655  ANIM_animdata_update(ac, &anim_data);
656  ANIM_animdata_freelist(&anim_data);
657 
658  return changed;
659 }
660 
661 /* ------------------- */
662 
664 {
665  bAnimContext ac;
666 
667  /* Get editor data. */
668  if (ANIM_animdata_get_context(C, &ac) == 0) {
669  return OPERATOR_CANCELLED;
670  }
671 
672  /* Duplicate keyframes. */
673  if (!duplicate_graph_keys(&ac)) {
674  return OPERATOR_CANCELLED;
675  }
676 
677  /* Set notifier that keyframes have changed. */
679 
680  return OPERATOR_FINISHED;
681 }
682 
684 {
685  /* Identifiers */
686  ot->name = "Duplicate Keyframes";
687  ot->idname = "GRAPH_OT_duplicate";
688  ot->description = "Make a copy of all selected keyframes";
689 
690  /* API callbacks */
693 
694  /* Flags */
696 
697  /* To give to transform. */
699 }
700 
703 /* -------------------------------------------------------------------- */
708 {
709  ListBase anim_data = {NULL, NULL};
710  bAnimListElem *ale;
711  int filter;
712  bool changed_final = false;
713 
714  /* Filter data. */
717  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
718 
719  /* Loop through filtered data and delete selected keys. */
720  for (ale = anim_data.first; ale; ale = ale->next) {
721  FCurve *fcu = (FCurve *)ale->key_data;
722  AnimData *adt = ale->adt;
723  bool changed;
724 
725  /* Delete selected keyframes only. */
726  changed = BKE_fcurve_delete_keys_selected(fcu);
727 
728  if (changed) {
729  ale->update |= ANIM_UPDATE_DEFAULT;
730  changed_final = true;
731  }
732 
733  /* Only delete curve too if it won't be doing anything anymore. */
734  if (BKE_fcurve_is_empty(fcu)) {
735  ANIM_fcurve_delete_from_animdata(ac, adt, fcu);
736  ale->key_data = NULL;
737  }
738  }
739 
740  ANIM_animdata_update(ac, &anim_data);
741  ANIM_animdata_freelist(&anim_data);
742 
743  return changed_final;
744 }
745 
746 /* ------------------- */
747 
749 {
750  bAnimContext ac;
751 
752  /* Get editor data. */
753  if (ANIM_animdata_get_context(C, &ac) == 0) {
754  return OPERATOR_CANCELLED;
755  }
756 
757  /* Delete keyframes. */
758  if (!delete_graph_keys(&ac)) {
759  return OPERATOR_CANCELLED;
760  }
761 
762  /* Set notifier that keyframes have changed. */
764 
765  return OPERATOR_FINISHED;
766 }
767 
769 {
770  /* Identifiers */
771  ot->name = "Delete Keyframes";
772  ot->idname = "GRAPH_OT_delete";
773  ot->description = "Remove all selected keyframes";
774 
775  /* API callbacks */
779 
780  /* Flags */
783 }
784 
787 /* -------------------------------------------------------------------- */
791 static void clean_graph_keys(bAnimContext *ac, float thresh, bool clean_chan)
792 {
793  ListBase anim_data = {NULL, NULL};
794  bAnimListElem *ale;
795  int filter;
796 
797  /* Filter data. */
800  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
801 
802  /* Loop through filtered data and clean curves. */
803  for (ale = anim_data.first; ale; ale = ale->next) {
804  clean_fcurve(ac, ale, thresh, clean_chan);
805 
806  ale->update |= ANIM_UPDATE_DEFAULT;
807  }
808 
809  ANIM_animdata_update(ac, &anim_data);
810  ANIM_animdata_freelist(&anim_data);
811 }
812 
813 /* ------------------- */
814 
816 {
817  bAnimContext ac;
818  float thresh;
819  bool clean_chan;
820 
821  /* Get editor data. */
822  if (ANIM_animdata_get_context(C, &ac) == 0) {
823  return OPERATOR_CANCELLED;
824  }
825 
826  /* Get cleaning threshold. */
827  thresh = RNA_float_get(op->ptr, "threshold");
828  clean_chan = RNA_boolean_get(op->ptr, "channels");
829  /* Clean keyframes. */
830  clean_graph_keys(&ac, thresh, clean_chan);
831 
832  /* Set notifier that keyframes have changed. */
834 
835  return OPERATOR_FINISHED;
836 }
837 
839 {
840  /* Identifiers */
841  ot->name = "Clean Keyframes";
842  ot->idname = "GRAPH_OT_clean";
843  ot->description = "Simplify F-Curves by removing closely spaced keyframes";
844 
845  /* API callbacks */
846  // ot->invoke = ???; /* XXX we need that number popup for this! */
849 
850  /* Flags */
852 
853  /* Properties */
854  ot->prop = RNA_def_float(
855  ot->srna, "threshold", 0.001f, 0.0f, FLT_MAX, "Threshold", "", 0.0f, 1000.0f);
856  RNA_def_boolean(ot->srna, "channels", false, "Channels", "");
857 }
858 
861 /* -------------------------------------------------------------------- */
867 /* Bake each F-Curve into a set of samples. */
868 static void bake_graph_curves(bAnimContext *ac, int start, int end)
869 {
870  ListBase anim_data = {NULL, NULL};
871  bAnimListElem *ale;
872  int filter;
873 
874  /* Filter data. */
877  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
878 
879  /* Loop through filtered data and add keys between selected keyframes on every frame. */
880  for (ale = anim_data.first; ale; ale = ale->next) {
881  FCurve *fcu = (FCurve *)ale->key_data;
882  ChannelDriver *driver = fcu->driver;
883 
884  /* Disable driver so that it don't muck up the sampling process. */
885  fcu->driver = NULL;
886 
887  /* Create samples. */
889 
890  /* Restore driver. */
891  fcu->driver = driver;
892 
893  ale->update |= ANIM_UPDATE_DEPS;
894  }
895 
896  ANIM_animdata_update(ac, &anim_data);
897  ANIM_animdata_freelist(&anim_data);
898 }
899 
900 /* ------------------- */
901 
903 {
904  bAnimContext ac;
905  Scene *scene = NULL;
906  int start, end;
907 
908  /* Get editor data. */
909  if (ANIM_animdata_get_context(C, &ac) == 0) {
910  return OPERATOR_CANCELLED;
911  }
912 
913  /* For now, init start/end from preview-range extents. */
914  /* TODO: add properties for this. (Joshua Leung 2009) */
915  scene = ac.scene;
916  start = PSFRA;
917  end = PEFRA;
918 
919  /* Bake keyframes. */
920  bake_graph_curves(&ac, start, end);
921 
922  /* Set notifier that keyframes have changed. */
923  /* NOTE: some distinction between order/number of keyframes and type should be made? */
925 
926  return OPERATOR_FINISHED;
927 }
928 
930 {
931  /* Identifiers */
932  ot->name = "Bake Curve";
933  ot->idname = "GRAPH_OT_bake";
934  ot->description = "Bake selected F-Curves to a set of sampled points defining a similar curve";
935 
936  /* API callbacks */
937  ot->invoke = WM_operator_confirm; /* FIXME */
940 
941  /* Flags */
943 
944  /* TODO: add props for start/end frames (Joshua Leung 2009) */
945 }
946 
949 /* -------------------------------------------------------------------- */
955 /* Un-Bake F-Points into F-Curves. */
956 static void unbake_graph_curves(bAnimContext *ac, int start, int end)
957 {
958  ListBase anim_data = {NULL, NULL};
959  bAnimListElem *ale;
960 
961  /* Filter data. */
964  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
965 
966  /* Loop through filtered data and add keys between selected keyframes on every frame. */
967  for (ale = anim_data.first; ale; ale = ale->next) {
968  FCurve *fcu = (FCurve *)ale->key_data;
969 
970  fcurve_samples_to_keyframes(fcu, start, end);
971 
972  ale->update |= ANIM_UPDATE_DEPS;
973  }
974 
975  ANIM_animdata_update(ac, &anim_data);
976  ANIM_animdata_freelist(&anim_data);
977 }
978 
979 /* ------------------- */
980 
982 {
983  bAnimContext ac;
984  Scene *scene = NULL;
985  int start, end;
986 
987  /* Get editor data. */
988  if (ANIM_animdata_get_context(C, &ac) == 0) {
989  return OPERATOR_CANCELLED;
990  }
991 
992  scene = ac.scene;
993  start = PSFRA;
994  end = PEFRA;
995 
996  /* Unbake keyframes. */
997  unbake_graph_curves(&ac, start, end);
998 
999  /* Set notifier that keyframes have changed. */
1000  /* NOTE: some distinction between order/number of keyframes and type should be made? */
1002 
1003  return OPERATOR_FINISHED;
1004 }
1005 
1007 {
1008  /* Identifiers */
1009  ot->name = "Un-Bake Curve";
1010  ot->idname = "GRAPH_OT_unbake";
1011  ot->description = "Un-Bake selected F-Points to F-Curves";
1012 
1013  /* API callbacks */
1016 
1017  /* Flags */
1019 }
1020 
1021 #ifdef WITH_AUDASPACE
1022 
1025 /* -------------------------------------------------------------------- */
1031 /* ------------------- */
1032 
1033 /* Custom data storage passed to the F-Sample-ing function,
1034  * which provides the necessary info for baking the sound.
1035  */
1036 typedef struct tSoundBakeInfo {
1037  float *samples;
1038  int length;
1039  int cfra;
1040 } tSoundBakeInfo;
1041 
1042 /* ------------------- */
1043 
1044 /* Sampling callback used to determine the value from the sound to
1045  * save in the F-Curve at the specified frame.
1046  */
1047 static float fcurve_samplingcb_sound(FCurve *UNUSED(fcu), void *data, float evaltime)
1048 {
1049  tSoundBakeInfo *sbi = (tSoundBakeInfo *)data;
1050 
1051  int position = evaltime - sbi->cfra;
1052  if ((position < 0) || (position >= sbi->length)) {
1053  return 0.0f;
1054  }
1055 
1056  return sbi->samples[position];
1057 }
1058 
1059 /* ------------------- */
1060 
1062 {
1063  bAnimContext ac;
1064  ListBase anim_data = {NULL, NULL};
1065  bAnimListElem *ale;
1066  int filter;
1067 
1068  tSoundBakeInfo sbi;
1069  Scene *scene = NULL;
1070  int start, end;
1071 
1072  char path[FILE_MAX];
1073 
1074  /* Get editor data. */
1075  if (ANIM_animdata_get_context(C, &ac) == 0) {
1076  return OPERATOR_CANCELLED;
1077  }
1078 
1079  RNA_string_get(op->ptr, "filepath", path);
1080 
1081  if (!BLI_is_file(path)) {
1082  BKE_reportf(op->reports, RPT_ERROR, "File not found '%s'", path);
1083  return OPERATOR_CANCELLED;
1084  }
1085 
1086  scene = ac.scene; /* Current scene. */
1087 
1088  /* Store necessary data for the baking steps. */
1089  sbi.samples = AUD_readSoundBuffer(path,
1090  RNA_float_get(op->ptr, "low"),
1091  RNA_float_get(op->ptr, "high"),
1092  RNA_float_get(op->ptr, "attack"),
1093  RNA_float_get(op->ptr, "release"),
1094  RNA_float_get(op->ptr, "threshold"),
1095  RNA_boolean_get(op->ptr, "use_accumulate"),
1096  RNA_boolean_get(op->ptr, "use_additive"),
1097  RNA_boolean_get(op->ptr, "use_square"),
1098  RNA_float_get(op->ptr, "sthreshold"),
1099  FPS,
1100  &sbi.length,
1101  0);
1102 
1103  if (sbi.samples == NULL) {
1104  BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
1105  return OPERATOR_CANCELLED;
1106  }
1107 
1108  /* Determine extents of the baking. */
1109  sbi.cfra = start = scene->r.cfra;
1110  end = scene->r.cfra + sbi.length - 1;
1111 
1112  /* Filter anim channels. */
1115  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1116 
1117  /* Loop through all selected F-Curves, replacing its data with the sound samples. */
1118  for (ale = anim_data.first; ale; ale = ale->next) {
1119  FCurve *fcu = (FCurve *)ale->key_data;
1120 
1121  /* Sample the sound. */
1122  fcurve_store_samples(fcu, &sbi, start, end, fcurve_samplingcb_sound);
1123 
1124  ale->update |= ANIM_UPDATE_DEFAULT;
1125  }
1126 
1127  /* Free sample data. */
1128  free(sbi.samples);
1129 
1130  /* Validate keyframes after editing. */
1131  ANIM_animdata_update(&ac, &anim_data);
1132  ANIM_animdata_freelist(&anim_data);
1133 
1134  /* Set notifier that 'keyframes' have changed. */
1136 
1137  return OPERATOR_FINISHED;
1138 }
1139 
1140 #else /* WITH_AUDASPACE */
1141 
1143 {
1144  BKE_report(op->reports, RPT_ERROR, "Compiled without sound support");
1145 
1146  return OPERATOR_CANCELLED;
1147 }
1148 
1149 #endif /* WITH_AUDASPACE */
1150 
1152 {
1153  bAnimContext ac;
1154 
1155  /* Verify editor data. */
1156  if (ANIM_animdata_get_context(C, &ac) == 0) {
1157  return OPERATOR_CANCELLED;
1158  }
1159 
1160  return WM_operator_filesel(C, op, event);
1161 }
1162 
1164 {
1165  /* Identifiers */
1166  ot->name = "Bake Sound to F-Curves";
1167  ot->idname = "GRAPH_OT_sound_bake";
1168  ot->description = "Bakes a sound wave to selected F-Curves";
1169 
1170  /* API callbacks */
1174 
1175  /* Flags */
1177 
1178  /* Properties */
1181  FILE_SPECIAL,
1182  FILE_OPENFILE,
1187  "low",
1188  0.0f,
1189  0.0,
1190  100000.0,
1191  "Lowest Frequency",
1192  "Cutoff frequency of a high-pass filter that is applied to the audio data",
1193  0.1,
1194  1000.00);
1196  "high",
1197  100000.0,
1198  0.0,
1199  100000.0,
1200  "Highest Frequency",
1201  "Cutoff frequency of a low-pass filter that is applied to the audio data",
1202  0.1,
1203  1000.00);
1205  "attack",
1206  0.005,
1207  0.0,
1208  2.0,
1209  "Attack Time",
1210  "Value for the hull curve calculation that tells how fast the hull curve can rise "
1211  "(the lower the value the steeper it can rise)",
1212  0.01,
1213  0.1);
1215  "release",
1216  0.2,
1217  0.0,
1218  5.0,
1219  "Release Time",
1220  "Value for the hull curve calculation that tells how fast the hull curve can fall "
1221  "(the lower the value the steeper it can fall)",
1222  0.01,
1223  0.2);
1225  "threshold",
1226  0.0,
1227  0.0,
1228  1.0,
1229  "Threshold",
1230  "Minimum amplitude value needed to influence the hull curve",
1231  0.01,
1232  0.1);
1234  "use_accumulate",
1235  0,
1236  "Accumulate",
1237  "Only the positive differences of the hull curve amplitudes are summarized to "
1238  "produce the output");
1240  ot->srna,
1241  "use_additive",
1242  0,
1243  "Additive",
1244  "The amplitudes of the hull curve are summarized (or, when Accumulate is enabled, "
1245  "both positive and negative differences are accumulated)");
1247  "use_square",
1248  0,
1249  "Square",
1250  "The output is a square curve (negative values always result in -1, and "
1251  "positive ones in 1)");
1253  "sthreshold",
1254  0.1,
1255  0.0,
1256  1.0,
1257  "Square Threshold",
1258  "Square only: all values with an absolute amplitude lower than that result in 0",
1259  0.01,
1260  0.1);
1261 }
1262 
1265 /* -------------------------------------------------------------------- */
1272 /* Evaluates the curves between each selected keyframe on each frame, and keys the value. */
1274 {
1275  ListBase anim_data = {NULL, NULL};
1276  bAnimListElem *ale;
1277  int filter;
1278 
1279  /* filter data */
1282  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1283 
1284  /* Loop through filtered data and add keys between selected keyframes on every frame. */
1285  for (ale = anim_data.first; ale; ale = ale->next) {
1286  sample_fcurve((FCurve *)ale->key_data);
1287 
1288  ale->update |= ANIM_UPDATE_DEPS;
1289  }
1290 
1291  ANIM_animdata_update(ac, &anim_data);
1292  ANIM_animdata_freelist(&anim_data);
1293 }
1294 
1295 /* ------------------- */
1296 
1298 {
1299  bAnimContext ac;
1300 
1301  /* Get editor data. */
1302  if (ANIM_animdata_get_context(C, &ac) == 0) {
1303  return OPERATOR_CANCELLED;
1304  }
1305 
1306  /* Sample keyframes. */
1307  sample_graph_keys(&ac);
1308 
1309  /* Set notifier that keyframes have changed. */
1311 
1312  return OPERATOR_FINISHED;
1313 }
1314 
1316 {
1317  /* Identifiers */
1318  ot->name = "Sample Keyframes";
1319  ot->idname = "GRAPH_OT_sample";
1320  ot->description = "Add keyframes on every frame between the selected keyframes";
1321 
1322  /* API callbacks */
1325 
1326  /* Flags */
1328 }
1329 
1332 /* ************************************************************************** */
1333 /* EXTRAPOLATION MODE AND KEYFRAME HANDLE SETTINGS */
1334 
1335 /* -------------------------------------------------------------------- */
1339 /* Defines for make/clear cyclic extrapolation tools. */
1340 #define MAKE_CYCLIC_EXPO -1
1341 #define CLEAR_CYCLIC_EXPO -2
1342 
1343 /* Defines for set extrapolation-type for selected keyframes tool. */
1346  "CONSTANT",
1347  0,
1348  "Constant Extrapolation",
1349  "Values on endpoint keyframes are held"},
1351  "LINEAR",
1352  0,
1353  "Linear Extrapolation",
1354  "Straight-line slope of end segments are extended past the endpoint keyframes"},
1355 
1357  "MAKE_CYCLIC",
1358  0,
1359  "Make Cyclic (F-Modifier)",
1360  "Add Cycles F-Modifier if one doesn't exist already"},
1362  "CLEAR_CYCLIC",
1363  0,
1364  "Clear Cyclic (F-Modifier)",
1365  "Remove Cycles F-Modifier if not needed anymore"},
1366  {0, NULL, 0, NULL, NULL},
1367 };
1368 
1369 /* This function is responsible for setting extrapolation mode for keyframes. */
1370 static void setexpo_graph_keys(bAnimContext *ac, short mode)
1371 {
1372  ListBase anim_data = {NULL, NULL};
1373  bAnimListElem *ale;
1374  int filter;
1375 
1376  /* Filter data. */
1379  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1380 
1381  /* Loop through setting mode per F-Curve. */
1382  for (ale = anim_data.first; ale; ale = ale->next) {
1383  FCurve *fcu = (FCurve *)ale->data;
1384 
1385  if (mode >= 0) {
1386  /* Just set mode setting. */
1387  fcu->extend = mode;
1388 
1389  ale->update |= ANIM_UPDATE_HANDLES;
1390  }
1391  else {
1392  /* Shortcuts for managing Cycles F-Modifiers to make it easier to toggle cyclic animation
1393  * without having to go through FModifier UI in Graph Editor to do so.
1394  */
1395  if (mode == MAKE_CYCLIC_EXPO) {
1396  /* Only add if one doesn't exist. */
1398  /* TODO: add some more preset versions which set different extrapolation options?
1399  * (Joshua Leung 2011) */
1401  }
1402  }
1403  else if (mode == CLEAR_CYCLIC_EXPO) {
1404  /* Remove all the modifiers fitting this description. */
1405  FModifier *fcm, *fcn = NULL;
1406 
1407  for (fcm = fcu->modifiers.first; fcm; fcm = fcn) {
1408  fcn = fcm->next;
1409 
1410  if (fcm->type == FMODIFIER_TYPE_CYCLES) {
1411  remove_fmodifier(&fcu->modifiers, fcm);
1412  }
1413  }
1414  }
1415  }
1416 
1417  ale->update |= ANIM_UPDATE_DEPS;
1418  }
1419 
1420  ANIM_animdata_update(ac, &anim_data);
1421  ANIM_animdata_freelist(&anim_data);
1422 }
1423 
1424 /* ------------------- */
1425 
1427 {
1428  bAnimContext ac;
1429  short mode;
1430 
1431  /* Get editor data. */
1432  if (ANIM_animdata_get_context(C, &ac) == 0) {
1433  return OPERATOR_CANCELLED;
1434  }
1435 
1436  /* Get handle setting mode. */
1437  mode = RNA_enum_get(op->ptr, "type");
1438 
1439  /* Set handle type. */
1440  setexpo_graph_keys(&ac, mode);
1441 
1442  /* Set notifier that keyframe properties have changed. */
1444 
1445  return OPERATOR_FINISHED;
1446 }
1447 
1449 {
1450  /* Identifiers */
1451  ot->name = "Set Keyframe Extrapolation";
1452  ot->idname = "GRAPH_OT_extrapolation_type";
1453  ot->description = "Set extrapolation mode for selected F-Curves";
1454 
1455  /* API callbacks */
1459 
1460  /* Flags */
1462 
1463  /* Id-props */
1464  ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_expo_types, 0, "Type", "");
1465 }
1466 
1469 /* -------------------------------------------------------------------- */
1473 /* This function is responsible for setting interpolation mode for keyframes. */
1474 static void setipo_graph_keys(bAnimContext *ac, short mode)
1475 {
1476  ListBase anim_data = {NULL, NULL};
1477  bAnimListElem *ale;
1478  int filter;
1480 
1481  /* Filter data. */
1484  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1485 
1486  /* Loop through setting BezTriple interpolation
1487  * NOTE: we do not supply KeyframeEditData to the looper yet.
1488  * Currently that's not necessary here.
1489  */
1490  for (ale = anim_data.first; ale; ale = ale->next) {
1492 
1494  }
1495 
1496  ANIM_animdata_update(ac, &anim_data);
1497  ANIM_animdata_freelist(&anim_data);
1498 }
1499 
1500 /* ------------------- */
1501 
1503 {
1504  bAnimContext ac;
1505  short mode;
1506 
1507  /* Get editor data. */
1508  if (ANIM_animdata_get_context(C, &ac) == 0) {
1509  return OPERATOR_CANCELLED;
1510  }
1511 
1512  /* Get handle setting mode. */
1513  mode = RNA_enum_get(op->ptr, "type");
1514 
1515  /* Set handle type. */
1516  setipo_graph_keys(&ac, mode);
1517 
1518  /* Set notifier that keyframe properties have changed. */
1520 
1521  return OPERATOR_FINISHED;
1522 }
1523 
1525 {
1526  /* Identifiers */
1527  ot->name = "Set Keyframe Interpolation";
1528  ot->idname = "GRAPH_OT_interpolation_type";
1529  ot->description =
1530  "Set interpolation mode for the F-Curve segments starting from the selected keyframes";
1531 
1532  /* API callbacks */
1536 
1537  /* Flags */
1539 
1540  /* Id-props */
1541  ot->prop = RNA_def_enum(
1542  ot->srna, "type", rna_enum_beztriple_interpolation_mode_items, 0, "Type", "");
1544 }
1545 
1548 /* -------------------------------------------------------------------- */
1552 static void seteasing_graph_keys(bAnimContext *ac, short mode)
1553 {
1554  ListBase anim_data = {NULL, NULL};
1555  bAnimListElem *ale;
1556  int filter;
1558 
1559  /* Filter data. */
1562  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1563 
1564  /* Loop through setting BezTriple easing.
1565  * NOTE: we do not supply KeyframeEditData to the looper yet.
1566  * Currently that's not necessary here.
1567  */
1568  for (ale = anim_data.first; ale; ale = ale->next) {
1570 
1572  }
1573 
1574  ANIM_animdata_update(ac, &anim_data);
1575  ANIM_animdata_freelist(&anim_data);
1576 }
1577 
1579 {
1580  bAnimContext ac;
1581  short mode;
1582 
1583  /* Get editor data. */
1584  if (ANIM_animdata_get_context(C, &ac) == 0) {
1585  return OPERATOR_CANCELLED;
1586  }
1587 
1588  /* Get handle setting mode. */
1589  mode = RNA_enum_get(op->ptr, "type");
1590 
1591  /* Set handle type. */
1592  seteasing_graph_keys(&ac, mode);
1593 
1594  /* Set notifier that keyframe properties have changed. */
1596 
1597  return OPERATOR_FINISHED;
1598 }
1599 
1601 {
1602  /* Identifiers */
1603  ot->name = "Set Keyframe Easing Type";
1604  ot->idname = "GRAPH_OT_easing_type";
1605  ot->description =
1606  "Set easing type for the F-Curve segments starting from the selected keyframes";
1607 
1608  /* API callbacks */
1612 
1613  /* Flags */
1615 
1616  /* Id-props */
1617  ot->prop = RNA_def_enum(
1618  ot->srna, "type", rna_enum_beztriple_interpolation_easing_items, 0, "Type", "");
1619 }
1620 
1623 /* -------------------------------------------------------------------- */
1627 /* This function is responsible for setting handle-type of selected keyframes. */
1628 static void sethandles_graph_keys(bAnimContext *ac, short mode)
1629 {
1630  ListBase anim_data = {NULL, NULL};
1631  bAnimListElem *ale;
1632  int filter;
1633 
1636 
1637  /* Filter data. */
1640  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1641 
1642  /* Loop through setting flags for handles.
1643  * NOTE: we do not supply KeyframeEditData to the looper yet.
1644  * Currently that's not necessary here.
1645  */
1646  for (ale = anim_data.first; ale; ale = ale->next) {
1647  FCurve *fcu = (FCurve *)ale->key_data;
1648 
1649  /* Any selected keyframes for editing? */
1650  if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, sel_cb, NULL)) {
1651  /* Change type of selected handles. */
1653 
1654  ale->update |= ANIM_UPDATE_DEFAULT;
1655  }
1656  }
1657 
1658  ANIM_animdata_update(ac, &anim_data);
1659  ANIM_animdata_freelist(&anim_data);
1660 }
1661 /* ------------------- */
1662 
1664 {
1665  bAnimContext ac;
1666  short mode;
1667 
1668  /* Get editor data. */
1669  if (ANIM_animdata_get_context(C, &ac) == 0) {
1670  return OPERATOR_CANCELLED;
1671  }
1672 
1673  /* Get handle setting mode. */
1674  mode = RNA_enum_get(op->ptr, "type");
1675 
1676  /* Set handle type. */
1677  sethandles_graph_keys(&ac, mode);
1678 
1679  /* Set notifier that keyframe properties have changed. */
1681 
1682  return OPERATOR_FINISHED;
1683 }
1684 
1686 {
1687  /* Identifiers */
1688  ot->name = "Set Keyframe Handle Type";
1689  ot->idname = "GRAPH_OT_handle_type";
1690  ot->description = "Set type of handle for selected keyframes";
1691 
1692  /* API callbacks */
1696 
1697  /* Flags */
1699 
1700  /* Id-props */
1701  ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_keyframe_handle_type_items, 0, "Type", "");
1702 }
1703 
1706 /* ************************************************************************** */
1707 /* EULER FILTER */
1708 
1709 /* -------------------------------------------------------------------- */
1718 /* Set of three euler-rotation F-Curves. */
1719 typedef struct tEulerFilter {
1721 
1723  ID *id;
1727  const char *rna_path;
1729 
1730 static bool keyframe_time_differs(BezTriple *keyframes[3])
1731 {
1732  const float precision = 1e-5;
1733  return fabs(keyframes[0]->vec[1][0] - keyframes[1]->vec[1][0]) > precision ||
1734  fabs(keyframes[1]->vec[1][0] - keyframes[2]->vec[1][0]) > precision ||
1735  fabs(keyframes[0]->vec[1][0] - keyframes[2]->vec[1][0]) > precision;
1736 }
1737 
1738 /* Find groups of `rotation_euler` channels. */
1739 static ListBase /*tEulerFilter*/ euler_filter_group_channels(
1740  const ListBase /*bAnimListElem*/ *anim_data, ReportList *reports, int *r_num_groups)
1741 {
1742  ListBase euler_groups = {NULL, NULL};
1743  tEulerFilter *euf = NULL;
1744  *r_num_groups = 0;
1745 
1746  LISTBASE_FOREACH (bAnimListElem *, ale, anim_data) {
1747  FCurve *const fcu = (FCurve *)ale->data;
1748 
1749  /* Check if this is an appropriate F-Curve:
1750  * - Only rotation curves.
1751  * - For pchan curves, make sure we're only using the euler curves.
1752  */
1753  if (strstr(fcu->rna_path, "rotation_euler") == NULL) {
1754  continue;
1755  }
1756  if (ELEM(fcu->array_index, 0, 1, 2) == 0) {
1757  BKE_reportf(reports,
1758  RPT_WARNING,
1759  "Euler Rotation F-Curve has invalid index (ID='%s', Path='%s', Index=%d)",
1760  (ale->id) ? ale->id->name : TIP_("<No ID>"),
1761  fcu->rna_path,
1762  fcu->array_index);
1763  continue;
1764  }
1765 
1766  /* Assume that this animation channel will be touched by the Euler filter. Doing this here
1767  * saves another loop over the animation data. */
1768  ale->update |= ANIM_UPDATE_DEFAULT;
1769 
1770  /* Optimization: assume that xyz curves will always be stored consecutively,
1771  * so if the paths or the ID's don't match up, then a curve needs to be added
1772  * to a new group.
1773  */
1774  if ((euf) && (euf->id == ale->id) && (STREQ(euf->rna_path, fcu->rna_path))) {
1775  /* This should be fine to add to the existing group then. */
1776  euf->fcurves[fcu->array_index] = fcu;
1777  continue;
1778  }
1779 
1780  /* Just add to a new block. */
1781  euf = MEM_callocN(sizeof(tEulerFilter), "tEulerFilter");
1782  BLI_addtail(&euler_groups, euf);
1783  ++*r_num_groups;
1784 
1785  euf->id = ale->id;
1786  /* This should be safe, since we're only using it for a short time. */
1787  euf->rna_path = fcu->rna_path;
1788  euf->fcurves[fcu->array_index] = fcu;
1789  }
1790 
1791  return euler_groups;
1792 }
1793 
1794 /* Perform discontinuity filter based on conversion to matrix and back.
1795  * Return true if the curves were filtered (which may have been a no-op), false otherwise. */
1797 {
1798  /* Sanity check: ensure that there are enough F-Curves to work on in this group. */
1799  if (ELEM(NULL, euf->fcurves[0], euf->fcurves[1], euf->fcurves[2])) {
1800  /* Report which components are missing. */
1801  BKE_reportf(reports,
1802  RPT_INFO,
1803  "Missing %s%s%s component(s) of euler rotation for ID='%s' and RNA-Path='%s'",
1804  (euf->fcurves[0] == NULL) ? "X" : "",
1805  (euf->fcurves[1] == NULL) ? "Y" : "",
1806  (euf->fcurves[2] == NULL) ? "Z" : "",
1807  euf->id->name,
1808  euf->rna_path);
1809  return false;
1810  }
1811 
1812  FCurve *fcu_rot_x = euf->fcurves[0];
1813  FCurve *fcu_rot_y = euf->fcurves[1];
1814  FCurve *fcu_rot_z = euf->fcurves[2];
1815  if (fcu_rot_x->totvert != fcu_rot_y->totvert || fcu_rot_y->totvert != fcu_rot_z->totvert) {
1816  BKE_reportf(reports,
1817  RPT_INFO,
1818  "XYZ rotations not equally keyed for ID='%s' and RNA-Path='%s'",
1819  euf->id->name,
1820  euf->rna_path);
1821  return false;
1822  }
1823 
1824  if (fcu_rot_x->totvert < 2) {
1825  /* Empty curves and single keyframes are trivially "filtered". */
1826  return false;
1827  }
1828 
1829  float filtered_euler[3] = {
1830  fcu_rot_x->bezt[0].vec[1][1],
1831  fcu_rot_y->bezt[0].vec[1][1],
1832  fcu_rot_z->bezt[0].vec[1][1],
1833  };
1834 
1835  for (int keyframe_index = 1; keyframe_index < fcu_rot_x->totvert; ++keyframe_index) {
1836  BezTriple *keyframes[3] = {
1837  &fcu_rot_x->bezt[keyframe_index],
1838  &fcu_rot_y->bezt[keyframe_index],
1839  &fcu_rot_z->bezt[keyframe_index],
1840  };
1841 
1842  if (keyframe_time_differs(keyframes)) {
1843  /* The X-coordinates of the keyframes are different, so we cannot correct this key. */
1844  continue;
1845  }
1846 
1847  const float unfiltered_euler[3] = {
1848  keyframes[0]->vec[1][1],
1849  keyframes[1]->vec[1][1],
1850  keyframes[2]->vec[1][1],
1851  };
1852 
1853  /* The conversion back from matrix to Euler angles actually performs the filtering. */
1854  float matrix[3][3];
1855  eul_to_mat3(matrix, unfiltered_euler);
1856  mat3_normalized_to_compatible_eul(filtered_euler, filtered_euler, matrix);
1857 
1858  /* TODO(Sybren): it might be a nice touch to compare `filtered_euler` with `unfiltered_euler`,
1859  * to see if there was actually a change. This could improve reporting for the artist. */
1860 
1861  BKE_fcurve_keyframe_move_value_with_handles(keyframes[0], filtered_euler[0]);
1862  BKE_fcurve_keyframe_move_value_with_handles(keyframes[1], filtered_euler[1]);
1863  BKE_fcurve_keyframe_move_value_with_handles(keyframes[2], filtered_euler[2]);
1864  }
1865 
1866  return true;
1867 }
1868 
1869 /* Remove 360-degree flips from a single FCurve.
1870  * Return true if the curve was modified, false otherwise. */
1872 {
1873  /* Simple method: just treat any difference between keys of greater than 180 degrees as being a
1874  * flip. */
1875  BezTriple *bezt, *prev;
1876  uint i;
1877 
1878  /* Skip if not enough verts to do a decent analysis. */
1879  if (fcu->totvert <= 2) {
1880  return false;
1881  }
1882 
1883  /* `prev` follows bezt, bezt = "current" point to be fixed. */
1884  /* Our method depends on determining a "difference" from the previous vert. */
1885  bool is_modified = false;
1886  for (i = 1, prev = fcu->bezt, bezt = fcu->bezt + 1; i < fcu->totvert; i++, prev = bezt++) {
1887  const float sign = (prev->vec[1][1] > bezt->vec[1][1]) ? 1.0f : -1.0f;
1888 
1889  /* >= 180 degree flip? */
1890  if ((sign * (prev->vec[1][1] - bezt->vec[1][1])) < (float)M_PI) {
1891  continue;
1892  }
1893 
1894  /* 360 degrees to add/subtract frame value until difference
1895  * is acceptably small that there's no more flip. */
1896  const float fac = sign * 2.0f * (float)M_PI;
1897 
1898  while ((sign * (prev->vec[1][1] - bezt->vec[1][1])) >= (float)M_PI) {
1899  bezt->vec[0][1] += fac;
1900  bezt->vec[1][1] += fac;
1901  bezt->vec[2][1] += fac;
1902  }
1903 
1904  is_modified = true;
1905  }
1906 
1907  return is_modified;
1908 }
1909 
1910 static void euler_filter_perform_filter(ListBase /*tEulerFilter*/ *eulers,
1911  ReportList *reports,
1912  int *r_curves_filtered,
1913  int *r_curves_seen)
1914 {
1915  *r_curves_filtered = 0;
1916  *r_curves_seen = 0;
1917 
1918  LISTBASE_FOREACH (tEulerFilter *, euf, eulers) {
1919  int curves_filtered_this_group = 0;
1920 
1921  if (euler_filter_multi_channel(euf, reports)) {
1922  curves_filtered_this_group = 3;
1923  }
1924 
1925  for (int channel_index = 0; channel_index < 3; channel_index++) {
1926  FCurve *fcu = euf->fcurves[channel_index];
1927  if (fcu == NULL) {
1928  continue;
1929  }
1930  ++*r_curves_seen;
1931 
1932  if (euler_filter_single_channel(fcu)) {
1933  ++curves_filtered_this_group;
1934  }
1935  }
1936 
1937  *r_curves_filtered += min_ii(3, curves_filtered_this_group);
1938  }
1939 }
1940 
1942 {
1943  /* Get editor data. */
1944  bAnimContext ac;
1945  if (ANIM_animdata_get_context(C, &ac) == 0) {
1946  return OPERATOR_CANCELLED;
1947  }
1948 
1949  /* The process is done in two passes:
1950  * 1) Sets of three related rotation curves are identified from the selected channels,
1951  * and are stored as a single 'operation unit' for the next step.
1952  * 2) Each set of three F-Curves is processed for each keyframe, with the values being
1953  * processed as necessary.
1954  */
1955 
1956  /* Step 1: extract only the rotation f-curves. */
1959  ListBase anim_data = {NULL, NULL};
1960  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1961 
1962  int groups = 0;
1963  ListBase eulers = euler_filter_group_channels(&anim_data, op->reports, &groups);
1964  BLI_assert(BLI_listbase_count(&eulers) == groups);
1965 
1966  if (groups == 0) {
1967  ANIM_animdata_freelist(&anim_data);
1968  BKE_report(op->reports, RPT_WARNING, "No Euler Rotation F-Curves to fix up");
1969  return OPERATOR_CANCELLED;
1970  }
1971 
1972  /* Step 2: go through each set of curves, processing the values at each keyframe.
1973  * - It is assumed that there must be a full set of keyframes at each keyframe position.
1974  */
1975  int curves_filtered;
1976  int curves_seen;
1977  euler_filter_perform_filter(&eulers, op->reports, &curves_filtered, &curves_seen);
1978 
1979  BLI_freelistN(&eulers);
1980  ANIM_animdata_update(&ac, &anim_data);
1981  ANIM_animdata_freelist(&anim_data);
1982 
1983  if (curves_filtered == 0) {
1984  if (curves_seen < 3) {
1985  /* Showing the entire error message makes no sense when the artist is only trying to filter
1986  * one or two curves. */
1987  BKE_report(op->reports, RPT_WARNING, "No Euler Rotations could be corrected");
1988  }
1989  else {
1990  BKE_report(op->reports,
1991  RPT_ERROR,
1992  "No Euler Rotations could be corrected, ensure each rotation has keys for all "
1993  "components, "
1994  "and that F-Curves for these are in consecutive XYZ order and selected");
1995  }
1996  return OPERATOR_CANCELLED;
1997  }
1998 
1999  if (curves_filtered != curves_seen) {
2000  BLI_assert(curves_filtered < curves_seen);
2001  BKE_reportf(op->reports,
2002  RPT_INFO,
2003  "%d of %d rotation channels were filtered (see the Info window for details)",
2004  curves_filtered,
2005  curves_seen);
2006  }
2007  else if (curves_seen == 1) {
2008  BKE_report(op->reports, RPT_INFO, "The rotation channel was filtered");
2009  }
2010  else {
2011  BKE_reportf(op->reports, RPT_INFO, "All %d rotation channels were filtered", curves_seen);
2012  }
2013 
2014  /* Set notifier that keyframes have changed. */
2016 
2017  /* Done at last. */
2018  return OPERATOR_FINISHED;
2019 }
2020 
2022 {
2023  /* Identifiers */
2024  ot->name = "Euler Discontinuity Filter";
2025  ot->idname = "GRAPH_OT_euler_filter";
2026  ot->description =
2027  "Fix large jumps and flips in the selected "
2028  "Euler Rotation F-Curves arising from rotation "
2029  "values being clipped when baking physics";
2030 
2031  /* API callbacks */
2034 
2035  /* Flags */
2037 }
2038 
2041 /* ************************************************************************** */
2042 /* SNAPPING */
2043 
2044 /* -------------------------------------------------------------------- */
2049 {
2050  /* Prevent changes during render. */
2051  if (G.is_rendering) {
2052  return false;
2053  }
2054 
2056 }
2057 
2059 {
2060  ListBase anim_data = {NULL, NULL};
2061  bAnimListElem *ale;
2062  int filter;
2063  KeyframeEditData ked;
2064 
2065  /* Init edit data. */
2066  memset(&ked, 0, sizeof(KeyframeEditData));
2067 
2068  /* Loop over action data, averaging values. */
2071  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
2072 
2073  for (ale = anim_data.first; ale; ale = ale->next) {
2074  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
2075  short mapping_flag = ANIM_get_normalization_flags(ac);
2076  KeyframeEditData current_ked;
2077  float offset;
2078  float unit_scale = ANIM_unit_mapping_get_factor(
2079  ac->scene, ale->id, ale->key_data, mapping_flag | ANIM_UNITCONV_ONLYKEYS, &offset);
2080 
2081  memset(&current_ked, 0, sizeof(current_ked));
2082 
2083  if (adt) {
2084  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
2086  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
2087  }
2088  else {
2090  }
2091 
2092  ked.f1 += current_ked.f1;
2093  ked.i1 += current_ked.i1;
2094  ked.f2 += (current_ked.f2 + offset) * unit_scale;
2095  ked.i2 += current_ked.i2;
2096  }
2097 
2098  ANIM_animdata_freelist(&anim_data);
2099 
2100  return ked;
2101 }
2102 
2103 /* Snap current-frame indicator to 'average time' of selected keyframe. */
2105 {
2106  bAnimContext ac;
2107 
2108  /* Get editor data. */
2109  if (ANIM_animdata_get_context(C, &ac) == 0) {
2110  return OPERATOR_CANCELLED;
2111  }
2112 
2113  const KeyframeEditData keyframe_sum = sum_selected_keyframes(&ac);
2114  const float sum_time = keyframe_sum.f1;
2115  const float sum_value = keyframe_sum.f2;
2116  const int num_keyframes = keyframe_sum.i1;
2117 
2118  if (num_keyframes == 0) {
2119  return OPERATOR_FINISHED;
2120  }
2121 
2122  /* Set the new current frame and cursor values, based on the average time and value. */
2123  SpaceGraph *sipo = (SpaceGraph *)ac.sl;
2124  Scene *scene = ac.scene;
2125 
2126  /* Take the average values, rounding to the nearest int as necessary for int results. */
2127  if (sipo->mode == SIPO_MODE_DRIVERS) {
2128  /* Drivers Mode - Affects cursor (float) */
2129  sipo->cursorTime = sum_time / (float)num_keyframes;
2130  }
2131  else {
2132  /* Animation Mode - Affects current frame (int) */
2133  scene->r.cfra = round_fl_to_int(sum_time / num_keyframes);
2134  scene->r.subframe = 0.0f;
2135  }
2136  sipo->cursorVal = sum_value / (float)num_keyframes;
2137 
2138  /* Set notifier that things have changed. */
2140 
2141  return OPERATOR_FINISHED;
2142 }
2143 
2145 {
2146  /* Identifiers */
2147  ot->name = "Jump to Keyframes";
2148  ot->idname = "GRAPH_OT_frame_jump";
2149  ot->description = "Place the cursor on the midpoint of selected keyframes";
2150 
2151  /* API callbacks */
2154 
2155  /* Flags */
2157 }
2158 
2159 /* snap 2D cursor value to the average value of selected keyframe */
2161 {
2162  bAnimContext ac;
2163 
2164  if (ANIM_animdata_get_context(C, &ac) == 0) {
2165  return OPERATOR_CANCELLED;
2166  }
2167 
2168  const KeyframeEditData keyframe_sum = sum_selected_keyframes(&ac);
2169  const float sum_value = keyframe_sum.f2;
2170  const int num_keyframes = keyframe_sum.i1;
2171 
2172  if (num_keyframes == 0) {
2173  return OPERATOR_FINISHED;
2174  }
2175 
2176  SpaceGraph *sipo = (SpaceGraph *)ac.sl;
2177  sipo->cursorVal = sum_value / (float)num_keyframes;
2178  // WM_event_add_notifier(C, NC_SCENE | ND_FRAME, ac.scene);
2180 
2181  return OPERATOR_FINISHED;
2182 }
2183 
2185 {
2186  /* Identifiers. */
2187  ot->name = "Snap Cursor Value to Selected";
2188  ot->idname = "GRAPH_OT_snap_cursor_value";
2189  ot->description = "Place the cursor value on the average value of selected keyframes";
2190 
2191  /* API callbacks. */
2194 
2195  /* Flags */
2197 }
2198 
2201 /* -------------------------------------------------------------------- */
2205 /* Defines for snap keyframes tool. */
2208  "CFRA",
2209  0,
2210  "Selection to Current Frame",
2211  "Snap selected keyframes to the current frame"},
2213  "VALUE",
2214  0,
2215  "Selection to Cursor Value",
2216  "Set values of selected keyframes to the cursor value (Y/Horizontal component)"},
2218  "NEAREST_FRAME",
2219  0,
2220  "Selection to Nearest Frame",
2221  "Snap selected keyframes to the nearest (whole) frame (use to fix accidental subframe "
2222  "offsets)"},
2224  "NEAREST_SECOND",
2225  0,
2226  "Selection to Nearest Second",
2227  "Snap selected keyframes to the nearest second"},
2229  "NEAREST_MARKER",
2230  0,
2231  "Selection to Nearest Marker",
2232  "Snap selected keyframes to the nearest marker"},
2234  "HORIZONTAL",
2235  0,
2236  "Flatten Handles",
2237  "Flatten handles for a smoother transition"},
2238  {0, NULL, 0, NULL, NULL},
2239 };
2240 
2241 /* This function is responsible for snapping keyframes to frame-times. */
2242 static void snap_graph_keys(bAnimContext *ac, short mode)
2243 {
2244  ListBase anim_data = {NULL, NULL};
2245  bAnimListElem *ale;
2246  int filter;
2247 
2248  SpaceGraph *sipo = (SpaceGraph *)ac->sl;
2249  KeyframeEditData ked;
2250  KeyframeEditFunc edit_cb;
2251  float cursor_value = 0.0f;
2252 
2253  /* Filter data. */
2256  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
2257 
2258  /* Init custom data for iterating over keyframes. */
2259  memset(&ked, 0, sizeof(KeyframeEditData));
2260  ked.scene = ac->scene;
2261  if (mode == GRAPHKEYS_SNAP_NEAREST_MARKER) {
2262  ked.list.first = (ac->markers) ? ac->markers->first : NULL;
2263  ked.list.last = (ac->markers) ? ac->markers->last : NULL;
2264  }
2265  else if (mode == GRAPHKEYS_SNAP_VALUE) {
2266  cursor_value = (sipo) ? sipo->cursorVal : 0.0f;
2267  }
2268  else if (mode == GRAPHKEYS_SNAP_CFRA) {
2269  /* In drivers mode, use the cursor value instead
2270  * (We need to use a different callback for that though)
2271  */
2272  if (sipo->mode == SIPO_MODE_DRIVERS) {
2273  ked.f1 = sipo->cursorTime;
2274  mode = SNAP_KEYS_TIME;
2275  }
2276  }
2277 
2278  /* Get beztriple editing callbacks. */
2279  edit_cb = ANIM_editkeyframes_snap(mode);
2280 
2281  /* Snap keyframes. */
2282  for (ale = anim_data.first; ale; ale = ale->next) {
2283  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
2284 
2285  /* Normalize cursor value (for normalized F-Curves display). */
2286  if (mode == GRAPHKEYS_SNAP_VALUE) {
2287  short mapping_flag = ANIM_get_normalization_flags(ac);
2288  float offset;
2289  float unit_scale = ANIM_unit_mapping_get_factor(
2290  ac->scene, ale->id, ale->key_data, mapping_flag, &offset);
2291 
2292  ked.f1 = (cursor_value / unit_scale) - offset;
2293  }
2294 
2295  /* Perform snapping. */
2296  if (adt) {
2297  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
2299  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
2300  }
2301  else {
2303  }
2304 
2305  ale->update |= ANIM_UPDATE_DEFAULT;
2306  }
2307 
2308  ANIM_animdata_update(ac, &anim_data);
2309  ANIM_animdata_freelist(&anim_data);
2310 }
2311 
2312 /* ------------------- */
2313 
2315 {
2316  bAnimContext ac;
2317  short mode;
2318 
2319  /* Get editor data. */
2320  if (ANIM_animdata_get_context(C, &ac) == 0) {
2321  return OPERATOR_CANCELLED;
2322  }
2323 
2324  /* Get snapping mode. */
2325  mode = RNA_enum_get(op->ptr, "type");
2326 
2327  /* Snap keyframes. */
2328  snap_graph_keys(&ac, mode);
2329 
2330  /* Set notifier that keyframes have changed. */
2332 
2333  return OPERATOR_FINISHED;
2334 }
2335 
2337 {
2338  /* Identifiers */
2339  ot->name = "Snap Keys";
2340  ot->idname = "GRAPH_OT_snap";
2341  ot->description = "Snap selected keyframes to the chosen times/values";
2342 
2343  /* API callbacks */
2347 
2348  /* Flags */
2350 
2351  /* Id-props */
2352  ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_snap_types, 0, "Type", "");
2353 }
2354 
2357 /* -------------------------------------------------------------------- */
2361 /* Defines for equalize handles tool. */
2363  {GRAPHKEYS_EQUALIZE_LEFT, "LEFT", 0, "Left", "Equalize selected keyframes' left handles"},
2364  {GRAPHKEYS_EQUALIZE_RIGHT, "RIGHT", 0, "Right", "Equalize selected keyframes' right handles"},
2365  {GRAPHKEYS_EQUALIZE_BOTH, "BOTH", 0, "Both", "Equalize both of a keyframe's handles"},
2366  {0, NULL, 0, NULL, NULL},
2367 };
2368 
2369 /* ------------------- */
2370 
2371 /* Equalize selected keyframes' bezier handles. */
2372 static void equalize_graph_keys(bAnimContext *ac, int mode, float handle_length, bool flatten)
2373 {
2374  /* Filter data. */
2377  ListBase anim_data = {NULL, NULL};
2378  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
2379 
2380  /* Equalize keyframes. */
2381  LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
2382  ANIM_fcurve_equalize_keyframes_loop(ale->key_data, mode, handle_length, flatten);
2383  ale->update |= ANIM_UPDATE_DEFAULT;
2384  }
2385 
2386  ANIM_animdata_update(ac, &anim_data);
2387  ANIM_animdata_freelist(&anim_data);
2388 }
2389 
2391 {
2392  bAnimContext ac;
2393 
2394  /* Get editor data. */
2395  if (ANIM_animdata_get_context(C, &ac) == 0) {
2396  return OPERATOR_CANCELLED;
2397  }
2398 
2399  /* Get equalize mode. */
2400  int mode = RNA_enum_get(op->ptr, "side");
2401  float handle_length = RNA_float_get(op->ptr, "handle_length");
2402  bool flatten = RNA_boolean_get(op->ptr, "flatten");
2403 
2404  /* Equalize graph keyframes. */
2405  equalize_graph_keys(&ac, mode, handle_length, flatten);
2406 
2408 
2409  return OPERATOR_FINISHED;
2410 }
2411 
2413 {
2414  /* Identifiers */
2415  ot->name = "Equalize Handles";
2416  ot->idname = "GRAPH_OT_equalize_handles";
2417  ot->description =
2418  "Ensure selected keyframes' handles have equal length, optionally making them horizontal. "
2419  "Automatic, Automatic Clamped, or Vector handle types will be converted to Aligned";
2420  /* API callbacks */
2424 
2425  /* Flags */
2427 
2428  /* Properties */
2429  ot->prop = RNA_def_enum(ot->srna,
2430  "side",
2432  0,
2433  "Side",
2434  "Side of the keyframes' bezier handles to affect");
2436  "handle_length",
2437  5.0f,
2438  0.1f,
2439  FLT_MAX,
2440  "Handle Length",
2441  "Length to make selected keyframes' bezier handles",
2442  1.0f,
2443  50.0f);
2445  ot->srna,
2446  "flatten",
2447  false,
2448  "Flatten",
2449  "Make the values of the selected keyframes' handles the same as their respective keyframes");
2450 }
2451 
2454 /* -------------------------------------------------------------------- */
2458 /* Defines for mirror keyframes tool. */
2461  "CFRA",
2462  0,
2463  "By Times Over Current Frame",
2464  "Flip times of selected keyframes using the current frame as the mirror line"},
2466  "VALUE",
2467  0,
2468  "By Values Over Cursor Value",
2469  "Flip values of selected keyframes using the cursor value (Y/Horizontal component) as the "
2470  "mirror line"},
2472  "YAXIS",
2473  0,
2474  "By Times Over Zero Time",
2475  "Flip times of selected keyframes, effectively reversing the order they appear in"},
2477  "XAXIS",
2478  0,
2479  "By Values Over Zero Value",
2480  "Flip values of selected keyframes (i.e. negative values become positive, and vice versa)"},
2482  "MARKER",
2483  0,
2484  "By Times Over First Selected Marker",
2485  "Flip times of selected keyframes using the first selected marker as the reference point"},
2486  {0, NULL, 0, NULL, NULL},
2487 };
2488 
2489 /* This function is responsible for mirroring keyframes. */
2490 static void mirror_graph_keys(bAnimContext *ac, short mode)
2491 {
2492  ListBase anim_data = {NULL, NULL};
2493  bAnimListElem *ale;
2494  int filter;
2495 
2496  SpaceGraph *sipo = (SpaceGraph *)ac->sl;
2497  KeyframeEditData ked;
2498  KeyframeEditFunc edit_cb;
2499  float cursor_value = 0.0f;
2500 
2501  /* Init custom data for looping over keyframes. */
2502  memset(&ked, 0, sizeof(KeyframeEditData));
2503  ked.scene = ac->scene;
2504 
2505  /* Store mode-specific custom data... */
2506  if (mode == GRAPHKEYS_MIRROR_MARKER) {
2507  TimeMarker *marker = NULL;
2508 
2509  /* Find first selected marker. */
2510  marker = ED_markers_get_first_selected(ac->markers);
2511 
2512  /* Store marker's time (if available). */
2513  if (marker) {
2514  ked.f1 = (float)marker->frame;
2515  }
2516  else {
2517  return;
2518  }
2519  }
2520  else if (mode == GRAPHKEYS_MIRROR_VALUE) {
2521  cursor_value = (sipo) ? sipo->cursorVal : 0.0f;
2522  }
2523  else if (mode == GRAPHKEYS_MIRROR_CFRA) {
2524  /* In drivers mode, use the cursor value instead
2525  * (We need to use a different callback for that though)
2526  */
2527  if (sipo->mode == SIPO_MODE_DRIVERS) {
2528  ked.f1 = sipo->cursorTime;
2529  mode = MIRROR_KEYS_TIME;
2530  }
2531  }
2532 
2533  /* Get beztriple editing callbacks. */
2534  edit_cb = ANIM_editkeyframes_mirror(mode);
2535 
2536  /* Filter data. */
2539  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
2540 
2541  /* Mirror keyframes. */
2542  for (ale = anim_data.first; ale; ale = ale->next) {
2543  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
2544 
2545  /* Apply unit corrections. */
2546  if (mode == GRAPHKEYS_MIRROR_VALUE) {
2547  short mapping_flag = ANIM_get_normalization_flags(ac);
2548  float offset;
2549  float unit_scale = ANIM_unit_mapping_get_factor(
2550  ac->scene, ale->id, ale->key_data, mapping_flag | ANIM_UNITCONV_ONLYKEYS, &offset);
2551 
2552  ked.f1 = (cursor_value - offset) / unit_scale;
2553  }
2554 
2555  /* Perform actual mirroring. */
2556  if (adt) {
2557  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
2559  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
2560  }
2561  else {
2563  }
2564 
2565  ale->update |= ANIM_UPDATE_DEFAULT;
2566  }
2567 
2568  ANIM_animdata_update(ac, &anim_data);
2569  ANIM_animdata_freelist(&anim_data);
2570 }
2571 
2572 /* ------------------- */
2573 
2575 {
2576  bAnimContext ac;
2577  short mode;
2578 
2579  /* Get editor data. */
2580  if (ANIM_animdata_get_context(C, &ac) == 0) {
2581  return OPERATOR_CANCELLED;
2582  }
2583 
2584  /* Get mirroring mode. */
2585  mode = RNA_enum_get(op->ptr, "type");
2586 
2587  /* Mirror keyframes. */
2588  mirror_graph_keys(&ac, mode);
2589 
2590  /* Set notifier that keyframes have changed. */
2592 
2593  return OPERATOR_FINISHED;
2594 }
2595 
2597 {
2598  /* Identifiers */
2599  ot->name = "Mirror Keys";
2600  ot->idname = "GRAPH_OT_mirror";
2601  ot->description = "Flip selected keyframes over the selected mirror line";
2602 
2603  /* API callbacks */
2607 
2608  /* Flags */
2610 
2611  /* Id-props */
2612  ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_mirror_types, 0, "Type", "");
2613 }
2614 
2617 /* -------------------------------------------------------------------- */
2622 {
2623  bAnimContext ac;
2624  ListBase anim_data = {NULL, NULL};
2625  bAnimListElem *ale;
2626  int filter;
2627 
2628  /* Get editor data. */
2629  if (ANIM_animdata_get_context(C, &ac) == 0) {
2630  return OPERATOR_CANCELLED;
2631  }
2632 
2633  /* Filter data. */
2636  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2637 
2638  /* Smooth keyframes. */
2639  for (ale = anim_data.first; ale; ale = ale->next) {
2640  /* For now, we can only smooth by flattening handles AND smoothing curve values.
2641  * Perhaps the mode argument could be removed, as that functionality is offered through
2642  * Snap->Flatten Handles anyway.
2643  */
2644  smooth_fcurve(ale->key_data);
2645 
2646  ale->update |= ANIM_UPDATE_DEFAULT;
2647  }
2648 
2649  ANIM_animdata_update(&ac, &anim_data);
2650  ANIM_animdata_freelist(&anim_data);
2651 
2652  /* Set notifier that keyframes have changed. */
2654 
2655  return OPERATOR_FINISHED;
2656 }
2657 
2659 {
2660  /* Identifiers */
2661  ot->name = "Smooth Keys";
2662  ot->idname = "GRAPH_OT_smooth";
2663  ot->description = "Apply weighted moving means to make selected F-Curves less bumpy";
2664 
2665  /* API callbacks */
2668 
2669  /* Flags */
2671 }
2672 
2675 /* ************************************************************************** */
2676 /* F-CURVE MODIFIERS */
2677 
2678 /* -------------------------------------------------------------------- */
2683  PointerRNA *UNUSED(ptr),
2684  PropertyRNA *UNUSED(prop),
2685  bool *r_free)
2686 {
2687  EnumPropertyItem *item = NULL;
2688  int totitem = 0;
2689  int i = 0;
2690 
2691  if (C == NULL) {
2693  }
2694 
2695  /* Start from 1 to skip the 'Invalid' modifier type. */
2696  for (i = 1; i < FMODIFIER_NUM_TYPES; i++) {
2697  const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(i);
2698  int index;
2699 
2700  /* Check if modifier is valid for this context. */
2701  if (fmi == NULL) {
2702  continue;
2703  }
2704 
2706  if (index != -1) { /* Not all types are implemented yet... */
2707  RNA_enum_item_add(&item, &totitem, &rna_enum_fmodifier_type_items[index]);
2708  }
2709  }
2710 
2711  RNA_enum_item_end(&item, &totitem);
2712  *r_free = true;
2713 
2714  return item;
2715 }
2716 
2718 {
2719  bAnimContext ac;
2720  ListBase anim_data = {NULL, NULL};
2721  bAnimListElem *ale;
2722  int filter;
2723  short type;
2724 
2725  /* Get editor data. */
2726  if (ANIM_animdata_get_context(C, &ac) == 0) {
2727  return OPERATOR_CANCELLED;
2728  }
2729 
2730  /* Get type of modifier to add. */
2731  type = RNA_enum_get(op->ptr, "type");
2732 
2733  /* Filter data. */
2736  if (RNA_boolean_get(op->ptr, "only_active")) {
2737  /* FIXME: enforce in this case only a single channel to get handled? */
2739  }
2740  else {
2742  }
2743  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2744 
2745  /* Add f-modifier to each curve. */
2746  for (ale = anim_data.first; ale; ale = ale->next) {
2747  FCurve *fcu = (FCurve *)ale->data;
2748  FModifier *fcm;
2749 
2750  /* Add F-Modifier of specified type to active F-Curve, and make it the active one. */
2751  fcm = add_fmodifier(&fcu->modifiers, type, fcu);
2752  if (fcm) {
2753  set_active_fmodifier(&fcu->modifiers, fcm);
2754  }
2755  else {
2756  BKE_report(op->reports, RPT_ERROR, "Modifier could not be added (see console for details)");
2757  break;
2758  }
2759 
2760  ale->update |= ANIM_UPDATE_DEPS;
2761  }
2762 
2763  ANIM_animdata_update(&ac, &anim_data);
2764  ANIM_animdata_freelist(&anim_data);
2765 
2766  /* Set notifier that things have changed. */
2768 
2769  return OPERATOR_FINISHED;
2770 }
2771 
2773 {
2774  PropertyRNA *prop;
2775 
2776  /* Identifiers */
2777  ot->name = "Add F-Curve Modifier";
2778  ot->idname = "GRAPH_OT_fmodifier_add";
2779  ot->description = "Add F-Modifier to the active/selected F-Curves";
2780 
2781  /* API callbacks */
2785 
2786  /* Flags */
2788 
2789  /* Id-props */
2790  prop = RNA_def_enum(ot->srna, "type", rna_enum_fmodifier_type_items, 0, "Type", "");
2793  ot->prop = prop;
2794 
2796  ot->srna, "only_active", 1, "Only Active", "Only add F-Modifier to active F-Curve");
2797 }
2798 
2801 /* -------------------------------------------------------------------- */
2806 {
2807  bAnimContext ac;
2808  bAnimListElem *ale;
2809  bool ok = false;
2810 
2811  /* Get editor data. */
2812  if (ANIM_animdata_get_context(C, &ac) == 0) {
2813  return OPERATOR_CANCELLED;
2814  }
2815 
2816  /* Clear buffer first. */
2818 
2819  /* Get the active F-Curve. */
2820  ale = get_active_fcurve_channel(&ac);
2821 
2822  /* If this exists, call the copy F-Modifiers API function. */
2823  if (ale && ale->data) {
2824  FCurve *fcu = (FCurve *)ale->data;
2825 
2826  /* TODO: When 'active' vs 'all' boolean is added, change last param! (Joshua Leung 2010) */
2827  ok = ANIM_fmodifiers_copy_to_buf(&fcu->modifiers, 0);
2828 
2829  /* Free temp data now. */
2830  MEM_freeN(ale);
2831  }
2832 
2833  /* Successful or not? */
2834  if (ok == 0) {
2835  BKE_report(op->reports, RPT_ERROR, "No F-Modifiers available to be copied");
2836  return OPERATOR_CANCELLED;
2837  }
2838  return OPERATOR_FINISHED;
2839 }
2840 
2842 {
2843  /* Identifiers */
2844  ot->name = "Copy F-Modifiers";
2845  ot->idname = "GRAPH_OT_fmodifier_copy";
2846  ot->description = "Copy the F-Modifier(s) of the active F-Curve";
2847 
2848  /* API callbacks */
2851 
2852  /* Flags */
2854 
2855  /* Id-props */
2856 #if 0
2858  "all",
2859  1,
2860  "All F-Modifiers",
2861  "Copy all the F-Modifiers, instead of just the active one");
2862 #endif
2863 }
2864 
2867 /* -------------------------------------------------------------------- */
2872 {
2873  bAnimContext ac;
2874 
2875  ListBase anim_data = {NULL, NULL};
2876  bAnimListElem *ale;
2877  int filter;
2878 
2879  const bool replace = RNA_boolean_get(op->ptr, "replace");
2880  bool ok = false;
2881 
2882  /* Get editor data. */
2883  if (ANIM_animdata_get_context(C, &ac) == 0) {
2884  return OPERATOR_CANCELLED;
2885  }
2886 
2887  /* Filter data. */
2888  if (RNA_boolean_get(op->ptr, "only_active")) {
2889  /* This should be the default (for buttons) - Just paste to the active FCurve. */
2892  }
2893  else {
2894  /* This is only if the operator gets called from a hotkey or search -
2895  * Paste to all visible curves. */
2898  }
2899 
2900  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2901 
2902  /* Paste modifiers. */
2903  for (ale = anim_data.first; ale; ale = ale->next) {
2904  FCurve *fcu = (FCurve *)ale->data;
2905  int tot;
2906 
2907  tot = ANIM_fmodifiers_paste_from_buf(&fcu->modifiers, replace, fcu);
2908 
2909  if (tot) {
2910  ale->update |= ANIM_UPDATE_DEPS;
2911  ok = true;
2912  }
2913  }
2914 
2915  if (ok) {
2916  ANIM_animdata_update(&ac, &anim_data);
2917  }
2918  ANIM_animdata_freelist(&anim_data);
2919 
2920  /* Successful or not? */
2921  if (ok) {
2922  /* Set notifier that keyframes have changed. */
2924 
2925  return OPERATOR_FINISHED;
2926  }
2927 
2928  BKE_report(op->reports, RPT_ERROR, "No F-Modifiers to paste");
2929  return OPERATOR_CANCELLED;
2930 }
2931 
2933 {
2934  /* Identifiers */
2935  ot->name = "Paste F-Modifiers";
2936  ot->idname = "GRAPH_OT_fmodifier_paste";
2937  ot->description = "Add copied F-Modifiers to the selected F-Curves";
2938 
2939  /* API callbacks */
2942 
2943  /* Flags */
2945 
2946  /* Properties */
2948  ot->srna, "only_active", false, "Only Active", "Only paste F-Modifiers on active F-Curve");
2950  ot->srna,
2951  "replace",
2952  false,
2953  "Replace Existing",
2954  "Replace existing F-Modifiers, instead of just appending to the end of the existing list");
2955 }
2956 
2959 /* ************************************************************************** */
2960 /* Drivers */
2961 
2962 /* -------------------------------------------------------------------- */
2967 {
2968  bool ok = false;
2969 
2970  PointerRNA ptr = CTX_data_pointer_get_type(C, "active_editable_fcurve", &RNA_FCurve);
2971 
2972  /* If this exists, call the copy driver vars API function. */
2973  FCurve *fcu = ptr.data;
2974 
2975  if (fcu) {
2976  ok = ANIM_driver_vars_copy(op->reports, fcu);
2977  }
2978 
2979  /* Successful or not? */
2980  if (ok) {
2981  return OPERATOR_FINISHED;
2982  }
2983  return OPERATOR_CANCELLED;
2984 }
2985 
2987 {
2988  /* Identifiers */
2989  ot->name = "Copy Driver Variables";
2990  ot->idname = "GRAPH_OT_driver_variables_copy";
2991  ot->description = "Copy the driver variables of the active driver";
2992 
2993  /* API callbacks */
2996 
2997  /* Flags */
2999 }
3000 
3003 /* -------------------------------------------------------------------- */
3008 {
3009  const bool replace = RNA_boolean_get(op->ptr, "replace");
3010  bool ok = false;
3011 
3012  PointerRNA ptr = CTX_data_pointer_get_type(C, "active_editable_fcurve", &RNA_FCurve);
3013 
3014  /* If this exists, call the paste driver vars API function. */
3015  FCurve *fcu = ptr.data;
3016 
3017  if (fcu) {
3018  ok = ANIM_driver_vars_paste(op->reports, fcu, replace);
3019  }
3020 
3021  /* Successful or not? */
3022  if (ok) {
3023  /* Rebuild depsgraph, now that there are extra deps here. */
3025 
3026  /* Set notifier that keyframes have changed. */
3028 
3029  return OPERATOR_FINISHED;
3030  }
3031  return OPERATOR_CANCELLED;
3032 }
3033 
3035 {
3036  /* Identifiers */
3037  ot->name = "Paste Driver Variables";
3038  ot->idname = "GRAPH_OT_driver_variables_paste";
3039  ot->description = "Add copied driver variables to the active driver";
3040 
3041  /* API callbacks */
3044 
3045  /* Flags */
3047 
3048  /* Properties */
3050  "replace",
3051  false,
3052  "Replace Existing",
3053  "Replace existing driver variables, instead of just appending to the end of the "
3054  "existing list");
3055 }
3056 
3059 /* -------------------------------------------------------------------- */
3064 {
3065  bAnimContext ac;
3066  ListBase anim_data = {NULL, NULL};
3067  bAnimListElem *ale;
3068  int filter;
3069  bool ok = false;
3070  uint deleted = 0;
3071 
3072  /* Get editor data. */
3073  if (ANIM_animdata_get_context(C, &ac) == 0) {
3074  return OPERATOR_CANCELLED;
3075  }
3076 
3077  /* NOTE: We might need a scene update to evaluate the driver flags. */
3078 
3079  /* Filter data. */
3082  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
3083 
3084  /* Find invalid drivers. */
3085  for (ale = anim_data.first; ale; ale = ale->next) {
3086  FCurve *fcu = (FCurve *)ale->data;
3087  if (ELEM(NULL, fcu, fcu->driver)) {
3088  continue;
3089  }
3090  if (!(fcu->driver->flag & DRIVER_FLAG_INVALID)) {
3091  continue;
3092  }
3093 
3094  ok |= ANIM_remove_driver(op->reports, ale->id, fcu->rna_path, fcu->array_index, 0);
3095  if (!ok) {
3096  break;
3097  }
3098  deleted += 1;
3099  }
3100 
3101  /* Cleanup. */
3102  ANIM_animdata_freelist(&anim_data);
3103 
3104  if (deleted > 0) {
3105  /* Notify the world of any changes. */
3108  WM_reportf(RPT_INFO, "Deleted %u drivers", deleted);
3109  }
3110  else {
3111  WM_report(RPT_INFO, "No drivers deleted");
3112  }
3113 
3114  /* Successful or not? */
3115  if (!ok) {
3116  return OPERATOR_CANCELLED;
3117  }
3118 
3119  return OPERATOR_FINISHED;
3120 }
3121 
3123 {
3124  bAnimContext ac;
3125  ScrArea *area = CTX_wm_area(C);
3126 
3127  /* Firstly, check if in Graph Editor. */
3128  if ((area == NULL) || (area->spacetype != SPACE_GRAPH)) {
3129  return false;
3130  }
3131 
3132  /* Try to init Anim-Context stuff ourselves and check. */
3133  return ANIM_animdata_get_context(C, &ac) != 0;
3134 }
3135 
3137 {
3138  /* Identifiers */
3139  ot->name = "Delete Invalid Drivers";
3140  ot->idname = "GRAPH_OT_driver_delete_invalid";
3141  ot->description = "Delete all visible drivers considered invalid";
3142 
3143  /* API callbacks */
3146 
3147  /* Flags */
3149 }
3150 
typedef float(TangentPoint)[2]
void BKE_animsys_free_nla_keyframing_context_cache(struct ListBase *cache)
Definition: anim_sys.c:3866
AnimationEvalContext BKE_animsys_eval_context_construct(struct Depsgraph *depsgraph, float eval_time)
Definition: anim_sys.c:761
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
Definition: context.c:473
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
void BKE_fcurve_keyframe_move_value_with_handles(struct BezTriple *keyframe, float new_value)
Definition: fcurve.c:891
float evaluate_fcurve_only_curve(struct FCurve *fcu, float evaltime)
Definition: fcurve.c:2142
bool BKE_fcurve_is_empty(struct FCurve *fcu)
Definition: fcurve.c:2198
bool BKE_fcurve_delete_keys_selected(struct FCurve *fcu)
Definition: fcurve.c:1690
void fcurve_samples_to_keyframes(struct FCurve *fcu, int start, int end)
Definition: fcurve.c:1084
const FModifierTypeInfo * get_fmodifier_typeinfo(int type)
Definition: fmodifier.c:1052
void fcurve_store_samples(struct FCurve *fcu, void *data, int start, int end, FcuSampleFunc sample_cb)
Definition: fcurve.c:1037
void set_active_fmodifier(ListBase *modifiers, struct FModifier *fcm)
Definition: fmodifier.c:1266
bool BKE_fcurve_is_keyframable(struct FCurve *fcu)
Definition: fcurve.c:968
bool remove_fmodifier(ListBase *modifiers, struct FModifier *fcm)
Definition: fmodifier.c:1190
void BKE_fcurve_handles_recalc(struct FCurve *fcu)
Definition: fcurve.c:1303
struct FModifier * add_fmodifier(ListBase *modifiers, int type, struct FCurve *owner_fcu)
Definition: fmodifier.c:1087
bool list_has_suitable_fmodifier(ListBase *modifiers, int mtype, short acttype)
Definition: fmodifier.c:1286
float fcurve_samplingcb_evalcurve(struct FCurve *fcu, void *data, float evaltime)
@ NLATIME_CONVERT_UNMAP
Definition: BKE_nla.h:357
float BKE_nla_tweakedit_remap(struct AnimData *adt, float cframe, short mode)
Definition: nla.c:642
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
#define BLI_assert(a)
Definition: BLI_assert.h:46
bool BLI_is_file(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: storage.c:402
void BLI_kdtree_nd_() free(KDTree *tree)
Definition: kdtree_impl.h:102
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:273
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int round_fl_to_int(float a)
MINLINE int min_ii(int a, int b)
#define M_PI
Definition: BLI_math_base.h:20
void eul_to_mat3(float mat[3][3], const float eul[3])
void mat3_normalized_to_compatible_eul(float eul[3], const float old[3], float mat[3][3])
#define FILE_MAX
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:42
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED(x)
#define ELEM(...)
#define STREQ(a, b)
#define BLT_I18NCONTEXT_ID_ACTION
#define TIP_(msgid)
void DEG_relations_tag_update(struct Main *bmain)
eInsertKeyFlags
@ FMODIFIER_TYPE_CYCLES
@ FMODIFIER_NUM_TYPES
@ DRIVER_FLAG_INVALID
@ FCURVE_PROTECTED
@ FCURVE_EXTRAPOLATE_CONSTANT
@ FCURVE_EXTRAPOLATE_LINEAR
#define PSFRA
#define FPS
#define PEFRA
@ FILE_SORT_DEFAULT
@ FILE_SPECIAL
@ FILE_TYPE_MOVIE
@ FILE_TYPE_SOUND
@ FILE_TYPE_FOLDER
@ SPACE_GRAPH
@ SIPO_MODE_DRIVERS
@ FILE_DEFAULTDISPLAY
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
#define ANIM_UPDATE_DEFAULT_NOHANDLES
Definition: ED_anim_api.h:275
#define ANIM_UPDATE_DEFAULT
Definition: ED_anim_api.h:274
@ ANIM_UPDATE_DEPS
Definition: ED_anim_api.h:268
@ ANIM_UPDATE_HANDLES
Definition: ED_anim_api.h:270
@ ANIMFILTER_ACTIVE
Definition: ED_anim_api.h:303
@ 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_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
@ ANIM_UNITCONV_RESTORE
Definition: ED_anim_api.h:932
@ MIRROR_KEYS_TIME
eKeyMergeMode
@ KEYFRAME_PASTE_MERGE_MIX
eKeyPasteOffset
@ KEYFRAME_PASTE_OFFSET_CFRA_START
@ BEZT_OK_SELECTED
short(* KeyframeEditFunc)(KeyframeEditData *ked, struct BezTriple *bezt)
@ SNAP_KEYS_TIME
@ SELECT_SUBTRACT
eKeyPasteError
@ KEYFRAME_PASTE_NOTHING_TO_PASTE
@ KEYFRAME_PASTE_OK
@ KEYFRAME_PASTE_NOWHERE_TO_PASTE
void ED_region_tag_redraw(struct ARegion *region)
Definition: area.c:655
@ TFM_TRANSLATION
Definition: ED_transform.h:30
_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
_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 type
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(const struct View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
@ WM_FILESEL_SHOW_PROPS
Definition: WM_api.h:758
@ WM_FILESEL_FILEPATH
Definition: WM_api.h:755
@ FILE_OPENFILE
Definition: WM_api.h:764
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define NC_ANIMATION
Definition: WM_types.h:338
#define NC_SCENE
Definition: WM_types.h:328
#define NA_ADDED
Definition: WM_types.h:525
#define NA_EDITED
Definition: WM_types.h:523
#define ND_KEYFRAME_PROP
Definition: WM_types.h:443
#define ND_FRAME
Definition: WM_types.h:382
#define NA_REMOVED
Definition: WM_types.h:526
#define ND_KEYFRAME
Definition: WM_types.h:442
void ANIM_fcurve_delete_from_animdata(bAnimContext *ac, AnimData *adt, FCurve *fcu)
void ANIM_animdata_freelist(ListBase *anim_data)
Definition: anim_deps.c:397
void ANIM_animdata_update(bAnimContext *ac, ListBase *anim_data)
Definition: anim_deps.c:302
AnimData * ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale)
Definition: anim_draw.c:216
void ANIM_nla_mapping_apply_fcurve(AnimData *adt, FCurve *fcu, bool restore, bool only_keys)
Definition: anim_draw.c:291
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
TimeMarker * ED_markers_get_first_selected(ListBase *markers)
Definition: anim_markers.c:344
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
float evaltime
Definition: bpy_driver.c:161
Scene scene
bool ANIM_remove_driver(ReportList *UNUSED(reports), ID *id, const char rna_path[], int array_index, short UNUSED(flag))
Definition: drivers.c:517
bool ANIM_driver_vars_copy(ReportList *reports, FCurve *fcu)
Definition: drivers.c:715
bool ANIM_driver_vars_paste(ReportList *reports, FCurve *fcu, bool replace)
Definition: drivers.c:737
bool ANIM_fmodifiers_paste_from_buf(ListBase *modifiers, bool replace, FCurve *curve)
Definition: fmodifier_ui.c:989
void ANIM_fmodifiers_copybuf_free(void)
Definition: fmodifier_ui.c:954
bool ANIM_fmodifiers_copy_to_buf(ListBase *modifiers, bool active)
Definition: fmodifier_ui.c:960
static int graph_fmodifier_paste_exec(bContext *C, wmOperator *op)
Definition: graph_edit.c:2871
static const EnumPropertyItem prop_graphkeys_insertkey_types[]
Definition: graph_edit.c:72
void GRAPH_OT_delete(wmOperatorType *ot)
Definition: graph_edit.c:768
static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode)
Definition: graph_edit.c:97
static int graphkeys_sample_exec(bContext *C, wmOperator *UNUSED(op))
Definition: graph_edit.c:1297
void GRAPH_OT_click_insert(wmOperatorType *ot)
Definition: graph_edit.c:402
static int graphkeys_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
Definition: graph_edit.c:663
struct tEulerFilter tEulerFilter
void GRAPH_OT_fmodifier_paste(wmOperatorType *ot)
Definition: graph_edit.c:2932
void GRAPH_OT_smooth(wmOperatorType *ot)
Definition: graph_edit.c:2658
static const EnumPropertyItem prop_graphkeys_equalize_handles_sides[]
Definition: graph_edit.c:2362
static void clean_graph_keys(bAnimContext *ac, float thresh, bool clean_chan)
Definition: graph_edit.c:791
static void mirror_graph_keys(bAnimContext *ac, short mode)
Definition: graph_edit.c:2490
static KeyframeEditData sum_selected_keyframes(bAnimContext *ac)
Definition: graph_edit.c:2058
void GRAPH_OT_equalize_handles(wmOperatorType *ot)
Definition: graph_edit.c:2412
static int graphkeys_easing_exec(bContext *C, wmOperator *op)
Definition: graph_edit.c:1578
static int graphkeys_expo_exec(bContext *C, wmOperator *op)
Definition: graph_edit.c:1426
static bool euler_filter_multi_channel(tEulerFilter *euf, ReportList *reports)
Definition: graph_edit.c:1796
static bool graph_driver_delete_invalid_poll(bContext *C)
Definition: graph_edit.c:3122
static int graphkeys_insertkey_exec(bContext *C, wmOperator *op)
Definition: graph_edit.c:238
void GRAPH_OT_snap_cursor_value(wmOperatorType *ot)
Definition: graph_edit.c:2184
static void euler_filter_perform_filter(ListBase *eulers, ReportList *reports, int *r_curves_filtered, int *r_curves_seen)
Definition: graph_edit.c:1910
static int graphkeys_click_insert_exec(bContext *C, wmOperator *op)
Definition: graph_edit.c:285
static void sethandles_graph_keys(bAnimContext *ac, short mode)
Definition: graph_edit.c:1628
static bool euler_filter_single_channel(FCurve *fcu)
Definition: graph_edit.c:1871
static int graphkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op))
Definition: graph_edit.c:2104
static int graphkeys_mirror_exec(bContext *C, wmOperator *op)
Definition: graph_edit.c:2574
static bool keyframe_time_differs(BezTriple *keyframes[3])
Definition: graph_edit.c:1730
void GRAPH_OT_mirror(wmOperatorType *ot)
Definition: graph_edit.c:2596
void GRAPH_OT_sample(wmOperatorType *ot)
Definition: graph_edit.c:1315
void GRAPH_OT_bake(wmOperatorType *ot)
Definition: graph_edit.c:929
static void snap_graph_keys(bAnimContext *ac, short mode)
Definition: graph_edit.c:2242
void GRAPH_OT_fmodifier_copy(wmOperatorType *ot)
Definition: graph_edit.c:2841
static const EnumPropertyItem prop_graphkeys_mirror_types[]
Definition: graph_edit.c:2459
void GRAPH_OT_handle_type(wmOperatorType *ot)
Definition: graph_edit.c:1685
static int graphkeys_delete_exec(bContext *C, wmOperator *UNUSED(op))
Definition: graph_edit.c:748
static void equalize_graph_keys(bAnimContext *ac, int mode, float handle_length, bool flatten)
Definition: graph_edit.c:2372
static void sample_graph_keys(bAnimContext *ac)
Definition: graph_edit.c:1273
void GRAPH_OT_frame_jump(wmOperatorType *ot)
Definition: graph_edit.c:2144
void GRAPH_OT_driver_variables_copy(wmOperatorType *ot)
Definition: graph_edit.c:2986
void GRAPH_OT_extrapolation_type(wmOperatorType *ot)
Definition: graph_edit.c:1448
static bool delete_graph_keys(bAnimContext *ac)
Definition: graph_edit.c:707
#define MAKE_CYCLIC_EXPO
Definition: graph_edit.c:1340
static int graphkeys_ipo_exec(bContext *C, wmOperator *op)
Definition: graph_edit.c:1502
void GRAPH_OT_unbake(wmOperatorType *ot)
Definition: graph_edit.c:1006
static void unbake_graph_curves(bAnimContext *ac, int start, int end)
Definition: graph_edit.c:956
void GRAPH_OT_driver_variables_paste(wmOperatorType *ot)
Definition: graph_edit.c:3034
static int graphkeys_snap_cursor_value_exec(bContext *C, wmOperator *UNUSED(op))
Definition: graph_edit.c:2160
void GRAPH_OT_interpolation_type(wmOperatorType *ot)
Definition: graph_edit.c:1524
static int graphkeys_bake_exec(bContext *C, wmOperator *UNUSED(op))
Definition: graph_edit.c:902
static int graph_driver_vars_copy_exec(bContext *C, wmOperator *op)
Definition: graph_edit.c:2966
static void setexpo_graph_keys(bAnimContext *ac, short mode)
Definition: graph_edit.c:1370
eGraphKeys_InsertKey_Types
Definition: graph_edit.c:64
@ GRAPHKEYS_INSERTKEY_CURSOR
Definition: graph_edit.c:67
@ GRAPHKEYS_INSERTKEY_ACTIVE
Definition: graph_edit.c:68
@ GRAPHKEYS_INSERTKEY_ALL
Definition: graph_edit.c:65
@ GRAPHKEYS_INSERTKEY_SEL
Definition: graph_edit.c:66
static int graphkeys_equalize_handles_exec(bContext *C, wmOperator *op)
Definition: graph_edit.c:2390
static const EnumPropertyItem prop_graphkeys_expo_types[]
Definition: graph_edit.c:1344
static int graph_fmodifier_copy_exec(bContext *C, wmOperator *op)
Definition: graph_edit.c:2805
static int graph_driver_delete_invalid_exec(bContext *C, wmOperator *op)
Definition: graph_edit.c:3063
static int graphkeys_click_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: graph_edit.c:373
void GRAPH_OT_easing_type(wmOperatorType *ot)
Definition: graph_edit.c:1600
static int graph_driver_vars_paste_exec(bContext *C, wmOperator *op)
Definition: graph_edit.c:3007
static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op)
Definition: graph_edit.c:1941
static int graph_fmodifier_add_exec(bContext *C, wmOperator *op)
Definition: graph_edit.c:2717
static int graphkeys_smooth_exec(bContext *C, wmOperator *UNUSED(op))
Definition: graph_edit.c:2621
void GRAPH_OT_copy(wmOperatorType *ot)
Definition: graph_edit.c:527
static int graphkeys_paste_exec(bContext *C, wmOperator *op)
Definition: graph_edit.c:542
static char * graphkeys_paste_description(bContext *UNUSED(C), wmOperatorType *UNUSED(op), PointerRNA *ptr)
Definition: graph_edit.c:578
static void setipo_graph_keys(bAnimContext *ac, short mode)
Definition: graph_edit.c:1474
void GRAPH_OT_driver_delete_invalid(wmOperatorType *ot)
Definition: graph_edit.c:3136
static eKeyPasteError paste_graph_keys(bAnimContext *ac, const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode, bool flip)
Definition: graph_edit.c:476
void GRAPH_OT_keyframe_insert(wmOperatorType *ot)
Definition: graph_edit.c:260
void GRAPH_OT_sound_bake(wmOperatorType *ot)
Definition: graph_edit.c:1163
static int graphkeys_copy_exec(bContext *C, wmOperator *op)
Definition: graph_edit.c:508
void GRAPH_OT_duplicate(wmOperatorType *ot)
Definition: graph_edit.c:683
static void seteasing_graph_keys(bAnimContext *ac, short mode)
Definition: graph_edit.c:1552
static int graphkeys_handletype_exec(bContext *C, wmOperator *op)
Definition: graph_edit.c:1663
static int graphkeys_sound_bake_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: graph_edit.c:1151
void GRAPH_OT_euler_filter(wmOperatorType *ot)
Definition: graph_edit.c:2021
static bool graphkeys_framejump_poll(bContext *C)
Definition: graph_edit.c:2048
static int graphkeys_sound_bake_exec(bContext *UNUSED(C), wmOperator *op)
Definition: graph_edit.c:1142
static short copy_graph_keys(bAnimContext *ac)
Definition: graph_edit.c:448
void GRAPH_OT_clean(wmOperatorType *ot)
Definition: graph_edit.c:838
static int graphkeys_clean_exec(bContext *C, wmOperator *op)
Definition: graph_edit.c:815
static int graphkeys_snap_exec(bContext *C, wmOperator *op)
Definition: graph_edit.c:2314
#define CLEAR_CYCLIC_EXPO
Definition: graph_edit.c:1341
void GRAPH_OT_snap(wmOperatorType *ot)
Definition: graph_edit.c:2336
static const EnumPropertyItem * graph_fmodifier_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
Definition: graph_edit.c:2682
static int graphkeys_unbake_exec(bContext *C, wmOperator *UNUSED(op))
Definition: graph_edit.c:981
static bool duplicate_graph_keys(bAnimContext *ac)
Definition: graph_edit.c:636
static void bake_graph_curves(bAnimContext *ac, int start, int end)
Definition: graph_edit.c:868
static ListBase euler_filter_group_channels(const ListBase *anim_data, ReportList *reports, int *r_num_groups)
Definition: graph_edit.c:1739
void GRAPH_OT_fmodifier_add(wmOperatorType *ot)
Definition: graph_edit.c:2772
static const EnumPropertyItem prop_graphkeys_snap_types[]
Definition: graph_edit.c:2206
void GRAPH_OT_paste(wmOperatorType *ot)
Definition: graph_edit.c:591
@ GRAPHKEYS_MIRROR_XAXIS
Definition: graph_intern.h:163
@ GRAPHKEYS_MIRROR_CFRA
Definition: graph_intern.h:161
@ GRAPHKEYS_MIRROR_VALUE
Definition: graph_intern.h:165
@ GRAPHKEYS_MIRROR_YAXIS
Definition: graph_intern.h:162
@ GRAPHKEYS_MIRROR_MARKER
Definition: graph_intern.h:164
bool graphop_active_fcurve_poll(struct bContext *C)
Definition: graph_utils.c:219
@ GRAPHKEYS_SNAP_NEAREST_MARKER
Definition: graph_intern.h:143
@ GRAPHKEYS_SNAP_VALUE
Definition: graph_intern.h:145
@ GRAPHKEYS_SNAP_NEAREST_SECOND
Definition: graph_intern.h:142
@ GRAPHKEYS_SNAP_HORIZONTAL
Definition: graph_intern.h:144
@ GRAPHKEYS_SNAP_CFRA
Definition: graph_intern.h:140
@ GRAPHKEYS_SNAP_NEAREST_FRAME
Definition: graph_intern.h:141
bool graphop_active_editable_fcurve_ctx_poll(struct bContext *C)
Definition: graph_utils.c:262
@ GRAPHKEYS_EQUALIZE_RIGHT
Definition: graph_intern.h:153
@ GRAPHKEYS_EQUALIZE_BOTH
Definition: graph_intern.h:154
@ GRAPHKEYS_EQUALIZE_LEFT
Definition: graph_intern.h:152
struct bAnimListElem * get_active_fcurve_channel(struct bAnimContext *ac)
Definition: graph_utils.c:81
bool graphop_selected_fcurve_poll(struct bContext *C)
Definition: graph_utils.c:269
bool graphop_visible_keyframes_poll(struct bContext *C)
Definition: graph_utils.c:111
bool graphop_editable_keyframes_poll(struct bContext *C)
Definition: graph_utils.c:163
void deselect_graph_keys(struct bAnimContext *ac, bool test, short sel, bool do_channels)
Definition: graph_select.c:335
DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
KeyframeEditFunc ANIM_editkeyframes_mirror(short mode)
KeyframeEditFunc ANIM_editkeyframes_easing(short mode)
KeyframeEditFunc ANIM_editkeyframes_ipo(short mode)
void ANIM_fcurve_equalize_keyframes_loop(FCurve *fcu, const eEditKeyframes_Equalize mode, const float handle_length, const bool flatten)
short ANIM_fcurve_keyframes_loop(KeyframeEditData *ked, FCurve *fcu, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
KeyframeEditFunc ANIM_editkeyframes_ok(short mode)
KeyframeEditFunc ANIM_editkeyframes_snap(short mode)
short bezt_calc_average(KeyframeEditData *ked, BezTriple *bezt)
KeyframeEditFunc ANIM_editkeyframes_handles(short mode)
const EnumPropertyItem rna_enum_keyframe_paste_offset_items[]
eKeyPasteError paste_animedit_keys(bAnimContext *ac, ListBase *anim_data, const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode, bool flip)
short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data)
const EnumPropertyItem rna_enum_keyframe_paste_merge_items[]
void sample_fcurve(FCurve *fcu)
void smooth_fcurve(FCurve *fcu)
void ANIM_fcurves_copybuf_free(void)
bool duplicate_fcurve_keys(FCurve *fcu)
void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, bool cleardefault)
int insert_vert_fcurve(FCurve *fcu, float x, float y, eBezTriple_KeyframeType keyframe_type, eInsertKeyFlags flag)
Main Key-framing API call.
Definition: keyframing.c:545
eInsertKeyFlags ANIM_get_keyframing_flags(Scene *scene, const bool use_autokey_mode)
Definition: keyframing.c:82
int insert_keyframe(Main *bmain, ReportList *reports, ID *id, bAction *act, const char group[], const char rna_path[], int array_index, const AnimationEvalContext *anim_eval_context, eBezTriple_KeyframeType keytype, ListBase *nla_cache, eInsertKeyFlags flag)
Definition: keyframing.c:1476
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
ccl_device_inline float2 fabs(const float2 &a)
Definition: math_float2.h:222
#define G(x, y, z)
double sign(double arg)
Definition: utility.h:250
static void area(int d1, int d2, int e1, int e2, float weights[2])
T length(const vec_base< T, Size > &a)
SymEdge< T > * prev(const SymEdge< T > *se)
Definition: delaunay_2d.cc:105
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
Definition: rna_access.c:5116
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4957
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
Definition: rna_access.c:4968
int RNA_enum_from_value(const EnumPropertyItem *item, const int value)
Definition: rna_access.c:1736
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
const EnumPropertyItem rna_enum_beztriple_interpolation_mode_items[]
Definition: rna_curve.c:68
const EnumPropertyItem rna_enum_keyframe_handle_type_items[]
Definition: rna_curve.c:39
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
Definition: rna_define.c:3836
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_enum_item_end(EnumPropertyItem **items, int *totitem)
Definition: rna_define.c:4487
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
Definition: rna_define.c:4436
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
Definition: rna_define.c:2848
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
Definition: rna_define.c:3830
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
const EnumPropertyItem rna_enum_fmodifier_type_items[]
Definition: rna_fcurve.c:31
const EnumPropertyItem rna_enum_beztriple_interpolation_easing_items[]
Definition: rna_fcurve.c:110
float vec[3][3]
bActionGroup * grp
char * rna_path
FPoint * fpt
ChannelDriver * driver
BezTriple * bezt
short extend
int array_index
short flag
unsigned int totvert
ListBase modifiers
struct FModifier * next
Definition: DNA_ID.h:368
char name[66]
Definition: DNA_ID.h:378
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
void * data
Definition: RNA_types.h:38
struct ToolSettings * toolsettings
struct RenderData r
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 ReportList * reports
Definition: ED_anim_api.h:95
struct Main * bmain
Definition: ED_anim_api.h:82
struct SpaceLink * sl
Definition: ED_anim_api.h:74
struct Depsgraph * depsgraph
Definition: ED_anim_api.h:88
struct bAnimListElem * next
Definition: ED_anim_api.h:127
void * key_data
Definition: ED_anim_api.h:146
struct AnimData * adt
Definition: ED_anim_api.h:162
struct ID * id
Definition: ED_anim_api.h:160
int ymin
Definition: DNA_vec_types.h:64
int xmin
Definition: DNA_vec_types.h:63
const char * rna_path
Definition: graph_edit.c:1727
FCurve * fcurves[3]
Definition: graph_edit.c:1725
struct tEulerFilter * prev
Definition: graph_edit.c:1720
struct tEulerFilter * next
Definition: graph_edit.c:1720
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
const char * idname
Definition: WM_types.h:890
char *(* get_description)(struct bContext *C, struct wmOperatorType *, struct PointerRNA *)
Definition: WM_types.h:966
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
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
struct ReportList * reports
struct PointerRNA * ptr
const EnumPropertyItem rna_enum_transform_mode_types[]
void WM_report(eReportType type, const char *message)
void WM_reportf(eReportType type, const char *format,...)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition: wm_files.c:3480
wmOperatorType * ot
Definition: wm_files.c:3479
void WM_operator_properties_confirm_or_exec(wmOperatorType *ot)
void WM_operator_properties_filesel(wmOperatorType *ot, const int filter, const short type, const eFileSel_Action action, const eFileSel_Flag flag, const short display, const short sort)
int WM_operator_confirm(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
int WM_operator_confirm_or_exec(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
int WM_operator_filesel(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))