4 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version. The Blender
10 * Foundation also sells licenses for use in proprietary software under
11 * the Blender License. See http://www.blender.org/BL/ for information
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24 * All rights reserved.
26 * The Original Code is: all of this file.
28 * Contributor(s): none yet.
30 * ***** END GPL/BL DUAL LICENSE BLOCK *****
34 /* this code feels over-complex, mostly because I choose in the past to devise a system
35 that converts the Ipo blocks (linked to Object, Material, etc), into a copy of that
36 data which is being worked on; the 'editipo'.
37 The editipo then can have 'ipokey' data, which is optimized for editing curves as if
38 it were key positions. This is still a great feature to work with, which makes ipo editing
39 in Blender still valuable. However, getting this beast under control was hard, even
54 #include "BLI_winstuff.h"
56 #include "MEM_guardedalloc.h"
59 #include "BLI_blenlib.h"
60 #include "BLI_arithb.h"
62 #include "DNA_constraint_types.h"
63 #include "DNA_action_types.h"
64 #include "DNA_armature_types.h"
65 #include "DNA_object_types.h"
66 #include "DNA_lamp_types.h"
67 #include "DNA_sequence_types.h"
68 #include "DNA_sound_types.h"
69 #include "DNA_camera_types.h"
70 #include "DNA_material_types.h"
71 #include "DNA_key_types.h"
72 #include "DNA_screen_types.h"
73 #include "DNA_scene_types.h"
74 #include "DNA_ipo_types.h"
75 #include "DNA_curve_types.h"
76 #include "DNA_space_types.h"
77 #include "DNA_userdef_types.h"
78 #include "DNA_view3d_types.h"
79 #include "DNA_group_types.h"
80 #include "DNA_ika_types.h"
82 #include "BKE_utildefines.h"
83 #include "BKE_action.h"
85 #include "BKE_material.h"
89 #include "BKE_displist.h"
90 #include "BKE_global.h"
91 #include "BKE_group.h"
93 #include "BIF_butspace.h"
94 #include "BIF_editkey.h"
95 #include "BIF_editseq.h"
96 #include "BIF_editview.h"
97 #include "BIF_interface.h"
98 #include "BIF_mywindow.h"
99 #include "BIF_poseobject.h"
100 #include "BIF_screen.h"
101 #include "BIF_space.h"
102 #include "BIF_toolbox.h"
103 #include "BIF_poseobject.h"
105 #include "BDR_drawobject.h"
106 #include "BDR_editobject.h"
108 #include "BSE_trans_types.h"
109 #include "BSE_editipo_types.h"
110 #include "BSE_drawipo.h"
111 #include "BSE_editipo.h"
112 #include "BSE_editaction.h"
113 #include "BSE_edit.h"
114 #include "BSE_drawview.h"
115 #include "BSE_headerbuttons.h"
118 #include "mydevice.h"
122 #define BEZSELECTED(bezt) (((bezt)->f1 & 1) || ((bezt)->f2 & 1) || ((bezt)->f3 & 1))
124 #define IPOTHRESH 0.9
125 #define ISPOIN(a, b, c) ( (a->b) && (a->c) )
126 #define ISPOIN3(a, b, c, d) ( (a->b) && (a->c) && (a->d) )
127 #define ISPOIN4(a, b, c, d, e) ( (a->b) && (a->c) && (a->d) && (a->e) )
141 void getname_ac_ei(int nr, char *str)
145 strcpy(str, "LocX"); break;
147 strcpy(str, "LocY"); break;
149 strcpy(str, "LocZ"); break;
151 strcpy(str, "SizeX"); break;
153 strcpy(str, "SizeY"); break;
155 strcpy(str, "SizeZ"); break;
157 strcpy(str, "QuatX"); break;
159 strcpy(str, "QuatY"); break;
161 strcpy(str, "QuatZ"); break;
163 strcpy(str, "QuatW"); break;
169 void getname_co_ei(int nr, char *str)
173 strcpy(str, "Inf"); break;
177 void getname_ob_ei(int nr, char *str, int colipo)
181 strcpy(str, "LocX"); break;
183 strcpy(str, "LocY"); break;
185 strcpy(str, "LocZ"); break;
187 strcpy(str, "dLocX"); break;
189 strcpy(str, "dLocY"); break;
191 strcpy(str, "dLocZ"); break;
194 strcpy(str, "RotX"); break;
196 strcpy(str, "RotY"); break;
198 strcpy(str, "RotZ"); break;
200 strcpy(str, "dRotX"); break;
202 strcpy(str, "dRotY"); break;
204 strcpy(str, "dRotZ"); break;
207 strcpy(str, "SizeX"); break;
209 strcpy(str, "SizeY"); break;
211 strcpy(str, "SizeZ"); break;
213 strcpy(str, "dSizeX"); break;
215 strcpy(str, "dSizeY"); break;
217 strcpy(str, "dSizeZ"); break;
220 strcpy(str, "Layer"); break;
223 strcpy(str, "Time"); break;
225 if(colipo) strcpy(str, "ColR");
226 else strcpy(str, "EffX");
229 if(colipo) strcpy(str, "ColG");
230 else strcpy(str, "EffY");
233 if(colipo) strcpy(str, "ColB");
234 else strcpy(str, "EffZ");
240 strcpy(str, "FStreng");
243 strcpy(str, "FFall");
246 strcpy(str, "Damping");
249 strcpy(str, "RDamp");
259 void getname_tex_ei(int nr, char *str)
263 strcpy(str, "OfsX"); break;
265 strcpy(str, "OfsY"); break;
267 strcpy(str, "OfsZ"); break;
269 strcpy(str, "SizeX"); break;
271 strcpy(str, "SizeY"); break;
273 strcpy(str, "SizeZ"); break;
275 strcpy(str, "texR"); break;
277 strcpy(str, "texG"); break;
279 strcpy(str, "texB"); break;
281 strcpy(str, "DefVar"); break;
283 strcpy(str, "Col"); break;
285 strcpy(str, "Nor"); break;
287 strcpy(str, "Var"); break;
293 void getname_mat_ei(int nr, char *str)
295 if(nr>=MA_MAP1) getname_tex_ei((nr & (MA_MAP1-1)), str);
299 strcpy(str, "R"); break;
301 strcpy(str, "G"); break;
303 strcpy(str, "B"); break;
305 strcpy(str, "SpecR"); break;
307 strcpy(str, "SpecG"); break;
309 strcpy(str, "SpecB"); break;
311 strcpy(str, "MirR"); break;
313 strcpy(str, "MirG"); break;
315 strcpy(str, "MirB"); break;
317 strcpy(str, "Ref"); break;
319 strcpy(str, "Alpha"); break;
321 strcpy(str, "Emit"); break;
323 strcpy(str, "Amb"); break;
325 strcpy(str, "Spec"); break;
327 strcpy(str, "Hard"); break;
329 strcpy(str, "SpTra"); break;
331 strcpy(str, "Ang"); break;
333 strcpy(str, "Mode"); break;
335 strcpy(str, "HaSize"); break;
342 void getname_world_ei(int nr, char *str)
344 if(nr>=MA_MAP1) getname_tex_ei((nr & (MA_MAP1-1)), str);
348 strcpy(str, "HorR"); break;
350 strcpy(str, "HorG"); break;
352 strcpy(str, "HorB"); break;
354 strcpy(str, "ZenR"); break;
356 strcpy(str, "ZenG"); break;
358 strcpy(str, "ZenB"); break;
361 strcpy(str, "Expos"); break;
364 strcpy(str, "Misi"); break;
366 strcpy(str, "MisDi"); break;
368 strcpy(str, "MisSta"); break;
370 strcpy(str, "MisHi"); break;
373 strcpy(str, "StarR"); break;
375 strcpy(str, "StarB"); break;
377 strcpy(str, "StarG"); break;
380 strcpy(str, "StarDi"); break;
382 strcpy(str, "StarSi"); break;
389 void getname_seq_ei(int nr, char *str)
393 strcpy(str, "Fac"); break;
399 void getname_cu_ei(int nr, char *str)
404 strcpy(str, "Speed"); break;
410 void getname_key_ei(int nr, char *str)
412 if(nr==KEY_SPEED) strcpy(str, "Speed");
413 else sprintf(str, "Key %d", nr);
416 void getname_la_ei(int nr, char *str)
418 if(nr>=MA_MAP1) getname_tex_ei((nr & (MA_MAP1-1)), str);
422 strcpy(str, "Energ"); break;
424 strcpy(str, "R"); break;
426 strcpy(str, "G"); break;
428 strcpy(str, "B"); break;
430 strcpy(str, "Dist"); break;
432 strcpy(str, "SpoSi"); break;
434 strcpy(str, "SpoBl"); break;
436 strcpy(str, "Quad1"); break;
438 strcpy(str, "Quad2"); break;
440 strcpy(str, "HaInt"); break;
447 void getname_cam_ei(int nr, char *str)
451 strcpy(str, "Lens"); break;
453 strcpy(str, "ClSta"); break;
455 strcpy(str, "ClEnd"); break;
461 void getname_snd_ei(int nr, char *str)
465 strcpy(str, "Vol"); break;
467 strcpy(str, "Pitch"); break;
469 strcpy(str, "Pan"); break;
471 strcpy(str, "Atten"); break;
478 IpoCurve *find_ipocurve(Ipo *ipo, int adrcode)
481 IpoCurve *icu= ipo->curve.first;
483 if(icu->adrcode==adrcode) return icu;
490 void boundbox_ipocurve(IpoCurve *icu)
493 float vec[3]={0.0,0.0,0.0};
494 float min[3], max[3];
498 INIT_MINMAX(min, max);
504 if(icu->vartype & IPO_BITS) {
505 vec[0]= bezt->vec[1][0];
507 DO_MINMAX(vec, min, max);
510 DO_MINMAX(vec, min, max);
513 if(icu->ipo==IPO_BEZ && a!=icu->totvert-1) {
514 DO_MINMAX(bezt->vec[0], min, max);
516 DO_MINMAX(bezt->vec[1], min, max);
517 if(icu->ipo==IPO_BEZ && a!=0) {
518 DO_MINMAX(bezt->vec[2], min, max);
525 if(min[0]==max[0]) max[0]= (float)(min[0]+1.0);
526 if(min[1]==max[1]) max[1]= (float)(min[1]+0.1);
528 icu->totrct.xmin= min[0];
529 icu->totrct.ymin= min[1];
530 icu->totrct.xmax= max[0];
531 icu->totrct.ymax= max[1];
534 icu->totrct.xmin= icu->totrct.ymin= 0.0;
535 icu->totrct.xmax= EFRA;
536 icu->totrct.ymax= 1.0;
540 void boundbox_ipo(Ipo *ipo, rctf *bb)
545 icu= ipo->curve.first;
548 boundbox_ipocurve(icu);
554 else BLI_union_rctf(bb, &(icu->totrct));
562 void editipo_changed(SpaceIpo *si, int doredraw)
575 for(a=0; a<si->totipo; a++, ei++) {
579 /* twice because of ittererating new autohandle */
580 calchandles_ipocurve(ei->icu);
581 calchandles_ipocurve(ei->icu);
583 if(ei->flag & IPO_VISIBLE) {
585 boundbox_ipocurve(ei->icu);
586 sort_time_ipocurve(ei->icu);
588 si->v2d.tot= ei->icu->totrct;
591 else BLI_union_rctf(&(si->v2d.tot), &(ei->icu->totrct));
599 if(si->blocktype==ID_KE) {
600 key= (Key *)si->from;
601 if(key && key->block.first) {
602 kb= key->block.first;
603 if(kb->pos < v2d->tot.ymin) v2d->tot.ymin= kb->pos;
605 if(kb->pos > v2d->tot.ymax) v2d->tot.ymax= kb->pos;
610 /* is there no curve? */
614 v2d->tot.ymin= (float)-0.1;
615 v2d->tot.ymax= (float)1.1;
617 if(si->blocktype==ID_SEQ) {
619 v2d->tot.xmax= 105.0;
620 v2d->tot.ymin= (float)-0.1;
621 v2d->tot.ymax= (float)1.1;
628 /* if you always call do_ipo: you get problems with insertkey, for example
629 * when inserting only a 'loc' the 'ob->rot' value then is changed.
632 if(si->blocktype==ID_OB) {
633 /* clear delta loc,rot,size (when free/delete ipo) */
634 clear_delta_obipo(si->ipo);
640 allqueue(REDRAWIPO, 0);
641 allqueue (REDRAWACTION, 0);
642 allqueue(REDRAWNLA, 0);
643 allqueue(REDRAWBUTSOBJECT, 0);
645 if(si->blocktype==ID_OB) {
646 Object *ob= (Object *)si->from;
647 if(ob && ob->type==OB_IKA) itterate_ika(ob);
648 allqueue(REDRAWVIEW3D, 0);
649 allqueue(REDRAWNLA, 0);
652 else if(si->blocktype==ID_MA) allqueue(REDRAWBUTSSHADING, 0);
653 else if(si->blocktype==ID_WO) allqueue(REDRAWBUTSSHADING, 0);
654 else if(si->blocktype==ID_LA) allqueue(REDRAWBUTSSHADING, 0);
655 // else if(si->blocktype==ID_SO) allqueue(REDRAWBUTSSOUND, 0);
656 else if(si->blocktype==ID_CA) {
657 allqueue(REDRAWBUTSEDIT, 0);
658 allqueue(REDRAWVIEW3D, 0);
660 else if(si->blocktype==ID_SEQ) clear_last_seq();
661 else if(si->blocktype==ID_AC){
663 allqueue(REDRAWACTION, 0);
664 allqueue(REDRAWNLA, 0);
666 else if(si->blocktype==ID_KE) {
667 do_spec_key((Key *)si->from);
668 allqueue(REDRAWVIEW3D, 0);
670 else if(si->blocktype==ID_CU) {
671 calc_curvepath(OBACT);
672 allqueue(REDRAWVIEW3D, 0);
676 if(si->showkey) make_ipokey();
681 /* comes from buttons, scale with G.sipo->tot rect */
688 facx= (G.sipo->tot.xmax-G.sipo->tot.xmin)/(G.sipo->v2d.tot.xmax-G.sipo->v2d.tot.xmin);
689 facy= (G.sipo->tot.ymax-G.sipo->tot.ymin)/(G.sipo->v2d.tot.ymax-G.sipo->v2d.tot.ymin);
693 for(a=0; a<G.sipo->totipo; a++, ei++) {
694 if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
699 bezt->vec[0][0]= facx*(bezt->vec[0][0] - G.sipo->v2d.tot.xmin) + G.sipo->tot.xmin;
700 bezt->vec[1][0]= facx*(bezt->vec[1][0] - G.sipo->v2d.tot.xmin) + G.sipo->tot.xmin;
701 bezt->vec[2][0]= facx*(bezt->vec[2][0] - G.sipo->v2d.tot.xmin) + G.sipo->tot.xmin;
703 bezt->vec[0][1]= facy*(bezt->vec[0][1] - G.sipo->v2d.tot.ymin) + G.sipo->tot.ymin;
704 bezt->vec[1][1]= facy*(bezt->vec[1][1] - G.sipo->v2d.tot.ymin) + G.sipo->tot.ymin;
705 bezt->vec[2][1]= facy*(bezt->vec[2][1] - G.sipo->v2d.tot.ymin) + G.sipo->tot.ymin;
711 editipo_changed(G.sipo, 1);
712 allqueue(REDRAWNLA, 0);
713 allqueue (REDRAWACTION, 0);
714 allqueue(REDRAWIPO, 0);
718 Ipo *get_ipo_to_edit(ID **from)
726 *from = G.sipo->from;
730 if(G.sipo->blocktype==ID_SEQ) {
731 extern Sequence *last_seq;
733 *from= (ID *)last_seq;
734 if(last_seq) return last_seq->ipo;
736 else if(G.sipo->blocktype==IPO_CO){
737 if (ob && ob->activecon){
739 return ob->activecon->ipo;
742 else if(G.sipo->blocktype==ID_AC) {
743 bActionChannel *chan;
744 if (ob && ob->action){
745 *from= (ID *) ob->action;
746 chan= get_hilighted_action_channel(ob->action);
756 else if(G.sipo->blocktype==ID_WO) {
757 World *wo= G.scene->world;
759 if(wo) return wo->ipo;
761 else if(G.sipo->blocktype==ID_OB) {
767 else if(G.sipo->blocktype==ID_MA) {
769 Material *ma= give_current_material(ob, ob->actcol);
771 if(ma) return ma->ipo;
774 else if(G.sipo->blocktype==ID_KE) {
776 Key *key= give_current_key(ob);
778 if(key) return key->ipo;
781 else if(G.sipo->blocktype==ID_CU) {
782 if(ob && ob->type==OB_CURVE) {
788 else if(G.sipo->blocktype==ID_LA) {
789 if(ob && ob->type==OB_LAMP) {
795 else if(G.sipo->blocktype==ID_CA) {
796 if(ob && ob->type==OB_CAMERA) {
797 Camera *ca= ob->data;
799 if(ca) return ca->ipo;
802 else if(G.sipo->blocktype==ID_SO) {
804 // if (G.buts && G.buts->mainb == BUTS_SOUND) {
805 // bSound *sound = G.buts->lockpoin;
806 // *from= (ID *)sound;
807 // if(sound) return sound->ipo;
814 unsigned int ipo_rainbow(int cur, int tot)
816 float dfac, fac, sat;
818 dfac= (float)(1.0/( (float)tot+1.0));
820 /* this calculation makes 2 different cycles of rainbow colors */
821 if(cur< tot/2) fac= (float)(cur*2.0*dfac);
822 else fac= (float)((cur-tot/2)*2.0*dfac +dfac);
824 if(fac>0.5 && fac<0.8) sat= (float)0.4;
827 return hsv_to_cpack(fac, sat, 1.0);
830 void make_ob_editipo(Object *ob, SpaceIpo *si)
833 int a, len, colipo=0;
835 if(ob->type==OB_MESH) colipo= 1;
837 ei= si->editipo= MEM_callocN(OB_TOTIPO*sizeof(EditIpo), "editipo");
839 si->totipo= OB_TOTIPO;
841 for(a=0; a<OB_TOTIPO; a++) {
842 getname_ob_ei(ob_ar[a], ei->name, colipo);
843 ei->adrcode= ob_ar[a];
845 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;
846 else if(ei->adrcode==OB_LAY) ei->disptype= IPO_DISPBITS;
847 else if(ei->adrcode==OB_TIME) ei->disptype= IPO_DISPTIME;
849 ei->col= ipo_rainbow(a, OB_TOTIPO);
852 len= strlen(ei->name);
854 if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF;
855 else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50;
856 else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050;
860 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
862 ei->flag= ei->icu->flag;
870 void make_seq_editipo(SpaceIpo *si)
875 ei= si->editipo= MEM_callocN(SEQ_TOTIPO*sizeof(EditIpo), "editipo");
877 si->totipo= SEQ_TOTIPO;
880 for(a=0; a<SEQ_TOTIPO; a++) {
881 getname_seq_ei(seq_ar[a], ei->name);
882 ei->adrcode= seq_ar[a];
884 ei->col= ipo_rainbow(a, SEQ_TOTIPO);
886 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
888 ei->flag= ei->icu->flag;
890 else ei->flag |= IPO_VISIBLE;
896 void make_cu_editipo(SpaceIpo *si)
901 ei= si->editipo= MEM_callocN(CU_TOTIPO*sizeof(EditIpo), "editipo");
903 si->totipo= CU_TOTIPO;
906 for(a=0; a<CU_TOTIPO; a++) {
907 getname_cu_ei(cu_ar[a], ei->name);
908 ei->adrcode= cu_ar[a];
910 ei->col= ipo_rainbow(a, CU_TOTIPO);
912 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
914 ei->flag= ei->icu->flag;
916 else ei->flag |= IPO_VISIBLE;
922 void make_key_editipo(SpaceIpo *si)
929 ei= si->editipo= MEM_callocN(KEY_TOTIPO*sizeof(EditIpo), "editipo");
931 si->totipo= KEY_TOTIPO;
933 key= (Key *)G.sipo->from;
934 if(key) kb= key->block.first;
936 for(a=0; a<KEY_TOTIPO; a++, ei++) {
937 if(kb && kb->name[0] != 0) strncpy(ei->name, kb->name, 32); // length both same
938 else getname_key_ei(key_ar[a], ei->name);
939 ei->adrcode= key_ar[a];
941 ei->col= ipo_rainbow(a, KEY_TOTIPO);
943 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
945 ei->flag= ei->icu->flag;
947 else if(a==0) ei->flag |= IPO_VISIBLE;
953 if(key && key->type==KEY_RELATIVE) {
954 strcpy(ei->name, "----");
957 ei->flag |= IPO_VISIBLE;
961 int texchannel_to_adrcode(int channel)
964 case 0: return MA_MAP1;
965 case 1: return MA_MAP2;
966 case 2: return MA_MAP3;
967 case 3: return MA_MAP4;
968 case 4: return MA_MAP5;
969 case 5: return MA_MAP6;
970 case 6: return MA_MAP7;
971 case 7: return MA_MAP8;
976 void make_mat_editipo(SpaceIpo *si)
981 if(si->from==0) return;
983 ei= si->editipo= MEM_callocN(MA_TOTIPO*sizeof(EditIpo), "editipo");
985 si->totipo= MA_TOTIPO;
987 for(a=0; a<MA_TOTIPO; a++) {
988 getname_mat_ei(ma_ar[a], ei->name);
989 ei->adrcode= ma_ar[a];
991 if(ei->adrcode & MA_MAP1) {
992 ei->adrcode-= MA_MAP1;
993 ei->adrcode |= texchannel_to_adrcode(si->channel);
996 if(ei->adrcode==MA_MODE) ei->disptype= IPO_DISPBITS;
999 ei->col= ipo_rainbow(a, WO_TOTIPO);
1001 len= strlen(ei->name);
1003 if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF;
1004 else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50;
1005 else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050;
1008 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
1010 ei->flag= ei->icu->flag;
1017 void make_world_editipo(SpaceIpo *si)
1022 if(si->from==0) return;
1024 ei= si->editipo= MEM_callocN(WO_TOTIPO*sizeof(EditIpo), "editipo");
1026 si->totipo= WO_TOTIPO;
1028 for(a=0; a<WO_TOTIPO; a++) {
1029 getname_world_ei(wo_ar[a], ei->name);
1030 ei->adrcode= wo_ar[a];
1032 if(ei->adrcode & MA_MAP1) {
1033 ei->adrcode-= MA_MAP1;
1034 ei->adrcode |= texchannel_to_adrcode(si->channel);
1037 if(ei->adrcode==MA_MODE) ei->disptype= IPO_DISPBITS;
1040 ei->col= ipo_rainbow(a, MA_TOTIPO);
1042 len= strlen(ei->name);
1044 if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF;
1045 else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50;
1046 else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050;
1049 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
1051 ei->flag= ei->icu->flag;
1058 void make_lamp_editipo(SpaceIpo *si)
1063 ei= si->editipo= MEM_callocN(LA_TOTIPO*sizeof(EditIpo), "editipo");
1065 si->totipo= LA_TOTIPO;
1068 for(a=0; a<LA_TOTIPO; a++) {
1069 getname_la_ei(la_ar[a], ei->name);
1070 ei->adrcode= la_ar[a];
1072 if(ei->adrcode & MA_MAP1) {
1073 ei->adrcode-= MA_MAP1;
1074 ei->adrcode |= texchannel_to_adrcode(si->channel);
1077 ei->col= ipo_rainbow(a, LA_TOTIPO);
1079 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
1081 ei->flag= ei->icu->flag;
1088 void make_camera_editipo(SpaceIpo *si)
1093 ei= si->editipo= MEM_callocN(CAM_TOTIPO*sizeof(EditIpo), "editipo");
1095 si->totipo= CAM_TOTIPO;
1098 for(a=0; a<CAM_TOTIPO; a++) {
1099 getname_cam_ei(cam_ar[a], ei->name);
1100 ei->adrcode= cam_ar[a];
1102 ei->col= ipo_rainbow(a, CAM_TOTIPO);
1104 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
1106 ei->flag= ei->icu->flag;
1113 int make_constraint_editipo(Ipo *ipo, EditIpo **si)
1118 ei= *si= MEM_callocN(CO_TOTIPO*sizeof(EditIpo), "editipo");
1120 for(a=0; a<CO_TOTIPO; a++) {
1121 getname_co_ei(co_ar[a], ei->name);
1122 ei->adrcode= co_ar[a];
1124 ei->col= ipo_rainbow(a, CO_TOTIPO);
1126 ei->icu= find_ipocurve(ipo, ei->adrcode);
1128 ei->flag= ei->icu->flag;
1136 int make_action_editipo(Ipo *ipo, EditIpo **si)
1141 ei= *si= MEM_callocN(AC_TOTIPO*sizeof(EditIpo), "editipo");
1143 for(a=0; a<AC_TOTIPO; a++) {
1144 getname_ac_ei(ac_ar[a], ei->name);
1145 ei->adrcode= ac_ar[a];
1147 ei->col= ipo_rainbow(a, AC_TOTIPO);
1149 ei->icu= find_ipocurve(ipo, ei->adrcode);
1151 ei->flag= ei->icu->flag;
1160 void make_sound_editipo(SpaceIpo *si)
1165 ei= si->editipo= MEM_callocN(SND_TOTIPO*sizeof(EditIpo), "editipo");
1167 si->totipo= SND_TOTIPO;
1170 for(a=0; a<SND_TOTIPO; a++) {
1171 getname_snd_ei(snd_ar[a], ei->name);
1172 ei->adrcode= snd_ar[a];
1174 ei->col= ipo_rainbow(a, SND_TOTIPO);
1176 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
1178 ei->flag= ei->icu->flag;
1194 MEM_freeN(G.sipo->editipo);
1199 G.sipo->ipo= get_ipo_to_edit(&from);
1202 if(G.sipo->ipo) G.sipo->showkey= G.sipo->ipo->showkey;
1204 if(G.sipo->blocktype==ID_SEQ) {
1205 make_seq_editipo(G.sipo);
1207 else if(G.sipo->blocktype==ID_WO) {
1208 make_world_editipo(G.sipo);
1210 else if(G.sipo->blocktype==ID_OB) {
1213 make_ob_editipo(ob, G.sipo);
1216 else if(G.sipo->blocktype==ID_MA) {
1219 make_mat_editipo(G.sipo);
1222 else if(G.sipo->blocktype==ID_CU) {
1225 make_cu_editipo(G.sipo);
1228 else if(G.sipo->blocktype==ID_KE) {
1231 make_key_editipo(G.sipo);
1234 else if(G.sipo->blocktype==ID_LA) {
1237 make_lamp_editipo(G.sipo);
1240 else if(G.sipo->blocktype==ID_CA) {
1243 make_camera_editipo(G.sipo);
1246 else if(G.sipo->blocktype==ID_SO) {
1249 make_sound_editipo(G.sipo);
1252 else if(G.sipo->blocktype==IPO_CO){
1253 G.sipo->totipo = make_constraint_editipo(G.sipo->ipo, (EditIpo**)&G.sipo->editipo);
1258 else if(G.sipo->blocktype==ID_AC) {
1260 G.sipo->totipo = make_action_editipo(G.sipo->ipo, (EditIpo**)&G.sipo->editipo);
1266 if(G.sipo->editipo==0) return;
1268 /* rowbut for VISIBLE select */
1270 ei= G.sipo->editipo;
1271 for(a=0; a<G.sipo->totipo; a++, ei++) {
1273 if(ei->flag & IPO_VISIBLE) G.sipo->rowbut |= (1<<a);
1275 if(ei->icu) ei->icu->flag= ei->flag;
1277 editipo_changed(G.sipo, 0);
1282 rf= &(G.sipo->v2d.cur);
1284 rf= &(G.sipo->ipo->cur);
1286 if(rf->xmin<rf->xmax && rf->ymin<rf->ymax) G.v2d->cur= *rf;
1290 if(G.sipo->blocktype==ID_OB) {
1291 G.v2d->cur.xmin= 0.0;
1292 G.v2d->cur.xmax= EFRA;
1293 G.v2d->cur.ymin= -5.0;
1294 G.v2d->cur.ymax= +5.0;
1296 else if(G.sipo->blocktype==ID_CA) {
1297 G.v2d->cur.xmin= 0.0;
1298 G.v2d->cur.xmax= EFRA;
1299 G.v2d->cur.ymin= 0.0;
1300 G.v2d->cur.ymax= 100.0;
1302 else if ELEM5(G.sipo->blocktype, ID_MA, ID_CU, ID_WO, ID_LA, IPO_CO) {
1303 G.v2d->cur.xmin= (float)-0.1;
1304 G.v2d->cur.xmax= EFRA;
1305 G.v2d->cur.ymin= (float)-0.1;
1306 G.v2d->cur.ymax= (float)+1.1;
1308 else if(G.sipo->blocktype==ID_SEQ) {
1309 G.v2d->cur.xmin= -5.0;
1310 G.v2d->cur.xmax= 105.0;
1311 G.v2d->cur.ymin= (float)-0.1;
1312 G.v2d->cur.ymax= (float)+1.1;
1314 else if(G.sipo->blocktype==ID_KE) {
1315 G.v2d->cur.xmin= (float)-0.1;
1316 G.v2d->cur.xmax= EFRA;
1317 G.v2d->cur.ymin= (float)-0.1;
1318 G.v2d->cur.ymax= (float)+2.1;
1330 if(G.sipo->editipo==0){
1334 ipo= get_ipo_to_edit(&from);
1336 if(G.sipo->ipo != ipo || G.sipo->from!=from)
1346 G.sipo->ipo->cur = G.v2d->cur;
1350 /* ****************************************** */
1352 int totipo_edit, totipo_sel, totipo_vis, totipo_vert, totipo_vertsel, totipo_key, totipo_keysel;
1354 void get_status_editipo()
1369 if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
1371 ei= G.sipo->editipo;
1373 for(a=0; a<G.sipo->totipo; a++) {
1374 if( ei->flag & IPO_VISIBLE ) {
1376 if(ei->flag & IPO_SELECT) totipo_sel++;
1377 if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
1379 /* if showkey: do count the vertices (for grab) */
1380 if(G.sipo->showkey==0) totipo_edit++;
1384 bezt= ei->icu->bezt;
1385 b= ei->icu->totvert;
1387 if(ei->icu->ipo==IPO_BEZ) {
1388 if(bezt->f1 & 1) totipo_vertsel++;
1389 if(bezt->f3 & 1) totipo_vertsel++;
1392 if(bezt->f2 & 1) totipo_vertsel++;
1404 if(G.sipo->showkey) {
1405 ik= G.sipo->ipokey.first;
1408 if(ik->flag & 1) totipo_keysel++;
1416 void update_editipo_flags()
1423 ei= G.sipo->editipo;
1425 for(a=0; a<G.sipo->totipo; a++, ei++) {
1426 ei->flag &= ~IPO_VISIBLE;
1428 if( G.sipo->rowbut & flag ) ei->flag |= IPO_VISIBLE;
1430 if(ei->icu) ei->icu->flag= ei->flag;
1434 if(G.sipo->showkey) {
1435 ik= G.sipo->ipokey.first;
1437 for(a=0; a<G.sipo->totipo; a++) {
1440 ik->data[a]->f1 |= 1;
1441 ik->data[a]->f2 |= 1;
1442 ik->data[a]->f3 |= 1;
1445 ik->data[a]->f1 &= ~1;
1446 ik->data[a]->f2 &= ~1;
1447 ik->data[a]->f3 &= ~1;
1456 void set_editflag_editipo()
1459 int a; /* , tot= 0, ok= 0; */
1461 /* after showkey immediately go to editing of selected points */
1462 if(G.sipo->showkey) {
1464 if(G.sipo->ipo) G.sipo->ipo->showkey= 0;
1465 ei= G.sipo->editipo;
1466 for(a=0; a<G.sipo->totipo; a++, ei++) ei->flag |= IPO_SELECT;
1467 scrarea_queue_headredraw(curarea);
1468 allqueue(REDRAWVIEW3D, 0);
1471 get_status_editipo();
1473 if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
1475 ei= G.sipo->editipo;
1476 for(a=0; a<G.sipo->totipo; a++, ei++) {
1478 if(ei->flag & IPO_VISIBLE) {
1480 if(totipo_edit==0 && (ei->flag & IPO_SELECT)) {
1481 ei->flag |= IPO_EDIT;
1482 ei->icu->flag= ei->flag;
1484 else if(totipo_edit && (ei->flag & IPO_EDIT)) {
1485 ei->flag -= IPO_EDIT;
1486 ei->icu->flag= ei->flag;
1488 else if(totipo_vis==1) {
1489 if(ei->flag & IPO_EDIT) ei->flag -= IPO_EDIT;
1490 else ei->flag |= IPO_EDIT;
1491 ei->icu->flag= ei->flag;
1496 scrarea_queue_headredraw(curarea);
1497 scrarea_queue_winredraw(curarea);
1500 void ipo_toggle_showkey(void) {
1501 if(G.sipo->showkey) {
1503 swap_selectall_editipo(); /* sel all */
1505 else G.sipo->showkey= 1;
1506 free_ipokey(&G.sipo->ipokey);
1507 if(G.sipo->ipo) G.sipo->ipo->showkey= G.sipo->showkey;
1510 void swap_selectall_editipo()
1516 int a, b; /* , sel=0; */
1521 get_status_editipo();
1525 if(G.sipo->showkey) {
1526 ik= G.sipo->ipokey.first;
1528 if(totipo_vertsel) ik->flag &= ~1;
1532 update_editipo_flags();
1534 if(G.sipo->showkey && G.sipo->blocktype==ID_OB ) {
1536 if(ob && (ob->ipoflag & OB_DRAWKEY)) draw_object_ext(BASACT);
1539 else if(totipo_edit==0) {
1540 ei= G.sipo->editipo;
1542 for(a=0; a<G.sipo->totipo; a++) {
1543 if( ei->flag & IPO_VISIBLE ) {
1544 if(totipo_sel) ei->flag &= ~IPO_SELECT;
1545 else ei->flag |= IPO_SELECT;
1549 update_editipo_flags();
1553 ei= G.sipo->editipo;
1554 for(a=0; a<G.sipo->totipo; a++) {
1555 if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu ) {
1556 bezt= ei->icu->bezt;
1558 b= ei->icu->totvert;
1560 if(totipo_vertsel) {
1561 bezt->f1= bezt->f2= bezt->f3= 0;
1564 bezt->f1= bezt->f2= bezt->f3= 1;
1575 scrarea_queue_winredraw(curarea);
1579 void swap_visible_editipo()
1583 int a; /* , sel=0; */
1585 get_status_editipo();
1589 ei= G.sipo->editipo;
1590 for(a=0; a<G.sipo->totipo; a++) {
1593 ei->flag |= IPO_VISIBLE;
1594 G.sipo->rowbut |= (1<<a);
1597 else ei->flag &= ~IPO_VISIBLE;
1601 update_editipo_flags();
1603 if(G.sipo->showkey) {
1608 if(ob && (ob->ipoflag & OB_DRAWKEY)) allqueue(REDRAWVIEW3D, 0);
1611 scrarea_queue_winredraw(curarea);
1615 void deselectall_editipo()
1620 int a, b; /* , sel=0; */
1624 get_status_editipo();
1626 if(G.sipo->showkey) {
1627 ik= G.sipo->ipokey.first;
1632 update_editipo_flags();
1635 else if(totipo_edit==0) {
1637 ei= G.sipo->editipo;
1638 for(a=0; a<G.sipo->totipo; a++) {
1639 if( ei->flag & IPO_VISIBLE ) {
1640 ei->flag &= ~IPO_SELECT;
1644 update_editipo_flags();
1647 ei= G.sipo->editipo;
1648 for(a=0; a<G.sipo->totipo; a++) {
1649 if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu ) {
1651 bezt= ei->icu->bezt;
1652 b= ei->icu->totvert;
1654 bezt->f1= bezt->f2= bezt->f3= 0;
1663 scrarea_queue_winredraw(curarea);
1666 short findnearest_ipovert(IpoCurve **icu, BezTriple **bezt)
1668 /* selected verts get a disadvantage */
1669 /* in icu and (bezt or bp) the nearest is written */
1670 /* return 0 1 2: handlepunt */
1673 int dist= 100, temp, a, b;
1674 short mval[2], hpoint=0;
1679 getmouseco_areawin(mval);
1681 ei= G.sipo->editipo;
1682 for(a=0; a<G.sipo->totipo; a++, ei++) {
1683 if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu) {
1686 bezt1= ei->icu->bezt;
1687 b= ei->icu->totvert;
1690 ipoco_to_areaco_noclip(G.v2d, bezt1->vec[0], bezt1->s[0]);
1691 ipoco_to_areaco_noclip(G.v2d, bezt1->vec[1], bezt1->s[1]);
1692 ipoco_to_areaco_noclip(G.v2d, bezt1->vec[2], bezt1->s[2]);
1694 if(ei->disptype==IPO_DISPBITS) {
1695 temp= abs(mval[0]- bezt1->s[1][0]);
1697 else temp= abs(mval[0]- bezt1->s[1][0])+ abs(mval[1]- bezt1->s[1][1]);
1699 if( bezt1->f2 & 1) temp+=5;
1707 if(ei->disptype!=IPO_DISPBITS && ei->icu->ipo==IPO_BEZ) {
1708 /* middle points get an advantage */
1709 temp= -3+abs(mval[0]- bezt1->s[0][0])+ abs(mval[1]- bezt1->s[0][1]);
1710 if( bezt1->f1 & 1) temp+=5;
1718 temp= abs(mval[0]- bezt1->s[2][0])+ abs(mval[1]- bezt1->s[2][1]);
1719 if( bezt1->f3 & 1) temp+=5;
1737 void move_to_frame()
1745 if(G.sipo->editipo==0) return;
1747 ei= G.sipo->editipo;
1749 for(a=0; a<G.sipo->totipo; a++, ei++) {
1750 if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
1751 if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
1755 b= ei->icu->totvert;
1756 bezt= ei->icu->bezt;
1758 if(BEZSELECTED(bezt)) {
1760 cfra= bezt->vec[1][0]/G.scene->r.framelen;
1763 if(id && GS(id->name)==ID_OB ) {
1764 Object *ob= (Object *)id;
1765 if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
1766 cfra+= ob->sf/G.scene->r.framelen;
1769 CFRA= (short)floor(cfra+0.5);
1771 if(CFRA < 1) CFRA= 1;
1772 update_for_newframe();
1784 /* *********************************** */
1786 void do_ipowin_buts(short event)
1788 if((G.qual & LR_SHIFTKEY)==0) {
1789 G.sipo->rowbut= (1<<event);
1791 scrarea_queue_winredraw(curarea);
1793 update_editipo_flags();
1795 if(G.sipo->showkey) {
1797 if(G.sipo->blocktype==ID_OB) allqueue(REDRAWVIEW3D, 0);
1802 void do_ipo_selectbuttons()
1808 if(G.sipo->showkey) return;
1810 /* do not allow editipo here: convert editipos to selected */
1811 get_status_editipo();
1813 set_editflag_editipo();
1817 getmouseco_areawin(mval);
1819 nr= -(mval[1]-curarea->winy+30-G.sipo->butofs-IPOBUTY)/IPOBUTY;
1820 if(nr>=0 && nr<G.sipo->totipo) {
1821 ei= G.sipo->editipo;
1825 if((ei->flag & IPO_VISIBLE)==0) {
1826 ei->flag |= IPO_VISIBLE;
1827 G.sipo->rowbut |= (1<<nr);
1830 if((G.qual & LR_SHIFTKEY)==0) {
1831 ei1= G.sipo->editipo;
1832 for(a=0; a<G.sipo->totipo; a++) {
1833 ei1->flag &= ~IPO_SELECT;
1838 if(ei->flag & IPO_SELECT) {
1839 ei->flag &= ~IPO_SELECT;
1842 ei->flag |= IPO_SELECT;
1845 update_editipo_flags();
1846 scrarea_queue_winredraw(curarea);
1851 /* ******************************************* */
1853 EditIpo *get_editipo()
1856 int a; /* , sel=0; */
1858 get_status_editipo();
1863 if(G.sipo->editipo==0) return 0;
1865 ei= G.sipo->editipo;
1866 for(a=0; a<G.sipo->totipo; a++) {
1867 if(ei->flag & IPO_VISIBLE) {
1868 if( ei->flag & IPO_EDIT ) return ei;
1869 else if(totipo_vis==1) return ei;
1871 if(ei->flag & IPO_SELECT) {
1872 if(totipo_sel==1) return ei;
1881 Ipo *get_ipo(ID *from, short type, int make)
1896 if(ob->id.lib) return 0;
1899 if(make && ipo==0) ipo= ob->ipo= add_ipo("ObIpo", ID_OB);
1901 else if( type==IPO_CO){
1903 if(ob->id.lib) return 0;
1906 ipo= ob->activecon->ipo;
1907 if(make && ipo==0) ipo= ob->activecon->ipo= add_ipo("CoIpo", IPO_CO);
1910 else if( type==ID_AC) {
1911 act= (bAction *)from;
1912 if (!act->achan) return 0;
1913 if (act->id.lib) return 0;
1914 ipo= act->achan->ipo;
1916 /* This should never happen */
1917 if(make && ipo==0) ipo= act->achan->ipo= add_ipo("AcIpo", ID_AC);
1919 else if( type==ID_MA) {
1920 ma= (Material *)from;
1921 if(ma->id.lib) return 0;
1924 if(make && ipo==0) ipo= ma->ipo= add_ipo("MatIpo", ID_MA);
1927 else if( type==ID_SEQ) {
1928 seq= (Sequence *)from;
1930 if((seq->type & SEQ_EFFECT)||(seq->type == SEQ_SOUND)) {
1932 if(make && ipo==0) ipo= seq->ipo= add_ipo("SeqIpo", ID_SEQ);
1936 else if( type==ID_CU) {
1938 if(cu->id.lib) return 0;
1941 if(make && ipo==0) ipo= cu->ipo= add_ipo("CuIpo", ID_CU);
1943 else if( type==ID_KE) {
1945 if(key->id.lib) return 0;
1948 if(make && ipo==0) ipo= key->ipo= add_ipo("KeyIpo", ID_KE);
1950 else if( type==ID_WO) {
1952 if(wo->id.lib) return 0;
1955 if(make && ipo==0) ipo= wo->ipo= add_ipo("WoIpo", ID_WO);
1957 else if( type==ID_LA) {
1959 if(la->id.lib) return 0;
1962 if(make && ipo==0) ipo= la->ipo= add_ipo("LaIpo", ID_LA);
1964 else if( type==ID_CA) {
1966 if(ca->id.lib) return 0;
1969 if(make && ipo==0) ipo= ca->ipo= add_ipo("CaIpo", ID_CA);
1971 else if( type==ID_SO) {
1972 bSound *snd= (bSound *)from;
1973 if(snd->id.lib) return 0;
1976 if(make && ipo==0) ipo= snd->ipo= add_ipo("SndIpo", ID_SO);
1984 // this function should not have the G.sipo in it...
1986 IpoCurve *get_ipocurve(ID *from, short type, int adrcode, Ipo *useipo)
1991 /* return 0 if lib */
1992 /* also test if ipo and ipocurve exist */
1996 if (G.sipo==NULL || G.sipo->pin==0){
1997 ipo= get_ipo(from, type, 1); /* 1= make */
2004 if (G.sipo->pin==0) G.sipo->ipo= ipo;
2011 if(ipo && ipo->id.lib==0) {
2013 icu= ipo->curve.first;
2015 if(icu->adrcode==adrcode) break;
2019 icu= MEM_callocN(sizeof(IpoCurve), "ipocurve");
2021 icu->flag |= IPO_VISIBLE;
2023 if (!useipo && G.sipo && G.sipo->pin)
2024 icu->blocktype = G.sipo->blocktype;
2026 icu->blocktype= type;
2027 icu->adrcode= adrcode;
2031 BLI_addtail( &(ipo->curve), icu);
2037 void insert_vert_ipo(IpoCurve *icu, float x, float y)
2039 BezTriple *bezt, beztr, *newbezt;
2042 memset(&beztr, 0, sizeof(BezTriple));
2045 beztr.hide= IPO_BEZ;
2046 beztr.f1= beztr.f2= beztr.f3= SELECT;
2047 beztr.h1= beztr.h2= HD_AUTO;
2052 icu->bezt= MEM_callocN( sizeof(BezTriple), "beztriple");
2053 *(icu->bezt)= beztr;
2057 /* all vertices deselect */
2058 for(a=0; a<icu->totvert; a++, bezt++) {
2059 bezt->f1= bezt->f2= bezt->f3= 0;
2063 for(a=0; a<=icu->totvert; a++, bezt++) {
2065 /* no double points */
2066 if(a<icu->totvert && (bezt->vec[1][0]>x-IPOTHRESH && bezt->vec[1][0]<x+IPOTHRESH)) {
2070 if(a==icu->totvert || bezt->vec[1][0] > x) {
2071 newbezt= MEM_callocN( (icu->totvert+1)*sizeof(BezTriple), "beztriple");
2073 if(a>0) memcpy(newbezt, icu->bezt, a*sizeof(BezTriple));
2078 if(a<icu->totvert) memcpy(newbezt+a+1, icu->bezt+a, (icu->totvert-a)*sizeof(BezTriple));
2080 MEM_freeN(icu->bezt);
2090 calchandles_ipocurve(icu);
2092 /* set handletype */
2093 if(icu->totvert>2) {
2095 if(a>0) h1= (bezt-1)->h2;
2096 if(a<icu->totvert-1) h2= (bezt+1)->h1;
2100 calchandles_ipocurve(icu);
2111 if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
2112 if(G.sipo->showkey) {
2114 free_ipokey(&G.sipo->ipokey);
2117 getmouseco_areawin(mval);
2119 if(mval[0]>G.v2d->mask.xmax) return;
2123 error("Too many EditIpos");
2127 areamouseco_to_ipoco(G.v2d, mval, &x, &y);
2131 ei->icu= get_ipocurve(G.sipo->from, G.sipo->blocktype, ei->adrcode, 0);
2133 if(ei->icu==0) return;
2135 if(ei->disptype==IPO_DISPBITS) {
2136 ei->icu->vartype= IPO_BITS;
2137 val= (int)floor(y-0.5);
2139 y= (float)(1 << val);
2142 insert_vert_ipo(ei->icu, x, y);
2144 /* to be sure: if icu was 0, or only 1 curve visible */
2145 ei->flag |= IPO_SELECT;
2146 ei->icu->flag= ei->flag;
2148 editipo_changed(G.sipo, 1);
2151 void add_duplicate_editipo()
2156 BezTriple *bezt, *beztn, *newb;
2159 get_status_editipo();
2160 if(totipo_vertsel==0) return;
2162 ei= G.sipo->editipo;
2163 for(a=0; a<G.sipo->totipo; a++, ei++) {
2164 if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
2165 if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
2168 /* how many points */
2173 if(bezt->f2 & 1) tot++;
2179 newb= beztn= MEM_mallocN(icu->totvert*sizeof(BezTriple), "bezt");
2181 b= icu->totvert-tot;
2185 beztn->f1= beztn->f2= beztn->f3= 0;
2192 MEM_freeN(icu->bezt);
2195 calchandles_ipocurve(icu);
2201 if(G.sipo->showkey) {
2203 if(G.sipo->blocktype==ID_OB) {
2205 if(ob && (ob->ipoflag & OB_DRAWKEY)) allqueue(REDRAWVIEW3D, 0);
2211 void remove_doubles_ipo()
2215 BezTriple *bezt, *newb, *new1;
2219 ei= G.sipo->editipo;
2220 for(a=0; a<G.sipo->totipo; a++, ei++) {
2221 if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
2223 /* OR the curve is selected OR in editmode OR in keymode */
2225 if(G.sipo->showkey || (ei->flag & IPO_EDIT)) mode= 1;
2226 else if(ei->flag & IPO_SELECT) mode= 2;
2229 bezt= ei->icu->bezt;
2230 newb= new1= MEM_mallocN(ei->icu->totvert*sizeof(BezTriple), "newbezt");
2232 b= ei->icu->totvert-1;
2236 /* can we remove? */
2237 if(mode==2 || (bezt->f2 & 1)) {
2239 /* are the points different? */
2240 if( fabs( bezt->vec[1][0]-newb->vec[1][0] ) > 0.9 ) {
2246 VecMidf(newb->vec[0], newb->vec[0], bezt->vec[0]);
2247 VecMidf(newb->vec[1], newb->vec[1], bezt->vec[1]);
2248 VecMidf(newb->vec[2], newb->vec[2], bezt->vec[2]);
2250 newb->h1= newb->h2= HD_FREE;
2263 MEM_freeN(ei->icu->bezt);
2264 ei->icu->bezt= new1;
2266 calchandles_ipocurve(ei->icu);
2271 editipo_changed(G.sipo, 1); /* makes ipokeys again! */
2273 /* remove double keys */
2274 if(G.sipo->showkey) {
2275 ik= G.sipo->ipokey.first;
2279 if( (ik->flag & 1) && (ikn->flag & 1) ) {
2280 if( fabs(ik->val-ikn->val) < 0.9 ) {
2281 val= (float)((ik->val + ikn->val)/2.0);
2283 for(a=0; a<G.sipo->totipo; a++) {
2284 if(ik->data[a]) ik->data[a]->vec[1][0]= val;
2285 if(ikn->data[a]) ikn->data[a]->vec[1][0]= val;
2294 editipo_changed(G.sipo, 1); /* makes ipokeys agian! */
2297 deselectall_editipo();
2300 void join_ipo_menu(void)
2303 mode= pupmenu("Join %t|All Selected %x1|Selected Doubles %x2");
2305 if (mode == -1) return;
2310 void join_ipo(int mode)
2315 BezTriple *bezt, *beztn, *newb;
2319 get_status_editipo();
2323 * Selected Doubles: 2
2327 remove_doubles_ipo();
2331 /* first: multiple selected verts in 1 curve */
2332 ei= G.sipo->editipo;
2333 for(a=0; a<G.sipo->totipo; a++, ei++) {
2334 if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
2335 if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
2338 /* how many points */
2343 if(bezt->f2 & 1) tot++;
2351 newb= MEM_mallocN(icu->totvert*sizeof(BezTriple), "bezt");
2352 /* the first point is the new one */
2357 b= icu->totvert+tot+1;
2361 if(tot==0) *newb= *bezt;
2363 VecAddf(newb->vec[0], newb->vec[0], bezt->vec[0]);
2364 VecAddf(newb->vec[1], newb->vec[1], bezt->vec[1]);
2365 VecAddf(newb->vec[2], newb->vec[2], bezt->vec[2]);
2376 VecMulf(newb->vec[0], (float)(1.0/((float)tot)));
2377 VecMulf(newb->vec[1], (float)(1.0/((float)tot)));
2378 VecMulf(newb->vec[2], (float)(1.0/((float)tot)));
2380 MEM_freeN(icu->bezt);
2383 sort_time_ipocurve(icu);
2384 calchandles_ipocurve(icu);
2390 /* next: in keymode: join multiple selected keys */
2392 editipo_changed(G.sipo, 1); /* makes ipokeys again! */
2394 if(G.sipo->showkey) {
2395 ik= G.sipo->ipokey.first;
2400 for(a=0; a<G.sipo->totipo; a++) {
2402 val+= ik->data[a]->vec[1][0];
2413 ik= G.sipo->ipokey.first;
2416 for(a=0; a<G.sipo->totipo; a++) {
2418 ik->data[a]->vec[1][0]= val;
2424 editipo_changed(G.sipo, 0);
2427 deselectall_editipo();
2430 void ipo_snap_menu(void)
2434 event= pupmenu("Snap %t|Horizontal %x1|To Next %x2|To Frame %x3|To Current Frame%x4");
2435 if(event < 1) return;
2440 void ipo_snap(short event)
2452 * To Current Frame: 4
2455 get_status_editipo();
2457 ei= G.sipo->editipo;
2458 for(b=0; b<G.sipo->totipo; b++, ei++) {
2459 if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
2462 if(G.sipo->showkey) ok2= 1;
2463 else if(totipo_vert && (ei->flag & IPO_EDIT)) ok2= 2;
2464 else if(totipo_vert==0 && (ei->flag & IPO_SELECT)) ok2= 3;
2467 bezt= ei->icu->bezt;
2468 a= ei->icu->totvert;
2472 if(bezt->f2 & 1) ok= 1;
2478 bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1];
2479 if(bezt->h1==HD_AUTO || bezt->h1==HD_VECT) bezt->h1= HD_ALIGN;
2480 if(bezt->h2==HD_AUTO || bezt->h2==HD_VECT) bezt->h2= HD_ALIGN;
2484 bezt->vec[0][1]= bezt->vec[1][1]= bezt->vec[2][1]= (bezt+1)->vec[1][1];
2485 if(bezt->h1==HD_AUTO || bezt->h1==HD_VECT) bezt->h1= HD_ALIGN;
2486 if(bezt->h2==HD_AUTO || bezt->h2==HD_VECT) bezt->h2= HD_ALIGN;
2490 bezt->vec[1][0]= (float)(floor(bezt->vec[1][0]+0.5));
2492 else if(event==4) { /* to current frame */
2494 if(ok2==1 || ok2==2) {
2496 if(G.sipo->blocktype==ID_SEQ) {
2499 seq= (Sequence *)G.sipo->from;
2501 dx= (float)(CFRA-seq->startdisp);
2502 dx= (float)(100.0*dx/((float)(seq->enddisp-seq->startdisp)));
2504 dx-= bezt->vec[1][0];
2507 else dx= G.scene->r.framelen*CFRA - bezt->vec[1][0];
2509 bezt->vec[0][0]+= dx;
2510 bezt->vec[1][0]+= dx;
2511 bezt->vec[2][0]+= dx;
2518 calchandles_ipocurve(ei->icu);
2522 editipo_changed(G.sipo, 1);
2527 void mouse_select_ipo()
2530 EditIpo *ei, *actei= 0;
2535 KeyBlock *kb, *actkb=0;
2536 float x, y, dist, mindist;
2537 int a, oldflag = 0, hand, ok;
2538 short mval[2], xo, yo;
2540 if(G.sipo->editipo==0) return;
2542 get_status_editipo();
2544 if(G.sipo->showkey) {
2545 getmouseco_areawin(mval);
2547 areamouseco_to_ipoco(G.v2d, mval, &x, &y);
2550 ik= G.sipo->ipokey.first;
2552 dist= (float)(fabs(ik->val-x));
2553 if(ik->flag & 1) dist+= 1.0;
2554 if(dist < mindist) {
2561 oldflag= actik->flag;
2563 if(G.qual & LR_SHIFTKEY);
2564 else deselectall_editipo();
2566 if(G.qual & LR_SHIFTKEY) {
2567 if(oldflag & 1) actik->flag &= ~1;
2568 else actik->flag |= 1;
2575 else if(totipo_edit) {
2577 hand= findnearest_ipovert(&icu, &bezt);
2579 if(G.qual & LR_SHIFTKEY) {
2582 if(BEZSELECTED(bezt)) {
2583 bezt->f1= bezt->f2= bezt->f3= 0;
2586 bezt->f1= bezt->f2= bezt->f3= 1;
2590 if(bezt->f1 & 1) bezt->f1= 0;
2594 if(bezt->f3 & 1) bezt->f3= 0;
2600 deselectall_editipo();
2604 bezt->f1|= 1; bezt->f2|= 1; bezt->f3|= 1;
2606 else if(hand==0) bezt->f1|= 1;
2615 if(G.sipo->blocktype==ID_KE && G.sipo->from) {
2616 key= (Key *)G.sipo->from;
2618 ei= G.sipo->editipo;
2619 if(key->type==KEY_NORMAL || (ei->flag & IPO_VISIBLE)) {
2620 getmouseco_areawin(mval);
2622 areamouseco_to_ipoco(G.v2d, mval, &x, &y);
2623 /* how much is 20 pixels? */
2624 mindist= (float)(20.0*(G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)curarea->winy);
2626 kb= key->block.first;
2628 dist= (float)(fabs(kb->pos-y));
2629 if(kb->flag & SELECT) dist+= (float)0.01;
2630 if(dist < mindist) {
2638 if(G.obedit && (actkb->flag & 1)==0) {
2639 ok= okee("Copy key after leaving Edit Mode");
2642 /* also does all keypos */
2643 deselectall_editipo();
2648 showkeypos((Key *)G.sipo->from, actkb);
2657 ei= G.sipo->editipo;
2658 for(a=0; a<G.sipo->totipo; a++, ei++) {
2660 if(ei->flag & IPO_VISIBLE) actei= ei;
2664 else if(totipo_vis>1) {
2665 actei= select_proj_ipo(0, 0);
2668 if(actei) oldflag= actei->flag;
2670 if(G.qual & LR_SHIFTKEY);
2671 else deselectall_editipo();
2674 if(G.qual & LR_SHIFTKEY) {
2675 if(oldflag & IPO_SELECT) actei->flag &= ~IPO_SELECT;
2676 else actei->flag |= IPO_SELECT;
2679 actei->flag |= IPO_SELECT;
2685 update_editipo_flags();
2689 if(G.sipo->showkey && G.sipo->blocktype==ID_OB) {
2691 if(ob && (ob->ipoflag & OB_DRAWKEY)) draw_object_ext(BASACT);
2694 getmouseco_areawin(mval);
2698 while(get_mbut()&R_MOUSE) {
2699 getmouseco_areawin(mval);
2700 if(abs(mval[0]-xo)+abs(mval[1]-yo) > 4) {
2702 if(actkb) move_keys();
2703 else transform_ipo('g');
2707 BIF_wait_for_statechange();
2711 int icu_keys_bezier_loop(IpoCurve *icu,
2712 int (*bezier_function)(BezTriple *),
2713 void (ipocurve_function)(struct IpoCurve *icu))
2715 /* This loops through the beziers in the Ipocurve, and executes
2716 * the generic user provided 'bezier_function' on each one.
2717 * Optionally executes the generic function ipocurve_function on the
2718 * IPO curve after looping (eg. calchandles_ipocurve)
2727 /* if bezier_function has been specified
2728 * then loop through each bezier executing
2732 if (bezier_function != NULL) {
2734 /* exit with return code 1 if the bezier function
2735 * returns 1 (good for when you are only interested
2736 * in finding the first bezier that
2737 * satisfies a condition).
2739 if (bezier_function(bezt)) return 1;
2744 /* if ipocurve_function has been specified
2747 if (ipocurve_function != NULL)
2748 ipocurve_function(icu);
2754 int ipo_keys_bezier_loop(Ipo *ipo,
2755 int (*bezier_function)(BezTriple *),
2756 void (ipocurve_function)(struct IpoCurve *icu))
2758 /* This loops through the beziers that are attached to
2759 * the selected keys on the Ipocurves of the Ipo, and executes
2760 * the generic user provided 'bezier_function' on each one.
2761 * Optionally executes the generic function ipocurve_function on a
2762 * IPO curve after looping (eg. calchandles_ipocurve)
2767 /* Loop through each curve in the Ipo
2769 for (icu=ipo->curve.first; icu; icu=icu->next){
2770 if (icu_keys_bezier_loop(icu,bezier_function, ipocurve_function))
2777 int selected_bezier_loop(int (*looptest)(EditIpo *),
2778 int (*bezier_function)(BezTriple *),
2779 void (ipocurve_function)(struct IpoCurve *icu))
2781 /* This loops through the beziers that are attached to
2782 * selected keys in editmode in the IPO window, and executes
2783 * the generic user-provided 'bezier_function' on each one
2784 * that satisfies the 'looptest' function. Optionally executes
2785 * the generic function ipocurve_function on a IPO curve
2786 * after looping (eg. calchandles_ipocurve)
2793 /* Get the first Edit Ipo from the selected Ipos
2795 ei= G.sipo->editipo;
2797 /* Loop throught all of the selected Ipo's
2799 for(a=0; a<G.sipo->totipo; a++, ei++) {
2800 /* Do a user provided test on the Edit Ipo
2801 * to determine whether we want to process it
2804 /* Loop through the selected
2805 * beziers on the Edit Ipo
2807 bezt = ei->icu->bezt;
2808 b = ei->icu->totvert;
2810 /* if bezier_function has been specified
2811 * then loop through each bezier executing
2814 if (bezier_function != NULL) {
2816 /* exit with return code 1 if the bezier function
2817 * returns 1 (good for when you are only interested
2818 * in finding the first bezier that
2819 * satisfies a condition).
2821 if (bezier_function(bezt)) return 1;
2826 /* if ipocurve_function has been specified
2829 if (ipocurve_function != NULL)
2830 ipocurve_function(ei->icu);
2832 /* nufte flourdje zim ploopydu <-- random dutch looking comment ;) */
2833 /* looks more like russian to me! (ton) */
2839 int select_bezier_add(BezTriple *bezt) {
2840 /* Select the bezier triple */
2847 int select_bezier_subtract(BezTriple *bezt) {
2848 /* Deselect the bezier triple */
2855 int select_bezier_invert(BezTriple *bezt) {
2856 /* Invert the selection for the bezier triple */
2858 if ( bezt->f2 & 1 ) {
2869 int set_bezier_auto(BezTriple *bezt)
2871 /* Sets the selected bezier handles to type 'auto'
2874 /* is a handle selected? If so
2875 * set it to type auto
2877 if(bezt->f1 || bezt->f3) {
2878 if(bezt->f1) bezt->h1= 1; /* the secret code for auto */
2879 if(bezt->f3) bezt->h2= 1;
2881 /* if the handles are not of the same type, set them
2884 if(bezt->h1!=bezt->h2) {
2885 if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
2886 if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
2892 int set_bezier_vector(BezTriple *bezt)
2894 /* Sets the selected bezier handles to type 'vector'
2897 /* is a handle selected? If so
2898 * set it to type vector
2900 if(bezt->f1 || bezt->f3) {
2901 if(bezt->f1) bezt->h1= 2; /* the code for vector */
2902 if(bezt->f3) bezt->h2= 2;
2904 /* if the handles are not of the same type, set them
2907 if(bezt->h1!=bezt->h2) {
2908 if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
2909 if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
2915 int bezier_isfree(BezTriple *bezt)
2917 /* queries whether the handle should be set
2918 * to type 'free' (I think)
2920 if(bezt->f1 && bezt->h1) return 1;
2921 if(bezt->f3 && bezt->h2) return 1;
2925 int set_bezier_free(BezTriple *bezt)
2927 /* Sets selected bezier handles to type 'free'
2929 if(bezt->f1) bezt->h1= HD_FREE;
2930 if(bezt->f3) bezt->h2= HD_FREE;
2934 int set_bezier_align(BezTriple *bezt)
2936 /* Sets selected bezier handles to type 'align'
2938 if(bezt->f1) bezt->h1= HD_ALIGN;
2939 if(bezt->f3) bezt->h2= HD_ALIGN;
2943 int vis_edit_icu_bez(EditIpo *ei) {
2944 /* A 4 part test for an EditIpo :
2947 * c) does it contain an Ipo Curve
2948 * d) does that ipo curve have a bezier
2950 * (The reason why I don't just use the macro
2951 * is I need a pointer to a function.)
2953 return ISPOIN4(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu, icu->bezt);
2956 void select_ipo_bezier_keys(Ipo *ipo, int selectmode)
2958 /* Select all of the beziers in all
2959 * of the Ipo curves belonging to the
2960 * Ipo, using the selection mode.
2962 switch (selectmode) {
2964 ipo_keys_bezier_loop(ipo, select_bezier_add, NULL);
2966 case SELECT_SUBTRACT:
2967 ipo_keys_bezier_loop(ipo, select_bezier_subtract, NULL);
2970 ipo_keys_bezier_loop(ipo, select_bezier_invert, NULL);
2975 void sethandles_ipo_keys(Ipo *ipo, int code)
2977 /* this function lets you set bezier handles all to
2978 * one type for some Ipo's (e.g. with hotkeys through
2979 * the action window).
2982 /* code==1: set autohandle */
2983 /* code==2: set vectorhandle */
2984 /* als code==3 (HD_ALIGN) toggelt het, vectorhandles worden HD_FREE */
2988 /*** Set to auto ***/
2989 ipo_keys_bezier_loop(ipo, set_bezier_auto,
2990 calchandles_ipocurve);
2993 /*** Set to vector ***/
2994 ipo_keys_bezier_loop(ipo, set_bezier_vector,
2995 calchandles_ipocurve);
2998 if ( ipo_keys_bezier_loop(ipo, bezier_isfree, NULL) ) {
2999 /*** Set to free ***/
3000 ipo_keys_bezier_loop(ipo, set_bezier_free,
3001 calchandles_ipocurve);
3004 /*** Set to align ***/
3005 ipo_keys_bezier_loop(ipo, set_bezier_align,
3006 calchandles_ipocurve);
3014 void sethandles_ipo(int code)
3016 /* this function lets you set bezier handles all to
3017 * one type for some selected keys in edit mode in the
3018 * IPO window (e.g. with hotkeys)
3021 /* code==1: set autohandle */
3022 /* code==2: set vectorhandle */
3023 /* als code==3 (HD_ALIGN) toggelt het, vectorhandles worden HD_FREE */
3025 if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
3029 /*** Set to auto ***/
3030 selected_bezier_loop(vis_edit_icu_bez, set_bezier_auto,
3031 calchandles_ipocurve);
3034 /*** Set to vector ***/
3035 selected_bezier_loop(vis_edit_icu_bez, set_bezier_vector,
3036 calchandles_ipocurve);
3039 if (selected_bezier_loop(vis_edit_icu_bez, bezier_isfree, NULL) ) {
3040 /*** Set to free ***/
3041 selected_bezier_loop(vis_edit_icu_bez, set_bezier_free,
3042 calchandles_ipocurve);
3045 /*** Set to align ***/
3046 selected_bezier_loop(vis_edit_icu_bez, set_bezier_align,
3047 calchandles_ipocurve);
3052 editipo_changed(G.sipo, 1);
3056 void set_ipocurve_constant(struct IpoCurve *icu) {
3057 /* Sets the type of the IPO curve to constant
3059 icu->ipo= IPO_CONST;
3062 void set_ipocurve_linear(struct IpoCurve *icu) {
3063 /* Sets the type of the IPO curve to linear
3068 void set_ipocurve_bezier(struct IpoCurve *icu) {
3069 /* Sets the type of the IPO curve to bezier
3075 void setipotype_ipo(Ipo *ipo, int code)
3077 /* Sets the type of the each ipo curve in the
3078 * Ipo to a value based on the code
3082 ipo_keys_bezier_loop(ipo, NULL, set_ipocurve_constant);
3085 ipo_keys_bezier_loop(ipo, NULL, set_ipocurve_linear);
3088 ipo_keys_bezier_loop(ipo, NULL, set_ipocurve_bezier);
3101 if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
3102 if(G.sipo->showkey) return;
3103 get_status_editipo();
3105 if(G.sipo->blocktype==ID_KE && totipo_edit==0 && totipo_sel==0) {
3106 key= (Key *)G.sipo->from;
3109 event= pupmenu("Key Type %t|Linear %x1|Cardinal %x2|B Spline %x3");
3110 if(event < 1) return;
3112 kb= key->block.first;
3114 if(kb->flag & SELECT) {
3116 if(event==1) kb->type= KEY_LINEAR;
3117 if(event==2) kb->type= KEY_CARDINAL;
3118 if(event==3) kb->type= KEY_BSPLINE;
3124 event= pupmenu("Ipo Type %t|Constant %x1|Linear %x2|Bezier %x3");
3125 if(event < 1) return;
3127 ei= G.sipo->editipo;
3128 for(a=0; a<G.sipo->totipo; a++, ei++) {
3129 if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) {
3130 if(event==1) ei->icu->ipo= IPO_CONST;
3131 else if(event==2) ei->icu->ipo= IPO_LIN;
3132 else ei->icu->ipo= IPO_BEZ;
3136 scrarea_queue_winredraw(curarea);
3139 void borderselect_ipo()
3149 get_status_editipo();
3151 val= get_border(&rect, 3);
3156 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
3159 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
3161 if(G.sipo->showkey) {
3162 ik= G.sipo->ipokey.first;
3164 if(rectf.xmin<ik->val && rectf.xmax>ik->val) {
3165 if(val==LEFTMOUSE) ik->flag |= 1;
3166 else ik->flag &= ~1;
3170 update_editipo_flags();
3172 else if(totipo_edit==0) {
3173 if(rect.xmin<rect.xmax && rect.ymin<rect.ymax)
3174 select_proj_ipo(&rectf, val);
3178 ei= G.sipo->editipo;
3179 for(a=0; a<G.sipo->totipo; a++, ei++) {
3180 if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu) {
3182 b= ei->icu->totvert;
3183 bezt= ei->icu->bezt;
3185 int bit= (val==LEFTMOUSE);
3187 if(BLI_in_rctf(&rectf, bezt->vec[0][0], bezt->vec[0][1]))
3188 bezt->f1 = (bezt->f1&~1) | bit;
3189 if(BLI_in_rctf(&rectf, bezt->vec[1][0], bezt->vec[1][1]))
3190 bezt->f2 = (bezt->f2&~1) | bit;
3191 if(BLI_in_rctf(&rectf, bezt->vec[2][0], bezt->vec[2][1]))
3192 bezt->f3 = (bezt->f3&~1) | bit;