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