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