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