A few fixes:
[blender.git] / source / blender / editors / animation / keyingsets.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): Joshua Leung (full recode)
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29  
30 #include <stdio.h>
31 #include <stddef.h>
32 #include <string.h>
33 #include <math.h>
34 #include <float.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "BLI_blenlib.h"
39 #include "BLI_arithb.h"
40 #include "BLI_dynstr.h"
41
42 #include "DNA_anim_types.h"
43 #include "DNA_action_types.h"
44 #include "DNA_armature_types.h"
45 #include "DNA_constraint_types.h"
46 #include "DNA_key_types.h"
47 #include "DNA_object_types.h"
48 #include "DNA_material_types.h"
49 #include "DNA_scene_types.h"
50 #include "DNA_userdef_types.h"
51 #include "DNA_windowmanager_types.h"
52
53 #include "BKE_animsys.h"
54 #include "BKE_action.h"
55 #include "BKE_constraint.h"
56 #include "BKE_fcurve.h"
57 #include "BKE_utildefines.h"
58 #include "BKE_context.h"
59 #include "BKE_report.h"
60 #include "BKE_key.h"
61 #include "BKE_material.h"
62
63 #include "ED_anim_api.h"
64 #include "ED_keyframing.h"
65 #include "ED_keyframes_edit.h"
66 #include "ED_screen.h"
67 #include "ED_util.h"
68
69 #include "UI_interface.h"
70
71 #include "WM_api.h"
72 #include "WM_types.h"
73
74 #include "RNA_access.h"
75 #include "RNA_define.h"
76 #include "RNA_types.h"
77
78 #include "anim_intern.h"
79
80 /* ************************************************** */
81 /* KEYING SETS - OPERATORS (for use in UI panels) */
82 /* These operators are really duplication of existing functionality, but just for completeness,
83  * they're here too, and will give the basic data needed...
84  */
85
86 /* poll callback for adding default KeyingSet */
87 static int keyingset_poll_default_add (bContext *C)
88 {
89         /* as long as there's an active Scene, it's fine */
90         return (CTX_data_scene(C) != NULL);
91 }
92
93 /* poll callback for editing active KeyingSet */
94 static int keyingset_poll_active_edit (bContext *C)
95 {
96         Scene *scene= CTX_data_scene(C);
97         
98         if (scene == NULL)
99                 return 0;
100         
101         /* there must be an active KeyingSet (and KeyingSets) */
102         return ((scene->active_keyingset > 0) && (scene->keyingsets.first));
103 }
104
105 /* poll callback for editing active KeyingSet Path */
106 static int keyingset_poll_activePath_edit (bContext *C)
107 {
108         Scene *scene= CTX_data_scene(C);
109         KeyingSet *ks;
110         
111         if (scene == NULL)
112                 return 0;
113         if (scene->active_keyingset <= 0)
114                 return 0;
115         else
116                 ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
117         
118         /* there must be an active KeyingSet and an active path */
119         return ((ks) && (ks->paths.first) && (ks->active_path > 0));
120 }
121
122  
123 /* Add a Default (Empty) Keying Set ------------------------- */
124
125 static int add_default_keyingset_exec (bContext *C, wmOperator *op)
126 {
127         Scene *scene= CTX_data_scene(C);
128         short flag=0, keyingflag=0;
129         
130         /* validate flags 
131          *      - absolute KeyingSets should be created by default
132          */
133         flag |= KEYINGSET_ABSOLUTE;
134         
135         if (IS_AUTOKEY_FLAG(AUTOMATKEY)) 
136                 keyingflag |= INSERTKEY_MATRIX;
137         if (IS_AUTOKEY_FLAG(INSERTNEEDED)) 
138                 keyingflag |= INSERTKEY_NEEDED;
139                 
140         /* call the API func, and set the active keyingset index */
141         BKE_keyingset_add(&scene->keyingsets, NULL, flag, keyingflag);
142         
143         scene->active_keyingset= BLI_countlist(&scene->keyingsets);
144         
145         return OPERATOR_FINISHED;
146 }
147
148 void ANIM_OT_keying_set_add (wmOperatorType *ot)
149 {
150         /* identifiers */
151         ot->name= "Add Empty Keying Set";
152         ot->idname= "ANIM_OT_keying_set_add";
153         ot->description= "Add a new (empty) Keying Set to the active Scene.";
154         
155         /* callbacks */
156         ot->exec= add_default_keyingset_exec;
157         ot->poll= keyingset_poll_default_add;
158 }
159
160 /* Remove 'Active' Keying Set ------------------------- */
161
162 static int remove_active_keyingset_exec (bContext *C, wmOperator *op)
163 {
164         Scene *scene= CTX_data_scene(C);
165         KeyingSet *ks;
166         
167         /* verify the Keying Set to use:
168          *      - use the active one
169          *      - return error if it doesn't exist
170          */
171         if (scene->active_keyingset == 0) {
172                 BKE_report(op->reports, RPT_ERROR, "No active Keying Set to remove");
173                 return OPERATOR_CANCELLED;
174         }
175         else
176                 ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
177         
178         /* free KeyingSet's data, then remove it from the scene */
179         BKE_keyingset_free(ks);
180         
181         BLI_freelinkN(&scene->keyingsets, ks);
182         scene->active_keyingset= 0;
183         
184         return OPERATOR_FINISHED;
185 }
186
187 void ANIM_OT_keying_set_remove (wmOperatorType *ot)
188 {
189         /* identifiers */
190         ot->name= "Removed Active Keying Set";
191         ot->idname= "ANIM_OT_keying_set_remove";
192         ot->description= "Remove the active Keying Set.";
193         
194         /* callbacks */
195         ot->exec= remove_active_keyingset_exec;
196         ot->poll= keyingset_poll_active_edit;
197 }
198
199 /* Add Empty Keying Set Path ------------------------- */
200
201 static int add_empty_ks_path_exec (bContext *C, wmOperator *op)
202 {
203         Scene *scene= CTX_data_scene(C);
204         KeyingSet *ks;
205         KS_Path *ksp;
206         
207         /* verify the Keying Set to use:
208          *      - use the active one
209          *      - return error if it doesn't exist
210          */
211         if (scene->active_keyingset == 0) {
212                 BKE_report(op->reports, RPT_ERROR, "No active Keying Set to add empty path to");
213                 return OPERATOR_CANCELLED;
214         }
215         else
216                 ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
217         
218         /* don't use the API method for this, since that checks on values... */
219         ksp= MEM_callocN(sizeof(KS_Path), "KeyingSetPath Empty");
220         BLI_addtail(&ks->paths, ksp);
221         ks->active_path= BLI_countlist(&ks->paths) + 1;
222         
223         ksp->groupmode= KSP_GROUP_KSNAME; // XXX?
224         
225         return OPERATOR_FINISHED;
226 }
227
228 void ANIM_OT_keying_set_path_add (wmOperatorType *ot)
229 {
230         /* identifiers */
231         ot->name= "Add Empty Keying Set Path";
232         ot->idname= "ANIM_OT_keying_set_path_add";
233         ot->description= "Add empty path to active Keying Set";
234         
235         /* callbacks */
236         ot->exec= add_empty_ks_path_exec;
237         ot->poll= keyingset_poll_active_edit;
238 }
239
240 /* Remove Active Keying Set Path ------------------------- */
241
242 static int remove_active_ks_path_exec (bContext *C, wmOperator *op)
243 {
244         Scene *scene= CTX_data_scene(C);
245         KeyingSet *ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
246         
247         /* if there is a KeyingSet, find the nominated path to remove */
248         if (ks) {
249                 KS_Path *ksp= BLI_findlink(&ks->paths, ks->active_path-1);
250                 
251                 if (ksp) {
252                         /* NOTE: sync this code with BKE_keyingset_free() */
253                         {
254                                 /* free RNA-path info */
255                                 MEM_freeN(ksp->rna_path);
256                                 
257                                 /* free path itself */
258                                 BLI_freelinkN(&ks->paths, ksp);
259                         }
260                         
261                         /* fix active path index */
262                         ks->active_path= 0;
263                 }
264                 else {
265                         BKE_report(op->reports, RPT_ERROR, "No active Keying Set Path to remove");
266                         return OPERATOR_CANCELLED;
267                 }
268         }
269         else {
270                 BKE_report(op->reports, RPT_ERROR, "No active Keying Set to remove a path from");
271                 return OPERATOR_CANCELLED;
272         }
273         
274         return OPERATOR_FINISHED;
275 }
276
277 void ANIM_OT_keying_set_path_remove (wmOperatorType *ot)
278 {
279         /* identifiers */
280         ot->name= "Remove Active Keying Set Path";
281         ot->idname= "ANIM_OT_keying_set_path_remove";
282         ot->description= "Remove active Path from active Keying Set.";
283         
284         /* callbacks */
285         ot->exec= remove_active_ks_path_exec;
286         ot->poll= keyingset_poll_activePath_edit;
287 }
288
289 /* ************************************************** */
290 /* KEYING SETS - OPERATORS (for use in UI menus) */
291
292 /* Add to KeyingSet Button Operator ------------------------ */
293
294 static int add_keyingset_button_exec (bContext *C, wmOperator *op)
295 {
296         Scene *scene= CTX_data_scene(C);
297         KeyingSet *ks = NULL;
298         PropertyRNA *prop= NULL;
299         PointerRNA ptr;
300         char *path = NULL;
301         short success= 0;
302         int index=0, pflag=0;
303         int all= RNA_boolean_get(op->ptr, "all");
304         
305         /* verify the Keying Set to use:
306          *      - use the active one for now (more control over this can be added later)
307          *      - add a new one if it doesn't exist 
308          */
309         if (scene->active_keyingset == 0) {
310                 short flag=0, keyingflag=0;
311                 
312                 /* validate flags 
313                  *      - absolute KeyingSets should be created by default
314                  */
315                 flag |= KEYINGSET_ABSOLUTE;
316                 
317                 if (IS_AUTOKEY_FLAG(AUTOMATKEY)) 
318                         keyingflag |= INSERTKEY_MATRIX;
319                 if (IS_AUTOKEY_FLAG(INSERTNEEDED)) 
320                         keyingflag |= INSERTKEY_NEEDED;
321                         
322                 /* call the API func, and set the active keyingset index */
323                 ks= BKE_keyingset_add(&scene->keyingsets, "ButtonKeyingSet", flag, keyingflag);
324                 
325                 scene->active_keyingset= BLI_countlist(&scene->keyingsets);
326         }
327         else
328                 ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
329         
330         /* try to add to keyingset using property retrieved from UI */
331         memset(&ptr, 0, sizeof(PointerRNA));
332         uiAnimContextProperty(C, &ptr, &prop, &index);
333         
334         /* check if property is able to be added */
335         if (ptr.data && prop && RNA_property_animateable(ptr.data, prop)) {
336                 path= RNA_path_from_ID_to_property(&ptr, prop);
337                 
338                 if (path) {
339                         /* set flags */
340                         if (all) {
341                                 pflag |= KSP_FLAG_WHOLE_ARRAY;
342                                 
343                                 /* we need to set the index for this to 0, even though it may break in some cases, this is 
344                                  * necessary if we want the entire array for most cases to get included without the user
345                                  * having to worry about where they clicked
346                                  */
347                                 index= 0;
348                         }
349                                 
350                         /* add path to this setting */
351                         BKE_keyingset_add_destination(ks, ptr.id.data, NULL, path, index, pflag, KSP_GROUP_KSNAME);
352                         ks->active_path= BLI_countlist(&ks->paths);
353                         success= 1;
354                         
355                         /* free the temp path created */
356                         MEM_freeN(path);
357                 }
358         }
359         
360         if (success) {
361                 /* send updates */
362                 ED_anim_dag_flush_update(C);    
363                 
364                 /* for now, only send ND_KEYS for KeyingSets */
365                 WM_event_add_notifier(C, NC_SCENE|ND_KEYINGSET, NULL);
366         }
367         
368         return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
369 }
370
371 void ANIM_OT_add_keyingset_button (wmOperatorType *ot)
372 {
373         /* identifiers */
374         ot->name= "Add to Keying Set";
375         ot->idname= "ANIM_OT_add_keyingset_button";
376         
377         /* callbacks */
378         ot->exec= add_keyingset_button_exec; 
379         //op->poll= ???
380         
381         /* flags */
382         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
383
384         /* properties */
385         RNA_def_boolean(ot->srna, "all", 1, "All", "Add all elements of the array to a Keying Set.");
386 }
387
388 /* Remove from KeyingSet Button Operator ------------------------ */
389
390 static int remove_keyingset_button_exec (bContext *C, wmOperator *op)
391 {
392         Scene *scene= CTX_data_scene(C);
393         KeyingSet *ks = NULL;
394         PropertyRNA *prop= NULL;
395         PointerRNA ptr;
396         char *path = NULL;
397         short success= 0;
398         int index=0;
399         
400         /* verify the Keying Set to use:
401          *      - use the active one for now (more control over this can be added later)
402          *      - return error if it doesn't exist
403          */
404         if (scene->active_keyingset == 0) {
405                 BKE_report(op->reports, RPT_ERROR, "No active Keying Set to remove property from");
406                 return OPERATOR_CANCELLED;
407         }
408         else
409                 ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
410         
411         /* try to add to keyingset using property retrieved from UI */
412         memset(&ptr, 0, sizeof(PointerRNA));
413         uiAnimContextProperty(C, &ptr, &prop, &index);
414
415         if (ptr.data && prop) {
416                 path= RNA_path_from_ID_to_property(&ptr, prop);
417                 
418                 if (path) {
419                         KS_Path *ksp;
420                         
421                         /* try to find a path matching this description */
422                         ksp= BKE_keyingset_find_destination(ks, ptr.id.data, ks->name, path, index, KSP_GROUP_KSNAME);
423                         
424                         if (ksp) {
425                                 /* just free it... */
426                                 MEM_freeN(ksp->rna_path);
427                                 BLI_freelinkN(&ks->paths, ksp);
428                                 
429                                 success= 1;
430                         }
431                         
432                         /* free temp path used */
433                         MEM_freeN(path);
434                 }
435         }
436         
437         
438         if (success) {
439                 /* send updates */
440                 ED_anim_dag_flush_update(C);    
441                 
442                 /* for now, only send ND_KEYS for KeyingSets */
443                 WM_event_add_notifier(C, NC_SCENE|ND_KEYINGSET, NULL);
444         }
445         
446         return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
447 }
448
449 void ANIM_OT_remove_keyingset_button (wmOperatorType *ot)
450 {
451         /* identifiers */
452         ot->name= "Remove from Keying Set";
453         ot->idname= "ANIM_OT_remove_keyingset_button";
454         
455         /* callbacks */
456         ot->exec= remove_keyingset_button_exec; 
457         //op->poll= ???
458         
459         /* flags */
460         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
461 }
462
463 /* ************************************************** */
464 /* KEYING SETS - EDITING API  */
465
466 /* UI API --------------------------------------------- */
467
468 /* Build menu-string of available keying-sets (allocates memory for string)
469  * NOTE: mode must not be longer than 64 chars
470  */
471 char *ANIM_build_keyingsets_menu (ListBase *list, short for_edit)
472 {
473         DynStr *pupds= BLI_dynstr_new();
474         KeyingSet *ks;
475         char buf[64];
476         char *str;
477         int i;
478         
479         /* add title first */
480         BLI_dynstr_append(pupds, "Keying Sets%t|");
481         
482         /* add dummy entries for none-active */
483         if (for_edit) { 
484                 BLI_dynstr_append(pupds, "Add New%x-1|");
485                 BLI_dynstr_append(pupds, " %x0|");
486         }
487         else
488                 BLI_dynstr_append(pupds, "No Keying Set%x0|");
489         
490         /* loop through keyingsets, adding them */
491         for (ks=list->first, i=1; ks; ks=ks->next, i++) {
492                 if (for_edit == 0)
493                         BLI_dynstr_append(pupds, "KS: ");
494                 
495                 BLI_dynstr_append(pupds, ks->name);
496                 BLI_snprintf( buf, 64, "%%x%d%s", i, ((ks->next)?"|":"") );
497                 BLI_dynstr_append(pupds, buf);
498         }
499         
500         /* convert to normal MEM_malloc'd string */
501         str= BLI_dynstr_get_cstring(pupds);
502         BLI_dynstr_free(pupds);
503         
504         return str;
505 }
506
507
508 /* ******************************************* */
509 /* KEYING SETS - BUILTIN */
510
511 #if 0 // XXX old keyingsets code based on adrcodes... to be restored in due course
512
513 /* ------------- KeyingSet Defines ------------ */
514 /* Note: these must all be named with the defks_* prefix, otherwise the template macro will not work! */
515
516 /* macro for defining keyingset contexts */
517 #define KSC_TEMPLATE(ctx_name) {&defks_##ctx_name[0], NULL, sizeof(defks_##ctx_name)/sizeof(bKeyingSet)}
518
519 /* --- */
520
521 /* check if option not available for deleting keys */
522 static short incl_non_del_keys (bKeyingSet *ks, const char mode[])
523 {
524         /* as optimisation, assume that it is sufficient to check only first letter
525          * of mode (int comparison should be faster than string!)
526          */
527         //if (strcmp(mode, "Delete")==0)
528         if (mode && mode[0]=='D')
529                 return 0;
530         
531         return 1;
532 }
533
534 /* Object KeyingSets  ------ */
535
536 /* check if include shapekey entry  */
537 static short incl_v3d_ob_shapekey (bKeyingSet *ks, const char mode[])
538 {
539         //Object *ob= (G.obedit)? (G.obedit) : (OBACT); // XXX
540         Object *ob= NULL;
541         char *newname= NULL;
542         
543         if(ob==NULL)
544                 return 0;
545         
546         /* not available for delete mode */
547         if (strcmp(mode, "Delete")==0)
548                 return 0;
549         
550         /* check if is geom object that can get shapekeys */
551         switch (ob->type) {
552                 /* geometry? */
553                 case OB_MESH:           newname= "Mesh";                break;
554                 case OB_CURVE:          newname= "Curve";               break;
555                 case OB_SURF:           newname= "Surface";             break;
556                 case OB_LATTICE:        newname= "Lattice";             break;
557                 
558                 /* not geometry! */
559                 default:
560                         return 0;
561         }
562         
563         /* if ks is shapekey entry (this could be callled for separator before too!) */
564         if (ks->flag == -3)
565                 BLI_strncpy(ks->name, newname, sizeof(ks->name));
566         
567         /* if it gets here, it's ok */
568         return 1;
569 }
570
571 /* array for object keyingset defines */
572 bKeyingSet defks_v3d_object[] = 
573 {
574         /* include_cb, adrcode-getter, name, blocktype, flag, chan_num, adrcodes */
575         {NULL, "Loc", ID_OB, 0, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}},
576         {NULL, "Rot", ID_OB, 0, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
577         {NULL, "Scale", ID_OB, 0, 3, {OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
578         
579         {NULL, "%l", 0, -1, 0, {0}}, // separator
580         
581         {NULL, "LocRot", ID_OB, 0, 6, 
582                 {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
583                  OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
584                  
585         {NULL, "LocScale", ID_OB, 0, 6, 
586                 {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
587                  OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
588                  
589         {NULL, "LocRotScale", ID_OB, 0, 9, 
590                 {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
591                  OB_ROT_X,OB_ROT_Y,OB_ROT_Z,
592                  OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
593                  
594         {NULL, "RotScale", ID_OB, 0, 6, 
595                 {OB_ROT_X,OB_ROT_Y,OB_ROT_Z,
596                  OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
597         
598         {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator
599         
600         {incl_non_del_keys, "VisualLoc", ID_OB, INSERTKEY_MATRIX, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}},
601         {incl_non_del_keys, "VisualRot", ID_OB, INSERTKEY_MATRIX, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
602         
603         {incl_non_del_keys, "VisualLocRot", ID_OB, INSERTKEY_MATRIX, 6, 
604                 {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
605                  OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
606         
607         {NULL, "%l", 0, -1, 0, {0}}, // separator
608         
609         {NULL, "Layer", ID_OB, 0, 1, {OB_LAY}}, // icky option...
610         {NULL, "Available", ID_OB, -2, 0, {0}},
611         
612         {incl_v3d_ob_shapekey, "%l%l", 0, -1, 0, {0}}, // separator (linked to shapekey entry)
613         {incl_v3d_ob_shapekey, "<ShapeKey>", ID_OB, -3, 0, {0}}
614 };
615
616 /* PoseChannel KeyingSets  ------ */
617
618 /* array for posechannel keyingset defines */
619 bKeyingSet defks_v3d_pchan[] = 
620 {
621         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
622         {NULL, "Loc", ID_PO, 0, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}},
623         {NULL, "Rot", ID_PO, COMMONKEY_PCHANROT, 1, {KAG_CHAN_EXTEND}},
624         {NULL, "Scale", ID_PO, 0, 3, {AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}},
625         
626         {NULL, "%l", 0, -1, 0, {0}}, // separator
627         
628         {NULL, "LocRot", ID_PO, COMMONKEY_PCHANROT, 4, 
629                 {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,
630                  KAG_CHAN_EXTEND}},
631                  
632         {NULL, "LocScale", ID_PO, 0, 6, 
633                 {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,
634                  AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}},
635                  
636         {NULL, "LocRotScale", ID_PO, COMMONKEY_PCHANROT, 7, 
637                 {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z, 
638                  KAG_CHAN_EXTEND}},
639                  
640         {NULL, "RotScale", ID_PO, 0, 4, 
641                 {AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z, 
642                  KAG_CHAN_EXTEND}},
643         
644         {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator
645         
646         {incl_non_del_keys, "VisualLoc", ID_PO, INSERTKEY_MATRIX, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}},
647         {incl_non_del_keys, "VisualRot", ID_PO, INSERTKEY_MATRIX|COMMONKEY_PCHANROT, 1, {KAG_CHAN_EXTEND}},
648         
649         {incl_non_del_keys, "VisualLocRot", ID_PO, INSERTKEY_MATRIX|COMMONKEY_PCHANROT, 4, 
650                 {AC_LOC_X,AC_LOC_Y,AC_LOC_Z, KAG_CHAN_EXTEND}},
651         
652         {NULL, "%l", 0, -1, 0, {0}}, // separator
653         
654         {NULL, "Available", ID_PO, -2, 0, {0}}
655 };
656
657 /* Material KeyingSets  ------ */
658
659 /* array for material keyingset defines */
660 bKeyingSet defks_buts_shading_mat[] = 
661 {
662         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
663         {NULL, "RGB", ID_MA, 0, 3, {MA_COL_R,MA_COL_G,MA_COL_B}},
664         {NULL, "Alpha", ID_MA, 0, 1, {MA_ALPHA}},
665         {NULL, "Halo Size", ID_MA, 0, 1, {MA_HASIZE}},
666         {NULL, "Mode", ID_MA, 0, 1, {MA_MODE}}, // evil bitflags
667         
668         {NULL, "%l", 0, -1, 0, {0}}, // separator
669         
670         {NULL, "All Color", ID_MA, 0, 18, 
671                 {MA_COL_R,MA_COL_G,MA_COL_B,
672                  MA_ALPHA,MA_HASIZE, MA_MODE,
673                  MA_SPEC_R,MA_SPEC_G,MA_SPEC_B,
674                  MA_REF,MA_EMIT,MA_AMB,MA_SPEC,MA_HARD,
675                  MA_MODE,MA_TRANSLU,MA_ADD}},
676                  
677         {NULL, "All Mirror", ID_MA, 0, 5, 
678                 {MA_RAYM,MA_FRESMIR,MA_FRESMIRI,
679                  MA_FRESTRA,MA_FRESTRAI}},
680         
681         {NULL, "%l", 0, -1, 0, {0}}, // separator
682         
683         {NULL, "Ofs", ID_MA, COMMONKEY_ADDMAP, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
684         {NULL, "Size", ID_MA, COMMONKEY_ADDMAP, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
685         
686         {NULL, "All Mapping", ID_MA, COMMONKEY_ADDMAP, 14, 
687                 {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
688                  MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
689                  MAP_R,MAP_G,MAP_B,MAP_DVAR,
690                  MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
691         
692         {NULL, "%l", 0, -1, 0, {0}}, // separator
693         
694         {NULL, "Available", ID_MA, -2, 0, {0}}
695 };
696
697 /* World KeyingSets  ------ */
698
699 /* array for world keyingset defines */
700 bKeyingSet defks_buts_shading_wo[] = 
701 {
702         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
703         {NULL, "Zenith RGB", ID_WO, 0, 3, {WO_ZEN_R,WO_ZEN_G,WO_ZEN_B}},
704         {NULL, "Horizon RGB", ID_WO, 0, 3, {WO_HOR_R,WO_HOR_G,WO_HOR_B}},
705         
706         {NULL, "%l", 0, -1, 0, {0}}, // separator
707         
708         {NULL, "Mist", ID_WO, 0, 4, {WO_MISI,WO_MISTDI,WO_MISTSTA,WO_MISTHI}},
709         {NULL, "Stars", ID_WO, 0, 5, {WO_STAR_R,WO_STAR_G,WO_STAR_B,WO_STARDIST,WO_STARSIZE}},
710         
711         
712         {NULL, "%l", 0, -1, 0, {0}}, // separator
713         
714         {NULL, "Ofs", ID_WO, COMMONKEY_ADDMAP, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
715         {NULL, "Size", ID_WO, COMMONKEY_ADDMAP, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
716         
717         {NULL, "All Mapping", ID_WO, COMMONKEY_ADDMAP, 14, 
718                 {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
719                  MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
720                  MAP_R,MAP_G,MAP_B,MAP_DVAR,
721                  MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
722         
723         {NULL, "%l", 0, -1, 0, {0}}, // separator
724         
725         {NULL, "Available", ID_WO, -2, 0, {0}}
726 };
727
728 /* Lamp KeyingSets  ------ */
729
730 /* array for lamp keyingset defines */
731 bKeyingSet defks_buts_shading_la[] = 
732 {
733         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
734         {NULL, "RGB", ID_LA, 0, 3, {LA_COL_R,LA_COL_G,LA_COL_B}},
735         {NULL, "Energy", ID_LA, 0, 1, {LA_ENERGY}},
736         {NULL, "Spot Size", ID_LA, 0, 1, {LA_SPOTSI}},
737         
738         {NULL, "%l", 0, -1, 0, {0}}, // separator
739         
740         {NULL, "Ofs", ID_LA, COMMONKEY_ADDMAP, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
741         {NULL, "Size", ID_LA, COMMONKEY_ADDMAP, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
742         
743         {NULL, "All Mapping", ID_LA, COMMONKEY_ADDMAP, 14, 
744                 {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
745                  MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
746                  MAP_R,MAP_G,MAP_B,MAP_DVAR,
747                  MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
748         
749         {NULL, "%l", 0, -1, 0, {0}}, // separator
750         
751         {NULL, "Available", ID_LA, -2, 0, {0}}
752 };
753
754 /* Texture KeyingSets  ------ */
755
756 /* array for texture keyingset defines */
757 bKeyingSet defks_buts_shading_tex[] = 
758 {
759         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
760         {NULL, "Clouds", ID_TE, 0, 5, 
761                 {TE_NSIZE,TE_NDEPTH,TE_NTYPE,
762                  TE_MG_TYP,TE_N_BAS1}},
763         
764         {NULL, "Marble", ID_TE, 0, 7, 
765                 {TE_NSIZE,TE_NDEPTH,TE_NTYPE,
766                  TE_TURB,TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}},
767                  
768         {NULL, "Stucci", ID_TE, 0, 5, 
769                 {TE_NSIZE,TE_NTYPE,TE_TURB,
770                  TE_MG_TYP,TE_N_BAS1}},
771                  
772         {NULL, "Wood", ID_TE, 0, 6, 
773                 {TE_NSIZE,TE_NTYPE,TE_TURB,
774                  TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}},
775                  
776         {NULL, "Magic", ID_TE, 0, 2, {TE_NDEPTH,TE_TURB}},
777         
778         {NULL, "Blend", ID_TE, 0, 1, {TE_MG_TYP}},      
779                 
780         {NULL, "Musgrave", ID_TE, 0, 6, 
781                 {TE_MG_TYP,TE_MGH,TE_MG_LAC,
782                  TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN}},
783                  
784         {NULL, "Voronoi", ID_TE, 0, 9, 
785                 {TE_VNW1,TE_VNW2,TE_VNW3,TE_VNW4,
786                 TE_VNMEXP,TE_VN_DISTM,TE_VN_COLT,
787                 TE_ISCA,TE_NSIZE}},
788                 
789         {NULL, "Distorted Noise", ID_TE, 0, 4, 
790                 {TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN,TE_DISTA}},
791         
792         {NULL, "Color Filter", ID_TE, 0, 5, 
793                 {TE_COL_R,TE_COL_G,TE_COL_B,TE_BRIGHT,TE_CONTRA}},
794         
795         {NULL, "%l", 0, -1, 0, {0}}, // separator
796         
797         {NULL, "Available", ID_TE, -2, 0, {0}}
798 };
799
800 /* Object Buttons KeyingSets  ------ */
801
802 /* check if include particles entry  */
803 static short incl_buts_ob (bKeyingSet *ks, const char mode[])
804 {
805         //Object *ob= OBACT; // xxx
806         Object *ob= NULL;
807         /* only if object is mesh type */
808         
809         if(ob==NULL) return 0;
810         return (ob->type == OB_MESH);
811 }
812
813 /* array for texture keyingset defines */
814 bKeyingSet defks_buts_object[] = 
815 {
816         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
817         {incl_buts_ob, "Surface Damping", ID_OB, 0, 1, {OB_PD_SDAMP}},
818         {incl_buts_ob, "Random Damping", ID_OB, 0, 1, {OB_PD_RDAMP}},
819         {incl_buts_ob, "Permeability", ID_OB, 0, 1, {OB_PD_PERM}},
820         
821         {NULL, "%l", 0, -1, 0, {0}}, // separator
822         
823         {NULL, "Force Strength", ID_OB, 0, 1, {OB_PD_FSTR}},
824         {NULL, "Force Falloff", ID_OB, 0, 1, {OB_PD_FFALL}},
825         
826         {NULL, "%l", 0, -1, 0, {0}}, // separator
827         
828         {NULL, "Available", ID_OB, -2, 0, {0}}  // this will include ob-transforms too!
829 };
830
831 /* Camera Buttons KeyingSets  ------ */
832
833 /* check if include internal-renderer entry  */
834 static short incl_buts_cam1 (bKeyingSet *ks, const char mode[])
835 {
836         Scene *scene= NULL; // FIXME this will cause a crash, but we need an extra arg first!
837         /* only if renderer is internal renderer */
838         return (scene->r.renderer==R_INTERN);
839 }
840
841 /* check if include external-renderer entry  */
842 static short incl_buts_cam2 (bKeyingSet *ks, const char mode[])
843 {
844         Scene *scene= NULL; // FIXME this will cause a crash, but we need an extra arg first!
845         /* only if renderer is internal renderer */
846         return (scene->r.renderer!=R_INTERN);
847 }
848
849 /* array for camera keyingset defines */
850 bKeyingSet defks_buts_cam[] = 
851 {
852         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
853         {NULL, "Lens", ID_CA, 0, 1, {CAM_LENS}},
854         {NULL, "Clipping", ID_CA, 0, 2, {CAM_STA,CAM_END}},
855         {NULL, "Focal Distance", ID_CA, 0, 1, {CAM_YF_FDIST}},
856         
857         {NULL, "%l", 0, -1, 0, {0}}, // separator
858         
859         
860         {incl_buts_cam2, "Aperture", ID_CA, 0, 1, {CAM_YF_APERT}},
861         {incl_buts_cam1, "Viewplane Shift", ID_CA, 0, 2, {CAM_SHIFT_X,CAM_SHIFT_Y}},
862         
863         {NULL, "%l", 0, -1, 0, {0}}, // separator
864         
865         {NULL, "Available", ID_CA, -2, 0, {0}}
866 };
867
868 /* --- */
869
870 /* Keying Context Defines - Must keep in sync with enumeration (eKS_Contexts) */
871 bKeyingContext ks_contexts[] = 
872 {
873         KSC_TEMPLATE(v3d_object),
874         KSC_TEMPLATE(v3d_pchan),
875         
876         KSC_TEMPLATE(buts_shading_mat),
877         KSC_TEMPLATE(buts_shading_wo),
878         KSC_TEMPLATE(buts_shading_la),
879         KSC_TEMPLATE(buts_shading_tex),
880
881         KSC_TEMPLATE(buts_object),
882         KSC_TEMPLATE(buts_cam)
883 };
884
885 /* Keying Context Enumeration - Must keep in sync with definitions*/
886 typedef enum eKS_Contexts {
887         KSC_V3D_OBJECT = 0,
888         KSC_V3D_PCHAN,
889         
890         KSC_BUTS_MAT,
891         KSC_BUTS_WO,
892         KSC_BUTS_LA,
893         KSC_BUTS_TEX,
894         
895         KSC_BUTS_OB,
896         KSC_BUTS_CAM,
897         
898                 /* make sure this last one remains untouched! */
899         KSC_TOT_TYPES
900 } eKS_Contexts;
901
902
903 #endif // XXX old keyingsets code based on adrcodes... to be restored in due course
904
905 /* Macros for Declaring KeyingSets ------------------- */
906
907 /* A note about this system for declaring built-in Keying Sets:
908  *      One may ask, "What is the purpose of all of these macros and static arrays?" and 
909  *      "Why not call the KeyingSets API defined in BKE_animsys.h?". The answer is two-fold.
910  *      
911  *      1) Firstly, we use static arrays of struct definitions instead of function calls, as
912  *         it reduces the start-up overhead and allocated-memory footprint of Blender. If we called
913  *         the KeyingSets API to build these sets, the overhead of checking for unique names, allocating
914  *         memory for each and every path and KeyingSet, scattered around in RAM, all of which would increase
915  *         the startup time (which is totally unacceptable) and could lead to fragmentation+slower access times.
916  *      2) Since we aren't using function calls, we need a nice way of defining these KeyingSets in a way which
917  *         is easily readable and less prone to breakage from changes to the underlying struct definitions. Further,
918  *         adding additional entries SHOULD NOT require custom code to be written to access these new entries/sets. 
919  *         Therefore, here we have a system with nice, human-readable statements via macros, and static arrays which
920  *         are linked together using more special macros + struct definitions, allowing for such a generic + simple
921  *         initialisation function (init_builtin_keyingsets()) compared with that of something like the Nodes system.
922  *
923  * -- Joshua Leung, April 2009
924  */
925
926 /* Struct type for declaring builtin KeyingSets in as entries in static arrays*/
927 typedef struct bBuiltinKeyingSet {
928         KeyingSet ks;                   /* the KeyingSet to build */
929         int tot;                                /* the total number of paths defined */
930         KS_Path paths[64];              /* the paths for the KeyingSet to use */
931 } bBuiltinKeyingSet;
932
933         /* WARNING: the following macros must be kept in sync with the 
934          * struct definitions in DNA_anim_types.h! 
935          */
936
937 /* macro for defining a builtin KeyingSet */
938 #define BI_KS_DEFINE_BEGIN(name, keyingflag) \
939         {{NULL, NULL, {NULL, NULL}, name, KEYINGSET_BUILTIN, keyingflag},
940         
941 /* macro to finish defining a builtin KeyingSet */
942 #define BI_KS_DEFINE_END \
943         }
944         
945 /* macro to start defining paths for a builtin KeyingSet */
946 #define BI_KS_PATHS_BEGIN(tot) \
947         tot, {
948         
949 /* macro to finish defining paths for a builtin KeyingSet */
950 #define BI_KS_PATHS_END \
951         }
952         
953 /* macro for defining a builtin KeyingSet's path */
954 #define BI_KSP_DEFINE(id_type, templates, prop_path, array_index, flag, groupflag) \
955         {NULL, NULL, NULL, "", id_type, templates, prop_path, array_index, flag, groupflag}
956         
957 /* macro for defining a builtin KeyingSet with no paths (use in place of BI_KS_PAHTS_BEGIN/END block) */
958 #define BI_KS_PATHS_NONE \
959         0, {0}
960         
961 /* ---- */
962
963 /* Struct type for finding all the arrays of builtin KeyingSets */
964 typedef struct bBuiltinKSContext {
965         bBuiltinKeyingSet *bks;         /* array of KeyingSet definitions */
966         int tot;                                        /* number of KeyingSets in this array */
967 } bBuiltinKSContext;
968
969 /* macro for defining builtin KeyingSet sets 
970  * NOTE: all the arrays of sets must follow this naming convention!
971  */
972 #define BKSC_TEMPLATE(ctx_name) {&def_builtin_keyingsets_##ctx_name[0], sizeof(def_builtin_keyingsets_##ctx_name)/sizeof(bBuiltinKeyingSet)}
973
974
975 /* 3D-View Builtin KeyingSets ------------------------ */
976
977 static bBuiltinKeyingSet def_builtin_keyingsets_v3d[] =
978 {
979         /* Simple Keying Sets ************************************* */
980         /* Keying Set - "Location" ---------- */
981         BI_KS_DEFINE_BEGIN("Location", 0)
982                 BI_KS_PATHS_BEGIN(1)
983                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) 
984                 BI_KS_PATHS_END
985         BI_KS_DEFINE_END,
986
987         /* Keying Set - "Rotation" ---------- */
988         BI_KS_DEFINE_BEGIN("Rotation", 0)
989                 BI_KS_PATHS_BEGIN(1)
990                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN|KSP_TEMPLATE_ROT, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) 
991                 BI_KS_PATHS_END
992         BI_KS_DEFINE_END,
993         
994         /* Keying Set - "Scaling" ---------- */
995         BI_KS_DEFINE_BEGIN("Scaling", 0)
996                 BI_KS_PATHS_BEGIN(1)
997                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "scale", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) 
998                 BI_KS_PATHS_END
999         BI_KS_DEFINE_END,
1000         
1001         /* Compound Keying Sets *********************************** */
1002         /* Keying Set - "LocRot" ---------- */
1003         BI_KS_DEFINE_BEGIN("LocRot", 0)
1004                 BI_KS_PATHS_BEGIN(2)
1005                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM), 
1006                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN|KSP_TEMPLATE_ROT, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) 
1007                 BI_KS_PATHS_END
1008         BI_KS_DEFINE_END,
1009         
1010         /* Keying Set - "LocRotScale" ---------- */
1011         BI_KS_DEFINE_BEGIN("LocRotScale", 0)
1012                 BI_KS_PATHS_BEGIN(3)
1013                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM), 
1014                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN|KSP_TEMPLATE_ROT, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM), 
1015                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "scale", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) 
1016                 BI_KS_PATHS_END
1017         BI_KS_DEFINE_END,
1018         
1019         /* Keying Sets with Keying Flags ************************* */
1020         /* Keying Set - "VisualLoc" ---------- */
1021         BI_KS_DEFINE_BEGIN("VisualLoc", INSERTKEY_MATRIX)
1022                 BI_KS_PATHS_BEGIN(1)
1023                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) 
1024                 BI_KS_PATHS_END
1025         BI_KS_DEFINE_END,
1026
1027         /* Keying Set - "Rotation" ---------- */
1028         BI_KS_DEFINE_BEGIN("VisualRot", INSERTKEY_MATRIX)
1029                 BI_KS_PATHS_BEGIN(1)
1030                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN|KSP_TEMPLATE_ROT, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) 
1031                 BI_KS_PATHS_END
1032         BI_KS_DEFINE_END,
1033         
1034         /* Keying Set - "VisualLocRot" ---------- */
1035         BI_KS_DEFINE_BEGIN("VisualLocRot", INSERTKEY_MATRIX)
1036                 BI_KS_PATHS_BEGIN(2)
1037                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM), 
1038                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN|KSP_TEMPLATE_ROT, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) 
1039                 BI_KS_PATHS_END
1040         BI_KS_DEFINE_END
1041 };
1042
1043 /* All Builtin KeyingSets ------------------------ */
1044
1045 /* total number of builtin KeyingSet contexts */
1046 #define MAX_BKSC_TYPES  1
1047
1048 /* array containing all the available builtin KeyingSets definition sets 
1049  *      - size of this is MAX_BKSC_TYPES+1 so that we don't smash the stack
1050  */
1051 static bBuiltinKSContext def_builtin_keyingsets[MAX_BKSC_TYPES+1] =
1052 {
1053         BKSC_TEMPLATE(v3d)
1054         /* add more contexts above this line... */
1055 };
1056
1057
1058 /* ListBase of these KeyingSets chained up ready for usage 
1059  * NOTE: this is exported to keyframing.c for use...
1060  */
1061 ListBase builtin_keyingsets = {NULL, NULL};
1062
1063 /* Utility API ------------------------ */
1064
1065 /* Link up all of the builtin Keying Sets when starting up Blender
1066  * This is called from WM_init() in wm_init_exit.c
1067  */
1068 void init_builtin_keyingsets (void)
1069 {
1070         bBuiltinKSContext *bksc;
1071         bBuiltinKeyingSet *bks;
1072         int bksc_i, bks_i;
1073         
1074         /* loop over all the sets of KeyingSets, setting them up, and chaining them to the builtins list */
1075         for (bksc_i= 0, bksc= &def_builtin_keyingsets[0]; bksc_i < MAX_BKSC_TYPES; bksc_i++, bksc++)
1076         {
1077                 /* for each set definitions for a builtin KeyingSet, chain the paths to that KeyingSet and add */
1078                 for (bks_i= 0, bks= bksc->bks; bks_i < bksc->tot; bks_i++, bks++)
1079                 {
1080                         KeyingSet *ks= &bks->ks;
1081                         KS_Path *ksp;
1082                         int pIndex;
1083                         
1084                         /* loop over paths, linking them to the KeyingSet and each other */
1085                         for (pIndex= 0, ksp= &bks->paths[0]; pIndex < bks->tot; pIndex++, ksp++)
1086                                 BLI_addtail(&ks->paths, ksp);
1087                                 
1088                         /* add KeyingSet to builtin sets list */
1089                         BLI_addtail(&builtin_keyingsets, ks);
1090                 }
1091         }
1092 }
1093
1094
1095 /* Get the first builtin KeyingSet with the given name, which occurs after the given one (or start of list if none given) */
1096 KeyingSet *ANIM_builtin_keyingset_get_named (KeyingSet *prevKS, char name[])
1097 {
1098         KeyingSet *ks, *first=NULL;
1099         
1100         /* sanity checks - any name to check? */
1101         if (name[0] == 0)
1102                 return NULL;
1103         
1104         /* get first KeyingSet to use */
1105         if (prevKS && prevKS->next)
1106                 first= prevKS->next;
1107         else
1108                 first= builtin_keyingsets.first;
1109                 
1110         /* loop over KeyingSets checking names */
1111         for (ks= first; ks; ks= ks->next) {
1112                 if (strcmp(name, ks->name) == 0)
1113                         return ks;
1114         }
1115         
1116         /* no matches found */
1117         return NULL;
1118 }
1119
1120
1121 /* Get the active Keying Set for the Scene provided */
1122 KeyingSet *ANIM_scene_get_active_keyingset (Scene *scene)
1123 {
1124         if (ELEM(NULL, scene, scene->keyingsets.first))
1125                 return NULL;
1126         
1127         /* currently, there are several possibilities here:
1128          *      -   0: no active keying set
1129          *      - > 0: one of the user-defined Keying Sets, but indices start from 0 (hence the -1)
1130          *      - < 0: a builtin keying set (XXX this isn't enabled yet so that we don't get errors on reading back files)
1131          */
1132         if (scene->active_keyingset > 0)
1133                 return BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
1134         else // for now...
1135                 return NULL; 
1136 }
1137
1138 /* ******************************************* */
1139 /* KEYFRAME MODIFICATION */
1140
1141 /* KeyingSet Menu Helpers ------------ */
1142
1143 /* Extract the maximum set of requirements from the KeyingSet */
1144 static int keyingset_relative_get_templates (KeyingSet *ks)
1145 {
1146         KS_Path *ksp;
1147         int templates= 0;
1148         
1149         /* loop over the paths (could be slow to do for a number of KeyingSets)? */
1150         for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
1151                 /* add the destination's templates to the set of templates required for the set */
1152                 templates |= ksp->templates;
1153         }
1154         
1155         return templates;
1156 }
1157
1158 /* Check if context data is suitable for the given absolute Keying Set */
1159 short keyingset_context_ok_poll (bContext *C, KeyingSet *ks)
1160 {
1161         ScrArea *sa= CTX_wm_area(C);
1162         
1163         /* data retrieved from context depends on active editor */
1164         if (sa == NULL) return 0;
1165                 
1166         switch (sa->spacetype) {
1167                 case SPACE_VIEW3D:
1168                 {
1169                         Object *obact= CTX_data_active_object(C);
1170                         
1171                         /* if in posemode, check if 'pose-channels' requested for in KeyingSet */
1172                         if ((obact && obact->pose) && (obact->mode & OB_MODE_POSE)) {
1173                                 /* check for posechannels */
1174                                 
1175                         }
1176                         else {
1177                                 /* check for selected object */
1178                                 
1179                         }
1180                 }
1181                         break;
1182         }
1183         
1184         
1185         return 1;
1186 }
1187
1188 /* KeyingSet Context Operations ------------ */
1189
1190 /* Get list of data-sources from context (in 3D-View) for inserting keyframes using the given relative Keying Set */
1191 static short modifykey_get_context_v3d_data (bContext *C, ListBase *dsources, KeyingSet *ks)
1192 {
1193         bCommonKeySrc *cks;
1194         Object *obact= CTX_data_active_object(C);
1195         int templates; 
1196         short ok= 0;
1197         
1198         /* get the templates in use in this KeyingSet which we should supply data for */
1199         templates = keyingset_relative_get_templates(ks);
1200         
1201         /* check if the active object is in PoseMode (i.e. only deal with bones) */
1202         // TODO: check with the templates to see what we really need to store 
1203         if ((obact && obact->pose) && (obact->mode & OB_MODE_POSE)) {
1204                 /* Pose Mode: Selected bones */
1205 #if 0
1206                 //set_pose_keys(ob);  /* sets pchan->flag to POSE_KEY if bone selected, and clears if not */
1207                 
1208                 /* loop through posechannels */
1209                 //for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
1210                 //      if (pchan->flag & POSE_KEY) {
1211                 //      }
1212                 //}
1213 #endif
1214                 
1215                 CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans)
1216                 {
1217                         /* add a new keying-source */
1218                         cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1219                         BLI_addtail(dsources, cks);
1220                         
1221                         /* set necessary info */
1222                         cks->id= &obact->id;
1223                         cks->pchan= pchan;
1224                         
1225                         if (templates & KSP_TEMPLATE_CONSTRAINT)
1226                                 cks->con= constraints_get_active(&pchan->constraints);
1227                         
1228                         ok= 1;
1229                 }
1230                 CTX_DATA_END;
1231         }
1232         else {
1233                 /* Object Mode: Selected objects */
1234                 CTX_DATA_BEGIN(C, Base*, base, selected_bases) 
1235                 {
1236                         Object *ob= base->object;
1237                         
1238                         /* add a new keying-source */
1239                         cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1240                         BLI_addtail(dsources, cks);
1241                         
1242                         /* set necessary info */
1243                         cks->id= &ob->id;
1244                         
1245                         if (templates & KSP_TEMPLATE_CONSTRAINT)
1246                                 cks->con= constraints_get_active(&ob->constraints);
1247                         
1248                         ok= 1;
1249                 }
1250                 CTX_DATA_END;
1251         }
1252         
1253         /* return whether any data was extracted */
1254         return ok;
1255 }
1256
1257 /* Get list of data-sources from context for inserting keyframes using the given relative Keying Set */
1258 short modifykey_get_context_data (bContext *C, ListBase *dsources, KeyingSet *ks)
1259 {
1260         ScrArea *sa= CTX_wm_area(C);
1261         
1262         /* for now, the active area is used to determine what set of contexts apply */
1263         if (sa == NULL)
1264                 return 0;
1265                 
1266         switch (sa->spacetype) {
1267                 case SPACE_VIEW3D:      /* 3D-View: Selected Objects or Bones */
1268                         return modifykey_get_context_v3d_data(C, dsources, ks);
1269         }
1270         
1271         /* nothing happened */
1272         return 0;
1273
1274
1275 /* KeyingSet Operations (Insert/Delete Keyframes) ------------ */
1276
1277 /* Given a KeyingSet and context info (if required), modify keyframes for the channels specified
1278  * by the KeyingSet. This takes into account many of the different combinations of using KeyingSets.
1279  * Returns the number of channels that keyframes were added to
1280  */
1281 int modify_keyframes (Scene *scene, ListBase *dsources, bAction *act, KeyingSet *ks, short mode, float cfra)
1282 {
1283         KS_Path *ksp;
1284         int kflag=0, success= 0;
1285         char *groupname= NULL;
1286         
1287         /* get flags to use */
1288         if (mode == MODIFYKEY_MODE_INSERT) {
1289                 /* use KeyingSet's flags as base */
1290                 kflag= ks->keyingflag;
1291                 
1292                 /* suppliment with info from the context */
1293                 if (IS_AUTOKEY_FLAG(AUTOMATKEY)) kflag |= INSERTKEY_MATRIX;
1294                 if (IS_AUTOKEY_FLAG(INSERTNEEDED)) kflag |= INSERTKEY_NEEDED;
1295                 if (IS_AUTOKEY_MODE(scene, EDITKEYS)) kflag |= INSERTKEY_REPLACE;
1296         }
1297         else if (mode == MODIFYKEY_MODE_DELETE)
1298                 kflag= 0;
1299         
1300         /* check if the KeyingSet is absolute or not (i.e. does it requires sources info) */
1301         if (ks->flag & KEYINGSET_ABSOLUTE) {
1302                 /* Absolute KeyingSets are simpler to use, as all the destination info has already been
1303                  * provided by the user, and is stored, ready to use, in the KeyingSet paths.
1304                  */
1305                 for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
1306                         int arraylen, i;
1307                         
1308                         /* get pointer to name of group to add channels to */
1309                         if (ksp->groupmode == KSP_GROUP_NONE)
1310                                 groupname= NULL;
1311                         else if (ksp->groupmode == KSP_GROUP_KSNAME)
1312                                 groupname= ks->name;
1313                         else
1314                                 groupname= ksp->group;
1315                         
1316                         /* init arraylen and i - arraylen should be greater than i so that
1317                          * normal non-array entries get keyframed correctly
1318                          */
1319                         i= ksp->array_index;
1320                         arraylen= i;
1321                         
1322                         /* get length of array if whole array option is enabled */
1323                         if (ksp->flag & KSP_FLAG_WHOLE_ARRAY) {
1324                                 PointerRNA id_ptr, ptr;
1325                                 PropertyRNA *prop;
1326                                 
1327                                 RNA_id_pointer_create(ksp->id, &id_ptr);
1328                                 if (RNA_path_resolve(&id_ptr, ksp->rna_path, &ptr, &prop) && prop)
1329                                         arraylen= RNA_property_array_length(&ptr, prop);
1330                         }
1331                         
1332                         /* we should do at least one step */
1333                         if (arraylen == i)
1334                                 arraylen++;
1335                         
1336                         /* for each possible index, perform operation 
1337                          *      - assume that arraylen is greater than index
1338                          */
1339                         for (; i < arraylen; i++) {
1340                                 /* action to take depends on mode */
1341                                 if (mode == MODIFYKEY_MODE_INSERT)
1342                                         success+= insert_keyframe(ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag);
1343                                 else if (mode == MODIFYKEY_MODE_DELETE)
1344                                         success+= delete_keyframe(ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag);
1345                         }
1346                         
1347                         /* set recalc-flags */
1348                         if (ksp->id) {
1349                                 switch (GS(ksp->id->name)) {
1350                                         case ID_OB: /* Object (or Object-Related) Keyframes */
1351                                         {
1352                                                 Object *ob= (Object *)ksp->id;
1353                                                 
1354                                                 ob->recalc |= OB_RECALC;
1355                                         }
1356                                                 break;
1357                                 }
1358                                 
1359                                 /* send notifiers for updates (this doesn't require context to work!) */
1360                                 WM_main_add_notifier(NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
1361                         }
1362                 }
1363         }
1364         else if (dsources && dsources->first) {
1365                 /* for each one of the 'sources', resolve the template markers and expand arrays, then insert keyframes */
1366                 bCommonKeySrc *cks;
1367                 
1368                 /* for each 'source' for keyframe data, resolve each of the paths from the KeyingSet */
1369                 for (cks= dsources->first; cks; cks= cks->next) {
1370                         /* for each path in KeyingSet, construct a path using the templates */
1371                         for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
1372                                 DynStr *pathds= BLI_dynstr_new();
1373                                 char *path = NULL;
1374                                 int arraylen, i;
1375                                 
1376                                 /* set initial group name */
1377                                 if (cks->id == NULL) {
1378                                         printf("ERROR: Skipping 'Common-Key' Source. No valid ID present.\n");
1379                                         continue;
1380                                 }
1381                                 else
1382                                         groupname= cks->id->name+2;
1383                                 
1384                                 /* construct the path */
1385                                 // FIXME: this currently only works with a few hardcoded cases
1386                                 if ((ksp->templates & KSP_TEMPLATE_PCHAN) && (cks->pchan)) {
1387                                         /* add basic pose-channel path access */
1388                                         BLI_dynstr_append(pathds, "pose.pose_channels[\"");
1389                                         BLI_dynstr_append(pathds, cks->pchan->name);
1390                                         BLI_dynstr_append(pathds, "\"]");
1391                                         
1392                                         /* override default group name */
1393                                         groupname= cks->pchan->name;
1394                                 }
1395                                 if ((ksp->templates & KSP_TEMPLATE_CONSTRAINT) && (cks->con)) {
1396                                         /* add basic constraint path access */
1397                                         BLI_dynstr_append(pathds, "constraints[\"");
1398                                         BLI_dynstr_append(pathds, cks->con->name);
1399                                         BLI_dynstr_append(pathds, "\"]");
1400                                         
1401                                         /* override default group name */
1402                                         groupname= cks->con->name;
1403                                 }
1404                                 {
1405                                         /* add property stored in KeyingSet Path */
1406                                         if (BLI_dynstr_get_len(pathds))
1407                                                 BLI_dynstr_append(pathds, ".");
1408                                                 
1409                                         /* apply some further templates? */
1410                                         if (ksp->templates & KSP_TEMPLATE_ROT) {
1411                                                 /* for builtin Keying Sets, this template makes the best fitting path for the 
1412                                                  * current rotation mode of the Object / PoseChannel to be used
1413                                                  */
1414                                                 if (strcmp(ksp->rna_path, "rotation")==0) {
1415                                                         /* get rotation mode */
1416                                                         short rotmode= (cks->pchan)? (cks->pchan->rotmode) : 
1417                                                                                    (GS(cks->id->name)==ID_OB)? ( ((Object *)cks->id)->rotmode ) :
1418                                                                                    (0);
1419                                                         
1420                                                         /* determine path to build */
1421                                                         if (rotmode == ROT_MODE_QUAT)
1422                                                                 BLI_dynstr_append(pathds, "rotation_quaternion");
1423                                                         else if (rotmode == ROT_MODE_AXISANGLE)
1424                                                                 BLI_dynstr_append(pathds, "rotation_axis_angle");
1425                                                         else
1426                                                                 BLI_dynstr_append(pathds, "rotation_euler");
1427                                                 }
1428                                         }
1429                                         else {
1430                                                 /* just directly use the path */
1431                                                 BLI_dynstr_append(pathds, ksp->rna_path);
1432                                         }
1433                                         
1434                                         /* convert to C-string */
1435                                         path= BLI_dynstr_get_cstring(pathds);
1436                                         BLI_dynstr_free(pathds);
1437                                 }
1438                                 
1439                                 /* get pointer to name of group to add channels to 
1440                                  *      - KSP_GROUP_TEMPLATE_ITEM is handled above while constructing the paths 
1441                                  */
1442                                 if (ksp->groupmode == KSP_GROUP_NONE)
1443                                         groupname= NULL;
1444                                 else if (ksp->groupmode == KSP_GROUP_KSNAME)
1445                                         groupname= ks->name;
1446                                 else if (ksp->groupmode == KSP_GROUP_NAMED)
1447                                         groupname= ksp->group;
1448                                 
1449                                 /* init arraylen and i - arraylen should be greater than i so that
1450                                  * normal non-array entries get keyframed correctly
1451                                  */
1452                                 i= ksp->array_index;
1453                                 arraylen= i+1;
1454                                 
1455                                 /* get length of array if whole array option is enabled */
1456                                 if (ksp->flag & KSP_FLAG_WHOLE_ARRAY) {
1457                                         PointerRNA id_ptr, ptr;
1458                                         PropertyRNA *prop;
1459                                         
1460                                         RNA_id_pointer_create(cks->id, &id_ptr);
1461                                         if (RNA_path_resolve(&id_ptr, path, &ptr, &prop) && prop)
1462                                                 arraylen= RNA_property_array_length(&ptr, prop);
1463                                 }
1464                                 
1465                                 /* for each possible index, perform operation 
1466                                  *      - assume that arraylen is greater than index
1467                                  */
1468                                 for (; i < arraylen; i++) {
1469                                         /* action to take depends on mode */
1470                                         if (mode == MODIFYKEY_MODE_INSERT)
1471                                                 success+= insert_keyframe(cks->id, act, groupname, path, i, cfra, kflag);
1472                                         else if (mode == MODIFYKEY_MODE_DELETE)
1473                                                 success+= delete_keyframe(cks->id, act, groupname, path, i, cfra, kflag);
1474                                 }
1475                                 
1476                                 /* free the path */
1477                                 MEM_freeN(path);
1478                         }
1479                         
1480                         /* set recalc-flags */
1481                         if (cks->id) {
1482                                 switch (GS(cks->id->name)) {
1483                                         case ID_OB: /* Object (or Object-Related) Keyframes */
1484                                         {
1485                                                 Object *ob= (Object *)cks->id;
1486                                                 
1487                                                 ob->recalc |= OB_RECALC;
1488                                         }
1489                                                 break;
1490                                 }
1491                                 
1492                                 /* send notifiers for updates (this doesn't require context to work!) */
1493                                 WM_main_add_notifier(NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
1494                         }
1495                 }
1496         }
1497         
1498         /* return the number of channels successfully affected */
1499         return success;
1500 }
1501
1502 /* ************************************************** */