1b77c1530bfe80757c28ea9b9f27dd01e31183e1
[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_constraint.h"
61 #include "BKE_depsgraph.h"
62 #include "BKE_fcurve.h"
63 #include "BKE_main.h"
64 #include "BKE_idcode.h"
65 #include "BKE_nla.h"
66 #include "BKE_global.h"
67 #include "BKE_context.h"
68 #include "BKE_report.h"
69 #include "BKE_key.h"
70 #include "BKE_material.h"
71
72 #include "ED_anim_api.h"
73 #include "ED_keyframing.h"
74 #include "ED_keyframes_edit.h"
75 #include "ED_screen.h"
76
77 #include "UI_interface.h"
78 #include "UI_resources.h"
79
80 #include "WM_api.h"
81 #include "WM_types.h"
82
83 #include "RNA_access.h"
84 #include "RNA_define.h"
85 #include "RNA_enum_types.h"
86
87 #include "anim_intern.h"
88
89 /* ************************************************** */
90 /* Keyframing Setting Wrangling */
91
92 /* Get the active settings for keyframing settings from context (specifically the given scene) */
93 short ANIM_get_keyframing_flags(Scene *scene, short incl_mode)
94 {
95         short flag = 0;
96         
97         /* standard flags */
98         {
99                 /* visual keying */
100                 if (IS_AUTOKEY_FLAG(scene, AUTOMATKEY)) 
101                         flag |= INSERTKEY_MATRIX;
102                 
103                 /* only needed */
104                 if (IS_AUTOKEY_FLAG(scene, INSERTNEEDED)) 
105                         flag |= INSERTKEY_NEEDED;
106                 
107                 /* default F-Curve color mode - RGB from XYZ indices */
108                 if (IS_AUTOKEY_FLAG(scene, XYZ2RGB)) 
109                         flag |= INSERTKEY_XYZ2RGB;
110         }
111                 
112         /* only if including settings from the autokeying mode... */
113         if (incl_mode) {
114                 /* keyframing mode - only replace existing keyframes */
115                 if (IS_AUTOKEY_MODE(scene, EDITKEYS)) 
116                         flag |= INSERTKEY_REPLACE;
117         }
118                 
119         return flag;
120 }
121
122 /* ******************************************* */
123 /* Animation Data Validation */
124
125 /* Get (or add relevant data to be able to do so) the Active Action for the given 
126  * Animation Data block, given an ID block where the Animation Data should reside.
127  */
128 bAction *verify_adt_action(ID *id, short add)
129 {
130         AnimData *adt;
131         
132         /* init animdata if none available yet */
133         adt = BKE_animdata_from_id(id);
134         if ((adt == NULL) && (add))
135                 adt = BKE_id_add_animdata(id);
136         if (adt == NULL) {
137                 /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */
138                 printf("ERROR: Couldn't add AnimData (ID = %s)\n", (id) ? (id->name) : "<None>");
139                 return NULL;
140         }
141
142         /* init action if none available yet */
143         /* TODO: need some wizardry to handle NLA stuff correct */
144         if ((adt->action == NULL) && (add)) {
145                 /* init action name from name of ID block */
146                 char actname[sizeof(id->name) - 2];
147                 BLI_snprintf(actname, sizeof(actname), "%sAction", id->name + 2);
148                 
149                 /* create action */
150                 adt->action = add_empty_action(G.main, actname);
151                 
152                 /* set ID-type from ID-block that this is going to be assigned to
153                  * so that users can't accidentally break actions by assigning them
154                  * to the wrong places
155                  */
156                 adt->action->idroot = GS(id->name);
157         }
158                 
159         /* return the action */
160         return adt->action;
161 }
162
163 /* Get (or add relevant data to be able to do so) F-Curve from the Active Action, 
164  * for the given Animation Data block. This assumes that all the destinations are valid.
165  */
166 FCurve *verify_fcurve(bAction *act, const char group[], PointerRNA *ptr, 
167                       const char rna_path[], const int array_index, short add)
168 {
169         bActionGroup *agrp;
170         FCurve *fcu;
171         
172         /* sanity checks */
173         if (ELEM(NULL, act, rna_path))
174                 return NULL;
175                 
176         /* try to find f-curve matching for this setting 
177          *      - add if not found and allowed to add one
178          *              TODO: add auto-grouping support? how this works will need to be resolved
179          */
180         fcu = list_find_fcurve(&act->curves, rna_path, array_index);
181         
182         if ((fcu == NULL) && (add)) {
183                 /* use default settings to make a F-Curve */
184                 fcu = MEM_callocN(sizeof(FCurve), "FCurve");
185                 
186                 fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
187                 if (act->curves.first == NULL)
188                         fcu->flag |= FCURVE_ACTIVE;  /* first one added active */
189                         
190                 /* store path - make copy, and store that */
191                 fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path));
192                 fcu->array_index = array_index;
193                 
194                 /* if a group name has been provided, try to add or find a group, then add F-Curve to it */
195                 if (group) {
196                         /* try to find group */
197                         agrp = BKE_action_group_find_name(act, group);
198                         
199                         /* no matching groups, so add one */
200                         if (agrp == NULL) {
201                                 agrp = action_groups_add_new(act, group);
202                                 
203                                 /* sync bone group colors if applicable */
204                                 if (ptr && (ptr->type == &RNA_PoseBone)) {
205                                         Object *ob = (Object *)ptr->id.data;
206                                         bPoseChannel *pchan = (bPoseChannel *)ptr->data;
207                                         bPose *pose = ob->pose;
208                                         bActionGroup *grp;
209                                         
210                                         /* find bone group (if present), and use the color from that */
211                                         grp = (bActionGroup *)BLI_findlink(&pose->agroups, (pchan->agrp_index - 1));
212                                         if (grp) {
213                                                 agrp->customCol = grp->customCol;
214                                                 action_group_colors_sync(agrp, grp);
215                                         }
216                                 }
217                         }
218                         
219                         /* add F-Curve to group */
220                         action_groups_add_channel(act, agrp, fcu);
221                 }
222                 else {
223                         /* just add F-Curve to end of Action's list */
224                         BLI_addtail(&act->curves, fcu);
225                 }
226         }
227         
228         /* return the F-Curve */
229         return fcu;
230 }
231
232 /* Helper */
233 static void update_autoflags_fcurve_direct(FCurve *fcu, PropertyRNA *prop)
234 {
235         /* set additional flags for the F-Curve (i.e. only integer values) */
236         fcu->flag &= ~(FCURVE_INT_VALUES | FCURVE_DISCRETE_VALUES);
237         switch (RNA_property_type(prop)) {
238                 case PROP_FLOAT:
239                         /* do nothing */
240                         break;
241                 case PROP_INT:
242                         /* do integer (only 'whole' numbers) interpolation between all points */
243                         fcu->flag |= FCURVE_INT_VALUES;
244                         break;
245                 default:
246                         /* do 'discrete' (i.e. enum, boolean values which cannot take any intermediate
247                          * values at all) interpolation between all points
248                          *    - however, we must also ensure that evaluated values are only integers still
249                          */
250                         fcu->flag |= (FCURVE_DISCRETE_VALUES | FCURVE_INT_VALUES);
251                         break;
252         }
253 }
254
255 /*  Update integer/discrete flags of the FCurve (used when creating/inserting keyframes,
256  *  but also through RNA when editing an ID prop, see T37103).
257  */
258 void update_autoflags_fcurve(FCurve *fcu, bContext *C, ReportList *reports, PointerRNA *ptr)
259 {
260         PointerRNA tmp_ptr;
261         PropertyRNA *prop;
262         int old_flag = fcu->flag;
263
264         if ((ptr->id.data == NULL) && (ptr->data == NULL)) {
265                 BKE_report(reports, RPT_ERROR, "No RNA pointer available to retrieve values for this fcurve");
266                 return;
267         }
268
269         /* try to get property we should be affecting */
270         if (RNA_path_resolve_property(ptr, fcu->rna_path, &tmp_ptr, &prop) == false) {
271                 /* property not found... */
272                 const char *idname = (ptr->id.data) ? ((ID *)ptr->id.data)->name : TIP_("<No ID pointer>");
273
274                 BKE_reportf(reports, RPT_ERROR,
275                             "Could not update flags for this fcurve, as RNA path is invalid for the given ID "
276                             "(ID = %s, path = %s)",
277                             idname, fcu->rna_path);
278                 return;
279         }
280
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 curently
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                 Object *ob = (Object *)ptr->id.data; /* we assume that this is always set, and is an object */
783                 bPoseChannel *pchan = (bPoseChannel *)ptr->data;
784                 
785                 /* Although it is not strictly required for this particular space conversion, 
786                  * arg1 must not be null, as there is a null check for the other conversions to
787                  * be safe. Therefore, the active object is passed here, and in many cases, this
788                  * will be what owns the pose-channel that is getting this anyway.
789                  */
790                 copy_m4_m4(tmat, pchan->pose_mat);
791                 BKE_constraint_mat_convertspace(ob, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
792                 rotmode = pchan->rotmode;
793                 
794                 /* Loc code is specific... */
795                 if (strstr(identifier, "location")) {
796                         /* only use for non-connected bones */
797                         if ((pchan->bone->parent == NULL) || !(pchan->bone->flag & BONE_CONNECTED))
798                                 return tmat[3][array_index];
799                 }
800         }
801         else {
802                 return setting_get_rna_value(ptr, prop, array_index);
803         }
804         
805         /* Rot/Scale code are common! */
806         if (strstr(identifier, "rotation_euler")) {
807                 float eul[3];
808                 
809                 mat4_to_eulO(eul, rotmode, tmat);
810                 return eul[array_index];
811         }
812         else if (strstr(identifier, "rotation_quaternion")) {
813                 float mat3[3][3], quat[4];
814                 
815                 copy_m3_m4(mat3, tmat);
816                 mat3_to_quat_is_ok(quat, mat3);
817                 
818                 return quat[array_index];
819         }
820         else if (strstr(identifier, "rotation_axis_angle")) {
821                 float axis[3], angle;
822                 
823                 mat4_to_axis_angle(axis, &angle, tmat);
824                 
825                 /* w = 0, x,y,z = 1,2,3 */
826                 if (array_index == 0)
827                         return angle;
828                 else
829                         return axis[array_index - 1];
830         }
831         else if (strstr(identifier, "scale")) {
832                 float scale[3];
833                 
834                 mat4_to_size(scale, tmat);
835                 
836                 return scale[array_index];
837         }
838         
839         /* as the function hasn't returned yet, read value from system in the default way */
840         return setting_get_rna_value(ptr, prop, array_index);
841 }
842
843 /* ------------------------- Insert Key API ------------------------- */
844
845 /* Secondary Keyframing API call: 
846  *  Use this when validation of necessary animation data is not necessary, since an RNA-pointer to the necessary
847  *      data being keyframed, and a pointer to the F-Curve to use have both been provided.
848  *
849  *      The flag argument is used for special settings that alter the behavior of
850  *      the keyframe insertion. These include the 'visual' keyframing modes, quick refresh,
851  *      and extra keyframe filtering.
852  */
853 short insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, float cfra, short flag)
854 {
855         float curval = 0.0f;
856         
857         /* no F-Curve to add keyframe to? */
858         if (fcu == NULL) {
859                 BKE_report(reports, RPT_ERROR, "No F-Curve to add keyframes to");
860                 return 0;
861         }
862         /* F-Curve not editable? */
863         if (fcurve_is_keyframable(fcu) == 0) {
864                 BKE_reportf(reports, RPT_ERROR, 
865                             "F-Curve with path '%s[%d]' cannot be keyframed, ensure that it is not locked or sampled, "
866                             "and try removing F-Modifiers",
867                             fcu->rna_path, fcu->array_index);
868                 return 0;
869         }
870         
871         /* if no property given yet, try to validate from F-Curve info */
872         if ((ptr.id.data == NULL) && (ptr.data == NULL)) {
873                 BKE_report(reports, RPT_ERROR, "No RNA pointer available to retrieve values for keyframing from");
874                 return 0;
875         }
876         if (prop == NULL) {
877                 PointerRNA tmp_ptr;
878                 
879                 /* try to get property we should be affecting */
880                 if (RNA_path_resolve_property(&ptr, fcu->rna_path, &tmp_ptr, &prop) == false) {
881                         /* property not found... */
882                         const char *idname = (ptr.id.data) ? ((ID *)ptr.id.data)->name : TIP_("<No ID pointer>");
883                         
884                         BKE_reportf(reports, RPT_ERROR,
885                                     "Could not insert keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)",
886                                     idname, fcu->rna_path);
887                         return 0;
888                 }
889                 else {
890                         /* property found, so overwrite 'ptr' to make later code easier */
891                         ptr = tmp_ptr;
892                 }
893         }
894         
895         update_autoflags_fcurve_direct(fcu, prop);
896         
897         /* obtain value to give keyframe */
898         if ( (flag & INSERTKEY_MATRIX) && 
899              (visualkey_can_use(&ptr, prop)) )
900         {
901                 /* visual-keying is only available for object and pchan datablocks, as 
902                  * it works by keyframing using a value extracted from the final matrix 
903                  * instead of using the kt system to extract a value.
904                  */
905                 curval = visualkey_get_value(&ptr, prop, fcu->array_index);
906         }
907         else {
908                 /* read value from system */
909                 curval = setting_get_rna_value(&ptr, prop, fcu->array_index);
910         }
911         
912         /* only insert keyframes where they are needed */
913         if (flag & INSERTKEY_NEEDED) {
914                 short insert_mode;
915                 
916                 /* check whether this curve really needs a new keyframe */
917                 insert_mode = new_key_needed(fcu, cfra, curval);
918                 
919                 /* insert new keyframe at current frame */
920                 if (insert_mode)
921                         insert_vert_fcurve(fcu, cfra, curval, flag);
922                 
923                 /* delete keyframe immediately before/after newly added */
924                 switch (insert_mode) {
925                         case KEYNEEDED_DELPREV:
926                                 delete_fcurve_key(fcu, fcu->totvert - 2, 1);
927                                 break;
928                         case KEYNEEDED_DELNEXT:
929                                 delete_fcurve_key(fcu, 1, 1);
930                                 break;
931                 }
932                 
933                 /* only return success if keyframe added */
934                 if (insert_mode)
935                         return 1;
936         }
937         else {
938                 /* just insert keyframe */
939                 insert_vert_fcurve(fcu, cfra, curval, flag);
940                 
941                 /* return success */
942                 return 1;
943         }
944         
945         /* failed */
946         return 0;
947 }
948
949 /* Main Keyframing API call:
950  *      Use this when validation of necessary animation data is necessary, since it may not exist yet.
951  *      
952  *      The flag argument is used for special settings that alter the behavior of
953  *      the keyframe insertion. These include the 'visual' keyframing modes, quick refresh,
954  *      and extra keyframe filtering.
955  *
956  *      index of -1 keys all array indices
957  */
958 short insert_keyframe(ReportList *reports, ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag)
959 {       
960         PointerRNA id_ptr, ptr;
961         PropertyRNA *prop = NULL;
962         AnimData *adt;
963         FCurve *fcu;
964         int array_index_max = array_index + 1;
965         int ret = 0;
966         
967         /* validate pointer first - exit if failure */
968         if (id == NULL) {
969                 BKE_reportf(reports, RPT_ERROR, "No ID block to insert keyframe in (path = %s)", rna_path);
970                 return 0;
971         }
972         
973         RNA_id_pointer_create(id, &id_ptr);
974         if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
975                 BKE_reportf(reports, RPT_ERROR,
976                             "Could not insert keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)",
977                             (id) ? id->name : TIP_("<Missing ID block>"), rna_path);
978                 return 0;
979         }
980         
981         /* if no action is provided, keyframe to the default one attached to this ID-block */
982         if (act == NULL) {
983                 /* get action to add F-Curve+keyframe to */
984                 act = verify_adt_action(id, 1);
985                 
986                 if (act == NULL) {
987                         BKE_reportf(reports, RPT_ERROR, 
988                                     "Could not insert keyframe, as this type does not support animation data (ID = %s, path = %s)",
989                                     id->name, rna_path);
990                         return 0;
991                 }
992         }
993         
994         /* apply NLA-mapping to frame to use (if applicable) */
995         adt = BKE_animdata_from_id(id);
996         cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
997         
998         /* key entire array convenience method */
999         if (array_index == -1) {
1000                 array_index = 0;
1001                 array_index_max = RNA_property_array_length(&ptr, prop);
1002                 
1003                 /* for single properties, increase max_index so that the property itself gets included,
1004                  * but don't do this for standard arrays since that can cause corruption issues 
1005                  * (extra unused curves)
1006                  */
1007                 if (array_index_max == array_index)
1008                         array_index_max++;
1009         }
1010         
1011         /* will only loop once unless the array index was -1 */
1012         for (; array_index < array_index_max; array_index++) {
1013                 /* make sure the F-Curve exists 
1014                  *      - if we're replacing keyframes only, DO NOT create new F-Curves if they do not exist yet
1015                  *        but still try to get the F-Curve if it exists...
1016                  */
1017                 fcu = verify_fcurve(act, group, &ptr, rna_path, array_index, (flag & INSERTKEY_REPLACE) == 0);
1018                 
1019                 /* we may not have a F-Curve when we're replacing only... */
1020                 if (fcu) {
1021                         /* set color mode if the F-Curve is new (i.e. without any keyframes) */
1022                         if ((fcu->totvert == 0) && (flag & INSERTKEY_XYZ2RGB)) {
1023                                 /* for Loc/Rot/Scale and also Color F-Curves, the color of the F-Curve in the Graph Editor,
1024                                  * is determined by the array index for the F-Curve
1025                                  */
1026                                 if (ELEM5(RNA_property_subtype(prop), PROP_TRANSLATION, PROP_XYZ, PROP_EULER, PROP_COLOR, PROP_COORDS)) {
1027                                         fcu->color_mode = FCURVE_COLOR_AUTO_RGB;
1028                                 }
1029                         }
1030                         
1031                         /* insert keyframe */
1032                         ret += insert_keyframe_direct(reports, ptr, prop, fcu, cfra, flag);
1033                 }
1034         }
1035         
1036         return ret;
1037 }
1038
1039 /* ************************************************** */
1040 /* KEYFRAME DELETION */
1041
1042 /* Main Keyframing API call:
1043  *      Use this when validation of necessary animation data isn't necessary as it
1044  *      already exists. It will delete a keyframe at the current frame.
1045  *      
1046  *      The flag argument is used for special settings that alter the behavior of
1047  *      the keyframe deletion. These include the quick refresh options.
1048  */
1049
1050
1051
1052 /**
1053  * \note caller needs to run #BKE_nla_tweakedit_remap to get NLA relative frame.
1054  *       caller should also check #BKE_fcurve_is_protected before keying.
1055  */
1056 static bool delete_keyframe_fcurve(AnimData *adt, FCurve *fcu, float cfra)
1057 {
1058         bool found;
1059         int i;
1060
1061         /* try to find index of beztriple to get rid of */
1062         i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found);
1063         if (found) {
1064                 /* delete the key at the index (will sanity check + do recalc afterwards) */
1065                 delete_fcurve_key(fcu, i, 1);
1066
1067                 /* Only delete curve too if it won't be doing anything anymore */
1068                 if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0))
1069                         ANIM_fcurve_delete_from_animdata(NULL, adt, fcu);
1070
1071                 /* return success */
1072                 return true;
1073         }
1074         return false;
1075 }
1076
1077 short delete_keyframe(ReportList *reports, ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short UNUSED(flag))
1078 {
1079         AnimData *adt = BKE_animdata_from_id(id);
1080         PointerRNA id_ptr, ptr;
1081         PropertyRNA *prop;
1082         int array_index_max = array_index + 1;
1083         int ret = 0;
1084         
1085         /* sanity checks */
1086         if (ELEM(NULL, id, adt)) {
1087                 BKE_report(reports, RPT_ERROR, "No ID block and/or AnimData to delete keyframe from");
1088                 return 0;
1089         }
1090         
1091         /* validate pointer first - exit if failure */
1092         RNA_id_pointer_create(id, &id_ptr);
1093         if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
1094                 BKE_reportf(reports, RPT_ERROR,
1095                             "Could not delete keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)",
1096                             id->name, rna_path);
1097                 return 0;
1098         }
1099         
1100         /* get F-Curve
1101          * Note: here is one of the places where we don't want new Action + F-Curve added!
1102          *      so 'add' var must be 0
1103          */
1104         if (act == NULL) {
1105                 /* if no action is provided, use the default one attached to this ID-block 
1106                  *  - if it doesn't exist, then we're out of options...
1107                  */
1108                 if (adt->action) {
1109                         act = adt->action;
1110                         
1111                         /* apply NLA-mapping to frame to use (if applicable) */
1112                         cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
1113                 }
1114                 else {
1115                         BKE_reportf(reports, RPT_ERROR, "No action to delete keyframes from for ID = %s", id->name);
1116                         return 0;
1117                 }
1118         }
1119         
1120         /* key entire array convenience method */
1121         if (array_index == -1) {
1122                 array_index = 0;
1123                 array_index_max = RNA_property_array_length(&ptr, prop);
1124                 
1125                 /* for single properties, increase max_index so that the property itself gets included,
1126                  * but don't do this for standard arrays since that can cause corruption issues 
1127                  * (extra unused curves)
1128                  */
1129                 if (array_index_max == array_index)
1130                         array_index_max++;
1131         }
1132         
1133         /* will only loop once unless the array index was -1 */
1134         for (; array_index < array_index_max; array_index++) {
1135                 FCurve *fcu = verify_fcurve(act, group, &ptr, rna_path, array_index, 0);
1136
1137                 /* check if F-Curve exists and/or whether it can be edited */
1138                 if (fcu == NULL)
1139                         continue;
1140
1141                 if (BKE_fcurve_is_protected(fcu)) {
1142                         BKE_reportf(reports, RPT_WARNING,
1143                                     "Not deleting keyframe for locked F-Curve '%s' for %s '%s'",
1144                                     fcu->rna_path, BKE_idcode_to_name(GS(id->name)), id->name + 2);
1145                         continue;
1146                 }
1147
1148                 ret += delete_keyframe_fcurve(adt, fcu, cfra);
1149
1150         }
1151         
1152         /* return success/failure */
1153         return ret;
1154 }
1155
1156 /* ************************************************** */
1157 /* KEYFRAME CLEAR */
1158
1159 /* Main Keyframing API call:
1160  *      Use this when validation of necessary animation data isn't necessary as it
1161  *      already exists. It will clear the current buttons fcurve(s).
1162  *
1163  *      The flag argument is used for special settings that alter the behavior of
1164  *      the keyframe deletion. These include the quick refresh options.
1165  */
1166 static short clear_keyframe(ReportList *reports, ID *id, bAction *act, const char group[], const char rna_path[], int array_index, short UNUSED(flag))
1167 {
1168         AnimData *adt = BKE_animdata_from_id(id);
1169         PointerRNA id_ptr, ptr;
1170         PropertyRNA *prop;
1171         int array_index_max = array_index + 1;
1172         int ret = 0;
1173
1174         /* sanity checks */
1175         if (ELEM(NULL, id, adt)) {
1176                 BKE_report(reports, RPT_ERROR, "No ID block and/or AnimData to delete keyframe from");
1177                 return 0;
1178         }
1179
1180         /* validate pointer first - exit if failure */
1181         RNA_id_pointer_create(id, &id_ptr);
1182         if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
1183                 BKE_reportf(reports, RPT_ERROR,
1184                             "Could not clear keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)",
1185                             id->name, rna_path);
1186                 return 0;
1187         }
1188
1189         /* get F-Curve
1190          * Note: here is one of the places where we don't want new Action + F-Curve added!
1191          *      so 'add' var must be 0
1192          */
1193         if (act == NULL) {
1194                 /* if no action is provided, use the default one attached to this ID-block
1195                  *  - if it doesn't exist, then we're out of options...
1196                  */
1197                 if (adt->action) {
1198                         act = adt->action;
1199                 }
1200                 else {
1201                         BKE_reportf(reports, RPT_ERROR, "No action to delete keyframes from for ID = %s", id->name);
1202                         return 0;
1203                 }
1204         }
1205
1206         /* key entire array convenience method */
1207         if (array_index == -1) {
1208                 array_index = 0;
1209                 array_index_max = RNA_property_array_length(&ptr, prop);
1210
1211                 /* for single properties, increase max_index so that the property itself gets included,
1212                  * but don't do this for standard arrays since that can cause corruption issues
1213                  * (extra unused curves)
1214                  */
1215                 if (array_index_max == array_index)
1216                         array_index_max++;
1217         }
1218
1219         /* will only loop once unless the array index was -1 */
1220         for (; array_index < array_index_max; array_index++) {
1221                 FCurve *fcu = verify_fcurve(act, group, &ptr, rna_path, array_index, 0);
1222
1223                 /* check if F-Curve exists and/or whether it can be edited */
1224                 if (fcu == NULL)
1225                         continue;
1226
1227                 if (BKE_fcurve_is_protected(fcu)) {
1228                         if (G.debug & G_DEBUG)
1229                                 printf("WARNING: not deleting keyframe for locked F-Curve\n");
1230                         continue;
1231                 }
1232
1233                 ANIM_fcurve_delete_from_animdata(NULL, adt, fcu);
1234
1235                 /* return success */
1236                 ret++;
1237         }
1238
1239         /* return success/failure */
1240         return ret;
1241 }
1242
1243 /* ******************************************* */
1244 /* KEYFRAME MODIFICATION */
1245
1246 /* mode for commonkey_modifykey */
1247 enum {
1248         COMMONKEY_MODE_INSERT = 0,
1249         COMMONKEY_MODE_DELETE,
1250 } /*eCommonModifyKey_Modes*/;
1251
1252 /* Polling callback for use with ANIM_*_keyframe() operators
1253  * This is based on the standard ED_operator_areaactive callback,
1254  * except that it does special checks for a few spacetypes too...
1255  */
1256 static int modify_key_op_poll(bContext *C)
1257 {
1258         ScrArea *sa = CTX_wm_area(C);
1259         Scene *scene = CTX_data_scene(C);
1260         SpaceOops *so = CTX_wm_space_outliner(C);
1261         
1262         /* if no area or active scene */
1263         if (ELEM(NULL, sa, scene)) 
1264                 return 0;
1265         
1266         /* if Outliner, don't allow in some views */
1267         if (so) {
1268                 if (ELEM4(so->outlinevis, SO_GROUPS, SO_LIBRARIES, SO_SEQUENCE, SO_USERDEF)) {
1269                         return 0;
1270                 }
1271         }
1272         
1273         /* TODO: checks for other space types can be added here */
1274         
1275         /* should be fine */
1276         return 1;
1277 }
1278
1279 /* Insert Key Operator ------------------------ */
1280
1281 static int insert_key_exec(bContext *C, wmOperator *op)
1282 {
1283         Scene *scene = CTX_data_scene(C);
1284         KeyingSet *ks = NULL;
1285         int type = RNA_enum_get(op->ptr, "type");
1286         float cfra = (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
1287         short success;
1288         
1289         /* type is the Keying Set the user specified to use when calling the operator:
1290          *      - type == 0: use scene's active Keying Set
1291          *      - type > 0: use a user-defined Keying Set from the active scene
1292          *      - type < 0: use a builtin Keying Set
1293          */
1294         if (type == 0) 
1295                 type = scene->active_keyingset;
1296         if (type > 0)
1297                 ks = BLI_findlink(&scene->keyingsets, type - 1);
1298         else
1299                 ks = BLI_findlink(&builtin_keyingsets, -type - 1);
1300                 
1301         /* report failures */
1302         if (ks == NULL) {
1303                 BKE_report(op->reports, RPT_ERROR, "No active keying set");
1304                 return OPERATOR_CANCELLED;
1305         }
1306         
1307         /* try to insert keyframes for the channels specified by KeyingSet */
1308         success = ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
1309         if (G.debug & G_DEBUG)
1310                 BKE_reportf(op->reports, RPT_INFO, "Keying set '%s' - successfully added %d keyframes", ks->name, success);
1311         
1312         /* report failure or do updates? */
1313         if (success == MODIFYKEY_INVALID_CONTEXT) {
1314                 BKE_report(op->reports, RPT_ERROR, "No suitable context info for active keying set");
1315                 return OPERATOR_CANCELLED;
1316         }
1317         else if (success) {
1318                 /* if the appropriate properties have been set, make a note that we've inserted something */
1319                 if (RNA_boolean_get(op->ptr, "confirm_success"))
1320                         BKE_reportf(op->reports, RPT_INFO, "Successfully added %d keyframes for keying set '%s'", success, ks->name);
1321                 
1322                 /* send notifiers that keyframes have been changed */
1323                 WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
1324         }
1325         else
1326                 BKE_report(op->reports, RPT_WARNING, "Keying set failed to insert any keyframes");
1327         
1328         return OPERATOR_FINISHED;
1329 }
1330
1331 void ANIM_OT_keyframe_insert(wmOperatorType *ot)
1332 {
1333         PropertyRNA *prop;
1334         
1335         /* identifiers */
1336         ot->name = "Insert Keyframe";
1337         ot->idname = "ANIM_OT_keyframe_insert";
1338         ot->description = "Insert keyframes on the current frame for all properties in the specified Keying Set";
1339         
1340         /* callbacks */
1341         ot->exec = insert_key_exec; 
1342         ot->poll = modify_key_op_poll;
1343         
1344         /* flags */
1345         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1346         
1347         /* keyingset to use (dynamic enum) */
1348         prop = RNA_def_enum(ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
1349         RNA_def_enum_funcs(prop, ANIM_keying_sets_enum_itemf);
1350         RNA_def_property_flag(prop, PROP_HIDDEN);
1351         ot->prop = prop;
1352         
1353         /* confirm whether a keyframe was added by showing a popup 
1354          *      - by default, this is enabled, since this operator is assumed to be called independently
1355          */
1356         prop = RNA_def_boolean(ot->srna, "confirm_success", 1, "Confirm Successful Insert",
1357                                "Show a popup when the keyframes get successfully added");
1358         RNA_def_property_flag(prop, PROP_HIDDEN);
1359 }
1360
1361 /* Insert Key Operator (With Menu) ------------------------ */
1362 /* This operator checks if a menu should be shown for choosing the KeyingSet to use, 
1363  * then calls the menu if necessary before 
1364  */
1365
1366 static int insert_key_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1367 {
1368         Scene *scene = CTX_data_scene(C);
1369         
1370         /* if prompting or no active Keying Set, show the menu */
1371         if ((scene->active_keyingset == 0) || RNA_boolean_get(op->ptr, "always_prompt")) {
1372                 uiPopupMenu *pup;
1373                 uiLayout *layout;
1374                 
1375                 /* call the menu, which will call this operator again, hence the canceled */
1376                 pup = uiPupMenuBegin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
1377                 layout = uiPupMenuLayout(pup);
1378                 uiItemsEnumO(layout, "ANIM_OT_keyframe_insert_menu", "type");
1379                 uiPupMenuEnd(C, pup);
1380                 
1381                 return OPERATOR_CANCELLED;
1382         }
1383         else {
1384                 /* just call the exec() on the active keyingset */
1385                 RNA_enum_set(op->ptr, "type", 0);
1386                 RNA_boolean_set(op->ptr, "confirm_success", TRUE);
1387                 
1388                 return op->type->exec(C, op);
1389         }
1390 }
1391  
1392 void ANIM_OT_keyframe_insert_menu(wmOperatorType *ot)
1393 {
1394         PropertyRNA *prop;
1395         
1396         /* identifiers */
1397         ot->name = "Insert Keyframe Menu";
1398         ot->idname = "ANIM_OT_keyframe_insert_menu";
1399         ot->description = "Insert Keyframes for specified Keying Set, with menu of available Keying Sets if undefined";
1400         
1401         /* callbacks */
1402         ot->invoke = insert_key_menu_invoke;
1403         ot->exec = insert_key_exec; 
1404         ot->poll = ED_operator_areaactive;
1405         
1406         /* flags */
1407         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1408         
1409         /* keyingset to use (dynamic enum) */
1410         prop = RNA_def_enum(ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
1411         RNA_def_enum_funcs(prop, ANIM_keying_sets_enum_itemf);
1412         RNA_def_property_flag(prop, PROP_HIDDEN);
1413         ot->prop = prop;
1414         
1415         /* confirm whether a keyframe was added by showing a popup 
1416          *      - by default, this is disabled so that if a menu is shown, this doesn't come up too
1417          */
1418         // XXX should this just be always on?
1419         prop = RNA_def_boolean(ot->srna, "confirm_success", 0, "Confirm Successful Insert",
1420                                "Show a popup when the keyframes get successfully added");
1421         RNA_def_property_flag(prop, PROP_HIDDEN);
1422         
1423         /* whether the menu should always be shown 
1424          *      - by default, the menu should only be shown when there is no active Keying Set (2.5 behavior),
1425          *        although in some cases it might be useful to always shown (pre 2.5 behavior)
1426          */
1427         prop = RNA_def_boolean(ot->srna, "always_prompt", 0, "Always Show Menu", "");
1428         RNA_def_property_flag(prop, PROP_HIDDEN);
1429 }
1430
1431 /* Delete Key Operator ------------------------ */
1432
1433 static int delete_key_exec(bContext *C, wmOperator *op)
1434 {
1435         Scene *scene = CTX_data_scene(C);
1436         KeyingSet *ks = NULL;
1437         int type = RNA_enum_get(op->ptr, "type");
1438         float cfra = (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
1439         short success;
1440         
1441         /* type is the Keying Set the user specified to use when calling the operator:
1442          *      - type == 0: use scene's active Keying Set
1443          *      - type > 0: use a user-defined Keying Set from the active scene
1444          *      - type < 0: use a builtin Keying Set
1445          */
1446         if (type == 0) 
1447                 type = scene->active_keyingset;
1448         if (type > 0)
1449                 ks = BLI_findlink(&scene->keyingsets, type - 1);
1450         else
1451                 ks = BLI_findlink(&builtin_keyingsets, -type - 1);
1452         
1453         /* report failure */
1454         if (ks == NULL) {
1455                 BKE_report(op->reports, RPT_ERROR, "No active Keying Set");
1456                 return OPERATOR_CANCELLED;
1457         }
1458         
1459         /* try to delete keyframes for the channels specified by KeyingSet */
1460         success = ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_DELETE, cfra);
1461         if (G.debug & G_DEBUG)
1462                 printf("KeyingSet '%s' - Successfully removed %d Keyframes\n", ks->name, success);
1463         
1464         /* report failure or do updates? */
1465         if (success == MODIFYKEY_INVALID_CONTEXT) {
1466                 BKE_report(op->reports, RPT_ERROR, "No suitable context info for active keying set");
1467                 return OPERATOR_CANCELLED;
1468         }
1469         else if (success) {
1470                 /* if the appropriate properties have been set, make a note that we've inserted something */
1471                 if (RNA_boolean_get(op->ptr, "confirm_success"))
1472                         BKE_reportf(op->reports, RPT_INFO, "Successfully removed %d keyframes for keying set '%s'", success, ks->name);
1473                 
1474                 /* send notifiers that keyframes have been changed */
1475                 WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
1476         }
1477         else
1478                 BKE_report(op->reports, RPT_WARNING, "Keying set failed to remove any keyframes");
1479         
1480         return OPERATOR_FINISHED;
1481 }
1482
1483 void ANIM_OT_keyframe_delete(wmOperatorType *ot)
1484 {
1485         PropertyRNA *prop;
1486         
1487         /* identifiers */
1488         ot->name = "Delete Keying-Set Keyframe";
1489         ot->idname = "ANIM_OT_keyframe_delete";
1490         ot->description = "Delete keyframes on the current frame for all properties in the specified Keying Set";
1491         
1492         /* callbacks */
1493         ot->exec = delete_key_exec; 
1494         ot->poll = modify_key_op_poll;
1495         
1496         /* flags */
1497         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1498         
1499         /* keyingset to use (dynamic enum) */
1500         prop = RNA_def_enum(ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
1501         RNA_def_enum_funcs(prop, ANIM_keying_sets_enum_itemf);
1502         RNA_def_property_flag(prop, PROP_HIDDEN);
1503         ot->prop = prop;
1504         
1505         /* confirm whether a keyframe was added by showing a popup 
1506          *      - by default, this is enabled, since this operator is assumed to be called independently
1507          */
1508         RNA_def_boolean(ot->srna, "confirm_success", 1, "Confirm Successful Delete",
1509                         "Show a popup when the keyframes get successfully removed");
1510 }
1511
1512 /* Delete Key Operator ------------------------ */
1513 /* NOTE: Although this version is simpler than the more generic version for KeyingSets,
1514  * it is more useful for animators working in the 3D view.
1515  */
1516  
1517 static int clear_anim_v3d_exec(bContext *C, wmOperator *UNUSED(op))
1518 {
1519         bool changed = false;
1520
1521         CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
1522         {
1523                 /* just those in active action... */
1524                 if ((ob->adt) && (ob->adt->action)) {
1525                         AnimData *adt = ob->adt;
1526                         bAction *act = adt->action;
1527                         FCurve *fcu, *fcn;
1528                         
1529                         for (fcu = act->curves.first; fcu; fcu = fcn) {
1530                                 short can_delete = FALSE;
1531                                 
1532                                 fcn = fcu->next;
1533                                 
1534                                 /* in pose mode, only delete the F-Curve if it belongs to a selected bone */
1535                                 if (ob->mode & OB_MODE_POSE) {
1536                                         if ((fcu->rna_path) && strstr(fcu->rna_path, "pose.bones[")) {
1537                                                 bPoseChannel *pchan;
1538                                                 char *bone_name;
1539                                                 
1540                                                 /* get bone-name, and check if this bone is selected */
1541                                                 bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
1542                                                 pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
1543                                                 if (bone_name) MEM_freeN(bone_name);
1544                                                 
1545                                                 /* delete if bone is selected*/
1546                                                 if ((pchan) && (pchan->bone)) {
1547                                                         if (pchan->bone->flag & BONE_SELECTED)
1548                                                                 can_delete = TRUE;
1549                                                 }
1550                                         }
1551                                 }
1552                                 else {
1553                                         /* object mode - all of Object's F-Curves are affected */
1554                                         can_delete = TRUE;
1555                                 }
1556                                 
1557                                 /* delete F-Curve completely */
1558                                 if (can_delete) {
1559                                         ANIM_fcurve_delete_from_animdata(NULL, adt, fcu);
1560                                         DAG_id_tag_update(&ob->id, OB_RECALC_OB);
1561                                         changed = true;
1562                                 }
1563                         }
1564                 }
1565         }
1566         CTX_DATA_END;
1567
1568         if (!changed) {
1569                 return OPERATOR_CANCELLED;
1570         }
1571
1572         /* send updates */
1573         WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
1574         
1575         return OPERATOR_FINISHED;
1576 }
1577
1578 void ANIM_OT_keyframe_clear_v3d(wmOperatorType *ot)
1579 {
1580         /* identifiers */
1581         ot->name = "Remove Animation";
1582         ot->description = "Remove all keyframe animation for selected objects";
1583         ot->idname = "ANIM_OT_keyframe_clear_v3d";
1584         
1585         /* callbacks */
1586         ot->invoke = WM_operator_confirm;
1587         ot->exec = clear_anim_v3d_exec; 
1588         
1589         ot->poll = ED_operator_areaactive;
1590         
1591         /* flags */
1592         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1593 }
1594
1595
1596 static int delete_key_v3d_exec(bContext *C, wmOperator *op)
1597 {
1598         Scene *scene = CTX_data_scene(C);
1599         float cfra = (float)CFRA;
1600         
1601         CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
1602         {
1603                 ID *id = &ob->id;
1604                 int success = 0;
1605                 
1606                 /* just those in active action... */
1607                 if ((ob->adt) && (ob->adt->action)) {
1608                         AnimData *adt = ob->adt;
1609                         bAction *act = adt->action;
1610                         FCurve *fcu, *fcn;
1611                         const float cfra_unmap = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
1612                         
1613                         for (fcu = act->curves.first; fcu; fcu = fcn) {
1614                                 fcn = fcu->next;
1615
1616                                 if (BKE_fcurve_is_protected(fcu)) {
1617                                         BKE_reportf(op->reports, RPT_WARNING,
1618                                                     "Not deleting keyframe for locked F-Curve '%s', object '%s'",
1619                                                     fcu->rna_path, id->name + 2);
1620                                         continue;
1621                                 }
1622
1623                                 /* delete keyframes on current frame 
1624                                  * WARNING: this can delete the next F-Curve, hence the "fcn" copying
1625                                  */
1626                                 success += delete_keyframe_fcurve(adt, fcu, cfra_unmap);
1627                         }
1628                 }
1629                 
1630                 /* report success (or failure) */
1631                 BKE_reportf(op->reports, RPT_INFO, "Object '%s' successfully had %d keyframes removed", id->name + 2, success);
1632                 DAG_id_tag_update(&ob->id, OB_RECALC_OB);
1633         }
1634         CTX_DATA_END;
1635         
1636         /* send updates */
1637         WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
1638         
1639         return OPERATOR_FINISHED;
1640 }
1641
1642 void ANIM_OT_keyframe_delete_v3d(wmOperatorType *ot)
1643 {
1644         /* identifiers */
1645         ot->name = "Delete Keyframe";
1646         ot->description = "Remove keyframes on current frame for selected objects";
1647         ot->idname = "ANIM_OT_keyframe_delete_v3d";
1648         
1649         /* callbacks */
1650         ot->invoke = WM_operator_confirm;
1651         ot->exec = delete_key_v3d_exec; 
1652         
1653         ot->poll = ED_operator_areaactive;
1654         
1655         /* flags */
1656         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1657 }
1658
1659
1660 /* Insert Key Button Operator ------------------------ */
1661
1662 static int insert_key_button_exec(bContext *C, wmOperator *op)
1663 {
1664         Scene *scene = CTX_data_scene(C);
1665         PointerRNA ptr = {{NULL}};
1666         PropertyRNA *prop = NULL;
1667         char *path;
1668         float cfra = (float)CFRA;
1669         short success = 0;
1670         int a, index, length, all = RNA_boolean_get(op->ptr, "all");
1671         short flag = 0;
1672         
1673         /* flags for inserting keyframes */
1674         flag = ANIM_get_keyframing_flags(scene, 1);
1675         
1676         /* try to insert keyframe using property retrieved from UI */
1677         uiContextActiveProperty(C, &ptr, &prop, &index);
1678         
1679         if ((ptr.id.data && ptr.data && prop) && RNA_property_animateable(&ptr, prop)) {
1680                 path = RNA_path_from_ID_to_property(&ptr, prop);
1681                 
1682                 if (path) {
1683                         if (all) {
1684                                 length = RNA_property_array_length(&ptr, prop);
1685                                 
1686                                 if (length) index = 0;
1687                                 else length = 1;
1688                         }
1689                         else
1690                                 length = 1;
1691                         
1692                         for (a = 0; a < length; a++)
1693                                 success += insert_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index + a, cfra, flag);
1694                         
1695                         MEM_freeN(path);
1696                 }
1697                 else if (ptr.type == &RNA_NlaStrip) {
1698                         /* handle special vars for NLA-strips */
1699                         NlaStrip *strip = (NlaStrip *)ptr.data;
1700                         FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), flag);
1701                         
1702                         success += insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, 0);
1703                 }
1704                 else {
1705                         BKE_report(op->reports, RPT_WARNING, 
1706                                    "Failed to resolve path to property, try manually specifying this using a Keying Set instead");
1707                 }
1708         }
1709         else {
1710                 if (prop && !RNA_property_animateable(&ptr, prop)) {
1711                         BKE_reportf(op->reports, RPT_WARNING, 
1712                                    "\"%s\" property cannot be animated",
1713                                    RNA_property_identifier(prop));
1714                 }
1715                 else {
1716                         BKE_reportf(op->reports, RPT_WARNING,
1717                                     "Button doesn't appear to have any property information attached (ptr.data = %p, prop = %p)",
1718                                     (void *)ptr.data, (void *)prop);
1719                 }
1720         }
1721         
1722         if (success) {
1723                 /* send updates */
1724                 uiContextAnimUpdate(C);
1725                 
1726                 /* send notifiers that keyframes have been changed */
1727                 WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
1728         }
1729         
1730         return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
1731 }
1732
1733 void ANIM_OT_keyframe_insert_button(wmOperatorType *ot)
1734 {
1735         /* identifiers */
1736         ot->name = "Insert Keyframe (Buttons)";
1737         ot->idname = "ANIM_OT_keyframe_insert_button";
1738         ot->description = "Insert a keyframe for current UI-active property";
1739         
1740         /* callbacks */
1741         ot->exec = insert_key_button_exec; 
1742         ot->poll = modify_key_op_poll;
1743         
1744         /* flags */
1745         ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
1746
1747         /* properties */
1748         RNA_def_boolean(ot->srna, "all", 1, "All", "Insert a keyframe for all element of the array");
1749 }
1750
1751 /* Delete Key Button Operator ------------------------ */
1752
1753 static int delete_key_button_exec(bContext *C, wmOperator *op)
1754 {
1755         Scene *scene = CTX_data_scene(C);
1756         PointerRNA ptr = {{NULL}};
1757         PropertyRNA *prop = NULL;
1758         char *path;
1759         float cfra = (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
1760         short success = 0;
1761         int a, index, length, all = RNA_boolean_get(op->ptr, "all");
1762         
1763         /* try to insert keyframe using property retrieved from UI */
1764         uiContextActiveProperty(C, &ptr, &prop, &index);
1765
1766         if (ptr.id.data && ptr.data && prop) {
1767                 path = RNA_path_from_ID_to_property(&ptr, prop);
1768                 
1769                 if (path) {
1770                         if (all) {
1771                                 length = RNA_property_array_length(&ptr, prop);
1772                                 
1773                                 if (length) index = 0;
1774                                 else length = 1;
1775                         }
1776                         else
1777                                 length = 1;
1778                         
1779                         for (a = 0; a < length; a++)
1780                                 success += delete_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index + a, cfra, 0);
1781                         
1782                         MEM_freeN(path);
1783                 }
1784                 else if (G.debug & G_DEBUG)
1785                         printf("Button Delete-Key: no path to property\n");
1786         }
1787         else if (G.debug & G_DEBUG) {
1788                 printf("ptr.data = %p, prop = %p\n", (void *)ptr.data, (void *)prop);
1789         }
1790         
1791         
1792         if (success) {
1793                 /* send updates */
1794                 uiContextAnimUpdate(C);
1795                 
1796                 /* send notifiers that keyframes have been changed */
1797                 WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
1798         }
1799         
1800         return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
1801 }
1802
1803 void ANIM_OT_keyframe_delete_button(wmOperatorType *ot)
1804 {
1805         /* identifiers */
1806         ot->name = "Delete Keyframe (Buttons)";
1807         ot->idname = "ANIM_OT_keyframe_delete_button";
1808         ot->description = "Delete current keyframe of current UI-active property";
1809         
1810         /* callbacks */
1811         ot->exec = delete_key_button_exec; 
1812         ot->poll = modify_key_op_poll;
1813         
1814         /* flags */
1815         ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
1816
1817         /* properties */
1818         RNA_def_boolean(ot->srna, "all", 1, "All", "Delete keyframes from all elements of the array");
1819 }
1820
1821
1822 /* Clear Key Button Operator ------------------------ */
1823
1824 static int clear_key_button_exec(bContext *C, wmOperator *op)
1825 {
1826         PointerRNA ptr = {{NULL}};
1827         PropertyRNA *prop = NULL;
1828         char *path;
1829         short success = 0;
1830         int a, index, length, all = RNA_boolean_get(op->ptr, "all");
1831
1832         /* try to insert keyframe using property retrieved from UI */
1833         uiContextActiveProperty(C, &ptr, &prop, &index);
1834
1835         if (ptr.id.data && ptr.data && prop) {
1836                 path = RNA_path_from_ID_to_property(&ptr, prop);
1837                 
1838                 if (path) {
1839                         if (all) {
1840                                 length = RNA_property_array_length(&ptr, prop);
1841                                 
1842                                 if (length) index = 0;
1843                                 else length = 1;
1844                         }
1845                         else
1846                                 length = 1;
1847                         
1848                         for (a = 0; a < length; a++)
1849                                 success += clear_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index + a, 0);
1850                         
1851                         MEM_freeN(path);
1852                 }
1853                 else if (G.debug & G_DEBUG)
1854                         printf("Button Clear-Key: no path to property\n");
1855         }
1856         else if (G.debug & G_DEBUG) {
1857                 printf("ptr.data = %p, prop = %p\n", (void *)ptr.data, (void *)prop);
1858         }
1859
1860
1861         if (success) {
1862                 /* send updates */
1863                 uiContextAnimUpdate(C);
1864                 
1865                 /* send notifiers that keyframes have been changed */
1866                 WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
1867         }
1868
1869         return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
1870 }
1871
1872 void ANIM_OT_keyframe_clear_button(wmOperatorType *ot)
1873 {
1874         /* identifiers */
1875         ot->name = "Clear Keyframe (Buttons)";
1876         ot->idname = "ANIM_OT_keyframe_clear_button";
1877         ot->description = "Clear all keyframes on the currently active property";
1878
1879         /* callbacks */
1880         ot->exec = clear_key_button_exec;
1881         ot->poll = modify_key_op_poll;
1882
1883         /* flags */
1884         ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
1885
1886         /* properties */
1887         RNA_def_boolean(ot->srna, "all", 1, "All", "Clear keyframes from all elements of the array");
1888 }
1889
1890 /* ******************************************* */
1891 /* AUTO KEYFRAME */
1892
1893 int autokeyframe_cfra_can_key(Scene *scene, ID *id)
1894 {
1895         float cfra = (float)CFRA; // XXX for now, this will do
1896         
1897         /* only filter if auto-key mode requires this */
1898         if (IS_AUTOKEY_ON(scene) == 0)
1899                 return 0;
1900                 
1901         if (IS_AUTOKEY_MODE(scene, NORMAL)) {
1902                 /* can insert anytime we like... */
1903                 return 1;
1904         }
1905         else { /* REPLACE */
1906                 /* for whole block - only key if there's a keyframe on that frame already
1907                  *      this is a valid assumption when we're blocking + tweaking
1908                  */
1909                 return id_frame_has_keyframe(id, cfra, ANIMFILTER_KEYS_LOCAL);
1910         }
1911 }
1912
1913 /* ******************************************* */
1914 /* KEYFRAME DETECTION */
1915
1916 /* --------------- API/Per-Datablock Handling ------------------- */
1917
1918 /* Checks if some F-Curve has a keyframe for a given frame */
1919 short fcurve_frame_has_keyframe(FCurve *fcu, float frame, short filter)
1920 {
1921         /* quick sanity check */
1922         if (ELEM(NULL, fcu, fcu->bezt))
1923                 return 0;
1924         
1925         /* we either include all regardless of muting, or only non-muted  */
1926         if ((filter & ANIMFILTER_KEYS_MUTED) || (fcu->flag & FCURVE_MUTED) == 0) {
1927                 bool replace;
1928                 int i = binarysearch_bezt_index(fcu->bezt, frame, fcu->totvert, &replace);
1929                 
1930                 /* binarysearch_bezt_index will set replace to be 0 or 1
1931                  * - obviously, 1 represents a match
1932                  */
1933                 if (replace) {
1934                         /* sanity check: 'i' may in rare cases exceed arraylen */
1935                         if ((i >= 0) && (i < fcu->totvert))
1936                                 return 1;
1937                 }
1938         }
1939         
1940         return 0;
1941 }
1942
1943 /* Checks whether an Action has a keyframe for a given frame 
1944  * Since we're only concerned whether a keyframe exists, we can simply loop until a match is found...
1945  */
1946 static short action_frame_has_keyframe(bAction *act, float frame, short filter)
1947 {
1948         FCurve *fcu;
1949         
1950         /* can only find if there is data */
1951         if (act == NULL)
1952                 return 0;
1953                 
1954         /* if only check non-muted, check if muted */
1955         if ((filter & ANIMFILTER_KEYS_MUTED) || (act->flag & ACT_MUTED))
1956                 return 0;
1957         
1958         /* loop over F-Curves, using binary-search to try to find matches 
1959          *      - this assumes that keyframes are only beztriples
1960          */
1961         for (fcu = act->curves.first; fcu; fcu = fcu->next) {
1962                 /* only check if there are keyframes (currently only of type BezTriple) */
1963                 if (fcu->bezt && fcu->totvert) {
1964                         if (fcurve_frame_has_keyframe(fcu, frame, filter))
1965                                 return 1;
1966                 }
1967         }
1968         
1969         /* nothing found */
1970         return 0;
1971 }
1972
1973 /* Checks whether an Object has a keyframe for a given frame */
1974 static short object_frame_has_keyframe(Object *ob, float frame, short filter)
1975 {
1976         /* error checking */
1977         if (ob == NULL)
1978                 return 0;
1979         
1980         /* check own animation data - specifically, the action it contains */
1981         if ((ob->adt) && (ob->adt->action)) {
1982                 if (action_frame_has_keyframe(ob->adt->action, frame, filter))
1983                         return 1;
1984         }
1985         
1986         /* try shapekey keyframes (if available, and allowed by filter) */
1987         if (!(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOSKEY) ) {
1988                 Key *key = BKE_key_from_object(ob);
1989                 
1990                 /* shapekeys can have keyframes ('Relative Shape Keys') 
1991                  * or depend on time (old 'Absolute Shape Keys') 
1992                  */
1993                  
1994                 /* 1. test for relative (with keyframes) */
1995                 if (id_frame_has_keyframe((ID *)key, frame, filter))
1996                         return 1;
1997
1998                 /* 2. test for time */
1999                 /* TODO... yet to be implemented (this feature may evolve before then anyway) */
2000         }
2001
2002         /* try materials */
2003         if (!(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOMAT) ) {
2004                 /* if only active, then we can skip a lot of looping */
2005                 if (filter & ANIMFILTER_KEYS_ACTIVE) {
2006                         Material *ma = give_current_material(ob, (ob->actcol + 1));
2007                         
2008                         /* we only retrieve the active material... */
2009                         if (id_frame_has_keyframe((ID *)ma, frame, filter))
2010                                 return 1;
2011                 }
2012                 else {
2013                         int a;
2014                         
2015                         /* loop over materials */
2016                         for (a = 0; a < ob->totcol; a++) {
2017                                 Material *ma = give_current_material(ob, a + 1);
2018                                 
2019                                 if (id_frame_has_keyframe((ID *)ma, frame, filter))
2020                                         return 1;
2021                         }
2022                 }
2023         }
2024         
2025         /* nothing found */
2026         return 0;
2027 }
2028
2029 /* --------------- API ------------------- */
2030
2031 /* Checks whether a keyframe exists for the given ID-block one the given frame */
2032 short id_frame_has_keyframe(ID *id, float frame, short filter)
2033 {
2034         /* sanity checks */
2035         if (id == NULL)
2036                 return 0;
2037         
2038         /* perform special checks for 'macro' types */
2039         switch (GS(id->name)) {
2040                 case ID_OB: /* object */
2041                         return object_frame_has_keyframe((Object *)id, frame, filter);
2042                         break;
2043                         
2044 #if 0
2045                 // XXX TODO... for now, just use 'normal' behavior
2046                 case ID_SCE: /* scene */
2047                         break;
2048 #endif
2049                 default:  /* 'normal type' */
2050                 {
2051                         AnimData *adt = BKE_animdata_from_id(id);
2052                         
2053                         /* only check keyframes in active action */
2054                         if (adt)
2055                                 return action_frame_has_keyframe(adt->action, frame, filter);
2056                         break;
2057                 }
2058         }
2059         
2060         
2061         /* no keyframe found */
2062         return 0;
2063 }
2064
2065 /* ************************************************** */
2066
2067 int ED_autokeyframe_object(bContext *C, Scene *scene, Object *ob, KeyingSet *ks)
2068 {
2069         /* auto keyframing */
2070         if (autokeyframe_cfra_can_key(scene, &ob->id)) {
2071                 ListBase dsources = {NULL, NULL};
2072
2073                 /* now insert the keyframe(s) using the Keying Set
2074                  *      1) add datasource override for the Object
2075                  *      2) insert keyframes
2076                  *      3) free the extra info
2077                  */
2078                 ANIM_relative_keyingset_add_source(&dsources, &ob->id, NULL, NULL);
2079                 ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
2080                 BLI_freelistN(&dsources);
2081
2082                 return TRUE;
2083         }
2084         else {
2085                 return FALSE;
2086         }
2087 }
2088
2089 int ED_autokeyframe_pchan(bContext *C, Scene *scene, Object *ob, bPoseChannel *pchan, KeyingSet *ks)
2090 {
2091         if (autokeyframe_cfra_can_key(scene, &ob->id)) {
2092                 ListBase dsources = {NULL, NULL};
2093
2094                 /* now insert the keyframe(s) using the Keying Set
2095                  *      1) add datasource override for the PoseChannel
2096                  *      2) insert keyframes
2097                  *      3) free the extra info
2098                  */
2099                 ANIM_relative_keyingset_add_source(&dsources, &ob->id, &RNA_PoseBone, pchan);
2100                 ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
2101                 BLI_freelistN(&dsources);
2102
2103                 /* clear any unkeyed tags */
2104                 if (pchan->bone) {
2105                         pchan->bone->flag &= ~BONE_UNKEYED;
2106                 }
2107
2108                 return TRUE;
2109         }
2110         else {
2111                 /* add unkeyed tags */
2112                 if (pchan->bone) {
2113                         pchan->bone->flag |= BONE_UNKEYED;
2114                 }
2115
2116                 return FALSE;
2117         }
2118 }