Py-Driver: add 'self' option
[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                 PathResolvedRNA anim_rna;
937
938                 if (RNA_path_resolved_create(&ptr, prop, fcu->array_index, &anim_rna)) {
939                         /* for making it easier to add corrective drivers... */
940                         cfra = evaluate_driver(&anim_rna, fcu->driver, cfra);
941                 }
942                 else {
943                         cfra = 0.0f;
944                 }
945         }
946         
947         /* obtain value to give keyframe */
948         if ( (flag & INSERTKEY_MATRIX) && 
949              (visualkey_can_use(&ptr, prop)) )
950         {
951                 /* visual-keying is only available for object and pchan datablocks, as 
952                  * it works by keyframing using a value extracted from the final matrix 
953                  * instead of using the kt system to extract a value.
954                  */
955                 curval = visualkey_get_value(&ptr, prop, fcu->array_index);
956         }
957         else {
958                 /* read value from system */
959                 curval = setting_get_rna_value(&ptr, prop, fcu->array_index);
960         }
961         
962         /* only insert keyframes where they are needed */
963         if (flag & INSERTKEY_NEEDED) {
964                 short insert_mode;
965                 
966                 /* check whether this curve really needs a new keyframe */
967                 insert_mode = new_key_needed(fcu, cfra, curval);
968                 
969                 /* insert new keyframe at current frame */
970                 if (insert_mode)
971                         insert_vert_fcurve(fcu, cfra, curval, keytype, flag);
972                 
973                 /* delete keyframe immediately before/after newly added */
974                 switch (insert_mode) {
975                         case KEYNEEDED_DELPREV:
976                                 delete_fcurve_key(fcu, fcu->totvert - 2, 1);
977                                 break;
978                         case KEYNEEDED_DELNEXT:
979                                 delete_fcurve_key(fcu, 1, 1);
980                                 break;
981                 }
982                 
983                 /* only return success if keyframe added */
984                 if (insert_mode)
985                         return true;
986         }
987         else {
988                 /* just insert keyframe */
989                 insert_vert_fcurve(fcu, cfra, curval, keytype, flag);
990                 
991                 /* return success */
992                 return true;
993         }
994         
995         /* failed */
996         return false;
997 }
998
999 /* Main Keyframing API call:
1000  *      Use this when validation of necessary animation data is necessary, since it may not exist yet.
1001  *      
1002  *      The flag argument is used for special settings that alter the behavior of
1003  *      the keyframe insertion. These include the 'visual' keyframing modes, quick refresh,
1004  *      and extra keyframe filtering.
1005  *
1006  *      index of -1 keys all array indices
1007  */
1008 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)
1009 {       
1010         PointerRNA id_ptr, ptr;
1011         PropertyRNA *prop = NULL;
1012         AnimData *adt;
1013         FCurve *fcu;
1014         int array_index_max = array_index + 1;
1015         int ret = 0;
1016         
1017         /* validate pointer first - exit if failure */
1018         if (id == NULL) {
1019                 BKE_reportf(reports, RPT_ERROR, "No ID block to insert keyframe in (path = %s)", rna_path);
1020                 return 0;
1021         }
1022         
1023         RNA_id_pointer_create(id, &id_ptr);
1024         if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
1025                 BKE_reportf(reports, RPT_ERROR,
1026                             "Could not insert keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)",
1027                             (id) ? id->name : TIP_("<Missing ID block>"), rna_path);
1028                 return 0;
1029         }
1030         
1031         /* if no action is provided, keyframe to the default one attached to this ID-block */
1032         if (act == NULL) {
1033                 /* get action to add F-Curve+keyframe to */
1034                 act = verify_adt_action(id, 1);
1035                 
1036                 if (act == NULL) {
1037                         BKE_reportf(reports, RPT_ERROR, 
1038                                     "Could not insert keyframe, as this type does not support animation data (ID = %s, path = %s)",
1039                                     id->name, rna_path);
1040                         return 0;
1041                 }
1042         }
1043         
1044         /* apply NLA-mapping to frame to use (if applicable) */
1045         adt = BKE_animdata_from_id(id);
1046         cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
1047         
1048         /* key entire array convenience method */
1049         if (array_index == -1) {
1050                 array_index = 0;
1051                 array_index_max = RNA_property_array_length(&ptr, prop);
1052                 
1053                 /* for single properties, increase max_index so that the property itself gets included,
1054                  * but don't do this for standard arrays since that can cause corruption issues 
1055                  * (extra unused curves)
1056                  */
1057                 if (array_index_max == array_index)
1058                         array_index_max++;
1059         }
1060         
1061         /* will only loop once unless the array index was -1 */
1062         for (; array_index < array_index_max; array_index++) {
1063                 /* make sure the F-Curve exists 
1064                  *      - if we're replacing keyframes only, DO NOT create new F-Curves if they do not exist yet
1065                  *        but still try to get the F-Curve if it exists...
1066                  */
1067                 fcu = verify_fcurve(act, group, &ptr, rna_path, array_index, (flag & INSERTKEY_REPLACE) == 0);
1068                 
1069                 /* we may not have a F-Curve when we're replacing only... */
1070                 if (fcu) {
1071                         /* set color mode if the F-Curve is new (i.e. without any keyframes) */
1072                         if ((fcu->totvert == 0) && (flag & INSERTKEY_XYZ2RGB)) {
1073                                 /* for Loc/Rot/Scale and also Color F-Curves, the color of the F-Curve in the Graph Editor,
1074                                  * is determined by the array index for the F-Curve
1075                                  */
1076                                 if (ELEM(RNA_property_subtype(prop), PROP_TRANSLATION, PROP_XYZ, PROP_EULER, PROP_COLOR, PROP_COORDS)) {
1077                                         fcu->color_mode = FCURVE_COLOR_AUTO_RGB;
1078                                 }
1079                                 else if (RNA_property_subtype(prop), PROP_QUATERNION) {
1080                                         fcu->color_mode = FCURVE_COLOR_AUTO_YRGB;
1081                                 }
1082                         }
1083                         
1084                         /* insert keyframe */
1085                         ret += insert_keyframe_direct(reports, ptr, prop, fcu, cfra, keytype, flag);
1086                 }
1087         }
1088         
1089         return ret;
1090 }
1091
1092 /* ************************************************** */
1093 /* KEYFRAME DELETION */
1094
1095 /* Main Keyframing API call:
1096  *      Use this when validation of necessary animation data isn't necessary as it
1097  *      already exists. It will delete a keyframe at the current frame.
1098  *      
1099  *      The flag argument is used for special settings that alter the behavior of
1100  *      the keyframe deletion. These include the quick refresh options.
1101  */
1102
1103
1104
1105 /**
1106  * \note caller needs to run #BKE_nla_tweakedit_remap to get NLA relative frame.
1107  *       caller should also check #BKE_fcurve_is_protected before keying.
1108  */
1109 static bool delete_keyframe_fcurve(AnimData *adt, FCurve *fcu, float cfra)
1110 {
1111         bool found;
1112         int i;
1113
1114         /* try to find index of beztriple to get rid of */
1115         i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found);
1116         if (found) {
1117                 /* delete the key at the index (will sanity check + do recalc afterwards) */
1118                 delete_fcurve_key(fcu, i, 1);
1119
1120                 /* Only delete curve too if it won't be doing anything anymore */
1121                 if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0))
1122                         ANIM_fcurve_delete_from_animdata(NULL, adt, fcu);
1123
1124                 /* return success */
1125                 return true;
1126         }
1127         return false;
1128 }
1129
1130 short delete_keyframe(ReportList *reports, ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short UNUSED(flag))
1131 {
1132         AnimData *adt = BKE_animdata_from_id(id);
1133         PointerRNA id_ptr, ptr;
1134         PropertyRNA *prop;
1135         int array_index_max = array_index + 1;
1136         int ret = 0;
1137         
1138         /* sanity checks */
1139         if (ELEM(NULL, id, adt)) {
1140                 BKE_report(reports, RPT_ERROR, "No ID block and/or AnimData to delete keyframe from");
1141                 return 0;
1142         }
1143         
1144         /* validate pointer first - exit if failure */
1145         RNA_id_pointer_create(id, &id_ptr);
1146         if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
1147                 BKE_reportf(reports, RPT_ERROR,
1148                             "Could not delete keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)",
1149                             id->name, rna_path);
1150                 return 0;
1151         }
1152         
1153         /* get F-Curve
1154          * Note: here is one of the places where we don't want new Action + F-Curve added!
1155          *      so 'add' var must be 0
1156          */
1157         if (act == NULL) {
1158                 /* if no action is provided, use the default one attached to this ID-block 
1159                  *  - if it doesn't exist, then we're out of options...
1160                  */
1161                 if (adt->action) {
1162                         act = adt->action;
1163                         
1164                         /* apply NLA-mapping to frame to use (if applicable) */
1165                         cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
1166                 }
1167                 else {
1168                         BKE_reportf(reports, RPT_ERROR, "No action to delete keyframes from for ID = %s", id->name);
1169                         return 0;
1170                 }
1171         }
1172         
1173         /* key entire array convenience method */
1174         if (array_index == -1) {
1175                 array_index = 0;
1176                 array_index_max = RNA_property_array_length(&ptr, prop);
1177                 
1178                 /* for single properties, increase max_index so that the property itself gets included,
1179                  * but don't do this for standard arrays since that can cause corruption issues 
1180                  * (extra unused curves)
1181                  */
1182                 if (array_index_max == array_index)
1183                         array_index_max++;
1184         }
1185         
1186         /* will only loop once unless the array index was -1 */
1187         for (; array_index < array_index_max; array_index++) {
1188                 FCurve *fcu = verify_fcurve(act, group, &ptr, rna_path, array_index, 0);
1189
1190                 /* check if F-Curve exists and/or whether it can be edited */
1191                 if (fcu == NULL)
1192                         continue;
1193
1194                 if (BKE_fcurve_is_protected(fcu)) {
1195                         BKE_reportf(reports, RPT_WARNING,
1196                                     "Not deleting keyframe for locked F-Curve '%s' for %s '%s'",
1197                                     fcu->rna_path, BKE_idcode_to_name(GS(id->name)), id->name + 2);
1198                         continue;
1199                 }
1200
1201                 ret += delete_keyframe_fcurve(adt, fcu, cfra);
1202
1203         }
1204         
1205         /* return success/failure */
1206         return ret;
1207 }
1208
1209 /* ************************************************** */
1210 /* KEYFRAME CLEAR */
1211
1212 /* Main Keyframing API call:
1213  *      Use this when validation of necessary animation data isn't necessary as it
1214  *      already exists. It will clear the current buttons fcurve(s).
1215  *
1216  *      The flag argument is used for special settings that alter the behavior of
1217  *      the keyframe deletion. These include the quick refresh options.
1218  */
1219 static short clear_keyframe(ReportList *reports, ID *id, bAction *act, const char group[], const char rna_path[], int array_index, short UNUSED(flag))
1220 {
1221         AnimData *adt = BKE_animdata_from_id(id);
1222         PointerRNA id_ptr, ptr;
1223         PropertyRNA *prop;
1224         int array_index_max = array_index + 1;
1225         int ret = 0;
1226
1227         /* sanity checks */
1228         if (ELEM(NULL, id, adt)) {
1229                 BKE_report(reports, RPT_ERROR, "No ID block and/or AnimData to delete keyframe from");
1230                 return 0;
1231         }
1232
1233         /* validate pointer first - exit if failure */
1234         RNA_id_pointer_create(id, &id_ptr);
1235         if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
1236                 BKE_reportf(reports, RPT_ERROR,
1237                             "Could not clear keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)",
1238                             id->name, rna_path);
1239                 return 0;
1240         }
1241
1242         /* get F-Curve
1243          * Note: here is one of the places where we don't want new Action + F-Curve added!
1244          *      so 'add' var must be 0
1245          */
1246         if (act == NULL) {
1247                 /* if no action is provided, use the default one attached to this ID-block
1248                  *  - if it doesn't exist, then we're out of options...
1249                  */
1250                 if (adt->action) {
1251                         act = adt->action;
1252                 }
1253                 else {
1254                         BKE_reportf(reports, RPT_ERROR, "No action to delete keyframes from for ID = %s", id->name);
1255                         return 0;
1256                 }
1257         }
1258
1259         /* key entire array convenience method */
1260         if (array_index == -1) {
1261                 array_index = 0;
1262                 array_index_max = RNA_property_array_length(&ptr, prop);
1263
1264                 /* for single properties, increase max_index so that the property itself gets included,
1265                  * but don't do this for standard arrays since that can cause corruption issues
1266                  * (extra unused curves)
1267                  */
1268                 if (array_index_max == array_index)
1269                         array_index_max++;
1270         }
1271
1272         /* will only loop once unless the array index was -1 */
1273         for (; array_index < array_index_max; array_index++) {
1274                 FCurve *fcu = verify_fcurve(act, group, &ptr, rna_path, array_index, 0);
1275
1276                 /* check if F-Curve exists and/or whether it can be edited */
1277                 if (fcu == NULL)
1278                         continue;
1279
1280                 if (BKE_fcurve_is_protected(fcu)) {
1281                         BKE_reportf(reports, RPT_WARNING,
1282                                     "Not clearing all keyframes from locked F-Curve '%s' for %s '%s'",
1283                                     fcu->rna_path, BKE_idcode_to_name(GS(id->name)), id->name + 2);
1284                         continue;
1285                 }
1286
1287                 ANIM_fcurve_delete_from_animdata(NULL, adt, fcu);
1288
1289                 /* return success */
1290                 ret++;
1291         }
1292
1293         /* return success/failure */
1294         return ret;
1295 }
1296
1297 /* ******************************************* */
1298 /* KEYFRAME MODIFICATION */
1299
1300 /* mode for commonkey_modifykey */
1301 enum {
1302         COMMONKEY_MODE_INSERT = 0,
1303         COMMONKEY_MODE_DELETE,
1304 } /*eCommonModifyKey_Modes*/;
1305
1306 /* Polling callback for use with ANIM_*_keyframe() operators
1307  * This is based on the standard ED_operator_areaactive callback,
1308  * except that it does special checks for a few spacetypes too...
1309  */
1310 static int modify_key_op_poll(bContext *C)
1311 {
1312         ScrArea *sa = CTX_wm_area(C);
1313         Scene *scene = CTX_data_scene(C);
1314         
1315         /* if no area or active scene */
1316         if (ELEM(NULL, sa, scene)) 
1317                 return false;
1318         
1319         /* should be fine */
1320         return true;
1321 }
1322
1323 /* Insert Key Operator ------------------------ */
1324
1325 static int insert_key_exec(bContext *C, wmOperator *op)
1326 {
1327         Scene *scene = CTX_data_scene(C);
1328         Object *obedit = CTX_data_edit_object(C);
1329         bool ob_edit_mode = false;
1330         KeyingSet *ks = NULL;
1331         int type = RNA_enum_get(op->ptr, "type");
1332         float cfra = (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
1333         short success;
1334         
1335         /* type is the Keying Set the user specified to use when calling the operator:
1336          *      - type == 0: use scene's active Keying Set
1337          *      - type > 0: use a user-defined Keying Set from the active scene
1338          *      - type < 0: use a builtin Keying Set
1339          */
1340         if (type == 0) 
1341                 type = scene->active_keyingset;
1342         if (type > 0)
1343                 ks = BLI_findlink(&scene->keyingsets, type - 1);
1344         else
1345                 ks = BLI_findlink(&builtin_keyingsets, -type - 1);
1346                 
1347         /* report failures */
1348         if (ks == NULL) {
1349                 BKE_report(op->reports, RPT_ERROR, "No active keying set");
1350                 return OPERATOR_CANCELLED;
1351         }
1352
1353         /* exit the edit mode to make sure that those object data properties that have been
1354          * updated since the last switching to the edit mode will be keyframed correctly
1355          */
1356         if (obedit && ANIM_keyingset_find_id(ks, (ID *)obedit->data)) {
1357                 ED_object_toggle_modes(C, OB_MODE_EDIT);
1358                 ob_edit_mode = true;
1359         }
1360         
1361         /* try to insert keyframes for the channels specified by KeyingSet */
1362         success = ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
1363         if (G.debug & G_DEBUG)
1364                 BKE_reportf(op->reports, RPT_INFO, "Keying set '%s' - successfully added %d keyframes", ks->name, success);
1365         
1366         /* restore the edit mode if necessary */
1367         if (ob_edit_mode) {
1368                 ED_object_toggle_modes(C, OB_MODE_EDIT);
1369         }
1370
1371         /* report failure or do updates? */
1372         if (success == MODIFYKEY_INVALID_CONTEXT) {
1373                 BKE_report(op->reports, RPT_ERROR, "No suitable context info for active keying set");
1374                 return OPERATOR_CANCELLED;
1375         }
1376         else if (success) {
1377                 /* if the appropriate properties have been set, make a note that we've inserted something */
1378                 if (RNA_boolean_get(op->ptr, "confirm_success"))
1379                         BKE_reportf(op->reports, RPT_INFO, "Successfully added %d keyframes for keying set '%s'", success, ks->name);
1380                 
1381                 /* send notifiers that keyframes have been changed */
1382                 WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
1383         }
1384         else
1385                 BKE_report(op->reports, RPT_WARNING, "Keying set failed to insert any keyframes");
1386         
1387         return OPERATOR_FINISHED;
1388 }
1389
1390 void ANIM_OT_keyframe_insert(wmOperatorType *ot)
1391 {
1392         PropertyRNA *prop;
1393         
1394         /* identifiers */
1395         ot->name = "Insert Keyframe";
1396         ot->idname = "ANIM_OT_keyframe_insert";
1397         ot->description = "Insert keyframes on the current frame for all properties in the specified Keying Set";
1398         
1399         /* callbacks */
1400         ot->exec = insert_key_exec; 
1401         ot->poll = modify_key_op_poll;
1402         
1403         /* flags */
1404         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1405         
1406         /* keyingset to use (dynamic enum) */
1407         prop = RNA_def_enum(ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
1408         RNA_def_enum_funcs(prop, ANIM_keying_sets_enum_itemf);
1409         RNA_def_property_flag(prop, PROP_HIDDEN);
1410         ot->prop = prop;
1411         
1412         /* confirm whether a keyframe was added by showing a popup 
1413          *      - by default, this is enabled, since this operator is assumed to be called independently
1414          */
1415         prop = RNA_def_boolean(ot->srna, "confirm_success", 1, "Confirm Successful Insert",
1416                                "Show a popup when the keyframes get successfully added");
1417         RNA_def_property_flag(prop, PROP_HIDDEN);
1418 }
1419
1420 /* Insert Key Operator (With Menu) ------------------------ */
1421 /* This operator checks if a menu should be shown for choosing the KeyingSet to use, 
1422  * then calls the menu if necessary before 
1423  */
1424
1425 static int insert_key_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1426 {
1427         Scene *scene = CTX_data_scene(C);
1428         
1429         /* if prompting or no active Keying Set, show the menu */
1430         if ((scene->active_keyingset == 0) || RNA_boolean_get(op->ptr, "always_prompt")) {
1431                 uiPopupMenu *pup;
1432                 uiLayout *layout;
1433                 
1434                 /* call the menu, which will call this operator again, hence the canceled */
1435                 pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
1436                 layout = UI_popup_menu_layout(pup);
1437                 uiItemsEnumO(layout, "ANIM_OT_keyframe_insert_menu", "type");
1438                 UI_popup_menu_end(C, pup);
1439                 
1440                 return OPERATOR_INTERFACE;
1441         }
1442         else {
1443                 /* just call the exec() on the active keyingset */
1444                 RNA_enum_set(op->ptr, "type", 0);
1445                 RNA_boolean_set(op->ptr, "confirm_success", true);
1446                 
1447                 return op->type->exec(C, op);
1448         }
1449 }
1450  
1451 void ANIM_OT_keyframe_insert_menu(wmOperatorType *ot)
1452 {
1453         PropertyRNA *prop;
1454         
1455         /* identifiers */
1456         ot->name = "Insert Keyframe Menu";
1457         ot->idname = "ANIM_OT_keyframe_insert_menu";
1458         ot->description = "Insert Keyframes for specified Keying Set, with menu of available Keying Sets if undefined";
1459         
1460         /* callbacks */
1461         ot->invoke = insert_key_menu_invoke;
1462         ot->exec = insert_key_exec; 
1463         ot->poll = ED_operator_areaactive;
1464         
1465         /* flags */
1466         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1467         
1468         /* keyingset to use (dynamic enum) */
1469         prop = RNA_def_enum(ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
1470         RNA_def_enum_funcs(prop, ANIM_keying_sets_enum_itemf);
1471         RNA_def_property_flag(prop, PROP_HIDDEN);
1472         ot->prop = prop;
1473         
1474         /* confirm whether a keyframe was added by showing a popup 
1475          *      - by default, this is disabled so that if a menu is shown, this doesn't come up too
1476          */
1477         // XXX should this just be always on?
1478         prop = RNA_def_boolean(ot->srna, "confirm_success", 0, "Confirm Successful Insert",
1479                                "Show a popup when the keyframes get successfully added");
1480         RNA_def_property_flag(prop, PROP_HIDDEN);
1481         
1482         /* whether the menu should always be shown 
1483          *      - by default, the menu should only be shown when there is no active Keying Set (2.5 behavior),
1484          *        although in some cases it might be useful to always shown (pre 2.5 behavior)
1485          */
1486         prop = RNA_def_boolean(ot->srna, "always_prompt", 0, "Always Show Menu", "");
1487         RNA_def_property_flag(prop, PROP_HIDDEN);
1488 }
1489
1490 /* Delete Key Operator ------------------------ */
1491
1492 static int delete_key_exec(bContext *C, wmOperator *op)
1493 {
1494         Scene *scene = CTX_data_scene(C);
1495         KeyingSet *ks = NULL;
1496         int type = RNA_enum_get(op->ptr, "type");
1497         float cfra = (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
1498         short success;
1499         
1500         /* type is the Keying Set the user specified to use when calling the operator:
1501          *      - type == 0: use scene's active Keying Set
1502          *      - type > 0: use a user-defined Keying Set from the active scene
1503          *      - type < 0: use a builtin Keying Set
1504          */
1505         if (type == 0) 
1506                 type = scene->active_keyingset;
1507         if (type > 0)
1508                 ks = BLI_findlink(&scene->keyingsets, type - 1);
1509         else
1510                 ks = BLI_findlink(&builtin_keyingsets, -type - 1);
1511         
1512         /* report failure */
1513         if (ks == NULL) {
1514                 BKE_report(op->reports, RPT_ERROR, "No active Keying Set");
1515                 return OPERATOR_CANCELLED;
1516         }
1517         
1518         /* try to delete keyframes for the channels specified by KeyingSet */
1519         success = ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_DELETE, cfra);
1520         if (G.debug & G_DEBUG)
1521                 printf("KeyingSet '%s' - Successfully removed %d Keyframes\n", ks->name, success);
1522         
1523         /* report failure or do updates? */
1524         if (success == MODIFYKEY_INVALID_CONTEXT) {
1525                 BKE_report(op->reports, RPT_ERROR, "No suitable context info for active keying set");
1526                 return OPERATOR_CANCELLED;
1527         }
1528         else if (success) {
1529                 /* if the appropriate properties have been set, make a note that we've inserted something */
1530                 if (RNA_boolean_get(op->ptr, "confirm_success"))
1531                         BKE_reportf(op->reports, RPT_INFO, "Successfully removed %d keyframes for keying set '%s'", success, ks->name);
1532                 
1533                 /* send notifiers that keyframes have been changed */
1534                 WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL);
1535         }
1536         else
1537                 BKE_report(op->reports, RPT_WARNING, "Keying set failed to remove any keyframes");
1538         
1539         return OPERATOR_FINISHED;
1540 }
1541
1542 void ANIM_OT_keyframe_delete(wmOperatorType *ot)
1543 {
1544         PropertyRNA *prop;
1545         
1546         /* identifiers */
1547         ot->name = "Delete Keying-Set Keyframe";
1548         ot->idname = "ANIM_OT_keyframe_delete";
1549         ot->description = "Delete keyframes on the current frame for all properties in the specified Keying Set";
1550         
1551         /* callbacks */
1552         ot->exec = delete_key_exec; 
1553         ot->poll = modify_key_op_poll;
1554         
1555         /* flags */
1556         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1557         
1558         /* keyingset to use (dynamic enum) */
1559         prop = RNA_def_enum(ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
1560         RNA_def_enum_funcs(prop, ANIM_keying_sets_enum_itemf);
1561         RNA_def_property_flag(prop, PROP_HIDDEN);
1562         ot->prop = prop;
1563         
1564         /* confirm whether a keyframe was added by showing a popup 
1565          *      - by default, this is enabled, since this operator is assumed to be called independently
1566          */
1567         RNA_def_boolean(ot->srna, "confirm_success", 1, "Confirm Successful Delete",
1568                         "Show a popup when the keyframes get successfully removed");
1569 }
1570
1571 /* Delete Key Operator ------------------------ */
1572 /* NOTE: Although this version is simpler than the more generic version for KeyingSets,
1573  * it is more useful for animators working in the 3D view.
1574  */
1575  
1576 static int clear_anim_v3d_exec(bContext *C, wmOperator *UNUSED(op))
1577 {
1578         bool changed = false;
1579
1580         CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
1581         {
1582                 /* just those in active action... */
1583                 if ((ob->adt) && (ob->adt->action)) {
1584                         AnimData *adt = ob->adt;
1585                         bAction *act = adt->action;
1586                         FCurve *fcu, *fcn;
1587                         
1588                         for (fcu = act->curves.first; fcu; fcu = fcn) {
1589                                 bool can_delete = false;
1590                                 
1591                                 fcn = fcu->next;
1592                                 
1593                                 /* in pose mode, only delete the F-Curve if it belongs to a selected bone */
1594                                 if (ob->mode & OB_MODE_POSE) {
1595                                         if ((fcu->rna_path) && strstr(fcu->rna_path, "pose.bones[")) {
1596                                                 bPoseChannel *pchan;
1597                                                 char *bone_name;
1598                                                 
1599                                                 /* get bone-name, and check if this bone is selected */
1600                                                 bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
1601                                                 pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
1602                                                 if (bone_name) MEM_freeN(bone_name);
1603                                                 
1604                                                 /* delete if bone is selected*/
1605                                                 if ((pchan) && (pchan->bone)) {
1606                                                         if (pchan->bone->flag & BONE_SELECTED)
1607                                                                 can_delete = true;
1608                                                 }
1609                                         }
1610                                 }
1611                                 else {
1612                                         /* object mode - all of Object's F-Curves are affected */
1613                                         can_delete = true;
1614                                 }
1615                                 
1616                                 /* delete F-Curve completely */
1617                                 if (can_delete) {
1618                                         ANIM_fcurve_delete_from_animdata(NULL, adt, fcu);
1619                                         DAG_id_tag_update(&ob->id, OB_RECALC_OB);
1620                                         changed = true;
1621                                 }
1622                         }
1623                 }
1624         }
1625         CTX_DATA_END;
1626
1627         if (!changed) {
1628                 return OPERATOR_CANCELLED;
1629         }
1630
1631         /* send updates */
1632         WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
1633         
1634         return OPERATOR_FINISHED;
1635 }
1636
1637 void ANIM_OT_keyframe_clear_v3d(wmOperatorType *ot)
1638 {
1639         /* identifiers */
1640         ot->name = "Remove Animation";
1641         ot->description = "Remove all keyframe animation for selected objects";
1642         ot->idname = "ANIM_OT_keyframe_clear_v3d";
1643         
1644         /* callbacks */
1645         ot->invoke = WM_operator_confirm;
1646         ot->exec = clear_anim_v3d_exec; 
1647         
1648         ot->poll = ED_operator_areaactive;
1649         
1650         /* flags */
1651         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1652 }
1653
1654
1655 static int delete_key_v3d_exec(bContext *C, wmOperator *op)
1656 {
1657         Scene *scene = CTX_data_scene(C);
1658         float cfra = (float)CFRA;
1659         
1660         CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
1661         {
1662                 ID *id = &ob->id;
1663                 int success = 0;
1664                 
1665                 /* just those in active action... */
1666                 if ((ob->adt) && (ob->adt->action)) {
1667                         AnimData *adt = ob->adt;
1668                         bAction *act = adt->action;
1669                         FCurve *fcu, *fcn;
1670                         const float cfra_unmap = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
1671                         
1672                         for (fcu = act->curves.first; fcu; fcu = fcn) {
1673                                 fcn = fcu->next;
1674                                 
1675                                 /* don't touch protected F-Curves */
1676                                 if (BKE_fcurve_is_protected(fcu)) {
1677                                         BKE_reportf(op->reports, RPT_WARNING,
1678                                                     "Not deleting keyframe for locked F-Curve '%s', object '%s'",
1679                                                     fcu->rna_path, id->name + 2);
1680                                         continue;
1681                                 }
1682                                 
1683                                 /* special exception for bones, as this makes this operator more convenient to use
1684                                  * NOTE: This is only done in pose mode. In object mode, we're dealign with the entire object.
1685                                  */
1686                                 if ((ob->mode & OB_MODE_POSE) && strstr(fcu->rna_path, "pose.bones[\"")) {
1687                                         bPoseChannel *pchan;
1688                                         char *bone_name;
1689                                         
1690                                         /* get bone-name, and check if this bone is selected */
1691                                         bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
1692                                         pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
1693                                         if (bone_name) MEM_freeN(bone_name);
1694                                         
1695                                         /* skip if bone is not selected */
1696                                         if ((pchan) && (pchan->bone)) {
1697                                                 /* bones are only selected/editable if visible... */
1698                                                 bArmature *arm = (bArmature *)ob->data;
1699                                         
1700                                                 /* skipping - not visible on currently visible layers */
1701                                                 if ((arm->layer & pchan->bone->layer) == 0)
1702                                                         continue;
1703                                                 /* skipping - is currently hidden */
1704                                                 if (pchan->bone->flag & BONE_HIDDEN_P)
1705                                                         continue;
1706                                                 
1707                                                 /* selection flag... */
1708                                                 if ((pchan->bone->flag & BONE_SELECTED) == 0)
1709                                                         continue;
1710                                         }
1711                                 }
1712                                 
1713                                 /* delete keyframes on current frame 
1714                                  * WARNING: this can delete the next F-Curve, hence the "fcn" copying
1715                                  */
1716                                 success += delete_keyframe_fcurve(adt, fcu, cfra_unmap);
1717                         }
1718                 }
1719                 
1720                 /* report success (or failure) */
1721                 if (success)
1722                         BKE_reportf(op->reports, RPT_INFO, "Object '%s' successfully had %d keyframes removed", id->name + 2, success);
1723                 else
1724                         BKE_reportf(op->reports, RPT_ERROR, "No keyframes removed from Object '%s'", id->name + 2);
1725                 
1726                 DAG_id_tag_update(&ob->id, OB_RECALC_OB);
1727         }
1728         CTX_DATA_END;
1729         
1730         /* send updates */
1731         WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
1732         
1733         return OPERATOR_FINISHED;
1734 }
1735
1736 void ANIM_OT_keyframe_delete_v3d(wmOperatorType *ot)
1737 {
1738         /* identifiers */
1739         ot->name = "Delete Keyframe";
1740         ot->description = "Remove keyframes on current frame for selected objects and bones";
1741         ot->idname = "ANIM_OT_keyframe_delete_v3d";
1742         
1743         /* callbacks */
1744         ot->invoke = WM_operator_confirm;
1745         ot->exec = delete_key_v3d_exec; 
1746         
1747         ot->poll = ED_operator_areaactive;
1748         
1749         /* flags */
1750         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1751 }
1752
1753
1754 /* Insert Key Button Operator ------------------------ */
1755
1756 static int insert_key_button_exec(bContext *C, wmOperator *op)
1757 {
1758         Scene *scene = CTX_data_scene(C);
1759         ToolSettings *ts = scene->toolsettings;
1760         PointerRNA ptr = {{NULL}};
1761         PropertyRNA *prop = NULL;
1762         char *path;
1763         uiBut *but;
1764         float cfra = (float)CFRA;
1765         short success = 0;
1766         int index;
1767         const bool all = RNA_boolean_get(op->ptr, "all");
1768         short flag = 0;
1769         
1770         /* flags for inserting keyframes */
1771         flag = ANIM_get_keyframing_flags(scene, 1);
1772         
1773         /* try to insert keyframe using property retrieved from UI */
1774         but = UI_context_active_but_get(C);
1775         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
1776         
1777         if ((ptr.id.data && ptr.data && prop) && RNA_property_animateable(&ptr, prop)) {
1778                 if (ptr.type == &RNA_NlaStrip) {
1779                         /* Handle special properties for NLA Strips, whose F-Curves are stored on the
1780                          * strips themselves. These are stored separately or else the properties will
1781                          * not have any effect.
1782                          */
1783                         NlaStrip *strip = (NlaStrip *)ptr.data;
1784                         FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), index);
1785                         
1786                         success = insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, ts->keyframe_type, 0);
1787                 }
1788                 else if (UI_but_flag_is_set(but, UI_BUT_DRIVEN)) {
1789                         /* Driven property - Find driver */
1790                         FCurve *fcu;
1791                         bool driven, special;
1792                         
1793                         fcu = rna_get_fcurve_context_ui(C, &ptr, prop, index, NULL, NULL, &driven, &special);
1794                         
1795                         if (fcu && driven) {
1796                                 success = insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, ts->keyframe_type, INSERTKEY_DRIVER);
1797                         }
1798                 }
1799                 else {
1800                         /* standard properties */
1801                         path = RNA_path_from_ID_to_property(&ptr, prop);
1802                         
1803                         if (path) {
1804                                 if (all) {
1805                                         /* -1 indicates operating on the entire array (or the property itself otherwise) */
1806                                         index = -1;
1807                                 }
1808                                 
1809                                 success = insert_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index, cfra, ts->keyframe_type, flag);
1810                                 
1811                                 MEM_freeN(path);
1812                         }
1813                         else {
1814                                 BKE_report(op->reports, RPT_WARNING, 
1815                                            "Failed to resolve path to property, "
1816                                            "try manually specifying this using a Keying Set instead");
1817                         }
1818                 }
1819         }
1820         else {
1821                 if (prop && !RNA_property_animateable(&ptr, prop)) {
1822                         BKE_reportf(op->reports, RPT_WARNING, 
1823                                    "\"%s\" property cannot be animated",
1824                                    RNA_property_identifier(prop));
1825                 }
1826                 else {
1827                         BKE_reportf(op->reports, RPT_WARNING,
1828                                     "Button doesn't appear to have any property information attached (ptr.data = %p, prop = %p)",
1829                                     (void *)ptr.data, (void *)prop);
1830                 }
1831         }
1832         
1833         if (success) {
1834                 /* send updates */
1835                 UI_context_update_anim_flag(C);
1836                 
1837                 /* send notifiers that keyframes have been changed */
1838                 WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
1839         }
1840         
1841         return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
1842 }
1843
1844 void ANIM_OT_keyframe_insert_button(wmOperatorType *ot)
1845 {
1846         /* identifiers */
1847         ot->name = "Insert Keyframe (Buttons)";
1848         ot->idname = "ANIM_OT_keyframe_insert_button";
1849         ot->description = "Insert a keyframe for current UI-active property";
1850         
1851         /* callbacks */
1852         ot->exec = insert_key_button_exec; 
1853         ot->poll = modify_key_op_poll;
1854         
1855         /* flags */
1856         ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
1857
1858         /* properties */
1859         RNA_def_boolean(ot->srna, "all", 1, "All", "Insert a keyframe for all element of the array");
1860 }
1861
1862 /* Delete Key Button Operator ------------------------ */
1863
1864 static int delete_key_button_exec(bContext *C, wmOperator *op)
1865 {
1866         Scene *scene = CTX_data_scene(C);
1867         PointerRNA ptr = {{NULL}};
1868         PropertyRNA *prop = NULL;
1869         char *path;
1870         float cfra = (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
1871         short success = 0;
1872         int index;
1873         const bool all = RNA_boolean_get(op->ptr, "all");
1874         
1875         /* try to insert keyframe using property retrieved from UI */
1876         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
1877
1878         if (ptr.id.data && ptr.data && prop) {
1879                 if (ptr.type == &RNA_NlaStrip) {
1880                         /* Handle special properties for NLA Strips, whose F-Curves are stored on the
1881                          * strips themselves. These are stored separately or else the properties will
1882                          * not have any effect.
1883                          */
1884                         ID *id = ptr.id.data;
1885                         NlaStrip *strip = (NlaStrip *)ptr.data;
1886                         FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), 0);
1887                         
1888                         BLI_assert(fcu != NULL); /* NOTE: This should be true, or else we wouldn't be able to get here */
1889                         
1890                         if (BKE_fcurve_is_protected(fcu)) {
1891                                 BKE_reportf(op->reports, RPT_WARNING,
1892                                             "Not deleting keyframe for locked F-Curve for NLA Strip influence on %s - %s '%s'",
1893                                             strip->name, BKE_idcode_to_name(GS(id->name)), id->name + 2);
1894                         }
1895                         else {
1896                                 /* remove the keyframe directly
1897                                  * NOTE: cannot use delete_keyframe_fcurve(), as that will free the curve,
1898                                  *       and delete_keyframe() expects the FCurve to be part of an action
1899                                  */
1900                                 bool found = false;
1901                                 int i;
1902                                 
1903                                 /* try to find index of beztriple to get rid of */
1904                                 i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found);
1905                                 if (found) {
1906                                         /* delete the key at the index (will sanity check + do recalc afterwards) */
1907                                         delete_fcurve_key(fcu, i, 1);
1908                                         success = true;
1909                                 }
1910                         }
1911                 }
1912                 else {
1913                         /* standard properties */
1914                         path = RNA_path_from_ID_to_property(&ptr, prop);
1915                         
1916                         if (path) {
1917                                 if (all) {
1918                                         /* -1 indicates operating on the entire array (or the property itself otherwise) */
1919                                         index = -1;
1920                                 }
1921                                 
1922                                 success = delete_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index, cfra, 0);
1923                                 MEM_freeN(path);
1924                         }
1925                         else if (G.debug & G_DEBUG)
1926                                 printf("Button Delete-Key: no path to property\n");
1927                 }
1928         }
1929         else if (G.debug & G_DEBUG) {
1930                 printf("ptr.data = %p, prop = %p\n", (void *)ptr.data, (void *)prop);
1931         }
1932         
1933         
1934         if (success) {
1935                 /* send updates */
1936                 UI_context_update_anim_flag(C);
1937                 
1938                 /* send notifiers that keyframes have been changed */
1939                 WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL);
1940         }
1941         
1942         return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
1943 }
1944
1945 void ANIM_OT_keyframe_delete_button(wmOperatorType *ot)
1946 {
1947         /* identifiers */
1948         ot->name = "Delete Keyframe (Buttons)";
1949         ot->idname = "ANIM_OT_keyframe_delete_button";
1950         ot->description = "Delete current keyframe of current UI-active property";
1951         
1952         /* callbacks */
1953         ot->exec = delete_key_button_exec; 
1954         ot->poll = modify_key_op_poll;
1955         
1956         /* flags */
1957         ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
1958
1959         /* properties */
1960         RNA_def_boolean(ot->srna, "all", 1, "All", "Delete keyframes from all elements of the array");
1961 }
1962
1963
1964 /* Clear Key Button Operator ------------------------ */
1965
1966 static int clear_key_button_exec(bContext *C, wmOperator *op)
1967 {
1968         PointerRNA ptr = {{NULL}};
1969         PropertyRNA *prop = NULL;
1970         char *path;
1971         short success = 0;
1972         int index;
1973         const bool all = RNA_boolean_get(op->ptr, "all");
1974
1975         /* try to insert keyframe using property retrieved from UI */
1976         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
1977
1978         if (ptr.id.data && ptr.data && prop) {
1979                 path = RNA_path_from_ID_to_property(&ptr, prop);
1980                 
1981                 if (path) {
1982                         if (all) {
1983                                 /* -1 indicates operating on the entire array (or the property itself otherwise) */
1984                                 index = -1;
1985                         }
1986                         
1987                         success += clear_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index, 0);
1988                         MEM_freeN(path);
1989                 }
1990                 else if (G.debug & G_DEBUG)
1991                         printf("Button Clear-Key: no path to property\n");
1992         }
1993         else if (G.debug & G_DEBUG) {
1994                 printf("ptr.data = %p, prop = %p\n", (void *)ptr.data, (void *)prop);
1995         }
1996
1997
1998         if (success) {
1999                 /* send updates */
2000                 UI_context_update_anim_flag(C);
2001                 
2002                 /* send notifiers that keyframes have been changed */
2003                 WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL);
2004         }
2005
2006         return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
2007 }
2008
2009 void ANIM_OT_keyframe_clear_button(wmOperatorType *ot)
2010 {
2011         /* identifiers */
2012         ot->name = "Clear Keyframe (Buttons)";
2013         ot->idname = "ANIM_OT_keyframe_clear_button";
2014         ot->description = "Clear all keyframes on the currently active property";
2015
2016         /* callbacks */
2017         ot->exec = clear_key_button_exec;
2018         ot->poll = modify_key_op_poll;
2019
2020         /* flags */
2021         ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
2022
2023         /* properties */
2024         RNA_def_boolean(ot->srna, "all", 1, "All", "Clear keyframes from all elements of the array");
2025 }
2026
2027 /* ******************************************* */
2028 /* AUTO KEYFRAME */
2029
2030 bool autokeyframe_cfra_can_key(Scene *scene, ID *id)
2031 {
2032         float cfra = (float)CFRA; // XXX for now, this will do
2033         
2034         /* only filter if auto-key mode requires this */
2035         if (IS_AUTOKEY_ON(scene) == 0)
2036                 return false;
2037         
2038         if (IS_AUTOKEY_MODE(scene, EDITKEYS)) {
2039                 /* Replace Mode:
2040                  * For whole block, only key if there's a keyframe on that frame already
2041                  * This is a valid assumption when we're blocking + tweaking
2042                  */
2043                 return id_frame_has_keyframe(id, cfra, ANIMFILTER_KEYS_LOCAL);
2044         }
2045         else {
2046                 /* Normal Mode (or treat as being normal mode):
2047                  *
2048                  * Just in case the flags aren't set properly (i.e. only on/off is set, without a mode)
2049                  * let's set the "normal" flag too, so that it will all be sane everywhere...
2050                  */
2051                 scene->toolsettings->autokey_mode = AUTOKEY_MODE_NORMAL;
2052                 
2053                 /* Can insert anytime we like... */
2054                 return true;
2055         }
2056 }
2057
2058 /* ******************************************* */
2059 /* KEYFRAME DETECTION */
2060
2061 /* --------------- API/Per-Datablock Handling ------------------- */
2062
2063 /* Checks if some F-Curve has a keyframe for a given frame */
2064 bool fcurve_frame_has_keyframe(FCurve *fcu, float frame, short filter)
2065 {
2066         /* quick sanity check */
2067         if (ELEM(NULL, fcu, fcu->bezt))
2068                 return false;
2069         
2070         /* we either include all regardless of muting, or only non-muted  */
2071         if ((filter & ANIMFILTER_KEYS_MUTED) || (fcu->flag & FCURVE_MUTED) == 0) {
2072                 bool replace;
2073                 int i = binarysearch_bezt_index(fcu->bezt, frame, fcu->totvert, &replace);
2074                 
2075                 /* binarysearch_bezt_index will set replace to be 0 or 1
2076                  * - obviously, 1 represents a match
2077                  */
2078                 if (replace) {
2079                         /* sanity check: 'i' may in rare cases exceed arraylen */
2080                         if ((i >= 0) && (i < fcu->totvert))
2081                                 return true;
2082                 }
2083         }
2084         
2085         return false;
2086 }
2087
2088 /* Checks whether an Action has a keyframe for a given frame 
2089  * Since we're only concerned whether a keyframe exists, we can simply loop until a match is found...
2090  */
2091 static bool action_frame_has_keyframe(bAction *act, float frame, short filter)
2092 {
2093         FCurve *fcu;
2094         
2095         /* can only find if there is data */
2096         if (act == NULL)
2097                 return false;
2098                 
2099         /* if only check non-muted, check if muted */
2100         if ((filter & ANIMFILTER_KEYS_MUTED) || (act->flag & ACT_MUTED))
2101                 return false;
2102         
2103         /* loop over F-Curves, using binary-search to try to find matches 
2104          *      - this assumes that keyframes are only beztriples
2105          */
2106         for (fcu = act->curves.first; fcu; fcu = fcu->next) {
2107                 /* only check if there are keyframes (currently only of type BezTriple) */
2108                 if (fcu->bezt && fcu->totvert) {
2109                         if (fcurve_frame_has_keyframe(fcu, frame, filter))
2110                                 return true;
2111                 }
2112         }
2113         
2114         /* nothing found */
2115         return false;
2116 }
2117
2118 /* Checks whether an Object has a keyframe for a given frame */
2119 static bool object_frame_has_keyframe(Object *ob, float frame, short filter)
2120 {
2121         /* error checking */
2122         if (ob == NULL)
2123                 return false;
2124         
2125         /* check own animation data - specifically, the action it contains */
2126         if ((ob->adt) && (ob->adt->action)) {
2127                 /* T41525 - When the active action is a NLA strip being edited, 
2128                  * we need to correct the frame number to "look inside" the
2129                  * remapped action
2130                  */
2131                 float ob_frame = BKE_nla_tweakedit_remap(ob->adt, frame, NLATIME_CONVERT_UNMAP);
2132                 
2133                 if (action_frame_has_keyframe(ob->adt->action, ob_frame, filter))
2134                         return true;
2135         }
2136         
2137         /* try shapekey keyframes (if available, and allowed by filter) */
2138         if (!(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOSKEY)) {
2139                 Key *key = BKE_key_from_object(ob);
2140                 
2141                 /* shapekeys can have keyframes ('Relative Shape Keys') 
2142                  * or depend on time (old 'Absolute Shape Keys') 
2143                  */
2144                  
2145                 /* 1. test for relative (with keyframes) */
2146                 if (id_frame_has_keyframe((ID *)key, frame, filter))
2147                         return true;
2148
2149                 /* 2. test for time */
2150                 /* TODO... yet to be implemented (this feature may evolve before then anyway) */
2151         }
2152
2153         /* try materials */
2154         if (!(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOMAT)) {
2155                 /* if only active, then we can skip a lot of looping */
2156                 if (filter & ANIMFILTER_KEYS_ACTIVE) {
2157                         Material *ma = give_current_material(ob, (ob->actcol + 1));
2158                         
2159                         /* we only retrieve the active material... */
2160                         if (id_frame_has_keyframe((ID *)ma, frame, filter))
2161                                 return true;
2162                 }
2163                 else {
2164                         int a;
2165                         
2166                         /* loop over materials */
2167                         for (a = 0; a < ob->totcol; a++) {
2168                                 Material *ma = give_current_material(ob, a + 1);
2169                                 
2170                                 if (id_frame_has_keyframe((ID *)ma, frame, filter))
2171                                         return true;
2172                         }
2173                 }
2174         }
2175         
2176         /* nothing found */
2177         return false;
2178 }
2179
2180 /* --------------- API ------------------- */
2181
2182 /* Checks whether a keyframe exists for the given ID-block one the given frame */
2183 bool id_frame_has_keyframe(ID *id, float frame, short filter)
2184 {
2185         /* sanity checks */
2186         if (id == NULL)
2187                 return false;
2188         
2189         /* perform special checks for 'macro' types */
2190         switch (GS(id->name)) {
2191                 case ID_OB: /* object */
2192                         return object_frame_has_keyframe((Object *)id, frame, filter);
2193 #if 0
2194                 // XXX TODO... for now, just use 'normal' behavior
2195                 case ID_SCE: /* scene */
2196                         break;
2197 #endif
2198                 default:  /* 'normal type' */
2199                 {
2200                         AnimData *adt = BKE_animdata_from_id(id);
2201                         
2202                         /* only check keyframes in active action */
2203                         if (adt)
2204                                 return action_frame_has_keyframe(adt->action, frame, filter);
2205                         break;
2206                 }
2207         }
2208         
2209         
2210         /* no keyframe found */
2211         return false;
2212 }
2213
2214 /* ************************************************** */
2215
2216 bool ED_autokeyframe_object(bContext *C, Scene *scene, Object *ob, KeyingSet *ks)
2217 {
2218         /* auto keyframing */
2219         if (autokeyframe_cfra_can_key(scene, &ob->id)) {
2220                 ListBase dsources = {NULL, NULL};
2221
2222                 /* now insert the keyframe(s) using the Keying Set
2223                  *      1) add datasource override for the Object
2224                  *      2) insert keyframes
2225                  *      3) free the extra info
2226                  */
2227                 ANIM_relative_keyingset_add_source(&dsources, &ob->id, NULL, NULL);
2228                 ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
2229                 BLI_freelistN(&dsources);
2230
2231                 return true;
2232         }
2233         else {
2234                 return false;
2235         }
2236 }
2237
2238 bool ED_autokeyframe_pchan(bContext *C, Scene *scene, Object *ob, bPoseChannel *pchan, KeyingSet *ks)
2239 {
2240         if (autokeyframe_cfra_can_key(scene, &ob->id)) {
2241                 ListBase dsources = {NULL, NULL};
2242
2243                 /* now insert the keyframe(s) using the Keying Set
2244                  *      1) add datasource override for the PoseChannel
2245                  *      2) insert keyframes
2246                  *      3) free the extra info
2247                  */
2248                 ANIM_relative_keyingset_add_source(&dsources, &ob->id, &RNA_PoseBone, pchan);
2249                 ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
2250                 BLI_freelistN(&dsources);
2251
2252                 /* clear any unkeyed tags */
2253                 if (pchan->bone) {
2254                         pchan->bone->flag &= ~BONE_UNKEYED;
2255                 }
2256
2257                 return true;
2258         }
2259         else {
2260                 /* add unkeyed tags */
2261                 if (pchan->bone) {
2262                         pchan->bone->flag |= BONE_UNKEYED;
2263                 }
2264
2265                 return false;
2266         }
2267 }