Blender  V3.3
action_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 
8 #include <float.h>
9 #include <math.h>
10 #include <stdlib.h>
11 #include <string.h>
12 
13 #include "BLI_blenlib.h"
14 #include "BLI_math.h"
15 #include "BLI_utildefines.h"
16 
17 #include "BLT_translation.h"
18 
19 #include "DNA_anim_types.h"
20 #include "DNA_gpencil_types.h"
21 #include "DNA_key_types.h"
22 #include "DNA_mask_types.h"
23 #include "DNA_object_types.h"
24 #include "DNA_scene_types.h"
25 
26 #include "RNA_access.h"
27 #include "RNA_define.h"
28 #include "RNA_enum_types.h"
29 
30 #include "BKE_action.h"
31 #include "BKE_animsys.h"
32 #include "BKE_context.h"
33 #include "BKE_fcurve.h"
34 #include "BKE_global.h"
35 #include "BKE_gpencil.h"
36 #include "BKE_key.h"
37 #include "BKE_nla.h"
38 #include "BKE_report.h"
39 
40 #include "UI_view2d.h"
41 
42 #include "ED_anim_api.h"
43 #include "ED_gpencil.h"
44 #include "ED_keyframes_edit.h"
45 #include "ED_keyframing.h"
46 #include "ED_markers.h"
47 #include "ED_mask.h"
48 #include "ED_screen.h"
49 
50 #include "WM_api.h"
51 #include "WM_types.h"
52 
53 #include "UI_interface.h"
54 
55 #include "action_intern.h"
56 
57 /* ************************************************************************** */
58 /* POSE MARKERS STUFF */
59 
60 /* *************************** Localize Markers ***************************** */
61 
62 /* ensure that there is:
63  * 1) an active action editor
64  * 2) that the mode will have an active action available
65  * 3) that the set of markers being shown are the scene markers, not the list we're merging
66  * 4) that there are some selected markers
67  */
69 {
71 
72  /* 1) */
73  if (sact == NULL) {
74  return 0;
75  }
76 
77  /* 2) */
78  if (ELEM(sact->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY) == 0) {
79  return 0;
80  }
81  if (sact->action == NULL) {
82  return 0;
83  }
84 
85  /* 3) */
86  if (sact->flag & SACTION_POSEMARKERS_SHOW) {
87  return 0;
88  }
89 
90  /* 4) */
92 }
93 
95 {
97 
99  bAction *act = (sact) ? sact->action : NULL;
100 
101  TimeMarker *marker, *markern = NULL;
102 
103  /* sanity checks */
104  if (ELEM(NULL, markers, act)) {
105  return OPERATOR_CANCELLED;
106  }
107 
108  /* migrate markers */
109  for (marker = markers->first; marker; marker = markern) {
110  markern = marker->next;
111 
112  /* move if marker is selected */
113  if (marker->flag & SELECT) {
114  BLI_remlink(markers, marker);
115  BLI_addtail(&act->markers, marker);
116  }
117  }
118 
119  /* Now enable the "show posemarkers only" setting,
120  * so that we can see that something did happen */
122 
123  /* notifiers - both sets, as this change affects both */
126 
127  return OPERATOR_FINISHED;
128 }
129 
131 {
132  /* identifiers */
133  ot->name = "Make Markers Local";
134  ot->idname = "ACTION_OT_markers_make_local";
135  ot->description = "Move selected scene markers to the active Action as local 'pose' markers";
136 
137  /* callbacks */
140 
141  /* flags */
143 }
144 
145 /* ************************************************************************** */
146 /* KEYFRAME-RANGE STUFF */
147 
148 /* *************************** Calculate Range ************************** */
149 
150 /* Get the min/max keyframes. */
151 static bool get_keyframe_extents(bAnimContext *ac, float *min, float *max, const short onlySel)
152 {
153  ListBase anim_data = {NULL, NULL};
154  bAnimListElem *ale;
155  int filter;
156  bool found = false;
157 
158  /* get data to filter, from Action or Dopesheet */
159  /* XXX: what is sel doing here?!
160  * Commented it, was breaking things (eg. the "auto preview range" tool). */
161  filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_SEL */ |
163  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
164 
165  /* set large values to try to override */
166  *min = 999999999.0f;
167  *max = -999999999.0f;
168 
169  /* check if any channels to set range with */
170  if (anim_data.first) {
171  /* go through channels, finding max extents */
172  for (ale = anim_data.first; ale; ale = ale->next) {
173  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
174  if (ale->datatype == ALE_GPFRAME) {
175  bGPDlayer *gpl = ale->data;
176  bGPDframe *gpf;
177 
178  /* Find gp-frame which is less than or equal to current-frame. */
179  for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
180  if (!onlySel || (gpf->flag & GP_FRAME_SELECT)) {
181  const float framenum = (float)gpf->framenum;
182  *min = min_ff(*min, framenum);
183  *max = max_ff(*max, framenum);
184  found = true;
185  }
186  }
187  }
188  else if (ale->datatype == ALE_MASKLAY) {
189  MaskLayer *masklay = ale->data;
190  MaskLayerShape *masklay_shape;
191 
192  /* Find mask layer which is less than or equal to current-frame. */
193  for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
194  masklay_shape = masklay_shape->next) {
195  const float framenum = (float)masklay_shape->frame;
196  *min = min_ff(*min, framenum);
197  *max = max_ff(*max, framenum);
198  found = true;
199  }
200  }
201  else {
202  FCurve *fcu = (FCurve *)ale->key_data;
203  float tmin, tmax;
204 
205  /* get range and apply necessary scaling before processing */
206  if (BKE_fcurve_calc_range(fcu, &tmin, &tmax, onlySel, false)) {
207 
208  if (adt) {
209  tmin = BKE_nla_tweakedit_remap(adt, tmin, NLATIME_CONVERT_MAP);
210  tmax = BKE_nla_tweakedit_remap(adt, tmax, NLATIME_CONVERT_MAP);
211  }
212 
213  /* Try to set cur using these values,
214  * if they're more extreme than previously set values. */
215  *min = min_ff(*min, tmin);
216  *max = max_ff(*max, tmax);
217  found = true;
218  }
219  }
220  }
221 
222  if (fabsf(*max - *min) < 0.001f) {
223  *min -= 0.0005f;
224  *max += 0.0005f;
225  }
226 
227  /* free memory */
228  ANIM_animdata_freelist(&anim_data);
229  }
230  else {
231  /* set default range */
232  if (ac->scene) {
233  *min = (float)ac->scene->r.sfra;
234  *max = (float)ac->scene->r.efra;
235  }
236  else {
237  *min = -5;
238  *max = 100;
239  }
240  }
241 
242  return found;
243 }
244 
245 /* ****************** Automatic Preview-Range Operator ****************** */
246 
248 {
249  bAnimContext ac;
250  Scene *scene;
251  float min, max;
252 
253  /* get editor data */
254  if (ANIM_animdata_get_context(C, &ac) == 0) {
255  return OPERATOR_CANCELLED;
256  }
257  if (ac.scene == NULL) {
258  return OPERATOR_CANCELLED;
259  }
260 
261  scene = ac.scene;
262 
263  /* set the range directly */
264  get_keyframe_extents(&ac, &min, &max, true);
266  scene->r.psfra = floorf(min);
267  scene->r.pefra = ceilf(max);
268 
269  if (scene->r.psfra == scene->r.pefra) {
270  scene->r.pefra = scene->r.psfra + 1;
271  }
272 
273  /* set notifier that things have changed */
274  /* XXX err... there's nothing for frame ranges yet, but this should do fine too */
276 
277  return OPERATOR_FINISHED;
278 }
279 
281 {
282  /* identifiers */
283  ot->name = "Set Preview Range to Selected";
284  ot->idname = "ACTION_OT_previewrange_set";
285  ot->description = "Set Preview Range based on extents of selected Keyframes";
286 
287  /* api callbacks */
290 
291  /* flags */
293 }
294 
295 /* ****************** View-All Operator ****************** */
296 
304 static bool actkeys_channels_get_selected_extents(bAnimContext *ac, float *r_min, float *r_max)
305 {
306  ListBase anim_data = {NULL, NULL};
307  bAnimListElem *ale;
308  int filter;
309 
310  /* NOTE: not bool, since we want prioritize individual channels over expanders. */
311  short found = 0;
312 
313  /* get all items - we need to do it this way */
315  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
316 
317  /* loop through all channels, finding the first one that's selected */
318  float ymax = ACHANNEL_FIRST_TOP(ac);
319 
320  for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac)) {
322 
323  /* must be selected... */
324  if (acf && acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT) &&
326  /* update best estimate */
327  *r_min = ymax - ACHANNEL_HEIGHT(ac);
328  *r_max = ymax;
329 
330  /* is this high enough priority yet? */
331  found = acf->channel_role;
332 
333  /* only stop our search when we've found an actual channel
334  * - data-block expanders get less priority so that we don't abort prematurely
335  */
336  if (found == ACHANNEL_ROLE_CHANNEL) {
337  break;
338  }
339  }
340  }
341 
342  /* free all temp data */
343  ANIM_animdata_freelist(&anim_data);
344 
345  return (found != 0);
346 }
347 
348 static int actkeys_viewall(bContext *C, const bool only_sel)
349 {
350  bAnimContext ac;
351  View2D *v2d;
352  float extra, min, max;
353  bool found;
354 
355  /* get editor data */
356  if (ANIM_animdata_get_context(C, &ac) == 0) {
357  return OPERATOR_CANCELLED;
358  }
359  v2d = &ac.region->v2d;
360 
361  /* set the horizontal range, with an extra offset so that the extreme keys will be in view */
362  found = get_keyframe_extents(&ac, &min, &max, only_sel);
363 
364  if (only_sel && (found == false)) {
365  return OPERATOR_CANCELLED;
366  }
367 
368  if (fabsf(max - min) < 1.0f) {
369  /* Exception - center the single keyfrme */
370  float xwidth = BLI_rctf_size_x(&v2d->cur);
371 
372  v2d->cur.xmin = min - xwidth / 2.0f;
373  v2d->cur.xmax = max + xwidth / 2.0f;
374  }
375  else {
376  /* Normal case - stretch the two keyframes out to fill the space, with extra spacing */
377  v2d->cur.xmin = min;
378  v2d->cur.xmax = max;
379 
380  extra = 0.125f * BLI_rctf_size_x(&v2d->cur);
381  v2d->cur.xmin -= extra;
382  v2d->cur.xmax += extra;
383  }
384 
385  /* set vertical range */
386  if (only_sel == false) {
387  /* view all -> the summary channel is usually the shows everything,
388  * and resides right at the top... */
389  v2d->cur.ymax = 0.0f;
390  v2d->cur.ymin = (float)-BLI_rcti_size_y(&v2d->mask);
391  }
392  else {
393  /* locate first selected channel (or the active one), and frame those */
394  float ymin = v2d->cur.ymin;
395  float ymax = v2d->cur.ymax;
396 
397  if (actkeys_channels_get_selected_extents(&ac, &ymin, &ymax)) {
398  /* recenter the view so that this range is in the middle */
399  float ymid = (ymax - ymin) / 2.0f + ymin;
400  float x_center;
401 
402  UI_view2d_center_get(v2d, &x_center, NULL);
403  UI_view2d_center_set(v2d, x_center, ymid);
404  }
405  }
406 
407  /* do View2D syncing */
409 
410  /* just redraw this view */
412 
413  return OPERATOR_FINISHED;
414 }
415 
416 /* ......... */
417 
419 {
420  /* whole range */
421  return actkeys_viewall(C, false);
422 }
423 
425 {
426  /* only selected */
427  return actkeys_viewall(C, true);
428 }
429 
430 /* ......... */
431 
433 {
434  /* identifiers */
435  ot->name = "Frame All";
436  ot->idname = "ACTION_OT_view_all";
437  ot->description = "Reset viewable area to show full keyframe range";
438 
439  /* api callbacks */
442 
443  /* flags */
444  ot->flag = 0;
445 }
446 
448 {
449  /* identifiers */
450  ot->name = "Frame Selected";
451  ot->idname = "ACTION_OT_view_selected";
452  ot->description = "Reset viewable area to show selected keyframes range";
453 
454  /* api callbacks */
457 
458  /* flags */
459  ot->flag = 0;
460 }
461 
462 /* ****************** View-All Operator ****************** */
463 
465 {
466  const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
467  ANIM_center_frame(C, smooth_viewtx);
468 
469  return OPERATOR_FINISHED;
470 }
471 
473 {
474  /* identifiers */
475  ot->name = "Go to Current Frame";
476  ot->idname = "ACTION_OT_view_frame";
477  ot->description = "Move the view to the current frame";
478 
479  /* api callbacks */
482 
483  /* flags */
484  ot->flag = 0;
485 }
486 
487 /* ************************************************************************** */
488 /* GENERAL STUFF */
489 
490 /* ******************** Copy/Paste Keyframes Operator ************************* */
491 /* NOTE: the backend code for this is shared with the graph editor */
492 
494 {
495  ListBase anim_data = {NULL, NULL};
496  int filter, ok = 0;
497 
498  /* clear buffer first */
500 
501  /* filter data */
504  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
505 
506  /* copy keyframes */
507  ok = copy_animedit_keys(ac, &anim_data);
508 
509  /* clean up */
510  ANIM_animdata_freelist(&anim_data);
511 
512  return ok;
513 }
514 
516  const eKeyPasteOffset offset_mode,
517  const eKeyMergeMode merge_mode,
518  bool flip)
519 {
520  ListBase anim_data = {NULL, NULL};
521  int filter;
522 
523  /* filter data
524  * - First time we try to filter more strictly, allowing only selected channels
525  * to allow copying animation between channels
526  * - Second time, we loosen things up if nothing was found the first time, allowing
527  * users to just paste keyframes back into the original curve again T31670.
528  */
531 
532  if (ANIM_animdata_filter(ac, &anim_data, filter | ANIMFILTER_SEL, ac->data, ac->datatype) == 0) {
533  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
534  }
535 
536  /* paste keyframes */
537  const eKeyPasteError ok = paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode, flip);
538 
539  /* clean up */
540  ANIM_animdata_freelist(&anim_data);
541 
542  return ok;
543 }
544 
545 /* ------------------- */
546 
548 {
549  bAnimContext ac;
550 
551  /* get editor data */
552  if (ANIM_animdata_get_context(C, &ac) == 0) {
553  return OPERATOR_CANCELLED;
554  }
555 
556  /* copy keyframes */
557  if (ac.datatype == ANIMCONT_GPENCIL) {
558  if (ED_gpencil_anim_copybuf_copy(&ac) == false) {
559  /* check if anything ended up in the buffer */
560  BKE_report(op->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer");
561  return OPERATOR_CANCELLED;
562  }
563  }
564  else if (ac.datatype == ANIMCONT_MASK) {
565  /* FIXME: support this case. */
566  BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for mask mode");
567  return OPERATOR_CANCELLED;
568  }
569  else {
570  /* Both copy function needs to be evaluated to account for mixed selection */
571  const short kf_empty = copy_action_keys(&ac);
572  const bool gpf_ok = ED_gpencil_anim_copybuf_copy(&ac);
573 
574  if (kf_empty && !gpf_ok) {
575  BKE_report(op->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer");
576  return OPERATOR_CANCELLED;
577  }
578  }
579 
580  return OPERATOR_FINISHED;
581 }
582 
584 {
585  /* identifiers */
586  ot->name = "Copy Keyframes";
587  ot->idname = "ACTION_OT_copy";
588  ot->description = "Copy selected keyframes to the copy/paste buffer";
589 
590  /* api callbacks */
593 
594  /* flags */
596 }
597 
599 {
600  bAnimContext ac;
601 
602  const eKeyPasteOffset offset_mode = RNA_enum_get(op->ptr, "offset");
603  const eKeyMergeMode merge_mode = RNA_enum_get(op->ptr, "merge");
604  const bool flipped = RNA_boolean_get(op->ptr, "flipped");
605 
606  bool gpframes_inbuf = false;
607 
608  /* get editor data */
609  if (ANIM_animdata_get_context(C, &ac) == 0) {
610  return OPERATOR_CANCELLED;
611  }
612 
613  /* ac.reports by default will be the global reports list, which won't show warnings */
614  ac.reports = op->reports;
615 
616  /* paste keyframes */
617  if (ac.datatype == ANIMCONT_GPENCIL) {
618  if (ED_gpencil_anim_copybuf_paste(&ac, offset_mode) == false) {
619  BKE_report(op->reports, RPT_ERROR, "No data in buffer to paste");
620  return OPERATOR_CANCELLED;
621  }
622  }
623  else if (ac.datatype == ANIMCONT_MASK) {
624  /* FIXME: support this case. */
625  BKE_report(op->reports,
626  RPT_ERROR,
627  "Keyframe pasting is not available for grease pencil or mask mode");
628  return OPERATOR_CANCELLED;
629  }
630  else {
631  /* Both paste function needs to be evaluated to account for mixed selection */
632  const eKeyPasteError kf_empty = paste_action_keys(&ac, offset_mode, merge_mode, flipped);
633  /* non-zero return means an error occurred while trying to paste */
634  gpframes_inbuf = ED_gpencil_anim_copybuf_paste(&ac, offset_mode);
635 
636  /* Only report an error if nothing was pasted, i.e. when both FCurve and GPencil failed. */
637  if (!gpframes_inbuf) {
638  switch (kf_empty) {
639  case KEYFRAME_PASTE_OK:
640  /* FCurve paste was ok, so it's all good. */
641  break;
642 
644  BKE_report(op->reports, RPT_ERROR, "No selected F-Curves to paste into");
645  return OPERATOR_CANCELLED;
646 
648  BKE_report(op->reports, RPT_ERROR, "No data in buffer to paste");
649  return OPERATOR_CANCELLED;
650  }
651  }
652  }
653 
654  /* Grease Pencil needs extra update to refresh the added keyframes. */
655  if (ac.datatype == ANIMCONT_GPENCIL || gpframes_inbuf) {
657  }
658  /* set notifier that keyframes have changed */
660 
661  return OPERATOR_FINISHED;
662 }
663 
665  wmOperatorType *UNUSED(op),
666  PointerRNA *ptr)
667 {
668  /* Custom description if the 'flipped' option is used. */
669  if (RNA_boolean_get(ptr, "flipped")) {
670  return BLI_strdup(TIP_("Paste keyframes from mirrored bones if they exist"));
671  }
672 
673  /* Use the default description in the other cases. */
674  return NULL;
675 }
676 
678 {
679  PropertyRNA *prop;
680  /* identifiers */
681  ot->name = "Paste Keyframes";
682  ot->idname = "ACTION_OT_paste";
683  ot->description =
684  "Paste keyframes from copy/paste buffer for the selected channels, starting on the current "
685  "frame";
686 
687  /* api callbacks */
688  // ot->invoke = WM_operator_props_popup; // better wait for action redo panel
692 
693  /* flags */
695 
696  /* props */
698  "offset",
701  "Offset",
702  "Paste time offset of keys");
704  "merge",
707  "Type",
708  "Method of merging pasted keys and existing");
709  prop = RNA_def_boolean(
710  ot->srna, "flipped", false, "Flipped", "Paste keyframes from mirrored bones if they exist");
712 }
713 
714 /* ******************** Insert Keyframes Operator ************************* */
715 
716 /* defines for insert keyframes tool */
718  {1, "ALL", 0, "All Channels", ""},
719  {2, "SEL", 0, "Only Selected Channels", ""},
720  /* XXX not in all cases. */
721  {3, "GROUP", 0, "In Active Group", ""},
722  {0, NULL, 0, NULL, NULL},
723 };
724 
726  bAnimListElem *ale,
727  const eGP_GetFrame_Mode add_frame_mode,
728  bGPdata **gpd_old)
729 {
730  Scene *scene = ac->scene;
731  bGPdata *gpd = (bGPdata *)ale->id;
732  bGPDlayer *gpl = (bGPDlayer *)ale->data;
733  BKE_gpencil_layer_frame_get(gpl, scene->r.cfra, add_frame_mode);
734  /* Check if the gpd changes to tag only once. */
735  if (gpd != *gpd_old) {
736  BKE_gpencil_tag(gpd);
737  *gpd_old = gpd;
738  }
739 }
740 
742  bAnimListElem *ale,
743  const AnimationEvalContext anim_eval_context,
744  eInsertKeyFlags flag,
745  ListBase *nla_cache)
746 {
747  FCurve *fcu = (FCurve *)ale->key_data;
748 
749  ReportList *reports = ac->reports;
750  Scene *scene = ac->scene;
752 
753  /* Read value from property the F-Curve represents, or from the curve only?
754  * - ale->id != NULL:
755  * Typically, this means that we have enough info to try resolving the path.
756  *
757  * - ale->owner != NULL:
758  * If this is set, then the path may not be resolvable from the ID alone,
759  * so it's easier for now to just read the F-Curve directly.
760  * (TODO: add the full-blown PointerRNA relative parsing case here...)
761  */
762  if (ale->id && !ale->owner) {
764  reports,
765  ale->id,
766  NULL,
767  ((fcu->grp) ? (fcu->grp->name) : (NULL)),
768  fcu->rna_path,
769  fcu->array_index,
770  &anim_eval_context,
771  ts->keyframe_type,
772  nla_cache,
773  flag);
774  }
775  else {
776  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
777 
778  /* adjust current frame for NLA-scaling */
779  float cfra = anim_eval_context.eval_time;
780  if (adt) {
782  }
783 
784  const float curval = evaluate_fcurve(fcu, cfra);
785  insert_vert_fcurve(fcu, cfra, curval, ts->keyframe_type, 0);
786  }
787 
788  ale->update |= ANIM_UPDATE_DEFAULT;
789 }
790 
791 /* this function is responsible for inserting new keyframes */
792 static void insert_action_keys(bAnimContext *ac, short mode)
793 {
794  ListBase anim_data = {NULL, NULL};
795  ListBase nla_cache = {NULL, NULL};
796  bAnimListElem *ale;
797  int filter;
798 
799  Scene *scene = ac->scene;
801  eInsertKeyFlags flag;
802 
803  eGP_GetFrame_Mode add_frame_mode;
804  bGPdata *gpd_old = NULL;
805 
806  /* filter data */
809  if (mode == 2) {
811  }
812  else if (mode == 3) {
814  }
815 
816  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
817 
818  /* Init keyframing flag. */
819  flag = ANIM_get_keyframing_flags(scene, true);
820 
821  /* GPLayers specific flags */
823  add_frame_mode = GP_GETFRAME_ADD_COPY;
824  }
825  else {
826  add_frame_mode = GP_GETFRAME_ADD_NEW;
827  }
828 
829  /* insert keyframes */
831  ac->depsgraph, (float)scene->r.cfra);
832  for (ale = anim_data.first; ale; ale = ale->next) {
833  switch (ale->type) {
834  case ANIMTYPE_GPLAYER:
835  insert_gpencil_key(ac, ale, add_frame_mode, &gpd_old);
836  break;
837 
838  case ANIMTYPE_FCURVE:
839  insert_fcurve_key(ac, ale, anim_eval_context, flag, &nla_cache);
840  break;
841 
842  default:
843  BLI_assert_msg(false, "Keys cannot be inserted into this animation type.");
844  }
845  }
846 
848 
849  ANIM_animdata_update(ac, &anim_data);
850  ANIM_animdata_freelist(&anim_data);
851 }
852 
853 /* ------------------- */
854 
856 {
857  bAnimContext ac;
858  short mode;
859 
860  /* get editor data */
861  if (ANIM_animdata_get_context(C, &ac) == 0) {
862  return OPERATOR_CANCELLED;
863  }
864 
865  if (ac.datatype == ANIMCONT_MASK) {
866  BKE_report(op->reports, RPT_ERROR, "Insert Keyframes is not yet implemented for this mode");
867  return OPERATOR_CANCELLED;
868  }
869 
870  /* what channels to affect? */
871  mode = RNA_enum_get(op->ptr, "type");
872 
873  /* insert keyframes */
874  insert_action_keys(&ac, mode);
875 
876  /* set notifier that keyframes have changed */
877  if (ac.datatype == ANIMCONT_GPENCIL) {
879  }
881 
882  return OPERATOR_FINISHED;
883 }
884 
886 {
887  /* identifiers */
888  ot->name = "Insert Keyframes";
889  ot->idname = "ACTION_OT_keyframe_insert";
890  ot->description = "Insert keyframes for the specified channels";
891 
892  /* api callbacks */
896 
897  /* flags */
899 
900  /* id-props */
901  ot->prop = RNA_def_enum(ot->srna, "type", prop_actkeys_insertkey_types, 0, "Type", "");
902 }
903 
904 /* ******************** Duplicate Keyframes Operator ************************* */
905 
907 {
908  ListBase anim_data = {NULL, NULL};
909  bAnimListElem *ale;
910  int filter;
911  bool changed = false;
912 
913  /* filter data */
916  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
917 
918  /* loop through filtered data and delete selected keys */
919  for (ale = anim_data.first; ale; ale = ale->next) {
921  changed |= duplicate_fcurve_keys((FCurve *)ale->key_data);
922  }
923  else if (ale->type == ANIMTYPE_GPLAYER) {
926  }
927  else if (ale->type == ANIMTYPE_MASKLAYER) {
929  }
930  else {
931  BLI_assert(0);
932  }
933 
934  ale->update |= ANIM_UPDATE_DEFAULT;
935  }
936 
937  ANIM_animdata_update(ac, &anim_data);
938  ANIM_animdata_freelist(&anim_data);
939 
940  return changed;
941 }
942 
943 /* ------------------- */
944 
946 {
947  bAnimContext ac;
948 
949  /* get editor data */
950  if (ANIM_animdata_get_context(C, &ac) == 0) {
951  return OPERATOR_CANCELLED;
952  }
953 
954  /* duplicate keyframes */
955  if (!duplicate_action_keys(&ac)) {
956  return OPERATOR_CANCELLED;
957  }
958 
959  /* set notifier that keyframes have changed */
961 
962  return OPERATOR_FINISHED;
963 }
964 
966 {
967  /* identifiers */
968  ot->name = "Duplicate Keyframes";
969  ot->idname = "ACTION_OT_duplicate";
970  ot->description = "Make a copy of all selected keyframes";
971 
972  /* api callbacks */
975 
976  /* flags */
978 }
979 
980 /* ******************** Delete Keyframes Operator ************************* */
981 
983 {
984  ListBase anim_data = {NULL, NULL};
985  bAnimListElem *ale;
986  int filter;
987  bool changed_final = false;
988 
989  /* filter data */
992  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
993 
994  /* loop through filtered data and delete selected keys */
995  for (ale = anim_data.first; ale; ale = ale->next) {
996  bool changed = false;
997 
998  if (ale->type == ANIMTYPE_GPLAYER) {
999  changed = ED_gpencil_layer_frames_delete((bGPDlayer *)ale->data);
1000  }
1001  else if (ale->type == ANIMTYPE_MASKLAYER) {
1002  changed = ED_masklayer_frames_delete((MaskLayer *)ale->data);
1003  }
1004  else {
1005  FCurve *fcu = (FCurve *)ale->key_data;
1006  AnimData *adt = ale->adt;
1007 
1008  /* delete selected keyframes only */
1009  changed = BKE_fcurve_delete_keys_selected(fcu);
1010 
1011  /* Only delete curve too if it won't be doing anything anymore */
1012  if (BKE_fcurve_is_empty(fcu)) {
1013  ANIM_fcurve_delete_from_animdata(ac, adt, fcu);
1014  ale->key_data = NULL;
1015  }
1016  }
1017 
1018  if (changed) {
1019  ale->update |= ANIM_UPDATE_DEFAULT;
1020  changed_final = true;
1021  }
1022  }
1023 
1024  ANIM_animdata_update(ac, &anim_data);
1025  ANIM_animdata_freelist(&anim_data);
1026 
1027  return changed_final;
1028 }
1029 
1030 /* ------------------- */
1031 
1033 {
1034  bAnimContext ac;
1035 
1036  /* get editor data */
1037  if (ANIM_animdata_get_context(C, &ac) == 0) {
1038  return OPERATOR_CANCELLED;
1039  }
1040 
1041  /* delete keyframes */
1042  if (!delete_action_keys(&ac)) {
1043  return OPERATOR_CANCELLED;
1044  }
1045 
1046  /* set notifier that keyframes have changed */
1048 
1049  return OPERATOR_FINISHED;
1050 }
1051 
1053 {
1054  /* identifiers */
1055  ot->name = "Delete Keyframes";
1056  ot->idname = "ACTION_OT_delete";
1057  ot->description = "Remove all selected keyframes";
1058 
1059  /* api callbacks */
1063 
1064  /* flags */
1067 }
1068 
1069 /* ******************** Clean Keyframes Operator ************************* */
1070 
1071 static void clean_action_keys(bAnimContext *ac, float thresh, bool clean_chan)
1072 {
1073  ListBase anim_data = {NULL, NULL};
1074  bAnimListElem *ale;
1075  int filter;
1076 
1077  /* filter data */
1080  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1081 
1082  /* loop through filtered data and clean curves */
1083  for (ale = anim_data.first; ale; ale = ale->next) {
1084  clean_fcurve(ac, ale, thresh, clean_chan);
1085 
1086  ale->update |= ANIM_UPDATE_DEFAULT;
1087  }
1088 
1089  ANIM_animdata_update(ac, &anim_data);
1090  ANIM_animdata_freelist(&anim_data);
1091 }
1092 
1093 /* ------------------- */
1094 
1096 {
1097  bAnimContext ac;
1098  float thresh;
1099  bool clean_chan;
1100 
1101  /* get editor data */
1102  if (ANIM_animdata_get_context(C, &ac) == 0) {
1103  return OPERATOR_CANCELLED;
1104  }
1105 
1107  BKE_report(op->reports, RPT_ERROR, "Not implemented");
1108  return OPERATOR_PASS_THROUGH;
1109  }
1110 
1111  /* get cleaning threshold */
1112  thresh = RNA_float_get(op->ptr, "threshold");
1113  clean_chan = RNA_boolean_get(op->ptr, "channels");
1114 
1115  /* clean keyframes */
1116  clean_action_keys(&ac, thresh, clean_chan);
1117 
1118  /* set notifier that keyframes have changed */
1120 
1121  return OPERATOR_FINISHED;
1122 }
1123 
1125 {
1126  /* identifiers */
1127  ot->name = "Clean Keyframes";
1128  ot->idname = "ACTION_OT_clean";
1129  ot->description = "Simplify F-Curves by removing closely spaced keyframes";
1130 
1131  /* api callbacks */
1132  // ot->invoke = /* XXX we need that number popup for this! */
1135 
1136  /* flags */
1138 
1139  /* properties */
1140  ot->prop = RNA_def_float(
1141  ot->srna, "threshold", 0.001f, 0.0f, FLT_MAX, "Threshold", "", 0.0f, 1000.0f);
1142  RNA_def_boolean(ot->srna, "channels", false, "Channels", "");
1143 }
1144 
1145 /* ******************** Sample Keyframes Operator *********************** */
1146 
1147 /* Evaluates the curves between each selected keyframe on each frame, and keys the value. */
1149 {
1150  ListBase anim_data = {NULL, NULL};
1151  bAnimListElem *ale;
1152  int filter;
1153 
1154  /* filter data */
1157  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1158 
1159  /* Loop through filtered data and add keys between selected keyframes on every frame. */
1160  for (ale = anim_data.first; ale; ale = ale->next) {
1161  sample_fcurve((FCurve *)ale->key_data);
1162 
1163  ale->update |= ANIM_UPDATE_DEPS;
1164  }
1165 
1166  ANIM_animdata_update(ac, &anim_data);
1167  ANIM_animdata_freelist(&anim_data);
1168 }
1169 
1170 /* ------------------- */
1171 
1173 {
1174  bAnimContext ac;
1175 
1176  /* get editor data */
1177  if (ANIM_animdata_get_context(C, &ac) == 0) {
1178  return OPERATOR_CANCELLED;
1179  }
1180 
1182  BKE_report(op->reports, RPT_ERROR, "Not implemented");
1183  return OPERATOR_PASS_THROUGH;
1184  }
1185 
1186  /* sample keyframes */
1187  sample_action_keys(&ac);
1188 
1189  /* set notifier that keyframes have changed */
1191 
1192  return OPERATOR_FINISHED;
1193 }
1194 
1196 {
1197  /* identifiers */
1198  ot->name = "Sample Keyframes";
1199  ot->idname = "ACTION_OT_sample";
1200  ot->description = "Add keyframes on every frame between the selected keyframes";
1201 
1202  /* api callbacks */
1205 
1206  /* flags */
1208 }
1209 
1210 /* ************************************************************************** */
1211 /* SETTINGS STUFF */
1212 
1213 /* ******************** Set Extrapolation-Type Operator *********************** */
1214 
1215 /* defines for make/clear cyclic extrapolation tools */
1216 #define MAKE_CYCLIC_EXPO -1
1217 #define CLEAR_CYCLIC_EXPO -2
1218 
1219 /* defines for set extrapolation-type for selected keyframes tool */
1222  "CONSTANT",
1223  0,
1224  "Constant Extrapolation",
1225  "Values on endpoint keyframes are held"},
1227  "LINEAR",
1228  0,
1229  "Linear Extrapolation",
1230  "Straight-line slope of end segments are extended past the endpoint keyframes"},
1231 
1233  "MAKE_CYCLIC",
1234  0,
1235  "Make Cyclic (F-Modifier)",
1236  "Add Cycles F-Modifier if one doesn't exist already"},
1238  "CLEAR_CYCLIC",
1239  0,
1240  "Clear Cyclic (F-Modifier)",
1241  "Remove Cycles F-Modifier if not needed anymore"},
1242  {0, NULL, 0, NULL, NULL},
1243 };
1244 
1245 /* this function is responsible for setting extrapolation mode for keyframes */
1246 static void setexpo_action_keys(bAnimContext *ac, short mode)
1247 {
1248  ListBase anim_data = {NULL, NULL};
1249  bAnimListElem *ale;
1250  int filter;
1251 
1252  /* filter data */
1255  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1256 
1257  /* loop through setting mode per F-Curve */
1258  for (ale = anim_data.first; ale; ale = ale->next) {
1259  FCurve *fcu = (FCurve *)ale->data;
1260 
1261  if (mode >= 0) {
1262  /* just set mode setting */
1263  fcu->extend = mode;
1264  }
1265  else {
1266  /* shortcuts for managing Cycles F-Modifiers to make it easier to toggle cyclic animation
1267  * without having to go through FModifier UI in Graph Editor to do so
1268  */
1269  if (mode == MAKE_CYCLIC_EXPO) {
1270  /* only add if one doesn't exist */
1272  /* TODO: add some more preset versions which set different extrapolation options? */
1274  }
1275  }
1276  else if (mode == CLEAR_CYCLIC_EXPO) {
1277  /* remove all the modifiers fitting this description */
1278  FModifier *fcm, *fcn = NULL;
1279 
1280  for (fcm = fcu->modifiers.first; fcm; fcm = fcn) {
1281  fcn = fcm->next;
1282 
1283  if (fcm->type == FMODIFIER_TYPE_CYCLES) {
1284  remove_fmodifier(&fcu->modifiers, fcm);
1285  }
1286  }
1287  }
1288  }
1289 
1290  ale->update |= ANIM_UPDATE_DEFAULT;
1291  }
1292 
1293  ANIM_animdata_update(ac, &anim_data);
1294  ANIM_animdata_freelist(&anim_data);
1295 }
1296 
1297 /* ------------------- */
1298 
1300 {
1301  bAnimContext ac;
1302  short mode;
1303 
1304  /* get editor data */
1305  if (ANIM_animdata_get_context(C, &ac) == 0) {
1306  return OPERATOR_CANCELLED;
1307  }
1308 
1310  BKE_report(op->reports, RPT_ERROR, "Not implemented");
1311  return OPERATOR_PASS_THROUGH;
1312  }
1313 
1314  /* get handle setting mode */
1315  mode = RNA_enum_get(op->ptr, "type");
1316 
1317  /* set handle type */
1318  setexpo_action_keys(&ac, mode);
1319 
1320  /* set notifier that keyframe properties have changed */
1322 
1323  return OPERATOR_FINISHED;
1324 }
1325 
1327 {
1328  /* identifiers */
1329  ot->name = "Set Keyframe Extrapolation";
1330  ot->idname = "ACTION_OT_extrapolation_type";
1331  ot->description = "Set extrapolation mode for selected F-Curves";
1332 
1333  /* api callbacks */
1337 
1338  /* flags */
1340 
1341  /* id-props */
1342  ot->prop = RNA_def_enum(ot->srna, "type", prop_actkeys_expo_types, 0, "Type", "");
1343 }
1344 
1345 /* ******************** Set Interpolation-Type Operator *********************** */
1346 
1348 {
1349  bAnimContext ac;
1350  short mode;
1351 
1352  /* get editor data */
1353  if (ANIM_animdata_get_context(C, &ac) == 0) {
1354  return OPERATOR_CANCELLED;
1355  }
1356 
1358  BKE_report(op->reports, RPT_ERROR, "Not implemented");
1359  return OPERATOR_PASS_THROUGH;
1360  }
1361 
1362  /* get handle setting mode */
1363  mode = RNA_enum_get(op->ptr, "type");
1364 
1365  /* set handle type */
1370  ANIM_editkeyframes_ipo(mode));
1371 
1372  /* set notifier that keyframe properties have changed */
1374 
1375  return OPERATOR_FINISHED;
1376 }
1377 
1379 {
1380  /* identifiers */
1381  ot->name = "Set Keyframe Interpolation";
1382  ot->idname = "ACTION_OT_interpolation_type";
1383  ot->description =
1384  "Set interpolation mode for the F-Curve segments starting from the selected keyframes";
1385 
1386  /* api callbacks */
1390 
1391  /* flags */
1393 
1394  /* id-props */
1395  ot->prop = RNA_def_enum(
1396  ot->srna, "type", rna_enum_beztriple_interpolation_mode_items, 0, "Type", "");
1398 }
1399 
1400 /* ******************** Set Easing Operator *********************** */
1401 
1403 {
1404  bAnimContext ac;
1405  short mode;
1406 
1407  /* get editor data */
1408  if (ANIM_animdata_get_context(C, &ac) == 0) {
1409  return OPERATOR_CANCELLED;
1410  }
1411 
1412  /* get handle setting mode */
1413  mode = RNA_enum_get(op->ptr, "type");
1414 
1415  /* set handle type */
1421 
1422  /* set notifier that keyframe properties have changed */
1424 
1425  return OPERATOR_FINISHED;
1426 }
1427 
1429 {
1430  /* identifiers */
1431  ot->name = "Set Keyframe Easing Type";
1432  ot->idname = "ACTION_OT_easing_type";
1433  ot->description =
1434  "Set easing type for the F-Curve segments starting from the selected keyframes";
1435 
1436  /* api callbacks */
1440 
1441  /* flags */
1443 
1444  /* id-props */
1445  ot->prop = RNA_def_enum(
1446  ot->srna, "type", rna_enum_beztriple_interpolation_easing_items, 0, "Type", "");
1447 }
1448 
1449 /* ******************** Set Handle-Type Operator *********************** */
1450 
1451 /* this function is responsible for setting handle-type of selected keyframes */
1452 static void sethandles_action_keys(bAnimContext *ac, short mode)
1453 {
1454  ListBase anim_data = {NULL, NULL};
1455  bAnimListElem *ale;
1456  int filter;
1457 
1460 
1461  /* filter data */
1464  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1465 
1466  /* Loop through setting flags for handles
1467  * NOTE: we do not supply KeyframeEditData to the looper yet.
1468  * Currently that's not necessary here.
1469  */
1470  for (ale = anim_data.first; ale; ale = ale->next) {
1471  FCurve *fcu = (FCurve *)ale->key_data;
1472 
1473  /* any selected keyframes for editing? */
1474  if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, sel_cb, NULL)) {
1475  /* change type of selected handles */
1477 
1478  ale->update |= ANIM_UPDATE_DEFAULT;
1479  }
1480  }
1481 
1482  ANIM_animdata_update(ac, &anim_data);
1483  ANIM_animdata_freelist(&anim_data);
1484 }
1485 
1486 /* ------------------- */
1487 
1489 {
1490  bAnimContext ac;
1491  short mode;
1492 
1493  /* get editor data */
1494  if (ANIM_animdata_get_context(C, &ac) == 0) {
1495  return OPERATOR_CANCELLED;
1496  }
1497 
1499  BKE_report(op->reports, RPT_ERROR, "Not implemented");
1500  return OPERATOR_PASS_THROUGH;
1501  }
1502 
1503  /* get handle setting mode */
1504  mode = RNA_enum_get(op->ptr, "type");
1505 
1506  /* set handle type */
1507  sethandles_action_keys(&ac, mode);
1508 
1509  /* set notifier that keyframe properties have changed */
1511 
1512  return OPERATOR_FINISHED;
1513 }
1514 
1516 {
1517  /* identifiers */
1518  ot->name = "Set Keyframe Handle Type";
1519  ot->idname = "ACTION_OT_handle_type";
1520  ot->description = "Set type of handle for selected keyframes";
1521 
1522  /* api callbacks */
1526 
1527  /* flags */
1529 
1530  /* id-props */
1531  ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_keyframe_handle_type_items, 0, "Type", "");
1532 }
1533 
1534 /* ******************** Set Keyframe-Type Operator *********************** */
1535 
1536 /* this function is responsible for setting keyframe type for keyframes */
1537 static void setkeytype_action_keys(bAnimContext *ac, short mode)
1538 {
1539  ListBase anim_data = {NULL, NULL};
1540  bAnimListElem *ale;
1541  int filter;
1543 
1544  /* filter data */
1547  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1548 
1549  /* Loop through setting BezTriple interpolation
1550  * NOTE: we do not supply KeyframeEditData to the looper yet.
1551  * Currently that's not necessary here.
1552  */
1553  for (ale = anim_data.first; ale; ale = ale->next) {
1554  switch (ale->type) {
1555  case ANIMTYPE_GPLAYER:
1557  ale->update |= ANIM_UPDATE_DEPS;
1558  break;
1559 
1560  case ANIMTYPE_FCURVE:
1563  break;
1564 
1565  default:
1566  BLI_assert_msg(false, "Keytype cannot be set into this animation type.");
1567  }
1568  }
1569 
1570  ANIM_animdata_update(ac, &anim_data);
1571  ANIM_animdata_freelist(&anim_data);
1572 }
1573 
1574 /* ------------------- */
1575 
1577 {
1578  bAnimContext ac;
1579  short mode;
1580 
1581  /* get editor data */
1582  if (ANIM_animdata_get_context(C, &ac) == 0) {
1583  return OPERATOR_CANCELLED;
1584  }
1585 
1586  if (ac.datatype == ANIMCONT_MASK) {
1587  BKE_report(op->reports, RPT_ERROR, "Not implemented for Masks");
1588  return OPERATOR_PASS_THROUGH;
1589  }
1590 
1591  /* get handle setting mode */
1592  mode = RNA_enum_get(op->ptr, "type");
1593 
1594  /* set handle type */
1595  setkeytype_action_keys(&ac, mode);
1596 
1597  /* set notifier that keyframe properties have changed */
1599 
1600  return OPERATOR_FINISHED;
1601 }
1602 
1604 {
1605  /* identifiers */
1606  ot->name = "Set Keyframe Type";
1607  ot->idname = "ACTION_OT_keyframe_type";
1608  ot->description = "Set type of keyframe for the selected keyframes";
1609 
1610  /* api callbacks */
1614 
1615  /* flags */
1617 
1618  /* id-props */
1619  ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_beztriple_keyframe_type_items, 0, "Type", "");
1620 }
1621 
1622 /* ************************************************************************** */
1623 /* TRANSFORM STUFF */
1624 
1625 /* ***************** Jump to Selected Frames Operator *********************** */
1626 
1628 {
1629  /* prevent changes during render */
1630  if (G.is_rendering) {
1631  return 0;
1632  }
1633 
1634  return ED_operator_action_active(C);
1635 }
1636 
1637 /* snap current-frame indicator to 'average time' of selected keyframe */
1639 {
1640  bAnimContext ac;
1641  ListBase anim_data = {NULL, NULL};
1642  bAnimListElem *ale;
1643  int filter;
1644  KeyframeEditData ked = {{NULL}};
1645 
1646  /* get editor data */
1647  if (ANIM_animdata_get_context(C, &ac) == 0) {
1648  return OPERATOR_CANCELLED;
1649  }
1650 
1651  /* init edit data */
1652  /* loop over action data, averaging values */
1654  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1655 
1656  for (ale = anim_data.first; ale; ale = ale->next) {
1657  switch (ale->datatype) {
1658  case ALE_GPFRAME: {
1659  bGPDlayer *gpl = ale->data;
1660  bGPDframe *gpf;
1661 
1662  for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1663  /* only if selected */
1664  if (!(gpf->flag & GP_FRAME_SELECT)) {
1665  continue;
1666  }
1667  /* store average time in float 1 (only do rounding at last step) */
1668  ked.f1 += gpf->framenum;
1669 
1670  /* increment number of items */
1671  ked.i1++;
1672  }
1673  break;
1674  }
1675 
1676  case ALE_FCURVE: {
1677  AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
1678  if (adt) {
1679  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
1681  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
1682  }
1683  else {
1685  }
1686  break;
1687  }
1688 
1689  default:
1690  BLI_assert_msg(false, "Cannot jump to keyframe into this animation type.");
1691  }
1692  }
1693 
1694  ANIM_animdata_freelist(&anim_data);
1695 
1696  /* set the new current frame value, based on the average time */
1697  if (ked.i1) {
1698  Scene *scene = ac.scene;
1699  scene->r.cfra = round_fl_to_int(ked.f1 / ked.i1);
1700  scene->r.subframe = 0.0f;
1701  }
1702 
1703  /* set notifier that things have changed */
1705 
1706  return OPERATOR_FINISHED;
1707 }
1708 
1710 {
1711  /* identifiers */
1712  ot->name = "Jump to Keyframes";
1713  ot->idname = "ACTION_OT_frame_jump";
1714  ot->description = "Set the current frame to the average frame value of selected keyframes";
1715 
1716  /* api callbacks */
1719 
1720  /* flags */
1722 }
1723 
1724 /* ******************** Snap Keyframes Operator *********************** */
1725 
1726 /* defines for snap keyframes tool */
1729  "CFRA",
1730  0,
1731  "Selection to Current Frame",
1732  "Snap selected keyframes to the current frame"},
1734  "NEAREST_FRAME",
1735  0,
1736  "Selection to Nearest Frame",
1737  "Snap selected keyframes to the nearest (whole) frame "
1738  "(use to fix accidental sub-frame offsets)"},
1740  "NEAREST_SECOND",
1741  0,
1742  "Selection to Nearest Second",
1743  "Snap selected keyframes to the nearest second"},
1745  "NEAREST_MARKER",
1746  0,
1747  "Selection to Nearest Marker",
1748  "Snap selected keyframes to the nearest marker"},
1749  {0, NULL, 0, NULL, NULL},
1750 };
1751 
1752 /* this function is responsible for snapping keyframes to frame-times */
1753 static void snap_action_keys(bAnimContext *ac, short mode)
1754 {
1755  ListBase anim_data = {NULL, NULL};
1756  bAnimListElem *ale;
1757  int filter;
1758 
1759  KeyframeEditData ked = {{NULL}};
1760  KeyframeEditFunc edit_cb;
1761 
1762  /* filter data */
1765  }
1766  else {
1769  }
1770  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1771 
1772  /* get beztriple editing callbacks */
1773  edit_cb = ANIM_editkeyframes_snap(mode);
1774 
1775  ked.scene = ac->scene;
1776  if (mode == ACTKEYS_SNAP_NEAREST_MARKER) {
1777  ked.list.first = (ac->markers) ? ac->markers->first : NULL;
1778  ked.list.last = (ac->markers) ? ac->markers->last : NULL;
1779  }
1780 
1781  /* snap keyframes */
1782  for (ale = anim_data.first; ale; ale = ale->next) {
1783  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
1784 
1785  if (ale->type == ANIMTYPE_GPLAYER) {
1786  ED_gpencil_layer_snap_frames(ale->data, ac->scene, mode);
1787  }
1788  else if (ale->type == ANIMTYPE_MASKLAYER) {
1789  ED_masklayer_snap_frames(ale->data, ac->scene, mode);
1790  }
1791  else if (adt) {
1792  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
1794  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
1795  }
1796  else {
1798  }
1799 
1800  ale->update |= ANIM_UPDATE_DEFAULT;
1801  }
1802 
1803  ANIM_animdata_update(ac, &anim_data);
1804  ANIM_animdata_freelist(&anim_data);
1805 }
1806 
1807 /* ------------------- */
1808 
1810 {
1811  bAnimContext ac;
1812  short mode;
1813 
1814  /* get editor data */
1815  if (ANIM_animdata_get_context(C, &ac) == 0) {
1816  return OPERATOR_CANCELLED;
1817  }
1818 
1819  /* get snapping mode */
1820  mode = RNA_enum_get(op->ptr, "type");
1821 
1822  /* snap keyframes */
1823  snap_action_keys(&ac, mode);
1824 
1825  /* set notifier that keyframes have changed */
1827 
1828  return OPERATOR_FINISHED;
1829 }
1830 
1832 {
1833  /* identifiers */
1834  ot->name = "Snap Keys";
1835  ot->idname = "ACTION_OT_snap";
1836  ot->description = "Snap selected keyframes to the times specified";
1837 
1838  /* api callbacks */
1842 
1843  /* flags */
1845 
1846  /* id-props */
1847  ot->prop = RNA_def_enum(ot->srna, "type", prop_actkeys_snap_types, 0, "Type", "");
1848 }
1849 
1850 /* ******************** Mirror Keyframes Operator *********************** */
1851 
1852 /* defines for mirror keyframes tool */
1855  "CFRA",
1856  0,
1857  "By Times Over Current Frame",
1858  "Flip times of selected keyframes using the current frame as the mirror line"},
1860  "XAXIS",
1861  0,
1862  "By Values Over Zero Value",
1863  "Flip values of selected keyframes (i.e. negative values become positive, and vice versa)"},
1865  "MARKER",
1866  0,
1867  "By Times Over First Selected Marker",
1868  "Flip times of selected keyframes using the first selected marker as the reference point"},
1869  {0, NULL, 0, NULL, NULL},
1870 };
1871 
1872 /* this function is responsible for mirroring keyframes */
1873 static void mirror_action_keys(bAnimContext *ac, short mode)
1874 {
1875  ListBase anim_data = {NULL, NULL};
1876  bAnimListElem *ale;
1877  int filter;
1878 
1879  KeyframeEditData ked = {{NULL}};
1880  KeyframeEditFunc edit_cb;
1881 
1882  /* get beztriple editing callbacks */
1883  edit_cb = ANIM_editkeyframes_mirror(mode);
1884 
1885  ked.scene = ac->scene;
1886 
1887  /* for 'first selected marker' mode, need to find first selected marker first! */
1888  /* XXX should this be made into a helper func in the API? */
1889  if (mode == ACTKEYS_MIRROR_MARKER) {
1891 
1892  if (marker) {
1893  ked.f1 = (float)marker->frame;
1894  }
1895  else {
1896  return;
1897  }
1898  }
1899 
1900  /* filter data */
1903  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1904 
1905  /* mirror keyframes */
1906  for (ale = anim_data.first; ale; ale = ale->next) {
1907  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
1908 
1909  if (ale->type == ANIMTYPE_GPLAYER) {
1910  ED_gpencil_layer_mirror_frames(ale->data, ac->scene, mode);
1911  }
1912  else if (ale->type == ANIMTYPE_MASKLAYER) {
1913  /* TODO */
1914  }
1915  else if (adt) {
1916  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
1918  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
1919  }
1920  else {
1922  }
1923 
1924  ale->update |= ANIM_UPDATE_DEFAULT;
1925  }
1926 
1927  ANIM_animdata_update(ac, &anim_data);
1928  ANIM_animdata_freelist(&anim_data);
1929 }
1930 
1931 /* ------------------- */
1932 
1934 {
1935  bAnimContext ac;
1936  short mode;
1937 
1938  /* get editor data */
1939  if (ANIM_animdata_get_context(C, &ac) == 0) {
1940  return OPERATOR_CANCELLED;
1941  }
1942 
1943  /* get mirroring mode */
1944  mode = RNA_enum_get(op->ptr, "type");
1945 
1946  /* mirror keyframes */
1947  mirror_action_keys(&ac, mode);
1948 
1949  /* set notifier that keyframes have changed */
1951 
1952  return OPERATOR_FINISHED;
1953 }
1954 
1956 {
1957  /* identifiers */
1958  ot->name = "Mirror Keys";
1959  ot->idname = "ACTION_OT_mirror";
1960  ot->description = "Flip selected keyframes over the selected mirror line";
1961 
1962  /* api callbacks */
1966 
1967  /* flags */
1969 
1970  /* id-props */
1971  ot->prop = RNA_def_enum(ot->srna, "type", prop_actkeys_mirror_types, 0, "Type", "");
1972 }
1973 
1974 /* ************************************************************************** */
typedef float(TangentPoint)[2]
Blender kernel action and pose functionality.
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 bScreen * CTX_wm_screen(const bContext *C)
Definition: context.c:733
struct SpaceAction * CTX_wm_space_action(const bContext *C)
Definition: context.c:896
float evaluate_fcurve(struct FCurve *fcu, float evaltime)
Definition: fcurve.c:2135
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
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
bool BKE_fcurve_calc_range(struct FCurve *fcu, float *min, float *max, bool do_sel_only, bool do_min_length)
Definition: fcurve.c:754
struct bGPDframe * BKE_gpencil_layer_frame_get(struct bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew)
Definition: gpencil.c:1232
void BKE_gpencil_tag(struct bGPdata *gpd)
Definition: gpencil.c:506
eGP_GetFrame_Mode
Definition: BKE_gpencil.h:336
@ GP_GETFRAME_ADD_NEW
Definition: BKE_gpencil.h:341
@ GP_GETFRAME_ADD_COPY
Definition: BKE_gpencil.h:343
@ NLATIME_CONVERT_MAP
Definition: BKE_nla.h:360
@ 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_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
MINLINE int round_fl_to_int(float a)
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:190
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition: BLI_rect.h:194
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:42
#define UNUSED(x)
#define ELEM(...)
#define BLT_I18NCONTEXT_ID_ACTION
#define TIP_(msgid)
@ SACTCONT_ACTION
@ SACTCONT_SHAPEKEY
@ SACTION_POSEMARKERS_SHOW
eInsertKeyFlags
@ FMODIFIER_TYPE_CYCLES
@ FCURVE_EXTRAPOLATE_CONSTANT
@ FCURVE_EXTRAPOLATE_LINEAR
@ GP_FRAME_SELECT
Object is a sort of wrapper for general info.
#define SCER_PRV_RANGE
@ GP_TOOL_FLAG_RETAIN_LAST
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_PASS_THROUGH
#define ACHANNEL_HEIGHT(ac)
Definition: ED_anim_api.h:440
@ ANIMTYPE_NLACURVE
Definition: ED_anim_api.h:202
@ ANIMTYPE_GPLAYER
Definition: ED_anim_api.h:233
@ ANIMTYPE_MASKLAYER
Definition: ED_anim_api.h:236
@ ANIMTYPE_FCURVE
Definition: ED_anim_api.h:199
#define ACHANNEL_FIRST_TOP(ac)
Definition: ED_anim_api.h:438
@ ACHANNEL_ROLE_CHANNEL
Definition: ED_anim_api.h:544
#define ANIM_UPDATE_DEFAULT
Definition: ED_anim_api.h:274
@ ALE_GPFRAME
Definition: ED_anim_api.h:251
@ ALE_FCURVE
Definition: ED_anim_api.h:250
@ ALE_MASKLAY
Definition: ED_anim_api.h:252
@ ANIM_UPDATE_DEPS
Definition: ED_anim_api.h:268
@ ANIM_UPDATE_HANDLES
Definition: ED_anim_api.h:270
@ ANIMCONT_MASK
Definition: ED_anim_api.h:112
@ ANIMCONT_GPENCIL
Definition: ED_anim_api.h:106
@ ACHANNEL_SETTING_SELECT
Definition: ED_anim_api.h:561
#define ACHANNEL_STEP(ac)
Definition: ED_anim_api.h:442
@ 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_LIST_VISIBLE
Definition: ED_anim_api.h:295
@ ANIMFILTER_LIST_CHANNELS
Definition: ED_anim_api.h:300
@ ANIMFILTER_NODUPLIS
Definition: ED_anim_api.h:325
@ ANIMFILTER_FCURVESONLY
Definition: ED_anim_api.h:328
@ ANIMFILTER_SEL
Definition: ED_anim_api.h:308
@ ANIMFILTER_ACTGROUPED
Definition: ED_anim_api.h:305
eKeyMergeMode
@ KEYFRAME_PASTE_MERGE_MIX
eKeyPasteOffset
@ KEYFRAME_PASTE_OFFSET_CFRA_START
@ BEZT_OK_SELECTED
short(* KeyframeEditFunc)(KeyframeEditData *ked, struct BezTriple *bezt)
eKeyPasteError
@ KEYFRAME_PASTE_NOTHING_TO_PASTE
@ KEYFRAME_PASTE_OK
@ KEYFRAME_PASTE_NOWHERE_TO_PASTE
void ED_masklayer_frames_duplicate(struct MaskLayer *mask_layer)
bool ED_masklayer_frames_delete(struct MaskLayer *mask_layer)
void ED_masklayer_snap_frames(struct MaskLayer *mask_layer, struct Scene *scene, short mode)
void ED_area_tag_redraw(ScrArea *area)
Definition: area.c:729
bool ED_operator_action_active(struct bContext *C)
Definition: screen_ops.c:297
@ PROP_SKIP_SAVE
Definition: RNA_types.h:218
#define C
Definition: RandGen.cpp:25
void UI_view2d_center_set(struct View2D *v2d, float x, float y)
Definition: view2d.cc:1946
#define V2D_LOCK_COPY
Definition: UI_view2d.h:82
void UI_view2d_sync(struct bScreen *screen, struct ScrArea *area, struct View2D *v2dcur, int flag)
Definition: view2d.cc:851
void UI_view2d_center_get(const struct View2D *v2d, float *r_x, float *r_y)
Definition: view2d.cc:1936
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define ND_DATA
Definition: WM_types.h:456
#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_MARKERS
Definition: WM_types.h:381
#define ND_FRAME
Definition: WM_types.h:382
#define NA_REMOVED
Definition: WM_types.h:526
#define NC_GPENCIL
Definition: WM_types.h:349
#define ND_KEYFRAME
Definition: WM_types.h:442
void ACTION_OT_view_selected(wmOperatorType *ot)
Definition: action_edit.c:447
static bool actkeys_framejump_poll(bContext *C)
Definition: action_edit.c:1627
static int actkeys_delete_exec(bContext *C, wmOperator *UNUSED(op))
Definition: action_edit.c:1032
void ACTION_OT_keyframe_type(wmOperatorType *ot)
Definition: action_edit.c:1603
void ACTION_OT_easing_type(wmOperatorType *ot)
Definition: action_edit.c:1428
static bool act_markers_make_local_poll(bContext *C)
Definition: action_edit.c:68
static void snap_action_keys(bAnimContext *ac, short mode)
Definition: action_edit.c:1753
static int actkeys_view_frame_exec(bContext *C, wmOperator *op)
Definition: action_edit.c:464
static void clean_action_keys(bAnimContext *ac, float thresh, bool clean_chan)
Definition: action_edit.c:1071
static int actkeys_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
Definition: action_edit.c:945
static const EnumPropertyItem prop_actkeys_snap_types[]
Definition: action_edit.c:1727
void ACTION_OT_view_all(wmOperatorType *ot)
Definition: action_edit.c:432
void ACTION_OT_sample(wmOperatorType *ot)
Definition: action_edit.c:1195
static int actkeys_viewall(bContext *C, const bool only_sel)
Definition: action_edit.c:348
static bool duplicate_action_keys(bAnimContext *ac)
Definition: action_edit.c:906
void ACTION_OT_previewrange_set(wmOperatorType *ot)
Definition: action_edit.c:280
static int actkeys_snap_exec(bContext *C, wmOperator *op)
Definition: action_edit.c:1809
void ACTION_OT_duplicate(wmOperatorType *ot)
Definition: action_edit.c:965
void ACTION_OT_delete(wmOperatorType *ot)
Definition: action_edit.c:1052
void ACTION_OT_view_frame(wmOperatorType *ot)
Definition: action_edit.c:472
static int actkeys_previewrange_exec(bContext *C, wmOperator *UNUSED(op))
Definition: action_edit.c:247
static void insert_fcurve_key(bAnimContext *ac, bAnimListElem *ale, const AnimationEvalContext anim_eval_context, eInsertKeyFlags flag, ListBase *nla_cache)
Definition: action_edit.c:741
void ACTION_OT_extrapolation_type(wmOperatorType *ot)
Definition: action_edit.c:1326
static int actkeys_ipo_exec(bContext *C, wmOperator *op)
Definition: action_edit.c:1347
void ACTION_OT_keyframe_insert(wmOperatorType *ot)
Definition: action_edit.c:885
static void insert_action_keys(bAnimContext *ac, short mode)
Definition: action_edit.c:792
static eKeyPasteError paste_action_keys(bAnimContext *ac, const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode, bool flip)
Definition: action_edit.c:515
static char * actkeys_paste_description(bContext *UNUSED(C), wmOperatorType *UNUSED(op), PointerRNA *ptr)
Definition: action_edit.c:664
static bool delete_action_keys(bAnimContext *ac)
Definition: action_edit.c:982
void ACTION_OT_snap(wmOperatorType *ot)
Definition: action_edit.c:1831
static int act_markers_make_local_exec(bContext *C, wmOperator *UNUSED(op))
Definition: action_edit.c:94
static int actkeys_paste_exec(bContext *C, wmOperator *op)
Definition: action_edit.c:598
#define MAKE_CYCLIC_EXPO
Definition: action_edit.c:1216
void ACTION_OT_frame_jump(wmOperatorType *ot)
Definition: action_edit.c:1709
static void sample_action_keys(bAnimContext *ac)
Definition: action_edit.c:1148
void ACTION_OT_paste(wmOperatorType *ot)
Definition: action_edit.c:677
static int actkeys_clean_exec(bContext *C, wmOperator *op)
Definition: action_edit.c:1095
static const EnumPropertyItem prop_actkeys_mirror_types[]
Definition: action_edit.c:1853
static bool actkeys_channels_get_selected_extents(bAnimContext *ac, float *r_min, float *r_max)
Definition: action_edit.c:304
static void sethandles_action_keys(bAnimContext *ac, short mode)
Definition: action_edit.c:1452
static void mirror_action_keys(bAnimContext *ac, short mode)
Definition: action_edit.c:1873
void ACTION_OT_copy(wmOperatorType *ot)
Definition: action_edit.c:583
static short copy_action_keys(bAnimContext *ac)
Definition: action_edit.c:493
static bool get_keyframe_extents(bAnimContext *ac, float *min, float *max, const short onlySel)
Definition: action_edit.c:151
static int actkeys_easing_exec(bContext *C, wmOperator *op)
Definition: action_edit.c:1402
static int actkeys_copy_exec(bContext *C, wmOperator *op)
Definition: action_edit.c:547
static int actkeys_mirror_exec(bContext *C, wmOperator *op)
Definition: action_edit.c:1933
void ACTION_OT_markers_make_local(wmOperatorType *ot)
Definition: action_edit.c:130
void ACTION_OT_interpolation_type(wmOperatorType *ot)
Definition: action_edit.c:1378
static int actkeys_expo_exec(bContext *C, wmOperator *op)
Definition: action_edit.c:1299
static int actkeys_handletype_exec(bContext *C, wmOperator *op)
Definition: action_edit.c:1488
void ACTION_OT_handle_type(wmOperatorType *ot)
Definition: action_edit.c:1515
static const EnumPropertyItem prop_actkeys_insertkey_types[]
Definition: action_edit.c:717
static int actkeys_insertkey_exec(bContext *C, wmOperator *op)
Definition: action_edit.c:855
void ACTION_OT_mirror(wmOperatorType *ot)
Definition: action_edit.c:1955
static void insert_gpencil_key(bAnimContext *ac, bAnimListElem *ale, const eGP_GetFrame_Mode add_frame_mode, bGPdata **gpd_old)
Definition: action_edit.c:725
static void setexpo_action_keys(bAnimContext *ac, short mode)
Definition: action_edit.c:1246
static void setkeytype_action_keys(bAnimContext *ac, short mode)
Definition: action_edit.c:1537
void ACTION_OT_clean(wmOperatorType *ot)
Definition: action_edit.c:1124
#define CLEAR_CYCLIC_EXPO
Definition: action_edit.c:1217
static int actkeys_viewsel_exec(bContext *C, wmOperator *UNUSED(op))
Definition: action_edit.c:424
static int actkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op))
Definition: action_edit.c:1638
static int actkeys_viewall_exec(bContext *C, wmOperator *UNUSED(op))
Definition: action_edit.c:418
static int actkeys_keytype_exec(bContext *C, wmOperator *op)
Definition: action_edit.c:1576
static const EnumPropertyItem prop_actkeys_expo_types[]
Definition: action_edit.c:1220
static int actkeys_sample_exec(bContext *C, wmOperator *op)
Definition: action_edit.c:1172
@ ACTKEYS_SNAP_NEAREST_FRAME
@ ACTKEYS_SNAP_NEAREST_SECOND
@ ACTKEYS_SNAP_CFRA
@ ACTKEYS_SNAP_NEAREST_MARKER
@ ACTKEYS_MIRROR_CFRA
@ ACTKEYS_MIRROR_MARKER
@ ACTKEYS_MIRROR_XAXIS
short ANIM_channel_setting_get(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting)
const bAnimChannelType * ANIM_channel_get_typeinfo(bAnimListElem *ale)
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
void ANIM_center_frame(struct bContext *C, int smooth_viewtx)
Definition: anim_draw.c:619
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
ListBase * ED_context_get_markers(const bContext *C)
Definition: anim_markers.c:88
#define SELECT
Scene scene
void ED_gpencil_layer_frames_keytype_set(bGPDlayer *gpl, short type)
void ED_gpencil_layer_frames_duplicate(bGPDlayer *gpl)
bool ED_gpencil_layer_frames_delete(bGPDlayer *gpl)
bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode)
bool ED_gpencil_layer_frame_select_check(const bGPDlayer *gpl)
void ED_gpencil_layer_mirror_frames(bGPDlayer *gpl, Scene *scene, short mode)
void ED_gpencil_layer_snap_frames(bGPDlayer *gpl, Scene *scene, short mode)
bool ED_gpencil_anim_copybuf_copy(bAnimContext *ac)
DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
const vector< Marker > & markers
KeyframeEditFunc ANIM_editkeyframes_mirror(short mode)
KeyframeEditFunc ANIM_editkeyframes_keytype(short mode)
KeyframeEditFunc ANIM_editkeyframes_easing(short mode)
KeyframeEditFunc ANIM_editkeyframes_ipo(short mode)
short ANIM_fcurve_keyframes_loop(KeyframeEditData *ked, FCurve *fcu, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
KeyframeEditFunc ANIM_editkeyframes_ok(short mode)
KeyframeEditFunc ANIM_editkeyframes_snap(short mode)
void ANIM_animdata_keyframe_callback(bAnimContext *ac, eAnimFilter_Flags filter, KeyframeEditFunc callback_fn)
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 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
#define G(x, y, z)
#define ceilf(x)
Definition: metal/compat.h:225
#define floorf(x)
Definition: metal/compat.h:224
#define fabsf(x)
Definition: metal/compat.h:219
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4957
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_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
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_beztriple_interpolation_easing_items[]
Definition: rna_fcurve.c:110
const EnumPropertyItem rna_enum_beztriple_keyframe_type_items[]
Definition: rna_fcurve.c:81
#define min(a, b)
Definition: sort.c:35
bActionGroup * grp
char * rna_path
short extend
int array_index
ListBase modifiers
struct FModifier * next
struct Scene * scene
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
struct MaskLayerShape * next
ListBase splines_shapes
struct ToolSettings * toolsettings
struct RenderData r
bAction * action
ListBase markers
bool(* has_setting)(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting)
Definition: ED_anim_api.h:604
eAnimChannel_Role channel_role
Definition: ED_anim_api.h:583
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 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
struct bGPDframe * next
ListBase frames
float xmax
Definition: DNA_vec_types.h:69
float xmin
Definition: DNA_vec_types.h:69
float ymax
Definition: DNA_vec_types.h:70
float ymin
Definition: DNA_vec_types.h:70
int(* 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
float max
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)
int WM_operator_confirm_or_exec(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
int WM_operator_smooth_viewtx_get(const wmOperator *op)
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))