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