Blender  V3.3
keyframing.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2009 Blender Foundation, Joshua Leung. All rights reserved. */
3 
8 #include <float.h>
9 #include <math.h>
10 #include <stddef.h>
11 #include <stdio.h>
12 #include <string.h>
13 
14 #include "MEM_guardedalloc.h"
15 
16 #include "BLI_blenlib.h"
17 #include "BLI_dynstr.h"
18 #include "BLI_math.h"
19 #include "BLI_utildefines.h"
20 
21 #include "BLT_translation.h"
22 
23 #include "DNA_action_types.h"
24 #include "DNA_anim_types.h"
25 #include "DNA_armature_types.h"
26 #include "DNA_constraint_types.h"
27 #include "DNA_key_types.h"
28 #include "DNA_material_types.h"
29 #include "DNA_object_types.h"
30 #include "DNA_rigidbody_types.h"
31 #include "DNA_scene_types.h"
32 
33 #include "BKE_action.h"
34 #include "BKE_anim_data.h"
35 #include "BKE_animsys.h"
36 #include "BKE_armature.h"
37 #include "BKE_context.h"
38 #include "BKE_fcurve.h"
39 #include "BKE_fcurve_driver.h"
40 #include "BKE_global.h"
41 #include "BKE_idtype.h"
42 #include "BKE_key.h"
43 #include "BKE_lib_id.h"
44 #include "BKE_main.h"
45 #include "BKE_material.h"
46 #include "BKE_nla.h"
47 #include "BKE_report.h"
48 
49 #include "DEG_depsgraph.h"
50 #include "DEG_depsgraph_build.h"
51 #include "DEG_depsgraph_query.h"
52 
53 #include "ED_anim_api.h"
54 #include "ED_keyframes_edit.h"
55 #include "ED_keyframing.h"
56 #include "ED_object.h"
57 #include "ED_screen.h"
58 
59 #include "UI_interface.h"
60 #include "UI_resources.h"
61 
62 #include "WM_api.h"
63 #include "WM_types.h"
64 
65 #include "RNA_access.h"
66 #include "RNA_define.h"
67 #include "RNA_enum_types.h"
68 #include "RNA_path.h"
69 #include "RNA_prototypes.h"
70 
71 #include "anim_intern.h"
72 
74  PropertyRNA *prop,
75  Scene *scene);
76 
78 
79 /* ************************************************** */
80 /* Keyframing Setting Wrangling */
81 
82 eInsertKeyFlags ANIM_get_keyframing_flags(Scene *scene, const bool use_autokey_mode)
83 {
85 
86  /* standard flags */
87  {
88  /* visual keying */
89  if (IS_AUTOKEY_FLAG(scene, AUTOMATKEY)) {
90  flag |= INSERTKEY_MATRIX;
91  }
92 
93  /* only needed */
94  if (IS_AUTOKEY_FLAG(scene, INSERTNEEDED)) {
95  flag |= INSERTKEY_NEEDED;
96  }
97 
98  /* default F-Curve color mode - RGB from XYZ indices */
99  if (IS_AUTOKEY_FLAG(scene, XYZ2RGB)) {
100  flag |= INSERTKEY_XYZ2RGB;
101  }
102  }
103 
104  /* only if including settings from the autokeying mode... */
105  if (use_autokey_mode) {
106  /* keyframing mode - only replace existing keyframes */
107  if (IS_AUTOKEY_MODE(scene, EDITKEYS)) {
108  flag |= INSERTKEY_REPLACE;
109  }
110 
111  /* cycle-aware keyframe insertion - preserve cycle period and flow */
112  if (IS_AUTOKEY_FLAG(scene, CYCLEAWARE)) {
113  flag |= INSERTKEY_CYCLE_AWARE;
114  }
115  }
116 
117  return flag;
118 }
119 
120 /* ******************************************* */
121 /* Animation Data Validation */
122 
124 {
125  AnimData *adt;
126 
127  /* init animdata if none available yet */
128  adt = BKE_animdata_from_id(id);
129  if (adt == NULL) {
130  adt = BKE_animdata_ensure_id(id);
131  }
132  if (adt == NULL) {
133  /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */
134  printf("ERROR: Couldn't add AnimData (ID = %s)\n", (id) ? (id->name) : "<None>");
135  return NULL;
136  }
137 
138  /* init action if none available yet */
139  /* TODO: need some wizardry to handle NLA stuff correct */
140  if (adt->action == NULL) {
141  /* init action name from name of ID block */
142  char actname[sizeof(id->name) - 2];
143  BLI_snprintf(actname, sizeof(actname), "%sAction", id->name + 2);
144 
145  /* create action */
146  adt->action = BKE_action_add(bmain, actname);
147 
148  /* set ID-type from ID-block that this is going to be assigned to
149  * so that users can't accidentally break actions by assigning them
150  * to the wrong places
151  */
153 
154  /* Tag depsgraph to be rebuilt to include time dependency. */
156  }
157 
159 
160  /* return the action */
161  return adt->action;
162 }
163 
164 FCurve *ED_action_fcurve_find(struct bAction *act, const char rna_path[], const int array_index)
165 {
166  /* Sanity checks. */
167  if (ELEM(NULL, act, rna_path)) {
168  return NULL;
169  }
170  return BKE_fcurve_find(&act->curves, rna_path, array_index);
171 }
172 
174  struct bAction *act,
175  const char group[],
176  struct PointerRNA *ptr,
177  const char rna_path[],
178  const int array_index)
179 {
180  bActionGroup *agrp;
181  FCurve *fcu;
182 
183  /* Sanity checks. */
184  if (ELEM(NULL, act, rna_path)) {
185  return NULL;
186  }
187 
188  /* try to find f-curve matching for this setting
189  * - add if not found and allowed to add one
190  * TODO: add auto-grouping support? how this works will need to be resolved
191  */
192  fcu = BKE_fcurve_find(&act->curves, rna_path, array_index);
193 
194  if (fcu == NULL) {
195  /* use default settings to make a F-Curve */
196  fcu = BKE_fcurve_create();
197 
199  fcu->auto_smoothing = U.auto_smoothing_new;
200  if (BLI_listbase_is_empty(&act->curves)) {
201  fcu->flag |= FCURVE_ACTIVE; /* first one added active */
202  }
203 
204  /* store path - make copy, and store that */
205  fcu->rna_path = BLI_strdup(rna_path);
206  fcu->array_index = array_index;
207 
208  /* if a group name has been provided, try to add or find a group, then add F-Curve to it */
209  if (group) {
210  /* try to find group */
211  agrp = BKE_action_group_find_name(act, group);
212 
213  /* no matching groups, so add one */
214  if (agrp == NULL) {
215  agrp = action_groups_add_new(act, group);
216 
217  /* sync bone group colors if applicable */
218  if (ptr && (ptr->type == &RNA_PoseBone)) {
219  Object *ob = (Object *)ptr->owner_id;
220  bPoseChannel *pchan = ptr->data;
221  bPose *pose = ob->pose;
222  bActionGroup *grp;
223 
224  /* find bone group (if present), and use the color from that */
225  grp = (bActionGroup *)BLI_findlink(&pose->agroups, (pchan->agrp_index - 1));
226  if (grp) {
227  agrp->customCol = grp->customCol;
228  action_group_colors_sync(agrp, grp);
229  }
230  }
231  }
232 
233  /* add F-Curve to group */
234  action_groups_add_channel(act, agrp, fcu);
235  }
236  else {
237  /* just add F-Curve to end of Action's list */
238  BLI_addtail(&act->curves, fcu);
239  }
240 
241  /* New f-curve was added, meaning it's possible that it affects
242  * dependency graph component which wasn't previously animated.
243  */
245  }
246 
247  /* return the F-Curve */
248  return fcu;
249 }
250 
253 {
254  /* set additional flags for the F-Curve (i.e. only integer values) */
256  switch (RNA_property_type(prop)) {
257  case PROP_FLOAT:
258  /* do nothing */
259  break;
260  case PROP_INT:
261  /* do integer (only 'whole' numbers) interpolation between all points */
262  fcu->flag |= FCURVE_INT_VALUES;
263  break;
264  default:
265  /* do 'discrete' (i.e. enum, boolean values which cannot take any intermediate
266  * values at all) interpolation between all points
267  * - however, we must also ensure that evaluated values are only integers still
268  */
270  break;
271  }
272 }
273 
275 {
276  PointerRNA tmp_ptr;
277  PropertyRNA *prop;
278  int old_flag = fcu->flag;
279 
280  if ((ptr->owner_id == NULL) && (ptr->data == NULL)) {
281  BKE_report(reports, RPT_ERROR, "No RNA pointer available to retrieve values for this fcurve");
282  return;
283  }
284 
285  /* try to get property we should be affecting */
286  if (RNA_path_resolve_property(ptr, fcu->rna_path, &tmp_ptr, &prop) == false) {
287  /* property not found... */
288  const char *idname = (ptr->owner_id) ? ptr->owner_id->name : TIP_("<No ID pointer>");
289 
290  BKE_reportf(reports,
291  RPT_ERROR,
292  "Could not update flags for this fcurve, as RNA path is invalid for the given ID "
293  "(ID = %s, path = %s)",
294  idname,
295  fcu->rna_path);
296  return;
297  }
298 
299  /* update F-Curve flags */
301 
302  if (old_flag != fcu->flag) {
303  /* Same as if keyframes had been changed */
305  }
306 }
307 
308 /* ************************************************** */
309 /* KEYFRAME INSERTION */
310 
315 static eFCU_Cycle_Type remap_cyclic_keyframe_location(FCurve *fcu, float *px, float *py)
316 {
317  if (fcu->totvert < 2 || !fcu->bezt) {
318  return FCU_CYCLE_NONE;
319  }
320 
322 
323  if (type == FCU_CYCLE_NONE) {
324  return FCU_CYCLE_NONE;
325  }
326 
327  BezTriple *first = &fcu->bezt[0], *last = &fcu->bezt[fcu->totvert - 1];
328  float start = first->vec[1][0], end = last->vec[1][0];
329 
330  if (start >= end) {
331  return FCU_CYCLE_NONE;
332  }
333 
334  if (*px < start || *px > end) {
335  float period = end - start;
336  float step = floorf((*px - start) / period);
337  *px -= step * period;
338 
339  if (type == FCU_CYCLE_OFFSET) {
340  /* Nasty check to handle the case when the modes are different better. */
341  FMod_Cycles *data = ((FModifier *)fcu->modifiers.first)->data;
342  short mode = (step >= 0) ? data->after_mode : data->before_mode;
343 
345  *py -= step * (last->vec[1][1] - first->vec[1][1]);
346  }
347  }
348  }
349 
350  return type;
351 }
352 
354 static void make_new_fcurve_cyclic(const bAction *act, FCurve *fcu)
355 {
356  /* The curve must contain one (newly-added) keyframe. */
357  if (fcu->totvert != 1 || !fcu->bezt) {
358  return;
359  }
360 
361  const float period = act->frame_end - act->frame_start;
362 
363  if (period < 0.1f) {
364  return;
365  }
366 
367  /* Move the keyframe into the range. */
368  const float frame_offset = fcu->bezt[0].vec[1][0] - act->frame_start;
369  const float fix = floorf(frame_offset / period) * period;
370 
371  fcu->bezt[0].vec[0][0] -= fix;
372  fcu->bezt[0].vec[1][0] -= fix;
373  fcu->bezt[0].vec[2][0] -= fix;
374 
375  /* Duplicate and offset the keyframe. */
376  fcu->bezt = MEM_reallocN(fcu->bezt, sizeof(BezTriple) * 2);
377  fcu->totvert = 2;
378 
379  fcu->bezt[1] = fcu->bezt[0];
380  fcu->bezt[1].vec[0][0] += period;
381  fcu->bezt[1].vec[1][0] += period;
382  fcu->bezt[1].vec[2][0] += period;
383 
384  /* Add the cycles modifier. */
385  if (!fcu->modifiers.first) {
387  }
388 }
389 
390 /* -------------- BezTriple Insertion -------------------- */
391 
392 /* Change the Y position of a keyframe to match the input, adjusting handles. */
393 static void replace_bezt_keyframe_ypos(BezTriple *dst, const BezTriple *bezt)
394 {
395  /* just change the values when replacing, so as to not overwrite handles */
396  float dy = bezt->vec[1][1] - dst->vec[1][1];
397 
398  /* just apply delta value change to the handle values */
399  dst->vec[0][1] += dy;
400  dst->vec[1][1] += dy;
401  dst->vec[2][1] += dy;
402 
403  dst->f1 = bezt->f1;
404  dst->f2 = bezt->f2;
405  dst->f3 = bezt->f3;
406 
407  /* TODO: perform some other operations? */
408 }
409 
411 {
412  int i = 0;
413 
414  /* are there already keyframes? */
415  if (fcu->bezt) {
416  bool replace;
417  i = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, bezt->vec[1][0], fcu->totvert, &replace);
418 
419  /* replace an existing keyframe? */
420  if (replace) {
421  /* sanity check: 'i' may in rare cases exceed arraylen */
422  if ((i >= 0) && (i < fcu->totvert)) {
423  if (flag & INSERTKEY_OVERWRITE_FULL) {
424  fcu->bezt[i] = *bezt;
425  }
426  else {
427  replace_bezt_keyframe_ypos(&fcu->bezt[i], bezt);
428  }
429 
430  if (flag & INSERTKEY_CYCLE_AWARE) {
431  /* If replacing an end point of a cyclic curve without offset,
432  * modify the other end too. */
433  if (ELEM(i, 0, fcu->totvert - 1) &&
435  replace_bezt_keyframe_ypos(&fcu->bezt[i == 0 ? fcu->totvert - 1 : 0], bezt);
436  }
437  }
438  }
439  }
440  /* Keyframing modes allow not replacing the keyframe. */
441  else if ((flag & INSERTKEY_REPLACE) == 0) {
442  /* insert new - if we're not restricted to replacing keyframes only */
443  BezTriple *newb = MEM_callocN((fcu->totvert + 1) * sizeof(BezTriple), "beztriple");
444 
445  /* Add the beztriples that should occur before the beztriple to be pasted
446  * (originally in fcu). */
447  if (i > 0) {
448  memcpy(newb, fcu->bezt, i * sizeof(BezTriple));
449  }
450 
451  /* add beztriple to paste at index i */
452  *(newb + i) = *bezt;
453 
454  /* add the beztriples that occur after the beztriple to be pasted (originally in fcu) */
455  if (i < fcu->totvert) {
456  memcpy(newb + i + 1, fcu->bezt + i, (fcu->totvert - i) * sizeof(BezTriple));
457  }
458 
459  /* replace (+ free) old with new, only if necessary to do so */
460  MEM_freeN(fcu->bezt);
461  fcu->bezt = newb;
462 
463  fcu->totvert++;
464  }
465  else {
466  return -1;
467  }
468  }
469  /* no keyframes already, but can only add if...
470  * 1) keyframing modes say that keyframes can only be replaced, so adding new ones won't know
471  * 2) there are no samples on the curve
472  * NOTE: maybe we may want to allow this later when doing samples -> bezt conversions,
473  * but for now, having both is asking for trouble
474  */
475  else if ((flag & INSERTKEY_REPLACE) == 0 && (fcu->fpt == NULL)) {
476  /* create new keyframes array */
477  fcu->bezt = MEM_callocN(sizeof(BezTriple), "beztriple");
478  *(fcu->bezt) = *bezt;
479  fcu->totvert = 1;
480  }
481  /* cannot add anything */
482  else {
483  /* return error code -1 to prevent any misunderstandings */
484  return -1;
485  }
486 
487  /* we need to return the index, so that some tools which do post-processing can
488  * detect where we added the BezTriple in the array
489  */
490  return i;
491 }
492 
503 static void subdivide_nonauto_handles(const FCurve *fcu,
504  BezTriple *bezt,
505  BezTriple *prev,
506  BezTriple *next)
507 {
508  if (prev->ipo != BEZT_IPO_BEZ || bezt->ipo != BEZT_IPO_BEZ) {
509  return;
510  }
511 
512  /* Don't change Vector handles, or completely auto regions. */
513  const bool bezt_auto = BEZT_IS_AUTOH(bezt) || (bezt->h1 == HD_VECT && bezt->h2 == HD_VECT);
514  const bool prev_auto = BEZT_IS_AUTOH(prev) || (prev->h2 == HD_VECT);
515  const bool next_auto = BEZT_IS_AUTOH(next) || (next->h1 == HD_VECT);
516  if (bezt_auto && prev_auto && next_auto) {
517  return;
518  }
519 
520  /* Subdivide the curve. */
521  float delta;
522  if (!BKE_fcurve_bezt_subdivide_handles(bezt, prev, next, &delta)) {
523  return;
524  }
525 
526  /* Decide when to force auto to manual. */
527  if (!BEZT_IS_AUTOH(bezt)) {
528  return;
529  }
530  if ((prev_auto || next_auto) && fcu->auto_smoothing == FCURVE_SMOOTH_CONT_ACCEL) {
531  const float hx = bezt->vec[1][0] - bezt->vec[0][0];
532  const float dx = bezt->vec[1][0] - prev->vec[1][0];
533 
534  /* This mode always uses 1/3 of key distance for handle x size. */
535  const bool auto_works_well = fabsf(hx - dx / 3.0f) < 0.001f;
536  if (auto_works_well) {
537  return;
538  }
539  }
540 
541  /* Turn off auto mode. */
542  bezt->h1 = bezt->h2 = HD_ALIGN;
543 }
544 
546  FCurve *fcu, float x, float y, eBezTriple_KeyframeType keyframe_type, eInsertKeyFlags flag)
547 {
548  BezTriple beztr = {{{0}}};
549  uint oldTot = fcu->totvert;
550  int a;
551 
552  /* set all three points, for nicer start position
553  * NOTE: +/- 1 on vec.x for left and right handles is so that 'free' handles work ok...
554  */
555  beztr.vec[0][0] = x - 1.0f;
556  beztr.vec[0][1] = y;
557  beztr.vec[1][0] = x;
558  beztr.vec[1][1] = y;
559  beztr.vec[2][0] = x + 1.0f;
560  beztr.vec[2][1] = y;
561  beztr.f1 = beztr.f2 = beztr.f3 = SELECT;
562 
563  /* set default handle types and interpolation mode */
564  if (flag & INSERTKEY_NO_USERPREF) {
565  /* for Py-API, we want scripts to have predictable behavior,
566  * hence the option to not depend on the userpref defaults
567  */
568  beztr.h1 = beztr.h2 = HD_AUTO_ANIM;
569  beztr.ipo = BEZT_IPO_BEZ;
570  }
571  else {
572  /* For UI usage - defaults should come from the user-preferences and/or tool-settings. */
573  beztr.h1 = beztr.h2 = U.keyhandles_new; /* use default handle type here */
574 
575  /* use default interpolation mode, with exceptions for int/discrete values */
576  beztr.ipo = U.ipo_new;
577  }
578 
579  /* interpolation type used is constrained by the type of values the curve can take */
580  if (fcu->flag & FCURVE_DISCRETE_VALUES) {
581  beztr.ipo = BEZT_IPO_CONST;
582  }
583  else if ((beztr.ipo == BEZT_IPO_BEZ) && (fcu->flag & FCURVE_INT_VALUES)) {
584  beztr.ipo = BEZT_IPO_LIN;
585  }
586 
587  /* set keyframe type value (supplied), which should come from the scene settings in most cases */
588  BEZKEYTYPE(&beztr) = keyframe_type;
589 
590  /* set default values for "easing" interpolation mode settings
591  * NOTE: Even if these modes aren't currently used, if users switch
592  * to these later, we want these to work in a sane way out of
593  * the box.
594  */
595 
596  /* "back" easing - this value used to be used when overshoot=0, but that
597  * introduced discontinuities in how the param worked. */
598  beztr.back = 1.70158f;
599 
600  /* "elastic" easing - values here were hand-optimized for a default duration of
601  * ~10 frames (typical mograph motion length) */
602  beztr.amplitude = 0.8f;
603  beztr.period = 4.1f;
604 
605  /* add temp beztriple to keyframes */
606  a = insert_bezt_fcurve(fcu, &beztr, flag);
608 
609  /* what if 'a' is a negative index?
610  * for now, just exit to prevent any segfaults
611  */
612  if (a < 0) {
613  return -1;
614  }
615 
616  /* Set handle-type and interpolation. */
617  if ((fcu->totvert > 2) && (flag & INSERTKEY_REPLACE) == 0) {
618  BezTriple *bezt = (fcu->bezt + a);
619 
620  /* Set interpolation from previous (if available),
621  * but only if we didn't just replace some keyframe:
622  * - Replacement is indicated by no-change in number of verts.
623  * - When replacing, the user may have specified some interpolation that should be kept.
624  */
625  if (fcu->totvert > oldTot) {
626  if (a > 0) {
627  bezt->ipo = (bezt - 1)->ipo;
628  }
629  else if (a < fcu->totvert - 1) {
630  bezt->ipo = (bezt + 1)->ipo;
631  }
632 
633  if (0 < a && a < (fcu->totvert - 1) && (flag & INSERTKEY_OVERWRITE_FULL) == 0) {
634  subdivide_nonauto_handles(fcu, bezt, bezt - 1, bezt + 1);
635  }
636  }
637  }
638 
639  /* don't recalculate handles if fast is set
640  * - this is a hack to make importers faster
641  * - we may calculate twice (due to auto-handle needing to be calculated twice)
642  */
643  if ((flag & INSERTKEY_FAST) == 0) {
645  }
646 
647  /* return the index at which the keyframe was added */
648  return a;
649 }
650 
651 /* -------------- 'Smarter' Keyframing Functions -------------------- */
652 /* return codes for new_key_needed */
653 enum {
658 } /*eKeyNeededStatus*/;
659 
668 static short new_key_needed(FCurve *fcu, float cFrame, float nValue)
669 {
670  /* safety checking */
671  if (fcu == NULL) {
672  return KEYNEEDED_JUSTADD;
673  }
674  int totCount = fcu->totvert;
675  if (totCount == 0) {
676  return KEYNEEDED_JUSTADD;
677  }
678 
679  /* loop through checking if any are the same */
680  BezTriple *bezt = fcu->bezt;
681  BezTriple *prev = NULL;
682  for (int i = 0; i < totCount; i++) {
683  float prevPosi = 0.0f, prevVal = 0.0f;
684  float beztPosi = 0.0f, beztVal = 0.0f;
685 
686  /* get current time+value */
687  beztPosi = bezt->vec[1][0];
688  beztVal = bezt->vec[1][1];
689 
690  if (prev) {
691  /* there is a keyframe before the one currently being examined */
692 
693  /* get previous time+value */
694  prevPosi = prev->vec[1][0];
695  prevVal = prev->vec[1][1];
696 
697  /* keyframe to be added at point where there are already two similar points? */
698  if (IS_EQF(prevPosi, cFrame) && IS_EQF(beztPosi, cFrame) && IS_EQF(beztPosi, prevPosi)) {
699  return KEYNEEDED_DONTADD;
700  }
701 
702  /* keyframe between prev+current points ? */
703  if ((prevPosi <= cFrame) && (cFrame <= beztPosi)) {
704  /* is the value of keyframe to be added the same as keyframes on either side ? */
705  if (IS_EQF(prevVal, nValue) && IS_EQF(beztVal, nValue) && IS_EQF(prevVal, beztVal)) {
706  return KEYNEEDED_DONTADD;
707  }
708 
709  float realVal;
710 
711  /* get real value of curve at that point */
712  realVal = evaluate_fcurve(fcu, cFrame);
713 
714  /* compare whether it's the same as proposed */
715  if (IS_EQF(realVal, nValue)) {
716  return KEYNEEDED_DONTADD;
717  }
718  return KEYNEEDED_JUSTADD;
719  }
720 
721  /* new keyframe before prev beztriple? */
722  if (cFrame < prevPosi) {
723  /* A new keyframe will be added. However, whether the previous beztriple
724  * stays around or not depends on whether the values of previous/current
725  * beztriples and new keyframe are the same.
726  */
727  if (IS_EQF(prevVal, nValue) && IS_EQF(beztVal, nValue) && IS_EQF(prevVal, beztVal)) {
728  return KEYNEEDED_DELNEXT;
729  }
730 
731  return KEYNEEDED_JUSTADD;
732  }
733  }
734  else {
735  /* just add a keyframe if there's only one keyframe
736  * and the new one occurs before the existing one does.
737  */
738  if ((cFrame < beztPosi) && (totCount == 1)) {
739  return KEYNEEDED_JUSTADD;
740  }
741  }
742 
743  /* continue. frame to do not yet passed (or other conditions not met) */
744  if (i < (totCount - 1)) {
745  prev = bezt;
746  bezt++;
747  }
748  else {
749  break;
750  }
751  }
752 
753  /* Frame in which to add a new-keyframe occurs after all other keys
754  * -> If there are at least two existing keyframes, then if the values of the
755  * last two keyframes and the new-keyframe match, the last existing keyframe
756  * gets deleted as it is no longer required.
757  * -> Otherwise, a keyframe is just added. 1.0 is added so that fake-2nd-to-last
758  * keyframe is not equal to last keyframe.
759  */
760  bezt = (fcu->bezt + (fcu->totvert - 1));
761  float valA = bezt->vec[1][1];
762  float valB;
763  if (prev) {
764  valB = prev->vec[1][1];
765  }
766  else {
767  valB = bezt->vec[1][1] + 1.0f;
768  }
769 
770  if (IS_EQF(valA, nValue) && IS_EQF(valA, valB)) {
771  return KEYNEEDED_DELPREV;
772  }
773 
774  return KEYNEEDED_JUSTADD;
775 }
776 
777 /* ------------------ RNA Data-Access Functions ------------------ */
778 
781  PointerRNA *ptr, PropertyRNA *prop, float *buffer, int buffer_size, int *r_count)
782 {
783  BLI_assert(buffer_size >= 1);
784 
785  float *values = buffer;
786 
787  if (RNA_property_array_check(prop)) {
788  int length = *r_count = RNA_property_array_length(ptr, prop);
789  bool *tmp_bool;
790  int *tmp_int;
791 
792  if (length > buffer_size) {
793  values = MEM_malloc_arrayN(length, sizeof(float), __func__);
794  }
795 
796  switch (RNA_property_type(prop)) {
797  case PROP_BOOLEAN:
798  tmp_bool = MEM_malloc_arrayN(length, sizeof(*tmp_bool), __func__);
799  RNA_property_boolean_get_array(ptr, prop, tmp_bool);
800  for (int i = 0; i < length; i++) {
801  values[i] = (float)tmp_bool[i];
802  }
803  MEM_freeN(tmp_bool);
804  break;
805  case PROP_INT:
806  tmp_int = MEM_malloc_arrayN(length, sizeof(*tmp_int), __func__);
807  RNA_property_int_get_array(ptr, prop, tmp_int);
808  for (int i = 0; i < length; i++) {
809  values[i] = (float)tmp_int[i];
810  }
811  MEM_freeN(tmp_int);
812  break;
813  case PROP_FLOAT:
814  RNA_property_float_get_array(ptr, prop, values);
815  break;
816  default:
817  memset(values, 0, sizeof(float) * length);
818  }
819  }
820  else {
821  *r_count = 1;
822 
823  switch (RNA_property_type(prop)) {
824  case PROP_BOOLEAN:
825  *values = (float)RNA_property_boolean_get(ptr, prop);
826  break;
827  case PROP_INT:
828  *values = (float)RNA_property_int_get(ptr, prop);
829  break;
830  case PROP_FLOAT:
831  *values = RNA_property_float_get(ptr, prop);
832  break;
833  case PROP_ENUM:
834  *values = (float)RNA_property_enum_get(ptr, prop);
835  break;
836  default:
837  *values = 0.0f;
838  }
839  }
840 
841  return values;
842 }
843 
844 /* ------------------ 'Visual' Keyframing Functions ------------------ */
845 
846 /* internal status codes for visualkey_can_use */
847 enum {
852 };
853 
862 {
863  bConstraint *con = NULL;
864  short searchtype = VISUALKEY_NONE;
865  bool has_rigidbody = false;
866  bool has_parent = false;
867  const char *identifier = NULL;
868 
869  /* validate data */
870  if (ELEM(NULL, ptr, ptr->data, prop)) {
871  return false;
872  }
873 
874  /* get first constraint and determine type of keyframe constraints to check for
875  * - constraints can be on either Objects or PoseChannels, so we only check if the
876  * ptr->type is RNA_Object or RNA_PoseBone, which are the RNA wrapping-info for
877  * those structs, allowing us to identify the owner of the data
878  */
879  if (ptr->type == &RNA_Object) {
880  /* Object */
881  Object *ob = ptr->data;
882  RigidBodyOb *rbo = ob->rigidbody_object;
883 
884  con = ob->constraints.first;
885  identifier = RNA_property_identifier(prop);
886  has_parent = (ob->parent != NULL);
887 
888  /* active rigidbody objects only, as only those are affected by sim */
889  has_rigidbody = ((rbo) && (rbo->type == RBO_TYPE_ACTIVE));
890  }
891  else if (ptr->type == &RNA_PoseBone) {
892  /* Pose Channel */
893  bPoseChannel *pchan = ptr->data;
894 
895  con = pchan->constraints.first;
896  identifier = RNA_property_identifier(prop);
897  has_parent = (pchan->parent != NULL);
898  }
899 
900  /* check if any data to search using */
901  if (ELEM(NULL, con, identifier) && (has_parent == false) && (has_rigidbody == false)) {
902  return false;
903  }
904 
905  /* location or rotation identifiers only... */
906  if (identifier == NULL) {
907  printf("%s failed: NULL identifier\n", __func__);
908  return false;
909  }
910 
911  if (strstr(identifier, "location")) {
912  searchtype = VISUALKEY_LOC;
913  }
914  else if (strstr(identifier, "rotation")) {
915  searchtype = VISUALKEY_ROT;
916  }
917  else if (strstr(identifier, "scale")) {
918  searchtype = VISUALKEY_SCA;
919  }
920  else {
921  printf("%s failed: identifier - '%s'\n", __func__, identifier);
922  return false;
923  }
924 
925  /* only search if a searchtype and initial constraint are available */
926  if (searchtype) {
927  /* parent or rigidbody are always matching */
928  if (has_parent || has_rigidbody) {
929  return true;
930  }
931 
932  /* constraints */
933  for (; con; con = con->next) {
934  /* only consider constraint if it is not disabled, and has influence */
935  if (con->flag & CONSTRAINT_DISABLE) {
936  continue;
937  }
938  if (con->enforce == 0.0f) {
939  continue;
940  }
941 
942  /* some constraints may alter these transforms */
943  switch (con->type) {
944  /* multi-transform constraints */
947  return true;
950  return true;
952  return true;
954  return true;
955 
956  /* Single-transform constraints. */
958  if (searchtype == VISUALKEY_ROT) {
959  return true;
960  }
961  break;
963  if (searchtype == VISUALKEY_ROT) {
964  return true;
965  }
966  break;
968  if (searchtype == VISUALKEY_ROT) {
969  return true;
970  }
971  break;
973  if (searchtype == VISUALKEY_LOC) {
974  return true;
975  }
976  break;
978  if (searchtype == VISUALKEY_SCA) {
979  return true;
980  }
981  break;
983  if (searchtype == VISUALKEY_LOC) {
984  return true;
985  }
986  break;
988  if (searchtype == VISUALKEY_ROT) {
989  return true;
990  }
991  break;
993  if (searchtype == VISUALKEY_LOC) {
994  return true;
995  }
996  break;
998  if (searchtype == VISUALKEY_SCA) {
999  return true;
1000  }
1001  break;
1003  if (searchtype == VISUALKEY_ROT) {
1004  return true;
1005  }
1006  break;
1008  if (searchtype == VISUALKEY_LOC) {
1009  return true;
1010  }
1011  break;
1012 
1013  default:
1014  break;
1015  }
1016  }
1017  }
1018 
1019  /* when some condition is met, this function returns, so that means we've got nothing */
1020  return false;
1021 }
1022 
1028 static float *visualkey_get_values(
1029  PointerRNA *ptr, PropertyRNA *prop, float *buffer, int buffer_size, int *r_count)
1030 {
1031  BLI_assert(buffer_size >= 4);
1032 
1033  const char *identifier = RNA_property_identifier(prop);
1034  float tmat[4][4];
1035  int rotmode;
1036 
1037  /* handle for Objects or PoseChannels only
1038  * - only Location, Rotation or Scale keyframes are supported currently
1039  * - constraints can be on either Objects or PoseChannels, so we only check if the
1040  * ptr->type is RNA_Object or RNA_PoseBone, which are the RNA wrapping-info for
1041  * those structs, allowing us to identify the owner of the data
1042  * - assume that array_index will be sane
1043  */
1044  if (ptr->type == &RNA_Object) {
1045  Object *ob = ptr->data;
1046  /* Loc code is specific... */
1047  if (strstr(identifier, "location")) {
1048  copy_v3_v3(buffer, ob->obmat[3]);
1049  *r_count = 3;
1050  return buffer;
1051  }
1052 
1053  copy_m4_m4(tmat, ob->obmat);
1054  rotmode = ob->rotmode;
1055  }
1056  else if (ptr->type == &RNA_PoseBone) {
1057  bPoseChannel *pchan = ptr->data;
1058 
1059  BKE_armature_mat_pose_to_bone(pchan, pchan->pose_mat, tmat);
1060  rotmode = pchan->rotmode;
1061 
1062  /* Loc code is specific... */
1063  if (strstr(identifier, "location")) {
1064  /* only use for non-connected bones */
1065  if ((pchan->bone->parent == NULL) || !(pchan->bone->flag & BONE_CONNECTED)) {
1066  copy_v3_v3(buffer, tmat[3]);
1067  *r_count = 3;
1068  return buffer;
1069  }
1070  }
1071  }
1072  else {
1073  return setting_get_rna_values(ptr, prop, buffer, buffer_size, r_count);
1074  }
1075 
1076  /* Rot/Scale code are common! */
1077  if (strstr(identifier, "rotation_euler")) {
1078  mat4_to_eulO(buffer, rotmode, tmat);
1079 
1080  *r_count = 3;
1081  return buffer;
1082  }
1083 
1084  if (strstr(identifier, "rotation_quaternion")) {
1085  float mat3[3][3];
1086 
1087  copy_m3_m4(mat3, tmat);
1088  mat3_to_quat_is_ok(buffer, mat3);
1089 
1090  *r_count = 4;
1091  return buffer;
1092  }
1093 
1094  if (strstr(identifier, "rotation_axis_angle")) {
1095  /* w = 0, x,y,z = 1,2,3 */
1096  mat4_to_axis_angle(buffer + 1, buffer, tmat);
1097 
1098  *r_count = 4;
1099  return buffer;
1100  }
1101 
1102  if (strstr(identifier, "scale")) {
1103  mat4_to_size(buffer, tmat);
1104 
1105  *r_count = 3;
1106  return buffer;
1107  }
1108 
1109  /* as the function hasn't returned yet, read value from system in the default way */
1110  return setting_get_rna_values(ptr, prop, buffer, buffer_size, r_count);
1111 }
1112 
1113 /* ------------------------- Insert Key API ------------------------- */
1114 
1115 /* Check indices that were intended to be remapped and report any failed remaps. */
1117  PointerRNA ptr,
1118  PropertyRNA *prop,
1119  const int index,
1120  const int count,
1121  const bool force_all,
1122  const BLI_bitmap *successful_remaps)
1123 {
1124 
1125  DynStr *ds_failed_indices = BLI_dynstr_new();
1126 
1127  int total_failed = 0;
1128  for (int i = 0; i < count; i++) {
1129  const bool cur_index_evaluated = ELEM(index, i, -1) || force_all;
1130  if (!cur_index_evaluated) {
1131  /* `values[i]` was never intended to be remapped. */
1132  continue;
1133  }
1134 
1135  if (BLI_BITMAP_TEST_BOOL(successful_remaps, i)) {
1136  /* `values[i]` successfully remapped. */
1137  continue;
1138  }
1139 
1140  total_failed++;
1141  /* Report that `values[i]` were intended to be remapped but failed remapping process. */
1142  BLI_dynstr_appendf(ds_failed_indices, "%d, ", i);
1143  }
1144 
1145  if (total_failed == 0) {
1146  BLI_dynstr_free(ds_failed_indices);
1147  return;
1148  }
1149 
1150  char *str_failed_indices = BLI_dynstr_get_cstring(ds_failed_indices);
1151  BLI_dynstr_free(ds_failed_indices);
1152 
1153  BKE_reportf(reports,
1154  RPT_WARNING,
1155  "Could not insert %i keyframe(s) due to zero NLA influence, base value, or value "
1156  "remapping failed: %s.%s for indices [%s]",
1157  total_failed,
1158  ptr.owner_id->name,
1159  RNA_property_ui_name(prop),
1160  str_failed_indices);
1161 
1162  MEM_freeN(str_failed_indices);
1163 }
1164 
1172 static float *get_keyframe_values(ReportList *reports,
1173  PointerRNA ptr,
1174  PropertyRNA *prop,
1175  int index,
1176  struct NlaKeyframingContext *nla_context,
1177  eInsertKeyFlags flag,
1178  float *buffer,
1179  int buffer_size,
1180  const struct AnimationEvalContext *anim_eval_context,
1181  int *r_count,
1182  bool *r_force_all,
1183  BLI_bitmap **r_successful_remaps)
1184 {
1185  float *values;
1186 
1187  if ((flag & INSERTKEY_MATRIX) && (visualkey_can_use(&ptr, prop))) {
1188  /* visual-keying is only available for object and pchan datablocks, as
1189  * it works by keyframing using a value extracted from the final matrix
1190  * instead of using the kt system to extract a value.
1191  */
1192  values = visualkey_get_values(&ptr, prop, buffer, buffer_size, r_count);
1193  }
1194  else {
1195  /* read value from system */
1196  values = setting_get_rna_values(&ptr, prop, buffer, buffer_size, r_count);
1197  }
1198 
1199  *r_successful_remaps = BLI_BITMAP_NEW(*r_count, __func__);
1200 
1201  /* adjust the value for NLA factors */
1203  &ptr,
1204  prop,
1205  values,
1206  *r_count,
1207  index,
1208  anim_eval_context,
1209  r_force_all,
1210  *r_successful_remaps);
1212  ptr,
1213  prop,
1214  index,
1215  *r_count,
1216  r_force_all ? *r_force_all : false,
1217  *r_successful_remaps);
1218 
1219  return values;
1220 }
1221 
1222 /* Insert the specified keyframe value into a single F-Curve. */
1223 static bool insert_keyframe_value(ReportList *reports,
1224  PointerRNA *ptr,
1225  PropertyRNA *prop,
1226  FCurve *fcu,
1227  const AnimationEvalContext *anim_eval_context,
1228  float curval,
1229  eBezTriple_KeyframeType keytype,
1230  eInsertKeyFlags flag)
1231 {
1232  /* F-Curve not editable? */
1233  if (BKE_fcurve_is_keyframable(fcu) == 0) {
1234  BKE_reportf(
1235  reports,
1236  RPT_ERROR,
1237  "F-Curve with path '%s[%d]' cannot be keyframed, ensure that it is not locked or sampled, "
1238  "and try removing F-Modifiers",
1239  fcu->rna_path,
1240  fcu->array_index);
1241  return false;
1242  }
1243 
1244  float cfra = anim_eval_context->eval_time;
1245 
1246  /* adjust frame on which to add keyframe */
1247  if ((flag & INSERTKEY_DRIVER) && (fcu->driver)) {
1248  PathResolvedRNA anim_rna;
1249 
1250  if (RNA_path_resolved_create(ptr, prop, fcu->array_index, &anim_rna)) {
1251  /* for making it easier to add corrective drivers... */
1252  cfra = evaluate_driver(&anim_rna, fcu->driver, fcu->driver, anim_eval_context);
1253  }
1254  else {
1255  cfra = 0.0f;
1256  }
1257  }
1258 
1259  /* adjust coordinates for cycle aware insertion */
1260  if (flag & INSERTKEY_CYCLE_AWARE) {
1261  if (remap_cyclic_keyframe_location(fcu, &cfra, &curval) != FCU_CYCLE_PERFECT) {
1262  /* inhibit action from insert_vert_fcurve unless it's a perfect cycle */
1263  flag &= ~INSERTKEY_CYCLE_AWARE;
1264  }
1265  }
1266 
1267  /* only insert keyframes where they are needed */
1268  if (flag & INSERTKEY_NEEDED) {
1269  short insert_mode;
1270 
1271  /* check whether this curve really needs a new keyframe */
1272  insert_mode = new_key_needed(fcu, cfra, curval);
1273 
1274  /* only return success if keyframe added */
1275  if (insert_mode == KEYNEEDED_DONTADD) {
1276  return false;
1277  }
1278 
1279  /* insert new keyframe at current frame */
1280  if (insert_vert_fcurve(fcu, cfra, curval, keytype, flag) < 0) {
1281  return false;
1282  }
1283 
1284  /* delete keyframe immediately before/after newly added */
1285  switch (insert_mode) {
1286  case KEYNEEDED_DELPREV:
1287  BKE_fcurve_delete_key(fcu, fcu->totvert - 2);
1289  break;
1290  case KEYNEEDED_DELNEXT:
1291  BKE_fcurve_delete_key(fcu, 1);
1293  break;
1294  }
1295 
1296  return true;
1297  }
1298 
1299  /* just insert keyframe */
1300  return insert_vert_fcurve(fcu, cfra, curval, keytype, flag) >= 0;
1301 }
1302 
1304  PointerRNA ptr,
1305  PropertyRNA *prop,
1306  FCurve *fcu,
1307  const AnimationEvalContext *anim_eval_context,
1308  eBezTriple_KeyframeType keytype,
1309  struct NlaKeyframingContext *nla_context,
1310  eInsertKeyFlags flag)
1311 {
1312  float curval = 0.0f;
1313 
1314  /* no F-Curve to add keyframe to? */
1315  if (fcu == NULL) {
1316  BKE_report(reports, RPT_ERROR, "No F-Curve to add keyframes to");
1317  return false;
1318  }
1319 
1320  /* if no property given yet, try to validate from F-Curve info */
1321  if ((ptr.owner_id == NULL) && (ptr.data == NULL)) {
1322  BKE_report(
1323  reports, RPT_ERROR, "No RNA pointer available to retrieve values for keyframing from");
1324  return false;
1325  }
1326  if (prop == NULL) {
1327  PointerRNA tmp_ptr;
1328 
1329  /* try to get property we should be affecting */
1330  if (RNA_path_resolve_property(&ptr, fcu->rna_path, &tmp_ptr, &prop) == false) {
1331  /* property not found... */
1332  const char *idname = (ptr.owner_id) ? ptr.owner_id->name : TIP_("<No ID pointer>");
1333 
1334  BKE_reportf(reports,
1335  RPT_ERROR,
1336  "Could not insert keyframe, as RNA path is invalid for the given ID (ID = %s, "
1337  "path = %s)",
1338  idname,
1339  fcu->rna_path);
1340  return false;
1341  }
1342 
1343  /* property found, so overwrite 'ptr' to make later code easier */
1344  ptr = tmp_ptr;
1345  }
1346 
1347  /* update F-Curve flags to ensure proper behavior for property type */
1348  update_autoflags_fcurve_direct(fcu, prop);
1349 
1350  /* Obtain the value to insert. */
1351  float value_buffer[RNA_MAX_ARRAY_LENGTH];
1352  int value_count;
1353  int index = fcu->array_index;
1354 
1355  BLI_bitmap *successful_remaps = NULL;
1356  float *values = get_keyframe_values(reports,
1357  ptr,
1358  prop,
1359  index,
1360  nla_context,
1361  flag,
1362  value_buffer,
1364  anim_eval_context,
1365  &value_count,
1366  NULL,
1367  &successful_remaps);
1368 
1369  if (index >= 0 && index < value_count) {
1370  curval = values[index];
1371  }
1372 
1373  if (values != value_buffer) {
1374  MEM_freeN(values);
1375  }
1376 
1377  const bool curval_valid = BLI_BITMAP_TEST_BOOL(successful_remaps, index);
1378  MEM_freeN(successful_remaps);
1379 
1380  /* This happens if NLA rejects this insertion. */
1381  if (!curval_valid) {
1382  return false;
1383  }
1384 
1385  return insert_keyframe_value(reports, &ptr, prop, fcu, anim_eval_context, curval, keytype, flag);
1386 }
1387 
1390  ReportList *reports,
1391  PointerRNA *ptr,
1392  PropertyRNA *prop,
1393  bAction *act,
1394  const char group[],
1395  const char rna_path[],
1396  int array_index,
1397  const AnimationEvalContext *anim_eval_context,
1398  float curval,
1399  eBezTriple_KeyframeType keytype,
1400  eInsertKeyFlags flag)
1401 {
1402  /* make sure the F-Curve exists
1403  * - if we're replacing keyframes only, DO NOT create new F-Curves if they do not exist yet
1404  * but still try to get the F-Curve if it exists...
1405  */
1406  bool can_create_curve = (flag & (INSERTKEY_REPLACE | INSERTKEY_AVAILABLE)) == 0;
1407  FCurve *fcu = can_create_curve ?
1408  ED_action_fcurve_ensure(bmain, act, group, ptr, rna_path, array_index) :
1409  ED_action_fcurve_find(act, rna_path, array_index);
1410 
1411  /* we may not have a F-Curve when we're replacing only... */
1412  if (fcu) {
1413  const bool is_new_curve = (fcu->totvert == 0);
1414 
1415  /* set color mode if the F-Curve is new (i.e. without any keyframes) */
1416  if (is_new_curve && (flag & INSERTKEY_XYZ2RGB)) {
1417  /* for Loc/Rot/Scale and also Color F-Curves, the color of the F-Curve in the Graph Editor,
1418  * is determined by the array index for the F-Curve
1419  */
1420  PropertySubType prop_subtype = RNA_property_subtype(prop);
1423  }
1424  else if (ELEM(prop_subtype, PROP_QUATERNION)) {
1426  }
1427  }
1428 
1429  /* If the curve has only one key, make it cyclic if appropriate. */
1430  const bool is_cyclic_action = (flag & INSERTKEY_CYCLE_AWARE) && BKE_action_is_cyclic(act);
1431 
1432  if (is_cyclic_action && fcu->totvert == 1) {
1433  make_new_fcurve_cyclic(act, fcu);
1434  }
1435 
1436  /* update F-Curve flags to ensure proper behavior for property type */
1437  update_autoflags_fcurve_direct(fcu, prop);
1438 
1439  /* insert keyframe */
1440  const bool success = insert_keyframe_value(
1441  reports, ptr, prop, fcu, anim_eval_context, curval, keytype, flag);
1442 
1443  /* If the curve is new, make it cyclic if appropriate. */
1444  if (is_cyclic_action && is_new_curve) {
1445  make_new_fcurve_cyclic(act, fcu);
1446  }
1447 
1448  return success;
1449  }
1450 
1451  return false;
1452 }
1453 
1455  PointerRNA *id_ptr,
1456  AnimData *adt,
1457  bAction *act,
1458  ListBase *nla_cache,
1459  NlaKeyframingContext **r_nla_context)
1460 {
1461  if (adt && adt->action == act) {
1462  /* Get NLA context for value remapping. */
1463  *r_nla_context = BKE_animsys_get_nla_keyframing_context(
1464  nla_cache, id_ptr, adt, anim_eval_context);
1465 
1466  /* Apply NLA-mapping to frame. */
1467  const float remapped_frame = BKE_nla_tweakedit_remap(
1468  adt, anim_eval_context->eval_time, NLATIME_CONVERT_UNMAP);
1469  return BKE_animsys_eval_context_construct_at(anim_eval_context, remapped_frame);
1470  }
1471 
1472  *r_nla_context = NULL;
1473  return *anim_eval_context;
1474 }
1475 
1477  ReportList *reports,
1478  ID *id,
1479  bAction *act,
1480  const char group[],
1481  const char rna_path[],
1482  int array_index,
1483  const AnimationEvalContext *anim_eval_context,
1484  eBezTriple_KeyframeType keytype,
1485  ListBase *nla_cache,
1486  eInsertKeyFlags flag)
1487 {
1488  PointerRNA id_ptr, ptr;
1489  PropertyRNA *prop = NULL;
1490  AnimData *adt;
1491  ListBase tmp_nla_cache = {NULL, NULL};
1492  NlaKeyframingContext *nla_context = NULL;
1493  int ret = 0;
1494 
1495  /* validate pointer first - exit if failure */
1496  if (id == NULL) {
1497  BKE_reportf(reports, RPT_ERROR, "No ID block to insert keyframe in (path = %s)", rna_path);
1498  return 0;
1499  }
1500 
1501  if (!BKE_id_is_editable(bmain, id)) {
1502  BKE_reportf(reports, RPT_ERROR, "'%s' on %s is not editable", rna_path, id->name + 2);
1503  return 0;
1504  }
1505 
1506  RNA_id_pointer_create(id, &id_ptr);
1507  if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
1508  BKE_reportf(
1509  reports,
1510  RPT_ERROR,
1511  "Could not insert keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)",
1512  (id) ? id->name : TIP_("<Missing ID block>"),
1513  rna_path);
1514  return 0;
1515  }
1516 
1517  /* if no action is provided, keyframe to the default one attached to this ID-block */
1518  if (act == NULL) {
1519  /* get action to add F-Curve+keyframe to */
1520  act = ED_id_action_ensure(bmain, id);
1521 
1522  if (act == NULL) {
1523  BKE_reportf(reports,
1524  RPT_ERROR,
1525  "Could not insert keyframe, as this type does not support animation data (ID = "
1526  "%s, path = %s)",
1527  id->name,
1528  rna_path);
1529  return 0;
1530  }
1531  }
1532 
1533  /* apply NLA-mapping to frame to use (if applicable) */
1534  adt = BKE_animdata_from_id(id);
1535  const AnimationEvalContext remapped_context = nla_time_remap(
1536  anim_eval_context, &id_ptr, adt, act, nla_cache ? nla_cache : &tmp_nla_cache, &nla_context);
1537 
1538  /* Obtain values to insert. */
1539  float value_buffer[RNA_MAX_ARRAY_LENGTH];
1540  int value_count;
1541  bool force_all;
1542 
1543  BLI_bitmap *successful_remaps = NULL;
1544  float *values = get_keyframe_values(reports,
1545  ptr,
1546  prop,
1547  array_index,
1548  nla_context,
1549  flag,
1550  value_buffer,
1552  anim_eval_context,
1553  &value_count,
1554  &force_all,
1555  &successful_remaps);
1556 
1557  /* Key the entire array. */
1558  if (array_index == -1 || force_all) {
1559  /* In force mode, if any of the curves succeeds, drop the replace mode and restart. */
1560  if (force_all && (flag & (INSERTKEY_REPLACE | INSERTKEY_AVAILABLE)) != 0) {
1561  int exclude = -1;
1562 
1563  for (array_index = 0; array_index < value_count; array_index++) {
1564  if (!BLI_BITMAP_TEST_BOOL(successful_remaps, array_index)) {
1565  continue;
1566  }
1567 
1568  if (insert_keyframe_fcurve_value(bmain,
1569  reports,
1570  &ptr,
1571  prop,
1572  act,
1573  group,
1574  rna_path,
1575  array_index,
1576  &remapped_context,
1577  values[array_index],
1578  keytype,
1579  flag)) {
1580  ret++;
1581  exclude = array_index;
1582  break;
1583  }
1584  }
1585 
1586  if (exclude != -1) {
1588 
1589  for (array_index = 0; array_index < value_count; array_index++) {
1590  if (!BLI_BITMAP_TEST_BOOL(successful_remaps, array_index)) {
1591  continue;
1592  }
1593 
1594  if (array_index != exclude) {
1596  reports,
1597  &ptr,
1598  prop,
1599  act,
1600  group,
1601  rna_path,
1602  array_index,
1603  &remapped_context,
1604  values[array_index],
1605  keytype,
1606  flag);
1607  }
1608  }
1609  }
1610  }
1611  /* Simply insert all channels. */
1612  else {
1613  for (array_index = 0; array_index < value_count; array_index++) {
1614  if (!BLI_BITMAP_TEST_BOOL(successful_remaps, array_index)) {
1615  continue;
1616  }
1617 
1619  reports,
1620  &ptr,
1621  prop,
1622  act,
1623  group,
1624  rna_path,
1625  array_index,
1626  &remapped_context,
1627  values[array_index],
1628  keytype,
1629  flag);
1630  }
1631  }
1632  }
1633  /* Key a single index. */
1634  else {
1635  if (array_index >= 0 && array_index < value_count &&
1636  BLI_BITMAP_TEST_BOOL(successful_remaps, array_index)) {
1638  reports,
1639  &ptr,
1640  prop,
1641  act,
1642  group,
1643  rna_path,
1644  array_index,
1645  &remapped_context,
1646  values[array_index],
1647  keytype,
1648  flag);
1649  }
1650  }
1651 
1652  if (values != value_buffer) {
1653  MEM_freeN(values);
1654  }
1655 
1656  MEM_freeN(successful_remaps);
1658 
1659  if (ret) {
1660  if (act != NULL) {
1662  }
1663  if (adt != NULL && adt->action != NULL && adt->action != act) {
1665  }
1666  }
1667 
1668  return ret;
1669 }
1670 
1671 /* ************************************************** */
1672 /* KEYFRAME DELETION */
1673 
1674 /* Main Keyframing API call:
1675  * Use this when validation of necessary animation data isn't necessary as it
1676  * already exists. It will delete a keyframe at the current frame.
1677  *
1678  * The flag argument is used for special settings that alter the behavior of
1679  * the keyframe deletion. These include the quick refresh options.
1680  */
1681 
1686 static bool delete_keyframe_fcurve(AnimData *adt, FCurve *fcu, float cfra)
1687 {
1688  bool found;
1689  int i;
1690 
1691  /* try to find index of beztriple to get rid of */
1692  i = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, cfra, fcu->totvert, &found);
1693  if (found) {
1694  /* delete the key at the index (will sanity check + do recalc afterwards) */
1695  BKE_fcurve_delete_key(fcu, i);
1697 
1698  /* Only delete curve too if it won't be doing anything anymore */
1699  if (BKE_fcurve_is_empty(fcu)) {
1701  }
1702 
1703  /* return success */
1704  return true;
1705  }
1706  return false;
1707 }
1708 
1709 static void deg_tag_after_keyframe_delete(Main *bmain, ID *id, AnimData *adt)
1710 {
1711  if (adt->action == NULL) {
1712  /* In the case last f-curve was removed need to inform dependency graph
1713  * about relations update, since it needs to get rid of animation operation
1714  * for this data-block. */
1716  DEG_relations_tag_update(bmain);
1717  }
1718  else {
1720  }
1721 }
1722 
1724  ReportList *reports,
1725  ID *id,
1726  bAction *act,
1727  const char rna_path[],
1728  int array_index,
1729  float cfra)
1730 {
1731  AnimData *adt = BKE_animdata_from_id(id);
1732  PointerRNA id_ptr, ptr;
1733  PropertyRNA *prop;
1734  int array_index_max = array_index + 1;
1735  int ret = 0;
1736 
1737  /* sanity checks */
1738  if (ELEM(NULL, id, adt)) {
1739  BKE_report(reports, RPT_ERROR, "No ID block and/or AnimData to delete keyframe from");
1740  return 0;
1741  }
1742 
1743  /* validate pointer first - exit if failure */
1744  RNA_id_pointer_create(id, &id_ptr);
1745  if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
1746  BKE_reportf(
1747  reports,
1748  RPT_ERROR,
1749  "Could not delete keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)",
1750  id->name,
1751  rna_path);
1752  return 0;
1753  }
1754 
1755  /* get F-Curve
1756  * NOTE: here is one of the places where we don't want new Action + F-Curve added!
1757  * so 'add' var must be 0
1758  */
1759  if (act == NULL) {
1760  /* if no action is provided, use the default one attached to this ID-block
1761  * - if it doesn't exist, then we're out of options...
1762  */
1763  if (adt->action) {
1764  act = adt->action;
1765 
1766  /* apply NLA-mapping to frame to use (if applicable) */
1768  }
1769  else {
1770  BKE_reportf(reports, RPT_ERROR, "No action to delete keyframes from for ID = %s", id->name);
1771  return 0;
1772  }
1773  }
1774 
1775  /* key entire array convenience method */
1776  if (array_index == -1) {
1777  array_index = 0;
1778  array_index_max = RNA_property_array_length(&ptr, prop);
1779 
1780  /* for single properties, increase max_index so that the property itself gets included,
1781  * but don't do this for standard arrays since that can cause corruption issues
1782  * (extra unused curves)
1783  */
1784  if (array_index_max == array_index) {
1785  array_index_max++;
1786  }
1787  }
1788 
1789  /* will only loop once unless the array index was -1 */
1790  for (; array_index < array_index_max; array_index++) {
1791  FCurve *fcu = ED_action_fcurve_find(act, rna_path, array_index);
1792 
1793  /* check if F-Curve exists and/or whether it can be edited */
1794  if (fcu == NULL) {
1795  continue;
1796  }
1797 
1798  if (BKE_fcurve_is_protected(fcu)) {
1799  BKE_reportf(reports,
1800  RPT_WARNING,
1801  "Not deleting keyframe for locked F-Curve '%s' for %s '%s'",
1802  fcu->rna_path,
1804  id->name + 2);
1805  continue;
1806  }
1807 
1808  ret += delete_keyframe_fcurve(adt, fcu, cfra);
1809  }
1810  if (ret) {
1811  deg_tag_after_keyframe_delete(bmain, id, adt);
1812  }
1813  /* return success/failure */
1814  return ret;
1815 }
1816 
1817 /* ************************************************** */
1818 /* KEYFRAME CLEAR */
1819 
1830 static int clear_keyframe(Main *bmain,
1831  ReportList *reports,
1832  ID *id,
1833  bAction *act,
1834  const char rna_path[],
1835  int array_index,
1836  eInsertKeyFlags UNUSED(flag))
1837 {
1838  AnimData *adt = BKE_animdata_from_id(id);
1839  PointerRNA id_ptr, ptr;
1840  PropertyRNA *prop;
1841  int array_index_max = array_index + 1;
1842  int ret = 0;
1843 
1844  /* sanity checks */
1845  if (ELEM(NULL, id, adt)) {
1846  BKE_report(reports, RPT_ERROR, "No ID block and/or AnimData to delete keyframe from");
1847  return 0;
1848  }
1849 
1850  /* validate pointer first - exit if failure */
1851  RNA_id_pointer_create(id, &id_ptr);
1852  if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
1853  BKE_reportf(
1854  reports,
1855  RPT_ERROR,
1856  "Could not clear keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)",
1857  id->name,
1858  rna_path);
1859  return 0;
1860  }
1861 
1862  /* get F-Curve
1863  * NOTE: here is one of the places where we don't want new Action + F-Curve added!
1864  * so 'add' var must be 0
1865  */
1866  if (act == NULL) {
1867  /* if no action is provided, use the default one attached to this ID-block
1868  * - if it doesn't exist, then we're out of options...
1869  */
1870  if (adt->action) {
1871  act = adt->action;
1872  }
1873  else {
1874  BKE_reportf(reports, RPT_ERROR, "No action to delete keyframes from for ID = %s", id->name);
1875  return 0;
1876  }
1877  }
1878 
1879  /* key entire array convenience method */
1880  if (array_index == -1) {
1881  array_index = 0;
1882  array_index_max = RNA_property_array_length(&ptr, prop);
1883 
1884  /* for single properties, increase max_index so that the property itself gets included,
1885  * but don't do this for standard arrays since that can cause corruption issues
1886  * (extra unused curves)
1887  */
1888  if (array_index_max == array_index) {
1889  array_index_max++;
1890  }
1891  }
1892 
1893  /* will only loop once unless the array index was -1 */
1894  for (; array_index < array_index_max; array_index++) {
1895  FCurve *fcu = ED_action_fcurve_find(act, rna_path, array_index);
1896 
1897  /* check if F-Curve exists and/or whether it can be edited */
1898  if (fcu == NULL) {
1899  continue;
1900  }
1901 
1902  if (BKE_fcurve_is_protected(fcu)) {
1903  BKE_reportf(reports,
1904  RPT_WARNING,
1905  "Not clearing all keyframes from locked F-Curve '%s' for %s '%s'",
1906  fcu->rna_path,
1908  id->name + 2);
1909  continue;
1910  }
1911 
1913 
1914  /* return success */
1915  ret++;
1916  }
1917  if (ret) {
1918  deg_tag_after_keyframe_delete(bmain, id, adt);
1919  }
1920  /* return success/failure */
1921  return ret;
1922 }
1923 
1924 /* ******************************************* */
1925 /* KEYFRAME MODIFICATION */
1926 
1927 /* mode for commonkey_modifykey */
1928 enum {
1931 } /*eCommonModifyKey_Modes*/;
1932 
1939 {
1940  ScrArea *area = CTX_wm_area(C);
1942 
1943  /* if no area or active scene */
1944  if (ELEM(NULL, area, scene)) {
1945  return false;
1946  }
1947 
1948  /* should be fine */
1949  return true;
1950 }
1951 
1952 /* Insert Key Operator ------------------------ */
1953 
1955 {
1957  Object *obedit = CTX_data_edit_object(C);
1958  bool ob_edit_mode = false;
1959 
1960  float cfra = (float)
1961  scene->r.cfra; /* XXX for now, don't bother about all the yucky offset crap */
1962  int num_channels;
1963  const bool confirm = op->flag & OP_IS_INVOKE;
1964 
1966  if (ks == NULL) {
1967  return OPERATOR_CANCELLED;
1968  }
1969 
1970  /* exit the edit mode to make sure that those object data properties that have been
1971  * updated since the last switching to the edit mode will be keyframed correctly
1972  */
1973  if (obedit && ANIM_keyingset_find_id(ks, (ID *)obedit->data)) {
1975  ob_edit_mode = true;
1976  }
1977 
1978  /* try to insert keyframes for the channels specified by KeyingSet */
1979  num_channels = ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
1980  if (G.debug & G_DEBUG) {
1981  BKE_reportf(op->reports,
1982  RPT_INFO,
1983  "Keying set '%s' - successfully added %d keyframes",
1984  ks->name,
1985  num_channels);
1986  }
1987 
1988  /* restore the edit mode if necessary */
1989  if (ob_edit_mode) {
1991  }
1992 
1993  /* report failure or do updates? */
1994  if (num_channels < 0) {
1995  BKE_report(op->reports, RPT_ERROR, "No suitable context info for active keying set");
1996  return OPERATOR_CANCELLED;
1997  }
1998 
1999  if (num_channels > 0) {
2000  /* send notifiers that keyframes have been changed */
2002  }
2003 
2004  if (confirm) {
2005  /* if called by invoke (from the UI), make a note that we've inserted keyframes */
2006  if (num_channels > 0) {
2007  BKE_reportf(op->reports,
2008  RPT_INFO,
2009  "Successfully added %d keyframes for keying set '%s'",
2010  num_channels,
2011  ks->name);
2012  }
2013  else {
2014  BKE_report(op->reports, RPT_WARNING, "Keying set failed to insert any keyframes");
2015  }
2016  }
2017 
2018  return OPERATOR_FINISHED;
2019 }
2020 
2022 {
2023  PropertyRNA *prop;
2024 
2025  /* identifiers */
2026  ot->name = "Insert Keyframe";
2027  ot->idname = "ANIM_OT_keyframe_insert";
2028  ot->description =
2029  "Insert keyframes on the current frame for all properties in the specified Keying Set";
2030 
2031  /* callbacks */
2032  ot->exec = insert_key_exec;
2034 
2035  /* flags */
2037 
2038  /* keyingset to use (dynamic enum) */
2039  prop = RNA_def_enum(
2040  ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
2043  ot->prop = prop;
2044 }
2045 
2047 {
2048  PropertyRNA *prop;
2049 
2050  /* identifiers */
2051  ot->name = "Insert Keyframe (by name)";
2052  ot->idname = "ANIM_OT_keyframe_insert_by_name";
2053  ot->description = "Alternate access to 'Insert Keyframe' for keymaps to use";
2054 
2055  /* callbacks */
2056  ot->exec = insert_key_exec;
2058 
2059  /* flags */
2061 
2062  /* keyingset to use (idname) */
2063  prop = RNA_def_string(
2064  ot->srna, "type", NULL, MAX_ID_NAME - 2, "Keying Set", "The Keying Set to use");
2068  ot->prop = prop;
2069 }
2070 
2071 /* Insert Key Operator (With Menu) ------------------------ */
2072 /* This operator checks if a menu should be shown for choosing the KeyingSet to use,
2073  * then calls the menu if necessary before
2074  */
2075 
2076 static int insert_key_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
2077 {
2079 
2080  /* When there is an active keying set and no request to prompt, keyframe immediately. */
2081  if ((scene->active_keyingset != 0) && !RNA_boolean_get(op->ptr, "always_prompt")) {
2082  /* Just call the exec() on the active keying-set. */
2083  RNA_enum_set(op->ptr, "type", 0);
2084  return op->type->exec(C, op);
2085  }
2086 
2087  /* Show a menu listing all keying-sets, the enum is expanded here to make use of the
2088  * operator that accesses the keying-set by name. This is important for the ability
2089  * to assign shortcuts to arbitrarily named keying sets. See T89560.
2090  * These menu items perform the key-frame insertion (not this operator)
2091  * hence the #OPERATOR_INTERFACE return. */
2092  uiPopupMenu *pup = UI_popup_menu_begin(C, WM_operatortype_name(op->type, op->ptr), ICON_NONE);
2093  uiLayout *layout = UI_popup_menu_layout(pup);
2094 
2095  /* Even though `ANIM_OT_keyframe_insert_menu` can show a menu in one line,
2096  * prefer `ANIM_OT_keyframe_insert_by_name` so users can bind keys to specific
2097  * keying sets by name in the key-map instead of the index which isn't stable. */
2098  PropertyRNA *prop = RNA_struct_find_property(op->ptr, "type");
2099  const EnumPropertyItem *item_array = NULL;
2100  int totitem;
2101  bool free;
2102 
2103  RNA_property_enum_items_gettexted(C, op->ptr, prop, &item_array, &totitem, &free);
2104 
2105  for (int i = 0; i < totitem; i++) {
2106  const EnumPropertyItem *item = &item_array[i];
2107  if (item->identifier[0] != '\0') {
2108  uiItemStringO(layout,
2109  item->name,
2110  item->icon,
2111  "ANIM_OT_keyframe_insert_by_name",
2112  "type",
2113  item->identifier);
2114  }
2115  else {
2116  /* This enum shouldn't contain headings, assert there are none.
2117  * NOTE: If in the future the enum includes them, additional layout code can be
2118  * added to show them - although that doesn't seem likely. */
2119  BLI_assert(item->name == NULL);
2120  uiItemS(layout);
2121  }
2122  }
2123 
2124  if (free) {
2125  MEM_freeN((void *)item_array);
2126  }
2127 
2128  UI_popup_menu_end(C, pup);
2129 
2130  return OPERATOR_INTERFACE;
2131 }
2132 
2134 {
2135  PropertyRNA *prop;
2136 
2137  /* identifiers */
2138  ot->name = "Insert Keyframe Menu";
2139  ot->idname = "ANIM_OT_keyframe_insert_menu";
2140  ot->description =
2141  "Insert Keyframes for specified Keying Set, with menu of available Keying Sets if undefined";
2142 
2143  /* callbacks */
2145  ot->exec = insert_key_exec;
2147 
2148  /* flags */
2150 
2151  /* keyingset to use (dynamic enum) */
2152  prop = RNA_def_enum(
2153  ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
2156  ot->prop = prop;
2157 
2158  /* whether the menu should always be shown
2159  * - by default, the menu should only be shown when there is no active Keying Set (2.5 behavior),
2160  * although in some cases it might be useful to always shown (pre 2.5 behavior)
2161  */
2162  prop = RNA_def_boolean(ot->srna, "always_prompt", 0, "Always Show Menu", "");
2164 }
2165 
2166 /* Delete Key Operator ------------------------ */
2167 
2169 {
2172  if (ks == NULL) {
2173  return OPERATOR_CANCELLED;
2174  }
2175 
2176  return delete_key_using_keying_set(C, op, ks);
2177 }
2178 
2180 {
2182  float cfra = (float)
2183  scene->r.cfra; /* XXX for now, don't bother about all the yucky offset crap */
2184  int num_channels;
2185  const bool confirm = op->flag & OP_IS_INVOKE;
2186 
2187  /* try to delete keyframes for the channels specified by KeyingSet */
2188  num_channels = ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_DELETE, cfra);
2189  if (G.debug & G_DEBUG) {
2190  printf("KeyingSet '%s' - Successfully removed %d Keyframes\n", ks->name, num_channels);
2191  }
2192 
2193  /* report failure or do updates? */
2194  if (num_channels < 0) {
2195  BKE_report(op->reports, RPT_ERROR, "No suitable context info for active keying set");
2196  return OPERATOR_CANCELLED;
2197  }
2198 
2199  if (num_channels > 0) {
2201  }
2202 
2203  if (confirm) {
2204  /* if called by invoke (from the UI), make a note that we've removed keyframes */
2205  if (num_channels > 0) {
2206  BKE_reportf(op->reports,
2207  RPT_INFO,
2208  "Successfully removed %d keyframes for keying set '%s'",
2209  num_channels,
2210  ks->name);
2211  }
2212  else {
2213  BKE_report(op->reports, RPT_WARNING, "Keying set failed to remove any keyframes");
2214  }
2215  }
2216  return OPERATOR_FINISHED;
2217 }
2218 
2220 {
2221  PropertyRNA *prop;
2222 
2223  /* identifiers */
2224  ot->name = "Delete Keying-Set Keyframe";
2225  ot->idname = "ANIM_OT_keyframe_delete";
2226  ot->description =
2227  "Delete keyframes on the current frame for all properties in the specified Keying Set";
2228 
2229  /* callbacks */
2230  ot->exec = delete_key_exec;
2232 
2233  /* flags */
2235 
2236  /* keyingset to use (dynamic enum) */
2237  prop = RNA_def_enum(
2238  ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
2241  ot->prop = prop;
2242 }
2243 
2245 {
2246  PropertyRNA *prop;
2247 
2248  /* identifiers */
2249  ot->name = "Delete Keying-Set Keyframe (by name)";
2250  ot->idname = "ANIM_OT_keyframe_delete_by_name";
2251  ot->description = "Alternate access to 'Delete Keyframe' for keymaps to use";
2252 
2253  /* callbacks */
2254  ot->exec = delete_key_exec;
2256 
2257  /* flags */
2259 
2260  /* keyingset to use (idname) */
2261  prop = RNA_def_string(
2262  ot->srna, "type", NULL, MAX_ID_NAME - 2, "Keying Set", "The Keying Set to use");
2266  ot->prop = prop;
2267 }
2268 
2269 /* Delete Key Operator ------------------------ */
2270 /* NOTE: Although this version is simpler than the more generic version for KeyingSets,
2271  * it is more useful for animators working in the 3D view.
2272  */
2273 
2275 {
2276  bool changed = false;
2277 
2278  CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
2279  /* just those in active action... */
2280  if ((ob->adt) && (ob->adt->action)) {
2281  AnimData *adt = ob->adt;
2282  bAction *act = adt->action;
2283  FCurve *fcu, *fcn;
2284 
2285  for (fcu = act->curves.first; fcu; fcu = fcn) {
2286  bool can_delete = false;
2287 
2288  fcn = fcu->next;
2289 
2290  /* in pose mode, only delete the F-Curve if it belongs to a selected bone */
2291  if (ob->mode & OB_MODE_POSE) {
2292  if (fcu->rna_path) {
2293  /* Get bone-name, and check if this bone is selected. */
2294  bPoseChannel *pchan = NULL;
2295  char bone_name[sizeof(pchan->name)];
2297  fcu->rna_path, "pose.bones[", bone_name, sizeof(bone_name))) {
2298  pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
2299  /* Delete if bone is selected. */
2300  if ((pchan) && (pchan->bone)) {
2301  if (pchan->bone->flag & BONE_SELECTED) {
2302  can_delete = true;
2303  }
2304  }
2305  }
2306  }
2307  }
2308  else {
2309  /* object mode - all of Object's F-Curves are affected */
2310  can_delete = true;
2311  }
2312 
2313  /* delete F-Curve completely */
2314  if (can_delete) {
2317  changed = true;
2318  }
2319  }
2320 
2321  /* Delete the action itself if it is empty. */
2323  changed = true;
2324  }
2325  }
2326  }
2327  CTX_DATA_END;
2328 
2329  if (!changed) {
2330  return OPERATOR_CANCELLED;
2331  }
2332 
2333  /* send updates */
2335 
2336  return OPERATOR_FINISHED;
2337 }
2338 
2340 {
2341  /* identifiers */
2342  ot->name = "Remove Animation";
2343  ot->description = "Remove all keyframe animation for selected objects";
2344  ot->idname = "ANIM_OT_keyframe_clear_v3d";
2345 
2346  /* callbacks */
2349 
2351 
2352  /* flags */
2354 }
2355 
2357 {
2359  float cfra = (float)scene->r.cfra;
2360 
2361  int selected_objects_len = 0;
2362  int selected_objects_success_len = 0;
2363  int success_multi = 0;
2364 
2365  const bool confirm = op->flag & OP_IS_INVOKE;
2366 
2367  CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
2368  ID *id = &ob->id;
2369  int success = 0;
2370 
2371  selected_objects_len += 1;
2372 
2373  /* just those in active action... */
2374  if ((ob->adt) && (ob->adt->action)) {
2375  AnimData *adt = ob->adt;
2376  bAction *act = adt->action;
2377  FCurve *fcu, *fcn;
2378  const float cfra_unmap = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
2379 
2380  for (fcu = act->curves.first; fcu; fcu = fcn) {
2381  fcn = fcu->next;
2382 
2383  /* don't touch protected F-Curves */
2384  if (BKE_fcurve_is_protected(fcu)) {
2385  BKE_reportf(op->reports,
2386  RPT_WARNING,
2387  "Not deleting keyframe for locked F-Curve '%s', object '%s'",
2388  fcu->rna_path,
2389  id->name + 2);
2390  continue;
2391  }
2392 
2393  /* Special exception for bones, as this makes this operator more convenient to use
2394  * NOTE: This is only done in pose mode.
2395  * In object mode, we're dealing with the entire object.
2396  */
2397  if (ob->mode & OB_MODE_POSE) {
2398  bPoseChannel *pchan = NULL;
2399 
2400  /* Get bone-name, and check if this bone is selected. */
2401  char bone_name[sizeof(pchan->name)];
2402  if (!BLI_str_quoted_substr(fcu->rna_path, "pose.bones[", bone_name, sizeof(bone_name))) {
2403  continue;
2404  }
2405  pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
2406 
2407  /* skip if bone is not selected */
2408  if ((pchan) && (pchan->bone)) {
2409  /* bones are only selected/editable if visible... */
2410  bArmature *arm = (bArmature *)ob->data;
2411 
2412  /* skipping - not visible on currently visible layers */
2413  if ((arm->layer & pchan->bone->layer) == 0) {
2414  continue;
2415  }
2416  /* skipping - is currently hidden */
2417  if (pchan->bone->flag & BONE_HIDDEN_P) {
2418  continue;
2419  }
2420 
2421  /* selection flag... */
2422  if ((pchan->bone->flag & BONE_SELECTED) == 0) {
2423  continue;
2424  }
2425  }
2426  }
2427 
2428  /* delete keyframes on current frame
2429  * WARNING: this can delete the next F-Curve, hence the "fcn" copying
2430  */
2431  success += delete_keyframe_fcurve(adt, fcu, cfra_unmap);
2432  }
2433  DEG_id_tag_update(&ob->adt->action->id, ID_RECALC_ANIMATION_NO_FLUSH);
2434  }
2435 
2436  /* Only for reporting. */
2437  if (success) {
2438  selected_objects_success_len += 1;
2439  success_multi += success;
2440  }
2441 
2443  }
2444  CTX_DATA_END;
2445 
2446  if (selected_objects_success_len) {
2447  /* send updates */
2449  }
2450 
2451  if (confirm) {
2452  /* if called by invoke (from the UI), make a note that we've removed keyframes */
2453  if (selected_objects_success_len) {
2454  BKE_reportf(op->reports,
2455  RPT_INFO,
2456  "%d object(s) successfully had %d keyframes removed",
2457  selected_objects_success_len,
2458  success_multi);
2459  }
2460  else {
2461  BKE_reportf(
2462  op->reports, RPT_ERROR, "No keyframes removed from %d object(s)", selected_objects_len);
2463  }
2464  }
2465  return OPERATOR_FINISHED;
2466 }
2467 
2469 {
2472 
2473  if (ks == NULL) {
2475  }
2476 
2477  return delete_key_using_keying_set(C, op, ks);
2478 }
2479 
2481 {
2482  /* identifiers */
2483  ot->name = "Delete Keyframe";
2484  ot->description = "Remove keyframes on current frame for selected objects and bones";
2485  ot->idname = "ANIM_OT_keyframe_delete_v3d";
2486 
2487  /* callbacks */
2490 
2492 
2493  /* flags */
2495 }
2496 
2497 /* Insert Key Button Operator ------------------------ */
2498 
2500 {
2501  Main *bmain = CTX_data_main(C);
2504  PointerRNA ptr = {NULL};
2505  PropertyRNA *prop = NULL;
2506  char *path;
2507  uiBut *but;
2508  const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(
2510  bool changed = false;
2511  int index;
2512  const bool all = RNA_boolean_get(op->ptr, "all");
2514 
2515  /* flags for inserting keyframes */
2516  flag = ANIM_get_keyframing_flags(scene, true);
2517 
2518  /* try to insert keyframe using property retrieved from UI */
2519  if (!(but = UI_context_active_but_prop_get(C, &ptr, &prop, &index))) {
2520  /* pass event on if no active button found */
2522  }
2523 
2524  if ((ptr.owner_id && ptr.data && prop) && RNA_property_animateable(&ptr, prop)) {
2525  if (ptr.type == &RNA_NlaStrip) {
2526  /* Handle special properties for NLA Strips, whose F-Curves are stored on the
2527  * strips themselves. These are stored separately or else the properties will
2528  * not have any effect.
2529  */
2530  NlaStrip *strip = ptr.data;
2531  FCurve *fcu = BKE_fcurve_find(&strip->fcurves, RNA_property_identifier(prop), index);
2532 
2533  if (fcu) {
2534  changed = insert_keyframe_direct(
2535  op->reports, ptr, prop, fcu, &anim_eval_context, ts->keyframe_type, NULL, 0);
2536  }
2537  else {
2538  BKE_report(op->reports,
2539  RPT_ERROR,
2540  "This property cannot be animated as it will not get updated correctly");
2541  }
2542  }
2543  else if (UI_but_flag_is_set(but, UI_BUT_DRIVEN)) {
2544  /* Driven property - Find driver */
2545  FCurve *fcu;
2546  bool driven, special;
2547 
2548  fcu = BKE_fcurve_find_by_rna_context_ui(C, &ptr, prop, index, NULL, NULL, &driven, &special);
2549 
2550  if (fcu && driven) {
2551  changed = insert_keyframe_direct(op->reports,
2552  ptr,
2553  prop,
2554  fcu,
2555  &anim_eval_context,
2556  ts->keyframe_type,
2557  NULL,
2559  }
2560  }
2561  else {
2562  /* standard properties */
2563  path = RNA_path_from_ID_to_property(&ptr, prop);
2564 
2565  if (path) {
2566  const char *identifier = RNA_property_identifier(prop);
2567  const char *group = NULL;
2568 
2569  /* Special exception for keyframing transforms:
2570  * Set "group" for this manually, instead of having them appearing at the bottom
2571  * (ungrouped) part of the channels list.
2572  * Leaving these ungrouped is not a nice user behavior in this case.
2573  *
2574  * TODO: Perhaps we can extend this behavior in future for other properties...
2575  */
2576  if (ptr.type == &RNA_PoseBone) {
2577  bPoseChannel *pchan = ptr.data;
2578  group = pchan->name;
2579  }
2580  else if ((ptr.type == &RNA_Object) &&
2581  (strstr(identifier, "location") || strstr(identifier, "rotation") ||
2582  strstr(identifier, "scale"))) {
2583  /* NOTE: Keep this label in sync with the "ID" case in
2584  * keyingsets_utils.py :: get_transform_generators_base_info()
2585  */
2586  group = "Object Transforms";
2587  }
2588 
2589  if (all) {
2590  /* -1 indicates operating on the entire array (or the property itself otherwise) */
2591  index = -1;
2592  }
2593 
2594  changed = (insert_keyframe(bmain,
2595  op->reports,
2596  ptr.owner_id,
2597  NULL,
2598  group,
2599  path,
2600  index,
2601  &anim_eval_context,
2602  ts->keyframe_type,
2603  NULL,
2604  flag) != 0);
2605 
2606  MEM_freeN(path);
2607  }
2608  else {
2609  BKE_report(op->reports,
2610  RPT_WARNING,
2611  "Failed to resolve path to property, "
2612  "try manually specifying this using a Keying Set instead");
2613  }
2614  }
2615  }
2616  else {
2617  if (prop && !RNA_property_animateable(&ptr, prop)) {
2618  BKE_reportf(op->reports,
2619  RPT_WARNING,
2620  "\"%s\" property cannot be animated",
2621  RNA_property_identifier(prop));
2622  }
2623  else {
2624  BKE_reportf(op->reports,
2625  RPT_WARNING,
2626  "Button doesn't appear to have any property information attached (ptr.data = "
2627  "%p, prop = %p)",
2628  ptr.data,
2629  (void *)prop);
2630  }
2631  }
2632 
2633  if (changed) {
2634  ID *id = ptr.owner_id;
2635  AnimData *adt = BKE_animdata_from_id(id);
2636  if (adt->action != NULL) {
2638  }
2640 
2641  /* send updates */
2643 
2644  /* send notifiers that keyframes have been changed */
2646  }
2647 
2648  return (changed) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
2649 }
2650 
2652 {
2653  /* identifiers */
2654  ot->name = "Insert Keyframe (Buttons)";
2655  ot->idname = "ANIM_OT_keyframe_insert_button";
2656  ot->description = "Insert a keyframe for current UI-active property";
2657 
2658  /* callbacks */
2661 
2662  /* flags */
2664 
2665  /* properties */
2666  RNA_def_boolean(ot->srna, "all", 1, "All", "Insert a keyframe for all element of the array");
2667 }
2668 
2669 /* Delete Key Button Operator ------------------------ */
2670 
2672 {
2674  PointerRNA ptr = {NULL};
2675  PropertyRNA *prop = NULL;
2676  Main *bmain = CTX_data_main(C);
2677  char *path;
2678  float cfra = (float)
2679  scene->r.cfra; /* XXX for now, don't bother about all the yucky offset crap */
2680  bool changed = false;
2681  int index;
2682  const bool all = RNA_boolean_get(op->ptr, "all");
2683 
2684  /* try to insert keyframe using property retrieved from UI */
2685  if (!UI_context_active_but_prop_get(C, &ptr, &prop, &index)) {
2686  /* pass event on if no active button found */
2688  }
2689 
2690  if (ptr.owner_id && ptr.data && prop) {
2692  /* Handle special properties for NLA Strips, whose F-Curves are stored on the
2693  * strips themselves. These are stored separately or else the properties will
2694  * not have any effect.
2695  */
2696  ID *id = ptr.owner_id;
2697  NlaStrip *strip = ptr.data;
2698  FCurve *fcu = BKE_fcurve_find(&strip->fcurves, RNA_property_identifier(prop), 0);
2699 
2700  if (fcu) {
2701  if (BKE_fcurve_is_protected(fcu)) {
2702  BKE_reportf(
2703  op->reports,
2704  RPT_WARNING,
2705  "Not deleting keyframe for locked F-Curve for NLA Strip influence on %s - %s '%s'",
2706  strip->name,
2708  id->name + 2);
2709  }
2710  else {
2711  /* remove the keyframe directly
2712  * NOTE: cannot use delete_keyframe_fcurve(), as that will free the curve,
2713  * and delete_keyframe() expects the FCurve to be part of an action
2714  */
2715  bool found = false;
2716  int i;
2717 
2718  /* try to find index of beztriple to get rid of */
2719  i = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, cfra, fcu->totvert, &found);
2720  if (found) {
2721  /* delete the key at the index (will sanity check + do recalc afterwards) */
2722  BKE_fcurve_delete_key(fcu, i);
2724  changed = true;
2725  }
2726  }
2727  }
2728  }
2729  else {
2730  /* standard properties */
2731  path = RNA_path_from_ID_to_property(&ptr, prop);
2732 
2733  if (path) {
2734  if (all) {
2735  /* -1 indicates operating on the entire array (or the property itself otherwise) */
2736  index = -1;
2737  }
2738 
2739  changed = delete_keyframe(bmain, op->reports, ptr.owner_id, NULL, path, index, cfra) != 0;
2740  MEM_freeN(path);
2741  }
2742  else if (G.debug & G_DEBUG) {
2743  printf("Button Delete-Key: no path to property\n");
2744  }
2745  }
2746  }
2747  else if (G.debug & G_DEBUG) {
2748  printf("ptr.data = %p, prop = %p\n", ptr.data, (void *)prop);
2749  }
2750 
2751  if (changed) {
2752  /* send updates */
2754 
2755  /* send notifiers that keyframes have been changed */
2757  }
2758 
2759  return (changed) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
2760 }
2761 
2763 {
2764  /* identifiers */
2765  ot->name = "Delete Keyframe (Buttons)";
2766  ot->idname = "ANIM_OT_keyframe_delete_button";
2767  ot->description = "Delete current keyframe of current UI-active property";
2768 
2769  /* callbacks */
2772 
2773  /* flags */
2775 
2776  /* properties */
2777  RNA_def_boolean(ot->srna, "all", 1, "All", "Delete keyframes from all elements of the array");
2778 }
2779 
2780 /* Clear Key Button Operator ------------------------ */
2781 
2783 {
2784  PointerRNA ptr = {NULL};
2785  PropertyRNA *prop = NULL;
2786  Main *bmain = CTX_data_main(C);
2787  char *path;
2788  bool changed = false;
2789  int index;
2790  const bool all = RNA_boolean_get(op->ptr, "all");
2791 
2792  /* try to insert keyframe using property retrieved from UI */
2793  if (!UI_context_active_but_prop_get(C, &ptr, &prop, &index)) {
2794  /* pass event on if no active button found */
2796  }
2797 
2798  if (ptr.owner_id && ptr.data && prop) {
2799  path = RNA_path_from_ID_to_property(&ptr, prop);
2800 
2801  if (path) {
2802  if (all) {
2803  /* -1 indicates operating on the entire array (or the property itself otherwise) */
2804  index = -1;
2805  }
2806 
2807  changed |= (clear_keyframe(bmain, op->reports, ptr.owner_id, NULL, path, index, 0) != 0);
2808  MEM_freeN(path);
2809  }
2810  else if (G.debug & G_DEBUG) {
2811  printf("Button Clear-Key: no path to property\n");
2812  }
2813  }
2814  else if (G.debug & G_DEBUG) {
2815  printf("ptr.data = %p, prop = %p\n", ptr.data, (void *)prop);
2816  }
2817 
2818  if (changed) {
2819  /* send updates */
2821 
2822  /* send notifiers that keyframes have been changed */
2824  }
2825 
2826  return (changed) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
2827 }
2828 
2830 {
2831  /* identifiers */
2832  ot->name = "Clear Keyframe (Buttons)";
2833  ot->idname = "ANIM_OT_keyframe_clear_button";
2834  ot->description = "Clear all keyframes on the currently active property";
2835 
2836  /* callbacks */
2839 
2840  /* flags */
2842 
2843  /* properties */
2844  RNA_def_boolean(ot->srna, "all", 1, "All", "Clear keyframes from all elements of the array");
2845 }
2846 
2847 /* ******************************************* */
2848 /* AUTO KEYFRAME */
2849 
2851 {
2852  float cfra = (float)scene->r.cfra; /* XXX for now, this will do */
2853 
2854  /* only filter if auto-key mode requires this */
2855  if (IS_AUTOKEY_ON(scene) == 0) {
2856  return false;
2857  }
2858 
2859  if (IS_AUTOKEY_MODE(scene, EDITKEYS)) {
2860  /* Replace Mode:
2861  * For whole block, only key if there's a keyframe on that frame already
2862  * This is a valid assumption when we're blocking + tweaking
2863  */
2864  return id_frame_has_keyframe(id, cfra, ANIMFILTER_KEYS_LOCAL);
2865  }
2866 
2867  /* Normal Mode (or treat as being normal mode):
2868  *
2869  * Just in case the flags aren't set properly (i.e. only on/off is set, without a mode)
2870  * let's set the "normal" flag too, so that it will all be sane everywhere...
2871  */
2873 
2874  /* Can insert anytime we like... */
2875  return true;
2876 }
2877 
2878 /* ******************************************* */
2879 /* KEYFRAME DETECTION */
2880 
2881 /* --------------- API/Per-Datablock Handling ------------------- */
2882 
2883 bool fcurve_frame_has_keyframe(const FCurve *fcu, float frame, short filter)
2884 {
2885  /* quick sanity check */
2886  if (ELEM(NULL, fcu, fcu->bezt)) {
2887  return false;
2888  }
2889 
2890  /* We either include all regardless of muting, or only non-muted. */
2891  if ((filter & ANIMFILTER_KEYS_MUTED) || (fcu->flag & FCURVE_MUTED) == 0) {
2892  bool replace;
2893  int i = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, frame, fcu->totvert, &replace);
2894 
2895  /* BKE_fcurve_bezt_binarysearch_index will set replace to be 0 or 1
2896  * - obviously, 1 represents a match
2897  */
2898  if (replace) {
2899  /* sanity check: 'i' may in rare cases exceed arraylen */
2900  if ((i >= 0) && (i < fcu->totvert)) {
2901  return true;
2902  }
2903  }
2904  }
2905 
2906  return false;
2907 }
2908 
2910  PropertyRNA *prop,
2911  FCurve *fcu,
2912  const AnimationEvalContext *anim_eval_context)
2913 {
2914  PathResolvedRNA anim_rna;
2915  anim_rna.ptr = ptr;
2916  anim_rna.prop = prop;
2917  anim_rna.prop_index = fcu->array_index;
2918 
2920  int count, index = fcu->array_index;
2921  float *values = setting_get_rna_values(&ptr, prop, buffer, RNA_MAX_ARRAY_LENGTH, &count);
2922 
2923  float fcurve_val = calculate_fcurve(&anim_rna, fcu, anim_eval_context);
2924  float cur_val = (index >= 0 && index < count) ? values[index] : 0.0f;
2925 
2926  if (values != buffer) {
2927  MEM_freeN(values);
2928  }
2929 
2930  return !compare_ff_relative(fcurve_val, cur_val, FLT_EPSILON, 64);
2931 }
2932 
2938 static bool action_frame_has_keyframe(bAction *act, float frame, short filter)
2939 {
2940  FCurve *fcu;
2941 
2942  /* can only find if there is data */
2943  if (act == NULL) {
2944  return false;
2945  }
2946 
2947  /* if only check non-muted, check if muted */
2948  if ((filter & ANIMFILTER_KEYS_MUTED) || (act->flag & ACT_MUTED)) {
2949  return false;
2950  }
2951 
2952  /* loop over F-Curves, using binary-search to try to find matches
2953  * - this assumes that keyframes are only beztriples
2954  */
2955  for (fcu = act->curves.first; fcu; fcu = fcu->next) {
2956  /* only check if there are keyframes (currently only of type BezTriple) */
2957  if (fcu->bezt && fcu->totvert) {
2958  if (fcurve_frame_has_keyframe(fcu, frame, filter)) {
2959  return true;
2960  }
2961  }
2962  }
2963 
2964  /* nothing found */
2965  return false;
2966 }
2967 
2968 /* Checks whether an Object has a keyframe for a given frame */
2969 static bool object_frame_has_keyframe(Object *ob, float frame, short filter)
2970 {
2971  /* error checking */
2972  if (ob == NULL) {
2973  return false;
2974  }
2975 
2976  /* check own animation data - specifically, the action it contains */
2977  if ((ob->adt) && (ob->adt->action)) {
2978  /* T41525 - When the active action is a NLA strip being edited,
2979  * we need to correct the frame number to "look inside" the
2980  * remapped action
2981  */
2982  float ob_frame = BKE_nla_tweakedit_remap(ob->adt, frame, NLATIME_CONVERT_UNMAP);
2983 
2984  if (action_frame_has_keyframe(ob->adt->action, ob_frame, filter)) {
2985  return true;
2986  }
2987  }
2988 
2989  /* Try shape-key keyframes (if available, and allowed by filter). */
2991  Key *key = BKE_key_from_object(ob);
2992 
2993  /* Shape-keys can have keyframes ('Relative Shape Keys')
2994  * or depend on time (old 'Absolute Shape Keys'). */
2995 
2996  /* 1. test for relative (with keyframes) */
2997  if (id_frame_has_keyframe((ID *)key, frame, filter)) {
2998  return true;
2999  }
3000 
3001  /* 2. test for time */
3002  /* TODO: yet to be implemented (this feature may evolve before then anyway). */
3003  }
3004 
3005  /* try materials */
3007  /* if only active, then we can skip a lot of looping */
3009  Material *ma = BKE_object_material_get(ob, (ob->actcol + 1));
3010 
3011  /* we only retrieve the active material... */
3012  if (id_frame_has_keyframe((ID *)ma, frame, filter)) {
3013  return true;
3014  }
3015  }
3016  else {
3017  int a;
3018 
3019  /* loop over materials */
3020  for (a = 0; a < ob->totcol; a++) {
3021  Material *ma = BKE_object_material_get(ob, a + 1);
3022 
3023  if (id_frame_has_keyframe((ID *)ma, frame, filter)) {
3024  return true;
3025  }
3026  }
3027  }
3028  }
3029 
3030  /* nothing found */
3031  return false;
3032 }
3033 
3034 /* --------------- API ------------------- */
3035 
3036 bool id_frame_has_keyframe(ID *id, float frame, short filter)
3037 {
3038  /* sanity checks */
3039  if (id == NULL) {
3040  return false;
3041  }
3042 
3043  /* perform special checks for 'macro' types */
3044  switch (GS(id->name)) {
3045  case ID_OB: /* object */
3046  return object_frame_has_keyframe((Object *)id, frame, filter);
3047 #if 0
3048  /* XXX TODO... for now, just use 'normal' behavior */
3049  case ID_SCE: /* scene */
3050  break;
3051 #endif
3052  default: /* 'normal type' */
3053  {
3054  AnimData *adt = BKE_animdata_from_id(id);
3055 
3056  /* only check keyframes in active action */
3057  if (adt) {
3058  return action_frame_has_keyframe(adt->action, frame, filter);
3059  }
3060  break;
3061  }
3062  }
3063 
3064  /* no keyframe found */
3065  return false;
3066 }
3067 
3068 /* ************************************************** */
3069 
3071 {
3072  /* auto keyframing */
3073  if (autokeyframe_cfra_can_key(scene, &ob->id)) {
3074  ListBase dsources = {NULL, NULL};
3075 
3076  /* Now insert the key-frame(s) using the Keying Set:
3077  * 1) Add data-source override for the Object.
3078  * 2) Insert key-frames.
3079  * 3) Free the extra info.
3080  */
3081  ANIM_relative_keyingset_add_source(&dsources, &ob->id, NULL, NULL);
3082  ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)scene->r.cfra);
3083  BLI_freelistN(&dsources);
3084 
3085  return true;
3086  }
3087  return false;
3088 }
3089 
3091  bContext *C, Scene *scene, Object *ob, bPoseChannel *pchan, KeyingSet *ks)
3092 {
3093  if (autokeyframe_cfra_can_key(scene, &ob->id)) {
3094  ListBase dsources = {NULL, NULL};
3095 
3096  /* Now insert the keyframe(s) using the Keying Set:
3097  * 1) Add data-source override for the pose-channel.
3098  * 2) Insert key-frames.
3099  * 3) Free the extra info.
3100  */
3101  ANIM_relative_keyingset_add_source(&dsources, &ob->id, &RNA_PoseBone, pchan);
3102  ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)scene->r.cfra);
3103  BLI_freelistN(&dsources);
3104 
3105  return true;
3106  }
3107 
3108  return false;
3109 }
3110 
3112  Scene *scene,
3113  PointerRNA *ptr,
3114  PropertyRNA *prop,
3115  int rnaindex,
3116  float cfra,
3117  const bool only_if_property_keyed)
3118 {
3119  Main *bmain = CTX_data_main(C);
3122  cfra);
3123  ID *id;
3124  bAction *action;
3125  FCurve *fcu;
3126  bool driven;
3127  bool special;
3128  bool changed = false;
3129 
3130  /* for entire array buttons we check the first component, it's not perfect
3131  * but works well enough in typical cases */
3132  const int rnaindex_check = (rnaindex == -1) ? 0 : rnaindex;
3134  C, ptr, prop, rnaindex_check, NULL, &action, &driven, &special);
3135 
3136  /* Only early out when we actually want an existing F-curve already
3137  * (e.g. auto-keyframing from buttons). */
3138  if (fcu == NULL && (driven || special || only_if_property_keyed)) {
3139  return changed;
3140  }
3141 
3142  if (special) {
3143  /* NLA Strip property */
3144  if (IS_AUTOKEY_ON(scene)) {
3145  ReportList *reports = CTX_wm_reports(C);
3147 
3148  changed = insert_keyframe_direct(
3149  reports, *ptr, prop, fcu, &anim_eval_context, ts->keyframe_type, NULL, 0);
3151  }
3152  }
3153  else if (driven) {
3154  /* Driver - Try to insert keyframe using the driver's input as the frame,
3155  * making it easier to set up corrective drivers
3156  */
3157  if (IS_AUTOKEY_ON(scene)) {
3158  ReportList *reports = CTX_wm_reports(C);
3160 
3161  changed = insert_keyframe_direct(
3162  reports, *ptr, prop, fcu, &anim_eval_context, ts->keyframe_type, NULL, INSERTKEY_DRIVER);
3164  }
3165  }
3166  else {
3167  id = ptr->owner_id;
3168 
3169  /* TODO: this should probably respect the keyingset only option for anim */
3170  if (autokeyframe_cfra_can_key(scene, id)) {
3171  ReportList *reports = CTX_wm_reports(C);
3173  const eInsertKeyFlags flag = ANIM_get_keyframing_flags(scene, true);
3174  char *path = RNA_path_from_ID_to_property(ptr, prop);
3175 
3176  if (only_if_property_keyed) {
3177  /* NOTE: We use rnaindex instead of fcu->array_index,
3178  * because a button may control all items of an array at once.
3179  * E.g., color wheels (see T42567). */
3180  BLI_assert((fcu->array_index == rnaindex) || (rnaindex == -1));
3181  }
3182  changed = insert_keyframe(bmain,
3183  reports,
3184  id,
3185  action,
3186  (fcu && fcu->grp) ? fcu->grp->name : NULL,
3187  fcu ? fcu->rna_path : path,
3188  rnaindex,
3189  &anim_eval_context,
3190  ts->keyframe_type,
3191  NULL,
3192  flag) != 0;
3193  if (path) {
3194  MEM_freeN(path);
3195  }
3197  }
3198  }
3199  return changed;
3200 }
3201 
3202 /* -------------------------------------------------------------------- */
3208 {
3209  KeyingSet *ks = NULL;
3210  const int prop_type = RNA_property_type(prop);
3211  if (prop_type == PROP_ENUM) {
3212  int type = RNA_property_enum_get(op->ptr, prop);
3214  if (ks == NULL) {
3215  BKE_report(op->reports, RPT_ERROR, "No active Keying Set");
3216  }
3217  }
3218  else if (prop_type == PROP_STRING) {
3219  char type_id[MAX_ID_NAME - 2];
3220  RNA_property_string_get(op->ptr, prop, type_id);
3221  ks = ANIM_keyingset_get_from_idname(scene, type_id);
3222 
3223  if (ks == NULL) {
3224  BKE_reportf(op->reports, RPT_ERROR, "Keying set '%s' not found", type_id);
3225  }
3226  }
3227  else {
3228  BLI_assert(0);
3229  }
3230  return ks;
3231 }
3232 
typedef float(TangentPoint)[2]
Blender kernel action and pose functionality.
struct bActionGroup * action_groups_add_new(struct bAction *act, const char name[])
Definition: action.c:410
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
void action_group_colors_sync(struct bActionGroup *grp, const struct bActionGroup *ref_grp)
struct bActionGroup * BKE_action_group_find_name(struct bAction *act, const char name[])
Definition: action.c:582
struct bAction * BKE_action_add(struct Main *bmain, const char name[])
Definition: action.c:332
bool BKE_action_is_cyclic(const struct bAction *act)
Definition: action.c:1496
void action_groups_add_channel(struct bAction *act, struct bActionGroup *agrp, struct FCurve *fcurve)
Definition: action.c:435
bool BKE_animdata_action_ensure_idroot(const struct ID *owner, struct bAction *action)
struct AnimData * BKE_animdata_ensure_id(struct ID *id)
Definition: anim_data.c:90
struct AnimData * BKE_animdata_from_id(const struct ID *id)
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
void BKE_animsys_nla_remap_keyframe_values(struct NlaKeyframingContext *context, struct PointerRNA *prop_ptr, struct PropertyRNA *prop, float *values, int count, int index, const struct AnimationEvalContext *anim_eval_context, bool *r_force_all, BLI_bitmap *r_successful_remaps)
Definition: anim_sys.c:3740
struct NlaKeyframingContext * BKE_animsys_get_nla_keyframing_context(struct ListBase *cache, struct PointerRNA *ptr, struct AnimData *adt, const struct AnimationEvalContext *anim_eval_context)
AnimationEvalContext BKE_animsys_eval_context_construct_at(const AnimationEvalContext *anim_eval_context, float eval_time)
Definition: anim_sys.c:771
void BKE_armature_mat_pose_to_bone(struct bPoseChannel *pchan, const float inmat[4][4], float outmat[4][4])
Definition: armature.c:1849
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct Object * CTX_data_edit_object(const bContext *C)
Definition: context.c:1370
#define CTX_DATA_BEGIN(C, Type, instance, member)
Definition: BKE_context.h:269
struct ReportList * CTX_wm_reports(const bContext *C)
Definition: context.c:775
struct Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Definition: context.c:1505
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
#define CTX_DATA_END
Definition: BKE_context.h:278
void BKE_fcurve_active_keyframe_set(struct FCurve *fcu, const struct BezTriple *active_bezt)
float evaluate_fcurve(struct FCurve *fcu, float evaltime)
Definition: fcurve.c:2135
bool BKE_fcurve_bezt_subdivide_handles(struct BezTriple *bezt, struct BezTriple *prev, struct BezTriple *next, float *r_pdelta)
Definition: fcurve.c:1600
float calculate_fcurve(struct PathResolvedRNA *anim_rna, struct FCurve *fcu, const struct AnimationEvalContext *anim_eval_context)
eFCU_Cycle_Type
Definition: BKE_fcurve.h:440
@ FCU_CYCLE_OFFSET
Definition: BKE_fcurve.h:445
@ FCU_CYCLE_NONE
Definition: BKE_fcurve.h:441
@ FCU_CYCLE_PERFECT
Definition: BKE_fcurve.h:443
bool BKE_fcurve_is_empty(struct FCurve *fcu)
Definition: fcurve.c:2198
struct FCurve * BKE_fcurve_find_by_rna_context_ui(struct bContext *C, const struct PointerRNA *ptr, struct PropertyRNA *prop, int rnaindex, struct AnimData **r_animdata, struct bAction **r_action, bool *r_driven, bool *r_special)
int BKE_fcurve_bezt_binarysearch_index(const struct BezTriple array[], float frame, int arraylen, bool *r_replace)
Definition: fcurve.c:561
bool BKE_fcurve_is_keyframable(struct FCurve *fcu)
Definition: fcurve.c:968
bool BKE_fcurve_is_protected(struct FCurve *fcu)
Definition: fcurve.c:963
eFCU_Cycle_Type BKE_fcurve_get_cycle_type(struct FCurve *fcu)
Definition: fcurve.c:1159
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
struct FCurve * BKE_fcurve_create(void)
Definition: fcurve.c:53
void BKE_fcurve_delete_key(struct FCurve *fcu, int index)
Definition: fcurve.c:1661
struct FCurve * BKE_fcurve_find(ListBase *list, const char rna_path[], int array_index)
Definition: fcurve.c:249
float evaluate_driver(struct PathResolvedRNA *anim_rna, struct ChannelDriver *driver, struct ChannelDriver *driver_orig, const struct AnimationEvalContext *anim_eval_context)
@ G_DEBUG
Definition: BKE_global.h:174
const char * BKE_idtype_idcode_to_name(short idcode)
Definition: idtype.c:142
struct Key * BKE_key_from_object(struct Object *ob)
Definition: key.c:1803
bool BKE_id_is_editable(const struct Main *bmain, const struct ID *id)
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get(struct Object *ob, short act)
Definition: material.c:687
bool BKE_nlastrip_has_curves_for_property(const struct PointerRNA *ptr, const struct PropertyRNA *prop)
@ 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
#define BLI_BITMAP_NEW(_num, _alloc_string)
Definition: BLI_bitmap.h:40
#define BLI_BITMAP_TEST_BOOL(_bitmap, _index)
Definition: BLI_bitmap.h:74
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:16
A dynamically sized string ADT.
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_dynstr.c:50
char * BLI_dynstr_get_cstring(const DynStr *ds) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: BLI_dynstr.c:256
void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL()
Definition: BLI_dynstr.c:281
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
void BLI_kdtree_nd_() free(KDTree *tree)
Definition: kdtree_impl.h:102
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int compare_ff_relative(float a, float b, float max_diff, int max_ulps)
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:87
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:77
void mat4_to_size(float size[3], const float M[4][4])
Definition: math_matrix.c:2138
void mat4_to_axis_angle(float axis[3], float *angle, const float M[4][4])
void mat4_to_eulO(float eul[3], short order, const float mat[4][4])
void mat3_to_quat_is_ok(float q[4], const float mat[3][3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
bool bool BLI_str_quoted_substr(const char *__restrict str, const char *__restrict prefix, char *result, size_t result_maxlen)
Definition: string.c:424
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:42
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED(x)
#define ELEM(...)
#define IS_EQF(a, b)
#define TIP_(msgid)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
void DEG_id_tag_update_ex(struct Main *bmain, struct ID *id, int flag)
void DEG_id_tag_update(struct ID *id, int flag)
void DEG_relations_tag_update(struct Main *bmain)
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:771
@ ID_RECALC_ANIMATION_NO_FLUSH
Definition: DNA_ID.h:879
#define MAX_ID_NAME
Definition: DNA_ID.h:337
@ ID_SCE
Definition: DNA_ID_enums.h:45
@ ID_OB
Definition: DNA_ID_enums.h:47
@ ACT_MUTED
@ FCM_EXTRAPOLATE_CYCLIC_OFFSET
@ FCURVE_COLOR_AUTO_RGB
@ FCURVE_COLOR_AUTO_YRGB
eInsertKeyFlags
@ INSERTKEY_FAST
@ INSERTKEY_CYCLE_AWARE
@ INSERTKEY_OVERWRITE_FULL
@ INSERTKEY_REPLACE
@ INSERTKEY_MATRIX
@ INSERTKEY_NEEDED
@ INSERTKEY_XYZ2RGB
@ INSERTKEY_NO_USERPREF
@ INSERTKEY_AVAILABLE
@ INSERTKEY_DRIVER
@ INSERTKEY_NOFLAGS
@ FMODIFIER_TYPE_CYCLES
@ FCURVE_MUTED
@ FCURVE_INT_VALUES
@ FCURVE_ACTIVE
@ FCURVE_SELECTED
@ FCURVE_DISCRETE_VALUES
@ FCURVE_VISIBLE
@ FCURVE_SMOOTH_CONT_ACCEL
@ BONE_SELECTED
@ BONE_HIDDEN_P
@ BONE_CONNECTED
@ CONSTRAINT_DISABLE
@ CONSTRAINT_TYPE_TRACKTO
@ CONSTRAINT_TYPE_CHILDOF
@ CONSTRAINT_TYPE_TRANSFORM
@ CONSTRAINT_TYPE_ARMATURE
@ CONSTRAINT_TYPE_LOCLIKE
@ CONSTRAINT_TYPE_MINMAX
@ CONSTRAINT_TYPE_ROTLIMIT
@ CONSTRAINT_TYPE_ROTLIKE
@ CONSTRAINT_TYPE_KINEMATIC
@ CONSTRAINT_TYPE_DISTLIMIT
@ CONSTRAINT_TYPE_TRANSLIKE
@ CONSTRAINT_TYPE_LOCLIMIT
@ CONSTRAINT_TYPE_LOCKTRACK
@ CONSTRAINT_TYPE_SIZELIMIT
@ CONSTRAINT_TYPE_FOLLOWPATH
@ CONSTRAINT_TYPE_SIZELIKE
@ CONSTRAINT_TYPE_DAMPTRACK
#define BEZT_IS_AUTOH(bezt)
@ HD_AUTO_ANIM
@ HD_VECT
@ HD_ALIGN
@ BEZT_IPO_CONST
@ BEZT_IPO_BEZ
@ BEZT_IPO_LIN
eBezTriple_KeyframeType
@ OB_MODE_EDIT
@ OB_MODE_POSE
@ OB_MODE_OBJECT
Object is a sort of wrapper for general info.
Types and defines for representing Rigid Body entities.
@ RBO_TYPE_ACTIVE
@ AUTOKEY_MODE_NORMAL
@ OPERATOR_CANCELLED
@ OPERATOR_INTERFACE
@ OPERATOR_FINISHED
@ OPERATOR_PASS_THROUGH
#define BEZKEYTYPE(bezt)
Definition: ED_anim_api.h:969
@ ANIMFILTER_KEYS_NOSKEY
@ ANIMFILTER_KEYS_MUTED
@ ANIMFILTER_KEYS_LOCAL
@ ANIMFILTER_KEYS_ACTIVE
@ ANIMFILTER_KEYS_NOMAT
#define IS_AUTOKEY_FLAG(scene, flag)
#define IS_AUTOKEY_MODE(scene, mode)
@ MODIFYKEY_MODE_INSERT
@ MODIFYKEY_MODE_DELETE
#define IS_AUTOKEY_ON(scene)
bool ED_object_mode_set(struct bContext *C, eObjectMode mode)
Definition: object_modes.c:231
bool ED_operator_areaactive(struct bContext *C)
Definition: screen_ops.c:105
_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.
#define MEM_reallocN(vmemh, len)
#define RNA_MAX_ARRAY_LENGTH
Definition: RNA_define.h:25
@ PROP_STRING_SEARCH_SUGGESTION
Definition: RNA_types.h:561
@ PROP_FLOAT
Definition: RNA_types.h:61
@ PROP_BOOLEAN
Definition: RNA_types.h:59
@ PROP_ENUM
Definition: RNA_types.h:63
@ PROP_INT
Definition: RNA_types.h:60
@ PROP_STRING
Definition: RNA_types.h:62
@ PROP_HIDDEN
Definition: RNA_types.h:216
PropertySubType
Definition: RNA_types.h:125
@ PROP_XYZ
Definition: RNA_types.h:162
@ PROP_COLOR
Definition: RNA_types.h:153
@ PROP_EULER
Definition: RNA_types.h:159
@ PROP_COORDS
Definition: RNA_types.h:167
@ PROP_TRANSLATION
Definition: RNA_types.h:154
@ PROP_QUATERNION
Definition: RNA_types.h:160
#define C
Definition: RandGen.cpp:25
@ UI_BUT_DRIVEN
Definition: UI_interface.h:200
struct uiLayout * UI_popup_menu_layout(uiPopupMenu *pup)
void uiItemS(uiLayout *layout)
uiBut * UI_context_active_but_prop_get(const struct bContext *C, struct PointerRNA *r_ptr, struct PropertyRNA **r_prop, int *r_index)
void UI_popup_menu_end(struct bContext *C, struct uiPopupMenu *pup)
void uiItemStringO(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, const char *value)
void UI_context_update_anim_flag(const struct bContext *C)
uiPopupMenu * UI_popup_menu_begin(struct bContext *C, const char *title, int icon) ATTR_NONNULL()
bool UI_but_flag_is_set(uiBut *but, int flag)
Definition: interface.cc:5868
@ OPTYPE_INTERNAL
Definition: WM_types.h:168
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define NC_ANIMATION
Definition: WM_types.h:338
#define NA_ADDED
Definition: WM_types.h:525
#define NA_EDITED
Definition: WM_types.h:523
#define NA_REMOVED
Definition: WM_types.h:526
#define ND_KEYS
Definition: WM_types.h:412
#define ND_KEYFRAME
Definition: WM_types.h:442
#define NC_OBJECT
Definition: WM_types.h:329
bool ANIM_remove_empty_action_from_animdata(struct AnimData *adt)
void ANIM_fcurve_delete_from_animdata(bAnimContext *ac, AnimData *adt, FCurve *fcu)
__forceinline bool all(const avxb &b)
Definition: avxb.h:201
unsigned int U
Definition: btGjkEpa3.h:78
#define SELECT
Scene scene
const Depsgraph * depsgraph
DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
int count
#define GS(x)
Definition: iris.c:225
ccl_global float * buffer
static void replace_bezt_keyframe_ypos(BezTriple *dst, const BezTriple *bezt)
Definition: keyframing.c:393
@ COMMONKEY_MODE_INSERT
Definition: keyframing.c:1929
@ COMMONKEY_MODE_DELETE
Definition: keyframing.c:1930
void ANIM_OT_keyframe_insert_menu(wmOperatorType *ot)
Definition: keyframing.c:2133
static void deg_tag_after_keyframe_delete(Main *bmain, ID *id, AnimData *adt)
Definition: keyframing.c:1709
bool fcurve_is_changed(PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, const AnimationEvalContext *anim_eval_context)
Definition: keyframing.c:2909
static bool visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
Definition: keyframing.c:861
int delete_keyframe(Main *bmain, ReportList *reports, ID *id, bAction *act, const char rna_path[], int array_index, float cfra)
Main Delete Key-Framing API call.
Definition: keyframing.c:1723
static int insert_key_exec(bContext *C, wmOperator *op)
Definition: keyframing.c:1954
static int delete_key_exec(bContext *C, wmOperator *op)
Definition: keyframing.c:2168
static float * visualkey_get_values(PointerRNA *ptr, PropertyRNA *prop, float *buffer, int buffer_size, int *r_count)
Definition: keyframing.c:1028
static int insert_key_button_exec(bContext *C, wmOperator *op)
Definition: keyframing.c:2499
bool ED_autokeyframe_object(bContext *C, Scene *scene, Object *ob, KeyingSet *ks)
Definition: keyframing.c:3070
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
void ANIM_OT_keyframe_insert(wmOperatorType *ot)
Definition: keyframing.c:2021
static eFCU_Cycle_Type remap_cyclic_keyframe_location(FCurve *fcu, float *px, float *py)
Definition: keyframing.c:315
bAction * ED_id_action_ensure(Main *bmain, ID *id)
Definition: keyframing.c:123
static int delete_key_button_exec(bContext *C, wmOperator *op)
Definition: keyframing.c:2671
static bool object_frame_has_keyframe(Object *ob, float frame, short filter)
Definition: keyframing.c:2969
void ANIM_OT_keyframe_clear_button(wmOperatorType *ot)
Definition: keyframing.c:2829
bool insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, const AnimationEvalContext *anim_eval_context, eBezTriple_KeyframeType keytype, struct NlaKeyframingContext *nla_context, eInsertKeyFlags flag)
Definition: keyframing.c:1303
void ANIM_OT_keyframe_insert_by_name(wmOperatorType *ot)
Definition: keyframing.c:2046
static int clear_key_button_exec(bContext *C, wmOperator *op)
Definition: keyframing.c:2782
void ANIM_OT_keyframe_delete(wmOperatorType *ot)
Definition: keyframing.c:2219
static int insert_key_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
Definition: keyframing.c:2076
static float * get_keyframe_values(ReportList *reports, PointerRNA ptr, PropertyRNA *prop, int index, struct NlaKeyframingContext *nla_context, eInsertKeyFlags flag, float *buffer, int buffer_size, const struct AnimationEvalContext *anim_eval_context, int *r_count, bool *r_force_all, BLI_bitmap **r_successful_remaps)
Definition: keyframing.c:1172
bool fcurve_frame_has_keyframe(const FCurve *fcu, float frame, short filter)
Definition: keyframing.c:2883
bool id_frame_has_keyframe(ID *id, float frame, short filter)
Main Keyframe Checking API call.
Definition: keyframing.c:3036
static float * setting_get_rna_values(PointerRNA *ptr, PropertyRNA *prop, float *buffer, int buffer_size, int *r_count)
Definition: keyframing.c:780
static void get_keyframe_values_create_reports(ReportList *reports, PointerRNA ptr, PropertyRNA *prop, const int index, const int count, const bool force_all, const BLI_bitmap *successful_remaps)
Definition: keyframing.c:1116
void ANIM_OT_keyframe_clear_v3d(wmOperatorType *ot)
Definition: keyframing.c:2339
static bool delete_keyframe_fcurve(AnimData *adt, FCurve *fcu, float cfra)
Definition: keyframing.c:1686
@ KEYNEEDED_DONTADD
Definition: keyframing.c:654
@ KEYNEEDED_DELPREV
Definition: keyframing.c:656
@ KEYNEEDED_JUSTADD
Definition: keyframing.c:655
@ KEYNEEDED_DELNEXT
Definition: keyframing.c:657
static void update_autoflags_fcurve_direct(FCurve *fcu, PropertyRNA *prop)
Definition: keyframing.c:252
FCurve * ED_action_fcurve_ensure(struct Main *bmain, struct bAction *act, const char group[], struct PointerRNA *ptr, const char rna_path[], const int array_index)
Definition: keyframing.c:173
static void subdivide_nonauto_handles(const FCurve *fcu, BezTriple *bezt, BezTriple *prev, BezTriple *next)
Definition: keyframing.c:503
static void make_new_fcurve_cyclic(const bAction *act, FCurve *fcu)
Definition: keyframing.c:354
static int clear_anim_v3d_exec(bContext *C, wmOperator *UNUSED(op))
Definition: keyframing.c:2274
int insert_bezt_fcurve(FCurve *fcu, const BezTriple *bezt, eInsertKeyFlags flag)
Definition: keyframing.c:410
void ANIM_OT_keyframe_insert_button(wmOperatorType *ot)
Definition: keyframing.c:2651
static bool insert_keyframe_fcurve_value(Main *bmain, ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, bAction *act, const char group[], const char rna_path[], int array_index, const AnimationEvalContext *anim_eval_context, float curval, eBezTriple_KeyframeType keytype, eInsertKeyFlags flag)
Definition: keyframing.c:1389
static KeyingSet * keyingset_get_from_op_with_error(wmOperator *op, PropertyRNA *prop, Scene *scene)
Definition: keyframing.c:3207
static int clear_keyframe(Main *bmain, ReportList *reports, ID *id, bAction *act, const char rna_path[], int array_index, eInsertKeyFlags UNUSED(flag))
Definition: keyframing.c:1830
@ VISUALKEY_LOC
Definition: keyframing.c:849
@ VISUALKEY_NONE
Definition: keyframing.c:848
@ VISUALKEY_SCA
Definition: keyframing.c:851
@ VISUALKEY_ROT
Definition: keyframing.c:850
static AnimationEvalContext nla_time_remap(const AnimationEvalContext *anim_eval_context, PointerRNA *id_ptr, AnimData *adt, bAction *act, ListBase *nla_cache, NlaKeyframingContext **r_nla_context)
Definition: keyframing.c:1454
void update_autoflags_fcurve(FCurve *fcu, bContext *C, ReportList *reports, PointerRNA *ptr)
Lesser Key-framing API call.
Definition: keyframing.c:274
bool ED_autokeyframe_property(bContext *C, Scene *scene, PointerRNA *ptr, PropertyRNA *prop, int rnaindex, float cfra, const bool only_if_property_keyed)
Definition: keyframing.c:3111
static short new_key_needed(FCurve *fcu, float cFrame, float nValue)
Definition: keyframing.c:668
bool autokeyframe_cfra_can_key(const Scene *scene, ID *id)
Definition: keyframing.c:2850
static bool modify_key_op_poll(bContext *C)
Definition: keyframing.c:1938
bool ED_autokeyframe_pchan(bContext *C, Scene *scene, Object *ob, bPoseChannel *pchan, KeyingSet *ks)
Definition: keyframing.c:3090
void ANIM_OT_keyframe_delete_v3d(wmOperatorType *ot)
Definition: keyframing.c:2480
eInsertKeyFlags ANIM_get_keyframing_flags(Scene *scene, const bool use_autokey_mode)
Definition: keyframing.c:82
static bool action_frame_has_keyframe(bAction *act, float frame, short filter)
Definition: keyframing.c:2938
static bool insert_keyframe_value(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, FCurve *fcu, const AnimationEvalContext *anim_eval_context, float curval, eBezTriple_KeyframeType keytype, eInsertKeyFlags flag)
Definition: keyframing.c:1223
static int delete_key_v3d_without_keying_set(bContext *C, wmOperator *op)
Definition: keyframing.c:2356
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 ANIM_OT_keyframe_delete_button(wmOperatorType *ot)
Definition: keyframing.c:2762
void ANIM_OT_keyframe_delete_by_name(wmOperatorType *ot)
Definition: keyframing.c:2244
static int delete_key_using_keying_set(bContext *C, wmOperator *op, KeyingSet *ks)
Definition: keyframing.c:2179
static int delete_key_v3d_exec(bContext *C, wmOperator *op)
Definition: keyframing.c:2468
FCurve * ED_action_fcurve_find(struct bAction *act, const char rna_path[], const int array_index)
Definition: keyframing.c:164
int ANIM_apply_keyingset(bContext *C, ListBase *dsources, bAction *act, KeyingSet *ks, short mode, float cfra)
Definition: keyingsets.c:1038
KeyingSet * ANIM_keyingset_get_from_enum_type(Scene *scene, int type)
Definition: keyingsets.c:847
void ANIM_keyingset_visit_for_search_no_poll(const bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), const char *UNUSED(edit_text), StringPropertySearchVisitFunc visit_fn, void *visit_user_data)
Definition: keyingsets.c:767
KeyingSet * ANIM_scene_get_active_keyingset(const Scene *scene)
Definition: keyingsets.c:647
KeyingSet * ANIM_keyingset_get_from_idname(Scene *scene, const char *idname)
Definition: keyingsets.c:864
void ANIM_relative_keyingset_add_source(ListBase *dsources, ID *id, StructRNA *srna, void *data)
Definition: keyingsets.c:924
bool ANIM_keyingset_find_id(KeyingSet *ks, ID *id)
Definition: keyingsets.c:632
const EnumPropertyItem * ANIM_keying_sets_enum_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
Definition: keyingsets.c:779
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
static ulong * next
#define G(x, y, z)
#define floorf(x)
Definition: metal/compat.h:224
#define fabsf(x)
Definition: metal/compat.h:219
static unsigned a[3]
Definition: RandGen.cpp:78
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
return ret
float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2767
bool RNA_property_array_check(PropertyRNA *prop)
Definition: rna_access.c:1080
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
Definition: rna_access.c:2879
void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
Definition: rna_access.c:112
const char * RNA_property_identifier(const PropertyRNA *prop)
Definition: rna_access.c:1000
bool RNA_property_animateable(const PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:1993
void RNA_property_boolean_get_array(PointerRNA *ptr, PropertyRNA *prop, bool *values)
Definition: rna_access.c:2242
PropertyType RNA_property_type(PropertyRNA *prop)
Definition: rna_access.c:1010
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:717
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2153
void RNA_property_enum_items_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
Definition: rna_access.c:1560
int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2429
void RNA_property_string_get(PointerRNA *ptr, PropertyRNA *prop, char *value)
Definition: rna_access.c:3149
int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:1075
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:3402
void RNA_property_int_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
Definition: rna_access.c:2512
PropertySubType RNA_property_subtype(PropertyRNA *prop)
Definition: rna_access.c:1015
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:5015
bool RNA_path_resolved_create(PointerRNA *ptr, struct PropertyRNA *prop, const int prop_index, PathResolvedRNA *r_anim_rna)
Definition: rna_access.c:6788
const char * RNA_property_ui_name(const PropertyRNA *prop)
Definition: rna_access.c:1875
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_string_search_func_runtime(PropertyRNA *prop, StringPropertySearchFunc search_fn, const eStringPropertySearchFlag search_flag)
Definition: rna_define.c:3373
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3687
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
char * RNA_path_from_ID_to_property(const PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_path.cc:1127
bool RNA_path_resolve_property(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
Definition: rna_path.cc:531
const EnumPropertyItem DummyRNA_DEFAULT_items[]
Definition: rna_rna.c:31
bAction * action
uint8_t h1
uint8_t f3
float vec[3][3]
uint8_t f1
uint8_t f2
uint8_t h2
struct Bone * parent
const char * identifier
Definition: RNA_types.h:461
const char * name
Definition: RNA_types.h:465
struct FCurve * next
bActionGroup * grp
int color_mode
char * rna_path
FPoint * fpt
ChannelDriver * driver
BezTriple * bezt
int array_index
short flag
unsigned int totvert
char auto_smoothing
ListBase modifiers
Definition: DNA_ID.h:368
char name[66]
Definition: DNA_ID.h:378
char name[64]
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
ListBase fcurves
char name[64]
ListBase constraints
struct bPose * pose
struct RigidBodyOb * rigidbody_object
float obmat[4][4]
short rotmode
struct AnimData * adt
struct Object * parent
void * data
struct PropertyRNA * prop
Definition: RNA_types.h:51
struct PointerRNA ptr
Definition: RNA_types.h:50
struct StructRNA * type
Definition: RNA_types.h:37
void * data
Definition: RNA_types.h:38
struct ID * owner_id
Definition: RNA_types.h:36
int active_keyingset
struct ToolSettings * toolsettings
struct RenderData r
ListBase curves
float frame_start
float frame_end
unsigned int layer
struct bConstraint * next
ListBase constraints
struct Bone * bone
struct bPoseChannel * parent
float pose_mat[4][4]
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
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 wmOperatorType * type
struct PointerRNA * ptr
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
const char * WM_operatortype_name(struct wmOperatorType *ot, struct PointerRNA *properties)
int WM_operator_confirm(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))