RNA
[blender.git] / source / blender / editors / animation / keyingsets.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 #include "anim_intern.h"
54
55 /* ************************************************** */
56 /* KEYING SETS - EDITING API  */
57
58 /* Operators ------------------------------------------- */
59
60 /* These operators are only provided for scripting/macro usage, not for direct
61  * calling from the UI since they wrap some of the data-access API code for these
62  * (defined in blenkernel) which have quite a few properties.
63  */
64
65 /* ----- */
66
67 static int keyingset_add_destination_exec (bContext *C, wmOperator *op)
68 {
69         PointerRNA ptr;
70         KeyingSet *ks= NULL;
71         ID *id= NULL;
72         char rna_path[256], group_name[64]; // xxx
73         short groupmode=0, flag=0;
74         int array_index=0;
75         
76         /* get settings from operator properties */
77         ptr = RNA_pointer_get(op->ptr, "keyingset");
78         if (ptr.data) 
79                 ks= (KeyingSet *)ptr.data;
80         
81         ptr = RNA_pointer_get(op->ptr, "id");
82         if (ptr.data)
83                 id= (ID *)ptr.data;
84         
85         groupmode= RNA_enum_get(op->ptr, "grouping_method");
86         RNA_string_get(op->ptr, "group_name", group_name);              
87         
88         RNA_string_get(op->ptr, "rna_path", rna_path);
89         array_index= RNA_int_get(op->ptr, "array_index");
90         
91         if (RNA_boolean_get(op->ptr, "entire_array"))
92                 flag |= KSP_FLAG_WHOLE_ARRAY;
93         
94         /* if enough args are provided, call API method */
95         if (ks) {
96                 BKE_keyingset_add_destination(ks, id, group_name, rna_path, array_index, flag, groupmode);
97                 return OPERATOR_FINISHED;
98         }
99         else {
100                 BKE_report(op->reports, RPT_ERROR, "Keying Set could not be added.");
101                 return OPERATOR_CANCELLED;
102         }       
103 }
104
105 void ANIM_OT_keyingset_add_destination (wmOperatorType *ot)
106 {
107         // XXX: this is also defined in rna_animation.c
108         static EnumPropertyItem prop_mode_grouping_items[] = {
109                 {KSP_GROUP_NAMED, "NAMED", 0, "Named Group", ""},
110                 {KSP_GROUP_NONE, "NONE", 0, "None", ""},
111                 {KSP_GROUP_KSNAME, "KEYINGSET", 0, "Keying Set Name", ""},
112                 {0, NULL, 0, NULL, NULL}};
113         
114         /* identifiers */
115         ot->name= "Add Keying Set Destination";
116         ot->idname= "ANIM_OT_keyingset_add_destination";
117         
118         /* callbacks */
119         ot->exec= keyingset_add_destination_exec;
120         ot->poll= ED_operator_scene_editable;
121         
122         /* props */
123                 /* pointers */ // xxx - do we want to directly expose these?
124         RNA_def_pointer_runtime(ot->srna, "keyingset", &RNA_KeyingSet, "Keying Set", "Keying Set to add destination to.");
125         RNA_def_pointer_runtime(ot->srna, "id", &RNA_ID, "ID", "ID-block for the destination.");
126                 /* grouping */
127         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.");
128         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).");
129                 /* rna-path */
130         RNA_def_string(ot->srna, "rna_path", "", 256, "RNA-Path", "RNA-Path to destination property."); // xxx hopefully this is long enough
131         RNA_def_int(ot->srna, "array_index", 0, 0, INT_MAX, "Array Index", "If applicable, the index ", 0, INT_MAX);
132                 /* flags */
133         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.");
134         
135 }
136  
137 /* ----- */
138
139 static int keyingset_add_new_exec (bContext *C, wmOperator *op)
140 {
141         Scene *sce= CTX_data_scene(C);
142         KeyingSet *ks= NULL;
143         short flag=0, keyingflag=0;
144         char name[64];
145         
146         /* get settings from operator properties */
147         RNA_string_get(op->ptr, "name", name);
148         
149         if (RNA_boolean_get(op->ptr, "absolute"))
150                 flag |= KEYINGSET_ABSOLUTE;
151         if (RNA_boolean_get(op->ptr, "insertkey_needed"))
152                 keyingflag |= INSERTKEY_NEEDED;
153         if (RNA_boolean_get(op->ptr, "insertkey_visual"))
154                 keyingflag |= INSERTKEY_MATRIX;
155                 
156         /* call the API func, and set the active keyingset index */
157         ks= BKE_keyingset_add(&sce->keyingsets, name, flag, keyingflag);
158         
159         if (ks) {
160                 sce->active_keyingset= BLI_countlist(&sce->keyingsets);
161                 return OPERATOR_FINISHED;
162         }
163         else {
164                 BKE_report(op->reports, RPT_ERROR, "Keying Set could not be added.");
165                 return OPERATOR_CANCELLED;
166         }
167 }
168
169 void ANIM_OT_keyingset_add_new (wmOperatorType *ot)
170 {
171         /* identifiers */
172         ot->name= "Add Keying Set";
173         ot->idname= "ANIM_OT_keyingset_add_new";
174         
175         /* callbacks */
176         ot->exec= keyingset_add_new_exec;
177         ot->poll= ED_operator_scene_editable;
178         
179         /* props */
180                 /* name */
181         RNA_def_string(ot->srna, "name", "KeyingSet", 64, "Name", "Name of Keying Set");
182                 /* flags */
183         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)");
184                 /* keying flags */
185         RNA_def_boolean(ot->srna, "insertkey_needed", 0, "Insert Keyframes - Only Needed", "Only insert keyframes where they're needed in the relevant F-Curves.");
186         RNA_def_boolean(ot->srna, "insertkey_visual", 0, "Insert Keyframes - Visual", "Insert keyframes based on 'visual transforms'.");
187 }
188
189 /* UI API --------------------------------------------- */
190
191 /* Build menu-string of available keying-sets (allocates memory for string)
192  * NOTE: mode must not be longer than 64 chars
193  */
194 char *ANIM_build_keyingsets_menu (ListBase *list, short for_edit)
195 {
196         DynStr *pupds= BLI_dynstr_new();
197         KeyingSet *ks;
198         char buf[64];
199         char *str;
200         int i;
201         
202         /* add title first */
203         BLI_dynstr_append(pupds, "Keying Sets%t|");
204         
205         /* add dummy entries for none-active */
206         if (for_edit) { 
207                 BLI_dynstr_append(pupds, "Add New%x-1|");
208                 BLI_dynstr_append(pupds, " %x0|");
209         }
210         else
211                 BLI_dynstr_append(pupds, "<No Keying Set Active>%x0|");
212         
213         /* loop through keyingsets, adding them */
214         for (ks=list->first, i=1; ks; ks=ks->next, i++) {
215                 if (for_edit == 0)
216                         BLI_dynstr_append(pupds, "KS: ");
217                 
218                 BLI_dynstr_append(pupds, ks->name);
219                 BLI_snprintf( buf, 64, "%%x%d%s", i, ((ks->next)?"|":"") );
220                 BLI_dynstr_append(pupds, buf);
221         }
222         
223         /* convert to normal MEM_malloc'd string */
224         str= BLI_dynstr_get_cstring(pupds);
225         BLI_dynstr_free(pupds);
226         
227         return str;
228 }
229
230
231 /* ******************************************* */
232 /* KEYING SETS - BUILTIN */
233
234 #if 0 // XXX old keyingsets code based on adrcodes... to be restored in due course
235
236 /* ------------- KeyingSet Defines ------------ */
237 /* Note: these must all be named with the defks_* prefix, otherwise the template macro will not work! */
238
239 /* macro for defining keyingset contexts */
240 #define KSC_TEMPLATE(ctx_name) {&defks_##ctx_name[0], NULL, sizeof(defks_##ctx_name)/sizeof(bKeyingSet)}
241
242 /* --- */
243
244 /* check if option not available for deleting keys */
245 static short incl_non_del_keys (bKeyingSet *ks, const char mode[])
246 {
247         /* as optimisation, assume that it is sufficient to check only first letter
248          * of mode (int comparison should be faster than string!)
249          */
250         //if (strcmp(mode, "Delete")==0)
251         if (mode && mode[0]=='D')
252                 return 0;
253         
254         return 1;
255 }
256
257 /* Object KeyingSets  ------ */
258
259 /* check if include shapekey entry  */
260 static short incl_v3d_ob_shapekey (bKeyingSet *ks, const char mode[])
261 {
262         //Object *ob= (G.obedit)? (G.obedit) : (OBACT); // XXX
263         Object *ob= NULL;
264         char *newname= NULL;
265         
266         if(ob==NULL)
267                 return 0;
268         
269         /* not available for delete mode */
270         if (strcmp(mode, "Delete")==0)
271                 return 0;
272         
273         /* check if is geom object that can get shapekeys */
274         switch (ob->type) {
275                 /* geometry? */
276                 case OB_MESH:           newname= "Mesh";                break;
277                 case OB_CURVE:          newname= "Curve";               break;
278                 case OB_SURF:           newname= "Surface";             break;
279                 case OB_LATTICE:        newname= "Lattice";             break;
280                 
281                 /* not geometry! */
282                 default:
283                         return 0;
284         }
285         
286         /* if ks is shapekey entry (this could be callled for separator before too!) */
287         if (ks->flag == -3)
288                 BLI_strncpy(ks->name, newname, sizeof(ks->name));
289         
290         /* if it gets here, it's ok */
291         return 1;
292 }
293
294 /* array for object keyingset defines */
295 bKeyingSet defks_v3d_object[] = 
296 {
297         /* include_cb, adrcode-getter, name, blocktype, flag, chan_num, adrcodes */
298         {NULL, "Loc", ID_OB, 0, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}},
299         {NULL, "Rot", ID_OB, 0, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
300         {NULL, "Scale", ID_OB, 0, 3, {OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
301         
302         {NULL, "%l", 0, -1, 0, {0}}, // separator
303         
304         {NULL, "LocRot", ID_OB, 0, 6, 
305                 {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
306                  OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
307                  
308         {NULL, "LocScale", ID_OB, 0, 6, 
309                 {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
310                  OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
311                  
312         {NULL, "LocRotScale", ID_OB, 0, 9, 
313                 {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
314                  OB_ROT_X,OB_ROT_Y,OB_ROT_Z,
315                  OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
316                  
317         {NULL, "RotScale", ID_OB, 0, 6, 
318                 {OB_ROT_X,OB_ROT_Y,OB_ROT_Z,
319                  OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
320         
321         {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator
322         
323         {incl_non_del_keys, "VisualLoc", ID_OB, INSERTKEY_MATRIX, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}},
324         {incl_non_del_keys, "VisualRot", ID_OB, INSERTKEY_MATRIX, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
325         
326         {incl_non_del_keys, "VisualLocRot", ID_OB, INSERTKEY_MATRIX, 6, 
327                 {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
328                  OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
329         
330         {NULL, "%l", 0, -1, 0, {0}}, // separator
331         
332         {NULL, "Layer", ID_OB, 0, 1, {OB_LAY}}, // icky option...
333         {NULL, "Available", ID_OB, -2, 0, {0}},
334         
335         {incl_v3d_ob_shapekey, "%l%l", 0, -1, 0, {0}}, // separator (linked to shapekey entry)
336         {incl_v3d_ob_shapekey, "<ShapeKey>", ID_OB, -3, 0, {0}}
337 };
338
339 /* PoseChannel KeyingSets  ------ */
340
341 /* array for posechannel keyingset defines */
342 bKeyingSet defks_v3d_pchan[] = 
343 {
344         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
345         {NULL, "Loc", ID_PO, 0, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}},
346         {NULL, "Rot", ID_PO, COMMONKEY_PCHANROT, 1, {KAG_CHAN_EXTEND}},
347         {NULL, "Scale", ID_PO, 0, 3, {AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}},
348         
349         {NULL, "%l", 0, -1, 0, {0}}, // separator
350         
351         {NULL, "LocRot", ID_PO, COMMONKEY_PCHANROT, 4, 
352                 {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,
353                  KAG_CHAN_EXTEND}},
354                  
355         {NULL, "LocScale", ID_PO, 0, 6, 
356                 {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,
357                  AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}},
358                  
359         {NULL, "LocRotScale", ID_PO, COMMONKEY_PCHANROT, 7, 
360                 {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z, 
361                  KAG_CHAN_EXTEND}},
362                  
363         {NULL, "RotScale", ID_PO, 0, 4, 
364                 {AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z, 
365                  KAG_CHAN_EXTEND}},
366         
367         {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator
368         
369         {incl_non_del_keys, "VisualLoc", ID_PO, INSERTKEY_MATRIX, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}},
370         {incl_non_del_keys, "VisualRot", ID_PO, INSERTKEY_MATRIX|COMMONKEY_PCHANROT, 1, {KAG_CHAN_EXTEND}},
371         
372         {incl_non_del_keys, "VisualLocRot", ID_PO, INSERTKEY_MATRIX|COMMONKEY_PCHANROT, 4, 
373                 {AC_LOC_X,AC_LOC_Y,AC_LOC_Z, KAG_CHAN_EXTEND}},
374         
375         {NULL, "%l", 0, -1, 0, {0}}, // separator
376         
377         {NULL, "Available", ID_PO, -2, 0, {0}}
378 };
379
380 /* Material KeyingSets  ------ */
381
382 /* array for material keyingset defines */
383 bKeyingSet defks_buts_shading_mat[] = 
384 {
385         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
386         {NULL, "RGB", ID_MA, 0, 3, {MA_COL_R,MA_COL_G,MA_COL_B}},
387         {NULL, "Alpha", ID_MA, 0, 1, {MA_ALPHA}},
388         {NULL, "Halo Size", ID_MA, 0, 1, {MA_HASIZE}},
389         {NULL, "Mode", ID_MA, 0, 1, {MA_MODE}}, // evil bitflags
390         
391         {NULL, "%l", 0, -1, 0, {0}}, // separator
392         
393         {NULL, "All Color", ID_MA, 0, 18, 
394                 {MA_COL_R,MA_COL_G,MA_COL_B,
395                  MA_ALPHA,MA_HASIZE, MA_MODE,
396                  MA_SPEC_R,MA_SPEC_G,MA_SPEC_B,
397                  MA_REF,MA_EMIT,MA_AMB,MA_SPEC,MA_HARD,
398                  MA_MODE,MA_TRANSLU,MA_ADD}},
399                  
400         {NULL, "All Mirror", ID_MA, 0, 5, 
401                 {MA_RAYM,MA_FRESMIR,MA_FRESMIRI,
402                  MA_FRESTRA,MA_FRESTRAI}},
403         
404         {NULL, "%l", 0, -1, 0, {0}}, // separator
405         
406         {NULL, "Ofs", ID_MA, COMMONKEY_ADDMAP, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
407         {NULL, "Size", ID_MA, COMMONKEY_ADDMAP, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
408         
409         {NULL, "All Mapping", ID_MA, COMMONKEY_ADDMAP, 14, 
410                 {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
411                  MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
412                  MAP_R,MAP_G,MAP_B,MAP_DVAR,
413                  MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
414         
415         {NULL, "%l", 0, -1, 0, {0}}, // separator
416         
417         {NULL, "Available", ID_MA, -2, 0, {0}}
418 };
419
420 /* World KeyingSets  ------ */
421
422 /* array for world keyingset defines */
423 bKeyingSet defks_buts_shading_wo[] = 
424 {
425         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
426         {NULL, "Zenith RGB", ID_WO, 0, 3, {WO_ZEN_R,WO_ZEN_G,WO_ZEN_B}},
427         {NULL, "Horizon RGB", ID_WO, 0, 3, {WO_HOR_R,WO_HOR_G,WO_HOR_B}},
428         
429         {NULL, "%l", 0, -1, 0, {0}}, // separator
430         
431         {NULL, "Mist", ID_WO, 0, 4, {WO_MISI,WO_MISTDI,WO_MISTSTA,WO_MISTHI}},
432         {NULL, "Stars", ID_WO, 0, 5, {WO_STAR_R,WO_STAR_G,WO_STAR_B,WO_STARDIST,WO_STARSIZE}},
433         
434         
435         {NULL, "%l", 0, -1, 0, {0}}, // separator
436         
437         {NULL, "Ofs", ID_WO, COMMONKEY_ADDMAP, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
438         {NULL, "Size", ID_WO, COMMONKEY_ADDMAP, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
439         
440         {NULL, "All Mapping", ID_WO, COMMONKEY_ADDMAP, 14, 
441                 {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
442                  MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
443                  MAP_R,MAP_G,MAP_B,MAP_DVAR,
444                  MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
445         
446         {NULL, "%l", 0, -1, 0, {0}}, // separator
447         
448         {NULL, "Available", ID_WO, -2, 0, {0}}
449 };
450
451 /* Lamp KeyingSets  ------ */
452
453 /* array for lamp keyingset defines */
454 bKeyingSet defks_buts_shading_la[] = 
455 {
456         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
457         {NULL, "RGB", ID_LA, 0, 3, {LA_COL_R,LA_COL_G,LA_COL_B}},
458         {NULL, "Energy", ID_LA, 0, 1, {LA_ENERGY}},
459         {NULL, "Spot Size", ID_LA, 0, 1, {LA_SPOTSI}},
460         
461         {NULL, "%l", 0, -1, 0, {0}}, // separator
462         
463         {NULL, "Ofs", ID_LA, COMMONKEY_ADDMAP, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
464         {NULL, "Size", ID_LA, COMMONKEY_ADDMAP, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
465         
466         {NULL, "All Mapping", ID_LA, COMMONKEY_ADDMAP, 14, 
467                 {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
468                  MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
469                  MAP_R,MAP_G,MAP_B,MAP_DVAR,
470                  MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
471         
472         {NULL, "%l", 0, -1, 0, {0}}, // separator
473         
474         {NULL, "Available", ID_LA, -2, 0, {0}}
475 };
476
477 /* Texture KeyingSets  ------ */
478
479 /* array for texture keyingset defines */
480 bKeyingSet defks_buts_shading_tex[] = 
481 {
482         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
483         {NULL, "Clouds", ID_TE, 0, 5, 
484                 {TE_NSIZE,TE_NDEPTH,TE_NTYPE,
485                  TE_MG_TYP,TE_N_BAS1}},
486         
487         {NULL, "Marble", ID_TE, 0, 7, 
488                 {TE_NSIZE,TE_NDEPTH,TE_NTYPE,
489                  TE_TURB,TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}},
490                  
491         {NULL, "Stucci", ID_TE, 0, 5, 
492                 {TE_NSIZE,TE_NTYPE,TE_TURB,
493                  TE_MG_TYP,TE_N_BAS1}},
494                  
495         {NULL, "Wood", ID_TE, 0, 6, 
496                 {TE_NSIZE,TE_NTYPE,TE_TURB,
497                  TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}},
498                  
499         {NULL, "Magic", ID_TE, 0, 2, {TE_NDEPTH,TE_TURB}},
500         
501         {NULL, "Blend", ID_TE, 0, 1, {TE_MG_TYP}},      
502                 
503         {NULL, "Musgrave", ID_TE, 0, 6, 
504                 {TE_MG_TYP,TE_MGH,TE_MG_LAC,
505                  TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN}},
506                  
507         {NULL, "Voronoi", ID_TE, 0, 9, 
508                 {TE_VNW1,TE_VNW2,TE_VNW3,TE_VNW4,
509                 TE_VNMEXP,TE_VN_DISTM,TE_VN_COLT,
510                 TE_ISCA,TE_NSIZE}},
511                 
512         {NULL, "Distorted Noise", ID_TE, 0, 4, 
513                 {TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN,TE_DISTA}},
514         
515         {NULL, "Color Filter", ID_TE, 0, 5, 
516                 {TE_COL_R,TE_COL_G,TE_COL_B,TE_BRIGHT,TE_CONTRA}},
517         
518         {NULL, "%l", 0, -1, 0, {0}}, // separator
519         
520         {NULL, "Available", ID_TE, -2, 0, {0}}
521 };
522
523 /* Object Buttons KeyingSets  ------ */
524
525 /* check if include particles entry  */
526 static short incl_buts_ob (bKeyingSet *ks, const char mode[])
527 {
528         //Object *ob= OBACT; // xxx
529         Object *ob= NULL;
530         /* only if object is mesh type */
531         
532         if(ob==NULL) return 0;
533         return (ob->type == OB_MESH);
534 }
535
536 /* array for texture keyingset defines */
537 bKeyingSet defks_buts_object[] = 
538 {
539         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
540         {incl_buts_ob, "Surface Damping", ID_OB, 0, 1, {OB_PD_SDAMP}},
541         {incl_buts_ob, "Random Damping", ID_OB, 0, 1, {OB_PD_RDAMP}},
542         {incl_buts_ob, "Permeability", ID_OB, 0, 1, {OB_PD_PERM}},
543         
544         {NULL, "%l", 0, -1, 0, {0}}, // separator
545         
546         {NULL, "Force Strength", ID_OB, 0, 1, {OB_PD_FSTR}},
547         {NULL, "Force Falloff", ID_OB, 0, 1, {OB_PD_FFALL}},
548         
549         {NULL, "%l", 0, -1, 0, {0}}, // separator
550         
551         {NULL, "Available", ID_OB, -2, 0, {0}}  // this will include ob-transforms too!
552 };
553
554 /* Camera Buttons KeyingSets  ------ */
555
556 /* check if include internal-renderer entry  */
557 static short incl_buts_cam1 (bKeyingSet *ks, const char mode[])
558 {
559         Scene *scene= NULL; // FIXME this will cause a crash, but we need an extra arg first!
560         /* only if renderer is internal renderer */
561         return (scene->r.renderer==R_INTERN);
562 }
563
564 /* check if include external-renderer entry  */
565 static short incl_buts_cam2 (bKeyingSet *ks, const char mode[])
566 {
567         Scene *scene= NULL; // FIXME this will cause a crash, but we need an extra arg first!
568         /* only if renderer is internal renderer */
569         return (scene->r.renderer!=R_INTERN);
570 }
571
572 /* array for camera keyingset defines */
573 bKeyingSet defks_buts_cam[] = 
574 {
575         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
576         {NULL, "Lens", ID_CA, 0, 1, {CAM_LENS}},
577         {NULL, "Clipping", ID_CA, 0, 2, {CAM_STA,CAM_END}},
578         {NULL, "Focal Distance", ID_CA, 0, 1, {CAM_YF_FDIST}},
579         
580         {NULL, "%l", 0, -1, 0, {0}}, // separator
581         
582         
583         {incl_buts_cam2, "Aperture", ID_CA, 0, 1, {CAM_YF_APERT}},
584         {incl_buts_cam1, "Viewplane Shift", ID_CA, 0, 2, {CAM_SHIFT_X,CAM_SHIFT_Y}},
585         
586         {NULL, "%l", 0, -1, 0, {0}}, // separator
587         
588         {NULL, "Available", ID_CA, -2, 0, {0}}
589 };
590
591 /* --- */
592
593 /* Keying Context Defines - Must keep in sync with enumeration (eKS_Contexts) */
594 bKeyingContext ks_contexts[] = 
595 {
596         KSC_TEMPLATE(v3d_object),
597         KSC_TEMPLATE(v3d_pchan),
598         
599         KSC_TEMPLATE(buts_shading_mat),
600         KSC_TEMPLATE(buts_shading_wo),
601         KSC_TEMPLATE(buts_shading_la),
602         KSC_TEMPLATE(buts_shading_tex),
603
604         KSC_TEMPLATE(buts_object),
605         KSC_TEMPLATE(buts_cam)
606 };
607
608 /* Keying Context Enumeration - Must keep in sync with definitions*/
609 typedef enum eKS_Contexts {
610         KSC_V3D_OBJECT = 0,
611         KSC_V3D_PCHAN,
612         
613         KSC_BUTS_MAT,
614         KSC_BUTS_WO,
615         KSC_BUTS_LA,
616         KSC_BUTS_TEX,
617         
618         KSC_BUTS_OB,
619         KSC_BUTS_CAM,
620         
621                 /* make sure this last one remains untouched! */
622         KSC_TOT_TYPES
623 } eKS_Contexts;
624
625
626 #endif // XXX old keyingsets code based on adrcodes... to be restored in due course
627
628 /* Macros for Declaring KeyingSets ------------------- */
629
630 /* A note about this system for declaring built-in Keying Sets:
631  *      One may ask, "What is the purpose of all of these macros and static arrays?" and 
632  *      "Why not call the KeyingSets API defined in BKE_animsys.h?". The answer is two-fold.
633  *      
634  *      1) Firstly, we use static arrays of struct definitions instead of function calls, as
635  *         it reduces the start-up overhead and allocated-memory footprint of Blender. If we called
636  *         the KeyingSets API to build these sets, the overhead of checking for unique names, allocating
637  *         memory for each and every path and KeyingSet, scattered around in RAM, all of which would increase
638  *         the startup time (which is totally unacceptable) and could lead to fragmentation+slower access times.
639  *      2) Since we aren't using function calls, we need a nice way of defining these KeyingSets in a way which
640  *         is easily readable and less prone to breakage from changes to the underlying struct definitions. Further,
641  *         adding additional entries SHOULD NOT require custom code to be written to access these new entries/sets. 
642  *         Therefore, here we have a system with nice, human-readable statements via macros, and static arrays which
643  *         are linked together using more special macros + struct definitions, allowing for such a generic + simple
644  *         initialisation function (init_builtin_keyingsets()) compared with that of something like the Nodes system.
645  *
646  * -- Joshua Leung, April 2009
647  */
648
649 /* Struct type for declaring builtin KeyingSets in as entries in static arrays*/
650 typedef struct bBuiltinKeyingSet {
651         KeyingSet ks;                   /* the KeyingSet to build */
652         int tot;                                /* the total number of paths defined */
653         KS_Path paths[64];              /* the paths for the KeyingSet to use */
654 } bBuiltinKeyingSet;
655
656         /* WARNING: the following macros must be kept in sync with the 
657          * struct definitions in DNA_anim_types.h! 
658          */
659
660 /* macro for defining a builtin KeyingSet */
661 #define BI_KS_DEFINE_BEGIN(name, keyingflag) \
662         {{NULL, NULL, {NULL, NULL}, name, KEYINGSET_BUILTIN, keyingflag},
663         
664 /* macro to finish defining a builtin KeyingSet */
665 #define BI_KS_DEFINE_END \
666         }
667         
668 /* macro to start defining paths for a builtin KeyingSet */
669 #define BI_KS_PATHS_BEGIN(tot) \
670         tot, {
671         
672 /* macro to finish defining paths for a builtin KeyingSet */
673 #define BI_KS_PATHS_END \
674         }
675         
676 /* macro for defining a builtin KeyingSet's path */
677 #define BI_KSP_DEFINE(id_type, templates, prop_path, array_index, flag, groupflag) \
678         {NULL, NULL, NULL, "", id_type, templates, prop_path, array_index, flag, groupflag}
679         
680 /* macro for defining a builtin KeyingSet with no paths (use in place of BI_KS_PAHTS_BEGIN/END block) */
681 #define BI_KS_PATHS_NONE \
682         0, {0}
683         
684 /* ---- */
685
686 /* Struct type for finding all the arrays of builtin KeyingSets */
687 typedef struct bBuiltinKSContext {
688         bBuiltinKeyingSet *bks;         /* array of KeyingSet definitions */
689         int tot;                                        /* number of KeyingSets in this array */
690 } bBuiltinKSContext;
691
692 /* macro for defining builtin KeyingSet sets 
693  * NOTE: all the arrays of sets must follow this naming convention!
694  */
695 #define BKSC_TEMPLATE(ctx_name) {&def_builtin_keyingsets_##ctx_name[0], sizeof(def_builtin_keyingsets_##ctx_name)/sizeof(bBuiltinKeyingSet)}
696
697
698 /* 3D-View Builtin KeyingSets ------------------------ */
699
700 static bBuiltinKeyingSet def_builtin_keyingsets_v3d[] =
701 {
702         /* Simple Keying Sets ************************************* */
703         /* Keying Set - "Location" ---------- */
704         BI_KS_DEFINE_BEGIN("Location", 0)
705                 BI_KS_PATHS_BEGIN(1)
706                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) 
707                 BI_KS_PATHS_END
708         BI_KS_DEFINE_END,
709
710         /* Keying Set - "Rotation" ---------- */
711         BI_KS_DEFINE_BEGIN("Rotation", 0)
712                 BI_KS_PATHS_BEGIN(1)
713                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) 
714                 BI_KS_PATHS_END
715         BI_KS_DEFINE_END,
716         
717         /* Keying Set - "Scaling" ---------- */
718         BI_KS_DEFINE_BEGIN("Scaling", 0)
719                 BI_KS_PATHS_BEGIN(1)
720                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "scale", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) 
721                 BI_KS_PATHS_END
722         BI_KS_DEFINE_END,
723         
724         /* Compound Keying Sets *********************************** */
725         /* Keying Set - "LocRot" ---------- */
726         BI_KS_DEFINE_BEGIN("LocRot", 0)
727                 BI_KS_PATHS_BEGIN(2)
728                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM), 
729                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) 
730                 BI_KS_PATHS_END
731         BI_KS_DEFINE_END,
732         
733         /* Keying Set - "LocRotScale" ---------- */
734         BI_KS_DEFINE_BEGIN("LocRotScale", 0)
735                 BI_KS_PATHS_BEGIN(3)
736                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM), 
737                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM), 
738                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "scale", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) 
739                 BI_KS_PATHS_END
740         BI_KS_DEFINE_END,
741         
742         /* Keying Sets with Keying Flags ************************* */
743         /* Keying Set - "VisualLoc" ---------- */
744         BI_KS_DEFINE_BEGIN("VisualLoc", 0)
745                 BI_KS_PATHS_BEGIN(1)
746                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", INSERTKEY_MATRIX, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) 
747                 BI_KS_PATHS_END
748         BI_KS_DEFINE_END,
749
750         /* Keying Set - "Rotation" ---------- */
751         BI_KS_DEFINE_BEGIN("VisualRot", 0)
752                 BI_KS_PATHS_BEGIN(1)
753                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "rotation", INSERTKEY_MATRIX, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) 
754                 BI_KS_PATHS_END
755         BI_KS_DEFINE_END,
756         
757         /* Keying Set - "VisualLocRot" ---------- */
758         BI_KS_DEFINE_BEGIN("VisualLocRot", 0)
759                 BI_KS_PATHS_BEGIN(2)
760                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", INSERTKEY_MATRIX, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM), 
761                         BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "rotation", INSERTKEY_MATRIX, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) 
762                 BI_KS_PATHS_END
763         BI_KS_DEFINE_END
764 };
765
766 /* All Builtin KeyingSets ------------------------ */
767
768 /* total number of builtin KeyingSet contexts */
769 #define MAX_BKSC_TYPES  1
770
771 /* array containing all the available builtin KeyingSets definition sets 
772  *      - size of this is MAX_BKSC_TYPES+1 so that we don't smash the stack
773  */
774 static bBuiltinKSContext def_builtin_keyingsets[MAX_BKSC_TYPES+1] =
775 {
776         BKSC_TEMPLATE(v3d)
777         /* add more contexts above this line... */
778 };
779
780
781 /* ListBase of these KeyingSets chained up ready for usage 
782  * NOTE: this is exported to keyframing.c for use...
783  */
784 ListBase builtin_keyingsets = {NULL, NULL};
785
786 /* Utility API ------------------------ */
787
788 /* Link up all of the builtin Keying Sets when starting up Blender
789  * This is called from WM_init() in wm_init_exit.c
790  */
791 void init_builtin_keyingsets (void)
792 {
793         bBuiltinKSContext *bksc;
794         bBuiltinKeyingSet *bks;
795         int bksc_i, bks_i;
796         
797         /* loop over all the sets of KeyingSets, setting them up, and chaining them to the builtins list */
798         for (bksc_i= 0, bksc= &def_builtin_keyingsets[0]; bksc_i < MAX_BKSC_TYPES; bksc_i++, bksc++)
799         {
800                 /* for each set definitions for a builtin KeyingSet, chain the paths to that KeyingSet and add */
801                 for (bks_i= 0, bks= bksc->bks; bks_i < bksc->tot; bks_i++, bks++)
802                 {
803                         KeyingSet *ks= &bks->ks;
804                         KS_Path *ksp;
805                         int pIndex;
806                         
807                         /* loop over paths, linking them to the KeyingSet and each other */
808                         for (pIndex= 0, ksp= &bks->paths[0]; pIndex < bks->tot; pIndex++, ksp++)
809                                 BLI_addtail(&ks->paths, ksp);
810                                 
811                         /* add KeyingSet to builtin sets list */
812                         BLI_addtail(&builtin_keyingsets, ks);
813                 }
814         }
815 }
816
817
818 /* Get the first builtin KeyingSet with the given name, which occurs after the given one (or start of list if none given) */
819 KeyingSet *ANIM_builtin_keyingset_get_named (KeyingSet *prevKS, char name[])
820 {
821         KeyingSet *ks, *first=NULL;
822         
823         /* sanity checks - any name to check? */
824         if (name[0] == 0)
825                 return NULL;
826         
827         /* get first KeyingSet to use */
828         if (prevKS && prevKS->next)
829                 first= prevKS->next;
830         else
831                 first= builtin_keyingsets.first;
832                 
833         /* loop over KeyingSets checking names */
834         for (ks= first; ks; ks= ks->next) {
835                 if (strcmp(name, ks->name) == 0)
836                         return ks;
837         }
838         
839         /* no matches found */
840         return NULL;
841 }
842
843 /* ******************************************* */
844 /* KEYFRAME MODIFICATION */
845
846 /* KeyingSet Menu Helpers ------------ */
847
848 /* Extract the maximum set of requirements from the KeyingSet */
849 static int keyingset_relative_get_templates (KeyingSet *ks)
850 {
851         KS_Path *ksp;
852         int templates= 0;
853         
854         /* loop over the paths (could be slow to do for a number of KeyingSets)? */
855         for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
856                 /* add the destination's templates to the set of templates required for the set */
857                 templates |= ksp->templates;
858         }
859         
860         return templates;
861 }
862
863 /* Check if context data is suitable for the given absolute Keying Set */
864 short keyingset_context_ok_poll (bContext *C, KeyingSet *ks)
865 {
866         ScrArea *sa= CTX_wm_area(C);
867         
868         /* data retrieved from context depends on active editor */
869         if (sa == NULL) return 0;
870                 
871         switch (sa->spacetype) {
872                 case SPACE_VIEW3D:
873                 {
874                         Object *obact= CTX_data_active_object(C);
875                         
876                         /* if in posemode, check if 'pose-channels' requested for in KeyingSet */
877                         if ((obact && obact->pose) && (obact->flag & OB_POSEMODE)) {
878                                 /* check for posechannels */
879                                 
880                         }
881                         else {
882                                 /* check for selected object */
883                                 
884                         }
885                 }
886                         break;
887         }
888         
889         
890         return 1;
891 }
892
893 /* KeyingSet Context Operations ------------ */
894
895 /* Get list of data-sources from context (in 3D-View) for inserting keyframes using the given relative Keying Set */
896 static short modifykey_get_context_v3d_data (bContext *C, ListBase *dsources, KeyingSet *ks)
897 {
898         bCommonKeySrc *cks;
899         Object *obact= CTX_data_active_object(C);
900         int templates; 
901         short ok= 0;
902         
903         /* get the templates in use in this KeyingSet which we should supply data for */
904         templates = keyingset_relative_get_templates(ks);
905         
906         /* check if the active object is in PoseMode (i.e. only deal with bones) */
907         // TODO: check with the templates to see what we really need to store 
908         if ((obact && obact->pose) && (obact->flag & OB_POSEMODE)) {
909                 /* Pose Mode: Selected bones */
910 #if 0
911                 //set_pose_keys(ob);  /* sets pchan->flag to POSE_KEY if bone selected, and clears if not */
912                 
913                 /* loop through posechannels */
914                 //for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
915                 //      if (pchan->flag & POSE_KEY) {
916                 //      }
917                 //}
918 #endif
919                 
920                 CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans)
921                 {
922                         /* add a new keying-source */
923                         cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
924                         BLI_addtail(dsources, cks);
925                         
926                         /* set necessary info */
927                         cks->id= &obact->id;
928                         cks->pchan= pchan;
929                         
930                         if (templates & KSP_TEMPLATE_CONSTRAINT)
931                                 cks->con= constraints_get_active(&pchan->constraints);
932                         
933                         ok= 1;
934                 }
935                 CTX_DATA_END;
936         }
937         else {
938                 /* Object Mode: Selected objects */
939                 CTX_DATA_BEGIN(C, Base*, base, selected_bases) 
940                 {
941                         Object *ob= base->object;
942                         
943                         /* add a new keying-source */
944                         cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
945                         BLI_addtail(dsources, cks);
946                         
947                         /* set necessary info */
948                         cks->id= &ob->id;
949                         
950                         if (templates & KSP_TEMPLATE_CONSTRAINT)
951                                 cks->con= constraints_get_active(&ob->constraints);
952                         
953                         ok= 1;
954                 }
955                 CTX_DATA_END;
956         }
957         
958         /* return whether any data was extracted */
959         return ok;
960 }
961
962 /* Get list of data-sources from context for inserting keyframes using the given relative Keying Set */
963 short modifykey_get_context_data (bContext *C, ListBase *dsources, KeyingSet *ks)
964 {
965         ScrArea *sa= CTX_wm_area(C);
966         
967         /* for now, the active area is used to determine what set of contexts apply */
968         if (sa == NULL)
969                 return 0;
970                 
971         switch (sa->spacetype) {
972                 case SPACE_VIEW3D:      /* 3D-View: Selected Objects or Bones */
973                         return modifykey_get_context_v3d_data(C, dsources, ks);
974         }
975         
976         /* nothing happened */
977         return 0;
978
979
980 /* KeyingSet Operations (Insert/Delete Keyframes) ------------ */
981
982 /* Given a KeyingSet and context info (if required), modify keyframes for the channels specified
983  * by the KeyingSet. This takes into account many of the different combinations of using KeyingSets.
984  * Returns the number of channels that keyframes were added to
985  */
986 int modify_keyframes (bContext *C, ListBase *dsources, bAction *act, KeyingSet *ks, short mode, float cfra)
987 {
988         KS_Path *ksp;
989         int kflag=0, success= 0;
990         char *groupname= NULL;
991         
992         /* get flags to use */
993         if (mode == MODIFYKEY_MODE_INSERT) {
994                 /* use KeyingSet's flags as base */
995                 kflag= ks->keyingflag;
996                 
997                 /* suppliment with info from the context */
998                 if (IS_AUTOKEY_FLAG(AUTOMATKEY)) kflag |= INSERTKEY_MATRIX;
999                 if (IS_AUTOKEY_FLAG(INSERTNEEDED)) kflag |= INSERTKEY_NEEDED;
1000                 // if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE;
1001         }
1002         else if (mode == MODIFYKEY_MODE_DELETE)
1003                 kflag= 0;
1004         
1005         /* check if the KeyingSet is absolute or not (i.e. does it requires sources info) */
1006         if (ks->flag & KEYINGSET_ABSOLUTE) {
1007                 /* Absolute KeyingSets are simpler to use, as all the destination info has already been
1008                  * provided by the user, and is stored, ready to use, in the KeyingSet paths.
1009                  */
1010                 for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
1011                         int arraylen, i;
1012                         
1013                         /* get pointer to name of group to add channels to */
1014                         if (ksp->groupmode == KSP_GROUP_NONE)
1015                                 groupname= NULL;
1016                         else if (ksp->groupmode == KSP_GROUP_KSNAME)
1017                                 groupname= ks->name;
1018                         else
1019                                 groupname= ksp->group;
1020                         
1021                         /* init arraylen and i - arraylen should be greater than i so that
1022                          * normal non-array entries get keyframed correctly
1023                          */
1024                         i= ksp->array_index;
1025                         arraylen= i+1;
1026                         
1027                         /* get length of array if whole array option is enabled */
1028                         if (ksp->flag & KSP_FLAG_WHOLE_ARRAY) {
1029                                 PointerRNA id_ptr, ptr;
1030                                 PropertyRNA *prop;
1031                                 
1032                                 RNA_id_pointer_create(ksp->id, &id_ptr);
1033                                 if (RNA_path_resolve(&id_ptr, ksp->rna_path, &ptr, &prop) && prop)
1034                                         arraylen= RNA_property_array_length(prop);
1035                         }
1036                         
1037                         /* for each possible index, perform operation 
1038                          *      - assume that arraylen is greater than index
1039                          */
1040                         for (; i < arraylen; i++) {
1041                                 /* action to take depends on mode */
1042                                 if (mode == MODIFYKEY_MODE_INSERT)
1043                                         success+= insert_keyframe(ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag);
1044                                 else if (mode == MODIFYKEY_MODE_DELETE)
1045                                         success+= delete_keyframe(ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag);
1046                         }
1047                         
1048                         /* send notifiers and set recalc-flags */
1049                         // TODO: hopefully this doesn't result in execessive flooding of the notifier stack
1050                         if (C && ksp->id) {
1051                                 switch (GS(ksp->id->name)) {
1052                                         case ID_OB: /* Object (or Object-Related) Keyframes */
1053                                         {
1054                                                 Object *ob= (Object *)ksp->id;
1055                                                 
1056                                                 ob->recalc |= OB_RECALC;
1057                                                 WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, ksp->id);
1058                                         }
1059                                                 break;
1060                                         case ID_MA: /* Material Keyframes */
1061                                                 WM_event_add_notifier(C, NC_MATERIAL|ND_KEYS, ksp->id);
1062                                                 break;
1063                                 }
1064                         }
1065                 }
1066         }
1067         else if (dsources && dsources->first) {
1068                 /* for each one of the 'sources', resolve the template markers and expand arrays, then insert keyframes */
1069                 bCommonKeySrc *cks;
1070                 
1071                 /* for each 'source' for keyframe data, resolve each of the paths from the KeyingSet */
1072                 for (cks= dsources->first; cks; cks= cks->next) {
1073                         /* for each path in KeyingSet, construct a path using the templates */
1074                         for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
1075                                 DynStr *pathds= BLI_dynstr_new();
1076                                 char *path = NULL;
1077                                 int arraylen, i;
1078                                 
1079                                 /* set initial group name */
1080                                 groupname= (cks->id) ? cks->id->name+2 : NULL;
1081                                 
1082                                 /* construct the path */
1083                                 // FIXME: this currently only works with a few hardcoded cases
1084                                 if ((ksp->templates & KSP_TEMPLATE_PCHAN) && (cks->pchan)) {
1085                                         /* add basic pose-channel path access */
1086                                         BLI_dynstr_append(pathds, "pose.pose_channels[\"");
1087                                         BLI_dynstr_append(pathds, cks->pchan->name);
1088                                         BLI_dynstr_append(pathds, "\"]");
1089                                         
1090                                         /* override default group name */
1091                                         groupname= cks->pchan->name;
1092                                 }
1093                                 if ((ksp->templates & KSP_TEMPLATE_CONSTRAINT) && (cks->con)) {
1094                                         /* add basic constraint path access */
1095                                         BLI_dynstr_append(pathds, "constraints[\"");
1096                                         BLI_dynstr_append(pathds, cks->con->name);
1097                                         BLI_dynstr_append(pathds, "\"]");
1098                                         
1099                                         /* override default group name */
1100                                         groupname= cks->con->name;
1101                                 }
1102                                 {
1103                                         /* add property stored in KeyingSet Path */
1104                                         if (BLI_dynstr_get_len(pathds))
1105                                                 BLI_dynstr_append(pathds, ".");
1106                                         BLI_dynstr_append(pathds, ksp->rna_path);
1107                                         
1108                                         /* convert to C-string */
1109                                         path= BLI_dynstr_get_cstring(pathds);
1110                                         BLI_dynstr_free(pathds);
1111                                 }
1112                                 
1113                                 /* get pointer to name of group to add channels to 
1114                                  *      - KSP_GROUP_TEMPLATE_ITEM is handled above while constructing the paths 
1115                                  */
1116                                 if (ksp->groupmode == KSP_GROUP_NONE)
1117                                         groupname= NULL;
1118                                 else if (ksp->groupmode == KSP_GROUP_KSNAME)
1119                                         groupname= ks->name;
1120                                 else if (ksp->groupmode == KSP_GROUP_NAMED)
1121                                         groupname= ksp->group;
1122                                 
1123                                 /* init arraylen and i - arraylen should be greater than i so that
1124                                  * normal non-array entries get keyframed correctly
1125                                  */
1126                                 i= ksp->array_index;
1127                                 arraylen= i+1;
1128                                 
1129                                 /* get length of array if whole array option is enabled */
1130                                 if (ksp->flag & KSP_FLAG_WHOLE_ARRAY) {
1131                                         PointerRNA id_ptr, ptr;
1132                                         PropertyRNA *prop;
1133                                         
1134                                         RNA_id_pointer_create(cks->id, &id_ptr);
1135                                         if (RNA_path_resolve(&id_ptr, path, &ptr, &prop) && prop)
1136                                                 arraylen= RNA_property_array_length(prop);
1137                                 }
1138                                 
1139                                 /* for each possible index, perform operation 
1140                                  *      - assume that arraylen is greater than index
1141                                  */
1142                                 for (; i < arraylen; i++) {
1143                                         /* action to take depends on mode */
1144                                         if (mode == MODIFYKEY_MODE_INSERT)
1145                                                 success+= insert_keyframe(cks->id, act, groupname, path, i, cfra, kflag);
1146                                         else if (mode == MODIFYKEY_MODE_DELETE)
1147                                                 success+= delete_keyframe(cks->id, act, groupname, path, i, cfra, kflag);
1148                                 }
1149                                 
1150                                 /* free the path */
1151                                 MEM_freeN(path);
1152                         }
1153                         
1154                         /* send notifiers and set recalc-flags */
1155                         // TODO: hopefully this doesn't result in execessive flooding of the notifier stack
1156                         if (C && cks->id) {
1157                                 switch (GS(cks->id->name)) {
1158                                         case ID_OB: /* Object (or Object-Related) Keyframes */
1159                                         {
1160                                                 Object *ob= (Object *)cks->id;
1161                                                 
1162                                                 ob->recalc |= OB_RECALC;
1163                                                 WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, cks->id);
1164                                         }
1165                                                 break;
1166                                         case ID_MA: /* Material Keyframes */
1167                                                 WM_event_add_notifier(C, NC_MATERIAL|ND_KEYS, cks->id);
1168                                                 break;
1169                                 }
1170                         }
1171                 }
1172         }
1173         
1174         /* return the number of channels successfully affected */
1175         return success;
1176 }
1177
1178 /* ************************************************** */