d28bae9b12eaab18ff9cea9c2a4c2b540f5e2080
[blender.git] / source / blender / editors / animation / keyframing.c
1 /* Testing code for 2.5 animation system 
2  * Copyright 2009, Joshua Leung
3  */
4  
5 #include <stdio.h>
6 #include <stddef.h>
7 #include <string.h>
8 #include <math.h>
9 #include <float.h>
10
11 #include "MEM_guardedalloc.h"
12
13 #include "BLI_blenlib.h"
14 #include "BLI_arithb.h"
15 #include "BLI_dynstr.h"
16
17 #include "DNA_anim_types.h"
18 #include "DNA_action_types.h"
19 #include "DNA_armature_types.h"
20 #include "DNA_constraint_types.h"
21 #include "DNA_key_types.h"
22 #include "DNA_object_types.h"
23 #include "DNA_material_types.h"
24 #include "DNA_scene_types.h"
25 #include "DNA_userdef_types.h"
26 #include "DNA_windowmanager_types.h"
27
28 #include "BKE_animsys.h"
29 #include "BKE_action.h"
30 #include "BKE_constraint.h"
31 #include "BKE_fcurve.h"
32 #include "BKE_utildefines.h"
33 #include "BKE_context.h"
34 #include "BKE_report.h"
35 #include "BKE_key.h"
36 #include "BKE_material.h"
37
38 #include "ED_anim_api.h"
39 #include "ED_keyframing.h"
40 #include "ED_keyframes_edit.h"
41 #include "ED_screen.h"
42 #include "ED_util.h"
43
44 #include "UI_interface.h"
45
46 #include "WM_api.h"
47 #include "WM_types.h"
48
49 #include "RNA_access.h"
50 #include "RNA_define.h"
51 #include "RNA_types.h"
52
53 /* ************************************************** */
54 /* LOCAL TYPES AND DEFINES */
55
56 /* ----------- Common KeyData Sources ------------ */
57
58 /* temporary struct to gather data combos to keyframe */
59 typedef struct bCommonKeySrc {
60         struct bCommonKeySrc *next, *prev;
61                 
62                 /* general data/destination-source settings */
63         ID *id;                                 /* id-block this comes from */
64         char *rna_path;                 /* base path to use */  // xxx.... maybe we don't need this?
65         
66                 /* specific cases */
67         bPoseChannel *pchan;    /* only needed when doing recalcs... */
68 } bCommonKeySrc;
69
70 /* ******************************************* */
71 /* Animation Data Validation */
72
73 /* Get (or add relevant data to be able to do so) F-Curve from the Active Action, 
74  * for the given Animation Data block. This assumes that all the destinations are valid.
75  */
76 FCurve *verify_fcurve (ID *id, const char group[], const char rna_path[], const int array_index, short add)
77 {
78         AnimData *adt;
79         bAction *act;
80         bActionGroup *grp;
81         FCurve *fcu;
82         
83         /* sanity checks */
84         if ELEM(NULL, id, rna_path)
85                 return NULL;
86         
87         /* init animdata if none available yet */
88         adt= BKE_animdata_from_id(id);
89         if ((adt == NULL) && (add))
90                 adt= BKE_id_add_animdata(id);
91         if (adt == NULL) { 
92                 /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */
93                 return NULL;
94         }
95                 
96         /* init action if none available yet */
97         // TODO: need some wizardry to handle NLA stuff correct
98         if ((adt->action == NULL) && (add))
99                 adt->action= add_empty_action("Action");
100         act= adt->action;
101                 
102         /* try to find f-curve matching for this setting 
103          *      - add if not found and allowed to add one
104          *              TODO: add auto-grouping support? how this works will need to be resolved
105          */
106         if (act)
107                 fcu= list_find_fcurve(&act->curves, rna_path, array_index);
108         else
109                 fcu= NULL;
110         
111         if ((fcu == NULL) && (add)) {
112                 /* use default settings to make a F-Curve */
113                 fcu= MEM_callocN(sizeof(FCurve), "FCurve");
114                 
115                 fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
116                 if (act->curves.first==NULL) 
117                         fcu->flag |= FCURVE_ACTIVE;     /* first one added active */
118                         
119                 /* store path - make copy, and store that */
120                 fcu->rna_path= BLI_strdupn(rna_path, strlen(rna_path));
121                 fcu->array_index= array_index;
122                 
123                 /* if a group name has been provided, try to add or find a group, then add F-Curve to it */
124                 if (group) {
125                         /* try to find group */
126                         grp= action_groups_find_named(act, group);
127                         
128                         /* no matching groups, so add one */
129                         if (grp == NULL) {
130                                 /* Add a new group, and make it active */
131                                 grp= MEM_callocN(sizeof(bActionGroup), "bActionGroup");
132                                 
133                                 grp->flag |= (AGRP_ACTIVE|AGRP_SELECTED|AGRP_EXPANDED);
134                                 BLI_snprintf(grp->name, 64, group);
135                                 
136                                 BLI_addtail(&act->groups, grp);
137                                 BLI_uniquename(&act->groups, grp, "Group", offsetof(bActionGroup, name), 64);
138                                 
139                                 set_active_action_group(act, grp, 1);
140                         }
141                         
142                         /* add F-Curve to group */
143                         action_groups_add_channel(act, grp, fcu);
144                 }
145                 else {
146                         /* just add F-Curve to end of Action's list */
147                         BLI_addtail(&act->curves, fcu);
148                 }
149         }
150         
151         /* return the F-Curve */
152         return fcu;
153 }
154
155 /* ************************************************** */
156 /* KEYFRAME INSERTION */
157
158 /* -------------- BezTriple Insertion -------------------- */
159
160 /* threshold for inserting keyframes - threshold here should be good enough for now, but should become userpref */
161 #define BEZT_INSERT_THRESH      0.00001f
162
163 /* Binary search algorithm for finding where to insert BezTriple. (for use by insert_bezt_icu)
164  * Returns the index to insert at (data already at that index will be offset if replace is 0)
165  */
166 static int binarysearch_bezt_index (BezTriple array[], float frame, int arraylen, short *replace)
167 {
168         int start=0, end=arraylen;
169         int loopbreaker= 0, maxloop= arraylen * 2;
170         
171         /* initialise replace-flag first */
172         *replace= 0;
173         
174         /* sneaky optimisations (don't go through searching process if...):
175          *      - keyframe to be added is to be added out of current bounds
176          *      - keyframe to be added would replace one of the existing ones on bounds
177          */
178         if ((arraylen <= 0) || (array == NULL)) {
179                 printf("Warning: binarysearch_bezt_index() encountered invalid array \n");
180                 return 0;
181         }
182         else {
183                 /* check whether to add before/after/on */
184                 float framenum;
185                 
186                 /* 'First' Keyframe (when only one keyframe, this case is used) */
187                 framenum= array[0].vec[1][0];
188                 if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) {
189                         *replace = 1;
190                         return 0;
191                 }
192                 else if (frame < framenum)
193                         return 0;
194                         
195                 /* 'Last' Keyframe */
196                 framenum= array[(arraylen-1)].vec[1][0];
197                 if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) {
198                         *replace= 1;
199                         return (arraylen - 1);
200                 }
201                 else if (frame > framenum)
202                         return arraylen;
203         }
204         
205         
206         /* most of the time, this loop is just to find where to put it
207          * 'loopbreaker' is just here to prevent infinite loops 
208          */
209         for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) {
210                 /* compute and get midpoint */
211                 int mid = (start + end) / 2;
212                 float midfra= array[mid].vec[1][0];
213                 
214                 /* check if exactly equal to midpoint */
215                 if (IS_EQT(frame, midfra, BEZT_INSERT_THRESH)) {
216                         *replace = 1;
217                         return mid;
218                 }
219                 
220                 /* repeat in upper/lower half */
221                 if (frame > midfra)
222                         start= mid + 1;
223                 else if (frame < midfra)
224                         end= mid - 1;
225         }
226         
227         /* print error if loop-limit exceeded */
228         if (loopbreaker == (maxloop-1)) {
229                 printf("Error: binarysearch_bezt_index() was taking too long \n");
230                 
231                 // include debug info 
232                 printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen);
233         }
234         
235         /* not found, so return where to place it */
236         return start;
237 }
238
239 /* This function adds a given BezTriple to an F-Curve. It will allocate 
240  * memory for the array if needed, and will insert the BezTriple into a
241  * suitable place in chronological order.
242  * 
243  * NOTE: any recalculate of the F-Curve that needs to be done will need to 
244  *              be done by the caller.
245  */
246 int insert_bezt_fcurve (FCurve *fcu, BezTriple *bezt)
247 {
248         BezTriple *newb;
249         int i= 0;
250         
251         if (fcu->bezt) {
252                 short replace = -1;
253                 i = binarysearch_bezt_index(fcu->bezt, bezt->vec[1][0], fcu->totvert, &replace);
254                 
255                 if (replace) {                  
256                         /* sanity check: 'i' may in rare cases exceed arraylen */
257                         // FIXME: do not overwrite handletype if just replacing...?
258                         if ((i >= 0) && (i < fcu->totvert))
259                                 *(fcu->bezt + i) = *bezt;
260                 }
261                 else {
262                         /* add new */
263                         newb= MEM_callocN((fcu->totvert+1)*sizeof(BezTriple), "beztriple");
264                         
265                         /* add the beztriples that should occur before the beztriple to be pasted (originally in ei->icu) */
266                         if (i > 0)
267                                 memcpy(newb, fcu->bezt, i*sizeof(BezTriple));
268                         
269                         /* add beztriple to paste at index i */
270                         *(newb + i)= *bezt;
271                         
272                         /* add the beztriples that occur after the beztriple to be pasted (originally in icu) */
273                         if (i < fcu->totvert) 
274                                 memcpy(newb+i+1, fcu->bezt+i, (fcu->totvert-i)*sizeof(BezTriple));
275                         
276                         /* replace (+ free) old with new */
277                         MEM_freeN(fcu->bezt);
278                         fcu->bezt= newb;
279                         
280                         fcu->totvert++;
281                 }
282         }
283         else {
284                 // TODO: need to check for old sample-data now...
285                 fcu->bezt= MEM_callocN(sizeof(BezTriple), "beztriple");
286                 *(fcu->bezt)= *bezt;
287                 fcu->totvert= 1;
288         }
289         
290         
291         /* we need to return the index, so that some tools which do post-processing can 
292          * detect where we added the BezTriple in the array
293          */
294         return i;
295 }
296
297 /* This function is a wrapper for insert_bezt_icu, and should be used when
298  * adding a new keyframe to a curve, when the keyframe doesn't exist anywhere
299  * else yet. 
300  * 
301  * 'fast' - is only for the python API where importing BVH's would take an extreamly long time.
302  */
303 void insert_vert_fcurve (FCurve *fcu, float x, float y, short fast)
304 {
305         BezTriple beztr;
306         int a;
307         
308         /* set all three points, for nicer start position */
309         memset(&beztr, 0, sizeof(BezTriple));
310         beztr.vec[0][0]= x; 
311         beztr.vec[0][1]= y;
312         beztr.vec[1][0]= x;
313         beztr.vec[1][1]= y;
314         beztr.vec[2][0]= x;
315         beztr.vec[2][1]= y;
316         beztr.ipo= U.ipo_new; /* use default interpolation mode here... */
317         beztr.f1= beztr.f2= beztr.f3= SELECT;
318         beztr.h1= beztr.h2= HD_AUTO; // XXX what about when we replace an old one?
319         
320         /* add temp beztriple to keyframes */
321         a= insert_bezt_fcurve(fcu, &beztr);
322         
323         /* what if 'a' is a negative index? 
324          * for now, just exit to prevent any segfaults
325          */
326         if (a < 0) return;
327         
328         /* don't recalculate handles if fast is set
329          *      - this is a hack to make importers faster
330          *      - we may calculate twice (see editipo_changed(), due to autohandle needing two calculations)
331          */
332         if (!fast) calchandles_fcurve(fcu);
333         
334         /* set handletype and interpolation */
335         if (fcu->totvert > 2) {
336                 BezTriple *bezt= (fcu->bezt + a);
337                 char h1, h2;
338                 
339                 /* set handles (autohandles by default) */
340                 h1= h2= HD_AUTO;
341                 
342                 if (a > 0) h1= (bezt-1)->h2;
343                 if (a < fcu->totvert-1) h2= (bezt+1)->h1;
344                 
345                 bezt->h1= h1;
346                 bezt->h2= h2;
347                 
348                 /* set interpolation from previous (if available) */
349                 if (a > 0) bezt->ipo= (bezt-1)->ipo;
350                 else if (a < fcu->totvert-1) bezt->ipo= (bezt+1)->ipo;
351                         
352                 /* don't recalculate handles if fast is set
353                  *      - this is a hack to make importers faster
354                  *      - we may calculate twice (see editipo_changed(), due to autohandle needing two calculations)
355                  */
356                 if (!fast) calchandles_fcurve(fcu);
357         }
358 }
359
360 /* -------------- 'Smarter' Keyframing Functions -------------------- */
361 /* return codes for new_key_needed */
362 enum {
363         KEYNEEDED_DONTADD = 0,
364         KEYNEEDED_JUSTADD,
365         KEYNEEDED_DELPREV,
366         KEYNEEDED_DELNEXT
367 } eKeyNeededStatus;
368
369 /* This helper function determines whether a new keyframe is needed */
370 /* Cases where keyframes should not be added:
371  *      1. Keyframe to be added bewteen two keyframes with similar values
372  *      2. Keyframe to be added on frame where two keyframes are already situated
373  *      3. Keyframe lies at point that intersects the linear line between two keyframes
374  */
375 static short new_key_needed (FCurve *fcu, float cFrame, float nValue) 
376 {
377         BezTriple *bezt=NULL, *prev=NULL;
378         int totCount, i;
379         float valA = 0.0f, valB = 0.0f;
380         
381         /* safety checking */
382         if (fcu == NULL) return KEYNEEDED_JUSTADD;
383         totCount= fcu->totvert;
384         if (totCount == 0) return KEYNEEDED_JUSTADD;
385         
386         /* loop through checking if any are the same */
387         bezt= fcu->bezt;
388         for (i=0; i<totCount; i++) {
389                 float prevPosi=0.0f, prevVal=0.0f;
390                 float beztPosi=0.0f, beztVal=0.0f;
391                         
392                 /* get current time+value */    
393                 beztPosi= bezt->vec[1][0];
394                 beztVal= bezt->vec[1][1];
395                         
396                 if (prev) {
397                         /* there is a keyframe before the one currently being examined */               
398                         
399                         /* get previous time+value */
400                         prevPosi= prev->vec[1][0];
401                         prevVal= prev->vec[1][1];
402                         
403                         /* keyframe to be added at point where there are already two similar points? */
404                         if (IS_EQ(prevPosi, cFrame) && IS_EQ(beztPosi, cFrame) && IS_EQ(beztPosi, prevPosi)) {
405                                 return KEYNEEDED_DONTADD;
406                         }
407                         
408                         /* keyframe between prev+current points ? */
409                         if ((prevPosi <= cFrame) && (cFrame <= beztPosi)) {
410                                 /* is the value of keyframe to be added the same as keyframes on either side ? */
411                                 if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) {
412                                         return KEYNEEDED_DONTADD;
413                                 }
414                                 else {
415                                         float realVal;
416                                         
417                                         /* get real value of curve at that point */
418                                         realVal= evaluate_fcurve(fcu, cFrame);
419                                         
420                                         /* compare whether it's the same as proposed */
421                                         if (IS_EQ(realVal, nValue)) 
422                                                 return KEYNEEDED_DONTADD;
423                                         else 
424                                                 return KEYNEEDED_JUSTADD;
425                                 }
426                         }
427                         
428                         /* new keyframe before prev beztriple? */
429                         if (cFrame < prevPosi) {
430                                 /* A new keyframe will be added. However, whether the previous beztriple
431                                  * stays around or not depends on whether the values of previous/current
432                                  * beztriples and new keyframe are the same.
433                                  */
434                                 if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal))
435                                         return KEYNEEDED_DELNEXT;
436                                 else 
437                                         return KEYNEEDED_JUSTADD;
438                         }
439                 }
440                 else {
441                         /* just add a keyframe if there's only one keyframe 
442                          * and the new one occurs before the exisiting one does.
443                          */
444                         if ((cFrame < beztPosi) && (totCount==1))
445                                 return KEYNEEDED_JUSTADD;
446                 }
447                 
448                 /* continue. frame to do not yet passed (or other conditions not met) */
449                 if (i < (totCount-1)) {
450                         prev= bezt;
451                         bezt++;
452                 }
453                 else
454                         break;
455         }
456         
457         /* Frame in which to add a new-keyframe occurs after all other keys
458          * -> If there are at least two existing keyframes, then if the values of the
459          *       last two keyframes and the new-keyframe match, the last existing keyframe
460          *       gets deleted as it is no longer required.
461          * -> Otherwise, a keyframe is just added. 1.0 is added so that fake-2nd-to-last
462          *       keyframe is not equal to last keyframe.
463          */
464         bezt= (fcu->bezt + (fcu->totvert - 1));
465         valA= bezt->vec[1][1];
466         
467         if (prev)
468                 valB= prev->vec[1][1];
469         else 
470                 valB= bezt->vec[1][1] + 1.0f; 
471                 
472         if (IS_EQ(valA, nValue) && IS_EQ(valA, valB)) 
473                 return KEYNEEDED_DELPREV;
474         else 
475                 return KEYNEEDED_JUSTADD;
476 }
477
478 /* ------------------ RNA Data-Access Functions ------------------ */
479
480 /* Try to read value using RNA-properties obtained already */
481 static float setting_get_rna_value (PointerRNA *ptr, PropertyRNA *prop, int index)
482 {
483         float value= 0.0f;
484         
485         switch (RNA_property_type(ptr, prop)) {
486                 case PROP_BOOLEAN:
487                         if (RNA_property_array_length(ptr, prop))
488                                 value= (float)RNA_property_boolean_get_index(ptr, prop, index);
489                         else
490                                 value= (float)RNA_property_boolean_get(ptr, prop);
491                         break;
492                 case PROP_INT:
493                         if (RNA_property_array_length(ptr, prop))
494                                 value= (float)RNA_property_int_get_index(ptr, prop, index);
495                         else
496                                 value= (float)RNA_property_int_get(ptr, prop);
497                         break;
498                 case PROP_FLOAT:
499                         if (RNA_property_array_length(ptr, prop))
500                                 value= RNA_property_float_get_index(ptr, prop, index);
501                         else
502                                 value= RNA_property_float_get(ptr, prop);
503                         break;
504                 case PROP_ENUM:
505                         value= (float)RNA_property_enum_get(ptr, prop);
506                         break;
507                 default:
508                         break;
509         }
510         
511         return value;
512 }
513
514 /* ------------------ 'Visual' Keyframing Functions ------------------ */
515
516 /* internal status codes for visualkey_can_use */
517 enum {
518         VISUALKEY_NONE = 0,
519         VISUALKEY_LOC,
520         VISUALKEY_ROT,
521 };
522
523 /* This helper function determines if visual-keyframing should be used when  
524  * inserting keyframes for the given channel. As visual-keyframing only works
525  * on Object and Pose-Channel blocks, this should only get called for those 
526  * blocktypes, when using "standard" keying but 'Visual Keying' option in Auto-Keying 
527  * settings is on.
528  */
529 static short visualkey_can_use (PointerRNA *ptr, PropertyRNA *prop)
530 {
531         bConstraint *con= NULL;
532         short searchtype= VISUALKEY_NONE;
533         char *identifier= NULL;
534         
535         /* validate data */
536         // TODO: this check is probably not needed, but it won't hurt
537         if (ELEM3(NULL, ptr, ptr->data, prop))
538                 return 0;
539                 
540         /* get first constraint and determine type of keyframe constraints to check for 
541          *      - constraints can be on either Objects or PoseChannels, so we only check if the
542          *        ptr->type is RNA_Object or RNA_PoseChannel, which are the RNA wrapping-info for
543          *        those structs, allowing us to identify the owner of the data 
544          */
545         if (ptr->type == &RNA_Object) {
546                 /* Object */
547                 Object *ob= (Object *)ptr->data;
548                 
549                 con= ob->constraints.first;
550                 identifier= (char *)RNA_property_identifier(ptr, prop);
551         }
552         else if (ptr->type == &RNA_PoseChannel) {
553                 /* Pose Channel */
554                 bPoseChannel *pchan= (bPoseChannel *)ptr->data;
555                 
556                 con= pchan->constraints.first;
557                 identifier= (char *)RNA_property_identifier(ptr, prop);
558         }
559         
560         /* check if any data to search using */
561         if (ELEM(NULL, con, identifier))
562                 return 0;
563                 
564         /* location or rotation identifiers only... */
565         if (strstr(identifier, "location"))
566                 searchtype= VISUALKEY_LOC;
567         else if (strstr(identifier, "rotation"))
568                 searchtype= VISUALKEY_ROT;
569         else {
570                 printf("visualkey_can_use() failed: identifier - '%s' \n", identifier);
571                 return 0;
572         }
573         
574         
575         /* only search if a searchtype and initial constraint are available */
576         if (searchtype && con) {
577                 for (; con; con= con->next) {
578                         /* only consider constraint if it is not disabled, and has influence */
579                         if (con->flag & CONSTRAINT_DISABLE) continue;
580                         if (con->enforce == 0.0f) continue;
581                         
582                         /* some constraints may alter these transforms */
583                         switch (con->type) {
584                                 /* multi-transform constraints */
585                                 case CONSTRAINT_TYPE_CHILDOF:
586                                         return 1;
587                                 case CONSTRAINT_TYPE_TRANSFORM:
588                                         return 1;
589                                 case CONSTRAINT_TYPE_FOLLOWPATH:
590                                         return 1;
591                                 case CONSTRAINT_TYPE_KINEMATIC:
592                                         return 1;
593                                         
594                                 /* single-transform constraits  */
595                                 case CONSTRAINT_TYPE_TRACKTO:
596                                         if (searchtype==VISUALKEY_ROT) return 1;
597                                         break;
598                                 case CONSTRAINT_TYPE_ROTLIMIT:
599                                         if (searchtype==VISUALKEY_ROT) return 1;
600                                         break;
601                                 case CONSTRAINT_TYPE_LOCLIMIT:
602                                         if (searchtype==VISUALKEY_LOC) return 1;
603                                         break;
604                                 case CONSTRAINT_TYPE_ROTLIKE:
605                                         if (searchtype==VISUALKEY_ROT) return 1;
606                                         break;
607                                 case CONSTRAINT_TYPE_DISTLIMIT:
608                                         if (searchtype==VISUALKEY_LOC) return 1;
609                                         break;
610                                 case CONSTRAINT_TYPE_LOCLIKE:
611                                         if (searchtype==VISUALKEY_LOC) return 1;
612                                         break;
613                                 case CONSTRAINT_TYPE_LOCKTRACK:
614                                         if (searchtype==VISUALKEY_ROT) return 1;
615                                         break;
616                                 case CONSTRAINT_TYPE_MINMAX:
617                                         if (searchtype==VISUALKEY_LOC) return 1;
618                                         break;
619                                 
620                                 default:
621                                         break;
622                         }
623                 }
624         }
625         
626         /* when some condition is met, this function returns, so here it can be 0 */
627         return 0;
628 }
629
630 /* This helper function extracts the value to use for visual-keyframing 
631  * In the event that it is not possible to perform visual keying, try to fall-back
632  * to using the default method. Assumes that all data it has been passed is valid.
633  */
634 static float visualkey_get_value (PointerRNA *ptr, PropertyRNA *prop, int array_index)
635 {
636         char *identifier= (char *)RNA_property_identifier(ptr, prop);
637         
638         /* handle for Objects or PoseChannels only 
639          *      - constraints can be on either Objects or PoseChannels, so we only check if the
640          *        ptr->type is RNA_Object or RNA_PoseChannel, which are the RNA wrapping-info for
641          *        those structs, allowing us to identify the owner of the data 
642          *      - assume that array_index will be sane
643          */
644         if (ptr->type == &RNA_Object) {
645                 Object *ob= (Object *)ptr->data;
646                 
647                 /* parented objects are not supported, as the effects of the parent
648                  * are included in the matrix, which kindof beats the point
649                  */
650                 if (ob->parent == NULL) {
651                         /* only Location or Rotation keyframes are supported now */
652                         if (strstr(identifier, "location")) {
653                                 return ob->obmat[3][array_index];
654                         }
655                         else if (strstr(identifier, "rotation")) {
656                                 float eul[3];
657                                 
658                                 Mat4ToEul(ob->obmat, eul);
659                                 return eul[array_index]*(5.72958f);
660                         }
661                 }
662         }
663         else if (ptr->type == &RNA_PoseChannel) {
664                 Object *ob= (Object *)ptr->id.data; /* we assume that this is always set, and is an object */
665                 bPoseChannel *pchan= (bPoseChannel *)ptr->data;
666                 float tmat[4][4];
667                 
668                 /* Although it is not strictly required for this particular space conversion, 
669                  * arg1 must not be null, as there is a null check for the other conversions to
670                  * be safe. Therefore, the active object is passed here, and in many cases, this
671                  * will be what owns the pose-channel that is getting this anyway.
672                  */
673                 Mat4CpyMat4(tmat, pchan->pose_mat);
674                 constraint_mat_convertspace(ob, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
675                 
676                 /* Loc, Rot/Quat keyframes are supported... */
677                 if (strstr(identifier, "location")) {
678                         /* only use for non-connected bones */
679                         if ((pchan->bone->parent) && !(pchan->bone->flag & BONE_CONNECTED))
680                                 return tmat[3][array_index];
681                         else if (pchan->bone->parent == NULL)
682                                 return tmat[3][array_index];
683                 }
684                 else if (strstr(identifier, "euler_rotation")) {
685                         float eul[3];
686                         
687                         /* euler-rotation test before standard rotation, as standard rotation does quats */
688                         Mat4ToEul(tmat, eul);
689                         return eul[array_index];
690                 }
691                 else if (strstr(identifier, "rotation")) {
692                         float trimat[3][3], quat[4];
693                         
694                         Mat3CpyMat4(trimat, tmat);
695                         Mat3ToQuat_is_ok(trimat, quat);
696                         
697                         return quat[array_index];
698                 }
699         }
700         
701         /* as the function hasn't returned yet, read value from system in the default way */
702         return setting_get_rna_value(ptr, prop, array_index);
703 }
704
705 /* ------------------------- Insert Key API ------------------------- */
706
707 /* Main Keyframing API call:
708  *      Use this when validation of necessary animation data isn't necessary as it
709  *      already exists. It will insert a keyframe using the current value being keyframed.
710  *      
711  *      The flag argument is used for special settings that alter the behaviour of
712  *      the keyframe insertion. These include the 'visual' keyframing modes, quick refresh,
713  *      and extra keyframe filtering.
714  */
715 short insertkey (ID *id, const char group[], const char rna_path[], int array_index, float cfra, short flag)
716 {       
717         PointerRNA id_ptr, ptr;
718         PropertyRNA *prop;
719         FCurve *fcu;
720         
721         /* validate pointer first - exit if failure*/
722         RNA_id_pointer_create(id, &id_ptr);
723         if (RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0 || prop == NULL) {
724                 printf("Insert Key: Could not insert keyframe, as RNA Path is invalid for the given ID (%s)\n", rna_path);
725                 return 0;
726         }
727         
728         /* get F-Curve */
729         fcu= verify_fcurve(id, group, rna_path, array_index, 1);
730         
731         /* only continue if we have an F-Curve to add keyframe to */
732         if (fcu) {
733                 float curval= 0.0f;
734                 
735                 /* set additional flags for the F-Curve (i.e. only integer values) */
736                 if (RNA_property_type(&ptr, prop) != PROP_FLOAT)
737                         fcu->flag |= FCURVE_INT_VALUES;
738                 
739                 /* apply special time tweaking */
740                         // XXX check on this stuff...
741                 if (GS(id->name) == ID_OB) {
742                         //Object *ob= (Object *)id;
743                         
744                         /* apply NLA-scaling (if applicable) */
745                         //cfra= get_action_frame(ob, cfra);
746                         
747                         /* ancient time-offset cruft */
748                         //if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) {
749                         //      /* actually frametofloat calc again! */
750                         //      cfra-= give_timeoffset(ob)*scene->r.framelen;
751                         //}
752                 }
753                 
754                 /* obtain value to give keyframe */
755                 if ( (flag & INSERTKEY_MATRIX) && 
756                          (visualkey_can_use(&ptr, prop)) ) 
757                 {
758                         /* visual-keying is only available for object and pchan datablocks, as 
759                          * it works by keyframing using a value extracted from the final matrix 
760                          * instead of using the kt system to extract a value.
761                          */
762                         curval= visualkey_get_value(&ptr, prop, array_index);
763                 }
764                 else {
765                         /* read value from system */
766                         curval= setting_get_rna_value(&ptr, prop, array_index);
767                 }
768                 
769                 /* only insert keyframes where they are needed */
770                 if (flag & INSERTKEY_NEEDED) {
771                         short insert_mode;
772                         
773                         /* check whether this curve really needs a new keyframe */
774                         insert_mode= new_key_needed(fcu, cfra, curval);
775                         
776                         /* insert new keyframe at current frame */
777                         if (insert_mode)
778                                 insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST));
779                         
780                         /* delete keyframe immediately before/after newly added */
781                         switch (insert_mode) {
782                                 case KEYNEEDED_DELPREV:
783                                         delete_fcurve_key(fcu, fcu->totvert-2, 1);
784                                         break;
785                                 case KEYNEEDED_DELNEXT:
786                                         delete_fcurve_key(fcu, 1, 1);
787                                         break;
788                         }
789                         
790                         /* only return success if keyframe added */
791                         if (insert_mode)
792                                 return 1;
793                 }
794                 else {
795                         /* just insert keyframe */
796                         insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST));
797                         
798                         /* return success */
799                         return 1;
800                 }
801         }
802         
803         /* return failure */
804         return 0;
805 }
806
807 /* ************************************************** */
808 /* KEYFRAME DELETION */
809
810 /* Main Keyframing API call:
811  *      Use this when validation of necessary animation data isn't necessary as it
812  *      already exists. It will delete a keyframe at the current frame.
813  *      
814  *      The flag argument is used for special settings that alter the behaviour of
815  *      the keyframe deletion. These include the quick refresh options.
816  */
817 short deletekey (ID *id, const char group[], const char rna_path[], int array_index, float cfra, short flag)
818 {
819         AnimData *adt;
820         FCurve *fcu;
821         
822         /* get F-Curve
823          * Note: here is one of the places where we don't want new Action + F-Curve added!
824          *              so 'add' var must be 0
825          */
826         /* we don't check the validity of the path here yet, but it should be ok... */
827         fcu= verify_fcurve(id, group, rna_path, array_index, 0);
828         adt= BKE_animdata_from_id(id);
829         
830         /* only continue if we have an ipo-curve to remove keyframes from */
831         if (adt && adt->action && fcu) {
832                 bAction *act= adt->action;
833                 short found = -1;
834                 int i;
835                 
836                 /* apply special time tweaking */
837                 if (GS(id->name) == ID_OB) {
838                         //Object *ob= (Object *)id;
839                         
840                         /* apply NLA-scaling (if applicable) */
841                         //      cfra= get_action_frame(ob, cfra);
842                         
843                         /* ancient time-offset cruft */
844                         //if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) {
845                         //      /* actually frametofloat calc again! */
846                         //      cfra-= give_timeoffset(ob)*scene->r.framelen;
847                         //}
848                 }
849                 
850                 /* try to find index of beztriple to get rid of */
851                 i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found);
852                 if (found) {                    
853                         /* delete the key at the index (will sanity check + do recalc afterwards) */
854                         delete_fcurve_key(fcu, i, 1);
855                         
856                         /* Only delete curve too if there are no points (we don't need to check for drivers, as they're kept separate) */
857                         // XXX how do we handle drivers then?
858                         if (fcu->totvert == 0) {
859                                 BLI_remlink(&act->curves, fcu);
860                                 free_fcurve(fcu);
861                         }
862                         
863                         /* return success */
864                         return 1;
865                 }
866         }
867         
868         /* return failure */
869         return 0;
870 }
871
872 /* ******************************************* */
873 /* KEYFRAME MODIFICATION */
874
875 /* mode for common_modifykey */
876 enum {
877         COMMONKEY_MODE_INSERT = 0,
878         COMMONKEY_MODE_DELETE,
879 } eCommonModifyKey_Modes;
880
881
882 /* Build menu-string of available keying-sets (allocates memory for string)
883  * NOTE: mode must not be longer than 64 chars
884  */
885 char *ANIM_build_keyingsets_menu (ListBase *list, short for_edit)
886 {
887         DynStr *pupds= BLI_dynstr_new();
888         KeyingSet *ks;
889         char buf[64];
890         char *str;
891         int i;
892         
893         /* add title first */
894         BLI_dynstr_append(pupds, "Keying Sets%t|");
895         
896         /* add dummy entries for none-active */
897         if (for_edit) { 
898                 BLI_dynstr_append(pupds, "Add New%x-1|");
899                 BLI_dynstr_append(pupds, " %x0|");
900         }
901         else
902                 BLI_dynstr_append(pupds, "<No Keying Set Active>%x0|");
903         
904         /* loop through keyingsets, adding them */
905         for (ks=list->first, i=1; ks; ks=ks->next, i++) {
906                 if (for_edit == 0)
907                         BLI_dynstr_append(pupds, "KS: ");
908                 
909                 BLI_dynstr_append(pupds, ks->name);
910                 BLI_snprintf( buf, 64, "%%x%d%s", i, ((ks->next)?"|":"") );
911                 BLI_dynstr_append(pupds, buf);
912         }
913         
914         /* convert to normal MEM_malloc'd string */
915         str= BLI_dynstr_get_cstring(pupds);
916         BLI_dynstr_free(pupds);
917         
918         return str;
919 }
920
921 #if 0 // XXX old keyingsets code based on adrcodes... to be restored in due course
922
923 /* --------- KeyingSet Adrcode Getters ------------ */
924
925 /* initialise a channel-getter storage */
926 static void ks_adrcodegetter_init (bKS_AdrcodeGetter *kag, bKeyingSet *ks, bCommonKeySrc *cks)
927 {
928         /* error checking */
929         if (kag == NULL)
930                 return;
931         
932         if (ELEM(NULL, ks, cks)) {
933                 /* set invalid settings that won't cause harm */
934                 kag->ks= NULL;
935                 kag->cks= NULL;
936                 kag->index= -2;
937                 kag->tot= 0;
938         }
939         else {
940                 /* store settings */
941                 kag->ks= ks;
942                 kag->cks= cks;
943                 
944                 /* - index is -1, as that allows iterators to return first element
945                  * - tot is chan_num by default, but may get overriden if -1 is encountered (for extension-type getters)
946                  */
947                 kag->index= -1;
948                 kag->tot= ks->chan_num;
949         }
950 }
951
952 /* 'default' channel-getter that will be used when iterating through keyingset's channels 
953  *       - iteration will stop when adrcode <= 0 is encountered, so we use that as escape
954  */
955 static short ks_getnextadrcode_default (bKS_AdrcodeGetter *kag)
956 {       
957         bKeyingSet *ks= (kag)? kag->ks : NULL;
958         
959         /* error checking */
960         if (ELEM(NULL, kag, ks)) return 0;
961         if (kag->tot <= 0) return 0;
962         
963         kag->index++;
964         if ((kag->index < 0) || (kag->index >= kag->tot)) return 0;
965         
966         /* return the adrcode stored at index then */
967         return ks->adrcodes[kag->index];
968 }
969
970 /* add map flag (for MTex channels, as certain ones need special offset) */
971 static short ks_getnextadrcode_addmap (bKS_AdrcodeGetter *kag)
972 {
973         short adrcode= ks_getnextadrcode_default(kag);
974         
975         /* if there was an adrcode returned, assume that kag stuff is set ok */
976         if (adrcode) {
977                 bCommonKeySrc *cks= kag->cks;
978                 bKeyingSet *ks= kag->ks;
979                 
980                 if (ELEM3(ks->blocktype, ID_MA, ID_LA, ID_WO)) {
981                         switch (adrcode) {
982                                 case MAP_OFS_X: case MAP_OFS_Y: case MAP_OFS_Z:
983                                 case MAP_SIZE_X: case MAP_SIZE_Y: case MAP_SIZE_Z:
984                                 case MAP_R: case MAP_G: case MAP_B: case MAP_DVAR:
985                                 case MAP_COLF: case MAP_NORF: case MAP_VARF: case MAP_DISP:
986                                         adrcode += cks->map;
987                                         break;
988                         }
989                 }
990         }
991         
992         /* adrcode must be returned! */
993         return adrcode;
994 }
995
996 /* extend posechannel keyingsets with rotation info (when KAG_CHAN_EXTEND is encountered) 
997  *      - iteration will stop when adrcode <= 0 is encountered, so we use that as escape
998  *      - when we encounter KAG_CHAN_EXTEND as adrcode, start returning our own
999  */
1000 static short ks_getnextadrcode_pchanrot (bKS_AdrcodeGetter *kag)
1001 {       
1002         /* hardcoded adrcode channels used here only 
1003          *      - length is keyed-channels + 1 (last item must be 0 to escape)
1004          */
1005         static short quat_adrcodes[5] = {AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z, 0};
1006         static short eul_adrcodes[4] = {AC_EUL_X, AC_EUL_Y, AC_EUL_Z, 0};
1007                 
1008         /* useful variables */
1009         bKeyingSet *ks= (kag)? kag->ks : NULL;
1010         bCommonKeySrc *cks= (kag) ? kag->cks : NULL;
1011         short index, adrcode;
1012         
1013         /* error checking */
1014         if (ELEM3(NULL, kag, ks, cks)) return 0;
1015         if (ks->chan_num <= 0) return 0;
1016         
1017         /* get index 
1018          *      - if past the last item (kag->tot), return stuff from our static arrays
1019          *      - otherwise, just keep returning stuff from the keyingset (but check out for -1!) 
1020          */
1021         kag->index++;
1022         if (kag->index < 0)
1023                 return 0;
1024         
1025         /* normal (static stuff) */
1026         if (kag->index < kag->tot) {
1027                 /* get adrcode, and return if not KAG_CHAN_EXTEND (i.e. point for start of iteration) */
1028                 adrcode= ks->adrcodes[kag->index];
1029                 
1030                 if (adrcode != KAG_CHAN_EXTEND) 
1031                         return adrcode;
1032                 else    
1033                         kag->tot= kag->index;
1034         }
1035                 
1036         /* based on current rotation-mode
1037          *      - index can be at most 5, if we are to prevent segfaults
1038          */
1039         index= kag->index - kag->tot;
1040         if ((index < 0) || (index > 5))
1041                 return 0;
1042         
1043         if (cks->pchan && cks->pchan->rotmode)
1044                 return eul_adrcodes[index];
1045         else
1046                 return quat_adrcodes[index];
1047 }
1048
1049 /* ------------- KeyingSet Defines ------------ */
1050 /* Note: these must all be named with the defks_* prefix, otherwise the template macro will not work! */
1051
1052 /* macro for defining keyingset contexts */
1053 #define KSC_TEMPLATE(ctx_name) {&defks_##ctx_name[0], NULL, sizeof(defks_##ctx_name)/sizeof(bKeyingSet)}
1054
1055 /* --- */
1056
1057 /* check if option not available for deleting keys */
1058 static short incl_non_del_keys (bKeyingSet *ks, const char mode[])
1059 {
1060         /* as optimisation, assume that it is sufficient to check only first letter
1061          * of mode (int comparison should be faster than string!)
1062          */
1063         //if (strcmp(mode, "Delete")==0)
1064         if (mode && mode[0]=='D')
1065                 return 0;
1066         
1067         return 1;
1068 }
1069
1070 /* Object KeyingSets  ------ */
1071
1072 /* check if include shapekey entry  */
1073 static short incl_v3d_ob_shapekey (bKeyingSet *ks, const char mode[])
1074 {
1075         //Object *ob= (G.obedit)? (G.obedit) : (OBACT); // XXX
1076         Object *ob= NULL;
1077         char *newname= NULL;
1078         
1079         if(ob==NULL)
1080                 return 0;
1081         
1082         /* not available for delete mode */
1083         if (strcmp(mode, "Delete")==0)
1084                 return 0;
1085         
1086         /* check if is geom object that can get shapekeys */
1087         switch (ob->type) {
1088                 /* geometry? */
1089                 case OB_MESH:           newname= "Mesh";                break;
1090                 case OB_CURVE:          newname= "Curve";               break;
1091                 case OB_SURF:           newname= "Surface";             break;
1092                 case OB_LATTICE:        newname= "Lattice";             break;
1093                 
1094                 /* not geometry! */
1095                 default:
1096                         return 0;
1097         }
1098         
1099         /* if ks is shapekey entry (this could be callled for separator before too!) */
1100         if (ks->flag == -3)
1101                 BLI_strncpy(ks->name, newname, sizeof(ks->name));
1102         
1103         /* if it gets here, it's ok */
1104         return 1;
1105 }
1106
1107 /* array for object keyingset defines */
1108 bKeyingSet defks_v3d_object[] = 
1109 {
1110         /* include_cb, adrcode-getter, name, blocktype, flag, chan_num, adrcodes */
1111         {NULL, "Loc", ID_OB, 0, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}},
1112         {NULL, "Rot", ID_OB, 0, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
1113         {NULL, "Scale", ID_OB, 0, 3, {OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
1114         
1115         {NULL, "%l", 0, -1, 0, {0}}, // separator
1116         
1117         {NULL, "LocRot", ID_OB, 0, 6, 
1118                 {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
1119                  OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
1120                  
1121         {NULL, "LocScale", ID_OB, 0, 6, 
1122                 {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
1123                  OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
1124                  
1125         {NULL, "LocRotScale", ID_OB, 0, 9, 
1126                 {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
1127                  OB_ROT_X,OB_ROT_Y,OB_ROT_Z,
1128                  OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
1129                  
1130         {NULL, "RotScale", ID_OB, 0, 6, 
1131                 {OB_ROT_X,OB_ROT_Y,OB_ROT_Z,
1132                  OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
1133         
1134         {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator
1135         
1136         {incl_non_del_keys, "VisualLoc", ID_OB, INSERTKEY_MATRIX, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}},
1137         {incl_non_del_keys, "VisualRot", ID_OB, INSERTKEY_MATRIX, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
1138         
1139         {incl_non_del_keys, "VisualLocRot", ID_OB, INSERTKEY_MATRIX, 6, 
1140                 {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
1141                  OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
1142         
1143         {NULL, "%l", 0, -1, 0, {0}}, // separator
1144         
1145         {NULL, "Layer", ID_OB, 0, 1, {OB_LAY}}, // icky option...
1146         {NULL, "Available", ID_OB, -2, 0, {0}},
1147         
1148         {incl_v3d_ob_shapekey, "%l%l", 0, -1, 0, {0}}, // separator (linked to shapekey entry)
1149         {incl_v3d_ob_shapekey, "<ShapeKey>", ID_OB, -3, 0, {0}}
1150 };
1151
1152 /* PoseChannel KeyingSets  ------ */
1153
1154 /* array for posechannel keyingset defines */
1155 bKeyingSet defks_v3d_pchan[] = 
1156 {
1157         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
1158         {NULL, "Loc", ID_PO, 0, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}},
1159         {NULL, "Rot", ID_PO, COMMONKEY_PCHANROT, 1, {KAG_CHAN_EXTEND}},
1160         {NULL, "Scale", ID_PO, 0, 3, {AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}},
1161         
1162         {NULL, "%l", 0, -1, 0, {0}}, // separator
1163         
1164         {NULL, "LocRot", ID_PO, COMMONKEY_PCHANROT, 4, 
1165                 {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,
1166                  KAG_CHAN_EXTEND}},
1167                  
1168         {NULL, "LocScale", ID_PO, 0, 6, 
1169                 {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,
1170                  AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}},
1171                  
1172         {NULL, "LocRotScale", ID_PO, COMMONKEY_PCHANROT, 7, 
1173                 {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z, 
1174                  KAG_CHAN_EXTEND}},
1175                  
1176         {NULL, "RotScale", ID_PO, 0, 4, 
1177                 {AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z, 
1178                  KAG_CHAN_EXTEND}},
1179         
1180         {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator
1181         
1182         {incl_non_del_keys, "VisualLoc", ID_PO, INSERTKEY_MATRIX, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}},
1183         {incl_non_del_keys, "VisualRot", ID_PO, INSERTKEY_MATRIX|COMMONKEY_PCHANROT, 1, {KAG_CHAN_EXTEND}},
1184         
1185         {incl_non_del_keys, "VisualLocRot", ID_PO, INSERTKEY_MATRIX|COMMONKEY_PCHANROT, 4, 
1186                 {AC_LOC_X,AC_LOC_Y,AC_LOC_Z, KAG_CHAN_EXTEND}},
1187         
1188         {NULL, "%l", 0, -1, 0, {0}}, // separator
1189         
1190         {NULL, "Available", ID_PO, -2, 0, {0}}
1191 };
1192
1193 /* Material KeyingSets  ------ */
1194
1195 /* array for material keyingset defines */
1196 bKeyingSet defks_buts_shading_mat[] = 
1197 {
1198         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
1199         {NULL, "RGB", ID_MA, 0, 3, {MA_COL_R,MA_COL_G,MA_COL_B}},
1200         {NULL, "Alpha", ID_MA, 0, 1, {MA_ALPHA}},
1201         {NULL, "Halo Size", ID_MA, 0, 1, {MA_HASIZE}},
1202         {NULL, "Mode", ID_MA, 0, 1, {MA_MODE}}, // evil bitflags
1203         
1204         {NULL, "%l", 0, -1, 0, {0}}, // separator
1205         
1206         {NULL, "All Color", ID_MA, 0, 18, 
1207                 {MA_COL_R,MA_COL_G,MA_COL_B,
1208                  MA_ALPHA,MA_HASIZE, MA_MODE,
1209                  MA_SPEC_R,MA_SPEC_G,MA_SPEC_B,
1210                  MA_REF,MA_EMIT,MA_AMB,MA_SPEC,MA_HARD,
1211                  MA_MODE,MA_TRANSLU,MA_ADD}},
1212                  
1213         {NULL, "All Mirror", ID_MA, 0, 5, 
1214                 {MA_RAYM,MA_FRESMIR,MA_FRESMIRI,
1215                  MA_FRESTRA,MA_FRESTRAI}},
1216         
1217         {NULL, "%l", 0, -1, 0, {0}}, // separator
1218         
1219         {NULL, "Ofs", ID_MA, COMMONKEY_ADDMAP, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
1220         {NULL, "Size", ID_MA, COMMONKEY_ADDMAP, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
1221         
1222         {NULL, "All Mapping", ID_MA, COMMONKEY_ADDMAP, 14, 
1223                 {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
1224                  MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
1225                  MAP_R,MAP_G,MAP_B,MAP_DVAR,
1226                  MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
1227         
1228         {NULL, "%l", 0, -1, 0, {0}}, // separator
1229         
1230         {NULL, "Available", ID_MA, -2, 0, {0}}
1231 };
1232
1233 /* World KeyingSets  ------ */
1234
1235 /* array for world keyingset defines */
1236 bKeyingSet defks_buts_shading_wo[] = 
1237 {
1238         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
1239         {NULL, "Zenith RGB", ID_WO, 0, 3, {WO_ZEN_R,WO_ZEN_G,WO_ZEN_B}},
1240         {NULL, "Horizon RGB", ID_WO, 0, 3, {WO_HOR_R,WO_HOR_G,WO_HOR_B}},
1241         
1242         {NULL, "%l", 0, -1, 0, {0}}, // separator
1243         
1244         {NULL, "Mist", ID_WO, 0, 4, {WO_MISI,WO_MISTDI,WO_MISTSTA,WO_MISTHI}},
1245         {NULL, "Stars", ID_WO, 0, 5, {WO_STAR_R,WO_STAR_G,WO_STAR_B,WO_STARDIST,WO_STARSIZE}},
1246         
1247         
1248         {NULL, "%l", 0, -1, 0, {0}}, // separator
1249         
1250         {NULL, "Ofs", ID_WO, COMMONKEY_ADDMAP, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
1251         {NULL, "Size", ID_WO, COMMONKEY_ADDMAP, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
1252         
1253         {NULL, "All Mapping", ID_WO, COMMONKEY_ADDMAP, 14, 
1254                 {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
1255                  MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
1256                  MAP_R,MAP_G,MAP_B,MAP_DVAR,
1257                  MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
1258         
1259         {NULL, "%l", 0, -1, 0, {0}}, // separator
1260         
1261         {NULL, "Available", ID_WO, -2, 0, {0}}
1262 };
1263
1264 /* Lamp KeyingSets  ------ */
1265
1266 /* array for lamp keyingset defines */
1267 bKeyingSet defks_buts_shading_la[] = 
1268 {
1269         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
1270         {NULL, "RGB", ID_LA, 0, 3, {LA_COL_R,LA_COL_G,LA_COL_B}},
1271         {NULL, "Energy", ID_LA, 0, 1, {LA_ENERGY}},
1272         {NULL, "Spot Size", ID_LA, 0, 1, {LA_SPOTSI}},
1273         
1274         {NULL, "%l", 0, -1, 0, {0}}, // separator
1275         
1276         {NULL, "Ofs", ID_LA, COMMONKEY_ADDMAP, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
1277         {NULL, "Size", ID_LA, COMMONKEY_ADDMAP, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
1278         
1279         {NULL, "All Mapping", ID_LA, COMMONKEY_ADDMAP, 14, 
1280                 {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
1281                  MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
1282                  MAP_R,MAP_G,MAP_B,MAP_DVAR,
1283                  MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
1284         
1285         {NULL, "%l", 0, -1, 0, {0}}, // separator
1286         
1287         {NULL, "Available", ID_LA, -2, 0, {0}}
1288 };
1289
1290 /* Texture KeyingSets  ------ */
1291
1292 /* array for texture keyingset defines */
1293 bKeyingSet defks_buts_shading_tex[] = 
1294 {
1295         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
1296         {NULL, "Clouds", ID_TE, 0, 5, 
1297                 {TE_NSIZE,TE_NDEPTH,TE_NTYPE,
1298                  TE_MG_TYP,TE_N_BAS1}},
1299         
1300         {NULL, "Marble", ID_TE, 0, 7, 
1301                 {TE_NSIZE,TE_NDEPTH,TE_NTYPE,
1302                  TE_TURB,TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}},
1303                  
1304         {NULL, "Stucci", ID_TE, 0, 5, 
1305                 {TE_NSIZE,TE_NTYPE,TE_TURB,
1306                  TE_MG_TYP,TE_N_BAS1}},
1307                  
1308         {NULL, "Wood", ID_TE, 0, 6, 
1309                 {TE_NSIZE,TE_NTYPE,TE_TURB,
1310                  TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}},
1311                  
1312         {NULL, "Magic", ID_TE, 0, 2, {TE_NDEPTH,TE_TURB}},
1313         
1314         {NULL, "Blend", ID_TE, 0, 1, {TE_MG_TYP}},      
1315                 
1316         {NULL, "Musgrave", ID_TE, 0, 6, 
1317                 {TE_MG_TYP,TE_MGH,TE_MG_LAC,
1318                  TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN}},
1319                  
1320         {NULL, "Voronoi", ID_TE, 0, 9, 
1321                 {TE_VNW1,TE_VNW2,TE_VNW3,TE_VNW4,
1322                 TE_VNMEXP,TE_VN_DISTM,TE_VN_COLT,
1323                 TE_ISCA,TE_NSIZE}},
1324                 
1325         {NULL, "Distorted Noise", ID_TE, 0, 4, 
1326                 {TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN,TE_DISTA}},
1327         
1328         {NULL, "Color Filter", ID_TE, 0, 5, 
1329                 {TE_COL_R,TE_COL_G,TE_COL_B,TE_BRIGHT,TE_CONTRA}},
1330         
1331         {NULL, "%l", 0, -1, 0, {0}}, // separator
1332         
1333         {NULL, "Available", ID_TE, -2, 0, {0}}
1334 };
1335
1336 /* Object Buttons KeyingSets  ------ */
1337
1338 /* check if include particles entry  */
1339 static short incl_buts_ob (bKeyingSet *ks, const char mode[])
1340 {
1341         //Object *ob= OBACT; // xxx
1342         Object *ob= NULL;
1343         /* only if object is mesh type */
1344         
1345         if(ob==NULL) return 0;
1346         return (ob->type == OB_MESH);
1347 }
1348
1349 /* array for texture keyingset defines */
1350 bKeyingSet defks_buts_object[] = 
1351 {
1352         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
1353         {incl_buts_ob, "Surface Damping", ID_OB, 0, 1, {OB_PD_SDAMP}},
1354         {incl_buts_ob, "Random Damping", ID_OB, 0, 1, {OB_PD_RDAMP}},
1355         {incl_buts_ob, "Permeability", ID_OB, 0, 1, {OB_PD_PERM}},
1356         
1357         {NULL, "%l", 0, -1, 0, {0}}, // separator
1358         
1359         {NULL, "Force Strength", ID_OB, 0, 1, {OB_PD_FSTR}},
1360         {NULL, "Force Falloff", ID_OB, 0, 1, {OB_PD_FFALL}},
1361         
1362         {NULL, "%l", 0, -1, 0, {0}}, // separator
1363         
1364         {NULL, "Available", ID_OB, -2, 0, {0}}  // this will include ob-transforms too!
1365 };
1366
1367 /* Camera Buttons KeyingSets  ------ */
1368
1369 /* check if include internal-renderer entry  */
1370 static short incl_buts_cam1 (bKeyingSet *ks, const char mode[])
1371 {
1372         Scene *scene= NULL; // FIXME this will cause a crash, but we need an extra arg first!
1373         /* only if renderer is internal renderer */
1374         return (scene->r.renderer==R_INTERN);
1375 }
1376
1377 /* check if include external-renderer entry  */
1378 static short incl_buts_cam2 (bKeyingSet *ks, const char mode[])
1379 {
1380         Scene *scene= NULL; // FIXME this will cause a crash, but we need an extra arg first!
1381         /* only if renderer is internal renderer */
1382         return (scene->r.renderer!=R_INTERN);
1383 }
1384
1385 /* array for camera keyingset defines */
1386 bKeyingSet defks_buts_cam[] = 
1387 {
1388         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
1389         {NULL, "Lens", ID_CA, 0, 1, {CAM_LENS}},
1390         {NULL, "Clipping", ID_CA, 0, 2, {CAM_STA,CAM_END}},
1391         {NULL, "Focal Distance", ID_CA, 0, 1, {CAM_YF_FDIST}},
1392         
1393         {NULL, "%l", 0, -1, 0, {0}}, // separator
1394         
1395         
1396         {incl_buts_cam2, "Aperture", ID_CA, 0, 1, {CAM_YF_APERT}},
1397         {incl_buts_cam1, "Viewplane Shift", ID_CA, 0, 2, {CAM_SHIFT_X,CAM_SHIFT_Y}},
1398         
1399         {NULL, "%l", 0, -1, 0, {0}}, // separator
1400         
1401         {NULL, "Available", ID_CA, -2, 0, {0}}
1402 };
1403
1404 /* --- */
1405
1406 /* Keying Context Defines - Must keep in sync with enumeration (eKS_Contexts) */
1407 bKeyingContext ks_contexts[] = 
1408 {
1409         KSC_TEMPLATE(v3d_object),
1410         KSC_TEMPLATE(v3d_pchan),
1411         
1412         KSC_TEMPLATE(buts_shading_mat),
1413         KSC_TEMPLATE(buts_shading_wo),
1414         KSC_TEMPLATE(buts_shading_la),
1415         KSC_TEMPLATE(buts_shading_tex),
1416
1417         KSC_TEMPLATE(buts_object),
1418         KSC_TEMPLATE(buts_cam)
1419 };
1420
1421 /* Keying Context Enumeration - Must keep in sync with definitions*/
1422 typedef enum eKS_Contexts {
1423         KSC_V3D_OBJECT = 0,
1424         KSC_V3D_PCHAN,
1425         
1426         KSC_BUTS_MAT,
1427         KSC_BUTS_WO,
1428         KSC_BUTS_LA,
1429         KSC_BUTS_TEX,
1430         
1431         KSC_BUTS_OB,
1432         KSC_BUTS_CAM,
1433         
1434                 /* make sure this last one remains untouched! */
1435         KSC_TOT_TYPES
1436 } eKS_Contexts;
1437
1438
1439 /* ---------------- KeyingSet Tools ------------------- */
1440
1441 /* helper for commonkey_context_get() -  get keyingsets for 3d-view */
1442 static void commonkey_context_getv3d (const bContext *C, ListBase *sources, bKeyingContext **ksc)
1443 {
1444         Scene *scene= CTX_data_scene(C);
1445         Object *ob;
1446         IpoCurve *icu;
1447         
1448         if ((OBACT) && (OBACT->flag & OB_POSEMODE)) {
1449                 bPoseChannel *pchan;
1450                 
1451                 /* pose-level */
1452                 ob= OBACT;
1453                 *ksc= &ks_contexts[KSC_V3D_PCHAN];
1454                         // XXX
1455                 //set_pose_keys(ob);  /* sets pchan->flag to POSE_KEY if bone selected, and clears if not */
1456                 
1457                 /* loop through posechannels */
1458                 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
1459                         if (pchan->flag & POSE_KEY) {
1460                                 bCommonKeySrc *cks;
1461                                 
1462                                 /* add new keyframing destination */
1463                                 cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1464                                 BLI_addtail(sources, cks);
1465                                 
1466                                 /* set id-block to key to, and action */
1467                                 cks->id= (ID *)ob;
1468                                 cks->act= ob->action;
1469                                 
1470                                 /* set pchan */
1471                                 cks->pchan= pchan;
1472                                 cks->actname= pchan->name;
1473                         }
1474                 }
1475         }
1476         else {
1477                 /* object-level */
1478                 *ksc= &ks_contexts[KSC_V3D_OBJECT];
1479                 
1480                 /* loop through bases */
1481                 // XXX but we're only supposed to do this on editable ones, not just selected ones!
1482                 CTX_DATA_BEGIN(C, Base*, base, selected_bases) {
1483                         bCommonKeySrc *cks;
1484                         
1485                         /* add new keyframing destination */
1486                         cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1487                         BLI_addtail(sources, cks);
1488                         
1489                         /* set id-block to key to */
1490                         ob= base->object;
1491                         cks->id= (ID *)ob;
1492                         
1493                         /* when ob's keyframes are in an action, default to using 'Object' as achan name */
1494                         if (ob->ipoflag & OB_ACTION_OB)
1495                                 cks->actname= "Object";
1496                         
1497                         /* set ipo-flags */
1498                         // TODO: add checks for lib-linked data
1499                         if ((ob->ipo) || (ob->action)) {
1500                                 if (ob->ipo) {
1501                                         cks->ipo= ob->ipo;
1502                                 }
1503                                 else {
1504                                         bActionChannel *achan;
1505                                         
1506                                         cks->act= ob->action;
1507                                         achan= get_action_channel(ob->action, cks->actname);
1508                                         
1509                                         if (achan && achan->ipo)
1510                                                 cks->ipo= achan->ipo;
1511                                 }
1512                                 /* cks->ipo can be NULL while editing */
1513                                 if(cks->ipo) {
1514                                         /* deselect all ipo-curves */
1515                                         for (icu= cks->ipo->curve.first; icu; icu= icu->next) {
1516                                                 icu->flag &= ~IPO_SELECT;
1517                                         }
1518                                 }
1519                         }
1520                 }
1521                 CTX_DATA_END;
1522         }
1523 }
1524
1525 /* helper for commonkey_context_get() -  get keyingsets for buttons window */
1526 static void commonkey_context_getsbuts (const bContext *C, ListBase *sources, bKeyingContext **ksc)
1527 {
1528 #if 0 // XXX dunno what's the future of this stuff...   
1529         bCommonKeySrc *cks;
1530         
1531         /* check on tab-type */
1532         switch (G.buts->mainb) {
1533         case CONTEXT_SHADING:   /* ------------- Shading buttons ---------------- */
1534                 /* subtabs include "Material", "Texture", "Lamp", "World"*/
1535                 switch (G.buts->tab[CONTEXT_SHADING]) {
1536                         case TAB_SHADING_MAT: /* >------------- Material Tab -------------< */
1537                         {
1538                                 Material *ma= editnode_get_active_material(G.buts->lockpoin);
1539                                 
1540                                 if (ma) {
1541                                         /* add new keyframing destination */
1542                                         cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1543                                         BLI_addtail(sources, cks); 
1544                                         
1545                                         /* set data */
1546                                         cks->id= (ID *)ma;
1547                                         cks->ipo= ma->ipo;
1548                                         cks->map= texchannel_to_adrcode(ma->texact);
1549                                         
1550                                         /* set keyingsets */
1551                                         *ksc= &ks_contexts[KSC_BUTS_MAT];
1552                                         return;
1553                                 }
1554                         }
1555                                 break;
1556                         case TAB_SHADING_WORLD: /* >------------- World Tab -------------< */
1557                         {
1558                                 World *wo= G.buts->lockpoin;
1559                                 
1560                                 if (wo) {
1561                                         /* add new keyframing destination */
1562                                         cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1563                                         BLI_addtail(sources, cks); 
1564                                         
1565                                         /* set data */
1566                                         cks->id= (ID *)wo;
1567                                         cks->ipo= wo->ipo;
1568                                         cks->map= texchannel_to_adrcode(wo->texact);
1569                                         
1570                                         /* set keyingsets */
1571                                         *ksc= &ks_contexts[KSC_BUTS_WO];
1572                                         return;
1573                                 }
1574                         }
1575                                 break;
1576                         case TAB_SHADING_LAMP: /* >------------- Lamp Tab -------------< */
1577                         {
1578                                 Lamp *la= G.buts->lockpoin;
1579                                 
1580                                 if (la) {
1581                                         /* add new keyframing destination */
1582                                         cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1583                                         BLI_addtail(sources, cks); 
1584                                         
1585                                         /* set data */
1586                                         cks->id= (ID *)la;
1587                                         cks->ipo= la->ipo;
1588                                         cks->map= texchannel_to_adrcode(la->texact);
1589                                         
1590                                         /* set keyingsets */
1591                                         *ksc= &ks_contexts[KSC_BUTS_LA];
1592                                         return;
1593                                 }
1594                         }
1595                                 break;
1596                         case TAB_SHADING_TEX: /* >------------- Texture Tab -------------< */
1597                         {
1598                                 Tex *tex= G.buts->lockpoin;
1599                                 
1600                                 if (tex) {
1601                                         /* add new keyframing destination */
1602                                         cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1603                                         BLI_addtail(sources, cks); 
1604                                         
1605                                         /* set data */
1606                                         cks->id= (ID *)tex;
1607                                         cks->ipo= tex->ipo;
1608                                         
1609                                         /* set keyingsets */
1610                                         *ksc= &ks_contexts[KSC_BUTS_TEX];
1611                                         return;
1612                                 }
1613                         }
1614                                 break;
1615                 }
1616                 break;
1617         
1618         case CONTEXT_OBJECT:    /* ------------- Object buttons ---------------- */
1619                 {
1620                         Object *ob= OBACT;
1621                         
1622                         if (ob) {
1623                                 /* add new keyframing destination */
1624                                 cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1625                                 BLI_addtail(sources, cks);
1626                                 
1627                                 /* set id-block to key to */
1628                                 cks->id= (ID *)ob;
1629                                 cks->ipo= ob->ipo;
1630                                 
1631                                 /* set keyingsets */
1632                                 *ksc= &ks_contexts[KSC_BUTS_OB];
1633                                 return;
1634                         }
1635                 }
1636                 break;
1637         
1638         case CONTEXT_EDITING:   /* ------------- Editing buttons ---------------- */
1639                 {
1640                         Object *ob= OBACT;
1641                         
1642                         if ((ob) && (ob->type==OB_CAMERA) && (G.buts->lockpoin)) { /* >---------------- camera buttons ---------------< */
1643                                 Camera *ca= G.buts->lockpoin;
1644                                 
1645                                 /* add new keyframing destination */
1646                                 cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1647                                 BLI_addtail(sources, cks);
1648                                 
1649                                 /* set id-block to key to */
1650                                 cks->id= (ID *)ca;
1651                                 cks->ipo= ca->ipo;
1652                                 
1653                                 /* set keyingsets */
1654                                 *ksc= &ks_contexts[KSC_BUTS_CAM];
1655                                 return;
1656                         }
1657                 }
1658                 break;
1659         }
1660 #endif // XXX end of buttons stuff to port...
1661         
1662         /* if nothing happened... */
1663         *ksc= NULL;
1664 }
1665
1666
1667 /* get keyingsets for appropriate context */
1668 static void commonkey_context_get (const bContext *C, ScrArea *sa, short mode, ListBase *sources, bKeyingContext **ksc)
1669 {
1670         /* get current view if no view is defined */
1671         if (sa == NULL)
1672                 sa= CTX_wm_area(C);
1673         
1674         /* check view type */
1675         switch (sa->spacetype) {
1676                 /* 3d view - first one tested as most often used */
1677                 case SPACE_VIEW3D:
1678                 {
1679                         commonkey_context_getv3d(C, sources, ksc);
1680                 }
1681                         break;
1682                         
1683                 /* buttons view */
1684                 case SPACE_BUTS:
1685                 {
1686                         commonkey_context_getsbuts(C, sources, ksc);
1687                 }
1688                         break;
1689                         
1690                 /* spaces with their own methods */
1691                 case SPACE_IPO:
1692                         //if (mode == COMMONKEY_MODE_INSERT)
1693                         //      insertkey_editipo(); // XXX old calls...
1694                         return;
1695                 case SPACE_ACTION:
1696                         //if (mode == COMMONKEY_MODE_INSERT)
1697                         //      insertkey_action(); // XXX old calls...
1698                         return;
1699                         
1700                 /* timeline view - keyframe buttons */
1701                 case SPACE_TIME:
1702                 {
1703                         bScreen *sc= CTX_wm_screen(C);
1704                         ScrArea *sab;
1705                         int bigarea= 0;
1706                         
1707                         /* try to find largest 3d-view available 
1708                          * (mostly of the time, this is what when user will want this,
1709                          *  as it's a standard feature in all other apps) 
1710                          */
1711                         //sab= find_biggest_area_of_type(SPACE_VIEW3D);
1712                         sab= NULL; // XXX for now...
1713                         if (sab) {
1714                                 commonkey_context_getv3d(C, sources, ksc);
1715                                 return;
1716                         }
1717                         
1718                         /* if not found, sab is now NULL, so perform own biggest area test */
1719                         for (sa= sc->areabase.first; sa; sa= sa->next) { // XXX this has changed!
1720                                 int area= sa->winx * sa->winy;
1721                                 
1722                                 if (sa->spacetype != SPACE_TIME) {
1723                                         if ( (!sab) || (area > bigarea) ) {
1724                                                 sab= sa;
1725                                                 bigarea= area;
1726                                         }
1727                                 }
1728                         }
1729                         
1730                         /* use whichever largest area was found (it shouldn't be a time window) */
1731                         if (sab)
1732                                 commonkey_context_get(C, sab, mode, sources, ksc);
1733                 }
1734                         break;
1735         }
1736 }
1737
1738 /* flush updates after all operations */
1739 static void commonkey_context_finish (const bContext *C, ListBase *sources)
1740 {
1741         ScrArea *curarea= CTX_wm_area(C);
1742         Scene *scene= CTX_data_scene(C);
1743         
1744         /* check view type */
1745         switch (curarea->spacetype) {
1746                 /* 3d view - first one tested as most often used */
1747                 case SPACE_VIEW3D:
1748                 {
1749                         /* either pose or object level */
1750                         if (OBACT && (OBACT->pose)) {   
1751                                 //Object *ob= OBACT;
1752                                 
1753                                 /* recalculate ipo handles, etc. */
1754                                 // XXX this method has been removed!
1755                                 //if (ob->action)
1756                                 //      remake_action_ipos(ob->action);
1757                                 
1758                                 /* recalculate bone-paths on adding new keyframe? */
1759                                 // XXX missing function
1760                                 // TODO: currently, there is no setting to turn this on/off globally
1761                                 //if (ob->pose->flag & POSE_RECALCPATHS)
1762                                 //      pose_recalculate_paths(ob);
1763                         }
1764                         else {
1765                                 bCommonKeySrc *cks;
1766                                 
1767                                 /* loop over bases (as seen in sources) */
1768                                 for (cks= sources->first; cks; cks= cks->next) {
1769                                         Object *ob= (Object *)cks->id;
1770                                         
1771                                         /* simply set recalc flag */
1772                                         ob->recalc |= OB_RECALC_OB;
1773                                 }
1774                         }
1775                 }
1776                         break;
1777         }
1778 }
1779
1780 /* flush refreshes after undo */
1781 static void commonkey_context_refresh (bContext *C)
1782 {
1783         ScrArea *curarea= CTX_wm_area(C);
1784         
1785         /* check view type */
1786         switch (curarea->spacetype) {
1787                 /* 3d view - first one tested as most often used */
1788                 case SPACE_VIEW3D:
1789                 {
1790                         /* do refreshes */
1791                         ED_anim_dag_flush_update(C);
1792                 }
1793                         break;
1794                         
1795                 /* buttons window */
1796                 case SPACE_BUTS:
1797                 {
1798                         //allspace(REMAKEIPO, 0);
1799                         //allqueue(REDRAWVIEW3D, 0);
1800                         //allqueue(REDRAWMARKER, 0);
1801                 }
1802                         break;
1803         }
1804 }
1805
1806 /* --- */
1807
1808 /* Get the keying set that was chosen by the user from the menu */
1809 static bKeyingSet *get_keyingset_fromcontext (bKeyingContext *ksc, short index)
1810 {
1811         /* check if index is valid */
1812         if (ELEM(NULL, ksc, ksc->keyingsets))
1813                 return NULL;
1814         if ((index < 1) || (index > ksc->tot))
1815                 return NULL;
1816                 
1817         /* index starts from 1, and should directly correspond to keyingset in array */
1818         return (bKeyingSet *)(ksc->keyingsets + (index - 1));
1819 }
1820
1821 /* ---------------- Keyframe Management API -------------------- */
1822
1823 /* Display a menu for handling the insertion of keyframes based on the active view */
1824 void common_modifykey (bContext *C, short mode)
1825 {
1826         ListBase dsources = {NULL, NULL};
1827         bKeyingContext *ksc= NULL;
1828         bCommonKeySrc *cks;
1829         bKeyingSet *ks = NULL;
1830         char *menustr, buf[64];
1831         short menu_nr;
1832         
1833         /* check if mode is valid */
1834         if (ELEM(mode, COMMONKEY_MODE_INSERT, COMMONKEY_MODE_DELETE)==0)
1835                 return;
1836         
1837         /* delegate to other functions or get keyingsets to use 
1838          *      - if the current area doesn't have its own handling, there will be data returned...
1839          */
1840         commonkey_context_get(C, NULL, mode, &dsources, &ksc);
1841         
1842         /* check that there is data to operate on */
1843         if (ELEM(NULL, dsources.first, ksc)) {
1844                 BLI_freelistN(&dsources);
1845                 return;
1846         }
1847         
1848         /* get menu and process it */
1849         if (mode == COMMONKEY_MODE_DELETE)
1850                 menustr= build_keyingsets_menu(ksc, "Delete");
1851         else
1852                 menustr= build_keyingsets_menu(ksc, "Insert");
1853         // XXX: this goes to the invoke!
1854         //menu_nr= pupmenu(menustr);
1855         //if (menustr) MEM_freeN(menustr);
1856         menu_nr = -1; // XXX for now
1857         
1858         /* no item selected or shapekey entry? */
1859         if (menu_nr < 1) {
1860                 /* free temp sources */
1861                 BLI_freelistN(&dsources);
1862                 
1863                 /* check if insert new shapekey */
1864                 // XXX missing function!
1865                 //if ((menu_nr == 0) && (mode == COMMONKEY_MODE_INSERT))
1866                 //      insert_shapekey(OBACT);
1867                 //else 
1868                         ksc->lastused= NULL;
1869                         
1870                 return;
1871         }
1872         else {
1873                 /* try to get keyingset */
1874                 ks= get_keyingset_fromcontext(ksc, menu_nr);
1875                 
1876                 if (ks == NULL) {
1877                         BLI_freelistN(&dsources);
1878                         return;
1879                 }
1880         }
1881         
1882         /* loop over each destination, applying the keying set */
1883         for (cks= dsources.first; cks; cks= cks->next) {
1884                 short success= 0;
1885                 
1886                 /* special hacks for 'available' option */
1887                 if (ks->flag == -2) {
1888                         IpoCurve *icu= NULL, *icn= NULL;
1889                         
1890                         /* get first IPO-curve */
1891                         if (cks->act && cks->actname) {
1892                                 bActionChannel *achan= get_action_channel(cks->act, cks->actname);
1893                                 
1894                                 // FIXME: what about constraint channels?
1895                                 if (achan && achan->ipo)
1896                                         icu= achan->ipo->curve.first; 
1897                         }
1898                         else if(cks->ipo)
1899                                 icu= cks->ipo->curve.first;
1900                                 
1901                         /* we get adrcodes directly from IPO curves (see method below...) */
1902                         for (; icu; icu= icn) {
1903                                 short flag;
1904                                 
1905                                 /* get next ipo-curve in case current is deleted */
1906                                 icn= icu->next;
1907                                 
1908                                 /* insert mode or delete mode */
1909                                 if (mode == COMMONKEY_MODE_DELETE) {
1910                                         /* local flags only add on to global flags */
1911                                         flag = 0;
1912                                         
1913                                         /* delete keyframe */
1914                                         success += deletekey(cks->id, ks->blocktype, cks->actname, cks->constname, icu->adrcode, flag);
1915                                 }
1916                                 else {
1917                                         /* local flags only add on to global flags */
1918                                         flag = ks->flag;
1919                                         if (IS_AUTOKEY_FLAG(AUTOMATKEY)) flag |= INSERTKEY_MATRIX;
1920                                         if (IS_AUTOKEY_FLAG(INSERTNEEDED)) flag |= INSERTKEY_NEEDED;
1921                                         // if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE;
1922                                         
1923                                         /* insert keyframe */
1924                                         success += insertkey(cks->id, ks->blocktype, cks->actname, cks->constname, icu->adrcode, flag);
1925                                 }
1926                         }
1927                 }
1928                 else {
1929                         bKS_AdrcodeGetter kag;
1930                         short (*get_next_adrcode)(bKS_AdrcodeGetter *);
1931                         int adrcode;
1932                         
1933                         /* initialise keyingset channel iterator */
1934                         ks_adrcodegetter_init(&kag, ks, cks);
1935                         
1936                         /* get iterator - only one can be in use at a time... the flags should be mutually exclusive in this regard */
1937                         if (ks->flag & COMMONKEY_PCHANROT)
1938                                 get_next_adrcode= ks_getnextadrcode_pchanrot;
1939                         else if (ks->flag & COMMONKEY_ADDMAP)
1940                                 get_next_adrcode= ks_getnextadrcode_addmap;
1941                         else
1942                                 get_next_adrcode= ks_getnextadrcode_default;
1943                         
1944                         /* loop over channels available in keyingset */
1945                         for (adrcode= get_next_adrcode(&kag); adrcode > 0; adrcode= get_next_adrcode(&kag)) {
1946                                 short flag;
1947                                 
1948                                 /* insert mode or delete mode */
1949                                 if (mode == COMMONKEY_MODE_DELETE) {
1950                                         /* local flags only add on to global flags */
1951                                         flag = 0;
1952                                         //flag &= ~COMMONKEY_MODES;
1953                                         
1954                                         /* delete keyframe */
1955                                         success += deletekey(cks->id, ks->blocktype, cks->actname, cks->constname, adrcode, flag);
1956                                 }
1957                                 else {
1958                                         /* local flags only add on to global flags */
1959                                         flag = ks->flag;
1960                                         if (IS_AUTOKEY_FLAG(AUTOMATKEY)) flag |= INSERTKEY_MATRIX;
1961                                         if (IS_AUTOKEY_FLAG(INSERTNEEDED)) flag |= INSERTKEY_NEEDED;
1962                                         // if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE;
1963                                         flag &= ~COMMONKEY_MODES;
1964                                         
1965                                         /* insert keyframe */
1966                                         success += insertkey(cks->id, ks->blocktype, cks->actname, cks->constname, adrcode, flag);
1967                                 }
1968                         }
1969                 }
1970                 
1971                 /* special handling for some key-sources */
1972                 if (success) {
1973                         /* set pose recalc-paths flag */
1974                         if (cks->pchan) {
1975                                 Object *ob= (Object *)cks->id;
1976                                 bPoseChannel *pchan= cks->pchan;
1977                                 
1978                                 /* set flag to trigger path recalc */
1979                                 if (pchan->path) 
1980                                         ob->pose->flag |= POSE_RECALCPATHS;
1981                                         
1982                                 /* clear unkeyed flag (it doesn't matter if it's set or not) */
1983                                         // XXX old animation system
1984                                 //if (pchan->bone)
1985                                 //      pchan->bone->flag &= ~BONE_UNKEYED;
1986                         }
1987                         
1988                         // XXX for new system, need to remove overrides
1989                 }
1990         }
1991         
1992         /* apply post-keying flushes for this data sources */
1993         commonkey_context_finish(C, &dsources);
1994         
1995         /* free temp data */
1996         BLI_freelistN(&dsources);
1997         
1998         /* queue updates for contexts */
1999         commonkey_context_refresh(C);
2000 }
2001
2002 #endif // XXX old keyingsets code based on adrcodes... to be restored in due course
2003
2004 /* Given a KeyingSet and context info (if required), modify keyframes for the channels specified
2005  * by the KeyingSet. This takes into account many of the different combinations of using KeyingSets.
2006  * Returns the number of channels that keyframes were added to
2007  */
2008 static int commonkey_modifykey (ListBase *dsources, KeyingSet *ks, short mode, float cfra)
2009 {
2010         KS_Path *ksp;
2011         int kflag=0, success= 0;
2012         char *groupname= NULL;
2013         
2014         /* get flags to use */
2015         if (mode == COMMONKEY_MODE_INSERT) {
2016                 /* use KeyingSet's flags as base */
2017                 kflag= ks->keyingflag;
2018                 
2019                 /* suppliment with info from the context */
2020                 if (IS_AUTOKEY_FLAG(AUTOMATKEY)) kflag |= INSERTKEY_MATRIX;
2021                 if (IS_AUTOKEY_FLAG(INSERTNEEDED)) kflag |= INSERTKEY_NEEDED;
2022                 // if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE;
2023         }
2024         else if (mode == COMMONKEY_MODE_DELETE)
2025                 kflag= 0;
2026         
2027         /* check if the KeyingSet is absolute or not (i.e. does it requires sources info) */
2028         if (ks->flag & KEYINGSET_ABSOLUTE) {
2029                 /* Absolute KeyingSets are simpler to use, as all the destination info has already been
2030                  * provided by the user, and is stored, ready to use, in the KeyingSet paths.
2031                  */
2032                 for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
2033                         int arraylen, i;
2034                         
2035                         /* get pointer to name of group to add channels to */
2036                         if (ksp->groupmode == KSP_GROUP_NONE)
2037                                 groupname= NULL;
2038                         else if (ksp->groupmode == KSP_GROUP_KSNAME)
2039                                 groupname= ks->name;
2040                         else
2041                                 groupname= ksp->group;
2042                         
2043                         /* init arraylen and i - arraylen should be greater than i so that
2044                          * normal non-array entries get keyframed correctly
2045                          */
2046                         i= ksp->array_index;
2047                         arraylen= i+1;
2048                         
2049                         /* get length of array if whole array option is enabled */
2050                         if (ksp->flag & KSP_FLAG_WHOLE_ARRAY) {
2051                                 PointerRNA id_ptr, ptr;
2052                                 PropertyRNA *prop;
2053                                 
2054                                 RNA_id_pointer_create(ksp->id, &id_ptr);
2055                                 if (RNA_path_resolve(&id_ptr, ksp->rna_path, &ptr, &prop) && prop)
2056                                         arraylen= RNA_property_array_length(&ptr, prop);
2057                         }
2058                         
2059                         /* for each possible index, perform operation 
2060                          *      - assume that arraylen is greater than index
2061                          */
2062                         for (; i < arraylen; i++) {
2063                                 /* action to take depends on mode */
2064                                 if (mode == COMMONKEY_MODE_INSERT)
2065                                         success+= insertkey(ksp->id, groupname, ksp->rna_path, i, cfra, kflag);
2066                                 else if (mode == COMMONKEY_MODE_DELETE)
2067                                         success+= deletekey(ksp->id, groupname,  ksp->rna_path, i, cfra, kflag);
2068                         }
2069                         
2070                         // TODO: set recalc tags on the ID?
2071                 }
2072         }
2073 #if 0 // XXX still need to figure out how to get such keyingsets working
2074         else if (dsources) {
2075                 /* for each one of the 'sources', resolve the template markers and expand arrays, then insert keyframes */
2076                 bCommonKeySrc *cks;
2077                 char *path = NULL;
2078                 int index=0, tot=0;
2079                 
2080                 /* for each 'source' for keyframe data, resolve each of the paths from the KeyingSet */
2081                 for (cks= dsources->first; cks; cks= cks->next) {
2082                         
2083                 }
2084         }
2085 #endif // XXX still need to figure out how to get such 
2086         
2087         return success;
2088 }
2089
2090 /* Insert Key Operator ------------------------ */
2091
2092 /* NOTE:
2093  * This is one of the 'simpler new-style' Insert Keyframe operators which relies on Keying Sets.
2094  * For now, these are absolute Keying Sets only, so there is very little context info involved.
2095  *
2096  *      -- Joshua Leung, Feb 2009
2097  */
2098
2099 static int insert_key_exec (bContext *C, wmOperator *op)
2100 {
2101         ListBase dsources = {NULL, NULL};
2102         Scene *scene= CTX_data_scene(C);
2103         KeyingSet *ks= NULL;
2104         float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
2105         short success;
2106         
2107         /* try to get KeyingSet */
2108         if (scene->active_keyingset > 0)
2109                 ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
2110         /* report failure */
2111         if (ks == NULL) {
2112                 BKE_report(op->reports, RPT_ERROR, "No active Keying Set");
2113                 return OPERATOR_CANCELLED;
2114         }
2115         
2116         /* try to insert keyframes for the channels specified by KeyingSet */
2117         success= commonkey_modifykey(&dsources, ks, COMMONKEY_MODE_INSERT, cfra);
2118         printf("KeyingSet '%s' - Successfully added %d Keyframes \n", ks->name, success);
2119         
2120         /* report failure? */
2121         if (success == 0)
2122                 BKE_report(op->reports, RPT_WARNING, "Keying Set failed to insert any keyframes");
2123         
2124         /* send updates */
2125         ED_anim_dag_flush_update(C);    
2126         
2127         /* for now, only send ND_KEYS for KeyingSets */
2128         WM_event_add_notifier(C, ND_KEYS, NULL);
2129         
2130         return OPERATOR_FINISHED;
2131 }
2132
2133 void ANIM_OT_insert_keyframe (wmOperatorType *ot)
2134 {
2135         /* identifiers */
2136         ot->name= "Insert Keyframe";
2137         ot->idname= "ANIM_OT_insert_keyframe";
2138         
2139         /* callbacks */
2140         ot->exec= insert_key_exec; 
2141         ot->poll= ED_operator_areaactive;
2142         
2143         /* flags */
2144         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2145 }
2146
2147 /* Delete Key Operator ------------------------ */
2148
2149 /* NOTE:
2150  * This is one of the 'simpler new-style' Insert Keyframe operators which relies on Keying Sets.
2151  * For now, these are absolute Keying Sets only, so there is very little context info involved.
2152  *
2153  *      -- Joshua Leung, Feb 2009
2154  */
2155  
2156 static int delete_key_exec (bContext *C, wmOperator *op)
2157 {
2158         ListBase dsources = {NULL, NULL};
2159         Scene *scene= CTX_data_scene(C);
2160         KeyingSet *ks= NULL;
2161         float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
2162         short success;
2163         
2164         /* try to get KeyingSet */
2165         if (scene->active_keyingset > 0)
2166                 ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
2167         /* report failure */
2168         if (ks == NULL) {
2169                 BKE_report(op->reports, RPT_ERROR, "No active Keying Set");
2170                 return OPERATOR_CANCELLED;
2171         }
2172         
2173         /* try to insert keyframes for the channels specified by KeyingSet */
2174         success= commonkey_modifykey(&dsources, ks, COMMONKEY_MODE_DELETE, cfra);
2175         printf("KeyingSet '%s' - Successfully removed %d Keyframes \n", ks->name, success);
2176         
2177         /* report failure? */
2178         if (success == 0)
2179                 BKE_report(op->reports, RPT_WARNING, "Keying Set failed to remove any keyframes");
2180         
2181         /* send updates */
2182         ED_anim_dag_flush_update(C);    
2183         
2184         /* for now, only send ND_KEYS for KeyingSets */
2185         WM_event_add_notifier(C, ND_KEYS, NULL);
2186         
2187         return OPERATOR_FINISHED;
2188 }
2189
2190 void ANIM_OT_delete_keyframe (wmOperatorType *ot)
2191 {
2192         /* identifiers */
2193         ot->name= "Delete Keyframe";
2194         ot->idname= "ANIM_OT_delete_keyframe";
2195         
2196         /* callbacks */
2197         ot->exec= delete_key_exec; 
2198         
2199         ot->poll= ED_operator_areaactive;
2200         
2201         /* flags */
2202         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2203 }
2204
2205 /* Insert Key Operator ------------------------ */
2206
2207 /* XXX WARNING:
2208  * This is currently just a basic operator, which work in 3d-view context on objects/bones only
2209  * and will insert keyframes for a few settings only. This is until it becomes clear how
2210  * to separate (or not) the process for RNA-path creation between context + keyingsets.
2211  * 
2212  * -- Joshua Leung, Jan 2009
2213  */
2214
2215 /* defines for basic insert-key testing operator  */
2216         // XXX this will definitely be replaced
2217 EnumPropertyItem prop_insertkey_types[] = {
2218         {0, "KEYINGSET", "Active KeyingSet", ""},
2219         {1, "OBLOC", "Object Location", ""},
2220         {2, "OBROT", "Object Rotation", ""},
2221         {3, "OBSCALE", "Object Scale", ""},
2222         {4, "MAT_COL", "Active Material - Color", ""},
2223         {5, "PCHANLOC", "Pose-Channel Location", ""},
2224         {6, "PCHANROT", "Pose-Channel Rotation", ""},
2225         {7, "PCHANSCALE", "Pose-Channel Scale", ""},
2226         {0, NULL, NULL, NULL}
2227 };
2228
2229 static int insert_key_old_invoke (bContext *C, wmOperator *op, wmEvent *event)
2230 {
2231         Object *ob= CTX_data_active_object(C);
2232         uiMenuItem *head;
2233         
2234         if (ob == NULL)
2235                 return OPERATOR_CANCELLED;
2236                 
2237         head= uiPupMenuBegin("Insert Keyframe", 0);
2238         
2239         /* active keyingset */
2240         uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe_old", "type", 0);
2241         
2242         /* selective inclusion */
2243         if ((ob->pose) && (ob->flag & OB_POSEMODE)) {
2244                 /* bone types */        
2245                 uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe_old", "type", 5);
2246                 uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe_old", "type", 6);
2247                 uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe_old", "type", 7);
2248         }
2249         else {
2250                 /* object types */
2251                 uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe_old", "type", 1);
2252                 uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe_old", "type", 2);
2253                 uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe_old", "type", 3);
2254                 uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe_old", "type", 4);
2255         }
2256         
2257         uiPupMenuEnd(C, head);
2258         
2259         return OPERATOR_CANCELLED;
2260 }
2261  
2262 static int insert_key_old_exec (bContext *C, wmOperator *op)
2263 {
2264         Scene *scene= CTX_data_scene(C);
2265         short mode= RNA_enum_get(op->ptr, "type");
2266         float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
2267         
2268         /* for now, handle 'active keyingset' one separately */
2269         if (mode == 0) {
2270                 ListBase dsources = {NULL, NULL};
2271                 KeyingSet *ks= NULL;
2272                 short success;
2273                 
2274                 /* try to get KeyingSet */
2275                 if (scene->active_keyingset > 0)
2276                         ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
2277                 /* report failure */
2278                 if (ks == NULL) {
2279                         BKE_report(op->reports, RPT_ERROR, "No active Keying Set");
2280                         return OPERATOR_CANCELLED;
2281                 }
2282                 
2283                 /* try to insert keyframes for the channels specified by KeyingSet */
2284                 success= commonkey_modifykey(&dsources, ks, COMMONKEY_MODE_INSERT, cfra);
2285                 printf("KeyingSet '%s' - Successfully added %d Keyframes \n", ks->name, success);
2286                 
2287                 /* report failure? */
2288                 if (success == 0)
2289                         BKE_report(op->reports, RPT_WARNING, "Keying Set failed to insert any keyframes");
2290         }
2291         else {
2292                 // more comprehensive tests will be needed
2293                 CTX_DATA_BEGIN(C, Base*, base, selected_bases) 
2294                 {
2295                         Object *ob= base->object;
2296                         ID *id= (ID *)ob;
2297                         short success= 0;
2298                         
2299                         /* check which keyframing mode chosen for this object */
2300                         if (mode < 4) {
2301                                 /* object-based keyframes */
2302                                 switch (mode) {
2303                                 case 4: /* color of active material (only for geometry...) */
2304                                         // NOTE: this is just a demo... but ideally we'd go through materials instead of active one only so reference stays same
2305                                         // XXX no group for now
2306                                         success+= insertkey(id, NULL, "active_material.diffuse_color", 0, cfra, 0);
2307                                         success+= insertkey(id, NULL, "active_material.diffuse_color", 1, cfra, 0);
2308                                         success+= insertkey(id, NULL, "active_material.diffuse_color", 2, cfra, 0);
2309                                         break;
2310                                 case 3: /* object scale */
2311                                         success+= insertkey(id, "Object Transforms", "scale", 0, cfra, 0);
2312                                         success+= insertkey(id, "Object Transforms", "scale", 1, cfra, 0);
2313                                         success+= insertkey(id, "Object Transforms", "scale", 2, cfra, 0);
2314                                         break;
2315                                 case 2: /* object rotation */
2316                                         success+= insertkey(id, "Object Transforms", "rotation", 0, cfra, 0);
2317                                         success+= insertkey(id, "Object Transforms", "rotation", 1, cfra, 0);
2318                                         success+= insertkey(id, "Object Transforms", "rotation", 2, cfra, 0);
2319                                         break;
2320                                 case 1: /* object location */
2321                                         success+= insertkey(id, "Object Transforms", "location", 0, cfra, 0);
2322                                         success+= insertkey(id, "Object Transforms", "location", 1, cfra, 0);
2323                                         success+= insertkey(id, "Object Transforms", "location", 2, cfra, 0);
2324                                         break;
2325                                 }
2326                                 
2327                                 ob->recalc |= OB_RECALC_OB;
2328                         }
2329                         else if ((ob->pose) && (ob->flag & OB_POSEMODE)) {
2330                                 /* PoseChannel based keyframes */
2331                                 bPoseChannel *pchan;
2332                                 
2333                                 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
2334                                         /* only if selected */
2335                                         if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) {
2336                                                 char buf[512];
2337                                                 
2338                                                 switch (mode) {
2339                                                 case 6: /* pchan scale */
2340                                                         sprintf(buf, "pose.pose_channels[\"%s\"].scale", pchan->name);
2341                                                         success+= insertkey(id, pchan->name, buf, 0, cfra, 0);
2342                                                         success+= insertkey(id, pchan->name, buf, 1, cfra, 0);
2343                                                         success+= insertkey(id, pchan->name, buf, 2, cfra, 0);
2344                                                         break;
2345                                                 case 5: /* pchan rotation */
2346                                                         if (pchan->rotmode == PCHAN_ROT_QUAT) {
2347                                                                 sprintf(buf, "pose.pose_channels[\"%s\"].rotation", pchan->name);
2348                                                                 success+= insertkey(id, pchan->name, buf, 0, cfra, 0);
2349                                                                 success+= insertkey(id, pchan->name, buf, 1, cfra, 0);
2350                                                                 success+= insertkey(id, pchan->name, buf, 2, cfra, 0);
2351                                                                 success+= insertkey(id, pchan->name, buf, 3, cfra, 0);
2352                                                         }
2353                                                         else {
2354                                                                 sprintf(buf, "pose.pose_channels[\"%s\"].euler_rotation", pchan->name);
2355                                                                 success+= insertkey(id, pchan->name, buf, 0, cfra, 0);
2356                                                                 success+= insertkey(id, pchan->name, buf, 1, cfra, 0);
2357                                                                 success+= insertkey(id, pchan->name, buf, 2, cfra, 0);
2358                                                         }
2359                                                         break;
2360                                                 default: /* pchan location */
2361                                                         sprintf(buf, "pose.pose_channels[\"%s\"].location", pchan->name);
2362                                                         success+= insertkey(id, pchan->name, buf, 0, cfra, 0);
2363                                                         success+= insertkey(id, pchan->name, buf, 1, cfra, 0);
2364                                                         success+= insertkey(id, pchan->name, buf, 2, cfra, 0);
2365                                                         break;
2366                                                 }
2367                                         }
2368                                 }
2369                                 
2370                                 ob->recalc |= OB_RECALC_OB;
2371                         }
2372                         
2373                         printf("Ob '%s' - Successfully added %d Keyframes \n", id->name+2, success);
2374                 }
2375                 CTX_DATA_END;
2376         }
2377         
2378         /* send updates */
2379         ED_anim_dag_flush_update(C);    
2380         
2381         if (mode == 0) /* for now, only send ND_KEYS for KeyingSets */
2382                 WM_event_add_notifier(C, ND_KEYS, NULL);
2383         else if (mode == 4) /* material color requires different notifiers */
2384                 WM_event_add_notifier(C, NC_MATERIAL|ND_KEYS, NULL);
2385         else
2386                 WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, NULL);
2387         
2388         return OPERATOR_FINISHED;
2389 }
2390
2391 void ANIM_OT_insert_keyframe_old (wmOperatorType *ot)
2392 {
2393         PropertyRNA *prop;
2394         
2395         /* identifiers */
2396         ot->name= "Insert Keyframe";
2397         ot->idname= "ANIM_OT_insert_keyframe_old";
2398         
2399         /* callbacks */
2400         ot->invoke= insert_key_old_invoke;
2401         ot->exec= insert_key_old_exec; 
2402         ot->poll= ED_operator_areaactive;
2403         
2404         /* flags */
2405         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2406         
2407         /* properties */
2408                 // XXX update this for the latest RNA stuff styles...
2409         prop= RNA_def_property(ot->srna, "type", PROP_ENUM, PROP_NONE);
2410         RNA_def_property_enum_items(prop, prop_insertkey_types);
2411 }
2412
2413 /* Delete Key Operator ------------------------ */
2414
2415 /* XXX WARNING:
2416  * This is currently just a basic operator, which work in 3d-view context on objects only. 
2417  * -- Joshua Leung, Jan 2009
2418  */
2419  
2420 static int delete_key_old_exec (bContext *C, wmOperator *op)
2421 {
2422         Scene *scene= CTX_data_scene(C);
2423         float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
2424         
2425         // XXX more comprehensive tests will be needed
2426         CTX_DATA_BEGIN(C, Base*, base, selected_bases) 
2427         {
2428                 Object *ob= base->object;
2429                 ID *id= (ID *)ob;
2430                 FCurve *fcu, *fcn;
2431                 short success= 0;
2432                 
2433                 /* loop through all curves in animdata and delete keys on this frame */
2434                 if (ob->adt) {
2435                         AnimData *adt= ob->adt;
2436                         bAction *act= adt->action;
2437                         
2438                         for (fcu= act->curves.first; fcu; fcu= fcn) {
2439                                 fcn= fcu->next;
2440                                 success+= deletekey(id, NULL, fcu->rna_path, fcu->array_index, cfra, 0);
2441                         }
2442                 }
2443                 
2444                 printf("Ob '%s' - Successfully removed %d keyframes \n", id->name+2, success);
2445                 
2446                 ob->recalc |= OB_RECALC_OB;
2447         }
2448         CTX_DATA_END;
2449         
2450         /* send updates */
2451         ED_anim_dag_flush_update(C);    
2452         
2453                 // XXX what if it was a material keyframe?
2454         WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, NULL);
2455         
2456         return OPERATOR_FINISHED;
2457 }
2458
2459 void ANIM_OT_delete_keyframe_old (wmOperatorType *ot)
2460 {
2461         /* identifiers */
2462         ot->name= "Delete Keyframe";
2463         ot->idname= "ANIM_OT_delete_keyframe_old";
2464         
2465         /* callbacks */
2466         ot->invoke= WM_operator_confirm; // XXX we will need our own one eventually, to cope with the dynamic menus...
2467         ot->exec= delete_key_old_exec; 
2468         
2469         ot->poll= ED_operator_areaactive;
2470         
2471         /* flags */
2472         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2473 }
2474
2475 /* ******************************************* */
2476 /* KEYFRAME DETECTION */
2477
2478 /* --------------- API/Per-Datablock Handling ------------------- */
2479
2480 /* Checks whether an IPO-block has a keyframe for a given frame 
2481  * Since we're only concerned whether a keyframe exists, we can simply loop until a match is found...
2482  */
2483 short action_frame_has_keyframe (bAction *act, float frame, short filter)
2484 {
2485         FCurve *fcu;
2486         
2487         /* can only find if there is data */
2488         if (act == NULL)
2489                 return 0;
2490                 
2491         /* if only check non-muted, check if muted */
2492         if ((filter & ANIMFILTER_KEYS_MUTED) || (act->flag & ACT_MUTED))
2493                 return 0;
2494         
2495         /* loop over F-Curves, using binary-search to try to find matches 
2496          *      - this assumes that keyframes are only beztriples
2497          */
2498         for (fcu= act->curves.first; fcu; fcu= fcu->next) {
2499                 /* only check if there are keyframes (currently only of type BezTriple) */
2500                 if (fcu->bezt && fcu->totvert) {
2501                         /* we either include all regardless of muting, or only non-muted  */
2502                         if ((filter & ANIMFILTER_KEYS_MUTED) || (fcu->flag & FCURVE_MUTED)==0) {
2503                                 short replace = -1;
2504                                 int i = binarysearch_bezt_index(fcu->bezt, frame, fcu->totvert, &replace);
2505                                 
2506                                 /* binarysearch_bezt_index will set replace to be 0 or 1
2507                                  *      - obviously, 1 represents a match
2508                                  */
2509                                 if (replace) {                  
2510                                         /* sanity check: 'i' may in rare cases exceed arraylen */
2511                                         if ((i >= 0) && (i < fcu->totvert))
2512                                                 return 1;
2513                                 }
2514                         }
2515                 }
2516         }
2517         
2518         /* nothing found */
2519         return 0;
2520 }
2521
2522 /* Checks whether an Object has a keyframe for a given frame */
2523 short object_frame_has_keyframe (Object *ob, float frame, short filter)
2524 {
2525         /* error checking */
2526         if (ob == NULL)
2527                 return 0;
2528         
2529         /* check own animation data - specifically, the action it contains */
2530         if ((ob->adt) && (ob->adt->action)) {
2531                 if (action_frame_has_keyframe(ob->adt->action, frame, filter))
2532                         return 1;
2533         }
2534         
2535         /* try shapekey keyframes (if available, and allowed by filter) */
2536         if ( !(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOSKEY) ) {
2537                 Key *key= ob_get_key(ob);
2538                 
2539                 /* shapekeys can have keyframes ('Relative Shape Keys') 
2540                  * or depend on time (old 'Absolute Shape Keys') 
2541                  */
2542                  
2543                         /* 1. test for relative (with keyframes) */
2544                 if (id_frame_has_keyframe((ID *)key, frame, filter))
2545                         return 1;
2546                         
2547                         /* 2. test for time */
2548                 // TODO... yet to be implemented (this feature may evolve before then anyway)
2549         }
2550         
2551         /* try materials */
2552         if ( !(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOMAT) ) {
2553                 /* if only active, then we can skip a lot of looping */
2554                 if (filter & ANIMFILTER_KEYS_ACTIVE) {
2555                         Material *ma= give_current_material(ob, (ob->actcol + 1));
2556                         
2557                         /* we only retrieve the active material... */
2558                         if (id_frame_has_keyframe((ID *)ma, frame, filter))
2559                                 return 1;
2560                 }
2561                 else {
2562                         int a;
2563                         
2564                         /* loop over materials */
2565                         for (a=0; a<ob->totcol; a++) {
2566                                 Material *ma= give_current_material(ob, a+1);
2567                                 
2568                                 if (id_frame_has_keyframe((ID *)ma, frame, filter))
2569                                         return 1;
2570                         }
2571                 }
2572         }
2573         
2574         /* nothing found */
2575         return 0;
2576 }
2577
2578 /* --------------- API ------------------- */
2579
2580 /* Checks whether a keyframe exists for the given ID-block one the given frame */
2581 short id_frame_has_keyframe (ID *id, float frame, short filter)
2582 {
2583         /* sanity checks */
2584         if (id == NULL)
2585                 return 0;
2586         
2587         /* perform special checks for 'macro' types */
2588         switch (GS(id->name)) {
2589                 case ID_OB: /* object */
2590                         return object_frame_has_keyframe((Object *)id, frame, filter);
2591                         break;
2592                         
2593                 case ID_SCE: /* scene */
2594                 // XXX TODO... for now, just use 'normal' behaviour
2595                 //      break;
2596                 
2597                 default:        /* 'normal type' */
2598                 {
2599                         AnimData *adt= BKE_animdata_from_id(id);
2600                         
2601                         /* only check keyframes in active action */
2602                         if (adt)
2603                                 return action_frame_has_keyframe(adt->action, frame, filter);
2604                 }
2605                         break;
2606         }
2607         
2608         
2609         /* no keyframe found */
2610         return 0;
2611 }
2612
2613 /* ************************************************** */