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