/** * $Id$ * * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. The Blender * Foundation also sells licenses for use in proprietary software under * the Blender License. See http://www.blender.org/BL/ for information * about this. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ /* this code feels over-complex, mostly because I choose in the past to devise a system that converts the Ipo blocks (linked to Object, Material, etc), into a copy of that data which is being worked on; the 'editipo'. The editipo then can have 'ipokey' data, which is optimized for editing curves as if it were key positions. This is still a great feature to work with, which makes ipo editing in Blender still valuable. However, getting this beast under control was hard, even for me... (ton) */ #include #include #include #ifdef HAVE_CONFIG_H #include #endif #ifndef WIN32 #include #else #include #include "BLI_winstuff.h" #endif #include "MEM_guardedalloc.h" #include "PIL_time.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "DNA_constraint_types.h" #include "DNA_action_types.h" #include "DNA_armature_types.h" #include "DNA_object_types.h" #include "DNA_lamp_types.h" #include "DNA_sequence_types.h" #include "DNA_sound_types.h" #include "DNA_camera_types.h" #include "DNA_material_types.h" #include "DNA_key_types.h" #include "DNA_screen_types.h" #include "DNA_scene_types.h" #include "DNA_ipo_types.h" #include "DNA_curve_types.h" #include "DNA_space_types.h" #include "DNA_userdef_types.h" #include "DNA_view3d_types.h" #include "DNA_group_types.h" #include "DNA_ika_types.h" #include "BKE_utildefines.h" #include "BKE_action.h" #include "BKE_anim.h" #include "BKE_material.h" #include "BKE_ipo.h" #include "BKE_key.h" #include "BKE_ika.h" #include "BKE_displist.h" #include "BKE_global.h" #include "BKE_group.h" #include "BIF_butspace.h" #include "BIF_editkey.h" #include "BIF_editseq.h" #include "BIF_editview.h" #include "BIF_interface.h" #include "BIF_mywindow.h" #include "BIF_poseobject.h" #include "BIF_screen.h" #include "BIF_space.h" #include "BIF_toolbox.h" #include "BIF_poseobject.h" #include "BDR_drawobject.h" #include "BDR_editobject.h" #include "BSE_trans_types.h" #include "BSE_editipo_types.h" #include "BSE_drawipo.h" #include "BSE_editipo.h" #include "BSE_editaction.h" #include "BSE_edit.h" #include "BSE_drawview.h" #include "BSE_headerbuttons.h" #include "blendef.h" #include "mydevice.h" #include "render.h" /* forwards */ #define BEZSELECTED(bezt) (((bezt)->f1 & 1) || ((bezt)->f2 & 1) || ((bezt)->f3 & 1)) #define IPOTHRESH 0.9 #define ISPOIN(a, b, c) ( (a->b) && (a->c) ) #define ISPOIN3(a, b, c, d) ( (a->b) && (a->c) && (a->d) ) #define ISPOIN4(a, b, c, d, e) ( (a->b) && (a->c) && (a->d) && (a->e) ) extern int ob_ar[]; extern int ma_ar[]; extern int seq_ar[]; extern int cu_ar[]; extern int key_ar[]; extern int wo_ar[]; extern int la_ar[]; extern int cam_ar[]; extern int snd_ar[]; extern int ac_ar[]; extern int co_ar[]; void getname_ac_ei(int nr, char *str) { switch(nr) { case AC_LOC_X: strcpy(str, "LocX"); break; case AC_LOC_Y: strcpy(str, "LocY"); break; case AC_LOC_Z: strcpy(str, "LocZ"); break; case AC_SIZE_X: strcpy(str, "SizeX"); break; case AC_SIZE_Y: strcpy(str, "SizeY"); break; case AC_SIZE_Z: strcpy(str, "SizeZ"); break; case AC_QUAT_X: strcpy(str, "QuatX"); break; case AC_QUAT_Y: strcpy(str, "QuatY"); break; case AC_QUAT_Z: strcpy(str, "QuatZ"); break; case AC_QUAT_W: strcpy(str, "QuatW"); break; default: str[0]= 0; } } void getname_co_ei(int nr, char *str) { switch(nr){ case CO_ENFORCE: strcpy(str, "Inf"); break; } } void getname_ob_ei(int nr, char *str, int colipo) { switch(nr) { case OB_LOC_X: strcpy(str, "LocX"); break; case OB_LOC_Y: strcpy(str, "LocY"); break; case OB_LOC_Z: strcpy(str, "LocZ"); break; case OB_DLOC_X: strcpy(str, "dLocX"); break; case OB_DLOC_Y: strcpy(str, "dLocY"); break; case OB_DLOC_Z: strcpy(str, "dLocZ"); break; case OB_ROT_X: strcpy(str, "RotX"); break; case OB_ROT_Y: strcpy(str, "RotY"); break; case OB_ROT_Z: strcpy(str, "RotZ"); break; case OB_DROT_X: strcpy(str, "dRotX"); break; case OB_DROT_Y: strcpy(str, "dRotY"); break; case OB_DROT_Z: strcpy(str, "dRotZ"); break; case OB_SIZE_X: strcpy(str, "SizeX"); break; case OB_SIZE_Y: strcpy(str, "SizeY"); break; case OB_SIZE_Z: strcpy(str, "SizeZ"); break; case OB_DSIZE_X: strcpy(str, "dSizeX"); break; case OB_DSIZE_Y: strcpy(str, "dSizeY"); break; case OB_DSIZE_Z: strcpy(str, "dSizeZ"); break; case OB_LAY: strcpy(str, "Layer"); break; case OB_TIME: strcpy(str, "Time"); break; case OB_EFF_X: if(colipo) strcpy(str, "ColR"); else strcpy(str, "EffX"); break; case OB_EFF_Y: if(colipo) strcpy(str, "ColG"); else strcpy(str, "EffY"); break; case OB_EFF_Z: if(colipo) strcpy(str, "ColB"); else strcpy(str, "EffZ"); break; case OB_COL_A: strcpy(str, "ColA"); break; default: str[0]= 0; } } void getname_tex_ei(int nr, char *str) { switch(nr) { case MAP_OFS_X: strcpy(str, "OfsX"); break; case MAP_OFS_Y: strcpy(str, "OfsY"); break; case MAP_OFS_Z: strcpy(str, "OfsZ"); break; case MAP_SIZE_X: strcpy(str, "SizeX"); break; case MAP_SIZE_Y: strcpy(str, "SizeY"); break; case MAP_SIZE_Z: strcpy(str, "SizeZ"); break; case MAP_R: strcpy(str, "texR"); break; case MAP_G: strcpy(str, "texG"); break; case MAP_B: strcpy(str, "texB"); break; case MAP_DVAR: strcpy(str, "DefVar"); break; case MAP_COLF: strcpy(str, "Col"); break; case MAP_NORF: strcpy(str, "Nor"); break; case MAP_VARF: strcpy(str, "Var"); break; default: str[0]= 0; } } void getname_mat_ei(int nr, char *str) { if(nr>=MA_MAP1) getname_tex_ei((nr & (MA_MAP1-1)), str); else { switch(nr) { case MA_COL_R: strcpy(str, "R"); break; case MA_COL_G: strcpy(str, "G"); break; case MA_COL_B: strcpy(str, "B"); break; case MA_SPEC_R: strcpy(str, "SpecR"); break; case MA_SPEC_G: strcpy(str, "SpecG"); break; case MA_SPEC_B: strcpy(str, "SpecB"); break; case MA_MIR_R: strcpy(str, "MirR"); break; case MA_MIR_G: strcpy(str, "MirG"); break; case MA_MIR_B: strcpy(str, "MirB"); break; case MA_REF: strcpy(str, "Ref"); break; case MA_ALPHA: strcpy(str, "Alpha"); break; case MA_EMIT: strcpy(str, "Emit"); break; case MA_AMB: strcpy(str, "Amb"); break; case MA_SPEC: strcpy(str, "Spec"); break; case MA_HARD: strcpy(str, "Hard"); break; case MA_SPTR: strcpy(str, "SpTra"); break; case MA_ANG: strcpy(str, "Ang"); break; case MA_MODE: strcpy(str, "Mode"); break; case MA_HASIZE: strcpy(str, "HaSize"); break; default: str[0]= 0; } } } void getname_world_ei(int nr, char *str) { if(nr>=MA_MAP1) getname_tex_ei((nr & (MA_MAP1-1)), str); else { switch(nr) { case WO_HOR_R: strcpy(str, "HorR"); break; case WO_HOR_G: strcpy(str, "HorG"); break; case WO_HOR_B: strcpy(str, "HorB"); break; case WO_ZEN_R: strcpy(str, "ZenR"); break; case WO_ZEN_G: strcpy(str, "ZenG"); break; case WO_ZEN_B: strcpy(str, "ZenB"); break; case WO_EXPOS: strcpy(str, "Expos"); break; case WO_MISI: strcpy(str, "Misi"); break; case WO_MISTDI: strcpy(str, "MisDi"); break; case WO_MISTSTA: strcpy(str, "MisSta"); break; case WO_MISTHI: strcpy(str, "MisHi"); break; case WO_STAR_R: strcpy(str, "StarR"); break; case WO_STAR_G: strcpy(str, "StarB"); break; case WO_STAR_B: strcpy(str, "StarG"); break; case WO_STARDIST: strcpy(str, "StarDi"); break; case WO_STARSIZE: strcpy(str, "StarSi"); break; default: str[0]= 0; } } } void getname_seq_ei(int nr, char *str) { switch(nr) { case SEQ_FAC1: strcpy(str, "Fac"); break; default: str[0]= 0; } } void getname_cu_ei(int nr, char *str) { switch(nr) { case CU_SPEED: strcpy(str, "Speed"); break; default: str[0]= 0; } } void getname_key_ei(int nr, char *str) { if(nr==KEY_SPEED) strcpy(str, "Speed"); else sprintf(str, "Key %d", nr); } void getname_la_ei(int nr, char *str) { if(nr>=MA_MAP1) getname_tex_ei((nr & (MA_MAP1-1)), str); else { switch(nr) { case LA_ENERGY: strcpy(str, "Energ"); break; case LA_COL_R: strcpy(str, "R"); break; case LA_COL_G: strcpy(str, "G"); break; case LA_COL_B: strcpy(str, "B"); break; case LA_DIST: strcpy(str, "Dist"); break; case LA_SPOTSI: strcpy(str, "SpoSi"); break; case LA_SPOTBL: strcpy(str, "SpoBl"); break; case LA_QUAD1: strcpy(str, "Quad1"); break; case LA_QUAD2: strcpy(str, "Quad2"); break; case LA_HALOINT: strcpy(str, "HaInt"); break; default: str[0]= 0; } } } void getname_cam_ei(int nr, char *str) { switch(nr) { case CAM_LENS: strcpy(str, "Lens"); break; case CAM_STA: strcpy(str, "ClSta"); break; case CAM_END: strcpy(str, "ClEnd"); break; default: str[0]= 0; } } void getname_snd_ei(int nr, char *str) { switch(nr) { case SND_VOLUME: strcpy(str, "Vol"); break; case SND_PITCH: strcpy(str, "Pitch"); break; case SND_PANNING: strcpy(str, "Pan"); break; case SND_ATTEN: strcpy(str, "Atten"); break; default: str[0]= 0; } } IpoCurve *find_ipocurve(Ipo *ipo, int adrcode) { if(ipo) { IpoCurve *icu= ipo->curve.first; while(icu) { if(icu->adrcode==adrcode) return icu; icu= icu->next; } } return NULL; } void boundbox_ipocurve(IpoCurve *icu) { BezTriple *bezt; float vec[3]={0.0,0.0,0.0}; float min[3], max[3]; int a; if(icu->totvert) { INIT_MINMAX(min, max); if(icu->bezt ) { a= icu->totvert; bezt= icu->bezt; while(a--) { if(icu->vartype & IPO_BITS) { vec[0]= bezt->vec[1][0]; vec[1]= 0.0; DO_MINMAX(vec, min, max); vec[1]= 16.0; DO_MINMAX(vec, min, max); } else { if(icu->ipo==IPO_BEZ && a!=icu->totvert-1) { DO_MINMAX(bezt->vec[0], min, max); } DO_MINMAX(bezt->vec[1], min, max); if(icu->ipo==IPO_BEZ && a!=0) { DO_MINMAX(bezt->vec[2], min, max); } } bezt++; } } if(min[0]==max[0]) max[0]= (float)(min[0]+1.0); if(min[1]==max[1]) max[1]= (float)(min[1]+0.1); icu->totrct.xmin= min[0]; icu->totrct.ymin= min[1]; icu->totrct.xmax= max[0]; icu->totrct.ymax= max[1]; } else { icu->totrct.xmin= icu->totrct.ymin= 0.0; icu->totrct.xmax= EFRA; icu->totrct.ymax= 1.0; } } void boundbox_ipo(Ipo *ipo, rctf *bb) { IpoCurve *icu; int first= 1; icu= ipo->curve.first; while(icu) { boundbox_ipocurve(icu); if(first) { *bb= icu->totrct; first= 0; } else BLI_union_rctf(bb, &(icu->totrct)); icu= icu->next; } } void editipo_changed(SpaceIpo *si, int doredraw) { EditIpo *ei; View2D *v2d; Key *key; KeyBlock *kb; int a, first=1; ei= si->editipo; if(ei==0) return; for(a=0; atotipo; a++, ei++) { if(ei->icu) { /* twice because of ittererating new autohandle */ calchandles_ipocurve(ei->icu); calchandles_ipocurve(ei->icu); if(ei->flag & IPO_VISIBLE) { boundbox_ipocurve(ei->icu); sort_time_ipocurve(ei->icu); if(first) { si->v2d.tot= ei->icu->totrct; first= 0; } else BLI_union_rctf(&(si->v2d.tot), &(ei->icu->totrct)); } } } v2d= &(si->v2d); /* keylines? */ if(si->blocktype==ID_KE) { key= (Key *)si->from; if(key && key->block.first) { kb= key->block.first; if(kb->pos < v2d->tot.ymin) v2d->tot.ymin= kb->pos; kb= key->block.last; if(kb->pos > v2d->tot.ymax) v2d->tot.ymax= kb->pos; } } /* is there no curve? */ if(first) { v2d->tot.xmin= 0.0; v2d->tot.xmax= EFRA; v2d->tot.ymin= (float)-0.1; v2d->tot.ymax= (float)1.1; if(si->blocktype==ID_SEQ) { v2d->tot.xmin= -5.0; v2d->tot.xmax= 105.0; v2d->tot.ymin= (float)-0.1; v2d->tot.ymax= (float)1.1; } } si->tot= v2d->tot; if(doredraw) { /* if you always call do_ipo: you get problems with insertkey, for example * when inserting only a 'loc' the 'ob->rot' value then is changed. */ if(si->blocktype==ID_OB) { /* clear delta loc,rot,size (when free/delete ipo) */ clear_delta_obipo(si->ipo); } do_ipo(si->ipo); allqueue(REDRAWIPO, 0); allqueue (REDRAWACTION, 0); allqueue(REDRAWNLA, 0); allqueue(REDRAWBUTSOBJECT, 0); if(si->blocktype==ID_OB) { Object *ob= (Object *)si->from; if(ob && ob->type==OB_IKA) itterate_ika(ob); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWNLA, 0); } else if(si->blocktype==ID_MA) allqueue(REDRAWBUTSSHADING, 0); else if(si->blocktype==ID_WO) allqueue(REDRAWBUTSSHADING, 0); else if(si->blocktype==ID_LA) allqueue(REDRAWBUTSSHADING, 0); // else if(si->blocktype==ID_SO) allqueue(REDRAWBUTSSOUND, 0); else if(si->blocktype==ID_CA) { allqueue(REDRAWBUTSEDIT, 0); allqueue(REDRAWVIEW3D, 0); } else if(si->blocktype==ID_SEQ) clear_last_seq(); else if(si->blocktype==ID_AC){ do_all_actions(); allqueue(REDRAWACTION, 0); allqueue(REDRAWNLA, 0); } else if(si->blocktype==ID_KE) { do_spec_key((Key *)si->from); allqueue(REDRAWVIEW3D, 0); } else if(si->blocktype==ID_CU) { calc_curvepath(OBACT); allqueue(REDRAWVIEW3D, 0); } } if(si->showkey) make_ipokey(); } void scale_editipo() { /* comes from buttons, scale with G.sipo->tot rect */ EditIpo *ei; BezTriple *bezt; float facx, facy; int a, b; facx= (G.sipo->tot.xmax-G.sipo->tot.xmin)/(G.sipo->v2d.tot.xmax-G.sipo->v2d.tot.xmin); facy= (G.sipo->tot.ymax-G.sipo->tot.ymin)/(G.sipo->v2d.tot.ymax-G.sipo->v2d.tot.ymin); ei= G.sipo->editipo; if(ei==0) return; for(a=0; atotipo; a++, ei++) { if ISPOIN(ei, flag & IPO_VISIBLE, icu) { bezt= ei->icu->bezt; b= ei->icu->totvert; while(b--) { bezt->vec[0][0]= facx*(bezt->vec[0][0] - G.sipo->v2d.tot.xmin) + G.sipo->tot.xmin; bezt->vec[1][0]= facx*(bezt->vec[1][0] - G.sipo->v2d.tot.xmin) + G.sipo->tot.xmin; bezt->vec[2][0]= facx*(bezt->vec[2][0] - G.sipo->v2d.tot.xmin) + G.sipo->tot.xmin; bezt->vec[0][1]= facy*(bezt->vec[0][1] - G.sipo->v2d.tot.ymin) + G.sipo->tot.ymin; bezt->vec[1][1]= facy*(bezt->vec[1][1] - G.sipo->v2d.tot.ymin) + G.sipo->tot.ymin; bezt->vec[2][1]= facy*(bezt->vec[2][1] - G.sipo->v2d.tot.ymin) + G.sipo->tot.ymin; bezt++; } } } editipo_changed(G.sipo, 1); allqueue(REDRAWNLA, 0); allqueue (REDRAWACTION, 0); allqueue(REDRAWIPO, 0); } Ipo *get_ipo_to_edit(ID **from) { Object *ob= OBACT; *from= 0; if (G.sipo->pin) { *from = G.sipo->from; return G.sipo->ipo; } if(G.sipo->blocktype==ID_SEQ) { extern Sequence *last_seq; *from= (ID *)last_seq; if(last_seq) return last_seq->ipo; } else if(G.sipo->blocktype==IPO_CO){ if (ob && ob->activecon){ *from= (ID*) ob; return ob->activecon->ipo; } } else if(G.sipo->blocktype==ID_AC) { bActionChannel *chan; if (ob && ob->action){ *from= (ID *) ob->action; chan= get_hilighted_action_channel(ob->action); if (chan) return chan->ipo; else{ *from = NULL; return NULL; } } } else if(G.sipo->blocktype==ID_WO) { World *wo= G.scene->world; *from= (ID *)wo; if(wo) return wo->ipo; } else if(G.sipo->blocktype==ID_OB) { if(ob) { *from= (ID *)ob; return ob->ipo; } } else if(G.sipo->blocktype==ID_MA) { if(ob) { Material *ma= give_current_material(ob, ob->actcol); *from= (ID *)ma; if(ma) return ma->ipo; } } else if(G.sipo->blocktype==ID_KE) { if(ob) { Key *key= give_current_key(ob); *from= (ID *)key; if(key) return key->ipo; } } else if(G.sipo->blocktype==ID_CU) { if(ob && ob->type==OB_CURVE) { Curve *cu= ob->data; *from= (ID *)cu; return cu->ipo; } } else if(G.sipo->blocktype==ID_LA) { if(ob && ob->type==OB_LAMP) { Lamp *la= ob->data; *from= (ID *)la; return la->ipo; } } else if(G.sipo->blocktype==ID_CA) { if(ob && ob->type==OB_CAMERA) { Camera *ca= ob->data; *from= (ID *)ca; if(ca) return ca->ipo; } } else if(G.sipo->blocktype==ID_SO) { // if (G.buts && G.buts->mainb == BUTS_SOUND) { // bSound *sound = G.buts->lockpoin; // *from= (ID *)sound; // if(sound) return sound->ipo; // } } return NULL; } unsigned int ipo_rainbow(int cur, int tot) { float dfac, fac, sat; dfac= (float)(1.0/( (float)tot+1.0)); /* this calculation makes 2 different cycles of rainbow colors */ if(cur< tot/2) fac= (float)(cur*2.0*dfac); else fac= (float)((cur-tot/2)*2.0*dfac +dfac); if(fac>0.5 && fac<0.8) sat= (float)0.4; else sat= 0.5; return hsv_to_cpack(fac, sat, 1.0); } void make_ob_editipo(Object *ob, SpaceIpo *si) { EditIpo *ei; int a, len, colipo=0; if(ob->type==OB_MESH) colipo= 1; ei= si->editipo= MEM_callocN(OB_TOTIPO*sizeof(EditIpo), "editipo"); si->totipo= OB_TOTIPO; for(a=0; aname, colipo); ei->adrcode= ob_ar[a]; if ELEM6(ei->adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z, OB_DROT_X, OB_DROT_Y, OB_DROT_Z) ei->disptype= IPO_DISPDEGR; else if(ei->adrcode==OB_LAY) ei->disptype= IPO_DISPBITS; else if(ei->adrcode==OB_TIME) ei->disptype= IPO_DISPTIME; ei->col= ipo_rainbow(a, OB_TOTIPO); if(colipo) { len= strlen(ei->name); if(len) { if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF; else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50; else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050; } } ei->icu= find_ipocurve(si->ipo, ei->adrcode); if(ei->icu) { ei->flag= ei->icu->flag; } ei++; } } void make_seq_editipo(SpaceIpo *si) { EditIpo *ei; int a; ei= si->editipo= MEM_callocN(SEQ_TOTIPO*sizeof(EditIpo), "editipo"); si->totipo= SEQ_TOTIPO; for(a=0; aname); ei->adrcode= seq_ar[a]; ei->col= ipo_rainbow(a, SEQ_TOTIPO); ei->icu= find_ipocurve(si->ipo, ei->adrcode); if(ei->icu) { ei->flag= ei->icu->flag; } else ei->flag |= IPO_VISIBLE; ei++; } } void make_cu_editipo(SpaceIpo *si) { EditIpo *ei; int a; ei= si->editipo= MEM_callocN(CU_TOTIPO*sizeof(EditIpo), "editipo"); si->totipo= CU_TOTIPO; for(a=0; aname); ei->adrcode= cu_ar[a]; ei->col= ipo_rainbow(a, CU_TOTIPO); ei->icu= find_ipocurve(si->ipo, ei->adrcode); if(ei->icu) { ei->flag= ei->icu->flag; } else ei->flag |= IPO_VISIBLE; ei++; } } void make_key_editipo(SpaceIpo *si) { Key *key; EditIpo *ei; int a; ei= si->editipo= MEM_callocN(KEY_TOTIPO*sizeof(EditIpo), "editipo"); si->totipo= KEY_TOTIPO; for(a=0; aname); ei->adrcode= key_ar[a]; ei->col= ipo_rainbow(a, KEY_TOTIPO); ei->icu= find_ipocurve(si->ipo, ei->adrcode); if(ei->icu) { ei->flag= ei->icu->flag; } else if(a==0) ei->flag |= IPO_VISIBLE; ei++; } ei= si->editipo; key= (Key *)G.sipo->from; if(key && key->type==KEY_RELATIVE) { strcpy(ei->name, "----"); } else { ei->flag |= IPO_VISIBLE; } } int texchannel_to_adrcode(int channel) { switch(channel) { case 0: return MA_MAP1; case 1: return MA_MAP2; case 2: return MA_MAP3; case 3: return MA_MAP4; case 4: return MA_MAP5; case 5: return MA_MAP6; case 6: return MA_MAP7; case 7: return MA_MAP8; default: return 0; } } void make_mat_editipo(SpaceIpo *si) { EditIpo *ei; int a, len; if(si->from==0) return; ei= si->editipo= MEM_callocN(MA_TOTIPO*sizeof(EditIpo), "editipo"); si->totipo= MA_TOTIPO; for(a=0; aname); ei->adrcode= ma_ar[a]; if(ei->adrcode & MA_MAP1) { ei->adrcode-= MA_MAP1; ei->adrcode |= texchannel_to_adrcode(si->channel); } else { if(ei->adrcode==MA_MODE) ei->disptype= IPO_DISPBITS; } ei->col= ipo_rainbow(a, WO_TOTIPO); len= strlen(ei->name); if(len) { if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF; else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50; else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050; } ei->icu= find_ipocurve(si->ipo, ei->adrcode); if(ei->icu) { ei->flag= ei->icu->flag; } ei++; } } void make_world_editipo(SpaceIpo *si) { EditIpo *ei; int a, len; if(si->from==0) return; ei= si->editipo= MEM_callocN(WO_TOTIPO*sizeof(EditIpo), "editipo"); si->totipo= WO_TOTIPO; for(a=0; aname); ei->adrcode= wo_ar[a]; if(ei->adrcode & MA_MAP1) { ei->adrcode-= MA_MAP1; ei->adrcode |= texchannel_to_adrcode(si->channel); } else { if(ei->adrcode==MA_MODE) ei->disptype= IPO_DISPBITS; } ei->col= ipo_rainbow(a, MA_TOTIPO); len= strlen(ei->name); if(len) { if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF; else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50; else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050; } ei->icu= find_ipocurve(si->ipo, ei->adrcode); if(ei->icu) { ei->flag= ei->icu->flag; } ei++; } } void make_lamp_editipo(SpaceIpo *si) { EditIpo *ei; int a; ei= si->editipo= MEM_callocN(LA_TOTIPO*sizeof(EditIpo), "editipo"); si->totipo= LA_TOTIPO; for(a=0; aname); ei->adrcode= la_ar[a]; if(ei->adrcode & MA_MAP1) { ei->adrcode-= MA_MAP1; ei->adrcode |= texchannel_to_adrcode(si->channel); } ei->col= ipo_rainbow(a, LA_TOTIPO); ei->icu= find_ipocurve(si->ipo, ei->adrcode); if(ei->icu) { ei->flag= ei->icu->flag; } ei++; } } void make_camera_editipo(SpaceIpo *si) { EditIpo *ei; int a; ei= si->editipo= MEM_callocN(CAM_TOTIPO*sizeof(EditIpo), "editipo"); si->totipo= CAM_TOTIPO; for(a=0; aname); ei->adrcode= cam_ar[a]; ei->col= ipo_rainbow(a, CAM_TOTIPO); ei->icu= find_ipocurve(si->ipo, ei->adrcode); if(ei->icu) { ei->flag= ei->icu->flag; } ei++; } } int make_constraint_editipo(Ipo *ipo, EditIpo **si) { EditIpo *ei; int a; ei= *si= MEM_callocN(CO_TOTIPO*sizeof(EditIpo), "editipo"); for(a=0; aname); ei->adrcode= co_ar[a]; ei->col= ipo_rainbow(a, CO_TOTIPO); ei->icu= find_ipocurve(ipo, ei->adrcode); if(ei->icu) { ei->flag= ei->icu->flag; } ei++; } return CO_TOTIPO; } int make_action_editipo(Ipo *ipo, EditIpo **si) { EditIpo *ei; int a; ei= *si= MEM_callocN(AC_TOTIPO*sizeof(EditIpo), "editipo"); for(a=0; aname); ei->adrcode= ac_ar[a]; ei->col= ipo_rainbow(a, AC_TOTIPO); ei->icu= find_ipocurve(ipo, ei->adrcode); if(ei->icu) { ei->flag= ei->icu->flag; } ei++; } return AC_TOTIPO; } void make_sound_editipo(SpaceIpo *si) { EditIpo *ei; int a; ei= si->editipo= MEM_callocN(SND_TOTIPO*sizeof(EditIpo), "editipo"); si->totipo= SND_TOTIPO; for(a=0; aname); ei->adrcode= snd_ar[a]; ei->col= ipo_rainbow(a, SND_TOTIPO); ei->icu= find_ipocurve(si->ipo, ei->adrcode); if(ei->icu) { ei->flag= ei->icu->flag; } ei++; } } void make_editipo() { EditIpo *ei; Object *ob; ID *from; rctf *rf; int a; if(G.sipo->editipo) MEM_freeN(G.sipo->editipo); G.sipo->editipo= 0; G.sipo->totipo= 0; ob= OBACT; G.sipo->ipo= get_ipo_to_edit(&from); G.sipo->from= from; if(G.sipo->ipo) G.sipo->showkey= G.sipo->ipo->showkey; if(G.sipo->blocktype==ID_SEQ) { make_seq_editipo(G.sipo); } else if(G.sipo->blocktype==ID_WO) { make_world_editipo(G.sipo); } else if(G.sipo->blocktype==ID_OB) { if (ob) { ob->ipowin= ID_OB; make_ob_editipo(ob, G.sipo); } } else if(G.sipo->blocktype==ID_MA) { if (ob) { ob->ipowin= ID_MA; make_mat_editipo(G.sipo); } } else if(G.sipo->blocktype==ID_CU) { if (ob) { ob->ipowin= ID_CU; make_cu_editipo(G.sipo); } } else if(G.sipo->blocktype==ID_KE) { if (ob) { ob->ipowin= ID_KE; make_key_editipo(G.sipo); } } else if(G.sipo->blocktype==ID_LA) { if (ob) { ob->ipowin= ID_LA; make_lamp_editipo(G.sipo); } } else if(G.sipo->blocktype==ID_CA) { if (ob) { ob->ipowin= ID_CA; make_camera_editipo(G.sipo); } } else if(G.sipo->blocktype==ID_SO) { if (ob) { ob->ipowin= ID_SO; make_sound_editipo(G.sipo); } } else if(G.sipo->blocktype==IPO_CO){ G.sipo->totipo = make_constraint_editipo(G.sipo->ipo, (EditIpo**)&G.sipo->editipo); if (ob) { ob->ipowin= IPO_CO; } } else if(G.sipo->blocktype==ID_AC) { G.sipo->totipo = make_action_editipo(G.sipo->ipo, (EditIpo**)&G.sipo->editipo); if (ob) { ob->ipowin= ID_AC; } } if(G.sipo->editipo==0) return; /* rowbut for VISIBLE select */ G.sipo->rowbut= 0; ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if(ei->flag & IPO_VISIBLE) G.sipo->rowbut |= (1<icu) ei->icu->flag= ei->flag; } editipo_changed(G.sipo, 0); if(G.sipo->ipo) { if (G.sipo->pin) rf= &(G.sipo->v2d.cur); else rf= &(G.sipo->ipo->cur); if(rf->xminxmax && rf->yminymax) G.v2d->cur= *rf; } else { if(G.sipo->blocktype==ID_OB) { G.v2d->cur.xmin= 0.0; G.v2d->cur.xmax= EFRA; G.v2d->cur.ymin= -5.0; G.v2d->cur.ymax= +5.0; } else if(G.sipo->blocktype==ID_CA) { G.v2d->cur.xmin= 0.0; G.v2d->cur.xmax= EFRA; G.v2d->cur.ymin= 0.0; G.v2d->cur.ymax= 100.0; } else if ELEM5(G.sipo->blocktype, ID_MA, ID_CU, ID_WO, ID_LA, IPO_CO) { G.v2d->cur.xmin= (float)-0.1; G.v2d->cur.xmax= EFRA; G.v2d->cur.ymin= (float)-0.1; G.v2d->cur.ymax= (float)+1.1; } else if(G.sipo->blocktype==ID_SEQ) { G.v2d->cur.xmin= -5.0; G.v2d->cur.xmax= 105.0; G.v2d->cur.ymin= (float)-0.1; G.v2d->cur.ymax= (float)+1.1; } else if(G.sipo->blocktype==ID_KE) { G.v2d->cur.xmin= (float)-0.1; G.v2d->cur.xmax= EFRA; G.v2d->cur.ymin= (float)-0.1; G.v2d->cur.ymax= (float)+2.1; } } } void test_editipo() { Ipo *ipo; ID *from; if(G.sipo->editipo==0){ make_editipo(); } else { ipo= get_ipo_to_edit(&from); if(G.sipo->ipo != ipo || G.sipo->from!=from) make_editipo(); } if (G.sipo->pin) return; if(G.sipo->ipo) G.sipo->ipo->cur = G.v2d->cur; } /* ****************************************** */ int totipo_edit, totipo_sel, totipo_vis, totipo_vert, totipo_vertsel, totipo_key, totipo_keysel; void get_status_editipo() { EditIpo *ei; IpoKey *ik; BezTriple *bezt; int a, b; totipo_vis= 0; totipo_sel= 0; totipo_edit= 0; totipo_vert= 0; totipo_vertsel= 0; totipo_key= 0; totipo_keysel= 0; if(G.sipo->ipo && G.sipo->ipo->id.lib) return; ei= G.sipo->editipo; if(ei==0) return; for(a=0; atotipo; a++) { if( ei->flag & IPO_VISIBLE ) { totipo_vis++; if(ei->flag & IPO_SELECT) totipo_sel++; if(G.sipo->showkey || (ei->flag & IPO_EDIT)) { /* if showkey: do count the vertices (for grab) */ if(G.sipo->showkey==0) totipo_edit++; if(ei->icu) { if(ei->icu->bezt) { bezt= ei->icu->bezt; b= ei->icu->totvert; while(b--) { if(ei->icu->ipo==IPO_BEZ) { if(bezt->f1 & 1) totipo_vertsel++; if(bezt->f3 & 1) totipo_vertsel++; totipo_vert+= 2; } if(bezt->f2 & 1) totipo_vertsel++; totipo_vert++; bezt++; } } } } } ei++; } if(G.sipo->showkey) { ik= G.sipo->ipokey.first; while(ik) { totipo_key++; if(ik->flag & 1) totipo_keysel++; ik= ik->next; } } } void update_editipo_flags() { EditIpo *ei; IpoKey *ik; unsigned int flag; int a; ei= G.sipo->editipo; if(ei) { for(a=0; atotipo; a++, ei++) { ei->flag &= ~IPO_VISIBLE; flag= (1<rowbut & flag ) ei->flag |= IPO_VISIBLE; if(ei->icu) ei->icu->flag= ei->flag; } } if(G.sipo->showkey) { ik= G.sipo->ipokey.first; while(ik) { for(a=0; atotipo; a++) { if(ik->data[a]) { if(ik->flag & 1) { ik->data[a]->f1 |= 1; ik->data[a]->f2 |= 1; ik->data[a]->f3 |= 1; } else { ik->data[a]->f1 &= ~1; ik->data[a]->f2 &= ~1; ik->data[a]->f3 &= ~1; } } } ik= ik->next; } } } void set_editflag_editipo() { EditIpo *ei; int a; /* , tot= 0, ok= 0; */ /* after showkey immediately go to editing of selected points */ if(G.sipo->showkey) { G.sipo->showkey= 0; if(G.sipo->ipo) G.sipo->ipo->showkey= 0; ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) ei->flag |= IPO_SELECT; scrarea_queue_headredraw(curarea); allqueue(REDRAWVIEW3D, 0); } get_status_editipo(); if(G.sipo->ipo && G.sipo->ipo->id.lib) return; ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if(ei->icu) { if(ei->flag & IPO_VISIBLE) { if(totipo_edit==0 && (ei->flag & IPO_SELECT)) { ei->flag |= IPO_EDIT; ei->icu->flag= ei->flag; } else if(totipo_edit && (ei->flag & IPO_EDIT)) { ei->flag -= IPO_EDIT; ei->icu->flag= ei->flag; } else if(totipo_vis==1) { if(ei->flag & IPO_EDIT) ei->flag -= IPO_EDIT; else ei->flag |= IPO_EDIT; ei->icu->flag= ei->flag; } } } } scrarea_queue_headredraw(curarea); scrarea_queue_winredraw(curarea); } void ipo_toggle_showkey(void) { if(G.sipo->showkey) { G.sipo->showkey= 0; swap_selectall_editipo(); /* sel all */ } else G.sipo->showkey= 1; free_ipokey(&G.sipo->ipokey); if(G.sipo->ipo) G.sipo->ipo->showkey= G.sipo->showkey; } void swap_selectall_editipo() { Object *ob; EditIpo *ei; IpoKey *ik; BezTriple *bezt; int a, b; /* , sel=0; */ deselectall_key(); get_status_editipo(); if(G.sipo->showkey) { ik= G.sipo->ipokey.first; while(ik) { if(totipo_vertsel) ik->flag &= ~1; else ik->flag |= 1; ik= ik->next; } update_editipo_flags(); if(G.sipo->showkey && G.sipo->blocktype==ID_OB ) { ob= OBACT; if(ob && (ob->ipoflag & OB_DRAWKEY)) draw_object_ext(BASACT); } } else if(totipo_edit==0) { ei= G.sipo->editipo; if (ei){ for(a=0; atotipo; a++) { if( ei->flag & IPO_VISIBLE ) { if(totipo_sel) ei->flag &= ~IPO_SELECT; else ei->flag |= IPO_SELECT; } ei++; } update_editipo_flags(); } } else { ei= G.sipo->editipo; for(a=0; atotipo; a++) { if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu ) { bezt= ei->icu->bezt; if(bezt) { b= ei->icu->totvert; while(b--) { if(totipo_vertsel) { bezt->f1= bezt->f2= bezt->f3= 0; } else { bezt->f1= bezt->f2= bezt->f3= 1; } bezt++; } } } ei++; } } scrarea_queue_winredraw(curarea); } void swap_visible_editipo() { EditIpo *ei; Object *ob; int a; /* , sel=0; */ get_status_editipo(); G.sipo->rowbut= 0; ei= G.sipo->editipo; for(a=0; atotipo; a++) { if(totipo_vis==0) { if(ei->icu) { ei->flag |= IPO_VISIBLE; G.sipo->rowbut |= (1<flag &= ~IPO_VISIBLE; ei++; } update_editipo_flags(); if(G.sipo->showkey) { make_ipokey(); ob= OBACT; if(ob && (ob->ipoflag & OB_DRAWKEY)) allqueue(REDRAWVIEW3D, 0); } scrarea_queue_winredraw(curarea); } void deselectall_editipo() { EditIpo *ei; IpoKey *ik; BezTriple *bezt; int a, b; /* , sel=0; */ deselectall_key(); get_status_editipo(); if(G.sipo->showkey) { ik= G.sipo->ipokey.first; while(ik) { ik->flag &= ~1; ik= ik->next; } update_editipo_flags(); } else if(totipo_edit==0) { ei= G.sipo->editipo; for(a=0; atotipo; a++) { if( ei->flag & IPO_VISIBLE ) { ei->flag &= ~IPO_SELECT; } ei++; } update_editipo_flags(); } else { ei= G.sipo->editipo; for(a=0; atotipo; a++) { if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu ) { if(ei->icu->bezt) { bezt= ei->icu->bezt; b= ei->icu->totvert; while(b--) { bezt->f1= bezt->f2= bezt->f3= 0; bezt++; } } } ei++; } } scrarea_queue_winredraw(curarea); } short findnearest_ipovert(IpoCurve **icu, BezTriple **bezt) { /* selected verts get a disadvantage */ /* in icu and (bezt or bp) the nearest is written */ /* return 0 1 2: handlepunt */ EditIpo *ei; BezTriple *bezt1; int a, b; short dist= 100, temp, mval[2], hpoint=0; *icu= 0; *bezt= 0; getmouseco_areawin(mval); ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu) { if(ei->icu->bezt) { bezt1= ei->icu->bezt; b= ei->icu->totvert; while(b--) { ipoco_to_areaco_noclip(G.v2d, bezt1->vec[0], bezt1->s[0]); ipoco_to_areaco_noclip(G.v2d, bezt1->vec[1], bezt1->s[1]); ipoco_to_areaco_noclip(G.v2d, bezt1->vec[2], bezt1->s[2]); if(ei->disptype==IPO_DISPBITS) { temp= abs(mval[0]- bezt1->s[1][0]); } else temp= abs(mval[0]- bezt1->s[1][0])+ abs(mval[1]- bezt1->s[1][1]); if( bezt1->f2 & 1) temp+=5; if(tempicu; } if(ei->disptype!=IPO_DISPBITS && ei->icu->ipo==IPO_BEZ) { /* middle points get an advantage */ temp= -3+abs(mval[0]- bezt1->s[0][0])+ abs(mval[1]- bezt1->s[0][1]); if( bezt1->f1 & 1) temp+=5; if(tempicu; } temp= abs(mval[0]- bezt1->s[2][0])+ abs(mval[1]- bezt1->s[2][1]); if( bezt1->f3 & 1) temp+=5; if(tempicu; } } bezt1++; } } } } return hpoint; } void move_to_frame() { EditIpo *ei; BezTriple *bezt; ID *id; float cfra; int a, b; if(G.sipo->editipo==0) return; ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if ISPOIN(ei, flag & IPO_VISIBLE, icu) { if(G.sipo->showkey || (ei->flag & IPO_EDIT)) { if(ei->icu->bezt) { b= ei->icu->totvert; bezt= ei->icu->bezt; while(b--) { if(BEZSELECTED(bezt)) { cfra= bezt->vec[1][0]/G.scene->r.framelen; id= G.sipo->from; if(id && GS(id->name)==ID_OB ) { Object *ob= (Object *)id; if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) { cfra+= ob->sf/G.scene->r.framelen; } } CFRA= (short)floor(cfra+0.5); if(CFRA < 1) CFRA= 1; update_for_newframe(); break; } bezt++; } } } } } } /* *********************************** */ void do_ipowin_buts(short event) { if((G.qual & LR_SHIFTKEY)==0) { G.sipo->rowbut= (1<showkey) { make_ipokey(); if(G.sipo->blocktype==ID_OB) allqueue(REDRAWVIEW3D, 0); } } void do_ipo_selectbuttons() { EditIpo *ei, *ei1; int a, nr; short mval[2]; if(G.sipo->showkey) return; /* do not allow editipo here: convert editipos to selected */ get_status_editipo(); if(totipo_edit) { set_editflag_editipo(); } /* which */ getmouseco_areawin(mval); nr= -(mval[1]-curarea->winy+30-G.sipo->butofs-IPOBUTY)/IPOBUTY; if(nr>=0 && nrtotipo) { ei= G.sipo->editipo; ei+= nr; if(ei->icu) { if((ei->flag & IPO_VISIBLE)==0) { ei->flag |= IPO_VISIBLE; G.sipo->rowbut |= (1<editipo; for(a=0; atotipo; a++) { ei1->flag &= ~IPO_SELECT; ei1++; } } if(ei->flag & IPO_SELECT) { ei->flag &= ~IPO_SELECT; } else { ei->flag |= IPO_SELECT; } update_editipo_flags(); scrarea_queue_winredraw(curarea); } } } /* ******************************************* */ EditIpo *get_editipo() { EditIpo *ei; int a; /* , sel=0; */ get_status_editipo(); if(totipo_edit>1) { return 0; } if(G.sipo->editipo==0) return 0; ei= G.sipo->editipo; for(a=0; atotipo; a++) { if(ei->flag & IPO_VISIBLE) { if( ei->flag & IPO_EDIT ) return ei; else if(totipo_vis==1) return ei; if(ei->flag & IPO_SELECT) { if(totipo_sel==1) return ei; } } ei++; } return 0; } Ipo *get_ipo(ID *from, short type, int make) { Object *ob; Material *ma; Curve *cu; Sequence *seq; Key *key; World *wo; Lamp *la; Camera *ca; Ipo *ipo= 0; bAction *act; if( type==ID_OB) { ob= (Object *)from; if(ob->id.lib) return 0; ipo= ob->ipo; if(make && ipo==0) ipo= ob->ipo= add_ipo("ObIpo", ID_OB); } else if( type==IPO_CO){ ob= (Object *)from; if(ob->id.lib) return 0; if (ob->activecon){ ipo= ob->activecon->ipo; if(make && ipo==0) ipo= ob->activecon->ipo= add_ipo("CoIpo", IPO_CO); } } else if( type==ID_AC) { act= (bAction *)from; if (!act->achan) return 0; if (act->id.lib) return 0; ipo= act->achan->ipo; /* This should never happen */ if(make && ipo==0) ipo= act->achan->ipo= add_ipo("AcIpo", ID_AC); } else if( type==ID_MA) { ma= (Material *)from; if(ma->id.lib) return 0; ipo= ma->ipo; if(make && ipo==0) ipo= ma->ipo= add_ipo("MatIpo", ID_MA); } else if( type==ID_SEQ) { seq= (Sequence *)from; if((seq->type & SEQ_EFFECT)||(seq->type == SEQ_SOUND)) { ipo= seq->ipo; if(make && ipo==0) ipo= seq->ipo= add_ipo("SeqIpo", ID_SEQ); } else return 0; } else if( type==ID_CU) { cu= (Curve *)from; if(cu->id.lib) return 0; ipo= cu->ipo; if(make && ipo==0) ipo= cu->ipo= add_ipo("CuIpo", ID_CU); } else if( type==ID_KE) { key= (Key *)from; if(key->id.lib) return 0; ipo= key->ipo; if(make && ipo==0) ipo= key->ipo= add_ipo("KeyIpo", ID_KE); } else if( type==ID_WO) { wo= (World *)from; if(wo->id.lib) return 0; ipo= wo->ipo; if(make && ipo==0) ipo= wo->ipo= add_ipo("WoIpo", ID_WO); } else if( type==ID_LA) { la= (Lamp *)from; if(la->id.lib) return 0; ipo= la->ipo; if(make && ipo==0) ipo= la->ipo= add_ipo("LaIpo", ID_LA); } else if( type==ID_CA) { ca= (Camera *)from; if(ca->id.lib) return 0; ipo= ca->ipo; if(make && ipo==0) ipo= ca->ipo= add_ipo("CaIpo", ID_CA); } else if( type==ID_SO) { bSound *snd= (bSound *)from; if(snd->id.lib) return 0; ipo= snd->ipo; if(make && ipo==0) ipo= snd->ipo= add_ipo("SndIpo", ID_SO); } else return 0; return ipo; } // this function should not have the G.sipo in it... IpoCurve *get_ipocurve(ID *from, short type, int adrcode, Ipo *useipo) { Ipo *ipo= 0; IpoCurve *icu=0; /* return 0 if lib */ /* also test if ipo and ipocurve exist */ if (useipo==NULL) { if (G.sipo==NULL || G.sipo->pin==0){ ipo= get_ipo(from, type, 1); /* 1= make */ } else ipo = G.sipo->ipo; if(G.sipo) { if (G.sipo->pin==0) G.sipo->ipo= ipo; } } else ipo= useipo; if(ipo && ipo->id.lib==0) { icu= ipo->curve.first; while(icu) { if(icu->adrcode==adrcode) break; icu= icu->next; } if(icu==0) { icu= MEM_callocN(sizeof(IpoCurve), "ipocurve"); icu->flag |= IPO_VISIBLE; if (!useipo && G.sipo && G.sipo->pin) icu->blocktype = G.sipo->blocktype; else icu->blocktype= type; icu->adrcode= adrcode; set_icu_vars(icu); BLI_addtail( &(ipo->curve), icu); } } return icu; } void insert_vert_ipo(IpoCurve *icu, float x, float y) { BezTriple *bezt, beztr, *newbezt; int a = 0, h1, h2; memset(&beztr, 0, sizeof(BezTriple)); beztr.vec[1][0]= x; beztr.vec[1][1]= y; beztr.hide= IPO_BEZ; beztr.f1= beztr.f2= beztr.f3= SELECT; beztr.h1= beztr.h2= HD_AUTO; bezt= icu->bezt; if(bezt==0) { icu->bezt= MEM_callocN( sizeof(BezTriple), "beztriple"); *(icu->bezt)= beztr; icu->totvert= 1; } else { /* all vertices deselect */ for(a=0; atotvert; a++, bezt++) { bezt->f1= bezt->f2= bezt->f3= 0; } bezt= icu->bezt; for(a=0; a<=icu->totvert; a++, bezt++) { /* no double points */ if(atotvert && (bezt->vec[1][0]>x-IPOTHRESH && bezt->vec[1][0]totvert || bezt->vec[1][0] > x) { newbezt= MEM_callocN( (icu->totvert+1)*sizeof(BezTriple), "beztriple"); if(a>0) memcpy(newbezt, icu->bezt, a*sizeof(BezTriple)); bezt= newbezt+a; *(bezt)= beztr; if(atotvert) memcpy(newbezt+a+1, icu->bezt+a, (icu->totvert-a)*sizeof(BezTriple)); MEM_freeN(icu->bezt); icu->bezt= newbezt; icu->totvert++; break; } } } calchandles_ipocurve(icu); /* set handletype */ if(icu->totvert>2) { h1= h2= HD_AUTO; if(a>0) h1= (bezt-1)->h2; if(atotvert-1) h2= (bezt+1)->h1; bezt->h1= h1; bezt->h2= h2; calchandles_ipocurve(icu); } } void add_vert_ipo() { EditIpo *ei; float x, y; int val; short mval[2]; if(G.sipo->ipo && G.sipo->ipo->id.lib) return; if(G.sipo->showkey) { G.sipo->showkey= 0; free_ipokey(&G.sipo->ipokey); } getmouseco_areawin(mval); if(mval[0]>G.v2d->mask.xmax) return; ei= get_editipo(); if(ei==0) { error("Too many editipo's"); return; } areamouseco_to_ipoco(G.v2d, mval, &x, &y); if(ei->icu==0) { if(G.sipo->from) ei->icu= get_ipocurve(G.sipo->from, G.sipo->blocktype, ei->adrcode, 0); } if(ei->icu==0) return; if(ei->disptype==IPO_DISPBITS) { ei->icu->vartype= IPO_BITS; val= (int)floor(y-0.5); if(val<0) val= 0; y= (float)(1 << val); } insert_vert_ipo(ei->icu, x, y); /* to be sure: if icu was 0, or only 1 curve visible */ ei->flag |= IPO_SELECT; ei->icu->flag= ei->flag; editipo_changed(G.sipo, 1); } void add_duplicate_editipo() { Object *ob; EditIpo *ei; IpoCurve *icu; BezTriple *bezt, *beztn, *newb; int tot, a, b; get_status_editipo(); if(totipo_vertsel==0) return; ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) { if(G.sipo->showkey || (ei->flag & IPO_EDIT)) { icu= ei->icu; /* how many points */ tot= 0; b= icu->totvert; bezt= icu->bezt; while(b--) { if(bezt->f2 & 1) tot++; bezt++; } if(tot) { icu->totvert+= tot; newb= beztn= MEM_mallocN(icu->totvert*sizeof(BezTriple), "bezt"); bezt= icu->bezt; b= icu->totvert-tot; while(b--) { *beztn= *bezt; if(bezt->f2 & 1) { beztn->f1= beztn->f2= beztn->f3= 0; beztn++; *beztn= *bezt; } beztn++; bezt++; } MEM_freeN(icu->bezt); icu->bezt= newb; calchandles_ipocurve(icu); } } } } if(G.sipo->showkey) { make_ipokey(); if(G.sipo->blocktype==ID_OB) { ob= OBACT; if(ob && (ob->ipoflag & OB_DRAWKEY)) allqueue(REDRAWVIEW3D, 0); } } transform_ipo('g'); } void remove_doubles_ipo() { EditIpo *ei; IpoKey *ik, *ikn; BezTriple *bezt, *newb, *new1; float val; int mode, a, b; ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) { /* OR the curve is selected OR in editmode OR in keymode */ mode= 0; if(G.sipo->showkey || (ei->flag & IPO_EDIT)) mode= 1; else if(ei->flag & IPO_SELECT) mode= 2; if(mode) { bezt= ei->icu->bezt; newb= new1= MEM_mallocN(ei->icu->totvert*sizeof(BezTriple), "newbezt"); *newb= *bezt; b= ei->icu->totvert-1; bezt++; while(b--) { /* can we remove? */ if(mode==2 || (bezt->f2 & 1)) { /* are the points different? */ if( fabs( bezt->vec[1][0]-newb->vec[1][0] ) > 0.9 ) { newb++; *newb= *bezt; } else { /* median */ VecMidf(newb->vec[0], newb->vec[0], bezt->vec[0]); VecMidf(newb->vec[1], newb->vec[1], bezt->vec[1]); VecMidf(newb->vec[2], newb->vec[2], bezt->vec[2]); newb->h1= newb->h2= HD_FREE; ei->icu->totvert--; } } else { newb++; *newb= *bezt; } bezt++; } MEM_freeN(ei->icu->bezt); ei->icu->bezt= new1; calchandles_ipocurve(ei->icu); } } } editipo_changed(G.sipo, 1); /* makes ipokeys again! */ /* remove double keys */ if(G.sipo->showkey) { ik= G.sipo->ipokey.first; ikn= ik->next; while(ik && ikn) { if( (ik->flag & 1) && (ikn->flag & 1) ) { if( fabs(ik->val-ikn->val) < 0.9 ) { val= (float)((ik->val + ikn->val)/2.0); for(a=0; atotipo; a++) { if(ik->data[a]) ik->data[a]->vec[1][0]= val; if(ikn->data[a]) ikn->data[a]->vec[1][0]= val; } } } ik= ikn; ikn= ikn->next; } editipo_changed(G.sipo, 1); /* makes ipokeys agian! */ } deselectall_editipo(); } void join_ipo() { EditIpo *ei; IpoKey *ik; IpoCurve *icu; BezTriple *bezt, *beztn, *newb; float val; int mode, tot, a, b; get_status_editipo(); mode= pupmenu("Join %t|All Selected %x1|Selected doubles %x2"); if( mode==2 ) { remove_doubles_ipo(); return; } else if(mode!=1) return; /* first: multiple selected verts in 1 curve */ ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) { if(G.sipo->showkey || (ei->flag & IPO_EDIT)) { icu= ei->icu; /* how many points */ tot= 0; b= icu->totvert; bezt= icu->bezt; while(b--) { if(bezt->f2 & 1) tot++; bezt++; } if(tot>1) { tot--; icu->totvert-= tot; newb= MEM_mallocN(icu->totvert*sizeof(BezTriple), "bezt"); /* the first point is the new one */ beztn= newb+1; tot= 0; bezt= icu->bezt; b= icu->totvert+tot+1; while(b--) { if(bezt->f2 & 1) { if(tot==0) *newb= *bezt; else { VecAddf(newb->vec[0], newb->vec[0], bezt->vec[0]); VecAddf(newb->vec[1], newb->vec[1], bezt->vec[1]); VecAddf(newb->vec[2], newb->vec[2], bezt->vec[2]); } tot++; } else { *beztn= *bezt; beztn++; } bezt++; } VecMulf(newb->vec[0], (float)(1.0/((float)tot))); VecMulf(newb->vec[1], (float)(1.0/((float)tot))); VecMulf(newb->vec[2], (float)(1.0/((float)tot))); MEM_freeN(icu->bezt); icu->bezt= newb; sort_time_ipocurve(icu); calchandles_ipocurve(icu); } } } } /* next: in keymode: join multiple selected keys */ editipo_changed(G.sipo, 1); /* makes ipokeys again! */ if(G.sipo->showkey) { ik= G.sipo->ipokey.first; val= 0.0; tot= 0; while(ik) { if(ik->flag & 1) { for(a=0; atotipo; a++) { if(ik->data[a]) { val+= ik->data[a]->vec[1][0]; break; } } tot++; } ik= ik->next; } if(tot>1) { val/= (float)tot; ik= G.sipo->ipokey.first; while(ik) { if(ik->flag & 1) { for(a=0; atotipo; a++) { if(ik->data[a]) { ik->data[a]->vec[1][0]= val; } } } ik= ik->next; } editipo_changed(G.sipo, 0); } } deselectall_editipo(); } void ipo_snapmenu() { EditIpo *ei; BezTriple *bezt; float dx = 0.0; int a, b; short event, ok, ok2; event= pupmenu("Snap %t|Horizontal %x1|To next %x2|To frame %x3|To current frame%x4"); if(event < 1) return; get_status_editipo(); ei= G.sipo->editipo; for(b=0; btotipo; b++, ei++) { if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) { ok2= 0; if(G.sipo->showkey) ok2= 1; else if(totipo_vert && (ei->flag & IPO_EDIT)) ok2= 2; else if(totipo_vert==0 && (ei->flag & IPO_SELECT)) ok2= 3; if(ok2) { bezt= ei->icu->bezt; a= ei->icu->totvert; while(a--) { ok= 0; if(totipo_vert) { if(bezt->f2 & 1) ok= 1; } else ok= 1; if(ok) { if(event==1) { bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1]; if(bezt->h1==HD_AUTO || bezt->h1==HD_VECT) bezt->h1= HD_ALIGN; if(bezt->h2==HD_AUTO || bezt->h2==HD_VECT) bezt->h2= HD_ALIGN; } else if(event==2) { if(a) { bezt->vec[0][1]= bezt->vec[1][1]= bezt->vec[2][1]= (bezt+1)->vec[1][1]; if(bezt->h1==HD_AUTO || bezt->h1==HD_VECT) bezt->h1= HD_ALIGN; if(bezt->h2==HD_AUTO || bezt->h2==HD_VECT) bezt->h2= HD_ALIGN; } } else if(event==3) { bezt->vec[1][0]= (float)(floor(bezt->vec[1][0]+0.5)); } else if(event==4) { /* to current frame */ if(ok2==1 || ok2==2) { if(G.sipo->blocktype==ID_SEQ) { Sequence *seq; seq= (Sequence *)G.sipo->from; if(seq) { dx= (float)(CFRA-seq->startdisp); dx= (float)(100.0*dx/((float)(seq->enddisp-seq->startdisp))); dx-= bezt->vec[1][0]; } } else dx= G.scene->r.framelen*CFRA - bezt->vec[1][0]; bezt->vec[0][0]+= dx; bezt->vec[1][0]+= dx; bezt->vec[2][0]+= dx; } } } bezt++; } calchandles_ipocurve(ei->icu); } } } editipo_changed(G.sipo, 1); } void mouse_select_ipo() { Object *ob; EditIpo *ei, *actei= 0; IpoCurve *icu; IpoKey *ik, *actik; BezTriple *bezt; Key *key; KeyBlock *kb, *actkb=0; float x, y, dist, mindist; int a, oldflag = 0, hand, ok; short mval[2], xo, yo; if(G.sipo->editipo==0) return; get_status_editipo(); if(G.sipo->showkey) { getmouseco_areawin(mval); areamouseco_to_ipoco(G.v2d, mval, &x, &y); actik= 0; mindist= 1000.0; ik= G.sipo->ipokey.first; while(ik) { dist= (float)(fabs(ik->val-x)); if(ik->flag & 1) dist+= 1.0; if(dist < mindist) { actik= ik; mindist= dist; } ik= ik->next; } if(actik) { oldflag= actik->flag; if(G.qual & LR_SHIFTKEY); else deselectall_editipo(); if(G.qual & LR_SHIFTKEY) { if(oldflag & 1) actik->flag &= ~1; else actik->flag |= 1; } else { actik->flag |= 1; } } } else if(totipo_edit) { hand= findnearest_ipovert(&icu, &bezt); if(G.qual & LR_SHIFTKEY) { if(bezt) { if(hand==1) { if(BEZSELECTED(bezt)) { bezt->f1= bezt->f2= bezt->f3= 0; } else { bezt->f1= bezt->f2= bezt->f3= 1; } } else if(hand==0) { if(bezt->f1 & 1) bezt->f1= 0; else bezt->f1= 1; } else { if(bezt->f3 & 1) bezt->f3= 0; else bezt->f3= 1; } } } else { deselectall_editipo(); if(bezt) { if(hand==1) { bezt->f1|= 1; bezt->f2|= 1; bezt->f3|= 1; } else if(hand==0) bezt->f1|= 1; else bezt->f3|= 1; } } } else { /* vertex keys ? */ if(G.sipo->blocktype==ID_KE && G.sipo->from) { key= (Key *)G.sipo->from; ei= G.sipo->editipo; if(key->type==KEY_NORMAL || (ei->flag & IPO_VISIBLE)) { getmouseco_areawin(mval); areamouseco_to_ipoco(G.v2d, mval, &x, &y); /* how much is 20 pixels? */ mindist= (float)(20.0*(G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)curarea->winy); kb= key->block.first; while(kb) { dist= (float)(fabs(kb->pos-y)); if(kb->flag & SELECT) dist+= (float)0.01; if(dist < mindist) { actkb= kb; mindist= dist; } kb= kb->next; } if(actkb) { ok= TRUE; if(G.obedit && (actkb->flag & 1)==0) { ok= okee("Copy Key after leaving EditMode"); } if(ok) { /* also does all keypos */ deselectall_editipo(); actkb->flag |= 1; /* calc keypos */ showkeypos((Key *)G.sipo->from, actkb); } } } } /* select curve */ if(actkb==0) { if(totipo_vis==1) { ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if(ei->icu) { if(ei->flag & IPO_VISIBLE) actei= ei; } } } else if(totipo_vis>1) { actei= select_proj_ipo(0, 0); } if(actei) oldflag= actei->flag; if(G.qual & LR_SHIFTKEY); else deselectall_editipo(); if(actei) { if(G.qual & LR_SHIFTKEY) { if(oldflag & IPO_SELECT) actei->flag &= ~IPO_SELECT; else actei->flag |= IPO_SELECT; } else { actei->flag |= IPO_SELECT; } } } } update_editipo_flags(); force_draw(); if(G.sipo->showkey && G.sipo->blocktype==ID_OB) { ob= OBACT; if(ob && (ob->ipoflag & OB_DRAWKEY)) draw_object_ext(BASACT); } getmouseco_areawin(mval); xo= mval[0]; yo= mval[1]; while(get_mbut()&R_MOUSE) { getmouseco_areawin(mval); if(abs(mval[0]-xo)+abs(mval[1]-yo) > 4) { if(actkb) move_keys(); else transform_ipo('g'); return; } BIF_wait_for_statechange(); } } int icu_keys_bezier_loop(IpoCurve *icu, int (*bezier_function)(BezTriple *), void (ipocurve_function)(struct IpoCurve *icu)) { /* This loops through the beziers in the Ipocurve, and executes * the generic user provided 'bezier_function' on each one. * Optionally executes the generic function ipocurve_function on the * IPO curve after looping (eg. calchandles_ipocurve) */ int b; BezTriple *bezt; b = icu->totvert; bezt = icu->bezt; /* if bezier_function has been specified * then loop through each bezier executing * it. */ if (bezier_function != NULL) { while(b--) { /* exit with return code 1 if the bezier function * returns 1 (good for when you are only interested * in finding the first bezier that * satisfies a condition). */ if (bezier_function(bezt)) return 1; bezt++; } } /* if ipocurve_function has been specified * then execute it */ if (ipocurve_function != NULL) ipocurve_function(icu); return 0; } int ipo_keys_bezier_loop(Ipo *ipo, int (*bezier_function)(BezTriple *), void (ipocurve_function)(struct IpoCurve *icu)) { /* This loops through the beziers that are attached to * the selected keys on the Ipocurves of the Ipo, and executes * the generic user provided 'bezier_function' on each one. * Optionally executes the generic function ipocurve_function on a * IPO curve after looping (eg. calchandles_ipocurve) */ IpoCurve *icu; /* Loop through each curve in the Ipo */ for (icu=ipo->curve.first; icu; icu=icu->next){ if (icu_keys_bezier_loop(icu,bezier_function, ipocurve_function)) return 1; } return 0; } int selected_bezier_loop(int (*looptest)(EditIpo *), int (*bezier_function)(BezTriple *), void (ipocurve_function)(struct IpoCurve *icu)) { /* This loops through the beziers that are attached to * selected keys in editmode in the IPO window, and executes * the generic user-provided 'bezier_function' on each one * that satisfies the 'looptest' function. Optionally executes * the generic function ipocurve_function on a IPO curve * after looping (eg. calchandles_ipocurve) */ EditIpo *ei; BezTriple *bezt; int a, b; /* Get the first Edit Ipo from the selected Ipos */ ei= G.sipo->editipo; /* Loop throught all of the selected Ipo's */ for(a=0; atotipo; a++, ei++) { /* Do a user provided test on the Edit Ipo * to determine whether we want to process it */ if (looptest(ei)) { /* Loop through the selected * beziers on the Edit Ipo */ bezt = ei->icu->bezt; b = ei->icu->totvert; /* if bezier_function has been specified * then loop through each bezier executing * it. */ if (bezier_function != NULL) { while(b--) { /* exit with return code 1 if the bezier function * returns 1 (good for when you are only interested * in finding the first bezier that * satisfies a condition). */ if (bezier_function(bezt)) return 1; bezt++; } } /* if ipocurve_function has been specified * then execute it */ if (ipocurve_function != NULL) ipocurve_function(ei->icu); } /* nufte flourdje zim ploopydu <-- random dutch looking comment ;) */ /* looks more like russian to me! (ton) */ } return 0; } int select_bezier_add(BezTriple *bezt) { /* Select the bezier triple */ bezt->f1 |= 1; bezt->f2 |= 1; bezt->f3 |= 1; return 0; } int select_bezier_subtract(BezTriple *bezt) { /* Deselect the bezier triple */ bezt->f1 &= ~1; bezt->f2 &= ~1; bezt->f3 &= ~1; return 0; } int select_bezier_invert(BezTriple *bezt) { /* Invert the selection for the bezier triple */ bezt->f2 ^= 1; if ( bezt->f2 & 1 ) { bezt->f1 |= 1; bezt->f3 |= 1; } else { bezt->f1 &= ~1; bezt->f3 &= ~1; } return 0; } int set_bezier_auto(BezTriple *bezt) { /* Sets the selected bezier handles to type 'auto' */ /* is a handle selected? If so * set it to type auto */ if(bezt->f1 || bezt->f3) { if(bezt->f1) bezt->h1= 1; /* the secret code for auto */ if(bezt->f3) bezt->h2= 1; /* if the handles are not of the same type, set them * to type free */ if(bezt->h1!=bezt->h2) { if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE; if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE; } } return 0; } int set_bezier_vector(BezTriple *bezt) { /* Sets the selected bezier handles to type 'vector' */ /* is a handle selected? If so * set it to type vector */ if(bezt->f1 || bezt->f3) { if(bezt->f1) bezt->h1= 2; /* the code for vector */ if(bezt->f3) bezt->h2= 2; /* if the handles are not of the same type, set them * to type free */ if(bezt->h1!=bezt->h2) { if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE; if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE; } } return 0; } int bezier_isfree(BezTriple *bezt) { /* queries whether the handle should be set * to type 'free' (I think) */ if(bezt->f1 && bezt->h1) return 1; if(bezt->f3 && bezt->h2) return 1; return 0; } int set_bezier_free(BezTriple *bezt) { /* Sets selected bezier handles to type 'free' */ if(bezt->f1) bezt->h1= HD_FREE; if(bezt->f3) bezt->h2= HD_FREE; return 0; } int set_bezier_align(BezTriple *bezt) { /* Sets selected bezier handles to type 'align' */ if(bezt->f1) bezt->h1= HD_ALIGN; if(bezt->f3) bezt->h2= HD_ALIGN; return 0; } int vis_edit_icu_bez(EditIpo *ei) { /* A 4 part test for an EditIpo : * is it a) visible * b) in edit mode * c) does it contain an Ipo Curve * d) does that ipo curve have a bezier * * (The reason why I don't just use the macro * is I need a pointer to a function.) */ return ISPOIN4(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu, icu->bezt); } void select_ipo_bezier_keys(Ipo *ipo, int selectmode) { /* Select all of the beziers in all * of the Ipo curves belonging to the * Ipo, using the selection mode. */ switch (selectmode) { case SELECT_ADD: ipo_keys_bezier_loop(ipo, select_bezier_add, NULL); break; case SELECT_SUBTRACT: ipo_keys_bezier_loop(ipo, select_bezier_subtract, NULL); break; case SELECT_INVERT: ipo_keys_bezier_loop(ipo, select_bezier_invert, NULL); break; } } void sethandles_ipo_keys(Ipo *ipo, int code) { /* this function lets you set bezier handles all to * one type for some Ipo's (e.g. with hotkeys through * the action window). */ /* code==1: set autohandle */ /* code==2: set vectorhandle */ /* als code==3 (HD_ALIGN) toggelt het, vectorhandles worden HD_FREE */ switch(code) { case 1: /*** Set to auto ***/ ipo_keys_bezier_loop(ipo, set_bezier_auto, calchandles_ipocurve); break; case 2: /*** Set to vector ***/ ipo_keys_bezier_loop(ipo, set_bezier_vector, calchandles_ipocurve); break; default: if ( ipo_keys_bezier_loop(ipo, bezier_isfree, NULL) ) { /*** Set to free ***/ ipo_keys_bezier_loop(ipo, set_bezier_free, calchandles_ipocurve); } else { /*** Set to align ***/ ipo_keys_bezier_loop(ipo, set_bezier_align, calchandles_ipocurve); } break; } } void sethandles_ipo(int code) { /* this function lets you set bezier handles all to * one type for some selected keys in edit mode in the * IPO window (e.g. with hotkeys) */ /* code==1: set autohandle */ /* code==2: set vectorhandle */ /* als code==3 (HD_ALIGN) toggelt het, vectorhandles worden HD_FREE */ if(G.sipo->ipo && G.sipo->ipo->id.lib) return; switch(code) { case 1: /*** Set to auto ***/ selected_bezier_loop(vis_edit_icu_bez, set_bezier_auto, calchandles_ipocurve); break; case 2: /*** Set to vector ***/ selected_bezier_loop(vis_edit_icu_bez, set_bezier_vector, calchandles_ipocurve); break; default: if (selected_bezier_loop(vis_edit_icu_bez, bezier_isfree, NULL) ) { /*** Set to free ***/ selected_bezier_loop(vis_edit_icu_bez, set_bezier_free, calchandles_ipocurve); } else { /*** Set to align ***/ selected_bezier_loop(vis_edit_icu_bez, set_bezier_align, calchandles_ipocurve); } break; } editipo_changed(G.sipo, 1); } void set_ipocurve_constant(struct IpoCurve *icu) { /* Sets the type of the IPO curve to constant */ icu->ipo= IPO_CONST; } void set_ipocurve_linear(struct IpoCurve *icu) { /* Sets the type of the IPO curve to linear */ icu->ipo= IPO_LIN; } void set_ipocurve_bezier(struct IpoCurve *icu) { /* Sets the type of the IPO curve to bezier */ icu->ipo= IPO_BEZ; } void setipotype_ipo(Ipo *ipo, int code) { /* Sets the type of the each ipo curve in the * Ipo to a value based on the code */ switch (code) { case 1: ipo_keys_bezier_loop(ipo, NULL, set_ipocurve_constant); break; case 2: ipo_keys_bezier_loop(ipo, NULL, set_ipocurve_linear); break; case 3: ipo_keys_bezier_loop(ipo, NULL, set_ipocurve_bezier); break; } } void set_ipotype() { EditIpo *ei; Key *key; KeyBlock *kb; int a; short event; if(G.sipo->ipo && G.sipo->ipo->id.lib) return; if(G.sipo->showkey) return; get_status_editipo(); if(G.sipo->blocktype==ID_KE && totipo_edit==0 && totipo_sel==0) { key= (Key *)G.sipo->from; if(key==0) return; event= pupmenu("Key Type %t|Linear %x1|Cardinal %x2|B spline %x3"); if(event < 1) return; kb= key->block.first; while(kb) { if(kb->flag & SELECT) { kb->type= 0; if(event==1) kb->type= KEY_LINEAR; if(event==2) kb->type= KEY_CARDINAL; if(event==3) kb->type= KEY_BSPLINE; } kb= kb->next; } } else { event= pupmenu("Ipo Type %t|Constant %x1|Linear %x2|Bezier %x3"); if(event < 1) return; ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) { if(event==1) ei->icu->ipo= IPO_CONST; else if(event==2) ei->icu->ipo= IPO_LIN; else ei->icu->ipo= IPO_BEZ; } } } scrarea_queue_winredraw(curarea); } void borderselect_ipo() { EditIpo *ei; IpoKey *ik; BezTriple *bezt; rcti rect; rctf rectf; int a, b, val; short mval[2]; get_status_editipo(); val= get_border(&rect, 3); if(val) { mval[0]= rect.xmin; mval[1]= rect.ymin; areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin); mval[0]= rect.xmax; mval[1]= rect.ymax; areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax); if(G.sipo->showkey) { ik= G.sipo->ipokey.first; while(ik) { if(rectf.xminval && rectf.xmax>ik->val) { if(val==LEFTMOUSE) ik->flag |= 1; else ik->flag &= ~1; } ik= ik->next; } update_editipo_flags(); } else if(totipo_edit==0) { if(rect.xmineditipo; for(a=0; atotipo; a++, ei++) { if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu) { if(ei->icu->bezt) { b= ei->icu->totvert; bezt= ei->icu->bezt; while(b--) { int bit= (val==LEFTMOUSE); if(BLI_in_rctf(&rectf, bezt->vec[0][0], bezt->vec[0][1])) bezt->f1 = (bezt->f1&~1) | bit; if(BLI_in_rctf(&rectf, bezt->vec[1][0], bezt->vec[1][1])) bezt->f2 = (bezt->f2&~1) | bit; if(BLI_in_rctf(&rectf, bezt->vec[2][0], bezt->vec[2][1])) bezt->f3 = (bezt->f3&~1) | bit; bezt++; } } } } } scrarea_queue_winredraw(curarea); } } void del_ipo() { EditIpo *ei; BezTriple *bezt, *bezt1; int a, b; int del, event; get_status_editipo(); if(G.sipo->ipo && G.sipo->ipo->id.lib) return; if(totipo_edit==0 && totipo_sel==0 && totipo_vertsel==0) { delete_key(); return; } if( okee("Erase selected")==0 ) return; // eerste doorloop, kunnen hele stukken weg? ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { del= 0; if(G.sipo->showkey==0 && totipo_edit==0) { if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) { del= 1; } } else { if ISPOIN(ei, flag & IPO_VISIBLE, icu) { if(G.sipo->showkey || (ei->flag & IPO_EDIT)) { if(ei->icu->bezt) { bezt= ei->icu->bezt; b= ei->icu->totvert; if(b) { while(b) { if( BEZSELECTED(bezt) ); else break; b--; bezt++; } if(b==0) del= 1; } } } } } if(del) { BLI_remlink( &(G.sipo->ipo->curve), ei->icu); if(ei->icu->bezt) MEM_freeN(ei->icu->bezt); MEM_freeN(ei->icu); ei->flag &= ~IPO_SELECT; ei->flag &= ~IPO_EDIT; ei->icu= 0; } } // tweede doorloop, kleine stukken weg: alleen curves ei= G.sipo->editipo; for(b=0; btotipo; b++, ei++) { if ISPOIN(ei, flag & IPO_VISIBLE, icu) { if(G.sipo->showkey || (ei->flag & IPO_EDIT)) { event= 0; if(ei->icu->bezt) { bezt= ei->icu->bezt; for(a=0; aicu->totvert; a++) { if( BEZSELECTED(bezt) ) { memcpy(bezt, bezt+1, (ei->icu->totvert-a-1)*sizeof(BezTriple)); ei->icu->totvert--; a--; event= 1; } else bezt++; } if(event) { bezt1 = (BezTriple*) MEM_mallocN(ei->icu->totvert * sizeof(BezTriple), "delNurb"); memcpy(bezt1, ei->icu->bezt, (ei->icu->totvert)*sizeof(BezTriple) ); MEM_freeN(ei->icu->bezt); ei->icu->bezt= bezt1; } } } } } allqueue(REDRAWNLA, 0); allqueue (REDRAWACTION, 0); allqueue(REDRAWIPO, 0); allspace(REMAKEIPO, 0); } ListBase ipocopybuf={0, 0}; int totipocopybuf=0; void free_ipocopybuf() { IpoCurve *icu; while( (icu= ipocopybuf.first) ) { if(icu->bezt) MEM_freeN(icu->bezt); BLI_remlink(&ipocopybuf, icu); MEM_freeN(icu); } totipocopybuf= 0; } void copy_editipo() { EditIpo *ei; IpoCurve *icu; int a; if(G.sipo->showkey) { error("cannot copy\n"); return; } free_ipocopybuf(); ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if ISPOIN(ei, flag & IPO_VISIBLE, icu) { if( (ei->flag & IPO_EDIT) || (ei->flag & IPO_SELECT) ) { icu= MEM_callocN(sizeof(IpoCurve), "ipocopybuf"); *icu= *(ei->icu); BLI_addtail(&ipocopybuf, icu); if(icu->bezt) { icu->bezt= MEM_mallocN(icu->totvert*sizeof(BezTriple), "ipocopybuf"); memcpy(icu->bezt, ei->icu->bezt, icu->totvert*sizeof(BezTriple)); } totipocopybuf++; } } } if(totipocopybuf==0) error("Copybuf is empty"); } void paste_editipo() { EditIpo *ei; IpoCurve *icu; int a, ok; if(G.sipo->showkey) return; if(totipocopybuf==0) return; if(G.sipo->ipo==0) return; if(G.sipo->ipo && G.sipo->ipo->id.lib) return; get_status_editipo(); if(totipo_vis==0) { error("No visible splines"); } else if(totipo_vis!=totipocopybuf && totipo_sel!=totipocopybuf) { error("Incompatible paste"); } else { /* prevent problems: splines visible that are not selected */ if(totipo_vis==totipo_sel) totipo_vis= 0; icu= ipocopybuf.first; if(icu==0) return; ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if(ei->flag & IPO_VISIBLE) { ok= 0; if(totipo_vis==totipocopybuf) ok= 1; if(totipo_sel==totipocopybuf && (ei->flag & IPO_SELECT)) ok= 1; if(ok) { ei->icu= get_ipocurve(G.sipo->from, G.sipo->blocktype, ei->adrcode, 0); if(ei->icu==0) return; if(ei->icu->bezt) MEM_freeN(ei->icu->bezt); ei->icu->bezt= 0; ei->icu->totvert= icu->totvert; ei->icu->flag= ei->flag= icu->flag; ei->icu->extrap= icu->extrap; ei->icu->ipo= icu->ipo; if(icu->bezt) { ei->icu->bezt= MEM_mallocN(icu->totvert*sizeof(BezTriple), "ipocopybuf"); memcpy(ei->icu->bezt, icu->bezt, icu->totvert*sizeof(BezTriple)); } icu= icu->next; } } } editipo_changed(G.sipo, 1); } } void set_exprap_ipo(int mode) { EditIpo *ei; int a; if(G.sipo->ipo && G.sipo->ipo->id.lib) return; /* in case of keys: always ok */ ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if ISPOIN(ei, flag & IPO_VISIBLE, icu) { if( (ei->flag & IPO_EDIT) || (ei->flag & IPO_SELECT) || (G.sipo->showkey) ) { ei->icu->extrap= mode; } } } editipo_changed(G.sipo, 1); } int find_other_handles(EditIpo *eicur, float ctime, BezTriple **beztar) { EditIpo *ei; BezTriple *bezt; int a, b, c= 1, totvert; ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if(ei!=eicur && ei->icu && (ei->flag & IPO_VISIBLE)) { bezt= ei->icu->bezt; totvert= ei->icu->totvert; for(b=0; bvec[1][0] < ctime+IPOTHRESH && bezt->vec[1][0] > ctime-IPOTHRESH) { if(c>2) return 0; beztar[c]= bezt; c++; } } } } if(c==3) return 1; return 0; } void set_speed_editipo(float speed) { EditIpo *ei; BezTriple *bezt, *beztar[3]; float vec1[3], vec2[3]; int a, b, totvert, didit=0; if(G.sipo->ipo && G.sipo->ipo->id.lib) return; /* starting with 1 visible curve, selected point, associated points: do lencorr! */ ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if ISPOIN(ei, flag & IPO_VISIBLE, icu) { bezt= ei->icu->bezt; totvert= ei->icu->totvert; for(b=0; bvec[1][0], beztar) ) { beztar[0]->h1= beztar[0]->h2= HD_ALIGN; beztar[1]->h1= beztar[1]->h2= HD_ALIGN; beztar[2]->h1= beztar[2]->h2= HD_ALIGN; vec1[0]= (beztar[0]->vec[1][1] - beztar[0]->vec[0][1]) / (beztar[0]->vec[1][0] - beztar[0]->vec[0][0]) ; vec2[0]= (beztar[0]->vec[1][1] - beztar[0]->vec[2][1]) / (beztar[0]->vec[2][0] - beztar[0]->vec[1][0]) ; vec1[1]= (beztar[1]->vec[1][1] - beztar[1]->vec[0][1]) / (beztar[1]->vec[1][0] - beztar[1]->vec[0][0]) ; vec2[1]= (beztar[1]->vec[1][1] - beztar[1]->vec[2][1]) / (beztar[1]->vec[2][0] - beztar[1]->vec[1][0]) ; vec1[2]= (beztar[2]->vec[1][1] - beztar[2]->vec[0][1]) / (beztar[2]->vec[1][0] - beztar[2]->vec[0][0]) ; vec2[2]= (beztar[2]->vec[1][1] - beztar[2]->vec[2][1]) / (beztar[2]->vec[2][0] - beztar[2]->vec[1][0]) ; Normalise(vec1); Normalise(vec2); VecMulf(vec1, speed); VecMulf(vec2, speed); beztar[0]->vec[0][1]= beztar[0]->vec[1][1] - vec1[0]*(beztar[0]->vec[1][0] - beztar[0]->vec[0][0]) ; beztar[0]->vec[2][1]= beztar[0]->vec[1][1] - vec2[0]*(beztar[0]->vec[2][0] - beztar[0]->vec[1][0]) ; beztar[1]->vec[0][1]= beztar[1]->vec[1][1] - vec1[1]*(beztar[1]->vec[1][0] - beztar[1]->vec[0][0]) ; beztar[1]->vec[2][1]= beztar[1]->vec[1][1] - vec2[1]*(beztar[1]->vec[2][0] - beztar[1]->vec[1][0]) ; beztar[2]->vec[0][1]= beztar[2]->vec[1][1] - vec1[2]*(beztar[2]->vec[1][0] - beztar[2]->vec[0][0]) ; beztar[2]->vec[2][1]= beztar[2]->vec[1][1] - vec2[2]*(beztar[2]->vec[2][0] - beztar[2]->vec[1][0]) ; didit= 1; } else { error("Only works for 3 visible curves with handles"); } } } break; } } if(didit==0) error("Did not set speed"); editipo_changed(G.sipo, 1); allqueue(REDRAWNLA, 0); allqueue (REDRAWACTION, 0); allqueue(REDRAWIPO, 0); } void insertkey(ID *id, int adrcode) { IpoCurve *icu; Ipo *ipo; Object *ob; void *poin; float curval, cfra; int type; if(id) { // this call here, otherwise get_ipo_curve gives it from the pinned ipo ipo= get_ipo(id, GS(id->name), 1); // 1=make icu= get_ipocurve(id, GS(id->name), adrcode, ipo); if(icu) { poin= get_ipo_poin(id, icu, &type); if(poin) { curval= read_ipo_poin(poin, type); cfra= frame_to_float(CFRA); if( GS(id->name)==ID_OB ) { ob= (Object *)id; if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) { /* actually frametofloat calc again! */ cfra-= ob->sf*G.scene->r.framelen; } } insert_vert_ipo(icu, cfra, curval); } } } } void insertkey_editipo() { EditIpo *ei; IpoKey *ik; ID *id; float *fp, cfra, *insertvals; int a, nr, ok, tot; short event; if(G.sipo->showkey) event= pupmenu("Insert KeyVertices %t|Current frame %x1|Selected Keys %x2"); else event= pupmenu("Insert KeyVertices %t|Current frame %x1"); if(event<1) return; ei= G.sipo->editipo; for(nr=0; nrtotipo; nr++, ei++) { if ISPOIN(ei, flag & IPO_VISIBLE, icu) { ok= 0; if(G.sipo->showkey) ok= 1; else if(ei->flag & IPO_SELECT) ok= 1; if(ok) { /* count amount */ if(event==1) tot= 1; else { ik= G.sipo->ipokey.first; tot= 0; while(ik) { if(ik->flag & 1) tot++; ik= ik->next; } } if(tot) { /* correction for ob timeoffs */ cfra= frame_to_float(CFRA); id= G.sipo->from; if(id && GS(id->name)==ID_OB ) { Object *ob= (Object *)id; if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) { cfra-= ob->sf*G.scene->r.framelen; } } else if(id && GS(id->name)==ID_SEQ) { extern Sequence *last_seq; /* editsequence.c */ if(last_seq) { cfra= (float)(100.0*(cfra-last_seq->startdisp)/((float)(last_seq->enddisp-last_seq->startdisp))); } } insertvals= MEM_mallocN(sizeof(float)*2*tot, "insertkey_editipo"); /* make sure icu->curval is correct */ calc_ipo(G.sipo->ipo, cfra); if(event==1) { insertvals[0]= cfra; insertvals[1]= ei->icu->curval; } else { fp= insertvals; ik= G.sipo->ipokey.first; while(ik) { if(ik->flag & 1) { calc_ipo(G.sipo->ipo, ik->val); fp[0]= ik->val; fp[1]= ei->icu->curval; fp+= 2; } ik= ik->next; } } fp= insertvals; for(a=0; aicu, fp[0], fp[1]); } MEM_freeN(insertvals); calc_ipo(G.sipo->ipo, (float)CFRA); } } } } allqueue (REDRAWACTION, 0); allqueue(REDRAWNLA, 0); allqueue(REDRAWIPO, 0); allspace(REMAKEIPO, 0); } void common_insertkey() { Base *base; Object *ob; Material *ma; ID *id; IpoCurve *icu; World *wo; Lamp *la; int tlay, map, event; char menustr[256]; if(curarea->spacetype==SPACE_IPO) { insertkey_editipo(); } else if(curarea->spacetype==SPACE_BUTS) { if(G.buts->mainb==CONTEXT_SHADING) { int tab= G.buts->tab[CONTEXT_SHADING]; if(tab==TAB_SHADING_MAT) { id= G.buts->lockpoin; ma= G.buts->lockpoin; if(id) { event= pupmenu("Insert Key %t|RGB%x0|Alpha%x1|HaSize%x2|Mode %x3|All Color%x10|Ofs%x12|Size%x13|All Mapping%x11"); if(event== -1) return; map= texchannel_to_adrcode(ma->texact); if(event==0 || event==10) { insertkey(id, MA_COL_R); insertkey(id, MA_COL_G); insertkey(id, MA_COL_B); } if(event==1 || event==10) { insertkey(id, MA_ALPHA); } if(event==2 || event==10) { insertkey(id, MA_HASIZE); } if(event==3 || event==10) { insertkey(id, MA_MODE); } if(event==10) { insertkey(id, MA_SPEC_R); insertkey(id, MA_SPEC_G); insertkey(id, MA_SPEC_B); insertkey(id, MA_REF); insertkey(id, MA_EMIT); insertkey(id, MA_AMB); insertkey(id, MA_SPEC); insertkey(id, MA_HARD); insertkey(id, MA_MODE); } if(event==12 || event==11) { insertkey(id, map+MAP_OFS_X); insertkey(id, map+MAP_OFS_Y); insertkey(id, map+MAP_OFS_Z); } if(event==13 || event==11) { insertkey(id, map+MAP_SIZE_X); insertkey(id, map+MAP_SIZE_Y); insertkey(id, map+MAP_SIZE_Z); } if(event==11) { insertkey(id, map+MAP_R); insertkey(id, map+MAP_G); insertkey(id, map+MAP_B); insertkey(id, map+MAP_DVAR); insertkey(id, map+MAP_COLF); insertkey(id, map+MAP_NORF); insertkey(id, map+MAP_VARF); } } } else if(tab==TAB_SHADING_WORLD) { id= G.buts->lockpoin; wo= G.buts->lockpoin; if(id) { event= pupmenu("Insert Key %t|ZenRGB%x0|HorRGB%x1|Mist%x2|stars %x3|Ofs%x12|Size%x13"); if(event== -1) return; map= texchannel_to_adrcode(wo->texact); if(event==0) { insertkey(id, WO_ZEN_R); insertkey(id, WO_ZEN_G); insertkey(id, WO_ZEN_B); } if(event==1) { insertkey(id, WO_HOR_R); insertkey(id, WO_HOR_G); insertkey(id, WO_HOR_B); } if(event==2) { insertkey(id, WO_MISI); insertkey(id, WO_MISTDI); insertkey(id, WO_MISTSTA); insertkey(id, WO_MISTHI); } if(event==3) { insertkey(id, WO_STAR_R); insertkey(id, WO_STAR_G); insertkey(id, WO_STAR_B); insertkey(id, WO_STARDIST); insertkey(id, WO_STARSIZE); } if(event==12) { insertkey(id, map+MAP_OFS_X); insertkey(id, map+MAP_OFS_Y); insertkey(id, map+MAP_OFS_Z); } if(event==13) { insertkey(id, map+MAP_SIZE_X); insertkey(id, map+MAP_SIZE_Y); insertkey(id, map+MAP_SIZE_Z); } } } else if(tab==TAB_SHADING_LAMP) { id= G.buts->lockpoin; la= G.buts->lockpoin; if(id) { event= pupmenu("Insert Key %t|RGB%x0|Energy%x1|Spotsi%x2|Ofs%x12|Size%x13"); if(event== -1) return; map= texchannel_to_adrcode(la->texact); if(event==0) { insertkey(id, LA_COL_R); insertkey(id, LA_COL_G); insertkey(id, LA_COL_B); } if(event==1) { insertkey(id, LA_ENERGY); } if(event==2) { insertkey(id, LA_SPOTSI); } if(event==12) { insertkey(id, map+MAP_OFS_X); insertkey(id, map+MAP_OFS_Y); insertkey(id, map+MAP_OFS_Z); } if(event==13) { insertkey(id, map+MAP_SIZE_X); insertkey(id, map+MAP_SIZE_Y); insertkey(id, map+MAP_SIZE_Z); } } } } else if(G.buts->mainb==CONTEXT_EDITING) { ob= OBACT; if(ob && ob->type==OB_CAMERA) { id= G.buts->lockpoin; if(id) { event= pupmenu("Insert Key %t|Lens%x0|Clipping%x1"); if(event== -1) return; if(event==0) { insertkey(id, CAM_LENS); } if(event==1) { insertkey(id, CAM_STA); insertkey(id, CAM_END); } } } } else if(FALSE /* && G.buts->mainb==BUTS_SOUND */) { if(G.ssound) { id= G.buts->lockpoin; if(id) { event= pupmenu("Insert Key %t|Volume%x0|Pitch%x1|Panning%x2|Attennuation%x3"); if(event== -1) return; if(event==0) { insertkey(id, SND_VOLUME); } if(event==1) { insertkey(id, SND_PITCH); } if(event==2) { insertkey(id, SND_PANNING); } if(event==3) { insertkey(id, SND_ATTEN); } } } } allqueue(REDRAWACTION, 0); allqueue(REDRAWNLA, 0); allqueue(REDRAWIPO, 0); allspace(REMAKEIPO, 0); } else if(curarea->spacetype==SPACE_VIEW3D) { base= FIRSTBASE; while(base) { if TESTBASELIB(base) break; base= base->next; } if(base==0) return; if (G.obpose) strcpy(menustr, "Insert Key%t|Loc%x0|Rot%x1|Size%x2|LocRot%x3|LocRotSize%x4|Avail%x9"); else strcpy(menustr, "Insert Key%t|Loc%x0|Rot%x1|Size%x2|LocRot%x3|LocRotSize%x4|Layer%x5|Avail%x9"); if( (ob = OBACT)) { if(ob->type==OB_MESH) strcat(menustr, "| %x6|Mesh%x7"); else if(ob->type==OB_LATTICE) strcat(menustr, "| %x6|Lattice%x7"); else if(ob->type==OB_CURVE) strcat(menustr, "| %x6|Curve%x7"); else if(ob->type==OB_SURF) strcat(menustr, "| %x6|Surface%x7"); else if(ob->type==OB_IKA) strcat(menustr, "| %x6|Effector%x8"); if(ob->flag & OB_FROMGROUP) strcat(menustr, "| %x6|Entire Group%x10"); } event= pupmenu(menustr); if(event== -1) return; if(event==7) { if(ob->type==OB_MESH) insert_meshkey(ob->data, 0); else if ELEM(ob->type, OB_CURVE, OB_SURF) insert_curvekey(ob->data); else if(ob->type==OB_LATTICE) insert_lattkey(ob->data); allqueue(REDRAWIPO, 0); allqueue(REDRAWACTION, 0); allqueue(REDRAWNLA, 0); allqueue(REDRAWBUTSOBJECT, 0); return; } if(event==10) { Group *group= find_group(ob); if(group) { add_group_key(group); allqueue(REDRAWBUTSOBJECT, 0); } } base= FIRSTBASE; if (G.obpose){ bAction *act; bPose *pose; bPoseChannel *chan; bActionChannel *achan; ob = G.obpose; /* Get action & pose from object */ act=ob->action; pose=ob->pose; collect_pose_garbage(ob); if (!act){ act= G.obpose->action=add_empty_action(); /* this sets the non-pinned open ipowindow(s) to show the action curve */ ob->ipowin= ID_AC; allqueue(REDRAWIPO, ob->ipowin); allqueue(REDRAWACTION, 0); allqueue(REDRAWNLA, 0); } if (!pose){ error ("No pose!"); /* Should never happen */ } if (act->id.lib) { error ("Can't key libactions"); return; } filter_pose_keys (); for (chan=pose->chanbase.first; chan; chan=chan->next) { if (chan->flag & POSE_KEY){ // set_action_key(act, chan); if(event==0 || event==3 ||event==4) { set_action_key(act, chan, AC_LOC_X, 1); set_action_key(act, chan, AC_LOC_Y, 1); set_action_key(act, chan, AC_LOC_Z, 1); } if(event==1 || event==3 ||event==4) { set_action_key(act, chan, AC_QUAT_X, 1); set_action_key(act, chan, AC_QUAT_Y, 1); set_action_key(act, chan, AC_QUAT_Z, 1); set_action_key(act, chan, AC_QUAT_W, 1); } if(event==2 || event==4) { set_action_key(act, chan, AC_SIZE_X, 1); set_action_key(act, chan, AC_SIZE_Y, 1); set_action_key(act, chan, AC_SIZE_Z, 1); } if (event==9){ for (achan = act->chanbase.first; achan; achan=achan->next){ if (achan->ipo && !strcmp (achan->name, chan->name)){ for (icu = achan->ipo->curve.first; icu; icu=icu->next){ set_action_key(act, chan, icu->adrcode, 0); } break; } } } } remake_action_ipos(act); } allqueue(REDRAWIPO, 0); allqueue(REDRAWACTION, 0); allqueue(REDRAWNLA, 0); } else { while(base) { if TESTBASELIB(base) { id= (ID *)(base->object); /* all curves in ipo deselect */ if(base->object->ipo) { icu= base->object->ipo->curve.first; while(icu) { icu->flag &= ~IPO_SELECT; if(event==9) insertkey(id, icu->adrcode); icu= icu->next; } } if(event==0 || event==3 ||event==4) { insertkey(id, OB_LOC_X); insertkey(id, OB_LOC_Y); insertkey(id, OB_LOC_Z); } if(event==1 || event==3 ||event==4) { insertkey(id, OB_ROT_X); insertkey(id, OB_ROT_Y); insertkey(id, OB_ROT_Z); } if(event==2 || event==4) { insertkey(id, OB_SIZE_X); insertkey(id, OB_SIZE_Y); insertkey(id, OB_SIZE_Z); } if(event==5) { /* remove localview */ tlay= base->object->lay; base->object->lay &= 0xFFFFFF; insertkey(id, OB_LAY); base->object->lay= tlay; } if(event==8) { /* a patch, can be removed (old ika) */ Ika *ika= ob->data; VecMat4MulVecfl(ika->effg, ob->obmat, ika->effn); insertkey(id, OB_EFF_X); insertkey(id, OB_EFF_Y); insertkey(id, OB_EFF_Z); } } base= base->next; } } allspace(REMAKEIPO, 0); allqueue(REDRAWIPO, 0); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWACTION, 0); allqueue(REDRAWNLA, 0); } } /* **************************************************** */ /* IPOKEY: * * there are three ways to use this system: * 1. below: for drawing and editing in Ipo window * 2. for drawing key positions in View3D (see ipo.c and drawobject.c) * 3. editing keys in View3D (below and in editobject.c) * */ void free_ipokey(ListBase *lb) { IpoKey *ik; ik= lb->first; while(ik) { if(ik->data) MEM_freeN(ik->data); ik= ik->next; } BLI_freelistN(lb); } void add_to_ipokey(ListBase *lb, BezTriple *bezt, int nr, int len) { IpoKey *ik, *ikn; ik= lb->first; while(ik) { if( ik->val==bezt->vec[1][0] ) { if(ik->data[nr]==0) { /* double points! */ ik->data[nr]= bezt; if(bezt->f2 & 1) ik->flag= 1; return; } } else if(ik->val > bezt->vec[1][0]) break; ik= ik->next; } ikn= MEM_callocN(sizeof(IpoKey), "add_to_ipokey"); if(ik) BLI_insertlinkbefore(lb, ik, ikn); else BLI_addtail(lb, ikn); ikn->data= MEM_callocN(sizeof(float *)*len, "add_to_ipokey"); ikn->data[nr]= bezt; ikn->val= bezt->vec[1][0]; if(bezt->f2 & 1) ikn->flag= 1; } void make_ipokey(void) { EditIpo *ei; IpoKey *ik; ListBase *lb; BezTriple *bezt; int a, b, sel, desel, totvert; lb= &G.sipo->ipokey; free_ipokey(lb); ei= G.sipo->editipo; if(ei==0) return; for(a=0; atotipo; a++, ei++) { if ISPOIN(ei, flag & IPO_VISIBLE, icu) { bezt= ei->icu->bezt; totvert= ei->icu->totvert; for(b=0; btotipo); } ei->flag &= ~IPO_SELECT; ei->flag &= ~IPO_EDIT; ei->icu->flag= ei->flag; } } /* test selectflags */ ik= lb->first; while(ik) { sel= desel= 0; for(a=0; atotipo; a++) { if(ik->data[a]) { bezt= ik->data[a]; if(bezt->f2 & 1) sel++; else desel++; } } if(sel && desel) sel= 0; for(a=0; atotipo; a++) { if(ik->data[a]) { bezt= ik->data[a]; if(sel) { bezt->f1 |= 1; bezt->f2 |= 1; bezt->f3 |= 1; } else { bezt->f1 &= ~1; bezt->f2 &= ~1; bezt->f3 &= ~1; } } } if(sel) ik->flag = 1; else ik->flag= 0; ik= ik->next; } get_status_editipo(); } void make_ipokey_transform(Object *ob, ListBase *lb, int sel) { IpoCurve *icu; BezTriple *bezt; int a, adrcode = 0, ok, dloc=0, drot=0, dsize=0; if(ob->ipo==0) return; if(ob->ipo->showkey==0) return; /* test: are there delta curves? */ icu= ob->ipo->curve.first; while(icu) { if(icu->flag & IPO_VISIBLE) { switch(icu->adrcode) { case OB_DLOC_X: case OB_DLOC_Y: case OB_DLOC_Z: dloc= 1; break; case OB_DROT_X: case OB_DROT_Y: case OB_DROT_Z: drot= 1; break; case OB_DSIZE_X: case OB_DSIZE_Y: case OB_DSIZE_Z: dsize= 1; break; } } icu= icu->next; } icu= ob->ipo->curve.first; while(icu) { if(icu->flag & IPO_VISIBLE) { ok= 0; switch(icu->adrcode) { case OB_DLOC_X: case OB_DLOC_Y: case OB_DLOC_Z: case OB_DROT_X: case OB_DROT_Y: case OB_DROT_Z: case OB_DSIZE_X: case OB_DSIZE_Y: case OB_DSIZE_Z: ok= 1; break; case OB_LOC_X: case OB_LOC_Y: case OB_LOC_Z: if(dloc==0) ok= 1; break; case OB_ROT_X: case OB_ROT_Y: case OB_ROT_Z: if(drot==0) ok= 1; break; case OB_SIZE_X: case OB_SIZE_Y: case OB_SIZE_Z: if(dsize==0) ok= 1; break; } if(ok) { for(a=0; aadrcode==ob_ar[a]) { adrcode= a; break; } } bezt= icu->bezt; a= icu->totvert; while(a--) { if(sel==0 || (bezt->f2 & 1)) { add_to_ipokey(lb, bezt, adrcode, OB_TOTIPO); } bezt++; } } } icu= icu->next; } } void update_ipokey_val() /* after moving vertices */ { IpoKey *ik; int a; ik= G.sipo->ipokey.first; while(ik) { for(a=0; atotipo; a++) { if(ik->data[a]) { ik->val= ik->data[a]->vec[1][0]; break; } } ik= ik->next; } } void set_tob_old(float *old, float *poin) { old[0]= *(poin); old[3]= *(poin-3); old[6]= *(poin+3); } void set_ipo_pointers_transob(IpoKey *ik, TransOb *tob) { BezTriple *bezt; int a, delta= 0; tob->locx= tob->locy= tob->locz= 0; tob->rotx= tob->roty= tob->rotz= 0; tob->sizex= tob->sizey= tob->sizez= 0; for(a=0; adata[a]) { bezt= ik->data[a]; switch( ob_ar[a] ) { case OB_LOC_X: case OB_DLOC_X: tob->locx= &(bezt->vec[1][1]); break; case OB_LOC_Y: case OB_DLOC_Y: tob->locy= &(bezt->vec[1][1]); break; case OB_LOC_Z: case OB_DLOC_Z: tob->locz= &(bezt->vec[1][1]); break; case OB_DROT_X: delta= 1; case OB_ROT_X: tob->rotx= &(bezt->vec[1][1]); break; case OB_DROT_Y: delta= 1; case OB_ROT_Y: tob->roty= &(bezt->vec[1][1]); break; case OB_DROT_Z: delta= 1; case OB_ROT_Z: tob->rotz= &(bezt->vec[1][1]); break; case OB_SIZE_X: case OB_DSIZE_X: tob->sizex= &(bezt->vec[1][1]); break; case OB_SIZE_Y: case OB_DSIZE_Y: tob->sizey= &(bezt->vec[1][1]); break; case OB_SIZE_Z: case OB_DSIZE_Z: tob->sizez= &(bezt->vec[1][1]); break; } } } /* oldvals for e.g. undo */ if(tob->locx) set_tob_old(tob->oldloc, tob->locx); if(tob->locy) set_tob_old(tob->oldloc+1, tob->locy); if(tob->locz) set_tob_old(tob->oldloc+2, tob->locz); /* store first oldrot, for mapping curves ('1'=10 degrees) and correct calculation */ if(tob->rotx) set_tob_old(tob->oldrot+3, tob->rotx); if(tob->roty) set_tob_old(tob->oldrot+4, tob->roty); if(tob->rotz) set_tob_old(tob->oldrot+5, tob->rotz); /* store the first oldsize, this is not allowed to be dsize! */ if(tob->sizex) set_tob_old(tob->oldsize+3, tob->sizex); if(tob->sizey) set_tob_old(tob->oldsize+4, tob->sizey); if(tob->sizez) set_tob_old(tob->oldsize+5, tob->sizez); tob->flag= TOB_IPO; if(delta) tob->flag |= TOB_IPODROT; } void nextkey(ListBase *elems, int dir) { IpoKey *ik, *previk; int totsel; if(dir==1) ik= elems->last; else ik= elems->first; previk= 0; totsel= 0; while(ik) { if(ik->flag) totsel++; if(previk) { if(G.qual & LR_SHIFTKEY) { if(ik->flag) previk->flag= 1; } else previk->flag= ik->flag; } previk= ik; if(dir==1) ik= ik->prev; else ik= ik->next; if(G.qual & LR_SHIFTKEY); else if(ik==0) previk->flag= 0; } /* when no key select: */ if(totsel==0) { if(dir==1) ik= elems->first; else ik= elems->last; if(ik) ik->flag= 1; } } static int float_to_frame (float frame) { int to= (int) frame; if (frame-to>0.5) to++; return to; } void movekey_ipo(int dir) /* only call external from view3d queue */ { IpoKey *ik; float toframe = 0.0; int a; if(G.sipo->showkey==0) return; ik= G.sipo->ipokey.first; if (dir==-1) { while (ik && float_to_frame(ik->val)val; ik= ik->next; } } else { while (ik && float_to_frame(ik->val)<=CFRA) { ik= ik->next; } if (ik) toframe= ik->val; } a= float_to_frame(toframe); if (a!=CFRA && a>0) { CFRA= a; update_for_newframe(); } allqueue(REDRAWNLA, 0); allqueue(REDRAWACTION, 0); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWIPO, 0); allspace(REMAKEIPO, 0); } void movekey_obipo(int dir) /* only call external from view3d queue */ { Base *base; Object *ob; ListBase elems; IpoKey *ik; int a; float toframe= CFRA; base= FIRSTBASE; while(base) { if TESTBASE(base) { ob= base->object; if(ob->ipo && ob->ipo->showkey) { elems.first= elems.last= 0; make_ipokey_transform(ob, &elems, 0); if(elems.first) { ik= elems.first; if (dir==-1) { while (ik && float_to_frame(ik->val)val; ik= ik->next; } } else { while (ik && float_to_frame(ik->val)<=CFRA) { ik= ik->next; } if (ik) toframe= ik->val; } free_ipokey(&elems); } } } base= base->next; } a= float_to_frame(toframe); if (a!=CFRA && a>0) { CFRA= a; update_for_newframe(); } allqueue(REDRAWNLA, 0); allqueue(REDRAWACTION, 0); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWIPO, 0); allspace(REMAKEIPO, 0); } void nextkey_ipo(int dir) /* call from ipo queue */ { IpoKey *ik; int a; if(G.sipo->showkey==0) return; nextkey(&G.sipo->ipokey, dir); /* copy to beziers */ ik= G.sipo->ipokey.first; while(ik) { for(a=0; atotipo; a++) { if(ik->data[a]) ik->data[a]->f1= ik->data[a]->f2= ik->data[a]->f3= ik->flag; } ik= ik->next; } allqueue(REDRAWNLA, 0); allqueue(REDRAWACTION, 0); allqueue(REDRAWIPO, 0); if(G.sipo->blocktype == ID_OB) allqueue(REDRAWVIEW3D, 0); } void nextkey_obipo(int dir) /* only call external from view3d queue */ { Base *base; Object *ob; ListBase elems; IpoKey *ik; int a; /* problem: this doesnt work when you mix dLoc keys with Loc keys */ base= FIRSTBASE; while(base) { if TESTBASE(base) { ob= base->object; if( (ob->ipoflag & OB_DRAWKEY) && ob->ipo && ob->ipo->showkey) { elems.first= elems.last= 0; make_ipokey_transform(ob, &elems, 0); if(elems.first) { nextkey(&elems, dir); /* copy to beziers */ ik= elems.first; while(ik) { for(a=0; adata[a]) ik->data[a]->f1= ik->data[a]->f2= ik->data[a]->f3= ik->flag; } ik= ik->next; } free_ipokey(&elems); } } } base= base->next; } allqueue(REDRAWNLA, 0); allqueue(REDRAWACTION, 0); allqueue(REDRAWVIEW3D, 0); allspace(REMAKEIPO, 0); allqueue(REDRAWIPO, 0); } /* **************************************************** */ void remake_ipo_transverts(TransVert *transmain, float *dvec, int tot) { EditIpo *ei; TransVert *tv; BezTriple *bezt; int a, b; ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if ISPOIN(ei, flag & IPO_VISIBLE, icu) { if(ei->icu->bezt) { sort_time_ipocurve(ei->icu); } } } ei= G.sipo->editipo; tv= transmain; for(a=0; atotipo; a++, ei++) { if ISPOIN(ei, flag & IPO_VISIBLE, icu) { if( (ei->flag & IPO_EDIT) || G.sipo->showkey) { if(ei->icu->bezt) { bezt= ei->icu->bezt; b= ei->icu->totvert; while(b--) { if(ei->icu->ipo==IPO_BEZ) { if(bezt->f1 & 1) { tv->loc= bezt->vec[0]; tv++; } if(bezt->f3 & 1) { tv->loc= bezt->vec[2]; tv++; } } if(bezt->f2 & 1) { tv->loc= bezt->vec[1]; tv++; } bezt++; } testhandles_ipocurve(ei->icu); } } } } if(G.sipo->showkey) make_ipokey(); if(dvec==0) return; tv= transmain; for(a=0; aoldloc[0]= tv->loc[0]-dvec[0]; tv->oldloc[1]= tv->loc[1]-dvec[1]; } } void transform_ipo(int mode) { EditIpo *ei; BezTriple *bezt; TransVert *transmain = NULL, *tv; float xref=1.0, yref=1.0, dx, dy, dvec[2], min[3], max[3], vec[2], div, cent[2], size[2], sizefac; int tot=0, a, b, firsttime=1, afbreek=0, midtog= 0, dosort, proj = 0; unsigned short event = 0; short mval[2], val, xo, yo, xn, yn, xc, yc; char str[32]; if(G.sipo->ipo && G.sipo->ipo->id.lib) return; if(G.sipo->editipo==0) return; if(mode=='r') return; /* from gesture */ INIT_MINMAX(min, max); /* which vertices are involved */ get_status_editipo(); if(totipo_vertsel) { tot= totipo_vertsel; tv=transmain= MEM_callocN(tot*sizeof(TransVert), "transmain"); ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if ISPOIN(ei, flag & IPO_VISIBLE, icu) { if( (ei->flag & IPO_EDIT) || G.sipo->showkey) { if(ei->icu->bezt) { bezt= ei->icu->bezt; b= ei->icu->totvert; while(b--) { if(ei->icu->ipo==IPO_BEZ) { if(bezt->f1 & 1) { tv->loc= bezt->vec[0]; VECCOPY(tv->oldloc, tv->loc); if(ei->disptype==IPO_DISPBITS) tv->flag= 1; /* we take the middle vertex */ DO_MINMAX2(bezt->vec[1], min, max); tv++; } if(bezt->f3 & 1) { tv->loc= bezt->vec[2]; VECCOPY(tv->oldloc, tv->loc); if(ei->disptype==IPO_DISPBITS) tv->flag= 1; /* we take the middle vertex */ DO_MINMAX2(bezt->vec[1], min, max); tv++; } } if(bezt->f2 & 1) { tv->loc= bezt->vec[1]; VECCOPY(tv->oldloc, tv->loc); if(ei->disptype==IPO_DISPBITS) tv->flag= 1; DO_MINMAX2(bezt->vec[1], min, max); tv++; } bezt++; } } } } } } else if(totipo_edit==0 && totipo_sel!=0) { ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) { if(ei->icu->bezt && ei->icu->ipo==IPO_BEZ) tot+= 3*ei->icu->totvert; else tot+= ei->icu->totvert; } } if(tot==0) return; tv=transmain= MEM_callocN(tot*sizeof(TransVert), "transmain"); ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) { if(ei->icu->bezt) { bezt= ei->icu->bezt; b= ei->icu->totvert; while(b--) { if(ei->icu->ipo==IPO_BEZ) { tv->loc= bezt->vec[0]; VECCOPY(tv->oldloc, tv->loc); if(ei->disptype==IPO_DISPBITS) tv->flag= 1; tv++; tv->loc= bezt->vec[2]; VECCOPY(tv->oldloc, tv->loc); if(ei->disptype==IPO_DISPBITS) tv->flag= 1; tv++; } tv->loc= bezt->vec[1]; VECCOPY(tv->oldloc, tv->loc); if(ei->disptype==IPO_DISPBITS) tv->flag= 1; DO_MINMAX2(bezt->vec[1], min, max); tv++; bezt++; } } } } } if(tot==0) { if(totipo_edit==0) move_keys(); return; } cent[0]= (float)((min[0]+max[0])/2.0); cent[1]= (float)((min[1]+max[1])/2.0); if(G.sipo->showkey) { midtog= 1; proj= 1; } ipoco_to_areaco(G.v2d, cent, mval); xc= mval[0]; yc= mval[1]; getmouseco_areawin(mval); xo= xn= mval[0]; yo= yn= mval[1]; dvec[0]= dvec[1]= 0.0; sizefac= (float)(sqrt( (float)((yc-yn)*(yc-yn)+(xn-xc)*(xn-xc)) )); if(sizefac<2.0) sizefac= 2.0; while(afbreek==0) { getmouseco_areawin(mval); if(mval[0]!=xo || mval[1]!=yo || firsttime) { if(mode=='g') { dx= (float)(mval[0]- xo); dy= (float)(mval[1]- yo); div= (float)(G.v2d->mask.xmax-G.v2d->mask.xmin); dvec[0]+= (G.v2d->cur.xmax-G.v2d->cur.xmin)*(dx)/div; div= (float)(G.v2d->mask.ymax-G.v2d->mask.ymin); dvec[1]+= (G.v2d->cur.ymax-G.v2d->cur.ymin)*(dy)/div; if(midtog) dvec[proj]= 0.0; /* vec is reused below: remake_ipo_transverts */ vec[0]= dvec[0]; vec[1]= dvec[1]; apply_keyb_grid(vec, 0.0, (float)1.0, (float)0.1, U.flag & AUTOGRABGRID); apply_keyb_grid(vec+1, 0.0, (float)1.0, (float)0.1, 0); tv= transmain; for(a=0; aloc[0]= tv->oldloc[0]+vec[0]; if(tv->flag==0) tv->loc[1]= tv->oldloc[1]+vec[1]; } sprintf(str, "X: %.3f Y: %.3f ", vec[0], vec[1]); headerprint(str); } else if(mode=='s') { size[0]=size[1]=(float)( (sqrt( (float)((yc-mval[1])*(yc-mval[1])+(mval[0]-xc)*(mval[0]-xc)) ))/sizefac); if(midtog) size[proj]= 1.0; size[0]*= xref; size[1]*= yref; apply_keyb_grid(size, 0.0, (float)0.2, (float)0.1, U.flag & AUTOSIZEGRID); apply_keyb_grid(size+1, 0.0, (float)0.2, (float)0.1, U.flag & AUTOSIZEGRID); tv= transmain; for(a=0; aloc[0]= size[0]*(tv->oldloc[0]-cent[0])+ cent[0]; if(tv->flag==0) tv->loc[1]= size[1]*(tv->oldloc[1]-cent[1])+ cent[1]; } sprintf(str, "sizeX: %.3f sizeY: %.3f ", size[0], size[1]); headerprint(str); } xo= mval[0]; yo= mval[1]; dosort= 0; ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if ISPOIN(ei, flag & IPO_VISIBLE, icu) { /* watch it: if the time is wrong: do not correct handles */ if (test_time_ipocurve(ei->icu) ) dosort++; else testhandles_ipocurve(ei->icu); } } if(dosort) { if(mode=='g') remake_ipo_transverts(transmain, vec, tot); else remake_ipo_transverts(transmain, 0, tot); } if(G.sipo->showkey) update_ipokey_val(); calc_ipo(G.sipo->ipo, (float)CFRA); /* update realtime */ if(G.sipo->lock) { if(G.sipo->blocktype==ID_MA) { force_draw_plus(SPACE_BUTS); } else if(G.sipo->blocktype==ID_KE) { do_ob_key(OBACT); makeDispList(OBACT); force_draw_plus(SPACE_VIEW3D); } else if(G.sipo->blocktype==ID_AC) { do_all_actions(); force_draw_all(); } else if(G.sipo->blocktype==ID_OB) { Base *base= FIRSTBASE; while(base) { if(base->object->ipo==G.sipo->ipo) do_ob_ipo(base->object); base= base->next; } force_draw_plus(SPACE_VIEW3D); } else force_draw(); } else { force_draw(); } firsttime= 0; } else BIF_wait_for_statechange(); while(qtest()) { event= extern_qread(&val); if(val) { switch(event) { case ESCKEY: case LEFTMOUSE: case RIGHTMOUSE: case SPACEKEY: case RETKEY: afbreek= 1; break; case MIDDLEMOUSE: if(G.sipo->showkey==0) { midtog= ~midtog; if(midtog) { if( abs(mval[0]-xn) > abs(mval[1]-yn)) proj= 1; else proj= 0; firsttime= 1; } } break; case XKEY: case YKEY: if(event==XKEY) xref= -xref; else if(G.sipo->showkey==0) yref= -yref; firsttime= 1; break; case LEFTCTRLKEY: case RIGHTCTRLKEY: firsttime= 1; break; default: if(mode=='g') { if(G.qual & LR_CTRLKEY) { if(event==LEFTARROWKEY) {dvec[0]-= 1.0; firsttime= 1;} else if(event==RIGHTARROWKEY) {dvec[0]+= 1.0; firsttime= 1;} else if(event==UPARROWKEY) {dvec[1]+= 1.0; firsttime= 1;} else if(event==DOWNARROWKEY) {dvec[1]-= 1.0; firsttime= 1;} } else arrows_move_cursor(event); } else arrows_move_cursor(event); } } if(afbreek) break; } } if(event==ESCKEY || event==RIGHTMOUSE) { tv= transmain; for(a=0; aloc[0]= tv->oldloc[0]; tv->loc[1]= tv->oldloc[1]; } dosort= 0; ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if ISPOIN(ei, flag & IPO_VISIBLE, icu) { if( (ei->flag & IPO_EDIT) || G.sipo->showkey) { if( test_time_ipocurve(ei->icu)) { dosort= 1; break; } } } } if(dosort) remake_ipo_transverts(transmain, 0, tot); ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if ISPOIN(ei, flag & IPO_VISIBLE, icu) { if( (ei->flag & IPO_EDIT) || G.sipo->showkey) { testhandles_ipocurve(ei->icu); } } } calc_ipo(G.sipo->ipo, (float)CFRA); } editipo_changed(G.sipo, 1); MEM_freeN(transmain); } void clever_numbuts_ipo() { BezTriple *bezt=0, *bezt1; Key *key; KeyBlock *kb; EditIpo *ei; float far, delta[3], old[3]; int a, b, scale10=0, totbut=2; if(G.sipo->ipo && G.sipo->ipo->id.lib) return; if(G.sipo->editipo==0) return; /* which vertices are involved */ get_status_editipo(); if(G.qual & LR_SHIFTKEY) totbut= 1; if(G.vd==0) far= 10000.0; else far= (float)(MAX2(G.vd->far, 10000.0)); if(totipo_vertsel) { ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if ISPOIN(ei, flag & IPO_VISIBLE, icu) { if( (ei->flag & IPO_EDIT) || G.sipo->showkey) { if(ei->icu->bezt) { bezt1= ei->icu->bezt; b= ei->icu->totvert; while(b--) { if(BEZSELECTED(bezt1)) { bezt= bezt1; break; } bezt1++; } } } } if(bezt) break; } if(bezt==0) return; if(bezt->f2 & 1) { VECCOPY(old, bezt->vec[1]); if(totipo_vis==1 && G.sipo->blocktype==ID_OB) { if ELEM4(ei->icu->adrcode, OB_TIME, OB_ROT_X, OB_ROT_Y, OB_ROT_Z) scale10= 1; if ELEM3(ei->icu->adrcode, OB_DROT_X, OB_DROT_Y, OB_DROT_Z) scale10= 1; } if(scale10) bezt->vec[1][1]*= 10.0; add_numbut(0, NUM|FLO, "LocX:", -1000, 10000, bezt->vec[1], 0); if(totbut==2) add_numbut(1, NUM|FLO, "LocY:", -far, far, bezt->vec[1]+1, 0); do_clever_numbuts("Active BezierPoint", totbut, REDRAW); if(scale10) bezt->vec[1][1]/= 10.0; VecSubf(delta, bezt->vec[1], old); VECCOPY(bezt->vec[1], old); /* apply */ ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if ISPOIN(ei, flag & IPO_VISIBLE, icu) { if( (ei->flag & IPO_EDIT) || G.sipo->showkey) { if(ei->icu->bezt) { bezt= ei->icu->bezt; b= ei->icu->totvert; while(b--) { if(bezt->f2 & 1) { bezt->vec[0][0]+= delta[0]; bezt->vec[1][0]+= delta[0]; bezt->vec[2][0]+= delta[0]; bezt->vec[0][1]+= delta[1]; bezt->vec[1][1]+= delta[1]; bezt->vec[2][1]+= delta[1]; } bezt++; } } } } } ei= G.sipo->editipo; for(a=0; atotipo; a++, ei++) { if ISPOIN(ei, flag & IPO_VISIBLE, icu) { sort_time_ipocurve(ei->icu); testhandles_ipocurve(ei->icu); } } } else if(bezt->f1 & 1) { add_numbut(0, NUM|FLO, "LocX:", -1000, 10000, bezt->vec[0], 0); if(totbut==2) add_numbut(1, NUM|FLO, "LocY:", -far, far, bezt->vec[0]+1, 0); do_clever_numbuts("Active HandlePoint", totbut, REDRAW); } else if(bezt->f3 & 1) { add_numbut(0, NUM|FLO, "LocX:", -1000, 10000, bezt->vec[0], 0); if(totbut==2) add_numbut(1, NUM|FLO, "LocY:", -far, far, bezt->vec[2]+1, 0); do_clever_numbuts("Active HandlePoint", totbut, REDRAW); } editipo_changed(G.sipo, 1); } else { if(G.sipo->blocktype==ID_KE) { key= (Key *)G.sipo->from; if(key==0) return; kb= key->block.first; while(kb) { if(kb->flag & SELECT) break; kb= kb->next; } if(kb && G.sipo->rowbut&1) { add_numbut(0, NUM|FLO, "Pos:", -100, 100, &kb->pos, 0); do_clever_numbuts("Active Key", 1, REDRAW); sort_keys(key); } } } } void filter_sampledata(float *data, int sfra, int efra) { float *da; int a; da= data+1; for(a=sfra+1; aipo= IPO_LIN; if(icu->bezt) MEM_freeN(icu->bezt); icu->bezt= 0; tot= 1; /* first point */ da= data+1; for(a=sfra+1; atotvert= tot; bezt= icu->bezt= MEM_callocN(tot*sizeof(BezTriple), "samplebezt"); bezt->vec[1][0]= (float)sfra; bezt->vec[1][1]= data[0]; bezt++; da= data+1; for(a=sfra+1; avec[1][0]= (float)a; bezt->vec[1][1]= da[0]; bezt++; } } } void ipo_record() { /* only 1 or 2 active curves * make a copy (ESC) * * reference point is the current situation (or 0) * dx (dy) is the height correction factor * CTRL: start record */ extern double tottime; EditIpo *ei, *ei1=0, *ei2=0; ScrArea *sa, *oldarea; Ipo *ipo; void *poin; double swaptime; float or1, or2 = 0.0, fac, *data1, *data2; int type, a, afbreek=0, firsttime=1, cfrao, cfra, sfra, efra; unsigned short event = 0; short anim, val, xn, yn, mvalo[2], mval[2]; char str[128]; if(G.sipo->from==0) return; if(SFRA>=EFRA) return; anim= pupmenu("Record Mouse %t|Still %x1|Play anim %x2"); if(anim < 1) return; if(anim!=2) anim= 0; ipo= get_ipo(G.sipo->from, G.sipo->blocktype, 1); /* 1= make */ if(G.sipo) G.sipo->ipo= ipo; /* find the curves... */ ei= G.sipo->editipo; for(a=0; atotipo; a++) { if(ei->flag & IPO_VISIBLE) { if(ei1==0) ei1= ei; else if(ei2==0) ei2= ei; else { error("Max 2 visible curves"); return; } } ei++; } if(ei1==0) { error("Select 1 or 2 channels"); return; } /* make curves ready, start values */ if(ei1->icu==0) ei1->icu= get_ipocurve(G.sipo->from, G.sipo->blocktype, ei1->adrcode, 0); if(ei1->icu==0) return; poin= get_ipo_poin(G.sipo->from, ei1->icu, &type); if(poin) ei1->icu->curval= read_ipo_poin(poin, type); or1= ei1->icu->curval; ei1->icu->flag |= IPO_LOCK; if(ei2) { if(ei2->icu==0) ei2->icu= get_ipocurve(G.sipo->from, G.sipo->blocktype, ei2->adrcode, 0); if(ei2->icu==0) return; poin= get_ipo_poin(G.sipo->from, ei2->icu, &type); if(poin) ei2->icu->curval= read_ipo_poin(poin, type); or2= ei2->icu->curval; ei2->icu->flag |= IPO_LOCK; } fac= G.v2d->cur.ymax - G.v2d->cur.ymin; fac/= (float)curarea->winy; /* which area */ oldarea= curarea; sa= G.curscreen->areabase.first; while(sa) { if(sa->win) { if(G.sipo->blocktype==ID_MA || G.sipo->blocktype==ID_LA) { if(sa->spacetype==SPACE_BUTS) break; } else { if(sa->spacetype==SPACE_VIEW3D) break; } } sa= sa->next; } if(sa) areawinset(sa->win); /* can we? */ while(get_mbut()&L_MOUSE) BIF_wait_for_statechange(); data1= MEM_callocN(sizeof(float)*(EFRA-SFRA+1), "data1"); data2= MEM_callocN(sizeof(float)*(EFRA-SFRA+1), "data2"); getmouseco_areawin(mvalo); xn= mvalo[0]; yn= mvalo[1]; waitcursor(1); tottime= 0.0; swaptime= speed_to_swaptime(G.animspeed); cfrao= CFRA; cfra=efra= SFRA; sfra= EFRA; while(afbreek==0) { getmouseco_areawin(mval); if(mval[0]!= mvalo[0] || mval[1]!=mvalo[1] || firsttime || (G.qual & LR_CTRLKEY)) { if(anim) CFRA= cfra; else firsttime= 0; set_timecursor(cfra); /* do ipo: first all, then the specific ones */ if(anim==2) { do_all_ipos(); do_all_keys(); } ei1->icu->curval= or1 + fac*(mval[0]-xn); if(ei2) ei2->icu->curval= or2 + fac*(mval[1]-yn); do_ipo_nocalc(G.sipo->ipo); do_all_visible_ikas(); if(G.qual & LR_CTRLKEY) { sprintf(str, "Recording... %d\n", cfra); data1[ cfra-SFRA ]= ei1->icu->curval; if(ei2) data2[ cfra-SFRA ]= ei2->icu->curval; sfra= MIN2(sfra, cfra); efra= MAX2(efra, cfra); } else sprintf(str, "Mouse Recording. Use CTRL to start. LeftMouse or Space to end"); do_ob_key(OBACT); headerprint(str); if(sa) scrarea_do_windraw(sa); /* minimal wait swaptime */ tottime -= swaptime; while (update_time()) PIL_sleep_ms(1); screen_swapbuffers(); tottime= 0.0; mvalo[0]= mval[0]; mvalo[1]= mval[1]; if(anim || (G.qual & LR_CTRLKEY)) { cfra++; if(cfra>EFRA) cfra= SFRA; } } while(qtest()) { event= extern_qread(&val); if(val) { switch(event) { case LEFTMOUSE: case ESCKEY: case SPACEKEY: case RETKEY: afbreek= 1; break; } } if(afbreek) break; } } if(event!=ESCKEY) { sampledata_to_ipocurve(data1+sfra-SFRA, sfra, efra, ei1->icu); if(ei2) sampledata_to_ipocurve(data2+sfra-SFRA, sfra, efra, ei2->icu); /* not nice when this is on */ if(G.sipo->showkey) { G.sipo->showkey= 0; free_ipokey(&G.sipo->ipokey); } } else { /* undo: start values */ poin= get_ipo_poin(G.sipo->from, ei1->icu, &type); if(poin) write_ipo_poin(poin, type, or1); if(ei1->icu->bezt==0) { BLI_remlink( &(G.sipo->ipo->curve), ei1->icu); MEM_freeN(ei1->icu); ei1->icu= 0; } if(ei2) { poin= get_ipo_poin(G.sipo->from, ei2->icu, &type); if(poin) write_ipo_poin(poin, type, or2); if(ei2->icu->bezt==0) { BLI_remlink( &(G.sipo->ipo->curve), ei2->icu); MEM_freeN(ei2->icu); ei2->icu= 0; } } } if(ei1->icu) ei1->icu->flag &= ~IPO_LOCK; if(ei2 && ei2->icu) ei2->icu->flag &= ~IPO_LOCK; editipo_changed(G.sipo, 0); do_ipo(G.sipo->ipo); waitcursor(0); allqueue(REDRAWVIEW3D, 0); if(sa) scrarea_queue_headredraw(sa); /* headerprint */ scrarea_queue_redraw(oldarea); CFRA= cfrao; /* for the time being? */ update_for_newframe(); MEM_freeN(data1); MEM_freeN(data2); } void remake_object_ipos(Object *ob) { IpoCurve *icu; if (!ob) return; if (!ob->ipo) return; for (icu = ob->ipo->curve.first; icu; icu=icu->next){ sort_time_ipocurve(icu); testhandles_ipocurve(icu); } } int is_ipo_key_selected(Ipo *ipo) { int i; IpoCurve *icu; if (!ipo) return 0; for (icu=ipo->curve.first; icu; icu=icu->next){ for (i=0; itotvert; i++) if (BEZSELECTED(&icu->bezt[i])) return 1; } return 0; } void set_ipo_key_selection(Ipo *ipo, int sel) { int i; IpoCurve *icu; if (!ipo) return; for (icu=ipo->curve.first; icu; icu=icu->next){ for (i=0; itotvert; i++){ if (sel){ icu->bezt[i].f1|=1; icu->bezt[i].f2|=1; icu->bezt[i].f3|=1; } else{ icu->bezt[i].f1&=~1; icu->bezt[i].f2&=~1; icu->bezt[i].f3&=~1; } } } } void delete_ipo_keys(Ipo *ipo) { IpoCurve *icu, *next; int i; if (!ipo) return; for (icu=ipo->curve.first; icu; icu=next){ next = icu->next; for (i=0; itotvert; i++){ if (icu->bezt[i].f2 & 1){ // Delete the item memcpy (&icu->bezt[i], &icu->bezt[i+1], sizeof (BezTriple)*(icu->totvert-i-1)); icu->totvert--; i--; } } if (!icu->totvert){ /* Delete the curve */ BLI_remlink( &(ipo->curve), icu); if(icu->bezt) MEM_freeN(icu->bezt); MEM_freeN(icu); } } } int fullselect_ipo_keys(Ipo *ipo) { int i; IpoCurve *icu; int tvtot = 0; if (!ipo) return tvtot; for (icu=ipo->curve.first; icu; icu=icu->next){ for (i=0; itotvert; i++){ if (icu->bezt[i].f2 & 1){ tvtot+=3; icu->bezt[i].f1 |= 1; icu->bezt[i].f3 |= 1; } } } return tvtot; } int add_trans_ipo_keys(Ipo *ipo, TransVert *tv, int tvtot) { int i; IpoCurve *icu; if (!ipo) return tvtot; for (icu=ipo->curve.first; icu; icu=icu->next){ for (i=0; itotvert; i++){ if (icu->bezt[i].f2 & 1){ tv[tvtot+0].loc=icu->bezt[i].vec[0]; tv[tvtot+1].loc=icu->bezt[i].vec[1]; tv[tvtot+2].loc=icu->bezt[i].vec[2]; memcpy (&tv[tvtot+0].oldloc, icu->bezt[i].vec[0], sizeof (float)*3); memcpy (&tv[tvtot+1].oldloc, icu->bezt[i].vec[1], sizeof (float)*3); memcpy (&tv[tvtot+2].oldloc, icu->bezt[i].vec[2], sizeof (float)*3); tvtot+=3; } } } return tvtot; } void duplicate_ipo_keys(Ipo *ipo) { IpoCurve *icu; int i; BezTriple *newbezt; if (!ipo) return; for (icu=ipo->curve.first; icu; icu=icu->next){ for (i=0; itotvert; i++){ /* If a key is selected */ if (icu->bezt[i].f2 & 1){ /* Expand the list */ newbezt = MEM_callocN(sizeof(BezTriple) * (icu->totvert+1), "beztriple"); memcpy (newbezt, icu->bezt, sizeof(BezTriple) * (i+1)); memcpy (newbezt+i+1, icu->bezt+i, sizeof(BezTriple)); memcpy (newbezt+i+2, icu->bezt+i+1, sizeof (BezTriple) *(icu->totvert-(i+1))); icu->totvert++; MEM_freeN (icu->bezt); icu->bezt=newbezt; /* Unselect the current key*/ icu->bezt[i].f1 &= ~ 1; icu->bezt[i].f2 &= ~ 1; icu->bezt[i].f3 &= ~ 1; i++; /* Select the copied key */ icu->bezt[i].f1 |= 1; icu->bezt[i].f2 |= 1; icu->bezt[i].f3 |= 1; } } } } void borderselect_icu_key(IpoCurve *icu, float xmin, float xmax, int (*select_function)(BezTriple *)) { /* Selects all bezier triples in the Ipocurve * between times xmin and xmax, using the selection * function. */ int i; /* loop through all of the bezier triples in * the Ipocurve -- if the triple occurs between * times xmin and xmax then select it using the selection * function */ for (i=0; itotvert; i++){ if (icu->bezt[i].vec[1][0] > xmin && icu->bezt[i].vec[1][0] < xmax ){ select_function(&(icu->bezt[i])); } } } void borderselect_ipo_key(Ipo *ipo, float xmin, float xmax, int selectmode) { /* Selects all bezier triples in each Ipocurve of the * Ipo between times xmin and xmax, using the selection mode. */ IpoCurve *icu; int (*select_function)(BezTriple *); /* If the ipo is no good then return */ if (!ipo) return; /* Set the selection function based on the * selection mode. */ switch(selectmode) { case SELECT_ADD: select_function = select_bezier_add; break; case SELECT_SUBTRACT: select_function = select_bezier_subtract; break; case SELECT_INVERT: select_function = select_bezier_invert; break; default: return; } /* loop through all of the bezier triples in all * of the Ipocurves -- if the triple occurs between * times xmin and xmax then select it using the selection * function */ for (icu=ipo->curve.first; icu; icu=icu->next){ borderselect_icu_key(icu, xmin, xmax, select_function); } } void select_ipo_key(Ipo *ipo, float selx, int selectmode) { /* Selects all bezier triples in each Ipocurve of the * Ipo at time selx, using the selection mode. */ int i; IpoCurve *icu; int (*select_function)(BezTriple *); /* If the ipo is no good then return */ if (!ipo) return; /* Set the selection function based on the * selection mode. */ switch(selectmode) { case SELECT_ADD: select_function = select_bezier_add; break; case SELECT_SUBTRACT: select_function = select_bezier_subtract; break; case SELECT_INVERT: select_function = select_bezier_invert; break; default: return; } /* loop through all of the bezier triples in all * of the Ipocurves -- if the triple occurs at * time selx then select it using the selection * function */ for (icu=ipo->curve.first; icu; icu=icu->next){ for (i=0; itotvert; i++){ if (icu->bezt[i].vec[1][0]==selx){ select_function(&(icu->bezt[i])); } } } } void select_icu_key(IpoCurve *icu, float selx, int selectmode) { /* Selects all bezier triples in the Ipocurve * at time selx, using the selection mode. * This is kind of sloppy the obvious similarities * with the above function, forgive me ... */ int i; int (*select_function)(BezTriple *); /* If the icu is no good then return */ if (!icu) return; /* Set the selection function based on the * selection mode. */ switch(selectmode) { case SELECT_ADD: select_function = select_bezier_add; break; case SELECT_SUBTRACT: select_function = select_bezier_subtract; break; case SELECT_INVERT: select_function = select_bezier_invert; break; default: return; } /* loop through all of the bezier triples in * the Ipocurve -- if the triple occurs at * time selx then select it using the selection * function */ for (i=0; itotvert; i++){ if (icu->bezt[i].vec[1][0]==selx){ select_function(&(icu->bezt[i])); } } }