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