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