* Add some missing docu for Blender.Types
[blender.git] / source / blender / src / keyframing.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) 2008, Blender Foundation
21  * This is a new part of Blender (with some old code)
22  *
23  * Contributor(s): Joshua Leung
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27  
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <stddef.h>
32 #include <math.h>
33
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37
38 #include "MEM_guardedalloc.h"
39
40 #include "BLI_arithb.h"
41 #include "BLI_blenlib.h"
42 #include "BLI_dynstr.h"
43
44 #include "DNA_listBase.h"
45 #include "DNA_ID.h"
46 #include "DNA_action_types.h"
47 #include "DNA_armature_types.h"
48 #include "DNA_camera_types.h"
49 #include "DNA_constraint_types.h"
50 #include "DNA_curve_types.h"
51 #include "DNA_ipo_types.h"
52 #include "DNA_key_types.h"
53 #include "DNA_lamp_types.h"
54 #include "DNA_object_types.h"
55 #include "DNA_material_types.h"
56 #include "DNA_screen_types.h"
57 #include "DNA_scene_types.h"
58 #include "DNA_space_types.h"
59 #include "DNA_texture_types.h"
60 #include "DNA_userdef_types.h"
61 #include "DNA_vec_types.h"
62 #include "DNA_view3d_types.h"
63 #include "DNA_world_types.h"
64
65 #include "BKE_global.h"
66 #include "BKE_utildefines.h"
67 #include "BKE_blender.h"
68 #include "BKE_main.h"
69 #include "BKE_action.h"
70 #include "BKE_armature.h"
71 #include "BKE_constraint.h"
72 #include "BKE_curve.h"
73 #include "BKE_depsgraph.h"
74 #include "BKE_ipo.h"
75 #include "BKE_key.h"
76 #include "BKE_object.h"
77 #include "BKE_material.h"
78
79 #include "BIF_keyframing.h"
80 #include "BIF_butspace.h"
81 #include "BIF_editaction.h"
82 #include "BIF_editkey.h"
83 #include "BIF_interface.h"
84 #include "BIF_mywindow.h"
85 #include "BIF_poseobject.h"
86 #include "BIF_screen.h"
87 #include "BIF_space.h"
88 #include "BIF_toolbox.h"
89 #include "BIF_toets.h"
90
91 #include "BSE_editipo.h"
92 #include "BSE_node.h"
93 #include "BSE_time.h"
94 #include "BSE_view.h"
95
96 #include "blendef.h"
97
98 #include "PIL_time.h"                   /* sleep                                */
99 #include "mydevice.h"
100
101 /* ************************************************** */
102 /* LOCAL TYPES AND DEFINES */
103
104 /* -------------- Keying Sets ------------------- */
105
106 /* keying set - a set of channels that will be keyframed together  */
107 // TODO: move this to a header to allow custom sets someday?
108 typedef struct bKeyingSet {
109                 /* callback func to consider if keyingset should be included 
110                  * (by default, if this is undefined, item will be shown) 
111                  */
112         short (*include_cb)(struct bKeyingSet *, const char *);
113         
114         char name[48];                          /* name of keyingset */
115         int blocktype;                          /* blocktype that all channels belong to */  // in future, this may be eliminated
116         short flag;                                     /* flags to use when setting keyframes */
117         
118         short chan_num;                         /* number of channels to insert keyframe in */
119         short adrcodes[32];                     /* adrcodes for channels to insert keys for (ideally would be variable-len, but limit of 32 will suffice) */
120 } bKeyingSet;
121
122 /* keying set context - an array of keying sets and the number of them */
123 typedef struct bKeyingContext {
124         bKeyingSet *keyingsets;         /* array containing the keyingsets of interest */
125         bKeyingSet *lastused;           /* item that was chosen last time*/
126         int tot;                                        /* number of keyingsets in */
127 } bKeyingContext;
128
129
130 /* ----------- Common KeyData Sources ------------ */
131
132 /* temporary struct to gather data combos to keyframe */
133 typedef struct bCommonKeySrc {
134         struct bCommonKeySrc *next, *prev;
135                 
136                 /* general data/destination-source settings */
137         ID *id;                                 /* id-block this comes from */
138         char *actname;                  /* name of action channel */
139         char *constname;                /* name of constraint channel */
140         
141                 /* general destination source settings */
142         Ipo *ipo;                               /* ipo-block that id-block has (optional) */
143         bAction *act;                   /* action-block that id-block has (optional) */
144         
145                 /* pose-level settings */
146         bPoseChannel *pchan;    /* pose channel */
147                 
148                 /* buttons-window settings */
149         int map;                                /* offset to apply to certain adrcodes */
150 } bCommonKeySrc;
151
152 /* ************************************************** */
153 /* KEYFRAME INSERTION */
154
155 /* -------------- BezTriple Insertion -------------------- */
156
157 /* threshold for inserting keyframes - threshold here should be good enough for now, but should become userpref */
158 #define BEZT_INSERT_THRESH      0.00001
159
160 /* Binary search algorithm for finding where to insert BezTriple. (for use by insert_bezt_icu)
161  * Returns the index to insert at (data already at that index will be offset if replace is 0)
162  */
163 static int binarysearch_bezt_index (BezTriple array[], float frame, int arraylen, short *replace)
164 {
165         int start=0, end=arraylen;
166         int loopbreaker= 0, maxloop= arraylen * 2;
167         
168         /* initialise replace-flag first */
169         *replace= 0;
170         
171         /* sneaky optimisations (don't go through searching process if...):
172          *      - keyframe to be added is to be added out of current bounds
173          *      - keyframe to be added would replace one of the existing ones on bounds
174          */
175         if ((arraylen <= 0) || (array == NULL)) {
176                 printf("Warning: binarysearch_bezt_index encountered invalid array \n");
177                 return 0;
178         }
179         else {
180                 /* check whether to add before/after/on */
181                 float framenum;
182                 
183                 /* 'First' Keyframe (when only one keyframe, this case is used) */
184                 framenum= array[0].vec[1][0];
185                 if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) {
186                         *replace = 1;
187                         return 0;
188                 }
189                 else if (frame < framenum)
190                         return 0;
191                         
192                 /* 'Last' Keyframe */
193                 framenum= array[(arraylen-1)].vec[1][0];
194                 if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) {
195                         *replace= 1;
196                         return (arraylen - 1);
197                 }
198                 else if (frame > framenum)
199                         return arraylen;
200         }
201         
202         
203         /* most of the time, this loop is just to find where to put it
204          * 'loopbreaker' is just here to prevent infinite loops 
205          */
206         for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) {
207                 /* compute and get midpoint */
208                 int mid = (start + end) / 2;
209                 float midfra= array[mid].vec[1][0];
210                 
211                 /* check if exactly equal to midpoint */
212                 if (IS_EQT(frame, midfra, BEZT_INSERT_THRESH)) {
213                         *replace = 1;
214                         return mid;
215                 }
216                 
217                 /* repeat in upper/lower half */
218                 if (frame > midfra)
219                         start= mid + 1;
220                 else if (frame < midfra)
221                         end= mid - 1;
222         }
223         
224         /* print error if loop-limit exceeded */
225         if (loopbreaker == (maxloop-1)) {
226                 printf("Error: binarysearch_bezt_index was taking too long \n");
227                 
228                 // include debug info 
229                 printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen);
230         }
231         
232         /* not found, so return where to place it */
233         return start;
234 }
235
236 /* This function adds a given BezTriple to an IPO-Curve. It will allocate 
237  * memory for the array if needed, and will insert the BezTriple into a
238  * suitable place in chronological order.
239  * 
240  * NOTE: any recalculate of the IPO-Curve that needs to be done will need to 
241  *              be done by the caller.
242  */
243 int insert_bezt_icu (IpoCurve *icu, BezTriple *bezt)
244 {
245         BezTriple *newb;
246         int i= 0;
247         
248         if (icu->bezt == NULL) {
249                 icu->bezt= MEM_callocN(sizeof(BezTriple), "beztriple");
250                 *(icu->bezt)= *bezt;
251                 icu->totvert= 1;
252         }
253         else {
254                 short replace = -1;
255                 i = binarysearch_bezt_index(icu->bezt, bezt->vec[1][0], icu->totvert, &replace);
256                 
257                 if (replace) {                  
258                         /* sanity check: 'i' may in rare cases exceed arraylen */
259                         if ((i >= 0) && (i < icu->totvert))
260                                 *(icu->bezt + i) = *bezt;
261                 }
262                 else {
263                         /* add new */
264                         newb= MEM_callocN((icu->totvert+1)*sizeof(BezTriple), "beztriple");
265                         
266                         /* add the beztriples that should occur before the beztriple to be pasted (originally in ei->icu) */
267                         if (i > 0)
268                                 memcpy(newb, icu->bezt, i*sizeof(BezTriple));
269                         
270                         /* add beztriple to paste at index i */
271                         *(newb + i)= *bezt;
272                         
273                         /* add the beztriples that occur after the beztriple to be pasted (originally in icu) */
274                         if (i < icu->totvert) 
275                                 memcpy(newb+i+1, icu->bezt+i, (icu->totvert-i)*sizeof(BezTriple));
276                         
277                         /* replace (+ free) old with new */
278                         MEM_freeN(icu->bezt);
279                         icu->bezt= newb;
280                         
281                         icu->totvert++;
282                 }
283         }
284         
285         /* we need to return the index, so that some tools which do post-processing can 
286          * detect where we added the BezTriple in the array
287          */
288         return i;
289 }
290
291 /* This function is a wrapper for insert_bezt_icu, and should be used when
292  * adding a new keyframe to a curve, when the keyframe doesn't exist anywhere
293  * else yet. 
294  * 
295  * 'fast' - is only for the python API where importing BVH's would take an extreamly long time.
296  */
297 void insert_vert_icu (IpoCurve *icu, float x, float y, short fast)
298 {
299         BezTriple beztr;
300         int a, h1, h2;
301         
302         /* set all three points, for nicer start position */
303         memset(&beztr, 0, sizeof(BezTriple));
304         beztr.vec[0][0]= x; 
305         beztr.vec[0][1]= y;
306         beztr.vec[1][0]= x;
307         beztr.vec[1][1]= y;
308         beztr.vec[2][0]= x;
309         beztr.vec[2][1]= y;
310         beztr.hide= IPO_BEZ;
311         beztr.f1= beztr.f2= beztr.f3= SELECT;
312         beztr.h1= beztr.h2= HD_AUTO;
313         
314         /* add temp beztriple to keyframes */
315         a= insert_bezt_icu(icu, &beztr);
316         if (!fast) calchandles_ipocurve(icu);
317         
318         /* set handletype */
319         if (icu->totvert > 2) {
320                 BezTriple *bezt;
321                 
322                 h1= h2= HD_AUTO;
323                 bezt= (icu->bezt + a);
324                 
325                 if (a > 0) h1= (bezt-1)->h2;
326                 if (a < icu->totvert-1) h2= (bezt+1)->h1;
327                 
328                 bezt->h1= h1;
329                 bezt->h2= h2;
330                 
331                 if (!fast) calchandles_ipocurve(icu);
332         }
333 }
334
335 /* ------------------- Get Data ------------------------ */
336
337 /* Get pointer to use to get values from */
338 // FIXME: this should not be possible with Data-API
339 static void *get_context_ipo_poin (ID *id, int blocktype, char *actname, char *constname, IpoCurve *icu, int *vartype)
340 {
341         switch (blocktype) {
342                 case ID_PO:  /* posechannel */
343                         if (GS(id->name)==ID_OB) {
344                                 Object *ob= (Object *)id;
345                                 bPoseChannel *pchan= get_pose_channel(ob->pose, actname);
346                                 
347                                 if (pchan) {
348                                         *vartype= IPO_FLOAT;
349                                         return get_pchan_ipo_poin(pchan, icu->adrcode);
350                                 }
351                         }
352                         break;
353                         
354                 case ID_CO: /* constraint */
355                         if ((GS(id->name)==ID_OB) && (constname && constname[0])) {
356                                 Object *ob= (Object *)id;
357                                 bConstraint *con;
358                                 
359                                 /* assume that we only want the influence (as only used for Constraint Channels) */
360                                 if ((ob->ipoflag & OB_ACTION_OB) && !strcmp(actname, "Object")) {
361                                         for (con= ob->constraints.first; con; con= con->next) {
362                                                 if (strcmp(constname, con->name)==0) {
363                                                         *vartype= IPO_FLOAT;
364                                                         return &con->enforce;
365                                                 }
366                                         }
367                                 }
368                                 else if (ob->pose) {
369                                         bPoseChannel *pchan= get_pose_channel(ob->pose, actname);
370                                         
371                                         if (pchan) {
372                                                 for (con= pchan->constraints.first; con; con= con->next) {
373                                                         if (strcmp(constname, con->name)==0) {
374                                                                 *vartype= IPO_FLOAT;
375                                                                 return &con->enforce;
376                                                         }
377                                                 }
378                                         }
379                                 }
380                         }
381                         break;
382                         
383                 case ID_OB: /* object */
384                         /* hack: layer channels for object need to be keyed WITHOUT localview flag...
385                          * tsk... tsk... why must we just dump bitflags upon users :/
386                          */
387                         if ((GS(id->name)==ID_OB) && (icu->adrcode==OB_LAY)) {
388                                 Object *ob= (Object *)id;
389                                 static int layer = 0;
390                                 
391                                 /* init layer to be the object's layer var, then remove local view from it */
392                                 layer = ob->lay;
393                                 layer &= 0xFFFFFF;
394                                 *vartype= IPO_INT_BIT;
395                                 
396                                 /* return pointer to this static var 
397                                  *      - assumes that this pointer won't be stored for use later, so may not be threadsafe
398                                  *        if multiple keyframe calls are made, but that is unlikely to happen in the near future
399                                  */
400                                 return (void *)(&layer);
401                         }
402                         /* no break here for other ob channel-types - as they can be done normally */
403                 
404                 default: /* normal data-source */
405                         return get_ipo_poin(id, icu, vartype);
406         }
407
408         /* not valid... */
409         return NULL;
410 }
411
412
413 /* -------------- 'Smarter' Keyframing Functions -------------------- */
414 /* return codes for new_key_needed */
415 enum {
416         KEYNEEDED_DONTADD = 0,
417         KEYNEEDED_JUSTADD,
418         KEYNEEDED_DELPREV,
419         KEYNEEDED_DELNEXT
420 } eKeyNeededStatus;
421
422 /* This helper function determines whether a new keyframe is needed */
423 /* Cases where keyframes should not be added:
424  *      1. Keyframe to be added bewteen two keyframes with similar values
425  *      2. Keyframe to be added on frame where two keyframes are already situated
426  *      3. Keyframe lies at point that intersects the linear line between two keyframes
427  */
428 static short new_key_needed (IpoCurve *icu, float cFrame, float nValue) 
429 {
430         BezTriple *bezt=NULL, *prev=NULL;
431         int totCount, i;
432         float valA = 0.0f, valB = 0.0f;
433         
434         /* safety checking */
435         if (icu == NULL) return KEYNEEDED_JUSTADD;
436         totCount= icu->totvert;
437         if (totCount == 0) return KEYNEEDED_JUSTADD;
438         
439         /* loop through checking if any are the same */
440         bezt= icu->bezt;
441         for (i=0; i<totCount; i++) {
442                 float prevPosi=0.0f, prevVal=0.0f;
443                 float beztPosi=0.0f, beztVal=0.0f;
444                         
445                 /* get current time+value */    
446                 beztPosi= bezt->vec[1][0];
447                 beztVal= bezt->vec[1][1];
448                         
449                 if (prev) {
450                         /* there is a keyframe before the one currently being examined */               
451                         
452                         /* get previous time+value */
453                         prevPosi= prev->vec[1][0];
454                         prevVal= prev->vec[1][1];
455                         
456                         /* keyframe to be added at point where there are already two similar points? */
457                         if (IS_EQ(prevPosi, cFrame) && IS_EQ(beztPosi, cFrame) && IS_EQ(beztPosi, prevPosi)) {
458                                 return KEYNEEDED_DONTADD;
459                         }
460                         
461                         /* keyframe between prev+current points ? */
462                         if ((prevPosi <= cFrame) && (cFrame <= beztPosi)) {
463                                 /* is the value of keyframe to be added the same as keyframes on either side ? */
464                                 if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) {
465                                         return KEYNEEDED_DONTADD;
466                                 }
467                                 else {
468                                         float realVal;
469                                         
470                                         /* get real value of curve at that point */
471                                         realVal= eval_icu(icu, cFrame);
472                                         
473                                         /* compare whether it's the same as proposed */
474                                         if (IS_EQ(realVal, nValue)) 
475                                                 return KEYNEEDED_DONTADD;
476                                         else 
477                                                 return KEYNEEDED_JUSTADD;
478                                 }
479                         }
480                         
481                         /* new keyframe before prev beztriple? */
482                         if (cFrame < prevPosi) {
483                                 /* A new keyframe will be added. However, whether the previous beztriple
484                                  * stays around or not depends on whether the values of previous/current
485                                  * beztriples and new keyframe are the same.
486                                  */
487                                 if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal))
488                                         return KEYNEEDED_DELNEXT;
489                                 else 
490                                         return KEYNEEDED_JUSTADD;
491                         }
492                 }
493                 else {
494                         /* just add a keyframe if there's only one keyframe 
495                          * and the new one occurs before the exisiting one does.
496                          */
497                         if ((cFrame < beztPosi) && (totCount==1))
498                                 return KEYNEEDED_JUSTADD;
499                 }
500                 
501                 /* continue. frame to do not yet passed (or other conditions not met) */
502                 if (i < (totCount-1)) {
503                         prev= bezt;
504                         bezt++;
505                 }
506                 else
507                         break;
508         }
509         
510         /* Frame in which to add a new-keyframe occurs after all other keys
511          * -> If there are at least two existing keyframes, then if the values of the
512          *       last two keyframes and the new-keyframe match, the last existing keyframe
513          *       gets deleted as it is no longer required.
514          * -> Otherwise, a keyframe is just added. 1.0 is added so that fake-2nd-to-last
515          *       keyframe is not equal to last keyframe.
516          */
517         bezt= (icu->bezt + (icu->totvert - 1));
518         valA= bezt->vec[1][1];
519         
520         if (prev)
521                 valB= prev->vec[1][1];
522         else 
523                 valB= bezt->vec[1][1] + 1.0f; 
524                 
525         if (IS_EQ(valA, nValue) && IS_EQ(valA, valB)) 
526                 return KEYNEEDED_DELPREV;
527         else 
528                 return KEYNEEDED_JUSTADD;
529 }
530
531 /* ------------------ 'Visual' Keyframing Functions ------------------ */
532
533 /* internal status codes for visualkey_can_use */
534 enum {
535         VISUALKEY_NONE = 0,
536         VISUALKEY_LOC,
537         VISUALKEY_ROT
538 };
539
540 /* This helper function determines if visual-keyframing should be used when  
541  * inserting keyframes for the given channel. As visual-keyframing only works
542  * on Object and Pose-Channel blocks, this should only get called for those 
543  * blocktypes, when using "standard" keying but 'Visual Keying' option in Auto-Keying 
544  * settings is on.
545  */
546 static short visualkey_can_use (ID *id, int blocktype, char *actname, char *constname, int adrcode)
547 {
548         Object *ob= NULL;
549         bConstraint *con= NULL;
550         short searchtype= VISUALKEY_NONE;
551         
552         /* validate data */
553         if ((id == NULL) || (GS(id->name)!=ID_OB) || !(ELEM(blocktype, ID_OB, ID_PO))) 
554                 return 0;
555         
556         /* get first constraint and determine type of keyframe constraints to check for*/
557         ob= (Object *)id;
558         
559         if (blocktype == ID_OB) {
560                 con= ob->constraints.first;
561                 
562                 if (ELEM3(adrcode, OB_LOC_X, OB_LOC_Y, OB_LOC_Z))
563                         searchtype= VISUALKEY_LOC;
564                 else if (ELEM3(adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z))
565                         searchtype= VISUALKEY_ROT;
566         }
567         else if (blocktype == ID_PO) {
568                 bPoseChannel *pchan= get_pose_channel(ob->pose, actname);
569                 con= pchan->constraints.first;
570                 
571                 if (ELEM3(adrcode, AC_LOC_X, AC_LOC_Y, AC_LOC_Z))
572                         searchtype= VISUALKEY_LOC;
573                 else if (ELEM4(adrcode, AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z))
574                         searchtype= VISUALKEY_ROT;
575         }
576         
577         /* only search if a searchtype and initial constraint are available */
578         if (searchtype && con) {
579                 for (; con; con= con->next) {
580                         /* only consider constraint if it is not disabled, and has influence */
581                         if (con->flag & CONSTRAINT_DISABLE) continue;
582                         if (con->enforce == 0.0f) continue;
583                         
584                         /* some constraints may alter these transforms */
585                         switch (con->type) {
586                                 /* multi-transform constraints */
587                                 case CONSTRAINT_TYPE_CHILDOF:
588                                         return 1;
589                                 case CONSTRAINT_TYPE_TRANSFORM:
590                                         return 1;
591                                 case CONSTRAINT_TYPE_FOLLOWPATH:
592                                         return 1;
593                                         
594                                 /* single-transform constraits  */
595                                 case CONSTRAINT_TYPE_TRACKTO:
596                                         if (searchtype==VISUALKEY_ROT) return 1;
597                                         break;
598                                 case CONSTRAINT_TYPE_ROTLIMIT:
599                                         if (searchtype==VISUALKEY_ROT) return 1;
600                                         break;
601                                 case CONSTRAINT_TYPE_LOCLIMIT:
602                                         if (searchtype==VISUALKEY_LOC) return 1;
603                                         break;
604                                 case CONSTRAINT_TYPE_ROTLIKE:
605                                         if (searchtype==VISUALKEY_ROT) return 1;
606                                         break;
607                                 case CONSTRAINT_TYPE_DISTLIMIT:
608                                         if (searchtype==VISUALKEY_LOC) return 1;
609                                         break;
610                                 case CONSTRAINT_TYPE_LOCLIKE:
611                                         if (searchtype==VISUALKEY_LOC) return 1;
612                                         break;
613                                 case CONSTRAINT_TYPE_LOCKTRACK:
614                                         if (searchtype==VISUALKEY_ROT) return 1;
615                                         break;
616                                 case CONSTRAINT_TYPE_MINMAX:
617                                         if (searchtype==VISUALKEY_LOC) return 1;
618                                         break;
619                                 
620                                 default:
621                                         break;
622                         }
623                 }
624         }
625         
626         /* when some condition is met, this function returns, so here it can be 0 */
627         return 0;
628 }
629
630 /* This helper function extracts the value to use for visual-keyframing 
631  * In the event that it is not possible to perform visual keying, try to fall-back
632  * to using the poin method. Assumes that all data it has been passed is valid.
633  */
634 static float visualkey_get_value (ID *id, int blocktype, char *actname, char *constname, int adrcode, IpoCurve *icu)
635 {
636         Object *ob;
637         void *poin = NULL;
638         int index, vartype;
639         
640         /* validate situtation */
641         if ((id==NULL) || (GS(id->name)!=ID_OB) || (ELEM(blocktype, ID_OB, ID_PO)==0))
642                 return 0.0f;
643                 
644         /* get object */
645         ob= (Object *)id;
646         
647         /* only valid for objects or posechannels */
648         if (blocktype == ID_OB) {
649                 /* parented objects are not supported, as the effects of the parent
650                  * are included in the matrix, which kindof beats the point
651                  */
652                 if (ob->parent == NULL) {
653                         /* only Location or Rotation keyframes are supported now */
654                         if (ELEM3(adrcode, OB_LOC_X, OB_LOC_Y, OB_LOC_Z)) {
655                                 /* assumes that OB_LOC_Z > OB_LOC_Y > OB_LOC_X */
656                                 index= adrcode - OB_LOC_X;
657                                 
658                                 return ob->obmat[3][index];
659                         }
660                         else if (ELEM3(adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) {
661                                 float eul[3];
662                                 
663                                 /* assumes that OB_ROT_Z > OB_ROT_Y > OB_ROT_X */
664                                 index= adrcode - OB_ROT_X;
665                                 
666                                 Mat4ToEul(ob->obmat, eul);
667                                 return eul[index]*(5.72958f);
668                         }
669                 }
670         }
671         else if (blocktype == ID_PO) {
672                 bPoseChannel *pchan;
673                 float tmat[4][4];
674                 
675                 /* get data to use */
676                 pchan= get_pose_channel(ob->pose, actname);
677                 
678                 /* Although it is not strictly required for this particular space conversion, 
679                  * arg1 must not be null, as there is a null check for the other conversions to
680                  * be safe. Therefore, the active object is passed here, and in many cases, this
681                  * will be what owns the pose-channel that is getting this anyway.
682                  */
683                 Mat4CpyMat4(tmat, pchan->pose_mat);
684                 constraint_mat_convertspace(ob, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
685                 
686                 /* Loc, Rot/Quat keyframes are supported... */
687                 if (ELEM3(adrcode, AC_LOC_X, AC_LOC_Y, AC_LOC_Z)) {
688                         /* assumes that AC_LOC_Z > AC_LOC_Y > AC_LOC_X */
689                         index= adrcode - AC_LOC_X;
690                         
691                         /* only use for non-connected bones */
692                         if ((pchan->bone->parent) && !(pchan->bone->flag & BONE_CONNECTED))
693                                 return tmat[3][index];
694                         else if (pchan->bone->parent == NULL)
695                                 return tmat[3][index];
696                 }
697                 else if (ELEM4(adrcode, AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z)) {
698                         float trimat[3][3], quat[4];
699                         
700                         /* assumes that AC_QUAT_Z > AC_QUAT_Y > AC_QUAT_X > AC_QUAT_W */
701                         index= adrcode - AC_QUAT_W;
702                         
703                         Mat3CpyMat4(trimat, tmat);
704                         Mat3ToQuat_is_ok(trimat, quat);
705                         
706                         return quat[index];
707                 }
708         }
709         
710         /* as the function hasn't returned yet, try reading from poin */
711         poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype);
712         if (poin)
713                 return read_ipo_poin(poin, vartype);
714         else
715                 return 0.0;
716 }
717
718
719 /* ------------------------- Insert Key API ------------------------- */
720
721 /* Main Keyframing API call:
722  *      Use this when validation of necessary animation data isn't necessary as it
723  *      already exists. It will insert a keyframe using the current value being keyframed.
724  *      
725  *      The flag argument is used for special settings that alter the behaviour of
726  *      the keyframe insertion. These include the 'visual' keyframing modes, quick refresh,
727  *      and extra keyframe filtering.
728  */
729 short insertkey (ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag)
730 {       
731         IpoCurve *icu;
732         
733         /* get ipo-curve */
734         icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode, 1);
735         
736         /* only continue if we have an ipo-curve to add keyframe to */
737         if (icu) {
738                 float cfra = frame_to_float(CFRA);
739                 float curval= 0.0f;
740                 
741                 /* apply special time tweaking */
742                 if (GS(id->name) == ID_OB) {
743                         Object *ob= (Object *)id;
744                         
745                         /* apply NLA-scaling (if applicable) */
746                         if (actname && actname[0]) 
747                                 cfra= get_action_frame(ob, cfra);
748                         
749                         /* ancient time-offset cruft */
750                         if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) {
751                                 /* actually frametofloat calc again! */
752                                 cfra-= give_timeoffset(ob)*G.scene->r.framelen;
753                         }
754                 }
755                 
756                 /* obtain value to give keyframe */
757                 if ( (flag & INSERTKEY_MATRIX) && 
758                          (visualkey_can_use(id, blocktype, actname, constname, adrcode)) ) 
759                 {
760                         /* visual-keying is only available for object and pchan datablocks, as 
761                          * it works by keyframing using a value extracted from the final matrix 
762                          * instead of using the kt system to extract a value.
763                          */
764                         curval= visualkey_get_value(id, blocktype, actname, constname, adrcode, icu);
765                 }
766                 else {
767                         void *poin;
768                         int vartype;
769                         
770                         /* get pointer to data to read from */
771                         poin = get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype);
772                         if (poin == NULL) {
773                                 printf("Insert Key: No pointer to variable obtained \n");
774                                 return 0;
775                         }
776                         
777                         /* use kt's read_poin function to extract value (kt->read_poin should 
778                          * exist in all cases, but it never hurts to check)
779                          */
780                         curval= read_ipo_poin(poin, vartype);
781                 }
782                 
783                 /* only insert keyframes where they are needed */
784                 if (flag & INSERTKEY_NEEDED) {
785                         short insert_mode;
786                         
787                         /* check whether this curve really needs a new keyframe */
788                         insert_mode= new_key_needed(icu, cfra, curval);
789                         
790                         /* insert new keyframe at current frame */
791                         if (insert_mode)
792                                 insert_vert_icu(icu, cfra, curval, (flag & INSERTKEY_FAST));
793                         
794                         /* delete keyframe immediately before/after newly added */
795                         switch (insert_mode) {
796                                 case KEYNEEDED_DELPREV:
797                                         delete_icu_key(icu, icu->totvert-2, 1);
798                                         break;
799                                 case KEYNEEDED_DELNEXT:
800                                         delete_icu_key(icu, 1, 1);
801                                         break;
802                         }
803                         
804                         /* only return success if keyframe added */
805                         if (insert_mode)
806                                 return 1;
807                 }
808                 else {
809                         /* just insert keyframe */
810                         insert_vert_icu(icu, cfra, curval, (flag & INSERTKEY_FAST));
811                         
812                         /* return success */
813                         return 1;
814                 }
815         }
816         
817         /* return failure */
818         return 0;
819 }
820
821
822 /* ************************************************** */
823 /* KEYFRAME DELETION */
824
825 /* Main Keyframing API call:
826  *      Use this when validation of necessary animation data isn't necessary as it
827  *      already exists. It will delete a keyframe at the current frame.
828  *      
829  *      The flag argument is used for special settings that alter the behaviour of
830  *      the keyframe deletion. These include the quick refresh options.
831  */
832 short deletekey (ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag)
833 {
834         Ipo *ipo;
835         IpoCurve *icu;
836         
837         /* get ipo-curve 
838          * Note: here is one of the places where we don't want new ipo + ipo-curve added!
839          *              so 'add' var must be 0
840          */
841         ipo= verify_ipo(id, blocktype, actname, constname, NULL, 0);
842         icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode, 0);
843         
844         /* only continue if we have an ipo-curve to remove keyframes from */
845         if (icu) {
846                 float cfra = frame_to_float(CFRA);
847                 short found = -1;
848                 int i;
849                 
850                 /* apply special time tweaking */
851                 if (GS(id->name) == ID_OB) {
852                         Object *ob= (Object *)id;
853                         
854                         /* apply NLA-scaling (if applicable) */
855                         if (actname && actname[0]) 
856                                 cfra= get_action_frame(ob, cfra);
857                         
858                         /* ancient time-offset cruft */
859                         if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) {
860                                 /* actually frametofloat calc again! */
861                                 cfra-= give_timeoffset(ob)*G.scene->r.framelen;
862                         }
863                 }
864                 
865                 /* try to find index of beztriple to get rid of */
866                 i = binarysearch_bezt_index(icu->bezt, cfra, icu->totvert, &found);
867                 if (found) {                    
868                         /* delete the key at the index (will sanity check + do recalc afterwards ) */
869                         delete_icu_key(icu, i, 1);
870                         
871                         /* Only delete curve too if there isn't an ipo-driver still hanging around on an empty curve */
872                         if (icu->totvert==0 && icu->driver==NULL) {
873                                 BLI_remlink(&ipo->curve, icu);
874                                 free_ipo_curve(icu);
875                         }
876                         
877                         /* return success */
878                         return 1;
879                 }
880         }
881         
882         /* return failure */
883         return 0;
884 }
885
886 /* ************************************************** */
887 /* COMMON KEYFRAME MANAGEMENT (common_insertkey/deletekey) */
888
889 /* mode for common_modifykey */
890 enum {
891         COMMONKEY_MODE_INSERT = 0,
892         COMMONKEY_MODE_DELETE,
893 } eCommonModifyKey_Modes;
894
895 /* ------------- KeyingSet Defines ------------ */
896 /* Note: these must all be named with the defks_* prefix, otherwise the template macro will not work! */
897
898 /* macro for defining keyingset contexts */
899 #define KSC_TEMPLATE(ctx_name) {&defks_##ctx_name[0], NULL, sizeof(defks_##ctx_name)/sizeof(bKeyingSet)}
900
901 /* --- */
902
903 /* check if option not available for deleting keys */
904 static short incl_non_del_keys (bKeyingSet *ks, const char mode[])
905 {
906         /* as optimisation, assume that it is sufficient to check only first letter
907          * of mode (int comparison should be faster than string!)
908          */
909         //if (strcmp(mode, "Delete")==0)
910         if (mode && mode[0]=='D')
911                 return 0;
912         
913         return 1;
914 }
915
916 /* Object KeyingSets  ------ */
917
918 /* check if include shapekey entry  */
919 static short incl_v3d_ob_shapekey (bKeyingSet *ks, const char mode[])
920 {
921         Object *ob= (G.obedit)? (G.obedit) : (OBACT);
922         char *newname= NULL;
923         
924         /* not available for delete mode */
925         if (strcmp(mode, "Delete")==0)
926                 return 0;
927         
928         /* check if is geom object that can get shapekeys */
929         switch (ob->type) {
930                 /* geometry? */
931                 case OB_MESH:           newname= "Mesh";                break;
932                 case OB_CURVE:          newname= "Curve";               break;
933                 case OB_SURF:           newname= "Surface";             break;
934                 case OB_LATTICE:        newname= "Lattice";             break;
935                 
936                 /* not geometry! */
937                 default:
938                         return 0;
939         }
940         
941         /* if ks is shapekey entry (this could be callled for separator before too!) */
942         if (ks->flag == -3)
943                 sprintf(ks->name, newname);
944         
945         /* if it gets here, it's ok */
946         return 1;
947 }
948
949 /* array for object keyingset defines */
950 bKeyingSet defks_v3d_object[] = 
951 {
952         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
953         {NULL, "Loc", ID_OB, 0, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}},
954         {NULL, "Rot", ID_OB, 0, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
955         {NULL, "Scale", ID_OB, 0, 3, {OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
956         
957         {NULL, "%l", 0, -1, 0, {0}}, // separator
958         
959         {NULL, "LocRot", ID_OB, 0, 6, 
960                 {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
961                  OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
962                  
963         {NULL, "LocScale", ID_OB, 0, 6, 
964                 {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
965                  OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
966                  
967         {NULL, "LocRotScale", ID_OB, 0, 9, 
968                 {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
969                  OB_ROT_X,OB_ROT_Y,OB_ROT_Z,
970                  OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
971                  
972         {NULL, "RotScale", ID_OB, 0, 6, 
973                 {OB_ROT_X,OB_ROT_Y,OB_ROT_Z,
974                  OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
975         
976         {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator
977         
978         {incl_non_del_keys, "VisualLoc", ID_OB, INSERTKEY_MATRIX, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}},
979         {incl_non_del_keys, "VisualRot", ID_OB, INSERTKEY_MATRIX, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
980         
981         {incl_non_del_keys, "VisualLocRot", ID_OB, INSERTKEY_MATRIX, 6, 
982                 {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
983                  OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
984         
985         {NULL, "%l", 0, -1, 0, {0}}, // separator
986         
987         {NULL, "Layer", ID_OB, 0, 1, {OB_LAY}}, // icky option...
988         {NULL, "Available", ID_OB, -2, 0, {0}},
989         
990         {incl_v3d_ob_shapekey, "%l%l", 0, -1, 0, {0}}, // separator (linked to shapekey entry)
991         {incl_v3d_ob_shapekey, "<ShapeKey>", ID_OB, -3, 0, {0}}
992 };
993
994 /* PoseChannel KeyingSets  ------ */
995
996 /* array for posechannel keyingset defines */
997 bKeyingSet defks_v3d_pchan[] = 
998 {
999         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
1000         {NULL, "Loc", ID_PO, 0, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}},
1001         {NULL, "Rot", ID_PO, 0, 4, {AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}},
1002         {NULL, "Scale", ID_PO, 0, 3, {AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}},
1003         
1004         {NULL, "%l", 0, -1, 0, {0}}, // separator
1005         
1006         {NULL, "LocRot", ID_PO, 0, 7, 
1007                 {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_QUAT_W,
1008                  AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}},
1009                  
1010         {NULL, "LocScale", ID_PO, 0, 6, 
1011                 {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,
1012                  AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}},
1013                  
1014         {NULL, "LocRotScale", ID_PO, 0, 10, 
1015                 {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_QUAT_W,AC_QUAT_X,
1016                  AC_QUAT_Y,AC_QUAT_Z,AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}},
1017                  
1018         {NULL, "RotScale", ID_PO, 0, 7, 
1019                 {AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z,
1020                  AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}},
1021         
1022         {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator
1023         
1024         {incl_non_del_keys, "VisualLoc", ID_PO, INSERTKEY_MATRIX, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}},
1025         {incl_non_del_keys, "VisualRot", ID_PO, INSERTKEY_MATRIX, 4, {AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}},
1026         
1027         {incl_non_del_keys, "VisualLocRot", ID_PO, INSERTKEY_MATRIX, 7, 
1028                 {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_QUAT_W,
1029                  AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}},
1030         
1031         {NULL, "%l", 0, -1, 0, {0}}, // separator
1032         
1033         {NULL, "Available", ID_PO, -2, 0, {0}}
1034 };
1035
1036 /* Material KeyingSets  ------ */
1037
1038 /* array for material keyingset defines */
1039 bKeyingSet defks_buts_shading_mat[] = 
1040 {
1041         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
1042         {NULL, "RGB", ID_MA, 0, 3, {MA_COL_R,MA_COL_G,MA_COL_B}},
1043         {NULL, "Alpha", ID_MA, 0, 1, {MA_ALPHA}},
1044         {NULL, "Halo Size", ID_MA, 0, 1, {MA_HASIZE}},
1045         {NULL, "Mode", ID_MA, 0, 1, {MA_MODE}}, // evil bitflags
1046         
1047         {NULL, "%l", 0, -1, 0, {0}}, // separator
1048         
1049         {NULL, "All Color", ID_MA, 0, 18, 
1050                 {MA_COL_R,MA_COL_G,MA_COL_B,
1051                  MA_ALPHA,MA_HASIZE, MA_MODE,
1052                  MA_SPEC_R,MA_SPEC_G,MA_SPEC_B,
1053                  MA_REF,MA_EMIT,MA_AMB,MA_SPEC,MA_HARD,
1054                  MA_MODE,MA_TRANSLU,MA_ADD}},
1055                  
1056         {NULL, "All Mirror", ID_MA, 0, 5, 
1057                 {MA_RAYM,MA_FRESMIR,MA_FRESMIRI,
1058                  MA_FRESTRA,MA_FRESTRAI}},
1059         
1060         {NULL, "%l", 0, -1, 0, {0}}, // separator
1061         
1062         {NULL, "Ofs", ID_MA, COMMONKEY_ADDMAP, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
1063         {NULL, "Size", ID_MA, COMMONKEY_ADDMAP, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
1064         
1065         {NULL, "All Mapping", ID_MA, COMMONKEY_ADDMAP, 14, 
1066                 {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
1067                  MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
1068                  MAP_R,MAP_G,MAP_B,MAP_DVAR,
1069                  MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
1070         
1071         {NULL, "%l", 0, -1, 0, {0}}, // separator
1072         
1073         {NULL, "Available", ID_MA, -2, 0, {0}}
1074 };
1075
1076 /* World KeyingSets  ------ */
1077
1078 /* array for world keyingset defines */
1079 bKeyingSet defks_buts_shading_wo[] = 
1080 {
1081         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
1082         {NULL, "Zenith RGB", ID_WO, 0, 3, {WO_ZEN_R,WO_ZEN_G,WO_ZEN_B}},
1083         {NULL, "Horizon RGB", ID_WO, 0, 3, {WO_HOR_R,WO_HOR_G,WO_HOR_B}},
1084         
1085         {NULL, "%l", 0, -1, 0, {0}}, // separator
1086         
1087         {NULL, "Mist", ID_WO, 0, 4, {WO_MISI,WO_MISTDI,WO_MISTSTA,WO_MISTHI}},
1088         {NULL, "Stars", ID_WO, 0, 5, {WO_STAR_R,WO_STAR_G,WO_STAR_B,WO_STARDIST,WO_STARSIZE}},
1089         
1090         
1091         {NULL, "%l", 0, -1, 0, {0}}, // separator
1092         
1093         {NULL, "Ofs", ID_WO, COMMONKEY_ADDMAP, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
1094         {NULL, "Size", ID_WO, COMMONKEY_ADDMAP, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
1095         
1096         {NULL, "All Mapping", ID_WO, COMMONKEY_ADDMAP, 14, 
1097                 {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
1098                  MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
1099                  MAP_R,MAP_G,MAP_B,MAP_DVAR,
1100                  MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
1101         
1102         {NULL, "%l", 0, -1, 0, {0}}, // separator
1103         
1104         {NULL, "Available", ID_WO, -2, 0, {0}}
1105 };
1106
1107 /* Lamp KeyingSets  ------ */
1108
1109 /* array for lamp keyingset defines */
1110 bKeyingSet defks_buts_shading_la[] = 
1111 {
1112         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
1113         {NULL, "RGB", ID_LA, 0, 3, {LA_COL_R,LA_COL_G,LA_COL_B}},
1114         {NULL, "Energy", ID_LA, 0, 1, {LA_ENERGY}},
1115         {NULL, "Spot Size", ID_LA, 0, 1, {LA_SPOTSI}},
1116         
1117         {NULL, "%l", 0, -1, 0, {0}}, // separator
1118         
1119         {NULL, "Ofs", ID_LA, COMMONKEY_ADDMAP, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
1120         {NULL, "Size", ID_LA, COMMONKEY_ADDMAP, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
1121         
1122         {NULL, "All Mapping", ID_LA, COMMONKEY_ADDMAP, 14, 
1123                 {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
1124                  MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
1125                  MAP_R,MAP_G,MAP_B,MAP_DVAR,
1126                  MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
1127         
1128         {NULL, "%l", 0, -1, 0, {0}}, // separator
1129         
1130         {NULL, "Available", ID_LA, -2, 0, {0}}
1131 };
1132
1133 /* Texture KeyingSets  ------ */
1134
1135 /* array for texture keyingset defines */
1136 bKeyingSet defks_buts_shading_tex[] = 
1137 {
1138         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
1139         {NULL, "Clouds", ID_TE, 0, 5, 
1140                 {TE_NSIZE,TE_NDEPTH,TE_NTYPE,
1141                  TE_MG_TYP,TE_N_BAS1}},
1142         
1143         {NULL, "Marble", ID_TE, 0, 7, 
1144                 {TE_NSIZE,TE_NDEPTH,TE_NTYPE,
1145                  TE_TURB,TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}},
1146                  
1147         {NULL, "Stucci", ID_TE, 0, 5, 
1148                 {TE_NSIZE,TE_NTYPE,TE_TURB,
1149                  TE_MG_TYP,TE_N_BAS1}},
1150                  
1151         {NULL, "Wood", ID_TE, 0, 6, 
1152                 {TE_NSIZE,TE_NTYPE,TE_TURB,
1153                  TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}},
1154                  
1155         {NULL, "Magic", ID_TE, 0, 2, {TE_NDEPTH,TE_TURB}},
1156         
1157         {NULL, "Blend", ID_TE, 0, 1, {TE_MG_TYP}},      
1158                 
1159         {NULL, "Musgrave", ID_TE, 0, 6, 
1160                 {TE_MG_TYP,TE_MGH,TE_MG_LAC,
1161                  TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN}},
1162                  
1163         {NULL, "Voronoi", ID_TE, 0, 9, 
1164                 {TE_VNW1,TE_VNW2,TE_VNW3,TE_VNW4,
1165                 TE_VNMEXP,TE_VN_DISTM,TE_VN_COLT,
1166                 TE_ISCA,TE_NSIZE}},
1167                 
1168         {NULL, "Distorted Noise", ID_TE, 0, 4, 
1169                 {TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN,TE_DISTA}},
1170         
1171         {NULL, "Color Filter", ID_TE, 0, 5, 
1172                 {TE_COL_R,TE_COL_G,TE_COL_B,TE_BRIGHT,TE_CONTRA}},
1173         
1174         {NULL, "%l", 0, -1, 0, {0}}, // separator
1175         
1176         {NULL, "Available", ID_TE, -2, 0, {0}}
1177 };
1178
1179 /* Object Buttons KeyingSets  ------ */
1180
1181 /* check if include particles entry  */
1182 static short incl_buts_ob (bKeyingSet *ks, const char mode[])
1183 {
1184         Object *ob= OBACT;
1185         /* only if object is mesh type */
1186         return (ob->type == OB_MESH);
1187 }
1188
1189 /* array for texture keyingset defines */
1190 bKeyingSet defks_buts_object[] = 
1191 {
1192         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
1193         {incl_buts_ob, "Surface Damping", ID_OB, 0, 1, {OB_PD_SDAMP}},
1194         {incl_buts_ob, "Random Damping", ID_OB, 0, 1, {OB_PD_RDAMP}},
1195         {incl_buts_ob, "Permeability", ID_OB, 0, 1, {OB_PD_PERM}},
1196         
1197         {NULL, "%l", 0, -1, 0, {0}}, // separator
1198         
1199         {NULL, "Force Strength", ID_OB, 0, 1, {OB_PD_FSTR}},
1200         {NULL, "Force Falloff", ID_OB, 0, 1, {OB_PD_FFALL}},
1201         
1202         {NULL, "%l", 0, -1, 0, {0}}, // separator
1203         
1204         {NULL, "Available", ID_OB, -2, 0, {0}}  // this will include ob-transforms too!
1205 };
1206
1207 /* Camera Buttons KeyingSets  ------ */
1208
1209 /* check if include internal-renderer entry  */
1210 static short incl_buts_cam1 (bKeyingSet *ks, const char mode[])
1211 {
1212         /* only if renderer is internal renderer */
1213         return (G.scene->r.renderer==R_INTERN);
1214 }
1215
1216 /* check if include external-renderer entry  */
1217 static short incl_buts_cam2 (bKeyingSet *ks, const char mode[])
1218 {
1219         /* only if renderer is internal renderer */
1220         return (G.scene->r.renderer!=R_INTERN);
1221 }
1222
1223 /* array for camera keyingset defines */
1224 bKeyingSet defks_buts_cam[] = 
1225 {
1226         /* include_cb, name, blocktype, flag, chan_num, adrcodes */
1227         {NULL, "Lens", ID_CA, 0, 1, {CAM_LENS}},
1228         {NULL, "Clipping", ID_CA, 0, 2, {CAM_STA,CAM_END}},
1229         {NULL, "Focal Distance", ID_CA, 0, 1, {CAM_YF_FDIST}},
1230         
1231         {NULL, "%l", 0, -1, 0, {0}}, // separator
1232         
1233         
1234         {incl_buts_cam2, "Aperture", ID_CA, 0, 1, {CAM_YF_APERT}},
1235         {incl_buts_cam1, "Viewplane Shift", ID_CA, 0, 2, {CAM_SHIFT_X,CAM_SHIFT_Y}},
1236         
1237         {NULL, "%l", 0, -1, 0, {0}}, // separator
1238         
1239         {NULL, "Available", ID_CA, -2, 0, {0}}
1240 };
1241
1242 /* --- */
1243
1244 /* Keying Context Defines - Must keep in sync with enumeration (eKS_Contexts) */
1245 bKeyingContext ks_contexts[] = 
1246 {
1247         KSC_TEMPLATE(v3d_object),
1248         KSC_TEMPLATE(v3d_pchan),
1249         
1250         KSC_TEMPLATE(buts_shading_mat),
1251         KSC_TEMPLATE(buts_shading_wo),
1252         KSC_TEMPLATE(buts_shading_la),
1253         KSC_TEMPLATE(buts_shading_tex),
1254
1255         KSC_TEMPLATE(buts_object),
1256         KSC_TEMPLATE(buts_cam)
1257 };
1258
1259 /* Keying Context Enumeration - Must keep in sync with definitions*/
1260 typedef enum eKS_Contexts {
1261         KSC_V3D_OBJECT = 0,
1262         KSC_V3D_PCHAN,
1263         
1264         KSC_BUTS_MAT,
1265         KSC_BUTS_WO,
1266         KSC_BUTS_LA,
1267         KSC_BUTS_TEX,
1268         
1269         KSC_BUTS_OB,
1270         KSC_BUTS_CAM,
1271         
1272                 /* make sure this last one remains untouched! */
1273         KSC_TOT_TYPES
1274 } eKS_Contexts;
1275
1276
1277 /* ---------------- KeyingSet Tools ------------------- */
1278
1279 /* helper for commonkey_context_get() -  get keyingsets for 3d-view */
1280 static void commonkey_context_getv3d (ListBase *sources, bKeyingContext **ksc)
1281 {
1282         Object *ob;
1283         IpoCurve *icu;
1284         
1285         if ((OBACT) && (OBACT->flag & OB_POSEMODE)) {
1286                 bPoseChannel *pchan;
1287                 
1288                 /* pose-level */
1289                 ob= OBACT;
1290                 *ksc= &ks_contexts[KSC_V3D_PCHAN];
1291                 set_pose_keys(ob);  /* sets pchan->flag to POSE_KEY if bone selected, and clears if not */
1292                 
1293                 /* loop through posechannels */
1294                 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
1295                         if (pchan->flag & POSE_KEY) {
1296                                 bCommonKeySrc *cks;
1297                                 
1298                                 /* add new keyframing destination */
1299                                 cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1300                                 BLI_addtail(sources, cks);
1301                                 
1302                                 /* set id-block to key to, and action */
1303                                 cks->id= (ID *)ob;
1304                                 cks->act= ob->action;
1305                                 
1306                                 /* set pchan */
1307                                 cks->pchan= pchan;
1308                                 cks->actname= pchan->name;
1309                         }
1310                 }
1311         }
1312         else {
1313                 Base *base;
1314                 
1315                 /* object-level */
1316                 *ksc= &ks_contexts[KSC_V3D_OBJECT];
1317                 
1318                 /* loop through bases */
1319                 for (base= FIRSTBASE; base; base= base->next) {
1320                         if (TESTBASELIB(base)) {
1321                                 bCommonKeySrc *cks;
1322                                 
1323                                 /* add new keyframing destination */
1324                                 cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1325                                 BLI_addtail(sources, cks);
1326                                 
1327                                 /* set id-block to key to */
1328                                 ob= base->object;
1329                                 cks->id= (ID *)ob;
1330                                 
1331                                 /* when ob's keyframes are in an action, default to using 'Object' as achan name */
1332                                 if (ob->ipoflag & OB_ACTION_OB)
1333                                         cks->actname= "Object";
1334                                 
1335                                 /* set ipo-flags */
1336                                 // TODO: add checks for lib-linked data
1337                                 if ((ob->ipo) || (ob->action)) {
1338                                         if (ob->ipo) {
1339                                                 cks->ipo= ob->ipo;
1340                                         }
1341                                         else {
1342                                                 bActionChannel *achan;
1343                                                 
1344                                                 cks->act= ob->action;
1345                                                 achan= get_action_channel(ob->action, cks->actname);
1346                                                 
1347                                                 if (achan && achan->ipo)
1348                                                         cks->ipo= achan->ipo;
1349                                         }
1350                                         /* cks->ipo can be NULL while editing */
1351                                         if(cks->ipo) {
1352                                                 /* deselect all ipo-curves */
1353                                                 for (icu= cks->ipo->curve.first; icu; icu= icu->next) {
1354                                                         icu->flag &= ~IPO_SELECT;
1355                                                 }
1356                                         }
1357                                 }
1358                         }
1359                 }
1360         }
1361 }
1362
1363 /* helper for commonkey_context_get() -  get keyingsets for buttons window */
1364 static void commonkey_context_getsbuts (ListBase *sources, bKeyingContext **ksc)
1365 {
1366         bCommonKeySrc *cks;
1367         
1368         /* check on tab-type */
1369         switch (G.buts->mainb) {
1370         case CONTEXT_SHADING:   /* ------------- Shading buttons ---------------- */
1371                 /* subtabs include "Material", "Texture", "Lamp", "World"*/
1372                 switch (G.buts->tab[CONTEXT_SHADING]) {
1373                         case TAB_SHADING_MAT: /* >------------- Material Tab -------------< */
1374                         {
1375                                 Material *ma= editnode_get_active_material(G.buts->lockpoin);
1376                                 
1377                                 if (ma) {
1378                                         /* add new keyframing destination */
1379                                         cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1380                                         BLI_addtail(sources, cks); 
1381                                         
1382                                         /* set data */
1383                                         cks->id= (ID *)ma;
1384                                         cks->ipo= ma->ipo;
1385                                         cks->map= texchannel_to_adrcode(ma->texact);
1386                                         
1387                                         /* set keyingsets */
1388                                         *ksc= &ks_contexts[KSC_BUTS_MAT];
1389                                         return;
1390                                 }
1391                         }
1392                                 break;
1393                         case TAB_SHADING_WORLD: /* >------------- World Tab -------------< */
1394                         {
1395                                 World *wo= G.buts->lockpoin;
1396                                 
1397                                 if (wo) {
1398                                         /* add new keyframing destination */
1399                                         cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1400                                         BLI_addtail(sources, cks); 
1401                                         
1402                                         /* set data */
1403                                         cks->id= (ID *)wo;
1404                                         cks->ipo= wo->ipo;
1405                                         cks->map= texchannel_to_adrcode(wo->texact);
1406                                         
1407                                         /* set keyingsets */
1408                                         *ksc= &ks_contexts[KSC_BUTS_WO];
1409                                         return;
1410                                 }
1411                         }
1412                                 break;
1413                         case TAB_SHADING_LAMP: /* >------------- Lamp Tab -------------< */
1414                         {
1415                                 Lamp *la= G.buts->lockpoin;
1416                                 
1417                                 if (la) {
1418                                         /* add new keyframing destination */
1419                                         cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1420                                         BLI_addtail(sources, cks); 
1421                                         
1422                                         /* set data */
1423                                         cks->id= (ID *)la;
1424                                         cks->ipo= la->ipo;
1425                                         cks->map= texchannel_to_adrcode(la->texact);
1426                                         
1427                                         /* set keyingsets */
1428                                         *ksc= &ks_contexts[KSC_BUTS_LA];
1429                                         return;
1430                                 }
1431                         }
1432                                 break;
1433                         case TAB_SHADING_TEX: /* >------------- Texture Tab -------------< */
1434                         {
1435                                 Tex *tex= G.buts->lockpoin;
1436                                 
1437                                 if (tex) {
1438                                         /* add new keyframing destination */
1439                                         cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1440                                         BLI_addtail(sources, cks); 
1441                                         
1442                                         /* set data */
1443                                         cks->id= (ID *)tex;
1444                                         cks->ipo= tex->ipo;
1445                                         
1446                                         /* set keyingsets */
1447                                         *ksc= &ks_contexts[KSC_BUTS_TEX];
1448                                         return;
1449                                 }
1450                         }
1451                                 break;
1452                 }
1453                 break;
1454         
1455         case CONTEXT_OBJECT:    /* ------------- Object buttons ---------------- */
1456                 {
1457                         Object *ob= OBACT;
1458                         
1459                         if (ob) {
1460                                 /* add new keyframing destination */
1461                                 cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1462                                 BLI_addtail(sources, cks);
1463                                 
1464                                 /* set id-block to key to */
1465                                 cks->id= (ID *)ob;
1466                                 cks->ipo= ob->ipo;
1467                                 
1468                                 /* set keyingsets */
1469                                 *ksc= &ks_contexts[KSC_BUTS_OB];
1470                                 return;
1471                         }
1472                 }
1473                 break;
1474         
1475         case CONTEXT_EDITING:   /* ------------- Editing buttons ---------------- */
1476                 {
1477                         Object *ob= OBACT;
1478                         
1479                         if ((ob) && (ob->type==OB_CAMERA) && (G.buts->lockpoin)) { /* >---------------- camera buttons ---------------< */
1480                                 Camera *ca= G.buts->lockpoin;
1481                                 
1482                                 /* add new keyframing destination */
1483                                 cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1484                                 BLI_addtail(sources, cks);
1485                                 
1486                                 /* set id-block to key to */
1487                                 cks->id= (ID *)ca;
1488                                 cks->ipo= ca->ipo;
1489                                 
1490                                 /* set keyingsets */
1491                                 *ksc= &ks_contexts[KSC_BUTS_CAM];
1492                                 return;
1493                         }
1494                 }
1495                 break;
1496         }
1497         
1498         /* if nothing happened... */
1499         *ksc= NULL;
1500 }
1501
1502
1503 /* get keyingsets for appropriate context */
1504 static void commonkey_context_get (ScrArea *sa, short mode, ListBase *sources, bKeyingContext **ksc)
1505 {
1506         /* check view type */
1507         switch (sa->spacetype) {
1508                 /* 3d view - first one tested as most often used */
1509                 case SPACE_VIEW3D:
1510                 {
1511                         commonkey_context_getv3d(sources, ksc);
1512                 }
1513                         break;
1514                         
1515                 /* buttons view */
1516                 case SPACE_BUTS:
1517                 {
1518                         commonkey_context_getsbuts(sources, ksc);
1519                 }
1520                         break;
1521                         
1522                 /* spaces with their own methods */
1523                 case SPACE_IPO:
1524                         if (mode == COMMONKEY_MODE_INSERT)
1525                                 insertkey_editipo();
1526                         return;
1527                 case SPACE_ACTION:
1528                         if (mode == COMMONKEY_MODE_INSERT)
1529                                 insertkey_action();
1530                         return;
1531                         
1532                 /* timeline view - keyframe buttons */
1533                 case SPACE_TIME:
1534                 {
1535                         ScrArea *sab;
1536                         int bigarea= 0;
1537                         
1538                         /* try to find largest 3d-view available 
1539                          * (mostly of the time, this is what when user will want this,
1540                          *  as it's a standard feature in all other apps) 
1541                          */
1542                         sab= find_biggest_area_of_type(SPACE_VIEW3D);
1543                         if (sab) {
1544                                 commonkey_context_getv3d(sources, ksc);
1545                                 return;
1546                         }
1547                         
1548                         /* if not found, sab is now NULL, so perform own biggest area test */
1549                         for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
1550                                 int area= sa->winx * sa->winy;
1551                                 
1552                                 if (sa->spacetype != SPACE_TIME) {
1553                                         if ( (!sab) || (area > bigarea) ) {
1554                                                 sab= sa;
1555                                                 bigarea= area;
1556                                         }
1557                                 }
1558                         }
1559                         
1560                         /* use whichever largest area was found (it shouldn't be a time window) */
1561                         if (sab)
1562                                 commonkey_context_get(sab, mode, sources, ksc);
1563                 }
1564                         break;
1565         }
1566 }
1567
1568 /* flush updates after all operations */
1569 static void commonkey_context_finish (ListBase *sources)
1570 {
1571         /* check view type */
1572         switch (curarea->spacetype) {
1573                 /* 3d view - first one tested as most often used */
1574                 case SPACE_VIEW3D:
1575                 {
1576                         /* either pose or object level */
1577                         if (OBACT && (OBACT->pose)) {   
1578                                 Object *ob= OBACT;
1579                                 
1580                                 /* recalculate ipo handles, etc. */
1581                                 if (ob->action)
1582                                         remake_action_ipos(ob->action);
1583                                 
1584                                 /* recalculate bone-paths on adding new keyframe? */
1585                                 // TODO: currently, there is no setting to turn this on/off globally
1586                                 if (ob->pose->flag & POSE_RECALCPATHS)
1587                                         pose_recalculate_paths(ob);
1588                         }
1589                         else {
1590                                 bCommonKeySrc *cks;
1591                                 
1592                                 /* loop over bases (as seen in sources) */
1593                                 for (cks= sources->first; cks; cks= cks->next) {
1594                                         Object *ob= (Object *)cks->id;
1595                                         
1596                                         /* simply set recalc flag */
1597                                         ob->recalc |= OB_RECALC_OB;
1598                                 }
1599                         }
1600                 }
1601                         break;
1602         }
1603 }
1604
1605 /* flush refreshes after undo */
1606 static void commonkey_context_refresh (void)
1607 {
1608         /* check view type */
1609         switch (curarea->spacetype) {
1610                 /* 3d view - first one tested as most often used */
1611                 case SPACE_VIEW3D:
1612                 {
1613                         /* do refreshes */
1614                         DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0);
1615                         
1616                         allspace(REMAKEIPO, 0);
1617                         allqueue(REDRAWVIEW3D, 0);
1618                         allqueue(REDRAWMARKER, 0);
1619                 }
1620                         break;
1621                         
1622                 /* buttons window */
1623                 case SPACE_BUTS:
1624                 {
1625                         allspace(REMAKEIPO, 0);
1626                         allqueue(REDRAWVIEW3D, 0);
1627                         allqueue(REDRAWMARKER, 0);
1628                 }
1629                         break;
1630         }
1631 }
1632
1633 /* --- */
1634
1635 /* Build menu-string of available keying-sets (allocates memory for string)
1636  * NOTE: mode must not be longer than 64 chars
1637  */
1638 static char *build_keyingsets_menu (bKeyingContext *ksc, const char mode[48])
1639 {
1640         DynStr *pupds= BLI_dynstr_new();
1641         bKeyingSet *ks;
1642         char buf[64];
1643         char *str;
1644         int i, n;
1645         
1646         /* add title first */
1647         BLI_snprintf(buf, 64, "%s Key %%t|", mode);
1648         BLI_dynstr_append(pupds, buf);
1649         
1650         /* loop through keyingsets, adding them */
1651         for (ks=ksc->keyingsets, i=0, n=1; i < ksc->tot; ks++, i++, n++) {
1652                 /* check if keyingset can be used */
1653                 if (ks->flag == -1) {
1654                         /* optional separator? */
1655                         if (ks->include_cb) {
1656                                 if (ks->include_cb(ks, mode)) {
1657                                         BLI_snprintf( buf, 64, "%s%s", ks->name, ((n < ksc->tot)?"|":"") );
1658                                         BLI_dynstr_append(pupds, buf);
1659                                 }
1660                         }
1661                         else {
1662                                 BLI_snprintf( buf, 64, "%%l%s", ((n < ksc->tot)?"|":"") );
1663                                 BLI_dynstr_append(pupds, buf);
1664                         }
1665                 }
1666                 else if ( (ks->include_cb==NULL) || (ks->include_cb(ks, mode)) ) {
1667                         /* entry can be included */
1668                         BLI_dynstr_append(pupds, ks->name);
1669                         
1670                         /* check if special "shapekey" entry */
1671                         if (ks->flag == -3)
1672                                 BLI_snprintf( buf, 64, "%%x0%s", ((n < ksc->tot)?"|":"") );
1673                         else
1674                                 BLI_snprintf( buf, 64, "%%x%d%s", n, ((n < ksc->tot)?"|":"") );
1675                         BLI_dynstr_append(pupds, buf);
1676                 }
1677         }
1678         
1679         /* convert to normal MEM_malloc'd string */
1680         str= BLI_dynstr_get_cstring(pupds);
1681         BLI_dynstr_free(pupds);
1682         
1683         return str;
1684 }
1685
1686 /* Get the keying set that was chosen by the user from the menu */
1687 static bKeyingSet *get_keyingset_fromcontext (bKeyingContext *ksc, short index)
1688 {
1689         /* check if index is valid */
1690         if (ELEM(NULL, ksc, ksc->keyingsets))
1691                 return NULL;
1692         if ((index < 1) || (index > ksc->tot))
1693                 return NULL;
1694                 
1695         /* index starts from 1, and should directly correspond to keyingset in array */
1696         return (bKeyingSet *)(ksc->keyingsets + (index - 1));
1697 }
1698
1699 /* ---------------- Keyframe Management API -------------------- */
1700
1701 /* Display a menu for handling the insertion of keyframes based on the active view */
1702 // TODO: add back an option for repeating last keytype
1703 void common_modifykey (short mode)
1704 {
1705         ListBase dsources = {NULL, NULL};
1706         bKeyingContext *ksc= NULL;
1707         bCommonKeySrc *cks;
1708         bKeyingSet *ks = NULL;
1709         char *menustr, buf[64];
1710         short menu_nr;
1711         
1712         /* check if mode is valid */
1713         if (ELEM(mode, COMMONKEY_MODE_INSERT, COMMONKEY_MODE_DELETE)==0)
1714                 return;
1715         
1716         /* delegate to other functions or get keyingsets to use 
1717          *      - if the current area doesn't have its own handling, there will be data returned...
1718          */
1719         commonkey_context_get(curarea, mode, &dsources, &ksc);
1720         
1721         /* check that there is data to operate on */
1722         if (ELEM(NULL, dsources.first, ksc)) {
1723                 BLI_freelistN(&dsources);
1724                 return;
1725         }
1726         
1727         /* get menu and process it */
1728         if (mode == COMMONKEY_MODE_DELETE)
1729                 menustr= build_keyingsets_menu(ksc, "Delete");
1730         else
1731                 menustr= build_keyingsets_menu(ksc, "Insert");
1732         menu_nr= pupmenu(menustr);
1733         if (menustr) MEM_freeN(menustr);
1734         
1735         /* no item selected or shapekey entry? */
1736         if (menu_nr < 1) {
1737                 /* free temp sources */
1738                 BLI_freelistN(&dsources);
1739                 
1740                 /* check if insert new shapekey */
1741                 if ((menu_nr == 0) && (mode == COMMONKEY_MODE_INSERT))
1742                         insert_shapekey(OBACT);
1743                 else 
1744                         ksc->lastused= NULL;
1745                         
1746                 return;
1747         }
1748         else {
1749                 /* try to get keyingset */
1750                 ks= get_keyingset_fromcontext(ksc, menu_nr);
1751                 
1752                 if (ks == NULL) {
1753                         BLI_freelistN(&dsources);
1754                         return;
1755                 }
1756         }
1757         
1758         /* loop over each destination, applying the keying set */
1759         for (cks= dsources.first; cks; cks= cks->next) {
1760                 short success= 0;
1761                 
1762                 /* special hacks for 'available' option */
1763                 if (ks->flag == -2) {
1764                         IpoCurve *icu= NULL, *icn= NULL;
1765                         
1766                         /* get first IPO-curve */
1767                         if (cks->act && cks->actname) {
1768                                 bActionChannel *achan= get_action_channel(cks->act, cks->actname);
1769                                 
1770                                 // FIXME: what about constraint channels?
1771                                 if (achan && achan->ipo)
1772                                         icu= achan->ipo->curve.first; 
1773                         }
1774                         else if(cks->ipo)
1775                                 icu= cks->ipo->curve.first;
1776                                 
1777                         /* we get adrcodes directly from IPO curves (see method below...) */
1778                         for (; icu; icu= icn) {
1779                                 short flag;
1780                                 
1781                                 /* get next ipo-curve in case current is deleted */
1782                                 icn= icu->next;
1783                                 
1784                                 /* insert mode or delete mode */
1785                                 if (mode == COMMONKEY_MODE_DELETE) {
1786                                         /* local flags only add on to global flags */
1787                                         flag = 0;
1788                                         
1789                                         /* delete keyframe */
1790                                         success += deletekey(cks->id, ks->blocktype, cks->actname, cks->constname, icu->adrcode, flag);
1791                                 }
1792                                 else {
1793                                         /* local flags only add on to global flags */
1794                                         flag = ks->flag;
1795                                         if (IS_AUTOKEY_FLAG(AUTOMATKEY)) flag |= INSERTKEY_MATRIX;
1796                                         if (IS_AUTOKEY_FLAG(INSERTNEEDED)) flag |= INSERTKEY_NEEDED;
1797                                         // if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE;
1798                                         
1799                                         /* insert keyframe */
1800                                         success += insertkey(cks->id, ks->blocktype, cks->actname, cks->constname, icu->adrcode, flag);
1801                                 }
1802                         }
1803                 }
1804                 else {
1805                         int i;
1806                         
1807                         /* loop over channels available in keyingset */
1808                         for (i=0; i < ks->chan_num; i++) {
1809                                 short flag, adrcode;
1810                                 
1811                                 /* get adrcode
1812                                  *      - certain adrcodes (for MTEX channels need special offsets)     // BAD CRUFT!!!
1813                                  */
1814                                 adrcode= ks->adrcodes[i];
1815                                 if (ELEM3(ks->blocktype, ID_MA, ID_LA, ID_WO) && (ks->flag & COMMONKEY_ADDMAP)) {
1816                                         switch (adrcode) {
1817                                                 case MAP_OFS_X: case MAP_OFS_Y: case MAP_OFS_Z:
1818                                                 case MAP_SIZE_X: case MAP_SIZE_Y: case MAP_SIZE_Z:
1819                                                 case MAP_R: case MAP_G: case MAP_B: case MAP_DVAR:
1820                                                 case MAP_COLF: case MAP_NORF: case MAP_VARF: case MAP_DISP:
1821                                                         adrcode += cks->map;
1822                                                         break;
1823                                         }
1824                                 }
1825                                 
1826                                 /* insert mode or delete mode */
1827                                 if (mode == COMMONKEY_MODE_DELETE) {
1828                                         /* local flags only add on to global flags */
1829                                         flag = 0;
1830                                         //flag &= ~COMMONKEY_ADDMAP;
1831                                         
1832                                         /* delete keyframe */
1833                                         success += deletekey(cks->id, ks->blocktype, cks->actname, cks->constname, adrcode, flag);
1834                                 }
1835                                 else {
1836                                         /* local flags only add on to global flags */
1837                                         flag = ks->flag;
1838                                         if (IS_AUTOKEY_FLAG(AUTOMATKEY)) flag |= INSERTKEY_MATRIX;
1839                                         if (IS_AUTOKEY_FLAG(INSERTNEEDED)) flag |= INSERTKEY_NEEDED;
1840                                         // if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE;
1841                                         flag &= ~COMMONKEY_ADDMAP;
1842                                         
1843                                         /* insert keyframe */
1844                                         success += insertkey(cks->id, ks->blocktype, cks->actname, cks->constname, adrcode, flag);
1845                                 }
1846                         }
1847                 }
1848                 
1849                 /* special handling for some key-sources */
1850                 if (success) {
1851                         /* set pose recalc-paths flag */
1852                         if (cks->pchan) {
1853                                 Object *ob= (Object *)cks->id;
1854                                 bPoseChannel *pchan= cks->pchan;
1855                                 
1856                                 /* set flag to trigger path recalc */
1857                                 if (pchan->path) 
1858                                         ob->pose->flag |= POSE_RECALCPATHS;
1859                                         
1860                                 /* clear unkeyed flag (it doesn't matter if it's set or not) */
1861                                 if (pchan->bone)
1862                                         pchan->bone->flag &= ~BONE_UNKEYED;
1863                         }
1864                 }
1865         }
1866         
1867         /* apply post-keying flushes for this data sources */
1868         commonkey_context_finish(&dsources);
1869         ksc->lastused= ks;
1870         
1871         /* free temp data */
1872         BLI_freelistN(&dsources);
1873         
1874         /* undo pushes */
1875         if (mode == COMMONKEY_MODE_DELETE)
1876                 BLI_snprintf(buf, 64, "Delete %s Key", ks->name);
1877         else
1878                 BLI_snprintf(buf, 64, "Insert %s Key", ks->name);
1879         BIF_undo_push(buf);
1880         
1881         /* queue updates for contexts */
1882         commonkey_context_refresh();
1883 }
1884
1885 /* ---- */
1886
1887 /* used to insert keyframes from any view */
1888 void common_insertkey (void)
1889 {
1890         common_modifykey(COMMONKEY_MODE_INSERT);
1891 }
1892
1893 /* used to insert keyframes from any view */
1894 void common_deletekey (void)
1895 {
1896         common_modifykey(COMMONKEY_MODE_DELETE);
1897 }
1898
1899 /* ************************************************** */
1900 /* KEYFRAME DETECTION */
1901
1902 /* --------------- API/Per-Datablock Handling ------------------- */
1903
1904 /* Checks whether an IPO-block has a keyframe for a given frame 
1905  * Since we're only concerned whether a keyframe exists, we can simply loop until a match is found...
1906  */
1907 short ipo_frame_has_keyframe (Ipo *ipo, float frame, short filter)
1908 {
1909         IpoCurve *icu;
1910         
1911         /* can only find if there is data */
1912         if (ipo == NULL)
1913                 return 0;
1914                 
1915         /* if only check non-muted, check if muted */
1916         if ((filter & ANIMFILTER_MUTED) || (ipo->muteipo))
1917                 return 0;
1918         
1919         /* loop over IPO-curves, using binary-search to try to find matches 
1920          *      - this assumes that keyframes are only beztriples
1921          */
1922         for (icu= ipo->curve.first; icu; icu= icu->next) {
1923                 /* we either include all regardless of muting, or only non-muted  */
1924                 if ((filter & ANIMFILTER_MUTED) || (icu->flag & IPO_MUTE)==0) {
1925                         short replace = -1;
1926                         int i = binarysearch_bezt_index(icu->bezt, frame, icu->totvert, &replace);
1927                         
1928                         /* binarysearch_bezt_index will set replace to be 0 or 1
1929                          *      - obviously, 1 represents a match
1930                          */
1931                         if (replace) {                  
1932                                 /* sanity check: 'i' may in rare cases exceed arraylen */
1933                                 if ((i >= 0) && (i < icu->totvert))
1934                                         return 1;
1935                         }
1936                 }
1937         }
1938         
1939         /* nothing found */
1940         return 0;
1941 }
1942
1943 /* Checks whether an action-block has a keyframe for a given frame 
1944  * Since we're only concerned whether a keyframe exists, we can simply loop until a match is found...
1945  */
1946 short action_frame_has_keyframe (bAction *act, float frame, short filter)
1947 {
1948         bActionChannel *achan;
1949         
1950         /* error checking */
1951         if (act == NULL)
1952                 return 0;
1953                 
1954         /* check thorugh action-channels for match */
1955         for (achan= act->chanbase.first; achan; achan= achan->next) {
1956                 /* we either include all regardless of muting, or only non-muted 
1957                  *      - here we include 'hidden' channels in the muted definition
1958                  */
1959                 if ((filter & ANIMFILTER_MUTED) || (achan->flag & ACHAN_HIDDEN)==0) {
1960                         if (ipo_frame_has_keyframe(achan->ipo, frame, filter))
1961                                 return 1;
1962                 }
1963         }
1964         
1965         /* nothing found */
1966         return 0;
1967 }
1968
1969 /* Checks whether an Object has a keyframe for a given frame */
1970 short object_frame_has_keyframe (Object *ob, float frame, short filter)
1971 {
1972         /* error checking */
1973         if (ob == NULL)
1974                 return 0;
1975         
1976         /* check for an action - actions take priority over normal IPO's */
1977         if (ob->action) {
1978                 float aframe;
1979                 
1980                 /* apply nla-action scaling if needed */
1981                 if ((ob->nlaflag & OB_NLA_OVERRIDE) && (ob->nlastrips.first))
1982                         aframe= get_action_frame(ob, frame);
1983                 else
1984                         aframe= frame;
1985                 
1986                 /* priority check here goes to pose-channel checks (for armatures) */
1987                 if ((ob->pose) && (ob->flag & OB_POSEMODE)) {
1988                         /* only relevant check here is to only show active... */
1989                         if (filter & ANIMFILTER_ACTIVE) {
1990                                 bPoseChannel *pchan= get_active_posechannel(ob);
1991                                 bActionChannel *achan= (pchan) ? get_action_channel(ob->action, pchan->name) : NULL;
1992                                 
1993                                 /* since we're only interested in whether the selected one has any keyframes... */
1994                                 return (achan && ipo_frame_has_keyframe(achan->ipo, aframe, filter));
1995                         }
1996                 }
1997                 
1998                 /* for everything else, just use the standard test (only return if success) */
1999                 if (action_frame_has_keyframe(ob->action, aframe, filter))
2000                         return 1;
2001         }
2002         else if (ob->ipo) {
2003                 /* only return if success */
2004                 if (ipo_frame_has_keyframe(ob->ipo, frame, filter))
2005                         return 1;
2006         }
2007         
2008         /* try shapekey keyframes (if available, and allowed by filter) */
2009         if ( !(filter & ANIMFILTER_LOCAL) && !(filter & ANIMFILTER_NOSKEY) ) {
2010                 Key *key= ob_get_key(ob);
2011                 
2012                 /* shapekeys can have keyframes ('Relative Shape Keys') 
2013                  * or depend on time (old 'Absolute Shape Keys') 
2014                  */
2015                  
2016                         /* 1. test for relative (with keyframes) */
2017                 if (id_frame_has_keyframe((ID *)key, frame, filter))
2018                         return 1;
2019                         
2020                         /* 2. test for time */
2021                 // TODO... yet to be implemented (this feature may evolve before then anyway)
2022         }
2023         
2024         /* try materials */
2025         if ( !(filter & ANIMFILTER_LOCAL) && !(filter & ANIMFILTER_NOMAT) ) {
2026                 /* if only active, then we can skip a lot of looping */
2027                 if (filter & ANIMFILTER_ACTIVE) {
2028                         Material *ma= give_current_material(ob, (ob->actcol + 1));
2029                         
2030                         /* we only retrieve the active material... */
2031                         if (id_frame_has_keyframe((ID *)ma, frame, filter))
2032                                 return 1;
2033                 }
2034                 else {
2035                         int a;
2036                         
2037                         /* loop over materials */
2038                         for (a=0; a<ob->totcol; a++) {
2039                                 Material *ma= give_current_material(ob, a+1);
2040                                 
2041                                 if (id_frame_has_keyframe((ID *)ma, frame, filter))
2042                                         return 1;
2043                         }
2044                 }
2045         }
2046         
2047         /* nothing found */
2048         return 0;
2049 }
2050
2051 /* --------------- API ------------------- */
2052
2053 /* Checks whether a keyframe exists for the given ID-block one the given frame */
2054 short id_frame_has_keyframe (ID *id, float frame, short filter)
2055 {
2056         /* error checking */
2057         if (id == NULL)
2058                 return 0;
2059         
2060         /* check for a valid id-type */
2061         switch (GS(id->name)) {
2062                         /* animation data-types */
2063                 case ID_IP:     /* ipo */
2064                         return ipo_frame_has_keyframe((Ipo *)id, frame, filter);
2065                 case ID_AC: /* action */
2066                         return action_frame_has_keyframe((bAction *)id, frame, filter);
2067                         
2068                 case ID_OB: /* object */
2069                         return object_frame_has_keyframe((Object *)id, frame, filter);
2070                         
2071                 case ID_MA: /* material */
2072                 {
2073                         Material *ma= (Material *)id;
2074                         
2075                         /* currently, material's only have an ipo-block */
2076                         return ipo_frame_has_keyframe(ma->ipo, frame, filter);
2077                 }
2078                         break;
2079                         
2080                 case ID_KE: /* shapekey */
2081                 {
2082                         Key *key= (Key *)id;
2083                         
2084                         /* currently, shapekey's only have an ipo-block */
2085                         return ipo_frame_has_keyframe(key->ipo, frame, filter);
2086                 }
2087                         break;
2088         }
2089         
2090         /* no keyframe found */
2091         return 0;
2092 }
2093
2094 /* ************************************************** */