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