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