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