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