KeyingSets: Added two operators which wrap the internal (blenkernel) KeyingSets API...
[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 /* KEYINGSETS */
874
875 /* Operators ------------------------------------------- */
876
877 /* These operators are only provided for scripting/macro usage, not for direct
878  * calling from the UI since they wrap some of the data-access API code for these
879  * (defined in blenkernel) which have quite a few properties.
880  */
881
882 /* ----- */
883
884 static int keyingset_add_destination_exec (bContext *C, wmOperator *op)
885 {
886         //PointerRNA *ptr;
887         KeyingSet *ks= NULL;
888         ID *id= NULL;
889         char rna_path[256], group_name[64]; // xxx
890         short groupmode=0, flag=0;
891         int array_index=0;
892         
893         /* get settings from operator properties */
894 #if 0 // XXX - why can't we have something like this in the RNA-access API?
895         if ( (ptr = RNA_property_pointer_get(op->ptr, "keyingset")) )
896                 ks= (KeyingSet *)ptr->data;
897         if ( (ptr = RNA_property_pointer_get(op->ptr, "id")) )
898                 id= (ID *)ptr->id;
899 #endif 
900         
901         groupmode= RNA_enum_get(op->ptr, "grouping_method");
902         RNA_string_get(op->ptr, "group_name", group_name);              
903         
904         RNA_string_get(op->ptr, "rna_path", rna_path);
905         array_index= RNA_int_get(op->ptr, "array_index");
906         
907         if (RNA_boolean_get(op->ptr, "entire_array"))
908                 flag |= KSP_FLAG_WHOLE_ARRAY;
909         
910         /* if enough args are provided, call API method */
911         if (ks) {
912                 BKE_keyingset_add_destination(ks, id, group_name, rna_path, array_index, flag, groupmode);
913                 return OPERATOR_FINISHED;
914         }
915         else {
916                 BKE_report(op->reports, RPT_ERROR, "Keying Set could not be added.");
917                 return OPERATOR_CANCELLED;
918         }       
919 }
920
921 void ANIM_OT_keyingset_add_destination (wmOperatorType *ot)
922 {
923         // XXX: this is also defined in rna_animation.c
924         static EnumPropertyItem prop_mode_grouping_items[] = {
925                 {KSP_GROUP_NAMED, "NAMED", "Named Group", ""},
926                 {KSP_GROUP_NONE, "NONE", "None", ""},
927                 {KSP_GROUP_KSNAME, "KEYINGSET", "Keying Set Name", ""},
928                 {0, NULL, NULL, NULL}};
929         
930         /* identifiers */
931         ot->name= "Add Keying Set Destination";
932         ot->idname= "ANIM_OT_keyingset_add_destination";
933         
934         /* callbacks */
935         ot->exec= keyingset_add_destination_exec;
936         ot->poll= ED_operator_scene_editable;
937         
938         /* props */
939                 /* pointers */ // xxx - do we want to directly expose these?
940         RNA_def_pointer_runtime(ot->srna, "keyingset", &RNA_KeyingSet, "Keying Set", "Keying Set to add destination to.");
941         RNA_def_pointer_runtime(ot->srna, "id", &RNA_ID, "ID", "ID-block for the destination.");
942                 /* grouping */
943         RNA_def_enum(ot->srna, "grouping_method", prop_mode_grouping_items, KSP_GROUP_NAMED, "Grouping Method", "Method used to define which Group-name to use.");
944         RNA_def_string(ot->srna, "group_name", "", 64, "Group Name", "Name of Action Group to assign destination to (only if grouping mode is to use this name).");
945                 /* rna-path */
946         RNA_def_string(ot->srna, "rna_path", "", 256, "RNA-Path", "RNA-Path to destination property."); // xxx hopefully this is long enough
947         RNA_def_int(ot->srna, "array_index", 0, 0, INT_MAX, "Array Index", "If applicable, the index ", 0, INT_MAX);
948                 /* flags */
949         RNA_def_boolean(ot->srna, "entire_array", 1, "Entire Array", "hen an 'array/vector' type is chosen (Location, Rotation, Color, etc.), entire array is to be used.");
950         
951 }
952  
953 /* ----- */
954
955 static int keyingset_add_new_exec (bContext *C, wmOperator *op)
956 {
957         Scene *sce= CTX_data_scene(C);
958         KeyingSet *ks= NULL;
959         short flag=0, keyingflag=0;
960         char name[64];
961         
962         /* get settings from operator properties */
963         RNA_string_get(op->ptr, "name", name);
964         
965         if (RNA_boolean_get(op->ptr, "absolute"))
966                 flag |= KEYINGSET_ABSOLUTE;
967         if (RNA_boolean_get(op->ptr, "insertkey_needed"))
968                 keyingflag |= INSERTKEY_NEEDED;
969         if (RNA_boolean_get(op->ptr, "insertkey_visual"))
970                 keyingflag |= INSERTKEY_MATRIX;
971                 
972         /* call the API func, and set the active keyingset index */
973         ks= BKE_keyingset_add(&sce->keyingsets, name, flag, keyingflag);
974         
975         if (ks) {
976                 sce->active_keyingset= BLI_countlist(&sce->keyingsets);
977                 return OPERATOR_FINISHED;
978         }
979         else {
980                 BKE_report(op->reports, RPT_ERROR, "Keying Set could not be added.");
981                 return OPERATOR_CANCELLED;
982         }
983 }
984
985 void ANIM_OT_keyingset_add_new (wmOperatorType *ot)
986 {
987         /* identifiers */
988         ot->name= "Add Keying Set";
989         ot->idname= "ANIM_OT_keyingset_add_new";
990         
991         /* callbacks */
992         ot->exec= keyingset_add_new_exec;
993         ot->poll= ED_operator_scene_editable;
994         
995         /* props */
996                 /* name */
997         RNA_def_string(ot->srna, "name", "KeyingSet", 64, "Name", "Name of Keying Set");
998                 /* flags */
999         RNA_def_boolean(ot->srna, "absolute", 1, "Absolute", "Keying Set defines specifc paths/settings to be keyframed (i.e. is not reliant on context info)");
1000                 /* keying flags */
1001         RNA_def_boolean(ot->srna, "insertkey_needed", 0, "Insert Keyframes - Only Needed", "Only insert keyframes where they're needed in the relevant F-Curves.");
1002         RNA_def_boolean(ot->srna, "insertkey_visual", 0, "Insert Keyframes - Visual", "Insert keyframes based on 'visual transforms'.");
1003 }
1004
1005 /* UI API --------------------------------------------- */
1006
1007 /* Build menu-string of available keying-sets (allocates memory for string)
1008  * NOTE: mode must not be longer than 64 chars
1009  */
1010 char *ANIM_build_keyingsets_menu (ListBase *list, short for_edit)
1011 {
1012         DynStr *pupds= BLI_dynstr_new();
1013         KeyingSet *ks;
1014         char buf[64];
1015         char *str;
1016         int i;
1017         
1018         /* add title first */
1019         BLI_dynstr_append(pupds, "Keying Sets%t|");
1020         
1021         /* add dummy entries for none-active */
1022         if (for_edit) { 
1023                 BLI_dynstr_append(pupds, "Add New%x-1|");
1024                 BLI_dynstr_append(pupds, " %x0|");
1025         }
1026         else
1027                 BLI_dynstr_append(pupds, "<No Keying Set Active>%x0|");
1028         
1029         /* loop through keyingsets, adding them */
1030         for (ks=list->first, i=1; ks; ks=ks->next, i++) {
1031                 if (for_edit == 0)
1032                         BLI_dynstr_append(pupds, "KS: ");
1033                 
1034                 BLI_dynstr_append(pupds, ks->name);
1035                 BLI_snprintf( buf, 64, "%%x%d%s", i, ((ks->next)?"|":"") );
1036                 BLI_dynstr_append(pupds, buf);
1037         }
1038         
1039         /* convert to normal MEM_malloc'd string */
1040         str= BLI_dynstr_get_cstring(pupds);
1041         BLI_dynstr_free(pupds);
1042         
1043         return str;
1044 }
1045
1046
1047
1048 /* ******************************************* */
1049 /* KEYFRAME MODIFICATION */
1050
1051 /* mode for common_modifykey */
1052 enum {
1053         COMMONKEY_MODE_INSERT = 0,
1054         COMMONKEY_MODE_DELETE,
1055 } eCommonModifyKey_Modes;
1056
1057 #if 0 // XXX old keyingsets code based on adrcodes... to be restored in due course
1058
1059 /* --------- KeyingSet Adrcode Getters ------------ */
1060
1061 /* initialise a channel-getter storage */
1062 static void ks_adrcodegetter_init (bKS_AdrcodeGetter *kag, bKeyingSet *ks, bCommonKeySrc *cks)
1063 {
1064         /* error checking */
1065         if (kag == NULL)
1066                 return;
1067         
1068         if (ELEM(NULL, ks, cks)) {
1069                 /* set invalid settings that won't cause harm */
1070                 kag->ks= NULL;
1071                 kag->cks= NULL;
1072                 kag->index= -2;
1073                 kag->tot= 0;
1074         }
1075         else {
1076                 /* store settings */
1077                 kag->ks= ks;
1078                 kag->cks= cks;
1079                 
1080                 /* - index is -1, as that allows iterators to return first element
1081                  * - tot is chan_num by default, but may get overriden if -1 is encountered (for extension-type getters)
1082                  */
1083                 kag->index= -1;
1084                 kag->tot= ks->chan_num;
1085         }
1086 }
1087
1088 /* 'default' channel-getter that will be used when iterating through keyingset's channels 
1089  *       - iteration will stop when adrcode <= 0 is encountered, so we use that as escape
1090  */
1091 static short ks_getnextadrcode_default (bKS_AdrcodeGetter *kag)
1092 {       
1093         bKeyingSet *ks= (kag)? kag->ks : NULL;
1094         
1095         /* error checking */
1096         if (ELEM(NULL, kag, ks)) return 0;
1097         if (kag->tot <= 0) return 0;
1098         
1099         kag->index++;
1100         if ((kag->index < 0) || (kag->index >= kag->tot)) return 0;
1101         
1102         /* return the adrcode stored at index then */
1103         return ks->adrcodes[kag->index];
1104 }
1105
1106 /* add map flag (for MTex channels, as certain ones need special offset) */
1107 static short ks_getnextadrcode_addmap (bKS_AdrcodeGetter *kag)
1108 {
1109         short adrcode= ks_getnextadrcode_default(kag);
1110         
1111         /* if there was an adrcode returned, assume that kag stuff is set ok */
1112         if (adrcode) {
1113                 bCommonKeySrc *cks= kag->cks;
1114                 bKeyingSet *ks= kag->ks;
1115                 
1116                 if (ELEM3(ks->blocktype, ID_MA, ID_LA, ID_WO)) {
1117                         switch (adrcode) {
1118                                 case MAP_OFS_X: case MAP_OFS_Y: case MAP_OFS_Z:
1119                                 case MAP_SIZE_X: case MAP_SIZE_Y: case MAP_SIZE_Z:
1120                                 case MAP_R: case MAP_G: case MAP_B: case MAP_DVAR:
1121                                 case MAP_COLF: case MAP_NORF: case MAP_VARF: case MAP_DISP:
1122                                         adrcode += cks->map;
1123                                         break;
1124                         }
1125                 }
1126         }
1127         
1128         /* adrcode must be returned! */
1129         return adrcode;
1130 }
1131
1132 /* extend posechannel keyingsets with rotation info (when KAG_CHAN_EXTEND is encountered) 
1133  *      - iteration will stop when adrcode <= 0 is encountered, so we use that as escape
1134  *      - when we encounter KAG_CHAN_EXTEND as adrcode, start returning our own
1135  */
1136 static short ks_getnextadrcode_pchanrot (bKS_AdrcodeGetter *kag)
1137 {       
1138         /* hardcoded adrcode channels used here only 
1139          *      - length is keyed-channels + 1 (last item must be 0 to escape)
1140          */
1141         static short quat_adrcodes[5] = {AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z, 0};
1142         static short eul_adrcodes[4] = {AC_EUL_X, AC_EUL_Y, AC_EUL_Z, 0};
1143                 
1144         /* useful variables */
1145         bKeyingSet *ks= (kag)? kag->ks : NULL;
1146         bCommonKeySrc *cks= (kag) ? kag->cks : NULL;
1147         short index, adrcode;
1148         
1149         /* error checking */
1150         if (ELEM3(NULL, kag, ks, cks)) return 0;
1151         if (ks->chan_num <= 0) return 0;
1152         
1153         /* get index 
1154          *      - if past the last item (kag->tot), return stuff from our static arrays
1155          *      - otherwise, just keep returning stuff from the keyingset (but check out for -1!) 
1156          */
1157         kag->index++;
1158         if (kag->index < 0)
1159                 return 0;
1160         
1161         /* normal (static stuff) */
1162         if (kag->index < kag->tot) {
1163                 /* get adrcode, and return if not KAG_CHAN_EXTEND (i.e. point for start of iteration) */
1164                 adrcode= ks->adrcodes[kag->index];
1165                 
1166                 if (adrcode != KAG_CHAN_EXTEND) 
1167                         return adrcode;
1168                 else    
1169                         kag->tot= kag->index;
1170         }
1171                 
1172         /* based on current rotation-mode
1173          *      - index can be at most 5, if we are to prevent segfaults
1174          */
1175         index= kag->index - kag->tot;
1176         if ((index < 0) || (index > 5))
1177                 return 0;
1178         
1179         if (cks->pchan && cks->pchan->rotmode)
1180                 return eul_adrcodes[index];
1181         else
1182                 return quat_adrcodes[index];
1183 }
1184
1185 /* ------------- KeyingSet Defines ------------ */
1186 /* Note: these must all be named with the defks_* prefix, otherwise the template macro will not work! */
1187
1188 /* macro for defining keyingset contexts */
1189 #define KSC_TEMPLATE(ctx_name) {&defks_##ctx_name[0], NULL, sizeof(defks_##ctx_name)/sizeof(bKeyingSet)}
1190
1191 /* --- */
1192
1193 /* check if option not available for deleting keys */
1194 static short incl_non_del_keys (bKeyingSet *ks, const char mode[])
1195 {
1196         /* as optimisation, assume that it is sufficient to check only first letter
1197          * of mode (int comparison should be faster than string!)
1198          */
1199         //if (strcmp(mode, "Delete")==0)
1200         if (mode && mode[0]=='D')
1201                 return 0;
1202         
1203         return 1;
1204 }
1205
1206 /* Object KeyingSets  ------ */
1207
1208 /* check if include shapekey entry  */
1209 static short incl_v3d_ob_shapekey (bKeyingSet *ks, const char mode[])
1210 {
1211         //Object *ob= (G.obedit)? (G.obedit) : (OBACT); // XXX
1212         Object *ob= NULL;
1213         char *newname= NULL;
1214         
1215         if(ob==NULL)
1216                 return 0;
1217         
1218         /* not available for delete mode */
1219         if (strcmp(mode, "Delete")==0)
1220                 return 0;
1221         
1222         /* check if is geom object that can get shapekeys */
1223         switch (ob->type) {
1224                 /* geometry? */
1225                 case OB_MESH:           newname= "Mesh";                break;
1226                 case OB_CURVE:          newname= "Curve";               break;
1227                 case OB_SURF:           newname= "Surface";             break;
1228                 case OB_LATTICE:        newname= "Lattice";             break;
1229                 
1230                 /* not geometry! */
1231                 default:
1232                         return 0;
1233         }
1234         
1235         /* if ks is shapekey entry (this could be callled for separator before too!) */
1236         if (ks->flag == -3)
1237                 BLI_strncpy(ks->name, newname, sizeof(ks->name));
1238         
1239         /* if it gets here, it's ok */
1240         return 1;
1241 }
1242
1243 /* array for object keyingset defines */
1244 bKeyingSet defks_v3d_object[] = 
1245 {
1246         /* include_cb, adrcode-getter, name, blocktype, flag, chan_num, adrcodes */
1247         {NULL, "Loc", ID_OB, 0, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}},
1248         {NULL, "Rot", ID_OB, 0, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
1249         {NULL, "Scale", ID_OB, 0, 3, {OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
1250         
1251         {NULL, "%l", 0, -1, 0, {0}}, // separator
1252         
1253         {NULL, "LocRot", ID_OB, 0, 6, 
1254                 {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
1255                  OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
1256                  
1257         {NULL, "LocScale", ID_OB, 0, 6, 
1258                 {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
1259                  OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
1260                  
1261         {NULL, "LocRotScale", ID_OB, 0, 9, 
1262                 {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
1263                  OB_ROT_X,OB_ROT_Y,OB_ROT_Z,
1264                  OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
1265                  
1266         {NULL, "RotScale", ID_OB, 0, 6, 
1267                 {OB_ROT_X,OB_ROT_Y,OB_ROT_Z,
1268                  OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
1269         
1270         {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator
1271         
1272         {incl_non_del_keys, "VisualLoc", ID_OB, INSERTKEY_MATRIX, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}},
1273         {incl_non_del_keys, "VisualRot", ID_OB, INSERTKEY_MATRIX, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
1274         
1275         {incl_non_del_keys, "VisualLocRot", ID_OB, INSERTKEY_MATRIX, 6, 
1276                 {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
1277                  OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
1278         
1279         {NULL, "%l", 0, -1, 0, {0}}, // separator
1280         
1281         {NULL, "Layer", ID_OB, 0, 1, {OB_LAY}}, // icky option...
1282         {NULL, "Available", ID_OB, -2, 0, {0}},
1283         
1284         {incl_v3d_ob_shapekey, "%l%l", 0, -1, 0, {0}}, // separator (linked to shapekey entry)
1285         {incl_v3d_ob_shapekey, "<ShapeKey>", ID_OB, -3, 0, {0}}
1286 };
1287
1288 /* PoseChannel KeyingSets  ------ */
1289
1290 /* array for posechannel keyingset defines */
1291 bKeyingSet defks_v3d_pchan[] = 
1292 {
1293         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
1294         {NULL, "Loc", ID_PO, 0, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}},
1295         {NULL, "Rot", ID_PO, COMMONKEY_PCHANROT, 1, {KAG_CHAN_EXTEND}},
1296         {NULL, "Scale", ID_PO, 0, 3, {AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}},
1297         
1298         {NULL, "%l", 0, -1, 0, {0}}, // separator
1299         
1300         {NULL, "LocRot", ID_PO, COMMONKEY_PCHANROT, 4, 
1301                 {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,
1302                  KAG_CHAN_EXTEND}},
1303                  
1304         {NULL, "LocScale", ID_PO, 0, 6, 
1305                 {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,
1306                  AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}},
1307                  
1308         {NULL, "LocRotScale", ID_PO, COMMONKEY_PCHANROT, 7, 
1309                 {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z, 
1310                  KAG_CHAN_EXTEND}},
1311                  
1312         {NULL, "RotScale", ID_PO, 0, 4, 
1313                 {AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z, 
1314                  KAG_CHAN_EXTEND}},
1315         
1316         {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator
1317         
1318         {incl_non_del_keys, "VisualLoc", ID_PO, INSERTKEY_MATRIX, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}},
1319         {incl_non_del_keys, "VisualRot", ID_PO, INSERTKEY_MATRIX|COMMONKEY_PCHANROT, 1, {KAG_CHAN_EXTEND}},
1320         
1321         {incl_non_del_keys, "VisualLocRot", ID_PO, INSERTKEY_MATRIX|COMMONKEY_PCHANROT, 4, 
1322                 {AC_LOC_X,AC_LOC_Y,AC_LOC_Z, KAG_CHAN_EXTEND}},
1323         
1324         {NULL, "%l", 0, -1, 0, {0}}, // separator
1325         
1326         {NULL, "Available", ID_PO, -2, 0, {0}}
1327 };
1328
1329 /* Material KeyingSets  ------ */
1330
1331 /* array for material keyingset defines */
1332 bKeyingSet defks_buts_shading_mat[] = 
1333 {
1334         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
1335         {NULL, "RGB", ID_MA, 0, 3, {MA_COL_R,MA_COL_G,MA_COL_B}},
1336         {NULL, "Alpha", ID_MA, 0, 1, {MA_ALPHA}},
1337         {NULL, "Halo Size", ID_MA, 0, 1, {MA_HASIZE}},
1338         {NULL, "Mode", ID_MA, 0, 1, {MA_MODE}}, // evil bitflags
1339         
1340         {NULL, "%l", 0, -1, 0, {0}}, // separator
1341         
1342         {NULL, "All Color", ID_MA, 0, 18, 
1343                 {MA_COL_R,MA_COL_G,MA_COL_B,
1344                  MA_ALPHA,MA_HASIZE, MA_MODE,
1345                  MA_SPEC_R,MA_SPEC_G,MA_SPEC_B,
1346                  MA_REF,MA_EMIT,MA_AMB,MA_SPEC,MA_HARD,
1347                  MA_MODE,MA_TRANSLU,MA_ADD}},
1348                  
1349         {NULL, "All Mirror", ID_MA, 0, 5, 
1350                 {MA_RAYM,MA_FRESMIR,MA_FRESMIRI,
1351                  MA_FRESTRA,MA_FRESTRAI}},
1352         
1353         {NULL, "%l", 0, -1, 0, {0}}, // separator
1354         
1355         {NULL, "Ofs", ID_MA, COMMONKEY_ADDMAP, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
1356         {NULL, "Size", ID_MA, COMMONKEY_ADDMAP, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
1357         
1358         {NULL, "All Mapping", ID_MA, COMMONKEY_ADDMAP, 14, 
1359                 {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
1360                  MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
1361                  MAP_R,MAP_G,MAP_B,MAP_DVAR,
1362                  MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
1363         
1364         {NULL, "%l", 0, -1, 0, {0}}, // separator
1365         
1366         {NULL, "Available", ID_MA, -2, 0, {0}}
1367 };
1368
1369 /* World KeyingSets  ------ */
1370
1371 /* array for world keyingset defines */
1372 bKeyingSet defks_buts_shading_wo[] = 
1373 {
1374         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
1375         {NULL, "Zenith RGB", ID_WO, 0, 3, {WO_ZEN_R,WO_ZEN_G,WO_ZEN_B}},
1376         {NULL, "Horizon RGB", ID_WO, 0, 3, {WO_HOR_R,WO_HOR_G,WO_HOR_B}},
1377         
1378         {NULL, "%l", 0, -1, 0, {0}}, // separator
1379         
1380         {NULL, "Mist", ID_WO, 0, 4, {WO_MISI,WO_MISTDI,WO_MISTSTA,WO_MISTHI}},
1381         {NULL, "Stars", ID_WO, 0, 5, {WO_STAR_R,WO_STAR_G,WO_STAR_B,WO_STARDIST,WO_STARSIZE}},
1382         
1383         
1384         {NULL, "%l", 0, -1, 0, {0}}, // separator
1385         
1386         {NULL, "Ofs", ID_WO, COMMONKEY_ADDMAP, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
1387         {NULL, "Size", ID_WO, COMMONKEY_ADDMAP, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
1388         
1389         {NULL, "All Mapping", ID_WO, COMMONKEY_ADDMAP, 14, 
1390                 {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
1391                  MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
1392                  MAP_R,MAP_G,MAP_B,MAP_DVAR,
1393                  MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
1394         
1395         {NULL, "%l", 0, -1, 0, {0}}, // separator
1396         
1397         {NULL, "Available", ID_WO, -2, 0, {0}}
1398 };
1399
1400 /* Lamp KeyingSets  ------ */
1401
1402 /* array for lamp keyingset defines */
1403 bKeyingSet defks_buts_shading_la[] = 
1404 {
1405         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
1406         {NULL, "RGB", ID_LA, 0, 3, {LA_COL_R,LA_COL_G,LA_COL_B}},
1407         {NULL, "Energy", ID_LA, 0, 1, {LA_ENERGY}},
1408         {NULL, "Spot Size", ID_LA, 0, 1, {LA_SPOTSI}},
1409         
1410         {NULL, "%l", 0, -1, 0, {0}}, // separator
1411         
1412         {NULL, "Ofs", ID_LA, COMMONKEY_ADDMAP, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
1413         {NULL, "Size", ID_LA, COMMONKEY_ADDMAP, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
1414         
1415         {NULL, "All Mapping", ID_LA, COMMONKEY_ADDMAP, 14, 
1416                 {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
1417                  MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
1418                  MAP_R,MAP_G,MAP_B,MAP_DVAR,
1419                  MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
1420         
1421         {NULL, "%l", 0, -1, 0, {0}}, // separator
1422         
1423         {NULL, "Available", ID_LA, -2, 0, {0}}
1424 };
1425
1426 /* Texture KeyingSets  ------ */
1427
1428 /* array for texture keyingset defines */
1429 bKeyingSet defks_buts_shading_tex[] = 
1430 {
1431         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
1432         {NULL, "Clouds", ID_TE, 0, 5, 
1433                 {TE_NSIZE,TE_NDEPTH,TE_NTYPE,
1434                  TE_MG_TYP,TE_N_BAS1}},
1435         
1436         {NULL, "Marble", ID_TE, 0, 7, 
1437                 {TE_NSIZE,TE_NDEPTH,TE_NTYPE,
1438                  TE_TURB,TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}},
1439                  
1440         {NULL, "Stucci", ID_TE, 0, 5, 
1441                 {TE_NSIZE,TE_NTYPE,TE_TURB,
1442                  TE_MG_TYP,TE_N_BAS1}},
1443                  
1444         {NULL, "Wood", ID_TE, 0, 6, 
1445                 {TE_NSIZE,TE_NTYPE,TE_TURB,
1446                  TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}},
1447                  
1448         {NULL, "Magic", ID_TE, 0, 2, {TE_NDEPTH,TE_TURB}},
1449         
1450         {NULL, "Blend", ID_TE, 0, 1, {TE_MG_TYP}},      
1451                 
1452         {NULL, "Musgrave", ID_TE, 0, 6, 
1453                 {TE_MG_TYP,TE_MGH,TE_MG_LAC,
1454                  TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN}},
1455                  
1456         {NULL, "Voronoi", ID_TE, 0, 9, 
1457                 {TE_VNW1,TE_VNW2,TE_VNW3,TE_VNW4,
1458                 TE_VNMEXP,TE_VN_DISTM,TE_VN_COLT,
1459                 TE_ISCA,TE_NSIZE}},
1460                 
1461         {NULL, "Distorted Noise", ID_TE, 0, 4, 
1462                 {TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN,TE_DISTA}},
1463         
1464         {NULL, "Color Filter", ID_TE, 0, 5, 
1465                 {TE_COL_R,TE_COL_G,TE_COL_B,TE_BRIGHT,TE_CONTRA}},
1466         
1467         {NULL, "%l", 0, -1, 0, {0}}, // separator
1468         
1469         {NULL, "Available", ID_TE, -2, 0, {0}}
1470 };
1471
1472 /* Object Buttons KeyingSets  ------ */
1473
1474 /* check if include particles entry  */
1475 static short incl_buts_ob (bKeyingSet *ks, const char mode[])
1476 {
1477         //Object *ob= OBACT; // xxx
1478         Object *ob= NULL;
1479         /* only if object is mesh type */
1480         
1481         if(ob==NULL) return 0;
1482         return (ob->type == OB_MESH);
1483 }
1484
1485 /* array for texture keyingset defines */
1486 bKeyingSet defks_buts_object[] = 
1487 {
1488         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
1489         {incl_buts_ob, "Surface Damping", ID_OB, 0, 1, {OB_PD_SDAMP}},
1490         {incl_buts_ob, "Random Damping", ID_OB, 0, 1, {OB_PD_RDAMP}},
1491         {incl_buts_ob, "Permeability", ID_OB, 0, 1, {OB_PD_PERM}},
1492         
1493         {NULL, "%l", 0, -1, 0, {0}}, // separator
1494         
1495         {NULL, "Force Strength", ID_OB, 0, 1, {OB_PD_FSTR}},
1496         {NULL, "Force Falloff", ID_OB, 0, 1, {OB_PD_FFALL}},
1497         
1498         {NULL, "%l", 0, -1, 0, {0}}, // separator
1499         
1500         {NULL, "Available", ID_OB, -2, 0, {0}}  // this will include ob-transforms too!
1501 };
1502
1503 /* Camera Buttons KeyingSets  ------ */
1504
1505 /* check if include internal-renderer entry  */
1506 static short incl_buts_cam1 (bKeyingSet *ks, const char mode[])
1507 {
1508         Scene *scene= NULL; // FIXME this will cause a crash, but we need an extra arg first!
1509         /* only if renderer is internal renderer */
1510         return (scene->r.renderer==R_INTERN);
1511 }
1512
1513 /* check if include external-renderer entry  */
1514 static short incl_buts_cam2 (bKeyingSet *ks, const char mode[])
1515 {
1516         Scene *scene= NULL; // FIXME this will cause a crash, but we need an extra arg first!
1517         /* only if renderer is internal renderer */
1518         return (scene->r.renderer!=R_INTERN);
1519 }
1520
1521 /* array for camera keyingset defines */
1522 bKeyingSet defks_buts_cam[] = 
1523 {
1524         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
1525         {NULL, "Lens", ID_CA, 0, 1, {CAM_LENS}},
1526         {NULL, "Clipping", ID_CA, 0, 2, {CAM_STA,CAM_END}},
1527         {NULL, "Focal Distance", ID_CA, 0, 1, {CAM_YF_FDIST}},
1528         
1529         {NULL, "%l", 0, -1, 0, {0}}, // separator
1530         
1531         
1532         {incl_buts_cam2, "Aperture", ID_CA, 0, 1, {CAM_YF_APERT}},
1533         {incl_buts_cam1, "Viewplane Shift", ID_CA, 0, 2, {CAM_SHIFT_X,CAM_SHIFT_Y}},
1534         
1535         {NULL, "%l", 0, -1, 0, {0}}, // separator
1536         
1537         {NULL, "Available", ID_CA, -2, 0, {0}}
1538 };
1539
1540 /* --- */
1541
1542 /* Keying Context Defines - Must keep in sync with enumeration (eKS_Contexts) */
1543 bKeyingContext ks_contexts[] = 
1544 {
1545         KSC_TEMPLATE(v3d_object),
1546         KSC_TEMPLATE(v3d_pchan),
1547         
1548         KSC_TEMPLATE(buts_shading_mat),
1549         KSC_TEMPLATE(buts_shading_wo),
1550         KSC_TEMPLATE(buts_shading_la),
1551         KSC_TEMPLATE(buts_shading_tex),
1552
1553         KSC_TEMPLATE(buts_object),
1554         KSC_TEMPLATE(buts_cam)
1555 };
1556
1557 /* Keying Context Enumeration - Must keep in sync with definitions*/
1558 typedef enum eKS_Contexts {
1559         KSC_V3D_OBJECT = 0,
1560         KSC_V3D_PCHAN,
1561         
1562         KSC_BUTS_MAT,
1563         KSC_BUTS_WO,
1564         KSC_BUTS_LA,
1565         KSC_BUTS_TEX,
1566         
1567         KSC_BUTS_OB,
1568         KSC_BUTS_CAM,
1569         
1570                 /* make sure this last one remains untouched! */
1571         KSC_TOT_TYPES
1572 } eKS_Contexts;
1573
1574
1575 /* ---------------- KeyingSet Tools ------------------- */
1576
1577 /* helper for commonkey_context_get() -  get keyingsets for 3d-view */
1578 static void commonkey_context_getv3d (const bContext *C, ListBase *sources, bKeyingContext **ksc)
1579 {
1580         Scene *scene= CTX_data_scene(C);
1581         Object *ob;
1582         IpoCurve *icu;
1583         
1584         if ((OBACT) && (OBACT->flag & OB_POSEMODE)) {
1585                 bPoseChannel *pchan;
1586                 
1587                 /* pose-level */
1588                 ob= OBACT;
1589                 *ksc= &ks_contexts[KSC_V3D_PCHAN];
1590                         // XXX
1591                 //set_pose_keys(ob);  /* sets pchan->flag to POSE_KEY if bone selected, and clears if not */
1592                 
1593                 /* loop through posechannels */
1594                 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
1595                         if (pchan->flag & POSE_KEY) {
1596                                 bCommonKeySrc *cks;
1597                                 
1598                                 /* add new keyframing destination */
1599                                 cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1600                                 BLI_addtail(sources, cks);
1601                                 
1602                                 /* set id-block to key to, and action */
1603                                 cks->id= (ID *)ob;
1604                                 cks->act= ob->action;
1605                                 
1606                                 /* set pchan */
1607                                 cks->pchan= pchan;
1608                                 cks->actname= pchan->name;
1609                         }
1610                 }
1611         }
1612         else {
1613                 /* object-level */
1614                 *ksc= &ks_contexts[KSC_V3D_OBJECT];
1615                 
1616                 /* loop through bases */
1617                 // XXX but we're only supposed to do this on editable ones, not just selected ones!
1618                 CTX_DATA_BEGIN(C, Base*, base, selected_bases) {
1619                         bCommonKeySrc *cks;
1620                         
1621                         /* add new keyframing destination */
1622                         cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1623                         BLI_addtail(sources, cks);
1624                         
1625                         /* set id-block to key to */
1626                         ob= base->object;
1627                         cks->id= (ID *)ob;
1628                         
1629                         /* when ob's keyframes are in an action, default to using 'Object' as achan name */
1630                         if (ob->ipoflag & OB_ACTION_OB)
1631                                 cks->actname= "Object";
1632                         
1633                         /* set ipo-flags */
1634                         // TODO: add checks for lib-linked data
1635                         if ((ob->ipo) || (ob->action)) {
1636                                 if (ob->ipo) {
1637                                         cks->ipo= ob->ipo;
1638                                 }
1639                                 else {
1640                                         bActionChannel *achan;
1641                                         
1642                                         cks->act= ob->action;
1643                                         achan= get_action_channel(ob->action, cks->actname);
1644                                         
1645                                         if (achan && achan->ipo)
1646                                                 cks->ipo= achan->ipo;
1647                                 }
1648                                 /* cks->ipo can be NULL while editing */
1649                                 if(cks->ipo) {
1650                                         /* deselect all ipo-curves */
1651                                         for (icu= cks->ipo->curve.first; icu; icu= icu->next) {
1652                                                 icu->flag &= ~IPO_SELECT;
1653                                         }
1654                                 }
1655                         }
1656                 }
1657                 CTX_DATA_END;
1658         }
1659 }
1660
1661 /* helper for commonkey_context_get() -  get keyingsets for buttons window */
1662 static void commonkey_context_getsbuts (const bContext *C, ListBase *sources, bKeyingContext **ksc)
1663 {
1664 #if 0 // XXX dunno what's the future of this stuff...   
1665         bCommonKeySrc *cks;
1666         
1667         /* check on tab-type */
1668         switch (G.buts->mainb) {
1669         case CONTEXT_SHADING:   /* ------------- Shading buttons ---------------- */
1670                 /* subtabs include "Material", "Texture", "Lamp", "World"*/
1671                 switch (G.buts->tab[CONTEXT_SHADING]) {
1672                         case TAB_SHADING_MAT: /* >------------- Material Tab -------------< */
1673                         {
1674                                 Material *ma= editnode_get_active_material(G.buts->lockpoin);
1675                                 
1676                                 if (ma) {
1677                                         /* add new keyframing destination */
1678                                         cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1679                                         BLI_addtail(sources, cks); 
1680                                         
1681                                         /* set data */
1682                                         cks->id= (ID *)ma;
1683                                         cks->ipo= ma->ipo;
1684                                         cks->map= texchannel_to_adrcode(ma->texact);
1685                                         
1686                                         /* set keyingsets */
1687                                         *ksc= &ks_contexts[KSC_BUTS_MAT];
1688                                         return;
1689                                 }
1690                         }
1691                                 break;
1692                         case TAB_SHADING_WORLD: /* >------------- World Tab -------------< */
1693                         {
1694                                 World *wo= G.buts->lockpoin;
1695                                 
1696                                 if (wo) {
1697                                         /* add new keyframing destination */
1698                                         cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1699                                         BLI_addtail(sources, cks); 
1700                                         
1701                                         /* set data */
1702                                         cks->id= (ID *)wo;
1703                                         cks->ipo= wo->ipo;
1704                                         cks->map= texchannel_to_adrcode(wo->texact);
1705                                         
1706                                         /* set keyingsets */
1707                                         *ksc= &ks_contexts[KSC_BUTS_WO];
1708                                         return;
1709                                 }
1710                         }
1711                                 break;
1712                         case TAB_SHADING_LAMP: /* >------------- Lamp Tab -------------< */
1713                         {
1714                                 Lamp *la= G.buts->lockpoin;
1715                                 
1716                                 if (la) {
1717                                         /* add new keyframing destination */
1718                                         cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1719                                         BLI_addtail(sources, cks); 
1720                                         
1721                                         /* set data */
1722                                         cks->id= (ID *)la;
1723                                         cks->ipo= la->ipo;
1724                                         cks->map= texchannel_to_adrcode(la->texact);
1725                                         
1726                                         /* set keyingsets */
1727                                         *ksc= &ks_contexts[KSC_BUTS_LA];
1728                                         return;
1729                                 }
1730                         }
1731                                 break;
1732                         case TAB_SHADING_TEX: /* >------------- Texture Tab -------------< */
1733                         {
1734                                 Tex *tex= G.buts->lockpoin;
1735                                 
1736                                 if (tex) {
1737                                         /* add new keyframing destination */
1738                                         cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1739                                         BLI_addtail(sources, cks); 
1740                                         
1741                                         /* set data */
1742                                         cks->id= (ID *)tex;
1743                                         cks->ipo= tex->ipo;
1744                                         
1745                                         /* set keyingsets */
1746                                         *ksc= &ks_contexts[KSC_BUTS_TEX];
1747                                         return;
1748                                 }
1749                         }
1750                                 break;
1751                 }
1752                 break;
1753         
1754         case CONTEXT_OBJECT:    /* ------------- Object buttons ---------------- */
1755                 {
1756                         Object *ob= OBACT;
1757                         
1758                         if (ob) {
1759                                 /* add new keyframing destination */
1760                                 cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1761                                 BLI_addtail(sources, cks);
1762                                 
1763                                 /* set id-block to key to */
1764                                 cks->id= (ID *)ob;
1765                                 cks->ipo= ob->ipo;
1766                                 
1767                                 /* set keyingsets */
1768                                 *ksc= &ks_contexts[KSC_BUTS_OB];
1769                                 return;
1770                         }
1771                 }
1772                 break;
1773         
1774         case CONTEXT_EDITING:   /* ------------- Editing buttons ---------------- */
1775                 {
1776                         Object *ob= OBACT;
1777                         
1778                         if ((ob) && (ob->type==OB_CAMERA) && (G.buts->lockpoin)) { /* >---------------- camera buttons ---------------< */
1779                                 Camera *ca= G.buts->lockpoin;
1780                                 
1781                                 /* add new keyframing destination */
1782                                 cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1783                                 BLI_addtail(sources, cks);
1784                                 
1785                                 /* set id-block to key to */
1786                                 cks->id= (ID *)ca;
1787                                 cks->ipo= ca->ipo;
1788                                 
1789                                 /* set keyingsets */
1790                                 *ksc= &ks_contexts[KSC_BUTS_CAM];
1791                                 return;
1792                         }
1793                 }
1794                 break;
1795         }
1796 #endif // XXX end of buttons stuff to port...
1797         
1798         /* if nothing happened... */
1799         *ksc= NULL;
1800 }
1801
1802
1803 /* get keyingsets for appropriate context */
1804 static void commonkey_context_get (const bContext *C, ScrArea *sa, short mode, ListBase *sources, bKeyingContext **ksc)
1805 {
1806         /* get current view if no view is defined */
1807         if (sa == NULL)
1808                 sa= CTX_wm_area(C);
1809         
1810         /* check view type */
1811         switch (sa->spacetype) {
1812                 /* 3d view - first one tested as most often used */
1813                 case SPACE_VIEW3D:
1814                 {
1815                         commonkey_context_getv3d(C, sources, ksc);
1816                 }
1817                         break;
1818                         
1819                 /* buttons view */
1820                 case SPACE_BUTS:
1821                 {
1822                         commonkey_context_getsbuts(C, sources, ksc);
1823                 }
1824                         break;
1825                         
1826                 /* spaces with their own methods */
1827                 case SPACE_IPO:
1828                         //if (mode == COMMONKEY_MODE_INSERT)
1829                         //      insertkey_editipo(); // XXX old calls...
1830                         return;
1831                 case SPACE_ACTION:
1832                         //if (mode == COMMONKEY_MODE_INSERT)
1833                         //      insertkey_action(); // XXX old calls...
1834                         return;
1835                         
1836                 /* timeline view - keyframe buttons */
1837                 case SPACE_TIME:
1838                 {
1839                         bScreen *sc= CTX_wm_screen(C);
1840                         ScrArea *sab;
1841                         int bigarea= 0;
1842                         
1843                         /* try to find largest 3d-view available 
1844                          * (mostly of the time, this is what when user will want this,
1845                          *  as it's a standard feature in all other apps) 
1846                          */
1847                         //sab= find_biggest_area_of_type(SPACE_VIEW3D);
1848                         sab= NULL; // XXX for now...
1849                         if (sab) {
1850                                 commonkey_context_getv3d(C, sources, ksc);
1851                                 return;
1852                         }
1853                         
1854                         /* if not found, sab is now NULL, so perform own biggest area test */
1855                         for (sa= sc->areabase.first; sa; sa= sa->next) { // XXX this has changed!
1856                                 int area= sa->winx * sa->winy;
1857                                 
1858                                 if (sa->spacetype != SPACE_TIME) {
1859                                         if ( (!sab) || (area > bigarea) ) {
1860                                                 sab= sa;
1861                                                 bigarea= area;
1862                                         }
1863                                 }
1864                         }
1865                         
1866                         /* use whichever largest area was found (it shouldn't be a time window) */
1867                         if (sab)
1868                                 commonkey_context_get(C, sab, mode, sources, ksc);
1869                 }
1870                         break;
1871         }
1872 }
1873
1874 /* flush updates after all operations */
1875 static void commonkey_context_finish (const bContext *C, ListBase *sources)
1876 {
1877         ScrArea *curarea= CTX_wm_area(C);
1878         Scene *scene= CTX_data_scene(C);
1879         
1880         /* check view type */
1881         switch (curarea->spacetype) {
1882                 /* 3d view - first one tested as most often used */
1883                 case SPACE_VIEW3D:
1884                 {
1885                         /* either pose or object level */
1886                         if (OBACT && (OBACT->pose)) {   
1887                                 //Object *ob= OBACT;
1888                                 
1889                                 /* recalculate ipo handles, etc. */
1890                                 // XXX this method has been removed!
1891                                 //if (ob->action)
1892                                 //      remake_action_ipos(ob->action);
1893                                 
1894                                 /* recalculate bone-paths on adding new keyframe? */
1895                                 // XXX missing function
1896                                 // TODO: currently, there is no setting to turn this on/off globally
1897                                 //if (ob->pose->flag & POSE_RECALCPATHS)
1898                                 //      pose_recalculate_paths(ob);
1899                         }
1900                         else {
1901                                 bCommonKeySrc *cks;
1902                                 
1903                                 /* loop over bases (as seen in sources) */
1904                                 for (cks= sources->first; cks; cks= cks->next) {
1905                                         Object *ob= (Object *)cks->id;
1906                                         
1907                                         /* simply set recalc flag */
1908                                         ob->recalc |= OB_RECALC_OB;
1909                                 }
1910                         }
1911                 }
1912                         break;
1913         }
1914 }
1915
1916 /* flush refreshes after undo */
1917 static void commonkey_context_refresh (bContext *C)
1918 {
1919         ScrArea *curarea= CTX_wm_area(C);
1920         
1921         /* check view type */
1922         switch (curarea->spacetype) {
1923                 /* 3d view - first one tested as most often used */
1924                 case SPACE_VIEW3D:
1925                 {
1926                         /* do refreshes */
1927                         ED_anim_dag_flush_update(C);
1928                 }
1929                         break;
1930                         
1931                 /* buttons window */
1932                 case SPACE_BUTS:
1933                 {
1934                         //allspace(REMAKEIPO, 0);
1935                         //allqueue(REDRAWVIEW3D, 0);
1936                         //allqueue(REDRAWMARKER, 0);
1937                 }
1938                         break;
1939         }
1940 }
1941
1942 /* --- */
1943
1944 /* Get the keying set that was chosen by the user from the menu */
1945 static bKeyingSet *get_keyingset_fromcontext (bKeyingContext *ksc, short index)
1946 {
1947         /* check if index is valid */
1948         if (ELEM(NULL, ksc, ksc->keyingsets))
1949                 return NULL;
1950         if ((index < 1) || (index > ksc->tot))
1951                 return NULL;
1952                 
1953         /* index starts from 1, and should directly correspond to keyingset in array */
1954         return (bKeyingSet *)(ksc->keyingsets + (index - 1));
1955 }
1956
1957 /* ---------------- Keyframe Management API -------------------- */
1958
1959 /* Display a menu for handling the insertion of keyframes based on the active view */
1960 void common_modifykey (bContext *C, short mode)
1961 {
1962         ListBase dsources = {NULL, NULL};
1963         bKeyingContext *ksc= NULL;
1964         bCommonKeySrc *cks;
1965         bKeyingSet *ks = NULL;
1966         char *menustr, buf[64];
1967         short menu_nr;
1968         
1969         /* check if mode is valid */
1970         if (ELEM(mode, COMMONKEY_MODE_INSERT, COMMONKEY_MODE_DELETE)==0)
1971                 return;
1972         
1973         /* delegate to other functions or get keyingsets to use 
1974          *      - if the current area doesn't have its own handling, there will be data returned...
1975          */
1976         commonkey_context_get(C, NULL, mode, &dsources, &ksc);
1977         
1978         /* check that there is data to operate on */
1979         if (ELEM(NULL, dsources.first, ksc)) {
1980                 BLI_freelistN(&dsources);
1981                 return;
1982         }
1983         
1984         /* get menu and process it */
1985         if (mode == COMMONKEY_MODE_DELETE)
1986                 menustr= build_keyingsets_menu(ksc, "Delete");
1987         else
1988                 menustr= build_keyingsets_menu(ksc, "Insert");
1989         // XXX: this goes to the invoke!
1990         //menu_nr= pupmenu(menustr);
1991         //if (menustr) MEM_freeN(menustr);
1992         menu_nr = -1; // XXX for now
1993         
1994         /* no item selected or shapekey entry? */
1995         if (menu_nr < 1) {
1996                 /* free temp sources */
1997                 BLI_freelistN(&dsources);
1998                 
1999                 /* check if insert new shapekey */
2000                 // XXX missing function!
2001                 //if ((menu_nr == 0) && (mode == COMMONKEY_MODE_INSERT))
2002                 //      insert_shapekey(OBACT);
2003                 //else 
2004                         ksc->lastused= NULL;
2005                         
2006                 return;
2007         }
2008         else {
2009                 /* try to get keyingset */
2010                 ks= get_keyingset_fromcontext(ksc, menu_nr);
2011                 
2012                 if (ks == NULL) {
2013                         BLI_freelistN(&dsources);
2014                         return;
2015                 }
2016         }
2017         
2018         /* loop over each destination, applying the keying set */
2019         for (cks= dsources.first; cks; cks= cks->next) {
2020                 short success= 0;
2021                 
2022                 /* special hacks for 'available' option */
2023                 if (ks->flag == -2) {
2024                         IpoCurve *icu= NULL, *icn= NULL;
2025                         
2026                         /* get first IPO-curve */
2027                         if (cks->act && cks->actname) {
2028                                 bActionChannel *achan= get_action_channel(cks->act, cks->actname);
2029                                 
2030                                 // FIXME: what about constraint channels?
2031                                 if (achan && achan->ipo)
2032                                         icu= achan->ipo->curve.first; 
2033                         }
2034                         else if(cks->ipo)
2035                                 icu= cks->ipo->curve.first;
2036                                 
2037                         /* we get adrcodes directly from IPO curves (see method below...) */
2038                         for (; icu; icu= icn) {
2039                                 short flag;
2040                                 
2041                                 /* get next ipo-curve in case current is deleted */
2042                                 icn= icu->next;
2043                                 
2044                                 /* insert mode or delete mode */
2045                                 if (mode == COMMONKEY_MODE_DELETE) {
2046                                         /* local flags only add on to global flags */
2047                                         flag = 0;
2048                                         
2049                                         /* delete keyframe */
2050                                         success += deletekey(cks->id, ks->blocktype, cks->actname, cks->constname, icu->adrcode, flag);
2051                                 }
2052                                 else {
2053                                         /* local flags only add on to global flags */
2054                                         flag = ks->flag;
2055                                         if (IS_AUTOKEY_FLAG(AUTOMATKEY)) flag |= INSERTKEY_MATRIX;
2056                                         if (IS_AUTOKEY_FLAG(INSERTNEEDED)) flag |= INSERTKEY_NEEDED;
2057                                         // if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE;
2058                                         
2059                                         /* insert keyframe */
2060                                         success += insertkey(cks->id, ks->blocktype, cks->actname, cks->constname, icu->adrcode, flag);
2061                                 }
2062                         }
2063                 }
2064                 else {
2065                         bKS_AdrcodeGetter kag;
2066                         short (*get_next_adrcode)(bKS_AdrcodeGetter *);
2067                         int adrcode;
2068                         
2069                         /* initialise keyingset channel iterator */
2070                         ks_adrcodegetter_init(&kag, ks, cks);
2071                         
2072                         /* get iterator - only one can be in use at a time... the flags should be mutually exclusive in this regard */
2073                         if (ks->flag & COMMONKEY_PCHANROT)
2074                                 get_next_adrcode= ks_getnextadrcode_pchanrot;
2075                         else if (ks->flag & COMMONKEY_ADDMAP)
2076                                 get_next_adrcode= ks_getnextadrcode_addmap;
2077                         else
2078                                 get_next_adrcode= ks_getnextadrcode_default;
2079                         
2080                         /* loop over channels available in keyingset */
2081                         for (adrcode= get_next_adrcode(&kag); adrcode > 0; adrcode= get_next_adrcode(&kag)) {
2082                                 short flag;
2083                                 
2084                                 /* insert mode or delete mode */
2085                                 if (mode == COMMONKEY_MODE_DELETE) {
2086                                         /* local flags only add on to global flags */
2087                                         flag = 0;
2088                                         //flag &= ~COMMONKEY_MODES;
2089                                         
2090                                         /* delete keyframe */
2091                                         success += deletekey(cks->id, ks->blocktype, cks->actname, cks->constname, adrcode, flag);
2092                                 }
2093                                 else {
2094                                         /* local flags only add on to global flags */
2095                                         flag = ks->flag;
2096                                         if (IS_AUTOKEY_FLAG(AUTOMATKEY)) flag |= INSERTKEY_MATRIX;
2097                                         if (IS_AUTOKEY_FLAG(INSERTNEEDED)) flag |= INSERTKEY_NEEDED;
2098                                         // if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE;
2099                                         flag &= ~COMMONKEY_MODES;
2100                                         
2101                                         /* insert keyframe */
2102                                         success += insertkey(cks->id, ks->blocktype, cks->actname, cks->constname, adrcode, flag);
2103                                 }
2104                         }
2105                 }
2106                 
2107                 /* special handling for some key-sources */
2108                 if (success) {
2109                         /* set pose recalc-paths flag */
2110                         if (cks->pchan) {
2111                                 Object *ob= (Object *)cks->id;
2112                                 bPoseChannel *pchan= cks->pchan;
2113                                 
2114                                 /* set flag to trigger path recalc */
2115                                 if (pchan->path) 
2116                                         ob->pose->flag |= POSE_RECALCPATHS;
2117                                         
2118                                 /* clear unkeyed flag (it doesn't matter if it's set or not) */
2119                                         // XXX old animation system
2120                                 //if (pchan->bone)
2121                                 //      pchan->bone->flag &= ~BONE_UNKEYED;
2122                         }
2123                         
2124                         // XXX for new system, need to remove overrides
2125                 }
2126         }
2127         
2128         /* apply post-keying flushes for this data sources */
2129         commonkey_context_finish(C, &dsources);
2130         
2131         /* free temp data */
2132         BLI_freelistN(&dsources);
2133         
2134         /* queue updates for contexts */
2135         commonkey_context_refresh(C);
2136 }
2137
2138 #endif // XXX old keyingsets code based on adrcodes... to be restored in due course
2139
2140 /* Given a KeyingSet and context info (if required), modify keyframes for the channels specified
2141  * by the KeyingSet. This takes into account many of the different combinations of using KeyingSets.
2142  * Returns the number of channels that keyframes were added to
2143  */
2144 static int commonkey_modifykey (ListBase *dsources, KeyingSet *ks, short mode, float cfra)
2145 {
2146         KS_Path *ksp;
2147         int kflag=0, success= 0;
2148         char *groupname= NULL;
2149         
2150         /* get flags to use */
2151         if (mode == COMMONKEY_MODE_INSERT) {
2152                 /* use KeyingSet's flags as base */
2153                 kflag= ks->keyingflag;
2154                 
2155                 /* suppliment with info from the context */
2156                 if (IS_AUTOKEY_FLAG(AUTOMATKEY)) kflag |= INSERTKEY_MATRIX;
2157                 if (IS_AUTOKEY_FLAG(INSERTNEEDED)) kflag |= INSERTKEY_NEEDED;
2158                 // if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE;
2159         }
2160         else if (mode == COMMONKEY_MODE_DELETE)
2161                 kflag= 0;
2162         
2163         /* check if the KeyingSet is absolute or not (i.e. does it requires sources info) */
2164         if (ks->flag & KEYINGSET_ABSOLUTE) {
2165                 /* Absolute KeyingSets are simpler to use, as all the destination info has already been
2166                  * provided by the user, and is stored, ready to use, in the KeyingSet paths.
2167                  */
2168                 for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
2169                         int arraylen, i;
2170                         
2171                         /* get pointer to name of group to add channels to */
2172                         if (ksp->groupmode == KSP_GROUP_NONE)
2173                                 groupname= NULL;
2174                         else if (ksp->groupmode == KSP_GROUP_KSNAME)
2175                                 groupname= ks->name;
2176                         else
2177                                 groupname= ksp->group;
2178                         
2179                         /* init arraylen and i - arraylen should be greater than i so that
2180                          * normal non-array entries get keyframed correctly
2181                          */
2182                         i= ksp->array_index;
2183                         arraylen= i+1;
2184                         
2185                         /* get length of array if whole array option is enabled */
2186                         if (ksp->flag & KSP_FLAG_WHOLE_ARRAY) {
2187                                 PointerRNA id_ptr, ptr;
2188                                 PropertyRNA *prop;
2189                                 
2190                                 RNA_id_pointer_create(ksp->id, &id_ptr);
2191                                 if (RNA_path_resolve(&id_ptr, ksp->rna_path, &ptr, &prop) && prop)
2192                                         arraylen= RNA_property_array_length(&ptr, prop);
2193                         }
2194                         
2195                         /* for each possible index, perform operation 
2196                          *      - assume that arraylen is greater than index
2197                          */
2198                         for (; i < arraylen; i++) {
2199                                 /* action to take depends on mode */
2200                                 if (mode == COMMONKEY_MODE_INSERT)
2201                                         success+= insertkey(ksp->id, groupname, ksp->rna_path, i, cfra, kflag);
2202                                 else if (mode == COMMONKEY_MODE_DELETE)
2203                                         success+= deletekey(ksp->id, groupname,  ksp->rna_path, i, cfra, kflag);
2204                         }
2205                         
2206                         // TODO: set recalc tags on the ID?
2207                 }
2208         }
2209 #if 0 // XXX still need to figure out how to get such keyingsets working
2210         else if (dsources) {
2211                 /* for each one of the 'sources', resolve the template markers and expand arrays, then insert keyframes */
2212                 bCommonKeySrc *cks;
2213                 char *path = NULL;
2214                 int index=0, tot=0;
2215                 
2216                 /* for each 'source' for keyframe data, resolve each of the paths from the KeyingSet */
2217                 for (cks= dsources->first; cks; cks= cks->next) {
2218                         
2219                 }
2220         }
2221 #endif // XXX still need to figure out how to get such 
2222         
2223         return success;
2224 }
2225
2226 /* Insert Key Operator ------------------------ */
2227
2228 /* NOTE:
2229  * This is one of the 'simpler new-style' Insert Keyframe operators which relies on Keying Sets.
2230  * For now, these are absolute Keying Sets only, so there is very little context info involved.
2231  *
2232  *      -- Joshua Leung, Feb 2009
2233  */
2234
2235 static int insert_key_exec (bContext *C, wmOperator *op)
2236 {
2237         ListBase dsources = {NULL, NULL};
2238         Scene *scene= CTX_data_scene(C);
2239         KeyingSet *ks= NULL;
2240         float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
2241         short success;
2242         
2243         /* try to get KeyingSet */
2244         if (scene->active_keyingset > 0)
2245                 ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
2246         /* report failure */
2247         if (ks == NULL) {
2248                 BKE_report(op->reports, RPT_ERROR, "No active Keying Set");
2249                 return OPERATOR_CANCELLED;
2250         }
2251         
2252         /* try to insert keyframes for the channels specified by KeyingSet */
2253         success= commonkey_modifykey(&dsources, ks, COMMONKEY_MODE_INSERT, cfra);
2254         printf("KeyingSet '%s' - Successfully added %d Keyframes \n", ks->name, success);
2255         
2256         /* report failure? */
2257         if (success == 0)
2258                 BKE_report(op->reports, RPT_WARNING, "Keying Set failed to insert any keyframes");
2259         
2260         /* send updates */
2261         ED_anim_dag_flush_update(C);    
2262         
2263         /* for now, only send ND_KEYS for KeyingSets */
2264         WM_event_add_notifier(C, ND_KEYS, NULL);
2265         
2266         return OPERATOR_FINISHED;
2267 }
2268
2269 void ANIM_OT_insert_keyframe (wmOperatorType *ot)
2270 {
2271         /* identifiers */
2272         ot->name= "Insert Keyframe";
2273         ot->idname= "ANIM_OT_insert_keyframe";
2274         
2275         /* callbacks */
2276         ot->exec= insert_key_exec; 
2277         ot->poll= ED_operator_areaactive;
2278         
2279         /* flags */
2280         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2281 }
2282
2283 /* Delete Key Operator ------------------------ */
2284
2285 /* NOTE:
2286  * This is one of the 'simpler new-style' Insert Keyframe operators which relies on Keying Sets.
2287  * For now, these are absolute Keying Sets only, so there is very little context info involved.
2288  *
2289  *      -- Joshua Leung, Feb 2009
2290  */
2291  
2292 static int delete_key_exec (bContext *C, wmOperator *op)
2293 {
2294         ListBase dsources = {NULL, NULL};
2295         Scene *scene= CTX_data_scene(C);
2296         KeyingSet *ks= NULL;
2297         float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
2298         short success;
2299         
2300         /* try to get KeyingSet */
2301         if (scene->active_keyingset > 0)
2302                 ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
2303         /* report failure */
2304         if (ks == NULL) {
2305                 BKE_report(op->reports, RPT_ERROR, "No active Keying Set");
2306                 return OPERATOR_CANCELLED;
2307         }
2308         
2309         /* try to insert keyframes for the channels specified by KeyingSet */
2310         success= commonkey_modifykey(&dsources, ks, COMMONKEY_MODE_DELETE, cfra);
2311         printf("KeyingSet '%s' - Successfully removed %d Keyframes \n", ks->name, success);
2312         
2313         /* report failure? */
2314         if (success == 0)
2315                 BKE_report(op->reports, RPT_WARNING, "Keying Set failed to remove any keyframes");
2316         
2317         /* send updates */
2318         ED_anim_dag_flush_update(C);    
2319         
2320         /* for now, only send ND_KEYS for KeyingSets */
2321         WM_event_add_notifier(C, ND_KEYS, NULL);
2322         
2323         return OPERATOR_FINISHED;
2324 }
2325
2326 void ANIM_OT_delete_keyframe (wmOperatorType *ot)
2327 {
2328         /* identifiers */
2329         ot->name= "Delete Keyframe";
2330         ot->idname= "ANIM_OT_delete_keyframe";
2331         
2332         /* callbacks */
2333         ot->exec= delete_key_exec; 
2334         
2335         ot->poll= ED_operator_areaactive;
2336         
2337         /* flags */
2338         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2339 }
2340
2341 /* Insert Key Operator ------------------------ */
2342
2343 /* XXX WARNING:
2344  * This is currently just a basic operator, which work in 3d-view context on objects/bones only
2345  * and will insert keyframes for a few settings only. This is until it becomes clear how
2346  * to separate (or not) the process for RNA-path creation between context + keyingsets.
2347  * 
2348  * -- Joshua Leung, Jan 2009
2349  */
2350
2351 /* defines for basic insert-key testing operator  */
2352         // XXX this will definitely be replaced
2353 EnumPropertyItem prop_insertkey_types[] = {
2354         {0, "KEYINGSET", "Active KeyingSet", ""},
2355         {1, "OBLOC", "Object Location", ""},
2356         {2, "OBROT", "Object Rotation", ""},
2357         {3, "OBSCALE", "Object Scale", ""},
2358         {4, "MAT_COL", "Active Material - Color", ""},
2359         {5, "PCHANLOC", "Pose-Channel Location", ""},
2360         {6, "PCHANROT", "Pose-Channel Rotation", ""},
2361         {7, "PCHANSCALE", "Pose-Channel Scale", ""},
2362         {0, NULL, NULL, NULL}
2363 };
2364
2365 static int insert_key_old_invoke (bContext *C, wmOperator *op, wmEvent *event)
2366 {
2367         Object *ob= CTX_data_active_object(C);
2368         uiMenuItem *head;
2369         
2370         if (ob == NULL)
2371                 return OPERATOR_CANCELLED;
2372                 
2373         head= uiPupMenuBegin("Insert Keyframe", 0);
2374         
2375         /* active keyingset */
2376         uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe_old", "type", 0);
2377         
2378         /* selective inclusion */
2379         if ((ob->pose) && (ob->flag & OB_POSEMODE)) {
2380                 /* bone types */        
2381                 uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe_old", "type", 5);
2382                 uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe_old", "type", 6);
2383                 uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe_old", "type", 7);
2384         }
2385         else {
2386                 /* object types */
2387                 uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe_old", "type", 1);
2388                 uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe_old", "type", 2);
2389                 uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe_old", "type", 3);
2390                 uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe_old", "type", 4);
2391         }
2392         
2393         uiPupMenuEnd(C, head);
2394         
2395         return OPERATOR_CANCELLED;
2396 }
2397  
2398 static int insert_key_old_exec (bContext *C, wmOperator *op)
2399 {
2400         Scene *scene= CTX_data_scene(C);
2401         short mode= RNA_enum_get(op->ptr, "type");
2402         float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
2403         
2404         /* for now, handle 'active keyingset' one separately */
2405         if (mode == 0) {
2406                 ListBase dsources = {NULL, NULL};
2407                 KeyingSet *ks= NULL;
2408                 short success;
2409                 
2410                 /* try to get KeyingSet */
2411                 if (scene->active_keyingset > 0)
2412                         ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
2413                 /* report failure */
2414                 if (ks == NULL) {
2415                         BKE_report(op->reports, RPT_ERROR, "No active Keying Set");
2416                         return OPERATOR_CANCELLED;
2417                 }
2418                 
2419                 /* try to insert keyframes for the channels specified by KeyingSet */
2420                 success= commonkey_modifykey(&dsources, ks, COMMONKEY_MODE_INSERT, cfra);
2421                 printf("KeyingSet '%s' - Successfully added %d Keyframes \n", ks->name, success);
2422                 
2423                 /* report failure? */
2424                 if (success == 0)
2425                         BKE_report(op->reports, RPT_WARNING, "Keying Set failed to insert any keyframes");
2426         }
2427         else {
2428                 // more comprehensive tests will be needed
2429                 CTX_DATA_BEGIN(C, Base*, base, selected_bases) 
2430                 {
2431                         Object *ob= base->object;
2432                         ID *id= (ID *)ob;
2433                         short success= 0;
2434                         
2435                         /* check which keyframing mode chosen for this object */
2436                         if (mode < 4) {
2437                                 /* object-based keyframes */
2438                                 switch (mode) {
2439                                 case 4: /* color of active material (only for geometry...) */
2440                                         // NOTE: this is just a demo... but ideally we'd go through materials instead of active one only so reference stays same
2441                                         // XXX no group for now
2442                                         success+= insertkey(id, NULL, "active_material.diffuse_color", 0, cfra, 0);
2443                                         success+= insertkey(id, NULL, "active_material.diffuse_color", 1, cfra, 0);
2444                                         success+= insertkey(id, NULL, "active_material.diffuse_color", 2, cfra, 0);
2445                                         break;
2446                                 case 3: /* object scale */
2447                                         success+= insertkey(id, "Object Transforms", "scale", 0, cfra, 0);
2448                                         success+= insertkey(id, "Object Transforms", "scale", 1, cfra, 0);
2449                                         success+= insertkey(id, "Object Transforms", "scale", 2, cfra, 0);
2450                                         break;
2451                                 case 2: /* object rotation */
2452                                         success+= insertkey(id, "Object Transforms", "rotation", 0, cfra, 0);
2453                                         success+= insertkey(id, "Object Transforms", "rotation", 1, cfra, 0);
2454                                         success+= insertkey(id, "Object Transforms", "rotation", 2, cfra, 0);
2455                                         break;
2456                                 case 1: /* object location */
2457                                         success+= insertkey(id, "Object Transforms", "location", 0, cfra, 0);
2458                                         success+= insertkey(id, "Object Transforms", "location", 1, cfra, 0);
2459                                         success+= insertkey(id, "Object Transforms", "location", 2, cfra, 0);
2460                                         break;
2461                                 }
2462                                 
2463                                 ob->recalc |= OB_RECALC_OB;
2464                         }
2465                         else if ((ob->pose) && (ob->flag & OB_POSEMODE)) {
2466                                 /* PoseChannel based keyframes */
2467                                 bPoseChannel *pchan;
2468                                 
2469                                 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
2470                                         /* only if selected */
2471                                         if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) {
2472                                                 char buf[512];
2473                                                 
2474                                                 switch (mode) {
2475                                                 case 6: /* pchan scale */
2476                                                         sprintf(buf, "pose.pose_channels[\"%s\"].scale", pchan->name);
2477                                                         success+= insertkey(id, pchan->name, buf, 0, cfra, 0);
2478                                                         success+= insertkey(id, pchan->name, buf, 1, cfra, 0);
2479                                                         success+= insertkey(id, pchan->name, buf, 2, cfra, 0);
2480                                                         break;
2481                                                 case 5: /* pchan rotation */
2482                                                         if (pchan->rotmode == PCHAN_ROT_QUAT) {
2483                                                                 sprintf(buf, "pose.pose_channels[\"%s\"].rotation", pchan->name);
2484                                                                 success+= insertkey(id, pchan->name, buf, 0, cfra, 0);
2485                                                                 success+= insertkey(id, pchan->name, buf, 1, cfra, 0);
2486                                                                 success+= insertkey(id, pchan->name, buf, 2, cfra, 0);
2487                                                                 success+= insertkey(id, pchan->name, buf, 3, cfra, 0);
2488                                                         }
2489                                                         else {
2490                                                                 sprintf(buf, "pose.pose_channels[\"%s\"].euler_rotation", pchan->name);
2491                                                                 success+= insertkey(id, pchan->name, buf, 0, cfra, 0);
2492                                                                 success+= insertkey(id, pchan->name, buf, 1, cfra, 0);
2493                                                                 success+= insertkey(id, pchan->name, buf, 2, cfra, 0);
2494                                                         }
2495                                                         break;
2496                                                 default: /* pchan location */
2497                                                         sprintf(buf, "pose.pose_channels[\"%s\"].location", pchan->name);
2498                                                         success+= insertkey(id, pchan->name, buf, 0, cfra, 0);
2499                                                         success+= insertkey(id, pchan->name, buf, 1, cfra, 0);
2500                                                         success+= insertkey(id, pchan->name, buf, 2, cfra, 0);
2501                                                         break;
2502                                                 }
2503                                         }
2504                                 }
2505                                 
2506                                 ob->recalc |= OB_RECALC_OB;
2507                         }
2508                         
2509                         printf("Ob '%s' - Successfully added %d Keyframes \n", id->name+2, success);
2510                 }
2511                 CTX_DATA_END;
2512         }
2513         
2514         /* send updates */
2515         ED_anim_dag_flush_update(C);    
2516         
2517         if (mode == 0) /* for now, only send ND_KEYS for KeyingSets */
2518                 WM_event_add_notifier(C, ND_KEYS, NULL);
2519         else if (mode == 4) /* material color requires different notifiers */
2520                 WM_event_add_notifier(C, NC_MATERIAL|ND_KEYS, NULL);
2521         else
2522                 WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, NULL);
2523         
2524         return OPERATOR_FINISHED;
2525 }
2526
2527 void ANIM_OT_insert_keyframe_old (wmOperatorType *ot)
2528 {
2529         PropertyRNA *prop;
2530         
2531         /* identifiers */
2532         ot->name= "Insert Keyframe";
2533         ot->idname= "ANIM_OT_insert_keyframe_old";
2534         
2535         /* callbacks */
2536         ot->invoke= insert_key_old_invoke;
2537         ot->exec= insert_key_old_exec; 
2538         ot->poll= ED_operator_areaactive;
2539         
2540         /* flags */
2541         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2542         
2543         /* properties */
2544                 // XXX update this for the latest RNA stuff styles...
2545         prop= RNA_def_property(ot->srna, "type", PROP_ENUM, PROP_NONE);
2546         RNA_def_property_enum_items(prop, prop_insertkey_types);
2547 }
2548
2549 /* Delete Key Operator ------------------------ */
2550
2551 /* XXX WARNING:
2552  * This is currently just a basic operator, which work in 3d-view context on objects only. 
2553  * -- Joshua Leung, Jan 2009
2554  */
2555  
2556 static int delete_key_old_exec (bContext *C, wmOperator *op)
2557 {
2558         Scene *scene= CTX_data_scene(C);
2559         float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
2560         
2561         // XXX more comprehensive tests will be needed
2562         CTX_DATA_BEGIN(C, Base*, base, selected_bases) 
2563         {
2564                 Object *ob= base->object;
2565                 ID *id= (ID *)ob;
2566                 FCurve *fcu, *fcn;
2567                 short success= 0;
2568                 
2569                 /* loop through all curves in animdata and delete keys on this frame */
2570                 if (ob->adt) {
2571                         AnimData *adt= ob->adt;
2572                         bAction *act= adt->action;
2573                         
2574                         for (fcu= act->curves.first; fcu; fcu= fcn) {
2575                                 fcn= fcu->next;
2576                                 success+= deletekey(id, NULL, fcu->rna_path, fcu->array_index, cfra, 0);
2577                         }
2578                 }
2579                 
2580                 printf("Ob '%s' - Successfully removed %d keyframes \n", id->name+2, success);
2581                 
2582                 ob->recalc |= OB_RECALC_OB;
2583         }
2584         CTX_DATA_END;
2585         
2586         /* send updates */
2587         ED_anim_dag_flush_update(C);    
2588         
2589                 // XXX what if it was a material keyframe?
2590         WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, NULL);
2591         
2592         return OPERATOR_FINISHED;
2593 }
2594
2595 void ANIM_OT_delete_keyframe_old (wmOperatorType *ot)
2596 {
2597         /* identifiers */
2598         ot->name= "Delete Keyframe";
2599         ot->idname= "ANIM_OT_delete_keyframe_old";
2600         
2601         /* callbacks */
2602         ot->invoke= WM_operator_confirm; // XXX we will need our own one eventually, to cope with the dynamic menus...
2603         ot->exec= delete_key_old_exec; 
2604         
2605         ot->poll= ED_operator_areaactive;
2606         
2607         /* flags */
2608         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2609 }
2610
2611 /* ******************************************* */
2612 /* KEYFRAME DETECTION */
2613
2614 /* --------------- API/Per-Datablock Handling ------------------- */
2615
2616 /* Checks whether an IPO-block has a keyframe for a given frame 
2617  * Since we're only concerned whether a keyframe exists, we can simply loop until a match is found...
2618  */
2619 short action_frame_has_keyframe (bAction *act, float frame, short filter)
2620 {
2621         FCurve *fcu;
2622         
2623         /* can only find if there is data */
2624         if (act == NULL)
2625                 return 0;
2626                 
2627         /* if only check non-muted, check if muted */
2628         if ((filter & ANIMFILTER_KEYS_MUTED) || (act->flag & ACT_MUTED))
2629                 return 0;
2630         
2631         /* loop over F-Curves, using binary-search to try to find matches 
2632          *      - this assumes that keyframes are only beztriples
2633          */
2634         for (fcu= act->curves.first; fcu; fcu= fcu->next) {
2635                 /* only check if there are keyframes (currently only of type BezTriple) */
2636                 if (fcu->bezt && fcu->totvert) {
2637                         /* we either include all regardless of muting, or only non-muted  */
2638                         if ((filter & ANIMFILTER_KEYS_MUTED) || (fcu->flag & FCURVE_MUTED)==0) {
2639                                 short replace = -1;
2640                                 int i = binarysearch_bezt_index(fcu->bezt, frame, fcu->totvert, &replace);
2641                                 
2642                                 /* binarysearch_bezt_index will set replace to be 0 or 1
2643                                  *      - obviously, 1 represents a match
2644                                  */
2645                                 if (replace) {                  
2646                                         /* sanity check: 'i' may in rare cases exceed arraylen */
2647                                         if ((i >= 0) && (i < fcu->totvert))
2648                                                 return 1;
2649                                 }
2650                         }
2651                 }
2652         }
2653         
2654         /* nothing found */
2655         return 0;
2656 }
2657
2658 /* Checks whether an Object has a keyframe for a given frame */
2659 short object_frame_has_keyframe (Object *ob, float frame, short filter)
2660 {
2661         /* error checking */
2662         if (ob == NULL)
2663                 return 0;
2664         
2665         /* check own animation data - specifically, the action it contains */
2666         if ((ob->adt) && (ob->adt->action)) {
2667                 if (action_frame_has_keyframe(ob->adt->action, frame, filter))
2668                         return 1;
2669         }
2670         
2671         /* try shapekey keyframes (if available, and allowed by filter) */
2672         if ( !(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOSKEY) ) {
2673                 Key *key= ob_get_key(ob);
2674                 
2675                 /* shapekeys can have keyframes ('Relative Shape Keys') 
2676                  * or depend on time (old 'Absolute Shape Keys') 
2677                  */
2678                  
2679                         /* 1. test for relative (with keyframes) */
2680                 if (id_frame_has_keyframe((ID *)key, frame, filter))
2681                         return 1;
2682                         
2683                         /* 2. test for time */
2684                 // TODO... yet to be implemented (this feature may evolve before then anyway)
2685         }
2686         
2687         /* try materials */
2688         if ( !(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOMAT) ) {
2689                 /* if only active, then we can skip a lot of looping */
2690                 if (filter & ANIMFILTER_KEYS_ACTIVE) {
2691                         Material *ma= give_current_material(ob, (ob->actcol + 1));
2692                         
2693                         /* we only retrieve the active material... */
2694                         if (id_frame_has_keyframe((ID *)ma, frame, filter))
2695                                 return 1;
2696                 }
2697                 else {
2698                         int a;
2699                         
2700                         /* loop over materials */
2701                         for (a=0; a<ob->totcol; a++) {
2702                                 Material *ma= give_current_material(ob, a+1);
2703                                 
2704                                 if (id_frame_has_keyframe((ID *)ma, frame, filter))
2705                                         return 1;
2706                         }
2707                 }
2708         }
2709         
2710         /* nothing found */
2711         return 0;
2712 }
2713
2714 /* --------------- API ------------------- */
2715
2716 /* Checks whether a keyframe exists for the given ID-block one the given frame */
2717 short id_frame_has_keyframe (ID *id, float frame, short filter)
2718 {
2719         /* sanity checks */
2720         if (id == NULL)
2721                 return 0;
2722         
2723         /* perform special checks for 'macro' types */
2724         switch (GS(id->name)) {
2725                 case ID_OB: /* object */
2726                         return object_frame_has_keyframe((Object *)id, frame, filter);
2727                         break;
2728                         
2729                 case ID_SCE: /* scene */
2730                 // XXX TODO... for now, just use 'normal' behaviour
2731                 //      break;
2732                 
2733                 default:        /* 'normal type' */
2734                 {
2735                         AnimData *adt= BKE_animdata_from_id(id);
2736                         
2737                         /* only check keyframes in active action */
2738                         if (adt)
2739                                 return action_frame_has_keyframe(adt->action, frame, filter);
2740                 }
2741                         break;
2742         }
2743         
2744         
2745         /* no keyframe found */
2746         return 0;
2747 }
2748
2749 /* ************************************************** */