e8451b0f979646a89ad2d62b3f3d7c85db721ae0
[blender.git] / source / blender / editors / animation / keyframing.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): Joshua Leung (full recode)
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29  
30 #include <stdio.h>
31 #include <stddef.h>
32 #include <string.h>
33 #include <math.h>
34 #include <float.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "BLI_blenlib.h"
39 #include "BLI_arithb.h"
40 #include "BLI_dynstr.h"
41
42 #include "DNA_anim_types.h"
43 #include "DNA_action_types.h"
44 #include "DNA_armature_types.h"
45 #include "DNA_constraint_types.h"
46 #include "DNA_key_types.h"
47 #include "DNA_object_types.h"
48 #include "DNA_material_types.h"
49 #include "DNA_scene_types.h"
50 #include "DNA_userdef_types.h"
51 #include "DNA_windowmanager_types.h"
52
53 #include "BKE_animsys.h"
54 #include "BKE_action.h"
55 #include "BKE_constraint.h"
56 #include "BKE_fcurve.h"
57 #include "BKE_nla.h"
58 #include "BKE_global.h"
59 #include "BKE_utildefines.h"
60 #include "BKE_context.h"
61 #include "BKE_report.h"
62 #include "BKE_key.h"
63 #include "BKE_material.h"
64
65 #include "ED_anim_api.h"
66 #include "ED_keyframing.h"
67 #include "ED_keyframes_edit.h"
68 #include "ED_screen.h"
69 #include "ED_util.h"
70
71 #include "UI_interface.h"
72
73 #include "WM_api.h"
74 #include "WM_types.h"
75
76 #include "RNA_access.h"
77 #include "RNA_define.h"
78 #include "RNA_types.h"
79
80 #include "anim_intern.h"
81
82 /* ******************************************* */
83 /* Animation Data Validation */
84
85 /* Get (or add relevant data to be able to do so) the Active Action for the given 
86  * Animation Data block, given an ID block where the Animation Data should reside.
87  */
88 bAction *verify_adt_action (ID *id, short add)
89 {
90         AnimData *adt;
91         
92         /* init animdata if none available yet */
93         adt= BKE_animdata_from_id(id);
94         if ((adt == NULL) && (add))
95                 adt= BKE_id_add_animdata(id);
96         if (adt == NULL) { 
97                 /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */
98                 printf("ERROR: Couldn't add AnimData (ID = %s) \n", (id) ? (id->name) : "<None>");
99                 return NULL;
100         }
101                 
102         /* init action if none available yet */
103         // TODO: need some wizardry to handle NLA stuff correct
104         if ((adt->action == NULL) && (add))
105                 adt->action= add_empty_action("Action");
106                 
107         /* return the action */
108         return adt->action;
109 }
110
111 /* Get (or add relevant data to be able to do so) F-Curve from the Active Action, 
112  * for the given Animation Data block. This assumes that all the destinations are valid.
113  */
114 FCurve *verify_fcurve (bAction *act, const char group[], const char rna_path[], const int array_index, short add)
115 {
116         bActionGroup *grp;
117         FCurve *fcu;
118         
119         /* sanity checks */
120         if ELEM(NULL, act, rna_path)
121                 return NULL;
122                 
123         /* try to find f-curve matching for this setting 
124          *      - add if not found and allowed to add one
125          *              TODO: add auto-grouping support? how this works will need to be resolved
126          */
127         if (act)
128                 fcu= list_find_fcurve(&act->curves, rna_path, array_index);
129         else
130                 fcu= NULL;
131         
132         if ((fcu == NULL) && (add)) {
133                 /* use default settings to make a F-Curve */
134                 fcu= MEM_callocN(sizeof(FCurve), "FCurve");
135                 
136                 fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
137                 if (act->curves.first==NULL) 
138                         fcu->flag |= FCURVE_ACTIVE;     /* first one added active */
139                         
140                 /* store path - make copy, and store that */
141                 fcu->rna_path= BLI_strdupn(rna_path, strlen(rna_path));
142                 fcu->array_index= array_index;
143                 
144                 /* if a group name has been provided, try to add or find a group, then add F-Curve to it */
145                 if (group) {
146                         /* try to find group */
147                         grp= action_groups_find_named(act, group);
148                         
149                         /* no matching groups, so add one */
150                         if (grp == NULL) {
151                                 /* Add a new group, and make it active */
152                                 grp= MEM_callocN(sizeof(bActionGroup), "bActionGroup");
153                                 
154                                 grp->flag = AGRP_SELECTED;
155                                 BLI_snprintf(grp->name, 64, group);
156                                 
157                                 BLI_addtail(&act->groups, grp);
158                                 BLI_uniquename(&act->groups, grp, "Group", '.', offsetof(bActionGroup, name), 64);
159                         }
160                         
161                         /* add F-Curve to group */
162                         action_groups_add_channel(act, grp, fcu);
163                 }
164                 else {
165                         /* just add F-Curve to end of Action's list */
166                         BLI_addtail(&act->curves, fcu);
167                 }
168         }
169         
170         /* return the F-Curve */
171         return fcu;
172 }
173
174 /* ************************************************** */
175 /* KEYFRAME INSERTION */
176
177 /* -------------- BezTriple Insertion -------------------- */
178
179 /* This function adds a given BezTriple to an F-Curve. It will allocate 
180  * memory for the array if needed, and will insert the BezTriple into a
181  * suitable place in chronological order.
182  * 
183  * NOTE: any recalculate of the F-Curve that needs to be done will need to 
184  *              be done by the caller.
185  */
186 int insert_bezt_fcurve (FCurve *fcu, BezTriple *bezt, short flag)
187 {
188         int i= 0;
189         
190         if (fcu->bezt) {
191                 short replace = -1;
192                 i = binarysearch_bezt_index(fcu->bezt, bezt->vec[1][0], fcu->totvert, &replace);
193                 
194                 if (replace) {                  
195                         /* sanity check: 'i' may in rare cases exceed arraylen */
196                         if ((i >= 0) && (i < fcu->totvert)) {
197                                 /* take care with the handletypes and other info if the replacement flags are set */
198                                 if (flag & INSERTKEY_REPLACE) {
199                                         BezTriple *dst= (fcu->bezt + i);
200                                         float dy= bezt->vec[1][1] - dst->vec[1][1];
201                                         
202                                         /* just apply delta value change to the handle values */
203                                         dst->vec[0][1] += dy;
204                                         dst->vec[1][1] += dy;
205                                         dst->vec[2][1] += dy;
206                                         
207                                         // TODO: perform some other operations?
208                                 }
209                                 else {
210                                         /* just brutally replace the values */
211                                         *(fcu->bezt + i) = *bezt;
212                                 }
213                         }
214                 }
215                 else if ((flag & INSERTKEY_REPLACE) == 0) {
216                         /* insert new - if we're not restricted to replacing keyframes only */
217                         BezTriple *newb= MEM_callocN((fcu->totvert+1)*sizeof(BezTriple), "beztriple");
218                         
219                         /* add the beztriples that should occur before the beztriple to be pasted (originally in ei->icu) */
220                         if (i > 0)
221                                 memcpy(newb, fcu->bezt, i*sizeof(BezTriple));
222                         
223                         /* add beztriple to paste at index i */
224                         *(newb + i)= *bezt;
225                         
226                         /* add the beztriples that occur after the beztriple to be pasted (originally in icu) */
227                         if (i < fcu->totvert) 
228                                 memcpy(newb+i+1, fcu->bezt+i, (fcu->totvert-i)*sizeof(BezTriple));
229                         
230                         /* replace (+ free) old with new, only if necessary to do so */
231                         MEM_freeN(fcu->bezt);
232                         fcu->bezt= newb;
233                                 
234                         fcu->totvert++;
235                 }
236         }
237         else {
238                 // TODO: need to check for old sample-data now...
239                 fcu->bezt= MEM_callocN(sizeof(BezTriple), "beztriple");
240                 *(fcu->bezt)= *bezt;
241                 fcu->totvert= 1;
242         }
243         
244         
245         /* we need to return the index, so that some tools which do post-processing can 
246          * detect where we added the BezTriple in the array
247          */
248         return i;
249 }
250
251 /* This function is a wrapper for insert_bezt_fcurve_internal(), and should be used when
252  * adding a new keyframe to a curve, when the keyframe doesn't exist anywhere else yet. 
253  * It returns the index at which the keyframe was added.
254  */
255 int insert_vert_fcurve (FCurve *fcu, float x, float y, short flag)
256 {
257         BezTriple beztr;
258         int a;
259         
260         /* set all three points, for nicer start position */
261         memset(&beztr, 0, sizeof(BezTriple));
262         beztr.vec[0][0]= x; 
263         beztr.vec[0][1]= y;
264         beztr.vec[1][0]= x;
265         beztr.vec[1][1]= y;
266         beztr.vec[2][0]= x;
267         beztr.vec[2][1]= y;
268         beztr.ipo= U.ipo_new; /* use default interpolation mode here... */
269         beztr.f1= beztr.f2= beztr.f3= SELECT;
270         beztr.h1= beztr.h2= HD_AUTO; // XXX what about when we replace an old one?
271         
272         /* add temp beztriple to keyframes */
273         a= insert_bezt_fcurve(fcu, &beztr, flag);
274         
275         /* what if 'a' is a negative index? 
276          * for now, just exit to prevent any segfaults
277          */
278         if (a < 0) return -1;
279         
280         /* don't recalculate handles if fast is set
281          *      - this is a hack to make importers faster
282          *      - we may calculate twice (due to autohandle needing to be calculated twice)
283          */
284         if ((flag & INSERTKEY_FAST) == 0) 
285                 calchandles_fcurve(fcu);
286         
287         /* set handletype and interpolation */
288         if ((fcu->totvert > 2) && (flag & INSERTKEY_REPLACE)==0) {
289                 BezTriple *bezt= (fcu->bezt + a);
290                 char h1, h2;
291                 
292                 /* set handles (autohandles by default) */
293                 h1= h2= HD_AUTO;
294                 
295                 if (a > 0) h1= (bezt-1)->h2;
296                 if (a < fcu->totvert-1) h2= (bezt+1)->h1;
297                 
298                 bezt->h1= h1;
299                 bezt->h2= h2;
300                 
301                 /* set interpolation from previous (if available) */
302                 if (a > 0) bezt->ipo= (bezt-1)->ipo;
303                 else if (a < fcu->totvert-1) bezt->ipo= (bezt+1)->ipo;
304                         
305                 /* don't recalculate handles if fast is set
306                  *      - this is a hack to make importers faster
307                  *      - we may calculate twice (due to autohandle needing to be calculated twice)
308                  */
309                 if ((flag & INSERTKEY_FAST) == 0) 
310                         calchandles_fcurve(fcu);
311         }
312         
313         /* return the index at which the keyframe was added */
314         return a;
315 }
316
317 /* -------------- 'Smarter' Keyframing Functions -------------------- */
318 /* return codes for new_key_needed */
319 enum {
320         KEYNEEDED_DONTADD = 0,
321         KEYNEEDED_JUSTADD,
322         KEYNEEDED_DELPREV,
323         KEYNEEDED_DELNEXT
324 } eKeyNeededStatus;
325
326 /* This helper function determines whether a new keyframe is needed */
327 /* Cases where keyframes should not be added:
328  *      1. Keyframe to be added bewteen two keyframes with similar values
329  *      2. Keyframe to be added on frame where two keyframes are already situated
330  *      3. Keyframe lies at point that intersects the linear line between two keyframes
331  */
332 static short new_key_needed (FCurve *fcu, float cFrame, float nValue) 
333 {
334         BezTriple *bezt=NULL, *prev=NULL;
335         int totCount, i;
336         float valA = 0.0f, valB = 0.0f;
337         
338         /* safety checking */
339         if (fcu == NULL) return KEYNEEDED_JUSTADD;
340         totCount= fcu->totvert;
341         if (totCount == 0) return KEYNEEDED_JUSTADD;
342         
343         /* loop through checking if any are the same */
344         bezt= fcu->bezt;
345         for (i=0; i<totCount; i++) {
346                 float prevPosi=0.0f, prevVal=0.0f;
347                 float beztPosi=0.0f, beztVal=0.0f;
348                         
349                 /* get current time+value */    
350                 beztPosi= bezt->vec[1][0];
351                 beztVal= bezt->vec[1][1];
352                         
353                 if (prev) {
354                         /* there is a keyframe before the one currently being examined */               
355                         
356                         /* get previous time+value */
357                         prevPosi= prev->vec[1][0];
358                         prevVal= prev->vec[1][1];
359                         
360                         /* keyframe to be added at point where there are already two similar points? */
361                         if (IS_EQ(prevPosi, cFrame) && IS_EQ(beztPosi, cFrame) && IS_EQ(beztPosi, prevPosi)) {
362                                 return KEYNEEDED_DONTADD;
363                         }
364                         
365                         /* keyframe between prev+current points ? */
366                         if ((prevPosi <= cFrame) && (cFrame <= beztPosi)) {
367                                 /* is the value of keyframe to be added the same as keyframes on either side ? */
368                                 if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) {
369                                         return KEYNEEDED_DONTADD;
370                                 }
371                                 else {
372                                         float realVal;
373                                         
374                                         /* get real value of curve at that point */
375                                         realVal= evaluate_fcurve(fcu, cFrame);
376                                         
377                                         /* compare whether it's the same as proposed */
378                                         if (IS_EQ(realVal, nValue)) 
379                                                 return KEYNEEDED_DONTADD;
380                                         else 
381                                                 return KEYNEEDED_JUSTADD;
382                                 }
383                         }
384                         
385                         /* new keyframe before prev beztriple? */
386                         if (cFrame < prevPosi) {
387                                 /* A new keyframe will be added. However, whether the previous beztriple
388                                  * stays around or not depends on whether the values of previous/current
389                                  * beztriples and new keyframe are the same.
390                                  */
391                                 if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal))
392                                         return KEYNEEDED_DELNEXT;
393                                 else 
394                                         return KEYNEEDED_JUSTADD;
395                         }
396                 }
397                 else {
398                         /* just add a keyframe if there's only one keyframe 
399                          * and the new one occurs before the exisiting one does.
400                          */
401                         if ((cFrame < beztPosi) && (totCount==1))
402                                 return KEYNEEDED_JUSTADD;
403                 }
404                 
405                 /* continue. frame to do not yet passed (or other conditions not met) */
406                 if (i < (totCount-1)) {
407                         prev= bezt;
408                         bezt++;
409                 }
410                 else
411                         break;
412         }
413         
414         /* Frame in which to add a new-keyframe occurs after all other keys
415          * -> If there are at least two existing keyframes, then if the values of the
416          *       last two keyframes and the new-keyframe match, the last existing keyframe
417          *       gets deleted as it is no longer required.
418          * -> Otherwise, a keyframe is just added. 1.0 is added so that fake-2nd-to-last
419          *       keyframe is not equal to last keyframe.
420          */
421         bezt= (fcu->bezt + (fcu->totvert - 1));
422         valA= bezt->vec[1][1];
423         
424         if (prev)
425                 valB= prev->vec[1][1];
426         else 
427                 valB= bezt->vec[1][1] + 1.0f; 
428                 
429         if (IS_EQ(valA, nValue) && IS_EQ(valA, valB)) 
430                 return KEYNEEDED_DELPREV;
431         else 
432                 return KEYNEEDED_JUSTADD;
433 }
434
435 /* ------------------ RNA Data-Access Functions ------------------ */
436
437 /* Try to read value using RNA-properties obtained already */
438 static float setting_get_rna_value (PointerRNA *ptr, PropertyRNA *prop, int index)
439 {
440         float value= 0.0f;
441         
442         switch (RNA_property_type(prop)) {
443                 case PROP_BOOLEAN:
444                         if (RNA_property_array_length(ptr, prop))
445                                 value= (float)RNA_property_boolean_get_index(ptr, prop, index);
446                         else
447                                 value= (float)RNA_property_boolean_get(ptr, prop);
448                         break;
449                 case PROP_INT:
450                         if (RNA_property_array_length(ptr, prop))
451                                 value= (float)RNA_property_int_get_index(ptr, prop, index);
452                         else
453                                 value= (float)RNA_property_int_get(ptr, prop);
454                         break;
455                 case PROP_FLOAT:
456                         if (RNA_property_array_length(ptr, prop))
457                                 value= RNA_property_float_get_index(ptr, prop, index);
458                         else
459                                 value= RNA_property_float_get(ptr, prop);
460                         break;
461                 case PROP_ENUM:
462                         value= (float)RNA_property_enum_get(ptr, prop);
463                         break;
464                 default:
465                         break;
466         }
467         
468         return value;
469 }
470
471 /* ------------------ 'Visual' Keyframing Functions ------------------ */
472
473 /* internal status codes for visualkey_can_use */
474 enum {
475         VISUALKEY_NONE = 0,
476         VISUALKEY_LOC,
477         VISUALKEY_ROT,
478 };
479
480 /* This helper function determines if visual-keyframing should be used when  
481  * inserting keyframes for the given channel. As visual-keyframing only works
482  * on Object and Pose-Channel blocks, this should only get called for those 
483  * blocktypes, when using "standard" keying but 'Visual Keying' option in Auto-Keying 
484  * settings is on.
485  */
486 static short visualkey_can_use (PointerRNA *ptr, PropertyRNA *prop)
487 {
488         bConstraint *con= NULL;
489         short searchtype= VISUALKEY_NONE;
490         char *identifier= NULL;
491         
492         /* validate data */
493         // TODO: this check is probably not needed, but it won't hurt
494         if (ELEM3(NULL, ptr, ptr->data, prop))
495                 return 0;
496                 
497         /* get first constraint and determine type of keyframe constraints to check for 
498          *      - constraints can be on either Objects or PoseChannels, so we only check if the
499          *        ptr->type is RNA_Object or RNA_PoseChannel, which are the RNA wrapping-info for
500          *        those structs, allowing us to identify the owner of the data 
501          */
502         if (ptr->type == &RNA_Object) {
503                 /* Object */
504                 Object *ob= (Object *)ptr->data;
505                 
506                 con= ob->constraints.first;
507                 identifier= (char *)RNA_property_identifier(prop);
508         }
509         else if (ptr->type == &RNA_PoseChannel) {
510                 /* Pose Channel */
511                 bPoseChannel *pchan= (bPoseChannel *)ptr->data;
512                 
513                 con= pchan->constraints.first;
514                 identifier= (char *)RNA_property_identifier(prop);
515         }
516         
517         /* check if any data to search using */
518         if (ELEM(NULL, con, identifier))
519                 return 0;
520                 
521         /* location or rotation identifiers only... */
522         if (strstr(identifier, "location"))
523                 searchtype= VISUALKEY_LOC;
524         else if (strstr(identifier, "rotation"))
525                 searchtype= VISUALKEY_ROT;
526         else {
527                 printf("visualkey_can_use() failed: identifier - '%s' \n", identifier);
528                 return 0;
529         }
530         
531         
532         /* only search if a searchtype and initial constraint are available */
533         if (searchtype && con) {
534                 for (; con; con= con->next) {
535                         /* only consider constraint if it is not disabled, and has influence */
536                         if (con->flag & CONSTRAINT_DISABLE) continue;
537                         if (con->enforce == 0.0f) continue;
538                         
539                         /* some constraints may alter these transforms */
540                         switch (con->type) {
541                                 /* multi-transform constraints */
542                                 case CONSTRAINT_TYPE_CHILDOF:
543                                         return 1;
544                                 case CONSTRAINT_TYPE_TRANSFORM:
545                                         return 1;
546                                 case CONSTRAINT_TYPE_FOLLOWPATH:
547                                         return 1;
548                                 case CONSTRAINT_TYPE_KINEMATIC:
549                                         return 1;
550                                         
551                                 /* single-transform constraits  */
552                                 case CONSTRAINT_TYPE_TRACKTO:
553                                         if (searchtype==VISUALKEY_ROT) return 1;
554                                         break;
555                                 case CONSTRAINT_TYPE_ROTLIMIT:
556                                         if (searchtype==VISUALKEY_ROT) return 1;
557                                         break;
558                                 case CONSTRAINT_TYPE_LOCLIMIT:
559                                         if (searchtype==VISUALKEY_LOC) return 1;
560                                         break;
561                                 case CONSTRAINT_TYPE_ROTLIKE:
562                                         if (searchtype==VISUALKEY_ROT) return 1;
563                                         break;
564                                 case CONSTRAINT_TYPE_DISTLIMIT:
565                                         if (searchtype==VISUALKEY_LOC) return 1;
566                                         break;
567                                 case CONSTRAINT_TYPE_LOCLIKE:
568                                         if (searchtype==VISUALKEY_LOC) return 1;
569                                         break;
570                                 case CONSTRAINT_TYPE_LOCKTRACK:
571                                         if (searchtype==VISUALKEY_ROT) return 1;
572                                         break;
573                                 case CONSTRAINT_TYPE_MINMAX:
574                                         if (searchtype==VISUALKEY_LOC) return 1;
575                                         break;
576                                 
577                                 default:
578                                         break;
579                         }
580                 }
581         }
582         
583         /* when some condition is met, this function returns, so here it can be 0 */
584         return 0;
585 }
586
587 /* This helper function extracts the value to use for visual-keyframing 
588  * In the event that it is not possible to perform visual keying, try to fall-back
589  * to using the default method. Assumes that all data it has been passed is valid.
590  */
591 static float visualkey_get_value (PointerRNA *ptr, PropertyRNA *prop, int array_index)
592 {
593         char *identifier= (char *)RNA_property_identifier(prop);
594         
595         /* handle for Objects or PoseChannels only 
596          *      - constraints can be on either Objects or PoseChannels, so we only check if the
597          *        ptr->type is RNA_Object or RNA_PoseChannel, which are the RNA wrapping-info for
598          *        those structs, allowing us to identify the owner of the data 
599          *      - assume that array_index will be sane
600          */
601         if (ptr->type == &RNA_Object) {
602                 Object *ob= (Object *)ptr->data;
603                 
604                 /* parented objects are not supported, as the effects of the parent
605                  * are included in the matrix, which kindof beats the point
606                  */
607                 if (ob->parent == NULL) {
608                         /* only Location or Rotation keyframes are supported now */
609                         if (strstr(identifier, "location")) {
610                                 return ob->obmat[3][array_index];
611                         }
612                         else if (strstr(identifier, "rotation")) {
613                                 float eul[3];
614                                 
615                                 Mat4ToEul(ob->obmat, eul);
616                                 return eul[array_index];
617                         }
618                 }
619         }
620         else if (ptr->type == &RNA_PoseChannel) {
621                 Object *ob= (Object *)ptr->id.data; /* we assume that this is always set, and is an object */
622                 bPoseChannel *pchan= (bPoseChannel *)ptr->data;
623                 float tmat[4][4];
624                 
625                 /* Although it is not strictly required for this particular space conversion, 
626                  * arg1 must not be null, as there is a null check for the other conversions to
627                  * be safe. Therefore, the active object is passed here, and in many cases, this
628                  * will be what owns the pose-channel that is getting this anyway.
629                  */
630                 Mat4CpyMat4(tmat, pchan->pose_mat);
631                 constraint_mat_convertspace(ob, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
632                 
633                 /* Loc, Rot/Quat keyframes are supported... */
634                 if (strstr(identifier, "location")) {
635                         /* only use for non-connected bones */
636                         if ((pchan->bone->parent) && !(pchan->bone->flag & BONE_CONNECTED))
637                                 return tmat[3][array_index];
638                         else if (pchan->bone->parent == NULL)
639                                 return tmat[3][array_index];
640                 }
641                 else if (strstr(identifier, "euler_rotation")) {
642                         float eul[3];
643                         
644                         /* euler-rotation test before standard rotation, as standard rotation does quats */
645                         Mat4ToEulO(tmat, eul, pchan->rotmode);
646                         return eul[array_index];
647                 }
648                 else if (strstr(identifier, "rotation")) {
649                         float trimat[3][3], quat[4];
650                         
651                         Mat3CpyMat4(trimat, tmat);
652                         Mat3ToQuat_is_ok(trimat, quat);
653                         
654                         return quat[array_index];
655                 }
656         }
657         
658         /* as the function hasn't returned yet, read value from system in the default way */
659         return setting_get_rna_value(ptr, prop, array_index);
660 }
661
662 /* ------------------------- Insert Key API ------------------------- */
663
664 /* Secondary Keyframing API call: 
665  *      Use this when validation of necessary animation data is not necessary, since an RNA-pointer to the necessary
666  *      data being keyframed, and a pointer to the F-Curve to use have both been provided.
667  *
668  *      The flag argument is used for special settings that alter the behaviour of
669  *      the keyframe insertion. These include the 'visual' keyframing modes, quick refresh,
670  *      and extra keyframe filtering.
671  */
672 short insert_keyframe_direct (PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, float cfra, short flag)
673 {
674         float curval= 0.0f;
675         
676         /* no F-Curve to add keyframe to? */
677         if (fcu == NULL) {
678                 printf("ERROR: no F-Curve to add keyframes to \n");
679                 return 0;
680         }
681         /* F-Curve not editable? */
682         if ( (fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ) {
683                 if (G.f & G_DEBUG)
684                         printf("WARNING: not inserting keyframe for locked F-Curve \n");
685                 return 0;
686         }
687         
688         /* if no property given yet, try to validate from F-Curve info */
689         if ((ptr.id.data == NULL) && (ptr.data==NULL)) {
690                 printf("ERROR: no RNA-pointer available to retrieve values for keyframing from\n");
691                 return 0;
692         }
693         if (prop == NULL) {
694                 PointerRNA tmp_ptr;
695                 
696                 /* try to get property we should be affecting */
697                 if ((RNA_path_resolve(&ptr, fcu->rna_path, &tmp_ptr, &prop) == 0) || (prop == NULL)) {
698                         /* property not found... */
699                         char *idname= (ptr.id.data) ? ((ID *)ptr.id.data)->name : "<No ID-Pointer>";
700                         
701                         printf("Insert Key: Could not insert keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", idname, fcu->rna_path);
702                         return 0;
703                 }
704                 else {
705                         /* property found, so overwrite 'ptr' to make later code easier */
706                         ptr= tmp_ptr;
707                 }
708         }
709         
710         /* set additional flags for the F-Curve (i.e. only integer values) */
711         fcu->flag &= ~(FCURVE_INT_VALUES|FCURVE_DISCRETE_VALUES);
712         switch (RNA_property_type(prop)) {
713                 case PROP_FLOAT:
714                         /* do nothing */
715                         break;
716                 case PROP_INT:
717                         /* do integer (only 'whole' numbers) interpolation between all points */
718                         fcu->flag |= FCURVE_INT_VALUES;
719                         break;
720                 default:
721                         /* do 'discrete' (i.e. enum, boolean values which cannot take any intermediate
722                          * values at all) interpolation between all points
723                          *      - however, we must also ensure that evaluated values are only integers still
724                          */
725                         fcu->flag |= (FCURVE_DISCRETE_VALUES|FCURVE_INT_VALUES);
726                         break;
727         }
728         
729         /* obtain value to give keyframe */
730         if ( (flag & INSERTKEY_MATRIX) && 
731                  (visualkey_can_use(&ptr, prop)) ) 
732         {
733                 /* visual-keying is only available for object and pchan datablocks, as 
734                  * it works by keyframing using a value extracted from the final matrix 
735                  * instead of using the kt system to extract a value.
736                  */
737                 curval= visualkey_get_value(&ptr, prop, fcu->array_index);
738         }
739         else {
740                 /* read value from system */
741                 curval= setting_get_rna_value(&ptr, prop, fcu->array_index);
742         }
743         
744         /* only insert keyframes where they are needed */
745         if (flag & INSERTKEY_NEEDED) {
746                 short insert_mode;
747                 
748                 /* check whether this curve really needs a new keyframe */
749                 insert_mode= new_key_needed(fcu, cfra, curval);
750                 
751                 /* insert new keyframe at current frame */
752                 if (insert_mode)
753                         insert_vert_fcurve(fcu, cfra, curval, flag);
754                 
755                 /* delete keyframe immediately before/after newly added */
756                 switch (insert_mode) {
757                         case KEYNEEDED_DELPREV:
758                                 delete_fcurve_key(fcu, fcu->totvert-2, 1);
759                                 break;
760                         case KEYNEEDED_DELNEXT:
761                                 delete_fcurve_key(fcu, 1, 1);
762                                 break;
763                 }
764                 
765                 /* only return success if keyframe added */
766                 if (insert_mode)
767                         return 1;
768         }
769         else {
770                 /* just insert keyframe */
771                 insert_vert_fcurve(fcu, cfra, curval, flag);
772                 
773                 /* return success */
774                 return 1;
775         }
776         
777         /* failed */
778         return 0;
779 }
780
781 /* Main Keyframing API call:
782  *      Use this when validation of necessary animation data is necessary, since it may not exist yet.
783  *      
784  *      The flag argument is used for special settings that alter the behaviour of
785  *      the keyframe insertion. These include the 'visual' keyframing modes, quick refresh,
786  *      and extra keyframe filtering.
787  */
788 short insert_keyframe (ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag)
789 {       
790         PointerRNA id_ptr, ptr;
791         PropertyRNA *prop;
792         FCurve *fcu;
793         
794         /* validate pointer first - exit if failure */
795         RNA_id_pointer_create(id, &id_ptr);
796         if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) {
797                 printf("Insert Key: Could not insert keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path);
798                 return 0;
799         }
800         
801         /* get F-Curve - if no action is provided, keyframe to the default one attached to this ID-block */
802         if (act == NULL) {
803                 AnimData *adt= BKE_animdata_from_id(id);
804                 
805                 /* get action to add F-Curve+keyframe to */
806                 act= verify_adt_action(id, 1);
807                 
808                 /* apply NLA-mapping to frame to use (if applicable) */
809                 cfra= BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
810         }
811         fcu= verify_fcurve(act, group, rna_path, array_index, 1);
812         
813         /* apply special time tweaking */
814                 // XXX check on this stuff...
815         if (GS(id->name) == ID_OB) {
816                 //Object *ob= (Object *)id;
817                 
818                 /* ancient time-offset cruft */
819                 //if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) {
820                 //      /* actually frametofloat calc again! */
821                 //      cfra-= give_timeoffset(ob)*scene->r.framelen;
822                 //}
823         }
824         
825         /* insert keyframe */
826         return insert_keyframe_direct(ptr, prop, fcu, cfra, flag);
827 }
828
829 /* ************************************************** */
830 /* KEYFRAME DELETION */
831
832 /* Main Keyframing API call:
833  *      Use this when validation of necessary animation data isn't necessary as it
834  *      already exists. It will delete a keyframe at the current frame.
835  *      
836  *      The flag argument is used for special settings that alter the behaviour of
837  *      the keyframe deletion. These include the quick refresh options.
838  */
839 short delete_keyframe (ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag)
840 {
841         FCurve *fcu = NULL;
842         
843         /* get F-Curve
844          * Note: here is one of the places where we don't want new Action + F-Curve added!
845          *              so 'add' var must be 0
846          */
847         if (act == NULL) {
848                 /* if no action is provided, use the default one attached to this ID-block */
849                 AnimData *adt= BKE_animdata_from_id(id);
850                 act= adt->action;
851                 
852                 /* apply NLA-mapping to frame to use (if applicable) */
853                 cfra= BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP); 
854         }
855         /* we don't check the validity of the path here yet, but it should be ok... */
856         fcu= verify_fcurve(act, group, rna_path, array_index, 0);
857         
858         /* check if F-Curve exists and/or whether it can be edited */
859         if ELEM(NULL, act, fcu) {
860                 printf("ERROR: no F-Curve and/or Action to delete keyframe from \n");
861                 return 0;
862         }
863         if ( (fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ) {
864                 if (G.f & G_DEBUG)
865                         printf("WARNING: not inserting keyframe for locked F-Curve \n");
866                 return 0;
867         }
868         
869         /* it should be fine to continue now... */
870         {
871                 short found = -1;
872                 int i;
873                 
874                 /* apply special time tweaking */
875                 if (GS(id->name) == ID_OB) {
876                         //Object *ob= (Object *)id;
877                         
878                         /* ancient time-offset cruft */
879                         //if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) {
880                         //      /* actually frametofloat calc again! */
881                         //      cfra-= give_timeoffset(ob)*scene->r.framelen;
882                         //}
883                 }
884                 
885                 /* try to find index of beztriple to get rid of */
886                 i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found);
887                 if (found) {                    
888                         /* delete the key at the index (will sanity check + do recalc afterwards) */
889                         delete_fcurve_key(fcu, i, 1);
890                         
891                         /* Only delete curve too if there are no points (we don't need to check for drivers, as they're kept separate) */
892                         if (fcu->totvert == 0) {
893                                 BLI_remlink(&act->curves, fcu);
894                                 free_fcurve(fcu);
895                         }
896                         
897                         /* return success */
898                         return 1;
899                 }
900         }
901         
902         /* return failure */
903         return 0;
904 }
905
906 /* ******************************************* */
907 /* KEYFRAME MODIFICATION */
908
909 /* mode for commonkey_modifykey */
910 enum {
911         COMMONKEY_MODE_INSERT = 0,
912         COMMONKEY_MODE_DELETE,
913 } eCommonModifyKey_Modes;
914
915 /* Polling callback for use with ANIM_*_keyframe() operators
916  * This is based on the standard ED_operator_areaactive callback,
917  * except that it does special checks for a few spacetypes too...
918  */
919 static int modify_key_op_poll(bContext *C)
920 {
921         ScrArea *sa= CTX_wm_area(C);
922         Scene *scene= CTX_data_scene(C);
923         SpaceOops *so= CTX_wm_space_outliner(C);
924         
925         /* if no area or active scene */
926         if (ELEM(NULL, sa, scene)) 
927                 return 0;
928         
929         /* if Outliner, only allow in DataBlocks view */
930         if (so && (so->outlinevis != SO_DATABLOCKS))
931                 return 0;
932         
933         /* TODO: checks for other space types can be added here */
934         
935         /* should be fine */
936         return 1;
937 }
938
939 /* Insert Key Operator ------------------------ */
940
941 static int insert_key_exec (bContext *C, wmOperator *op)
942 {
943         ListBase dsources = {NULL, NULL};
944         Scene *scene= CTX_data_scene(C);
945         KeyingSet *ks= NULL;
946         int type= RNA_int_get(op->ptr, "type");
947         float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
948         short success;
949         
950         /* type is the Keying Set the user specified to use when calling the operator:
951          *      - type == 0: use scene's active Keying Set
952          *      - type > 0: use a user-defined Keying Set from the active scene
953          *      - type < 0: use a builtin Keying Set
954          */
955         if (type == 0) 
956                 type= scene->active_keyingset;
957         if (type > 0)
958                 ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
959         else
960                 ks= BLI_findlink(&builtin_keyingsets, -type-1);
961                 
962         /* report failures */
963         if (ks == NULL) {
964                 BKE_report(op->reports, RPT_ERROR, "No active Keying Set");
965                 return OPERATOR_CANCELLED;
966         }
967         
968         /* get context info for relative Keying Sets */
969         if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) {
970                 /* exit if no suitable data obtained */
971                 if (modifykey_get_context_data(C, &dsources, ks) == 0) {
972                         BKE_report(op->reports, RPT_ERROR, "No suitable context info for active Keying Set");
973                         return OPERATOR_CANCELLED;
974                 }
975         }
976         
977         /* try to insert keyframes for the channels specified by KeyingSet */
978         success= modify_keyframes(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
979         printf("KeyingSet '%s' - Successfully added %d Keyframes \n", ks->name, success);
980         
981         /* report failure? */
982         if (success == 0)
983                 BKE_report(op->reports, RPT_WARNING, "Keying Set failed to insert any keyframes");
984         
985         /* free temp context-data if available */
986         if (dsources.first) {
987                 /* we assume that there is no extra data that needs to be freed from here... */
988                 BLI_freelistN(&dsources);
989         }
990         
991         /* send updates */
992         ED_anim_dag_flush_update(C);    
993         
994         /* for now, only send ND_KEYS for KeyingSets */
995         WM_event_add_notifier(C, ND_KEYS, NULL);
996         
997         return OPERATOR_FINISHED;
998 }
999
1000 void ANIM_OT_insert_keyframe (wmOperatorType *ot)
1001 {
1002         /* identifiers */
1003         ot->name= "Insert Keyframe";
1004         ot->idname= "ANIM_OT_insert_keyframe";
1005         
1006         /* callbacks */
1007         ot->exec= insert_key_exec; 
1008         ot->poll= modify_key_op_poll;
1009         
1010         /* flags */
1011         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1012         
1013         /* settings */
1014         RNA_def_int(ot->srna, "type", 0, INT_MIN, INT_MAX, "Keying Set Number", "Index (determined internally) of the Keying Set to use", 0, 1);
1015 }
1016
1017 /* Insert Key Operator (With Menu) ------------------------ */
1018
1019 /* XXX 
1020  * This operator pops up a menu which sets gets the index of the keyingset to use,
1021  * setting the global settings, and calling the insert-keyframe operator using these
1022  * settings
1023  */
1024
1025 static int insert_key_menu_invoke (bContext *C, wmOperator *op, wmEvent *event)
1026 {
1027         Scene *scene= CTX_data_scene(C);
1028         KeyingSet *ks;
1029         uiPopupMenu *pup;
1030         uiLayout *layout;
1031         int i = 0;
1032         
1033         pup= uiPupMenuBegin(C, "Insert Keyframe", 0);
1034         layout= uiPupMenuLayout(pup);
1035         
1036         /* active Keying Set 
1037          *      - only include entry if it exists
1038          */
1039         if (scene->active_keyingset) {
1040                 uiItemIntO(layout, "Active Keying Set", 0, "ANIM_OT_insert_keyframe_menu", "type", i++);
1041                 uiItemS(layout);
1042         }
1043         else
1044                 i++;
1045         
1046         /* user-defined Keying Sets 
1047          *      - these are listed in the order in which they were defined for the active scene
1048          */
1049         if (scene->keyingsets.first) {
1050                 for (ks= scene->keyingsets.first; ks; ks= ks->next)
1051                         uiItemIntO(layout, ks->name, 0, "ANIM_OT_insert_keyframe_menu", "type", i++);
1052                 uiItemS(layout);
1053         }
1054         
1055         /* builtin Keying Sets */
1056         // XXX polling the entire list may lag
1057         i= -1;
1058         for (ks= builtin_keyingsets.first; ks; ks= ks->next) {
1059                 /* only show KeyingSet if context is suitable */
1060                 if (keyingset_context_ok_poll(C, ks)) {
1061                         uiItemIntO(layout, ks->name, 0, "ANIM_OT_insert_keyframe_menu", "type", i--);
1062                 }
1063         }
1064         
1065         uiPupMenuEnd(C, pup);
1066         
1067         return OPERATOR_CANCELLED;
1068 }
1069  
1070 void ANIM_OT_insert_keyframe_menu (wmOperatorType *ot)
1071 {
1072         /* identifiers */
1073         ot->name= "Insert Keyframe Menu";
1074         ot->idname= "ANIM_OT_insert_keyframe_menu";
1075         
1076         /* callbacks */
1077         ot->invoke= insert_key_menu_invoke;
1078         ot->exec= insert_key_exec; 
1079         ot->poll= ED_operator_areaactive;
1080         
1081         /* flags */
1082         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1083         
1084         /* properties
1085          *      - NOTE: here the type is int not enum, since many of the indicies here are determined dynamically
1086          */
1087         RNA_def_int(ot->srna, "type", 0, INT_MIN, INT_MAX, "Keying Set Number", "Index (determined internally) of the Keying Set to use", 0, 1);
1088 }
1089
1090 /* Delete Key Operator ------------------------ */
1091
1092 static int delete_key_exec (bContext *C, wmOperator *op)
1093 {
1094         ListBase dsources = {NULL, NULL};
1095         Scene *scene= CTX_data_scene(C);
1096         KeyingSet *ks= NULL;    
1097         int type= RNA_int_get(op->ptr, "type");
1098         float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
1099         short success;
1100         
1101         /* type is the Keying Set the user specified to use when calling the operator:
1102          *      - type == 0: use scene's active Keying Set
1103          *      - type > 0: use a user-defined Keying Set from the active scene
1104          *      - type < 0: use a builtin Keying Set
1105          */
1106         if (type == 0) 
1107                 type= scene->active_keyingset;
1108         if (type > 0)
1109                 ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
1110         else
1111                 ks= BLI_findlink(&builtin_keyingsets, -type-1);
1112         
1113         /* report failure */
1114         if (ks == NULL) {
1115                 BKE_report(op->reports, RPT_ERROR, "No active Keying Set");
1116                 return OPERATOR_CANCELLED;
1117         }
1118         
1119         /* get context info for relative Keying Sets */
1120         if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) {
1121                 /* exit if no suitable data obtained */
1122                 if (modifykey_get_context_data(C, &dsources, ks) == 0) {
1123                         BKE_report(op->reports, RPT_ERROR, "No suitable context info for active Keying Set");
1124                         return OPERATOR_CANCELLED;
1125                 }
1126         }
1127         
1128         /* try to insert keyframes for the channels specified by KeyingSet */
1129         success= modify_keyframes(C, &dsources, NULL, ks, MODIFYKEY_MODE_DELETE, cfra);
1130         printf("KeyingSet '%s' - Successfully removed %d Keyframes \n", ks->name, success);
1131         
1132         /* report failure? */
1133         if (success == 0)
1134                 BKE_report(op->reports, RPT_WARNING, "Keying Set failed to remove any keyframes");
1135         
1136         /* free temp context-data if available */
1137         if (dsources.first) {
1138                 /* we assume that there is no extra data that needs to be freed from here... */
1139                 BLI_freelistN(&dsources);
1140         }
1141         
1142         /* send updates */
1143         ED_anim_dag_flush_update(C);    
1144         
1145         /* for now, only send ND_KEYS for KeyingSets */
1146         WM_event_add_notifier(C, ND_KEYS, NULL);
1147         
1148         return OPERATOR_FINISHED;
1149 }
1150
1151 void ANIM_OT_delete_keyframe (wmOperatorType *ot)
1152 {
1153         /* identifiers */
1154         ot->name= "Delete Keyframe";
1155         ot->idname= "ANIM_OT_delete_keyframe";
1156         
1157         /* callbacks */
1158         ot->exec= delete_key_exec; 
1159         ot->poll= modify_key_op_poll;
1160         
1161         /* flags */
1162         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1163         
1164         /* properties
1165          *      - NOTE: here the type is int not enum, since many of the indicies here are determined dynamically
1166          */
1167         RNA_def_int(ot->srna, "type", 0, INT_MIN, INT_MAX, "Keying Set Number", "Index (determined internally) of the Keying Set to use", 0, 1);
1168 }
1169
1170 /* Delete Key Operator ------------------------ */
1171
1172 /* XXX WARNING:
1173  * This is currently just a basic operator, which work in 3d-view context on objects only. 
1174  * Should this be kept? It does have advantages over a version which requires selecting a keyingset to use...
1175  * -- Joshua Leung, Jan 2009
1176  */
1177  
1178 static int delete_key_v3d_exec (bContext *C, wmOperator *op)
1179 {
1180         Scene *scene= CTX_data_scene(C);
1181         float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
1182         
1183         // XXX more comprehensive tests will be needed
1184         CTX_DATA_BEGIN(C, Base*, base, selected_bases) 
1185         {
1186                 Object *ob= base->object;
1187                 ID *id= (ID *)ob;
1188                 FCurve *fcu, *fcn;
1189                 short success= 0;
1190                 
1191                 /* loop through all curves in animdata and delete keys on this frame */
1192                 if (ob->adt) {
1193                         AnimData *adt= ob->adt;
1194                         bAction *act= adt->action;
1195                         
1196                         for (fcu= act->curves.first; fcu; fcu= fcn) {
1197                                 fcn= fcu->next;
1198                                 success+= delete_keyframe(id, NULL, NULL, fcu->rna_path, fcu->array_index, cfra, 0);
1199                         }
1200                 }
1201                 
1202                 printf("Ob '%s' - Successfully removed %d keyframes \n", id->name+2, success);
1203                 
1204                 ob->recalc |= OB_RECALC_OB;
1205         }
1206         CTX_DATA_END;
1207         
1208         /* send updates */
1209         ED_anim_dag_flush_update(C);    
1210         
1211         WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, NULL);
1212         
1213         return OPERATOR_FINISHED;
1214 }
1215
1216 void ANIM_OT_delete_keyframe_v3d (wmOperatorType *ot)
1217 {
1218         /* identifiers */
1219         ot->name= "Delete Keyframe";
1220         ot->idname= "ANIM_OT_delete_keyframe_v3d";
1221         
1222         /* callbacks */
1223         ot->invoke= WM_operator_confirm;
1224         ot->exec= delete_key_v3d_exec; 
1225         
1226         ot->poll= ED_operator_areaactive;
1227         
1228         /* flags */
1229         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1230 }
1231
1232
1233 /* Insert Key Button Operator ------------------------ */
1234
1235 static int insert_key_button_exec (bContext *C, wmOperator *op)
1236 {
1237         Scene *scene= CTX_data_scene(C);
1238         PointerRNA ptr;
1239         PropertyRNA *prop= NULL;
1240         char *path;
1241         float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
1242         short success= 0;
1243         int a, index, length, all= RNA_boolean_get(op->ptr, "all");
1244         short flag = 0;
1245         
1246         /* flags for inserting keyframes */
1247         if (IS_AUTOKEY_FLAG(AUTOMATKEY))
1248                 flag |= INSERTKEY_MATRIX;
1249         if (IS_AUTOKEY_FLAG(INSERTNEEDED))
1250                 flag |= INSERTKEY_NEEDED;
1251         if (IS_AUTOKEY_MODE(scene, EDITKEYS))
1252                 flag |= INSERTKEY_REPLACE;
1253         
1254         /* try to insert keyframe using property retrieved from UI */
1255         memset(&ptr, 0, sizeof(PointerRNA));
1256         uiAnimContextProperty(C, &ptr, &prop, &index);
1257         
1258         if ((ptr.data && prop) && RNA_property_animateable(&ptr, prop)) {
1259                 path= RNA_path_from_ID_to_property(&ptr, prop);
1260                 
1261                 if (path) {
1262                         if (all) {
1263                                 length= RNA_property_array_length(&ptr, prop);
1264                                 
1265                                 if(length) index= 0;
1266                                 else length= 1;
1267                         }
1268                         else
1269                                 length= 1;
1270                         
1271                         for (a=0; a<length; a++)
1272                                 success+= insert_keyframe(ptr.id.data, NULL, NULL, path, index+a, cfra, flag);
1273                         
1274                         MEM_freeN(path);
1275                 }
1276                 else if (ptr.type == &RNA_NlaStrip) {
1277                         /* handle special vars for NLA-strips */
1278                         NlaStrip *strip= (NlaStrip *)ptr.data;
1279                         FCurve *fcu= list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), flag);
1280                         
1281                         success+= insert_keyframe_direct(ptr, prop, fcu, cfra, 0);
1282                 }
1283                 else {
1284                         if (G.f & G_DEBUG)
1285                                 printf("Button Insert-Key: no path to property \n");
1286                         BKE_report(op->reports, RPT_WARNING, "Failed to resolve path to property. Try using a Keying Set instead.");
1287                 }
1288         }
1289         else if (G.f & G_DEBUG) {
1290                 printf("ptr.data = %p, prop = %p,", ptr.data, prop);
1291                 if(prop)
1292                         printf("animateable = %d \n", RNA_property_animateable(&ptr, prop));
1293                 else
1294                         printf("animateable = NULL \n");
1295         }
1296         
1297         if (success) {
1298                 /* send updates */
1299                 ED_anim_dag_flush_update(C);    
1300                 
1301                 /* for now, only send ND_KEYS for KeyingSets */
1302                 WM_event_add_notifier(C, ND_KEYS, NULL);
1303         }
1304         
1305         return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
1306 }
1307
1308 void ANIM_OT_insert_keyframe_button (wmOperatorType *ot)
1309 {
1310         /* identifiers */
1311         ot->name= "Insert Keyframe (Buttons)";
1312         ot->idname= "ANIM_OT_insert_keyframe_button";
1313         
1314         /* callbacks */
1315         ot->exec= insert_key_button_exec; 
1316         ot->poll= modify_key_op_poll;
1317         
1318         /* flags */
1319         ot->flag= OPTYPE_UNDO;
1320
1321         /* properties */
1322         RNA_def_boolean(ot->srna, "all", 1, "All", "Insert a keyframe for all element of the array.");
1323 }
1324
1325 /* Delete Key Button Operator ------------------------ */
1326
1327 static int delete_key_button_exec (bContext *C, wmOperator *op)
1328 {
1329         Scene *scene= CTX_data_scene(C);
1330         PointerRNA ptr;
1331         PropertyRNA *prop= NULL;
1332         char *path;
1333         float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
1334         short success= 0;
1335         int a, index, length, all= RNA_boolean_get(op->ptr, "all");
1336         
1337         /* try to insert keyframe using property retrieved from UI */
1338         memset(&ptr, 0, sizeof(PointerRNA));
1339         uiAnimContextProperty(C, &ptr, &prop, &index);
1340
1341         if (ptr.data && prop) {
1342                 path= RNA_path_from_ID_to_property(&ptr, prop);
1343                 
1344                 if (path) {
1345                         if (all) {
1346                                 length= RNA_property_array_length(&ptr, prop);
1347                                 
1348                                 if(length) index= 0;
1349                                 else length= 1;
1350                         }
1351                         else
1352                                 length= 1;
1353                         
1354                         for (a=0; a<length; a++)
1355                                 success+= delete_keyframe(ptr.id.data, NULL, NULL, path, index+a, cfra, 0);
1356                         
1357                         MEM_freeN(path);
1358                 }
1359                 else if (G.f & G_DEBUG)
1360                         printf("Button Delete-Key: no path to property \n");
1361         }
1362         else if (G.f & G_DEBUG) {
1363                 printf("ptr.data = %p, prop = %p \n", ptr.data, prop);
1364         }
1365         
1366         
1367         if(success) {
1368                 /* send updates */
1369                 ED_anim_dag_flush_update(C);    
1370                 
1371                 /* for now, only send ND_KEYS for KeyingSets */
1372                 WM_event_add_notifier(C, ND_KEYS, NULL);
1373         }
1374         
1375         return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
1376 }
1377
1378 void ANIM_OT_delete_keyframe_button (wmOperatorType *ot)
1379 {
1380         /* identifiers */
1381         ot->name= "Delete Keyframe (Buttons)";
1382         ot->idname= "ANIM_OT_delete_keyframe_button";
1383         
1384         /* callbacks */
1385         ot->exec= delete_key_button_exec; 
1386         ot->poll= modify_key_op_poll;
1387         
1388         /* flags */
1389         ot->flag= OPTYPE_UNDO;
1390
1391         /* properties */
1392         RNA_def_boolean(ot->srna, "all", 1, "All", "Delete keyfames from all elements of the array.");
1393 }
1394
1395 /* ******************************************* */
1396 /* AUTO KEYFRAME */
1397
1398 int autokeyframe_cfra_can_key(Scene *scene, ID *id)
1399 {
1400         float cfra= (float)CFRA; // XXX for now, this will do
1401         
1402         /* only filter if auto-key mode requires this */
1403         if (IS_AUTOKEY_ON(scene) == 0)
1404                 return 0;
1405                 
1406         if (IS_AUTOKEY_MODE(scene, NORMAL)) {
1407                 /* can insert anytime we like... */
1408                 return 1;
1409         }
1410         else /* REPLACE */ {
1411                 /* for whole block - only key if there's a keyframe on that frame already
1412                  *      this is a valid assumption when we're blocking + tweaking
1413                  */
1414                 return id_frame_has_keyframe(id, cfra, ANIMFILTER_KEYS_LOCAL);
1415         }
1416 }
1417
1418 /* ******************************************* */
1419 /* KEYFRAME DETECTION */
1420
1421 /* --------------- API/Per-Datablock Handling ------------------- */
1422
1423 /* Checks if some F-Curve has a keyframe for a given frame */
1424 short fcurve_frame_has_keyframe (FCurve *fcu, float frame, short filter)
1425 {
1426         /* quick sanity check */
1427         if (fcu == NULL)
1428                 return 0;
1429         
1430         /* we either include all regardless of muting, or only non-muted  */
1431         if ((filter & ANIMFILTER_KEYS_MUTED) || (fcu->flag & FCURVE_MUTED)==0) {
1432                 short replace = -1;
1433                 int i = binarysearch_bezt_index(fcu->bezt, frame, fcu->totvert, &replace);
1434                 
1435                 /* binarysearch_bezt_index will set replace to be 0 or 1
1436                  *      - obviously, 1 represents a match
1437                  */
1438                 if (replace) {                  
1439                         /* sanity check: 'i' may in rare cases exceed arraylen */
1440                         if ((i >= 0) && (i < fcu->totvert))
1441                                 return 1;
1442                 }
1443         }
1444         
1445         return 0;
1446 }
1447
1448 /* Checks whether an Action has a keyframe for a given frame 
1449  * Since we're only concerned whether a keyframe exists, we can simply loop until a match is found...
1450  */
1451 short action_frame_has_keyframe (bAction *act, float frame, short filter)
1452 {
1453         FCurve *fcu;
1454         
1455         /* can only find if there is data */
1456         if (act == NULL)
1457                 return 0;
1458                 
1459         /* if only check non-muted, check if muted */
1460         if ((filter & ANIMFILTER_KEYS_MUTED) || (act->flag & ACT_MUTED))
1461                 return 0;
1462         
1463         /* loop over F-Curves, using binary-search to try to find matches 
1464          *      - this assumes that keyframes are only beztriples
1465          */
1466         for (fcu= act->curves.first; fcu; fcu= fcu->next) {
1467                 /* only check if there are keyframes (currently only of type BezTriple) */
1468                 if (fcu->bezt && fcu->totvert) {
1469                         if (fcurve_frame_has_keyframe(fcu, frame, filter))
1470                                 return 1;
1471                 }
1472         }
1473         
1474         /* nothing found */
1475         return 0;
1476 }
1477
1478 /* Checks whether an Object has a keyframe for a given frame */
1479 short object_frame_has_keyframe (Object *ob, float frame, short filter)
1480 {
1481         /* error checking */
1482         if (ob == NULL)
1483                 return 0;
1484         
1485         /* check own animation data - specifically, the action it contains */
1486         if ((ob->adt) && (ob->adt->action)) {
1487                 if (action_frame_has_keyframe(ob->adt->action, frame, filter))
1488                         return 1;
1489         }
1490         
1491         /* try shapekey keyframes (if available, and allowed by filter) */
1492         if ( !(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOSKEY) ) {
1493                 Key *key= ob_get_key(ob);
1494                 
1495                 /* shapekeys can have keyframes ('Relative Shape Keys') 
1496                  * or depend on time (old 'Absolute Shape Keys') 
1497                  */
1498                  
1499                         /* 1. test for relative (with keyframes) */
1500                 if (id_frame_has_keyframe((ID *)key, frame, filter))
1501                         return 1;
1502                         
1503                         /* 2. test for time */
1504                 // TODO... yet to be implemented (this feature may evolve before then anyway)
1505         }
1506         
1507         /* try materials */
1508         if ( !(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOMAT) ) {
1509                 /* if only active, then we can skip a lot of looping */
1510                 if (filter & ANIMFILTER_KEYS_ACTIVE) {
1511                         Material *ma= give_current_material(ob, (ob->actcol + 1));
1512                         
1513                         /* we only retrieve the active material... */
1514                         if (id_frame_has_keyframe((ID *)ma, frame, filter))
1515                                 return 1;
1516                 }
1517                 else {
1518                         int a;
1519                         
1520                         /* loop over materials */
1521                         for (a=0; a<ob->totcol; a++) {
1522                                 Material *ma= give_current_material(ob, a+1);
1523                                 
1524                                 if (id_frame_has_keyframe((ID *)ma, frame, filter))
1525                                         return 1;
1526                         }
1527                 }
1528         }
1529         
1530         /* nothing found */
1531         return 0;
1532 }
1533
1534 /* --------------- API ------------------- */
1535
1536 /* Checks whether a keyframe exists for the given ID-block one the given frame */
1537 short id_frame_has_keyframe (ID *id, float frame, short filter)
1538 {
1539         /* sanity checks */
1540         if (id == NULL)
1541                 return 0;
1542         
1543         /* perform special checks for 'macro' types */
1544         switch (GS(id->name)) {
1545                 case ID_OB: /* object */
1546                         return object_frame_has_keyframe((Object *)id, frame, filter);
1547                         break;
1548                         
1549                 case ID_SCE: /* scene */
1550                 // XXX TODO... for now, just use 'normal' behaviour
1551                 //      break;
1552                 
1553                 default:        /* 'normal type' */
1554                 {
1555                         AnimData *adt= BKE_animdata_from_id(id);
1556                         
1557                         /* only check keyframes in active action */
1558                         if (adt)
1559                                 return action_frame_has_keyframe(adt->action, frame, filter);
1560                 }
1561                         break;
1562         }
1563         
1564         
1565         /* no keyframe found */
1566         return 0;
1567 }
1568
1569 /* ************************************************** */