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