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