2 * $Id: keyframing.c 17745 2008-12-08 09:16:09Z aligorith $
4 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
20 * The Original Code is Copyright (C) 2008, Blender Foundation
21 * This is a new part of Blender (with some old code)
23 * Contributor(s): Joshua Leung
25 * ***** END GPL LICENSE BLOCK *****
41 #include "MEM_guardedalloc.h"
43 #include "BLI_arithb.h"
44 #include "BLI_blenlib.h"
45 #include "BLI_dynstr.h"
47 #include "DNA_listBase.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"
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"
81 #include "BKE_object.h"
82 #include "BKE_particle.h"
83 #include "BKE_material.h"
84 #include "BKE_modifier.h"
86 #include "ED_anim_api.h"
87 #include "ED_keyframing.h"
88 #include "ED_keyframes_edit.h"
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"
102 #include "BSE_editipo.h"
103 #include "BSE_node.h"
104 #include "BSE_time.h"
105 #include "BSE_view.h"
109 #include "PIL_time.h" /* sleep */
110 #include "mydevice.h"
111 #endif // XXX resolve these old dependencies!
115 /* ************************************************** */
116 /* LOCAL TYPES AND DEFINES */
118 /* ----------- Common KeyData Sources ------------ */
120 /* temporary struct to gather data combos to keyframe */
121 typedef struct bCommonKeySrc {
122 struct bCommonKeySrc *next, *prev;
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 */
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) */
133 /* pose-level settings */
134 bPoseChannel *pchan; /* pose channel */
136 /* buttons-window settings */
137 int map; /* offset to apply to certain adrcodes */
140 /* -------------- Keying Sets ------------------- */
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... */
147 short index; /* index of current channel to resume from */
148 short tot; /* index after which we start returning from some special collection */
151 /* flags to look out for in keyingset channels... */
152 #define KAG_CHAN_EXTEND (-1)
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)
161 short (*include_cb)(struct bKeyingSet *, const char *);
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 */
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) */
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 */
179 /* ************************************************** */
180 /* IPO DATA VERIFICATION */
181 // XXX these will need to be modified for use with RNA-IPO...
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
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)
195 /* lib-linked data is not appropriate here */
196 if ((from==NULL) || (from->lib))
199 /* first check action ipos */
200 if (actname && actname[0]) {
201 Object *ob= (Object *)from;
202 bActionChannel *achan;
204 if (GS(from->name)!=ID_OB) {
205 printf("called ipo system for action with wrong base pointer\n");
209 if ((ob->action==NULL) && (add))
210 ob->action= add_empty_action("Action");
213 achan= verify_action_channel(ob->action, actname);
215 achan= get_action_channel(ob->action, actname);
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);
222 /* constraint exception */
223 if (blocktype==ID_CO) {
224 bConstraintChannel *conchan;
227 conchan= verify_constraint_channel(&achan->constraintChannels, constname);
229 conchan= get_constraint_channel(&achan->constraintChannels, constname);
232 if ((conchan->ipo==NULL) && (add))
233 conchan->ipo= add_ipo("CoIpo", ID_CO);
238 if ((achan->ipo==NULL) && (add))
239 achan->ipo= add_ipo("ActIpo", blocktype);
245 switch (GS(from->name)) {
248 Object *ob= (Object *)from;
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);
257 for (con= pchan->constraints.first; con; con= con->next) {
258 if (strcmp(con->name, constname)==0)
263 if ((con->ipo==NULL) && (add))
264 con->ipo= add_ipo("CoIpo", ID_CO);
268 else { /* the actionchannel */
269 bConstraintChannel *conchan;
272 conchan= verify_constraint_channel(&ob->constraintChannels, constname);
274 conchan= get_constraint_channel(&ob->constraintChannels, constname);
277 if ((conchan->ipo==NULL) && (add))
278 conchan->ipo= add_ipo("CoIpo", ID_CO);
283 else if (blocktype==ID_OB) {
284 if ((ob->ipo==NULL) && (add))
285 ob->ipo= add_ipo("ObIpo", ID_OB);
288 else if (blocktype==ID_KE) {
289 Key *key= ob_get_key((Object *)from);
292 if ((key->ipo==NULL) && (add))
293 key->ipo= add_ipo("KeyIpo", ID_KE);
298 else if (blocktype== ID_FLUIDSIM) {
299 Object *ob= (Object *)from;
301 FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
303 FluidsimSettings *fss= fluidmd->fss;
305 if ((fss->ipo==NULL) && (add))
306 fss->ipo= add_ipo("FluidsimIpo", ID_FLUIDSIM);
310 else if(blocktype== ID_PA) {
311 Object *ob= (Object *)from;
312 ParticleSystem *psys= psys_get_current(ob);
315 if ((psys->part->ipo==NULL) && (add))
316 psys->part->ipo= add_ipo("ParticleIpo", ID_PA);
317 return psys->part->ipo;
325 Material *ma= (Material *)from;
327 if ((ma->ipo==NULL) && (add))
328 ma->ipo= add_ipo("MatIpo", ID_MA);
334 Tex *tex= (Tex *)from;
336 if ((tex->ipo==NULL) && (add))
337 tex->ipo= add_ipo("TexIpo", ID_TE);
343 Sequence *seq= (Sequence *)from; /* note, sequence is mimicing Id */
345 if ((seq->ipo==NULL) && (add))
346 seq->ipo= add_ipo("SeqIpo", ID_SEQ);
347 //update_seq_ipo_rect(seq); // XXX
353 Curve *cu= (Curve *)from;
355 if ((cu->ipo==NULL) && (add))
356 cu->ipo= add_ipo("CuIpo", ID_CU);
362 World *wo= (World *)from;
364 if ((wo->ipo==NULL) && (add))
365 wo->ipo= add_ipo("WoIpo", ID_WO);
371 Lamp *la= (Lamp *)from;
373 if ((la->ipo==NULL) && (add))
374 la->ipo= add_ipo("LaIpo", ID_LA);
380 Camera *ca= (Camera *)from;
382 if ((ca->ipo==NULL) && (add))
383 ca->ipo= add_ipo("CaIpo", ID_CA);
390 bSound *snd= (bSound *)from;
392 if ((snd->ipo==NULL) && (add))
393 snd->ipo= add_ipo("SndIpo", ID_SO);
395 #endif // depreceated
404 /* Returns and creates
405 * Make sure functions check for NULL or they will crash!
407 IpoCurve *verify_ipocurve(ID *from, short blocktype, char actname[], char constname[], char bonename[], int adrcode, short add)
412 /* return 0 if lib */
413 /* creates ipo too (if add) */
414 ipo= verify_ipo(from, blocktype, actname, constname, bonename, add);
416 if ((ipo) && (ipo->id.lib==NULL) && (from->lib==NULL)) {
417 /* try to find matching curve */
418 icu= find_ipocurve(ipo, adrcode);
420 /* make a new one if none found (and can add) */
421 if ((icu==NULL) && (add)) {
422 icu= MEM_callocN(sizeof(IpoCurve), "ipocurve");
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 */
429 icu->blocktype= blocktype;
430 icu->adrcode= adrcode;
434 /* default curve interpolation - from userpref */
437 /* add curve to IPO-block */
438 BLI_addtail(&ipo->curve, icu);
440 /* special type-dependent stuff */
441 switch (GS(from->name)) {
443 //Sequence *seq= (Sequence *)from;
445 //update_seq_icu_rects(seq); // XXX
452 /* return ipo-curve */
456 /* ************************************************** */
457 /* KEYFRAME INSERTION */
459 /* -------------- BezTriple Insertion -------------------- */
461 /* threshold for inserting keyframes - threshold here should be good enough for now, but should become userpref */
462 #define BEZT_INSERT_THRESH 0.00001
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)
467 static int binarysearch_bezt_index (BezTriple array[], float frame, int arraylen, short *replace)
469 int start=0, end=arraylen;
470 int loopbreaker= 0, maxloop= arraylen * 2;
472 /* initialise replace-flag first */
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
479 if ((arraylen <= 0) || (array == NULL)) {
480 printf("Warning: binarysearch_bezt_index() encountered invalid array \n");
484 /* check whether to add before/after/on */
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)) {
493 else if (frame < framenum)
496 /* 'Last' Keyframe */
497 framenum= array[(arraylen-1)].vec[1][0];
498 if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) {
500 return (arraylen - 1);
502 else if (frame > framenum)
507 /* most of the time, this loop is just to find where to put it
508 * 'loopbreaker' is just here to prevent infinite loops
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];
515 /* check if exactly equal to midpoint */
516 if (IS_EQT(frame, midfra, BEZT_INSERT_THRESH)) {
521 /* repeat in upper/lower half */
524 else if (frame < midfra)
528 /* print error if loop-limit exceeded */
529 if (loopbreaker == (maxloop-1)) {
530 printf("Error: binarysearch_bezt_index() was taking too long \n");
532 // include debug info
533 printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen);
536 /* not found, so return where to place it */
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.
544 * NOTE: any recalculate of the IPO-Curve that needs to be done will need to
545 * be done by the caller.
547 int insert_bezt_icu (IpoCurve *icu, BezTriple *bezt)
554 i = binarysearch_bezt_index(icu->bezt, bezt->vec[1][0], icu->totvert, &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;
564 newb= MEM_callocN((icu->totvert+1)*sizeof(BezTriple), "beztriple");
566 /* add the beztriples that should occur before the beztriple to be pasted (originally in ei->icu) */
568 memcpy(newb, icu->bezt, i*sizeof(BezTriple));
570 /* add beztriple to paste at index i */
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));
577 /* replace (+ free) old with new */
578 MEM_freeN(icu->bezt);
585 icu->bezt= MEM_callocN(sizeof(BezTriple), "beztriple");
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
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
601 * 'fast' - is only for the python API where importing BVH's would take an extreamly long time.
603 void insert_vert_icu (IpoCurve *icu, float x, float y, short fast)
608 /* set all three points, for nicer start position */
609 memset(&beztr, 0, sizeof(BezTriple));
617 beztr.f1= beztr.f2= beztr.f3= SELECT;
618 beztr.h1= beztr.h2= HD_AUTO;
620 /* add temp beztriple to keyframes */
621 a= insert_bezt_icu(icu, &beztr);
623 /* what if 'a' is a negative index?
624 * for now, just exit to prevent any segfaults
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)
632 if (!fast) calchandles_ipocurve(icu);
634 /* set handletype and interpolation */
635 if (icu->totvert > 2) {
636 BezTriple *bezt= (icu->bezt + a);
638 /* set handles (autohandles by default) */
641 if (a > 0) h1= (bezt-1)->h2;
642 if (a < icu->totvert-1) h2= (bezt+1)->h1;
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;
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)
659 if (!fast) calchandles_ipocurve(icu);
662 BezTriple *bezt= (icu->bezt + a);
664 /* set interpolation directly from ipo-curve */
670 /* ------------------- Get Data ------------------------ */
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)
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);
683 if (ELEM3(icu->adrcode, AC_EUL_X, AC_EUL_Y, AC_EUL_Z))
684 *vartype= IPO_FLOAT_DEGR;
687 return get_pchan_ipo_poin(pchan, icu->adrcode);
692 case ID_CO: /* constraint */
693 if ((GS(id->name)==ID_OB) && (constname && constname[0])) {
694 Object *ob= (Object *)id;
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) {
702 return &con->enforce;
707 bPoseChannel *pchan= get_pose_channel(ob->pose, actname);
710 for (con= pchan->constraints.first; con; con= con->next) {
711 if (strcmp(constname, con->name)==0) {
713 return &con->enforce;
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 :/
725 if ((GS(id->name)==ID_OB) && (icu->adrcode==OB_LAY)) {
726 Object *ob= (Object *)id;
727 static int layer = 0;
729 /* init layer to be the object's layer var, then remove local view from it */
732 *vartype= IPO_INT_BIT;
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
738 return (void *)(&layer);
740 /* no break here for other ob channel-types - as they can be done normally */
742 default: /* normal data-source */
743 return get_ipo_poin(id, icu, vartype);
751 /* -------------- 'Smarter' Keyframing Functions -------------------- */
752 /* return codes for new_key_needed */
754 KEYNEEDED_DONTADD = 0,
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
766 static short new_key_needed (IpoCurve *icu, float cFrame, float nValue)
768 BezTriple *bezt=NULL, *prev=NULL;
770 float valA = 0.0f, valB = 0.0f;
772 /* safety checking */
773 if (icu == NULL) return KEYNEEDED_JUSTADD;
774 totCount= icu->totvert;
775 if (totCount == 0) return KEYNEEDED_JUSTADD;
777 /* loop through checking if any are the same */
779 for (i=0; i<totCount; i++) {
780 float prevPosi=0.0f, prevVal=0.0f;
781 float beztPosi=0.0f, beztVal=0.0f;
783 /* get current time+value */
784 beztPosi= bezt->vec[1][0];
785 beztVal= bezt->vec[1][1];
788 /* there is a keyframe before the one currently being examined */
790 /* get previous time+value */
791 prevPosi= prev->vec[1][0];
792 prevVal= prev->vec[1][1];
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;
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;
808 /* get real value of curve at that point */
809 realVal= eval_icu(icu, cFrame);
811 /* compare whether it's the same as proposed */
812 if (IS_EQ(realVal, nValue))
813 return KEYNEEDED_DONTADD;
815 return KEYNEEDED_JUSTADD;
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.
825 if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal))
826 return KEYNEEDED_DELNEXT;
828 return KEYNEEDED_JUSTADD;
832 /* just add a keyframe if there's only one keyframe
833 * and the new one occurs before the exisiting one does.
835 if ((cFrame < beztPosi) && (totCount==1))
836 return KEYNEEDED_JUSTADD;
839 /* continue. frame to do not yet passed (or other conditions not met) */
840 if (i < (totCount-1)) {
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.
855 bezt= (icu->bezt + (icu->totvert - 1));
856 valA= bezt->vec[1][1];
859 valB= prev->vec[1][1];
861 valB= bezt->vec[1][1] + 1.0f;
863 if (IS_EQ(valA, nValue) && IS_EQ(valA, valB))
864 return KEYNEEDED_DELPREV;
866 return KEYNEEDED_JUSTADD;
869 /* ------------------ 'Visual' Keyframing Functions ------------------ */
871 /* internal status codes for visualkey_can_use */
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
884 static short visualkey_can_use (ID *id, int blocktype, char *actname, char *constname, int adrcode)
887 bConstraint *con= NULL;
888 short searchtype= VISUALKEY_NONE;
891 if ((id == NULL) || (GS(id->name)!=ID_OB) || !(ELEM(blocktype, ID_OB, ID_PO)))
894 /* get first constraint and determine type of keyframe constraints to check for*/
897 if (blocktype == ID_OB) {
898 con= ob->constraints.first;
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;
905 else if (blocktype == ID_PO) {
906 bPoseChannel *pchan= get_pose_channel(ob->pose, actname);
907 con= pchan->constraints.first;
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;
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;
922 /* some constraints may alter these transforms */
924 /* multi-transform constraints */
925 case CONSTRAINT_TYPE_CHILDOF:
927 case CONSTRAINT_TYPE_TRANSFORM:
929 case CONSTRAINT_TYPE_FOLLOWPATH:
931 case CONSTRAINT_TYPE_KINEMATIC:
934 /* single-transform constraits */
935 case CONSTRAINT_TYPE_TRACKTO:
936 if (searchtype==VISUALKEY_ROT) return 1;
938 case CONSTRAINT_TYPE_ROTLIMIT:
939 if (searchtype==VISUALKEY_ROT) return 1;
941 case CONSTRAINT_TYPE_LOCLIMIT:
942 if (searchtype==VISUALKEY_LOC) return 1;
944 case CONSTRAINT_TYPE_ROTLIKE:
945 if (searchtype==VISUALKEY_ROT) return 1;
947 case CONSTRAINT_TYPE_DISTLIMIT:
948 if (searchtype==VISUALKEY_LOC) return 1;
950 case CONSTRAINT_TYPE_LOCLIKE:
951 if (searchtype==VISUALKEY_LOC) return 1;
953 case CONSTRAINT_TYPE_LOCKTRACK:
954 if (searchtype==VISUALKEY_ROT) return 1;
956 case CONSTRAINT_TYPE_MINMAX:
957 if (searchtype==VISUALKEY_LOC) return 1;
966 /* when some condition is met, this function returns, so here it can be 0 */
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.
974 static float visualkey_get_value (ID *id, int blocktype, char *actname, char *constname, int adrcode, IpoCurve *icu)
980 /* validate situtation */
981 if ((id==NULL) || (GS(id->name)!=ID_OB) || (ELEM(blocktype, ID_OB, ID_PO)==0))
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
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;
998 return ob->obmat[3][index];
1000 else if (ELEM3(adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) {
1003 /* assumes that OB_ROT_Z > OB_ROT_Y > OB_ROT_X */
1004 index= adrcode - OB_ROT_X;
1006 Mat4ToEul(ob->obmat, eul);
1007 return eul[index]*(5.72958f);
1011 else if (blocktype == ID_PO) {
1012 bPoseChannel *pchan;
1015 /* get data to use */
1016 pchan= get_pose_channel(ob->pose, actname);
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.
1023 Mat4CpyMat4(tmat, pchan->pose_mat);
1024 constraint_mat_convertspace(ob, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
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;
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];
1037 else if (ELEM4(adrcode, AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z)) {
1038 float trimat[3][3], quat[4];
1040 /* assumes that AC_QUAT_Z > AC_QUAT_Y > AC_QUAT_X > AC_QUAT_W */
1041 index= adrcode - AC_QUAT_W;
1043 Mat3CpyMat4(trimat, tmat);
1044 Mat3ToQuat_is_ok(trimat, quat);
1050 /* as the function hasn't returned yet, try reading from poin */
1051 poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype);
1053 return read_ipo_poin(poin, vartype);
1058 /* ------------------------- Insert Key API ------------------------- */
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.
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.
1068 short insertkey (ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag)
1073 icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode, 1);
1075 /* only continue if we have an ipo-curve to add keyframe to */
1077 float cfra =1.0f;//= frame_to_float(CFRA);
1080 /* apply special time tweaking */
1081 if (GS(id->name) == ID_OB) {
1082 Object *ob= (Object *)id;
1084 /* apply NLA-scaling (if applicable) */
1085 if (actname && actname[0])
1086 cfra= get_action_frame(ob, cfra);
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;
1095 /* obtain value to give keyframe */
1096 if ( (flag & INSERTKEY_MATRIX) &&
1097 (visualkey_can_use(id, blocktype, actname, constname, adrcode)) )
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.
1103 curval= visualkey_get_value(id, blocktype, actname, constname, adrcode, icu);
1109 /* get pointer to data to read from */
1110 poin = get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype);
1112 printf("Insert Key: No pointer to variable obtained \n");
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)
1119 curval= read_ipo_poin(poin, vartype);
1122 /* only insert keyframes where they are needed */
1123 if (flag & INSERTKEY_NEEDED) {
1126 /* check whether this curve really needs a new keyframe */
1127 insert_mode= new_key_needed(icu, cfra, curval);
1129 /* insert new keyframe at current frame */
1131 insert_vert_icu(icu, cfra, curval, (flag & INSERTKEY_FAST));
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);
1138 case KEYNEEDED_DELNEXT:
1139 delete_icu_key(icu, 1, 1);
1143 /* only return success if keyframe added */
1148 /* just insert keyframe */
1149 insert_vert_icu(icu, cfra, curval, (flag & INSERTKEY_FAST));
1151 /* return success */
1156 /* return failure */
1161 /* ************************************************** */
1162 /* KEYFRAME DELETION */
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.
1168 * The flag argument is used for special settings that alter the behaviour of
1169 * the keyframe deletion. These include the quick refresh options.
1171 short deletekey (ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag)
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
1180 ipo= verify_ipo(id, blocktype, actname, constname, NULL, 0);
1181 icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode, 0);
1183 /* only continue if we have an ipo-curve to remove keyframes from */
1185 float cfra = 1.0f;//frame_to_float(CFRA);
1189 /* apply special time tweaking */
1190 if (GS(id->name) == ID_OB) {
1191 Object *ob= (Object *)id;
1193 /* apply NLA-scaling (if applicable) */
1194 if (actname && actname[0])
1195 cfra= get_action_frame(ob, cfra);
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;
1204 /* try to find index of beztriple to get rid of */
1205 i = binarysearch_bezt_index(icu->bezt, cfra, icu->totvert, &found);
1207 /* delete the key at the index (will sanity check + do recalc afterwards ) */
1208 delete_icu_key(icu, i, 1);
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);
1216 /* return success */
1221 /* return failure */
1225 /* ************************************************** */
1226 /* COMMON KEYFRAME MANAGEMENT (common_insertkey/deletekey) */
1228 /* mode for common_modifykey */
1230 COMMONKEY_MODE_INSERT = 0,
1231 COMMONKEY_MODE_DELETE,
1232 } eCommonModifyKey_Modes;
1234 /* --------- KeyingSet Adrcode Getters ------------ */
1236 /* initialise a channel-getter storage */
1237 static void ks_adrcodegetter_init (bKS_AdrcodeGetter *kag, bKeyingSet *ks, bCommonKeySrc *cks)
1239 /* error checking */
1243 if (ELEM(NULL, ks, cks)) {
1244 /* set invalid settings that won't cause harm */
1251 /* store settings */
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)
1259 kag->tot= ks->chan_num;
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
1266 static short ks_getnextadrcode_default (bKS_AdrcodeGetter *kag)
1268 bKeyingSet *ks= (kag)? kag->ks : NULL;
1270 /* error checking */
1271 if (ELEM(NULL, kag, ks)) return 0;
1272 if (kag->tot <= 0) return 0;
1275 if ((kag->index < 0) || (kag->index >= kag->tot)) return 0;
1277 /* return the adrcode stored at index then */
1278 return ks->adrcodes[kag->index];
1281 /* add map flag (for MTex channels, as certain ones need special offset) */
1282 static short ks_getnextadrcode_addmap (bKS_AdrcodeGetter *kag)
1284 short adrcode= ks_getnextadrcode_default(kag);
1286 /* if there was an adrcode returned, assume that kag stuff is set ok */
1288 bCommonKeySrc *cks= kag->cks;
1289 bKeyingSet *ks= kag->ks;
1291 if (ELEM3(ks->blocktype, ID_MA, ID_LA, ID_WO)) {
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;
1303 /* adrcode must be returned! */
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
1311 static short ks_getnextadrcode_pchanrot (bKS_AdrcodeGetter *kag)
1313 /* hardcoded adrcode channels used here only
1314 * - length is keyed-channels + 1 (last item must be 0 to escape)
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};
1319 /* useful variables */
1320 bKeyingSet *ks= (kag)? kag->ks : NULL;
1321 bCommonKeySrc *cks= (kag) ? kag->cks : NULL;
1322 short index, adrcode;
1324 /* error checking */
1325 if (ELEM3(NULL, kag, ks, cks)) return 0;
1326 if (ks->chan_num <= 0) return 0;
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!)
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];
1341 if (adrcode != KAG_CHAN_EXTEND)
1344 kag->tot= kag->index;
1347 /* based on current rotation-mode
1348 * - index can be at most 5, if we are to prevent segfaults
1350 index= kag->index - kag->tot;
1351 if ((index < 0) || (index > 5))
1354 if (cks->pchan && cks->pchan->rotmode)
1355 return eul_adrcodes[index];
1357 return quat_adrcodes[index];
1360 /* ------------- KeyingSet Defines ------------ */
1361 /* Note: these must all be named with the defks_* prefix, otherwise the template macro will not work! */
1363 /* macro for defining keyingset contexts */
1364 #define KSC_TEMPLATE(ctx_name) {&defks_##ctx_name[0], NULL, sizeof(defks_##ctx_name)/sizeof(bKeyingSet)}
1368 /* check if option not available for deleting keys */
1369 static short incl_non_del_keys (bKeyingSet *ks, const char mode[])
1371 /* as optimisation, assume that it is sufficient to check only first letter
1372 * of mode (int comparison should be faster than string!)
1374 //if (strcmp(mode, "Delete")==0)
1375 if (mode && mode[0]=='D')
1381 /* Object KeyingSets ------ */
1383 /* check if include shapekey entry */
1384 static short incl_v3d_ob_shapekey (bKeyingSet *ks, const char mode[])
1386 //Object *ob= (G.obedit)? (G.obedit) : (OBACT); // XXX
1388 char *newname= NULL;
1393 /* not available for delete mode */
1394 if (strcmp(mode, "Delete")==0)
1397 /* check if is geom object that can get shapekeys */
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;
1410 /* if ks is shapekey entry (this could be callled for separator before too!) */
1412 sprintf(ks->name, newname);
1414 /* if it gets here, it's ok */
1418 /* array for object keyingset defines */
1419 bKeyingSet defks_v3d_object[] =
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}},
1426 {NULL, "%l", 0, -1, 0, {0}}, // separator
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}},
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}},
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}},
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}},
1445 {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator
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}},
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}},
1454 {NULL, "%l", 0, -1, 0, {0}}, // separator
1456 {NULL, "Layer", ID_OB, 0, 1, {OB_LAY}}, // icky option...
1457 {NULL, "Available", ID_OB, -2, 0, {0}},
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}}
1463 /* PoseChannel KeyingSets ------ */
1465 /* array for posechannel keyingset defines */
1466 bKeyingSet defks_v3d_pchan[] =
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}},
1473 {NULL, "%l", 0, -1, 0, {0}}, // separator
1475 {NULL, "LocRot", ID_PO, COMMONKEY_PCHANROT, 4,
1476 {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,
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}},
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,
1487 {NULL, "RotScale", ID_PO, 0, 4,
1488 {AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z,
1491 {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator
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}},
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}},
1499 {NULL, "%l", 0, -1, 0, {0}}, // separator
1501 {NULL, "Available", ID_PO, -2, 0, {0}}
1504 /* Material KeyingSets ------ */
1506 /* array for material keyingset defines */
1507 bKeyingSet defks_buts_shading_mat[] =
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
1515 {NULL, "%l", 0, -1, 0, {0}}, // separator
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}},
1524 {NULL, "All Mirror", ID_MA, 0, 5,
1525 {MA_RAYM,MA_FRESMIR,MA_FRESMIRI,
1526 MA_FRESTRA,MA_FRESTRAI}},
1528 {NULL, "%l", 0, -1, 0, {0}}, // separator
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}},
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}},
1539 {NULL, "%l", 0, -1, 0, {0}}, // separator
1541 {NULL, "Available", ID_MA, -2, 0, {0}}
1544 /* World KeyingSets ------ */
1546 /* array for world keyingset defines */
1547 bKeyingSet defks_buts_shading_wo[] =
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}},
1553 {NULL, "%l", 0, -1, 0, {0}}, // separator
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}},
1559 {NULL, "%l", 0, -1, 0, {0}}, // separator
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}},
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}},
1570 {NULL, "%l", 0, -1, 0, {0}}, // separator
1572 {NULL, "Available", ID_WO, -2, 0, {0}}
1575 /* Lamp KeyingSets ------ */
1577 /* array for lamp keyingset defines */
1578 bKeyingSet defks_buts_shading_la[] =
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}},
1585 {NULL, "%l", 0, -1, 0, {0}}, // separator
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}},
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}},
1596 {NULL, "%l", 0, -1, 0, {0}}, // separator
1598 {NULL, "Available", ID_LA, -2, 0, {0}}
1601 /* Texture KeyingSets ------ */
1603 /* array for texture keyingset defines */
1604 bKeyingSet defks_buts_shading_tex[] =
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}},
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}},
1615 {NULL, "Stucci", ID_TE, 0, 5,
1616 {TE_NSIZE,TE_NTYPE,TE_TURB,
1617 TE_MG_TYP,TE_N_BAS1}},
1619 {NULL, "Wood", ID_TE, 0, 6,
1620 {TE_NSIZE,TE_NTYPE,TE_TURB,
1621 TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}},
1623 {NULL, "Magic", ID_TE, 0, 2, {TE_NDEPTH,TE_TURB}},
1625 {NULL, "Blend", ID_TE, 0, 1, {TE_MG_TYP}},
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}},
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,
1636 {NULL, "Distorted Noise", ID_TE, 0, 4,
1637 {TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN,TE_DISTA}},
1639 {NULL, "Color Filter", ID_TE, 0, 5,
1640 {TE_COL_R,TE_COL_G,TE_COL_B,TE_BRIGHT,TE_CONTRA}},
1642 {NULL, "%l", 0, -1, 0, {0}}, // separator
1644 {NULL, "Available", ID_TE, -2, 0, {0}}
1647 /* Object Buttons KeyingSets ------ */
1649 /* check if include particles entry */
1650 static short incl_buts_ob (bKeyingSet *ks, const char mode[])
1652 //Object *ob= OBACT; // xxx
1654 /* only if object is mesh type */
1656 if(ob==NULL) return 0;
1657 return (ob->type == OB_MESH);
1660 /* array for texture keyingset defines */
1661 bKeyingSet defks_buts_object[] =
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}},
1668 {NULL, "%l", 0, -1, 0, {0}}, // separator
1670 {NULL, "Force Strength", ID_OB, 0, 1, {OB_PD_FSTR}},
1671 {NULL, "Force Falloff", ID_OB, 0, 1, {OB_PD_FFALL}},
1673 {NULL, "%l", 0, -1, 0, {0}}, // separator
1675 {NULL, "Available", ID_OB, -2, 0, {0}} // this will include ob-transforms too!
1678 /* Camera Buttons KeyingSets ------ */
1680 /* check if include internal-renderer entry */
1681 static short incl_buts_cam1 (bKeyingSet *ks, const char mode[])
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);
1688 /* check if include external-renderer entry */
1689 static short incl_buts_cam2 (bKeyingSet *ks, const char mode[])
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);
1696 /* array for camera keyingset defines */
1697 bKeyingSet defks_buts_cam[] =
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}},
1704 {NULL, "%l", 0, -1, 0, {0}}, // separator
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}},
1710 {NULL, "%l", 0, -1, 0, {0}}, // separator
1712 {NULL, "Available", ID_CA, -2, 0, {0}}
1717 /* Keying Context Defines - Must keep in sync with enumeration (eKS_Contexts) */
1718 bKeyingContext ks_contexts[] =
1720 KSC_TEMPLATE(v3d_object),
1721 KSC_TEMPLATE(v3d_pchan),
1723 KSC_TEMPLATE(buts_shading_mat),
1724 KSC_TEMPLATE(buts_shading_wo),
1725 KSC_TEMPLATE(buts_shading_la),
1726 KSC_TEMPLATE(buts_shading_tex),
1728 KSC_TEMPLATE(buts_object),
1729 KSC_TEMPLATE(buts_cam)
1732 /* Keying Context Enumeration - Must keep in sync with definitions*/
1733 typedef enum eKS_Contexts {
1745 /* make sure this last one remains untouched! */
1750 /* ---------------- KeyingSet Tools ------------------- */
1752 /* helper for commonkey_context_get() - get keyingsets for 3d-view */
1753 static void commonkey_context_getv3d (const bContext *C, ListBase *sources, bKeyingContext **ksc)
1755 Scene *scene= CTX_data_scene(C);
1759 if ((OBACT) && (OBACT->flag & OB_POSEMODE)) {
1760 bPoseChannel *pchan;
1764 *ksc= &ks_contexts[KSC_V3D_PCHAN];
1766 //set_pose_keys(ob); /* sets pchan->flag to POSE_KEY if bone selected, and clears if not */
1768 /* loop through posechannels */
1769 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
1770 if (pchan->flag & POSE_KEY) {
1773 /* add new keyframing destination */
1774 cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1775 BLI_addtail(sources, cks);
1777 /* set id-block to key to, and action */
1779 cks->act= ob->action;
1783 cks->actname= pchan->name;
1789 *ksc= &ks_contexts[KSC_V3D_OBJECT];
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) {
1796 /* add new keyframing destination */
1797 cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1798 BLI_addtail(sources, cks);
1800 /* set id-block to key to */
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";
1809 // TODO: add checks for lib-linked data
1810 if ((ob->ipo) || (ob->action)) {
1815 bActionChannel *achan;
1817 cks->act= ob->action;
1818 achan= get_action_channel(ob->action, cks->actname);
1820 if (achan && achan->ipo)
1821 cks->ipo= achan->ipo;
1823 /* cks->ipo can be NULL while editing */
1825 /* deselect all ipo-curves */
1826 for (icu= cks->ipo->curve.first; icu; icu= icu->next) {
1827 icu->flag &= ~IPO_SELECT;
1836 /* helper for commonkey_context_get() - get keyingsets for buttons window */
1837 static void commonkey_context_getsbuts (const bContext *C, ListBase *sources, bKeyingContext **ksc)
1839 #if 0 // XXX dunno what's the future of this stuff...
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 -------------< */
1849 Material *ma= editnode_get_active_material(G.buts->lockpoin);
1852 /* add new keyframing destination */
1853 cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1854 BLI_addtail(sources, cks);
1859 cks->map= texchannel_to_adrcode(ma->texact);
1861 /* set keyingsets */
1862 *ksc= &ks_contexts[KSC_BUTS_MAT];
1867 case TAB_SHADING_WORLD: /* >------------- World Tab -------------< */
1869 World *wo= G.buts->lockpoin;
1872 /* add new keyframing destination */
1873 cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1874 BLI_addtail(sources, cks);
1879 cks->map= texchannel_to_adrcode(wo->texact);
1881 /* set keyingsets */
1882 *ksc= &ks_contexts[KSC_BUTS_WO];
1887 case TAB_SHADING_LAMP: /* >------------- Lamp Tab -------------< */
1889 Lamp *la= G.buts->lockpoin;
1892 /* add new keyframing destination */
1893 cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1894 BLI_addtail(sources, cks);
1899 cks->map= texchannel_to_adrcode(la->texact);
1901 /* set keyingsets */
1902 *ksc= &ks_contexts[KSC_BUTS_LA];
1907 case TAB_SHADING_TEX: /* >------------- Texture Tab -------------< */
1909 Tex *tex= G.buts->lockpoin;
1912 /* add new keyframing destination */
1913 cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1914 BLI_addtail(sources, cks);
1920 /* set keyingsets */
1921 *ksc= &ks_contexts[KSC_BUTS_TEX];
1929 case CONTEXT_OBJECT: /* ------------- Object buttons ---------------- */
1934 /* add new keyframing destination */
1935 cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1936 BLI_addtail(sources, cks);
1938 /* set id-block to key to */
1942 /* set keyingsets */
1943 *ksc= &ks_contexts[KSC_BUTS_OB];
1949 case CONTEXT_EDITING: /* ------------- Editing buttons ---------------- */
1953 if ((ob) && (ob->type==OB_CAMERA) && (G.buts->lockpoin)) { /* >---------------- camera buttons ---------------< */
1954 Camera *ca= G.buts->lockpoin;
1956 /* add new keyframing destination */
1957 cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
1958 BLI_addtail(sources, cks);
1960 /* set id-block to key to */
1964 /* set keyingsets */
1965 *ksc= &ks_contexts[KSC_BUTS_CAM];
1971 #endif // XXX end of buttons stuff to port...
1973 /* if nothing happened... */
1978 /* get keyingsets for appropriate context */
1979 static void commonkey_context_get (const bContext *C, ScrArea *sa, short mode, ListBase *sources, bKeyingContext **ksc)
1981 /* get current view if no view is defined */
1985 /* check view type */
1986 switch (sa->spacetype) {
1987 /* 3d view - first one tested as most often used */
1990 commonkey_context_getv3d(C, sources, ksc);
1997 commonkey_context_getsbuts(C, sources, ksc);
2001 /* spaces with their own methods */
2003 //if (mode == COMMONKEY_MODE_INSERT)
2004 // insertkey_editipo(); // XXX old calls...
2007 //if (mode == COMMONKEY_MODE_INSERT)
2008 // insertkey_action(); // XXX old calls...
2011 /* timeline view - keyframe buttons */
2014 bScreen *sc= CTX_wm_screen(C);
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)
2022 //sab= find_biggest_area_of_type(SPACE_VIEW3D);
2023 sab= NULL; // XXX for now...
2025 commonkey_context_getv3d(C, sources, ksc);
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;
2033 if (sa->spacetype != SPACE_TIME) {
2034 if ( (!sab) || (area > bigarea) ) {
2041 /* use whichever largest area was found (it shouldn't be a time window) */
2043 commonkey_context_get(C, sab, mode, sources, ksc);
2049 /* flush updates after all operations */
2050 static void commonkey_context_finish (const bContext *C, ListBase *sources)
2052 ScrArea *curarea= CTX_wm_area(C);
2053 Scene *scene= CTX_data_scene(C);
2055 /* check view type */
2056 switch (curarea->spacetype) {
2057 /* 3d view - first one tested as most often used */
2060 /* either pose or object level */
2061 if (OBACT && (OBACT->pose)) {
2062 //Object *ob= OBACT;
2064 /* recalculate ipo handles, etc. */
2065 // XXX this method has been removed!
2067 // remake_action_ipos(ob->action);
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);
2078 /* loop over bases (as seen in sources) */
2079 for (cks= sources->first; cks; cks= cks->next) {
2080 Object *ob= (Object *)cks->id;
2082 /* simply set recalc flag */
2083 ob->recalc |= OB_RECALC_OB;
2091 /* flush refreshes after undo */
2092 static void commonkey_context_refresh (const bContext *C)
2094 ScrArea *curarea= CTX_wm_area(C);
2096 /* check view type */
2097 switch (curarea->spacetype) {
2098 /* 3d view - first one tested as most often used */
2102 ED_anim_dag_flush_update(C);
2106 /* buttons window */
2109 //allspace(REMAKEIPO, 0);
2110 //allqueue(REDRAWVIEW3D, 0);
2111 //allqueue(REDRAWMARKER, 0);
2119 /* Build menu-string of available keying-sets (allocates memory for string)
2120 * NOTE: mode must not be longer than 64 chars
2122 static char *build_keyingsets_menu (bKeyingContext *ksc, const char mode[48])
2124 DynStr *pupds= BLI_dynstr_new();
2130 /* add title first */
2131 BLI_snprintf(buf, 64, "%s Key %%t|", mode);
2132 BLI_dynstr_append(pupds, buf);
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);
2146 BLI_snprintf( buf, 64, "%%l%s", ((n < ksc->tot)?"|":"") );
2147 BLI_dynstr_append(pupds, buf);
2150 else if ( (ks->include_cb==NULL) || (ks->include_cb(ks, mode)) ) {
2151 /* entry can be included */
2152 BLI_dynstr_append(pupds, ks->name);
2154 /* check if special "shapekey" entry */
2156 BLI_snprintf( buf, 64, "%%x0%s", ((n < ksc->tot)?"|":"") );
2158 BLI_snprintf( buf, 64, "%%x%d%s", n, ((n < ksc->tot)?"|":"") );
2159 BLI_dynstr_append(pupds, buf);
2163 /* convert to normal MEM_malloc'd string */
2164 str= BLI_dynstr_get_cstring(pupds);
2165 BLI_dynstr_free(pupds);
2170 /* Get the keying set that was chosen by the user from the menu */
2171 static bKeyingSet *get_keyingset_fromcontext (bKeyingContext *ksc, short index)
2173 /* check if index is valid */
2174 if (ELEM(NULL, ksc, ksc->keyingsets))
2176 if ((index < 1) || (index > ksc->tot))
2179 /* index starts from 1, and should directly correspond to keyingset in array */
2180 return (bKeyingSet *)(ksc->keyingsets + (index - 1));
2183 /* ---------------- Keyframe Management API -------------------- */
2185 /* Display a menu for handling the insertion of keyframes based on the active view */
2186 void common_modifykey (const bContext *C, short mode)
2188 ListBase dsources = {NULL, NULL};
2189 bKeyingContext *ksc= NULL;
2191 bKeyingSet *ks = NULL;
2192 char *menustr, buf[64];
2195 /* check if mode is valid */
2196 if (ELEM(mode, COMMONKEY_MODE_INSERT, COMMONKEY_MODE_DELETE)==0)
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...
2202 commonkey_context_get(C, NULL, mode, &dsources, &ksc);
2204 /* check that there is data to operate on */
2205 if (ELEM(NULL, dsources.first, ksc)) {
2206 BLI_freelistN(&dsources);
2210 /* get menu and process it */
2211 if (mode == COMMONKEY_MODE_DELETE)
2212 menustr= build_keyingsets_menu(ksc, "Delete");
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
2220 /* no item selected or shapekey entry? */
2222 /* free temp sources */
2223 BLI_freelistN(&dsources);
2225 /* check if insert new shapekey */
2226 // XXX missing function!
2227 //if ((menu_nr == 0) && (mode == COMMONKEY_MODE_INSERT))
2228 // insert_shapekey(OBACT);
2230 ksc->lastused= NULL;
2235 /* try to get keyingset */
2236 ks= get_keyingset_fromcontext(ksc, menu_nr);
2239 BLI_freelistN(&dsources);
2244 /* loop over each destination, applying the keying set */
2245 for (cks= dsources.first; cks; cks= cks->next) {
2248 /* special hacks for 'available' option */
2249 if (ks->flag == -2) {
2250 IpoCurve *icu= NULL, *icn= NULL;
2252 /* get first IPO-curve */
2253 if (cks->act && cks->actname) {
2254 bActionChannel *achan= get_action_channel(cks->act, cks->actname);
2256 // FIXME: what about constraint channels?
2257 if (achan && achan->ipo)
2258 icu= achan->ipo->curve.first;
2261 icu= cks->ipo->curve.first;
2263 /* we get adrcodes directly from IPO curves (see method below...) */
2264 for (; icu; icu= icn) {
2267 /* get next ipo-curve in case current is deleted */
2270 /* insert mode or delete mode */
2271 if (mode == COMMONKEY_MODE_DELETE) {
2272 /* local flags only add on to global flags */
2275 /* delete keyframe */
2276 success += deletekey(cks->id, ks->blocktype, cks->actname, cks->constname, icu->adrcode, flag);
2279 /* local flags only add on to global flags */
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;
2285 /* insert keyframe */
2286 success += insertkey(cks->id, ks->blocktype, cks->actname, cks->constname, icu->adrcode, flag);
2291 bKS_AdrcodeGetter kag;
2292 short (*get_next_adrcode)(bKS_AdrcodeGetter *);
2295 /* initialise keyingset channel iterator */
2296 ks_adrcodegetter_init(&kag, ks, cks);
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;
2304 get_next_adrcode= ks_getnextadrcode_default;
2306 /* loop over channels available in keyingset */
2307 for (adrcode= get_next_adrcode(&kag); adrcode > 0; adrcode= get_next_adrcode(&kag)) {
2310 /* insert mode or delete mode */
2311 if (mode == COMMONKEY_MODE_DELETE) {
2312 /* local flags only add on to global flags */
2314 //flag &= ~COMMONKEY_MODES;
2316 /* delete keyframe */
2317 success += deletekey(cks->id, ks->blocktype, cks->actname, cks->constname, adrcode, flag);
2320 /* local flags only add on to global flags */
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;
2327 /* insert keyframe */
2328 success += insertkey(cks->id, ks->blocktype, cks->actname, cks->constname, adrcode, flag);
2333 /* special handling for some key-sources */
2335 /* set pose recalc-paths flag */
2337 Object *ob= (Object *)cks->id;
2338 bPoseChannel *pchan= cks->pchan;
2340 /* set flag to trigger path recalc */
2342 ob->pose->flag |= POSE_RECALCPATHS;
2344 /* clear unkeyed flag (it doesn't matter if it's set or not) */
2346 pchan->bone->flag &= ~BONE_UNKEYED;
2351 /* apply post-keying flushes for this data sources */
2352 commonkey_context_finish(C, &dsources);
2355 /* free temp data */
2356 BLI_freelistN(&dsources);
2359 if (mode == COMMONKEY_MODE_DELETE)
2360 BLI_snprintf(buf, 64, "Delete %s Key", ks->name);
2362 BLI_snprintf(buf, 64, "Insert %s Key", ks->name);
2363 //BIF_undo_push(buf);
2365 /* queue updates for contexts */
2366 commonkey_context_refresh(C);
2371 /* used to insert keyframes from any view */
2372 void common_insertkey (const bContext *C)
2374 common_modifykey(C, COMMONKEY_MODE_INSERT);
2377 /* used to insert keyframes from any view */
2378 void common_deletekey (const bContext *C)
2380 common_modifykey(C, COMMONKEY_MODE_DELETE);
2384 /* ************************************************** */
2385 /* KEYFRAME DETECTION */
2387 /* --------------- API/Per-Datablock Handling ------------------- */
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...
2392 short ipo_frame_has_keyframe (Ipo *ipo, float frame, short filter)
2396 /* can only find if there is data */
2400 /* if only check non-muted, check if muted */
2401 if ((filter & ANIMFILTER_KEYS_MUTED) || (ipo->muteipo))
2404 /* loop over IPO-curves, using binary-search to try to find matches
2405 * - this assumes that keyframes are only beztriples
2407 for (icu= ipo->curve.first; icu; icu= icu->next) {
2408 /* only check if there are keyframes (currently only of type BezTriple) */
2410 /* we either include all regardless of muting, or only non-muted */
2411 if ((filter & ANIMFILTER_KEYS_MUTED) || (icu->flag & IPO_MUTE)==0) {
2413 int i = binarysearch_bezt_index(icu->bezt, frame, icu->totvert, &replace);
2415 /* binarysearch_bezt_index will set replace to be 0 or 1
2416 * - obviously, 1 represents a match
2419 /* sanity check: 'i' may in rare cases exceed arraylen */
2420 if ((i >= 0) && (i < icu->totvert))
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...
2434 short action_frame_has_keyframe (bAction *act, float frame, short filter)
2436 bActionChannel *achan;
2438 /* error checking */
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
2447 if ((filter & ANIMFILTER_KEYS_MUTED) || (achan->flag & ACHAN_HIDDEN)==0) {
2448 if (ipo_frame_has_keyframe(achan->ipo, frame, filter))
2457 /* Checks whether an Object has a keyframe for a given frame */
2458 short object_frame_has_keyframe (Object *ob, float frame, short filter)
2460 /* error checking */
2464 /* check for an action - actions take priority over normal IPO's */
2468 /* apply nla-action scaling if needed */
2469 if ((ob->nlaflag & OB_NLA_OVERRIDE) && (ob->nlastrips.first))
2470 aframe= get_action_frame(ob, frame);
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;
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));
2486 /* for everything else, just use the standard test (only return if success) */
2487 if (action_frame_has_keyframe(ob->action, aframe, filter))
2491 /* only return if success */
2492 if (ipo_frame_has_keyframe(ob->ipo, frame, filter))
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);
2500 /* shapekeys can have keyframes ('Relative Shape Keys')
2501 * or depend on time (old 'Absolute Shape Keys')
2504 /* 1. test for relative (with keyframes) */
2505 if (id_frame_has_keyframe((ID *)key, frame, filter))
2508 /* 2. test for time */
2509 // TODO... yet to be implemented (this feature may evolve before then anyway)
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));
2518 /* we only retrieve the active material... */
2519 if (id_frame_has_keyframe((ID *)ma, frame, filter))
2525 /* loop over materials */
2526 for (a=0; a<ob->totcol; a++) {
2527 Material *ma= give_current_material(ob, a+1);
2529 if (id_frame_has_keyframe((ID *)ma, frame, filter))
2539 /* --------------- API ------------------- */
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)
2544 /* error checking */
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);
2556 case ID_OB: /* object */
2557 return object_frame_has_keyframe((Object *)id, frame, filter);
2559 case ID_MA: /* material */
2561 Material *ma= (Material *)id;
2563 /* currently, material's only have an ipo-block */
2564 return ipo_frame_has_keyframe(ma->ipo, frame, filter);
2568 case ID_KE: /* shapekey */
2570 Key *key= (Key *)id;
2572 /* currently, shapekey's only have an ipo-block */
2573 return ipo_frame_has_keyframe(key->ipo, frame, filter);
2578 /* no keyframe found */
2582 /* ************************************************** */