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