4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * Contributor(s): Blender Foundation, 2005. Full recode.
24 * Roland Hess, 2007. Visual Key refactor.
26 * ***** END GPL LICENSE BLOCK *****
30 /* this code feels over-complex, mostly because I choose in the past to devise a system
31 that converts the Ipo blocks (linked to Object, Material, etc), into a copy of that
32 data which is being worked on; the 'editipo'.
33 The editipo then can have 'ipokey' data, which is optimized for editing curves as if
34 it were key positions. This is still a great feature to work with, which makes ipo editing
35 in Blender still valuable. However, getting this beast under control was hard, even
47 #include "MEM_guardedalloc.h"
50 #include "BLI_blenlib.h"
51 #include "BLI_arithb.h"
53 #include "DNA_constraint_types.h"
54 #include "DNA_action_types.h"
55 #include "DNA_armature_types.h"
56 #include "DNA_camera_types.h"
57 #include "DNA_curve_types.h"
58 #include "DNA_group_types.h"
59 #include "DNA_ipo_types.h"
60 #include "DNA_key_types.h"
61 #include "DNA_lamp_types.h"
62 #include "DNA_material_types.h"
63 #include "DNA_object_types.h"
64 #include "DNA_object_fluidsim.h"
65 #include "DNA_particle_types.h"
66 #include "DNA_screen_types.h"
67 #include "DNA_scene_types.h"
68 #include "DNA_space_types.h"
69 #include "DNA_sequence_types.h"
70 #include "DNA_sound_types.h"
71 #include "DNA_texture_types.h"
72 #include "DNA_userdef_types.h"
73 #include "DNA_view3d_types.h"
74 #include "DNA_world_types.h"
76 #include "BKE_action.h"
77 #include "BKE_armature.h"
79 #include "BKE_constraint.h"
80 #include "BKE_depsgraph.h"
81 #include "BKE_global.h"
82 #include "BKE_group.h"
86 #include "BKE_material.h"
87 #include "BKE_particle.h"
88 #include "BKE_texture.h"
89 #include "BKE_utildefines.h"
90 #include "BKE_object.h"
92 #include "BIF_butspace.h"
93 #include "BIF_editaction.h"
94 #include "BIF_editconstraint.h"
95 #include "BIF_editkey.h"
96 #include "BIF_editnla.h"
97 #include "BIF_editseq.h"
98 #include "BIF_editview.h"
99 #include "BIF_interface.h"
100 #include "BIF_keyframing.h"
101 #include "BIF_mywindow.h"
102 #include "BIF_poseobject.h"
103 #include "BIF_screen.h"
104 #include "BIF_space.h"
105 #include "BIF_toolbox.h"
106 #include "BIF_poseobject.h"
108 #include "BDR_drawobject.h"
109 #include "BDR_editobject.h"
110 #include "BDR_editcurve.h" // for bezt_compare
112 #include "BSE_trans_types.h"
113 #include "BSE_editipo_types.h"
114 #include "BSE_drawipo.h"
115 #include "BSE_editipo.h"
116 #include "BSE_edit.h"
117 #include "BSE_drawview.h"
118 #include "BSE_headerbuttons.h"
119 #include "BSE_node.h"
120 #include "BSE_sequence.h"
121 #include "BSE_seqaudio.h"
122 #include "BSE_time.h"
125 #include "mydevice.h"
126 #include "transform.h"
139 extern int fluidsim_ar[]; // NT
140 extern int part_ar[];
143 #define IPOTHRESH 0.9
145 /* tests if only one editipo is active */
146 static void check_active_editipo(void)
151 actei= G.sipo->editipo;
153 for(a=0; a<G.sipo->totipo; a++, actei++) {
154 if(actei->flag & IPO_ACTIVE)
158 /* set visible active */
159 for(a=0, ei=G.sipo->editipo; a<G.sipo->totipo; a++, ei++) {
160 if(ei->flag & IPO_VISIBLE)
163 if(ei==NULL) ei=G.sipo->editipo;
164 ei->flag |= IPO_ACTIVE;
165 if(ei->icu) ei->icu->flag |= IPO_ACTIVE;
168 /* make sure no others are active */
169 for(a=0, ei=G.sipo->editipo; a<G.sipo->totipo; a++, ei++) {
171 ei->flag &= ~IPO_ACTIVE;
172 if(ei->icu) ei->icu->flag &= ~IPO_ACTIVE;
179 /* sets this ei channel active */
180 static void set_active_editipo(EditIpo *actei)
185 for(a=0, ei=G.sipo->editipo; a<G.sipo->totipo; a++, ei++) {
186 ei->flag &= ~IPO_ACTIVE;
187 if(ei->icu) ei->icu->flag &= ~IPO_ACTIVE;
189 actei->flag |= IPO_ACTIVE;
190 if(actei->icu) actei->icu->flag |= IPO_ACTIVE;
193 EditIpo *get_active_editipo(void)
201 /* prevent confusing situations, like for sequencer */
202 if(G.sipo->totipo==1) {
204 ei->flag |= IPO_ACTIVE;
207 for(a=0, ei=G.sipo->editipo; a<G.sipo->totipo; a++, ei++)
208 if(ei->flag & IPO_ACTIVE)
214 static void set_active_key(int index)
216 if(G.sipo->blocktype==ID_KE && G.sipo->from) {
217 Object *ob= (Object *)G.sipo->from;
218 Key *key= ob_get_key(ob);
223 curkb= BLI_findlink(&key->block, index-1);
226 ob->shapeflag |= OB_SHAPE_TEMPLOCK;
229 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
230 allqueue(REDRAWVIEW3D, 0);
231 allqueue(REDRAWBUTSEDIT, 0);
237 void editipo_changed(SpaceIpo *si, int doredraw)
249 for(a=0; a<si->totipo; a++, ei++) {
253 /* twice because of ittererating new autohandle */
254 calchandles_ipocurve(ei->icu);
255 calchandles_ipocurve(ei->icu);
257 if(ei->flag & IPO_VISIBLE) {
259 boundbox_ipocurve(ei->icu, 0);
260 sort_time_ipocurve(ei->icu);
262 si->v2d.tot= ei->icu->totrct;
265 else BLI_union_rctf(&(si->v2d.tot), &(ei->icu->totrct));
274 if(si->blocktype==ID_KE) {
275 key= ob_get_key((Object *)G.sipo->from);
276 if(key && key->block.first) {
277 kb= key->block.first;
278 if(kb->pos < v2d->tot.ymin) v2d->tot.ymin= kb->pos;
280 if(kb->pos > v2d->tot.ymax) v2d->tot.ymax= kb->pos;
284 /* is there no curve? */
288 v2d->tot.ymin= (float)-0.1;
289 v2d->tot.ymax= (float)1.1;
291 if(si->blocktype==ID_SEQ) {
293 v2d->tot.xmax= 105.0;
294 v2d->tot.ymin= (float)-0.1;
295 v2d->tot.ymax= (float)1.1;
302 /* if you always call do_ipo: you get problems with insertkey, for example
303 * when inserting only a 'loc' the 'ob->rot' value then is changed.
306 if(si->blocktype==ID_OB) {
307 /* clear delta loc,rot,size (when free/delete ipo) */
308 clear_delta_obipo(si->ipo);
314 allqueue(REDRAWIPO, 0);
315 allqueue(REDRAWACTION, 0);
316 allqueue(REDRAWTIME, 0);
317 allqueue(REDRAWNLA, 0);
318 allqueue(REDRAWBUTSOBJECT, 0);
320 if(si->blocktype==ID_OB) {
321 Object *ob= (Object *)si->from;
322 if(ob) DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
323 allqueue(REDRAWVIEW3D, 0);
324 allqueue(REDRAWNLA, 0);
327 else if(si->blocktype==ID_MA) allqueue(REDRAWBUTSSHADING, 0);
328 else if(si->blocktype==ID_TE) allqueue(REDRAWBUTSSHADING, 0);
329 else if(si->blocktype==ID_WO) allqueue(REDRAWBUTSSHADING, 0);
330 else if(si->blocktype==ID_LA) allqueue(REDRAWBUTSSHADING, 0);
331 // else if(si->blocktype==ID_SO) allqueue(REDRAWBUTSSOUND, 0);
332 else if(si->blocktype==ID_CA) {
333 allqueue(REDRAWBUTSEDIT, 0);
334 allqueue(REDRAWVIEW3D, 0);
336 else if(si->blocktype==ID_SEQ) free_imbuf_seq_with_ipo(si->ipo);
337 else if(si->blocktype==ID_PO) {
340 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
342 allqueue(REDRAWVIEW3D, 0);
343 allqueue(REDRAWACTION, 0);
344 allqueue(REDRAWNLA, 0);
346 else if(si->blocktype==ID_KE) {
347 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
348 allqueue(REDRAWVIEW3D, 0);
350 else if(si->blocktype==ID_CU) {
351 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
352 allqueue(REDRAWVIEW3D, 0);
354 else if(si->blocktype==ID_PA){
355 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
356 allqueue(REDRAWVIEW3D, 0);
360 if(si->showkey) make_ipokey();
363 synchronize_action_strips();
366 void scale_editipo(void)
368 /* comes from buttons, scale with G.sipo->tot rect */
375 facx= (G.sipo->tot.xmax-G.sipo->tot.xmin)/(G.sipo->v2d.tot.xmax-G.sipo->v2d.tot.xmin);
376 facy= (G.sipo->tot.ymax-G.sipo->tot.ymin)/(G.sipo->v2d.tot.ymax-G.sipo->v2d.tot.ymin);
380 for(a=0; a<G.sipo->totipo; a++, ei++) {
381 if (ISPOIN(ei, flag & IPO_VISIBLE, icu)) {
386 bezt->vec[0][0]= facx*(bezt->vec[0][0] - G.sipo->v2d.tot.xmin) + G.sipo->tot.xmin;
387 bezt->vec[1][0]= facx*(bezt->vec[1][0] - G.sipo->v2d.tot.xmin) + G.sipo->tot.xmin;
388 bezt->vec[2][0]= facx*(bezt->vec[2][0] - G.sipo->v2d.tot.xmin) + G.sipo->tot.xmin;
390 bezt->vec[0][1]= facy*(bezt->vec[0][1] - G.sipo->v2d.tot.ymin) + G.sipo->tot.ymin;
391 bezt->vec[1][1]= facy*(bezt->vec[1][1] - G.sipo->v2d.tot.ymin) + G.sipo->tot.ymin;
392 bezt->vec[2][1]= facy*(bezt->vec[2][1] - G.sipo->v2d.tot.ymin) + G.sipo->tot.ymin;
399 editipo_changed(G.sipo, 1);
401 BIF_undo_push("Scale Edit Ipo");
402 allqueue(REDRAWNLA, 0);
403 allqueue (REDRAWACTION, 0);
404 allqueue(REDRAWIPO, 0);
407 static void make_ob_editipo(Object *ob, SpaceIpo *si)
410 int a, len, colipo=0;
413 if(ob->type==OB_MESH) colipo= 1;
415 ei= si->editipo= MEM_callocN(OB_TOTIPO*sizeof(EditIpo), "editipo");
417 si->totipo= OB_TOTIPO;
419 for(a=0; a<OB_TOTIPO; a++) {
420 name = getname_ob_ei(ob_ar[a], colipo);
421 strcpy(ei->name, name);
422 ei->adrcode= ob_ar[a];
424 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;
425 else if(ei->adrcode==OB_LAY) ei->disptype= IPO_DISPBITS;
426 else if(ei->adrcode==OB_TIME) ei->disptype= IPO_DISPTIME;
428 ei->col= ipo_rainbow(a, OB_TOTIPO);
431 len= strlen(ei->name);
433 if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF;
434 else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50;
435 else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050;
439 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
441 ei->flag= ei->icu->flag;
447 //fprintf(stderr,"FSIMAKE_OPBJ call %d \n", si->totipo);
450 static void make_part_editipo(SpaceIpo *si)
456 if(si->from==0) return;
458 ei= si->editipo= MEM_callocN(PART_TOTIPO*sizeof(EditIpo), "editipo");
460 si->totipo= PART_TOTIPO;
462 for(a=0; a<PART_TOTIPO; a++) {
463 name = getname_part_ei(part_ar[a]);
464 strcpy(ei->name, name);
465 ei->adrcode= part_ar[a];
466 ei->col= ipo_rainbow(a, PART_TOTIPO);
467 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
469 ei->flag= ei->icu->flag;
476 // copied from make_seq_editipo
477 static void make_fluidsim_editipo(SpaceIpo *si) // NT
482 ei= si->editipo= MEM_callocN(FLUIDSIM_TOTIPO*sizeof(EditIpo), "fluidsim_editipo");
483 si->totipo = FLUIDSIM_TOTIPO;
484 for(a=0; a<FLUIDSIM_TOTIPO; a++) {
485 //fprintf(stderr,"FSINAME %d %d \n",a,fluidsim_ar[a], (int)(getname_fluidsim_ei(fluidsim_ar[a])) );
486 name = getname_fluidsim_ei(fluidsim_ar[a]);
487 strcpy(ei->name, name);
488 ei->adrcode= fluidsim_ar[a];
489 ei->col= ipo_rainbow(a, FLUIDSIM_TOTIPO);
490 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
492 ei->flag = ei->icu->flag;
494 //else { ei->flag |= IPO_VISIBLE; }
495 //fprintf(stderr,"FSIMAKE eif%d,icuf%d icu%d %d|%d\n", ei->flag,ei->icu->flag, (int)ei->icu, IPO_VISIBLE,IPO_SELECT);
496 //fprintf(stderr,"FSIMAKE eif%d icu%d %d|%d\n", ei->flag, (int)ei->icu, IPO_VISIBLE,IPO_SELECT);
501 static void make_seq_editipo(SpaceIpo *si)
507 ei= si->editipo= MEM_callocN(SEQ_TOTIPO*sizeof(EditIpo), "editipo");
509 si->totipo= SEQ_TOTIPO;
512 for(a=0; a<SEQ_TOTIPO; a++) {
513 name = getname_seq_ei(seq_ar[a]);
514 strcpy(ei->name, name);
515 ei->adrcode= seq_ar[a];
517 ei->col= ipo_rainbow(a, SEQ_TOTIPO);
519 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
521 ei->flag= ei->icu->flag;
523 else ei->flag |= IPO_VISIBLE;
529 static void make_cu_editipo(SpaceIpo *si)
535 ei= si->editipo= MEM_callocN(CU_TOTIPO*sizeof(EditIpo), "editipo");
537 si->totipo= CU_TOTIPO;
540 for(a=0; a<CU_TOTIPO; a++) {
541 name = getname_cu_ei(cu_ar[a]);
542 strcpy(ei->name, name);
543 ei->adrcode= cu_ar[a];
545 ei->col= ipo_rainbow(a, CU_TOTIPO);
547 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
549 ei->flag= ei->icu->flag;
551 else ei->flag |= IPO_VISIBLE;
557 static void make_key_editipo(SpaceIpo *si)
564 key= ob_get_key((Object *)G.sipo->from);
565 if(key==NULL) return;
567 si->totipo= BLI_countlist(&key->block);
568 ei= si->editipo= MEM_callocN(si->totipo*sizeof(EditIpo), "editipo");
570 for(a=0, kb= key->block.first; a<si->totipo; a++, ei++, kb= kb->next) {
572 if(kb->name[0] != 0) strncpy(ei->name, kb->name, 31); // length both same
573 ei->adrcode= kb->adrcode;
575 ei->col= ipo_rainbow(a, KEY_TOTIPO);
577 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
579 ei->flag= ei->icu->flag;
582 if(key && key->type==KEY_NORMAL)
583 ei->flag |= IPO_VISIBLE;
585 /* active ipo is tied to active shape */
589 set_active_editipo(ei);
594 if(key && key->type==KEY_RELATIVE) {
595 strcpy(ei->name, "----");
598 ei->flag |= IPO_VISIBLE;
602 static void make_mat_editipo(SpaceIpo *si)
608 if(si->from==0) return;
610 ei= si->editipo= MEM_callocN(MA_TOTIPO*sizeof(EditIpo), "editipo");
612 si->totipo= MA_TOTIPO;
614 for(a=0; a<MA_TOTIPO; a++) {
615 name = getname_mat_ei(ma_ar[a]);
616 strcpy(ei->name, name);
617 ei->adrcode= ma_ar[a];
619 if(ei->adrcode & MA_MAP1) {
620 ei->adrcode-= MA_MAP1;
621 ei->adrcode |= texchannel_to_adrcode(si->channel);
624 if(ei->adrcode==MA_MODE) ei->disptype= IPO_DISPBITS;
627 ei->col= ipo_rainbow(a, MA_TOTIPO);
629 len= strlen(ei->name);
631 if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF;
632 else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50;
633 else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050;
636 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
638 ei->flag= ei->icu->flag;
645 static void make_texture_editipo(SpaceIpo *si)
651 if(si->from==0) return;
653 ei= si->editipo= MEM_callocN(TE_TOTIPO*sizeof(EditIpo), "editipo");
655 si->totipo= TE_TOTIPO;
657 for(a=0; a<TE_TOTIPO; a++) {
658 name = getname_tex_ei(te_ar[a]);
659 strcpy(ei->name, name);
660 ei->adrcode= te_ar[a];
662 ei->col= ipo_rainbow(a, TE_TOTIPO);
664 len= strlen(ei->name);
666 if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF;
667 else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50;
668 else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050;
670 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
672 ei->flag= ei->icu->flag;
679 static void make_world_editipo(SpaceIpo *si)
685 if(si->from==0) return;
687 ei= si->editipo= MEM_callocN(WO_TOTIPO*sizeof(EditIpo), "editipo");
689 si->totipo= WO_TOTIPO;
691 for(a=0; a<WO_TOTIPO; a++) {
692 name = getname_world_ei(wo_ar[a]);
694 strcpy(ei->name, name);
695 ei->adrcode= wo_ar[a];
697 if(ei->adrcode & MA_MAP1) {
698 ei->adrcode-= MA_MAP1;
699 ei->adrcode |= texchannel_to_adrcode(si->channel);
702 if(ei->adrcode==MA_MODE) ei->disptype= IPO_DISPBITS;
705 ei->col= ipo_rainbow(a, WO_TOTIPO);
707 len= strlen(ei->name);
709 if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF;
710 else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50;
711 else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050;
714 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
716 ei->flag= ei->icu->flag;
723 static void make_lamp_editipo(SpaceIpo *si)
729 ei= si->editipo= MEM_callocN(LA_TOTIPO*sizeof(EditIpo), "editipo");
731 si->totipo= LA_TOTIPO;
733 for(a=0; a<LA_TOTIPO; a++) {
734 name = getname_la_ei(la_ar[a]);
735 strcpy(ei->name, name);
736 ei->adrcode= la_ar[a];
738 if(ei->adrcode & MA_MAP1) {
739 ei->adrcode-= MA_MAP1;
740 ei->adrcode |= texchannel_to_adrcode(si->channel);
743 ei->col= ipo_rainbow(a, LA_TOTIPO);
745 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
747 ei->flag= ei->icu->flag;
754 static void make_camera_editipo(SpaceIpo *si)
760 ei= si->editipo= MEM_callocN(CAM_TOTIPO*sizeof(EditIpo), "editipo");
762 si->totipo= CAM_TOTIPO;
765 for(a=0; a<CAM_TOTIPO; a++) {
766 name = getname_cam_ei(cam_ar[a]);
767 strcpy(ei->name, name);
768 ei->adrcode= cam_ar[a];
770 ei->col= ipo_rainbow(a, CAM_TOTIPO);
772 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
774 ei->flag= ei->icu->flag;
781 static int make_constraint_editipo(Ipo *ipo, EditIpo **si)
787 ei= *si= MEM_callocN(CO_TOTIPO*sizeof(EditIpo), "editipo");
789 for(a=0; a<CO_TOTIPO; a++) {
790 name = getname_co_ei(co_ar[a]);
791 strcpy(ei->name, name);
792 ei->adrcode= co_ar[a];
794 ei->col= ipo_rainbow(a, CO_TOTIPO);
796 ei->icu= find_ipocurve(ipo, ei->adrcode);
798 ei->flag= ei->icu->flag;
807 static int make_bone_editipo(Ipo *ipo, EditIpo **si)
813 ei= *si= MEM_callocN(AC_TOTIPO*sizeof(EditIpo), "editipo");
815 for(a=0; a<AC_TOTIPO; a++) {
816 name = getname_ac_ei(ac_ar[a]);
817 strcpy(ei->name, name);
818 ei->adrcode= ac_ar[a];
820 ei->col= ipo_rainbow(a, AC_TOTIPO);
822 ei->icu= find_ipocurve(ipo, ei->adrcode);
824 ei->flag= ei->icu->flag;
833 static void make_sound_editipo(SpaceIpo *si)
839 ei= si->editipo= MEM_callocN(SND_TOTIPO*sizeof(EditIpo), "editipo");
841 si->totipo= SND_TOTIPO;
844 for(a=0; a<SND_TOTIPO; a++) {
845 name = getname_snd_ei(snd_ar[a]);
846 strcpy(ei->name, name);
847 ei->adrcode= snd_ar[a];
849 ei->col= ipo_rainbow(a, SND_TOTIPO);
851 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
853 ei->flag= ei->icu->flag;
860 /* only called in test_editipo() below */
861 static void make_editipo(void)
869 MEM_freeN(G.sipo->editipo);
871 G.sipo->editipo= NULL;
874 if(G.sipo->from==NULL) return;
878 if(G.sipo->ipo) G.sipo->showkey= G.sipo->ipo->showkey;
880 if(G.sipo->blocktype==ID_SEQ) {
881 make_seq_editipo(G.sipo);
883 else if(G.sipo->blocktype==ID_WO) {
884 make_world_editipo(G.sipo);
886 else if(G.sipo->blocktype==ID_OB) {
889 make_ob_editipo(ob, G.sipo);
892 else if(G.sipo->blocktype==ID_MA) {
895 make_mat_editipo(G.sipo);
898 else if(G.sipo->blocktype==ID_CU) {
901 make_cu_editipo(G.sipo);
904 else if(G.sipo->blocktype==ID_KE) {
907 make_key_editipo(G.sipo);
910 else if(G.sipo->blocktype==ID_LA) {
913 make_lamp_editipo(G.sipo);
916 else if(G.sipo->blocktype==ID_TE) {
919 make_texture_editipo(G.sipo);
921 else if(G.scene->world && give_current_world_texture()) {
922 make_texture_editipo(G.sipo);
925 else if(G.sipo->blocktype==ID_CA) {
928 make_camera_editipo(G.sipo);
931 else if(G.sipo->blocktype==ID_SO) {
934 make_sound_editipo(G.sipo);
937 else if(G.sipo->blocktype==ID_CO){
938 G.sipo->totipo = make_constraint_editipo(G.sipo->ipo, (EditIpo**)&G.sipo->editipo);
943 else if(G.sipo->blocktype==ID_PO) {
945 G.sipo->totipo = make_bone_editipo(G.sipo->ipo, (EditIpo**)&G.sipo->editipo);
950 else if(G.sipo->blocktype==ID_FLUIDSIM) {
952 ob->ipowin= ID_FLUIDSIM;
953 make_fluidsim_editipo(G.sipo);
956 else if(G.sipo->blocktype==ID_PA) {
959 make_part_editipo(G.sipo);
963 if(G.sipo->editipo==0) return;
966 for(a=0; a<G.sipo->totipo; a++, ei++) {
967 if(ei->icu) ei->icu->flag= ei->flag;
969 editipo_changed(G.sipo, 0);
971 /* sets globals, bad stuff but we need these variables in other parts of code */
972 get_status_editipo();
975 if (G.sipo->flag & SIPO_LOCK_VIEW) {
976 rf= &(G.v2d->cur); /* view is locked, dont move it, just to sanity check */
977 if(rf->xmin>=rf->xmax || rf->ymin>=rf->ymax) ipo_default_v2d_cur(G.sipo->blocktype, &G.v2d->cur);
981 rf= &(G.sipo->v2d.cur);
983 rf= &(G.sipo->ipo->cur);
985 if(rf->xmin<rf->xmax && rf->ymin<rf->ymax) G.v2d->cur= *rf;
986 else ipo_default_v2d_cur(G.sipo->blocktype, &G.v2d->cur);
989 ipo_default_v2d_cur(G.sipo->blocktype, &G.v2d->cur);
992 view2d_do_locks(curarea, V2D_LOCK_COPY);
995 /* evaluates context in the current UI */
996 /* blocktype is type of ipo */
997 /* from is the base pointer to find data to change (ob in case of action or pose) */
998 /* bonename is for local bone ipos (constraint only now) */
999 static void get_ipo_context(short blocktype, ID **from, Ipo **ipo, char *actname, char *constname, char *bonename)
1006 if(blocktype==ID_CO) {
1008 bConstraintChannel *chan;
1009 bConstraint *con= get_active_constraint(ob);
1014 BLI_strncpy(constname, con->name, 32);
1016 /* a bit hackish, but we want con->ipo to work */
1017 if(con->flag & CONSTRAINT_OWN_IPO) {
1018 if(ob->flag & OB_POSEMODE) {
1019 bPoseChannel *pchan= get_active_posechannel(ob);
1021 BLI_strncpy(bonename, pchan->name, 32);
1027 chan= get_active_constraint_channel(ob);
1030 BLI_strncpy(constname, con->name, 32);
1033 /* set actname if in posemode */
1035 if (ob->flag & OB_POSEMODE) {
1036 bPoseChannel *pchan= get_active_posechannel(ob);
1038 BLI_strncpy(actname, pchan->name, 32);
1039 BLI_strncpy(bonename, pchan->name, 32);
1042 else if (ob->ipoflag & OB_ACTION_OB)
1043 strcpy(actname, "Object");
1046 if (ob->flag & OB_POSEMODE) {
1047 bPoseChannel *pchan= get_active_posechannel(ob);
1049 BLI_strncpy(actname, pchan->name, 32);
1050 BLI_strncpy(bonename, pchan->name, 32);
1058 else if(blocktype==ID_PO) {
1059 if (ob && ob->action && ob->type==OB_ARMATURE) {
1060 bPoseChannel *pchan= get_active_posechannel(ob);
1064 bActionChannel *achan;
1066 BLI_strncpy(actname, pchan->name, 32); /* also set when no channel yet */
1068 achan= get_action_channel(ob->action, pchan->name);
1075 else if(blocktype==ID_OB) {
1078 if(ob->ipoflag & OB_ACTION_OB) {
1080 bActionChannel *achan= get_action_channel(ob->action, "Object");
1083 BLI_strncpy(actname, achan->name, 32);
1092 else if(blocktype==ID_SEQ) {
1093 Sequence *last_seq = get_last_seq();
1096 *from= (ID *)last_seq;
1097 *ipo= last_seq->ipo;
1100 else if(blocktype==ID_WO) {
1101 World *wo= G.scene->world;
1103 if(wo) *ipo= wo->ipo;
1105 else if(blocktype==ID_TE) {
1107 Tex *tex= give_current_texture(ob, ob->actcol);
1109 if(tex) *ipo= tex->ipo;
1111 else if(G.scene->world) {
1112 Tex *tex= give_current_world_texture();
1114 if(tex) *ipo= tex->ipo;
1117 else if(blocktype==ID_MA) {
1119 Material *ma= give_current_material(ob, ob->actcol);
1120 ma= editnode_get_active_material(ma);
1122 if(ma) *ipo= ma->ipo;
1125 else if(blocktype==ID_KE) {
1127 Key *key= ob_get_key(ob);
1129 if(ob->ipoflag & OB_ACTION_KEY) {
1131 bActionChannel *achan= get_action_channel(ob->action, "Shape");
1134 BLI_strncpy(actname, achan->name, 32);
1138 else if(key) *ipo= key->ipo;
1143 else if(blocktype==ID_CU) {
1144 if(ob && ob->type==OB_CURVE) {
1145 Curve *cu= ob->data;
1150 else if(blocktype==ID_LA) {
1151 if(ob && ob->type==OB_LAMP) {
1157 else if(blocktype==ID_CA) {
1158 if(ob && ob->type==OB_CAMERA) {
1159 Camera *ca= ob->data;
1161 if(ca) *ipo= ca->ipo;
1164 else if(blocktype==ID_SO) {
1166 // if (G.buts && G.buts->mainb == BUTS_SOUND) {
1167 // bSound *sound = G.buts->lockpoin;
1168 // *from= (ID *)sound;
1169 // if(sound) *ipo= sound->ipo;
1172 else if(blocktype==ID_FLUIDSIM) {
1173 if(ob && ( ob->fluidsimFlag & OB_FLUIDSIM_ENABLE)) {
1174 FluidsimSettings *fss= ob->fluidsimSettings;
1176 if(fss) *ipo= fss->ipo;
1179 else if(blocktype==ID_PA) {
1180 ParticleSystem *psys = psys_get_current(ob);
1183 *ipo= psys->part->ipo;
1188 /* called on each redraw, check if editipo data has to be remade */
1189 /* if doit already set, it always makes (in case no ipo exists, we need to see the channels */
1190 void test_editipo(int doit)
1193 if(G.sipo->pin==0) {
1196 char actname[32]="", constname[32]="", bonename[32]="";
1198 get_ipo_context(G.sipo->blocktype, &from, &ipo, actname, constname, bonename);
1200 if(G.sipo->ipo != ipo) {
1202 /* if lock we don't copy from ipo, this makes the UI jump around confusingly */
1203 if(G.v2d->flag & V2D_VIEWLOCK || G.sipo->flag & SIPO_LOCK_VIEW);
1204 else if(ipo) G.v2d->cur= ipo->cur;
1207 if(G.sipo->from != from) {
1211 if( strcmp(G.sipo->actname, actname)) {
1212 BLI_strncpy(G.sipo->actname, actname, 32);
1215 if( strcmp(G.sipo->constname, constname)) {
1216 BLI_strncpy(G.sipo->constname, constname, 32);
1219 if( strcmp(G.sipo->bonename, bonename)) {
1220 BLI_strncpy(G.sipo->bonename, bonename, 32);
1221 /* urmf; if bonename, then no action */
1222 if(bonename[0]) G.sipo->actname[0]= 0;
1227 G.sipo->ipo->cur = G.v2d->cur;
1231 if(G.sipo->editipo==NULL || doit) {
1236 /* ****************** EditIpo ************************ */
1238 int totipo_edit=0, totipo_sel=0, totipo_curve=0, totipo_vis=0, totipo_vert=0, totipo_vertsel=0, totipo_key=0, totipo_keysel=0;
1240 void get_status_editipo(void)
1256 if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
1258 ei= G.sipo->editipo;
1260 for(a=0; a<G.sipo->totipo; a++) {
1261 if( ei->flag & IPO_VISIBLE ) {
1263 if(ei->flag & IPO_SELECT) totipo_sel++;
1264 if(ei->icu && ei->icu->totvert) totipo_curve++;
1265 if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
1267 /* if showkey: do count the vertices (for grab) */
1268 if(G.sipo->showkey==0) totipo_edit++;
1272 bezt= ei->icu->bezt;
1273 b= ei->icu->totvert;
1275 if(ei->icu->ipo==IPO_BEZ) {
1276 if(bezt->f1 & SELECT) totipo_vertsel++;
1277 if(bezt->f3 & SELECT) totipo_vertsel++;
1280 if(bezt->f2 & SELECT) totipo_vertsel++;
1292 if(G.sipo->showkey) {
1293 ik= G.sipo->ipokey.first;
1296 if(ik->flag & 1) totipo_keysel++;
1302 /* synchronize editipo flag with icu flag and ipokey flags */
1303 void update_editipo_flags(void)
1309 ei= G.sipo->editipo;
1311 for(a=0; a<G.sipo->totipo; a++, ei++) {
1312 if(ei->icu) ei->icu->flag= ei->flag;
1315 if(G.sipo->showkey) {
1316 ik= G.sipo->ipokey.first;
1318 for(a=0; a<G.sipo->totipo; a++) {
1321 BEZ_SEL(ik->data[a]);
1324 BEZ_DESEL(ik->data[a]);
1333 /* sort of enter/leave editmode for curves */
1334 void set_editflag_editipo(void)
1337 int a; /* , tot= 0, ok= 0; */
1339 /* after showkey immediately go to editing of selected points */
1340 if(G.sipo->showkey) {
1342 if(G.sipo->ipo) G.sipo->ipo->showkey= 0;
1343 ei= G.sipo->editipo;
1344 for(a=0; a<G.sipo->totipo; a++, ei++) ei->flag |= IPO_SELECT;
1345 scrarea_queue_headredraw(curarea);
1346 allqueue(REDRAWVIEW3D, 0);
1349 get_status_editipo();
1351 if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
1353 ei= G.sipo->editipo;
1354 for(a=0; a<G.sipo->totipo; a++, ei++) {
1356 if(ei->flag & IPO_VISIBLE) {
1358 if(totipo_edit==0 && (ei->flag & IPO_SELECT)) {
1359 ei->flag |= IPO_EDIT;
1360 ei->icu->flag= ei->flag;
1362 else if(totipo_edit && (ei->flag & IPO_EDIT)) {
1363 ei->flag -= IPO_EDIT;
1364 ei->icu->flag= ei->flag;
1366 else if(totipo_vis==1) {
1367 if(ei->flag & IPO_EDIT) ei->flag -= IPO_EDIT;
1368 else ei->flag |= IPO_EDIT;
1369 ei->icu->flag= ei->flag;
1374 scrarea_queue_headredraw(curarea);
1375 scrarea_queue_winredraw(curarea);
1378 static short findnearest_ipovert(IpoCurve **icu, BezTriple **bezt)
1380 /* selected verts get a disadvantage */
1381 /* in icu and (bezt or bp) the nearest is written */
1382 /* return 0 1 2: handlepunt */
1385 int dist= 100, temp, a, b;
1386 short mval[2], hpoint=0, sco[3][2];
1391 getmouseco_areawin(mval);
1393 ei= G.sipo->editipo;
1394 for(a=0; a<G.sipo->totipo; a++, ei++) {
1395 if (ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu)) {
1398 bezt1= ei->icu->bezt;
1399 b= ei->icu->totvert;
1402 ipoco_to_areaco_noclip(G.v2d, bezt1->vec[0], sco[0]);
1403 ipoco_to_areaco_noclip(G.v2d, bezt1->vec[1], sco[1]);
1404 ipoco_to_areaco_noclip(G.v2d, bezt1->vec[2], sco[2]);
1406 if(ei->disptype==IPO_DISPBITS) {
1407 temp= abs(mval[0]- sco[1][0]);
1409 else temp= abs(mval[0]- sco[1][0])+ abs(mval[1]- sco[1][1]);
1411 if( bezt1->f2 & SELECT) temp+=5;
1419 if(ei->disptype!=IPO_DISPBITS && ei->icu->ipo==IPO_BEZ) {
1420 /* middle points get an advantage */
1421 temp= -3+abs(mval[0]- sco[0][0])+ abs(mval[1]- sco[0][1]);
1422 if( bezt1->f1 & SELECT) temp+=5;
1430 temp= abs(mval[0]- sco[2][0])+ abs(mval[1]- sco[2][1]);
1431 if( bezt1->f3 & 1) temp+=5;
1448 void mouse_select_ipo(void)
1451 KeyBlock *actkb=NULL;
1452 EditIpo *ei, *actei= 0;
1457 float x, y, dist, mindist;
1458 int a, oldflag = 0, hand, ok;
1459 short mval[2], xo, yo;
1461 if(G.sipo->editipo==0) return;
1463 get_status_editipo();
1464 marker=find_nearest_marker(SCE_MARKERS, 1);
1466 /* map ipo-points for editing if scaled ipo */
1467 if (NLA_IPO_SCALED) {
1468 actstrip_map_ipo_keys(OBACT, G.sipo->ipo, 0, 0);
1471 if(G.sipo->showkey) {
1474 view2d_getscale(G.v2d, &pixelwidth, NULL);
1476 getmouseco_areawin(mval);
1477 areamouseco_to_ipoco(G.v2d, mval, &x, &y);
1480 ik= G.sipo->ipokey.first;
1482 dist= (float)(fabs(ik->val-x));
1483 if(ik->flag & SELECT) dist+= pixelwidth;
1484 if(dist < mindist) {
1491 oldflag= actik->flag;
1493 if(G.qual & LR_SHIFTKEY);
1494 else deselectall_editipo();
1496 if(G.qual & LR_SHIFTKEY) {
1497 if(oldflag & 1) actik->flag &= ~1;
1498 else actik->flag |= 1;
1505 else if(totipo_edit) {
1507 hand= findnearest_ipovert(&icu, &bezt);
1509 if(G.qual & LR_SHIFTKEY) {
1512 if(BEZSELECTED(bezt)) {
1520 if(bezt->f1 & SELECT) bezt->f1 &= ~SELECT;
1521 else bezt->f1= SELECT;
1524 if(bezt->f3 & SELECT) bezt->f3 &= ~SELECT;
1525 else bezt->f3= SELECT;
1530 deselectall_editipo();
1536 else if(hand==0) bezt->f1 |= SELECT;
1537 else bezt->f3 |= SELECT;
1542 /* select timeline marker */
1543 if ((G.qual & LR_SHIFTKEY)==0) {
1544 oldflag= marker->flag;
1545 deselect_markers(0, 0);
1547 if (oldflag & SELECT)
1548 marker->flag &= ~SELECT;
1550 marker->flag |= SELECT;
1553 marker->flag |= SELECT;
1559 if(G.sipo->blocktype==ID_KE && G.sipo->from) {
1561 KeyBlock *kb, *curkb;
1564 ob= (Object *)G.sipo->from;
1565 key= ob_get_key(ob);
1566 curkb= BLI_findlink(&key->block, ob->shapenr-1);
1568 ei= G.sipo->editipo;
1569 if(key->type==KEY_NORMAL || (ei->flag & IPO_VISIBLE)) {
1570 getmouseco_areawin(mval);
1572 areamouseco_to_ipoco(G.v2d, mval, &x, &y);
1573 /* how much is 20 pixels? */
1574 mindist= (float)(20.0*(G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)curarea->winy);
1576 for(i=1, kb= key->block.first; kb; kb= kb->next, i++) {
1577 dist= (float)(fabs(kb->pos-y));
1578 if(kb==curkb) dist+= (float)0.01;
1579 if(dist < mindist) {
1587 if(G.obedit && actkb!=curkb) {
1588 ok= okee("Copy key after leaving Edit Mode");
1591 /* also does all keypos */
1592 deselectall_editipo();
1593 set_active_key(index);
1594 set_active_editipo(ei+index-1);
1603 ei= G.sipo->editipo;
1604 for(a=0; a<G.sipo->totipo; a++, ei++) {
1606 if(ei->flag & IPO_VISIBLE) actei= ei;
1610 else if(totipo_vis>1) {
1611 actei= select_proj_ipo(0, 0);
1614 if(actei) oldflag= actei->flag;
1616 if(G.qual & LR_SHIFTKEY);
1617 else deselectall_editipo();
1620 if(G.qual & LR_SHIFTKEY) {
1621 if(oldflag & IPO_SELECT) actei->flag &= ~IPO_SELECT;
1622 else actei->flag |= IPO_SELECT;
1625 actei->flag |= IPO_SELECT;
1627 set_active_editipo(actei);
1632 /* undo mapping of ipo-points for editing if scaled ipo */
1633 if (NLA_IPO_SCALED) {
1634 actstrip_map_ipo_keys(OBACT, G.sipo->ipo, 1, 0);
1637 update_editipo_flags();
1640 BIF_undo_push("Select Ipo");
1642 if(G.sipo->showkey && G.sipo->blocktype==ID_OB) {
1644 if(ob && (ob->ipoflag & OB_DRAWKEY)) allqueue(REDRAWVIEW3D, 0);
1646 /* points inside of curve are drawn selected too */
1647 if(G.sipo->blocktype==ID_CU)
1648 allqueue(REDRAWVIEW3D, 0);
1650 getmouseco_areawin(mval);
1654 while (get_mbut() & ((U.flag & USER_LMOUSESELECT)?L_MOUSE:R_MOUSE)) {
1655 getmouseco_areawin(mval);
1656 if(abs(mval[0]-xo)+abs(mval[1]-yo) > 4) {
1659 transform_markers('g', 0);
1662 if(actkb) move_keys(OBACT);
1663 else transform_ipo('g');
1668 BIF_wait_for_statechange();
1673 /* *********************************** */
1675 /* handling of right-hand channel/curve buttons in ipo window */
1676 void do_ipowin_buts(short event)
1681 /* without shift, all other channels are made invisible */
1682 if((G.qual & LR_SHIFTKEY)==0) {
1683 if(event>G.sipo->totipo) return;
1684 ei = G.sipo->editipo;
1685 for(a=0; a<G.sipo->totipo; a++) {
1686 if(a!=event) ei->flag &= ~IPO_VISIBLE;
1687 else ei->flag |= IPO_VISIBLE;
1693 if(event>=0 && event<G.sipo->totipo) {
1694 ei= G.sipo->editipo; // void pointer...
1695 set_active_editipo(ei+event);
1696 set_active_key(event+1); // only if there's a key, of course
1698 scrarea_queue_winredraw(curarea);
1700 update_editipo_flags();
1701 get_status_editipo();
1703 if(G.sipo->showkey) {
1705 if(G.sipo->blocktype==ID_OB) allqueue(REDRAWVIEW3D, 0);
1710 /* the fake buttons to the left of channel names, for select/deselect curves */
1711 void do_ipo_selectbuttons(void)
1717 if(G.sipo->showkey) return;
1719 /* do not allow editipo here: convert editipos to selected */
1720 get_status_editipo();
1722 set_editflag_editipo();
1726 getmouseco_areawin(mval);
1728 nr= -(mval[1]-curarea->winy+30-G.sipo->butofs-IPOBUTY)/IPOBUTY;
1729 if(G.sipo->blocktype==ID_KE) nr--; /* keys show something else in first channel */
1731 if(nr>=0 && nr<G.sipo->totipo) {
1732 ei= G.sipo->editipo;
1735 set_active_editipo(ei);
1736 set_active_key(nr+1);
1739 if((ei->flag & IPO_VISIBLE)==0) {
1740 ei->flag |= IPO_VISIBLE|IPO_SELECT;
1743 if((G.qual & LR_SHIFTKEY)==0) {
1744 ei1= G.sipo->editipo;
1745 for(a=0; a<G.sipo->totipo; a++) {
1746 ei1->flag &= ~IPO_SELECT;
1751 if(ei->flag & IPO_SELECT) {
1752 ei->flag &= ~IPO_SELECT;
1755 ei->flag |= IPO_SELECT;
1758 update_editipo_flags();
1759 scrarea_queue_winredraw(curarea);
1762 BIF_undo_push("Select Ipo curve");
1765 /* ********************************* Inserting keys ********************************************* */
1767 /* depending type, it returns ipo, if needed it creates one */
1768 /* returns either action ipo or "real" ipo */
1769 /* arguments define full context;
1770 - *from has to be set always, to Object in case of Actions
1771 - blocktype defines available channels of Ipo struct (blocktype ID_OB can be in action too)
1772 - if actname, use this to locate actionchannel, and optional constname
1773 - if bonename, the constname is the ipo to the constraint
1776 /* note: check header_ipo.c, spaceipo_assign_ipo() too */
1777 Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char *bonename, short add)
1779 /* lib-linked data is not appropriate here */
1780 if ((from==NULL) || (from->lib))
1783 /* first check action ipos */
1784 if (actname && actname[0]) {
1785 Object *ob= (Object *)from;
1786 bActionChannel *achan;
1788 if (GS(from->name)!=ID_OB) {
1789 printf("called ipo system for action with wrong base pointer\n");
1793 if ((ob->action==NULL) && (add))
1794 ob->action= add_empty_action("Action");
1797 achan= verify_action_channel(ob->action, actname);
1799 achan= get_action_channel(ob->action, actname);
1802 /* automatically assign achan to act-group based on pchan's grouping */
1803 if ((blocktype == ID_PO) && (add))
1804 verify_pchan2achan_grouping(ob->action, ob->pose, actname);
1806 /* constraint exception */
1807 if (blocktype==ID_CO) {
1808 bConstraintChannel *conchan;
1811 conchan= verify_constraint_channel(&achan->constraintChannels, constname);
1813 conchan= get_constraint_channel(&achan->constraintChannels, constname);
1816 if ((conchan->ipo==NULL) && (add))
1817 conchan->ipo= add_ipo("CoIpo", ID_CO);
1818 return conchan->ipo;
1822 if ((achan->ipo==NULL) && (add))
1823 achan->ipo= add_ipo("ActIpo", blocktype);
1829 switch (GS(from->name)) {
1832 Object *ob= (Object *)from;
1834 /* constraint exception */
1835 if (blocktype==ID_CO) {
1836 /* check the local constraint ipo */
1837 if (bonename && bonename[0] && ob->pose) {
1838 bPoseChannel *pchan= get_pose_channel(ob->pose, bonename);
1841 for (con= pchan->constraints.first; con; con= con->next) {
1842 if (strcmp(con->name, constname)==0)
1847 if ((con->ipo==NULL) && (add))
1848 con->ipo= add_ipo("CoIpo", ID_CO);
1852 else { /* the actionchannel */
1853 bConstraintChannel *conchan;
1856 conchan= verify_constraint_channel(&ob->constraintChannels, constname);
1858 conchan= get_constraint_channel(&ob->constraintChannels, constname);
1861 if ((conchan->ipo==NULL) && (add))
1862 conchan->ipo= add_ipo("CoIpo", ID_CO);
1863 return conchan->ipo;
1867 else if (blocktype==ID_OB) {
1868 if ((ob->ipo==NULL) && (add))
1869 ob->ipo= add_ipo("ObIpo", ID_OB);
1872 else if (blocktype==ID_KE) {
1873 Key *key= ob_get_key((Object *)from);
1876 if ((key->ipo==NULL) && (add))
1877 key->ipo= add_ipo("KeyIpo", ID_KE);
1882 else if (blocktype== ID_FLUIDSIM) {
1883 Object *ob= (Object *)from;
1885 if (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) {
1886 FluidsimSettings *fss= ob->fluidsimSettings;
1888 if ((fss->ipo==NULL) && (add))
1889 fss->ipo= add_ipo("FluidsimIpo", ID_FLUIDSIM);
1893 else if(blocktype== ID_PA) {
1894 Object *ob= (Object *)from;
1895 ParticleSystem *psys= psys_get_current(ob);
1898 if ((psys->part->ipo==NULL) && (add))
1899 psys->part->ipo= add_ipo("ParticleIpo", ID_PA);
1900 return psys->part->ipo;
1908 Material *ma= (Material *)from;
1910 if ((ma->ipo==NULL) && (add))
1911 ma->ipo= add_ipo("MatIpo", ID_MA);
1917 Tex *tex= (Tex *)from;
1919 if ((tex->ipo==NULL) && (add))
1920 tex->ipo= add_ipo("TexIpo", ID_TE);
1926 Sequence *seq= (Sequence *)from; /* note, sequence is mimicing Id */
1928 if ((seq->ipo==NULL) && (add))
1929 seq->ipo= add_ipo("SeqIpo", ID_SEQ);
1930 update_seq_ipo_rect(seq);
1936 Curve *cu= (Curve *)from;
1938 if ((cu->ipo==NULL) && (add))
1939 cu->ipo= add_ipo("CuIpo", ID_CU);
1945 World *wo= (World *)from;
1947 if ((wo->ipo==NULL) && (add))
1948 wo->ipo= add_ipo("WoIpo", ID_WO);
1954 Lamp *la= (Lamp *)from;
1956 if ((la->ipo==NULL) && (add))
1957 la->ipo= add_ipo("LaIpo", ID_LA);
1963 Camera *ca= (Camera *)from;
1965 if ((ca->ipo==NULL) && (add))
1966 ca->ipo= add_ipo("CaIpo", ID_CA);
1972 bSound *snd= (bSound *)from;
1974 if ((snd->ipo==NULL) && (add))
1975 snd->ipo= add_ipo("SndIpo", ID_SO);
1984 /* returns and creates
1985 * Make sure functions check for NULL or they will crash!
1987 IpoCurve *verify_ipocurve(ID *from, short blocktype, char *actname, char *constname, char *bonename, int adrcode, short add)
1990 IpoCurve *icu= NULL;
1992 /* return 0 if lib */
1993 /* creates ipo too (if add) */
1994 ipo= verify_ipo(from, blocktype, actname, constname, bonename, add);
1996 if (ipo && ipo->id.lib==NULL && from->lib==NULL) {
1997 /* try to find matching curve */
1998 for (icu= ipo->curve.first; icu; icu= icu->next) {
1999 if (icu->adrcode==adrcode)
2003 /* make a new one if none found (and can add) */
2004 if ((icu==NULL) && (add)) {
2005 icu= MEM_callocN(sizeof(IpoCurve), "ipocurve");
2007 icu->flag |= (IPO_VISIBLE|IPO_AUTO_HORIZ);
2008 if (ipo->curve.first==NULL)
2009 icu->flag |= IPO_ACTIVE; /* first one added active */
2011 icu->blocktype= blocktype;
2012 icu->adrcode= adrcode;
2016 BLI_addtail(&ipo->curve, icu);
2018 switch (GS(from->name)) {
2020 Sequence *seq= (Sequence *)from;
2022 update_seq_icu_rects(seq);
2029 /* return ipo-curve */
2034 void add_vert_ipo(void)
2041 if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
2042 if(G.sipo->showkey) {
2044 free_ipokey(&G.sipo->ipokey);
2047 getmouseco_areawin(mval);
2049 if(mval[0]>G.v2d->mask.xmax) return;
2051 ei= get_active_editipo();
2053 error("No active Ipo curve");
2056 ei->flag |= IPO_VISIBLE; /* can happen it is active but not visible */
2058 areamouseco_to_ipoco(G.v2d, mval, &x, &y);
2060 /* convert click-time to ipo-time */
2061 if (NLA_IPO_SCALED) {
2062 x= get_action_frame(OBACT, x);
2067 ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode, 1);
2069 ei->flag |= ei->icu->flag & IPO_AUTO_HORIZ; /* new curve could have been added, weak... */
2071 error("Cannot create an IPO curve, you may be using libdata");
2074 if(ei->icu==NULL) return;
2076 if(ei->disptype==IPO_DISPBITS) {
2077 ei->icu->vartype= IPO_BITS;
2078 val= (int)floor(y-0.5);
2080 y= (float)(1 << val);
2083 insert_vert_icu(ei->icu, x, y, 0);
2085 /* to be sure: if icu was 0, or only 1 curve visible */
2086 ei->flag |= IPO_SELECT;
2087 ei->icu->flag= ei->flag;
2089 editipo_changed(G.sipo, 1);
2090 BIF_undo_push("Add Ipo vertex");
2094 void insertkey_editipo(void)
2099 float *fp, cfra, *insertvals;
2103 ei= get_active_editipo();
2104 if(ei && ei->icu && ei->icu->driver)
2105 event= pupmenu("Insert Curve %t|Default one-to-one mapping %x3");
2106 else if(G.sipo->showkey)
2107 event= pupmenu("Insert Key Vertices %t|Current Frame %x1|Selected Keys %x2");
2109 event= pupmenu("Insert Key Vertices %t|Current Frame %x1");
2114 IpoDriver *driver= ei->icu->driver;
2116 if(ei->icu->bezt) MEM_freeN(ei->icu->bezt);
2117 ei->icu->totvert= 0;
2118 ei->icu->bezt= NULL;
2120 insert_vert_icu(ei->icu, 0.0f, 0.0f, 0);
2122 if(ELEM3(driver->adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) {
2123 if(ei->disptype==IPO_DISPDEGR)
2124 insert_vert_icu(ei->icu, 18.0f, 18.0f, 0);
2126 insert_vert_icu(ei->icu, 18.0f, 1.0f, 0);
2129 insert_vert_icu(ei->icu, 1.0f, 1.0f, 0);
2131 ei->flag |= IPO_SELECT|IPO_VISIBLE;
2132 ei->icu->flag= ei->flag;
2133 ei->icu->extrap= IPO_DIR;
2135 do_ipo_buttons(B_IPOHOME);
2138 ei= G.sipo->editipo;
2139 for(nr=0; nr<G.sipo->totipo; nr++, ei++) {
2140 if (ISPOIN(ei, flag & IPO_VISIBLE, icu)) {
2143 if(G.sipo->showkey) ok= 1;
2144 else if(ei->flag & IPO_SELECT) ok= 1;
2148 if(event==1) tot= 1;
2150 ik= G.sipo->ipokey.first;
2153 if(ik->flag & 1) tot++;
2159 /* correction for ob timeoffs */
2160 cfra= frame_to_float(CFRA);
2162 if(id && GS(id->name)==ID_OB ) {
2163 Object *ob= (Object *)id;
2164 if((ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0) ) {
2165 cfra-= give_timeoffset(ob)*G.scene->r.framelen;
2168 else if(id && GS(id->name)==ID_SEQ) {
2169 Sequence *last_seq = get_last_seq(); /* editsequence.c */
2171 if(last_seq && (last_seq->flag & SEQ_IPO_FRAME_LOCKED) == 0) {
2172 cfra= (float)(100.0*(cfra-last_seq->startdisp)/((float)(last_seq->enddisp-last_seq->startdisp)));
2176 /* convert cfra to ipo-time */
2177 if (NLA_IPO_SCALED) {
2178 cfra= get_action_frame(OBACT, cfra);
2181 insertvals= MEM_mallocN(sizeof(float)*2*tot, "insertkey_editipo");
2182 /* make sure icu->curval is correct */
2183 calc_ipo(G.sipo->ipo, cfra);
2186 insertvals[0]= cfra;
2188 insertvals[1]= ei->icu->curval;
2192 ik= G.sipo->ipokey.first;
2195 calc_ipo(G.sipo->ipo, ik->val);
2198 fp[1]= ei->icu->curval;
2205 for(a=0; a<tot; a++, fp+=2) {
2206 insert_vert_icu(ei->icu, fp[0], fp[1], 0);
2209 MEM_freeN(insertvals);
2210 calc_ipo(G.sipo->ipo, (float)CFRA);
2216 BIF_undo_push("Insert Key Ipo");
2217 allqueue (REDRAWACTION, 0);
2218 allqueue(REDRAWNLA, 0);
2219 allqueue(REDRAWIPO, 0);
2220 allspace(REMAKEIPO, 0);
2224 /* ****************************************************************************** */
2226 void add_duplicate_editipo(void)
2231 BezTriple *bezt, *beztn, *newb;
2234 get_status_editipo();
2235 if(totipo_vertsel==0) return;
2237 ei= G.sipo->editipo;
2238 for(a=0; a<G.sipo->totipo; a++, ei++) {
2239 if (ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt)) {
2240 if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
2243 /* how many points */
2248 if(bezt->f2 & SELECT) tot++;
2254 newb= beztn= MEM_mallocN(icu->totvert*sizeof(BezTriple), "bezt");
2256 b= icu->totvert-tot;
2259 if(bezt->f2 & SELECT) {
2267 MEM_freeN(icu->bezt);
2270 calchandles_ipocurve(icu);
2276 if(G.sipo->showkey) {
2278 if(G.sipo->blocktype==ID_OB) {
2280 if(ob && (ob->ipoflag & OB_DRAWKEY)) allqueue(REDRAWVIEW3D, 0);
2283 BIF_undo_push("Duplicate Ipo");
2287 void remove_doubles_ipo(void)
2291 BezTriple *bezt, *newb, *new1;
2295 ei= G.sipo->editipo;
2296 for(a=0; a<G.sipo->totipo; a++, ei++) {
2297 if (ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt)) {
2299 /* OR the curve is selected OR in editmode OR in keymode */
2301 if(G.sipo->showkey || (ei->flag & IPO_EDIT)) mode= 1;
2302 else if(ei->flag & IPO_SELECT) mode= 2;
2305 bezt= ei->icu->bezt;
2306 newb= new1= MEM_mallocN(ei->icu->totvert*sizeof(BezTriple), "newbezt");
2308 b= ei->icu->totvert-1;
2312 /* can we remove? */
2313 if(mode==2 || (bezt->f2 & SELECT)) {
2315 /* are the points different? */
2316 if( fabs( bezt->vec[1][0]-newb->vec[1][0] ) > 0.9 ) {
2322 VecMidf(newb->vec[0], newb->vec[0], bezt->vec[0]);
2323 VecMidf(newb->vec[1], newb->vec[1], bezt->vec[1]);
2324 VecMidf(newb->vec[2], newb->vec[2], bezt->vec[2]);
2326 newb->h1= newb->h2= HD_FREE;
2339 MEM_freeN(ei->icu->bezt);
2340 ei->icu->bezt= new1;
2342 calchandles_ipocurve(ei->icu);
2347 editipo_changed(G.sipo, 1); /* makes ipokeys again! */
2349 /* remove double keys */
2350 if(G.sipo->showkey) {
2351 ik= G.sipo->ipokey.first;
2355 if( (ik->flag & 1) && (ikn->flag & 1) ) {
2356 if( fabs(ik->val-ikn->val) < 0.9 ) {
2357 val= (float)((ik->val + ikn->val)/2.0);
2359 for(a=0; a<G.sipo->totipo; a++) {
2360 if(ik->data[a]) ik->data[a]->vec[1][0]= val;
2361 if(ikn->data[a]) ikn->data[a]->vec[1][0]= val;
2370 editipo_changed(G.sipo, 1); /* makes ipokeys agian! */
2373 deselectall_editipo();
2374 BIF_undo_push("Remove Doubles (IPO)");
2378 void clean_ipo(void)
2384 ok= fbutton(&G.scene->toolsettings->clean_thresh,
2385 0.0000001f, 1.0, 0.001, 0.1,
2389 get_status_editipo();
2391 ei= G.sipo->editipo;
2392 for(b=0; b<G.sipo->totipo; b++, ei++) {
2393 if (ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt)) {
2396 if(G.sipo->showkey) ok= 1;
2397 else if(totipo_vert && (ei->flag & IPO_EDIT)) ok= 2;
2398 else if(totipo_vert==0 && (ei->flag & IPO_SELECT)) ok= 3;
2401 /* only clean if ok */
2402 clean_ipo_curve(ei->icu);
2407 editipo_changed(G.sipo, 1);
2408 BIF_undo_push("Clean IPO");
2411 void clean_ipo_curve(IpoCurve *icu)
2413 BezTriple *old_bezts, *bezt, *beztn;
2418 /* check if any points */
2419 if (icu == NULL || icu->totvert <= 1)
2422 /* get threshold for match-testing */
2423 thresh= G.scene->toolsettings->clean_thresh;
2425 /* make a copy of the old BezTriples, and clear IPO curve */
2426 old_bezts = icu->bezt;
2427 totCount = icu->totvert;
2431 /* now insert first keyframe, as it should be ok */
2433 insert_vert_icu(icu, bezt->vec[1][0], bezt->vec[1][1], 0);
2435 /* Loop through BezTriples, comparing them. Skip any that do
2436 * not fit the criteria for "ok" points.
2438 for (i=1; i<totCount; i++) {
2439 float prev[2], cur[2], next[2];
2441 /* get BezTriples and their values */
2442 if (i < (totCount - 1)) {
2443 beztn = (old_bezts + (i+1));
2444 next[0]= beztn->vec[1][0]; next[1]= beztn->vec[1][1];
2448 next[0] = next[1] = 0.0f;
2450 lastb= (icu->bezt + (icu->totvert - 1));
2451 bezt= (old_bezts + i);
2453 /* get references for quicker access */
2454 prev[0] = lastb->vec[1][0]; prev[1] = lastb->vec[1][1];
2455 cur[0] = bezt->vec[1][0]; cur[1] = bezt->vec[1][1];
2457 /* check if current bezt occurs at same time as last ok */
2458 if (IS_EQT(cur[0], prev[0], thresh)) {
2459 /* If there is a next beztriple, and if occurs at the same time, only insert
2460 * if there is a considerable distance between the points, and also if the
2461 * current is further away than the next one is to the previous.
2463 if (beztn && (IS_EQT(cur[0], next[0], thresh)) &&
2464 (IS_EQT(next[1], prev[1], thresh)==0))
2466 /* only add if current is further away from previous */
2467 if (cur[1] > next[1]) {
2468 if (IS_EQT(cur[1], prev[1], thresh) == 0) {
2469 /* add new keyframe */
2470 insert_vert_icu(icu, cur[0], cur[1], 0);
2475 /* only add if values are a considerable distance apart */
2476 if (IS_EQT(cur[1], prev[1], thresh) == 0) {
2477 /* add new keyframe */
2478 insert_vert_icu(icu, cur[0], cur[1], 0);
2483 /* checks required are dependent on whether this is last keyframe or not */
2485 /* does current have same value as previous and next? */
2486 if (IS_EQT(cur[1], prev[1], thresh) == 0) {
2487 /* add new keyframe*/
2488 insert_vert_icu(icu, cur[0], cur[1], 0);
2490 else if (IS_EQT(cur[1], next[1], thresh) == 0) {
2491 /* add new keyframe */
2492 insert_vert_icu(icu, cur[0], cur[1], 0);
2496 /* add if value doesn't equal that of previous */
2497 if (IS_EQT(cur[1], prev[1], thresh) == 0) {
2498 /* add new keyframe */
2499 insert_vert_icu(icu, cur[0], cur[1], 0);
2505 /* now free the memory used by the old BezTriples */
2507 MEM_freeN(old_bezts);
2511 /* temp struct used for smooth_ipo */
2512 typedef struct tSmooth_Bezt {
2513 float *h1, *h2, *h3; /* bezt->vec[0,1,2][1] */
2516 void smooth_ipo(void)
2522 get_status_editipo();
2524 ei= G.sipo->editipo;
2525 for(b=0; b<G.sipo->totipo; b++, ei++) {
2526 if (ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt)) {
2528 if(G.sipo->showkey) ok= 1;
2529 else if(totipo_vert && (ei->flag & IPO_EDIT)) ok= 2;
2530 else if(totipo_vert==0 && (ei->flag & IPO_SELECT)) ok= 3;
2533 IpoCurve *icu= ei->icu;
2535 int i, x, totSel = 0;
2537 /* check if enough points */
2538 if (icu->totvert >= 3) {
2539 /* first loop through - count how many verts are selected, and fix up handles */
2541 for (i=0; i < icu->totvert; i++, bezt++) {
2542 if (BEZSELECTED(bezt)) {
2543 /* line point's handles up with point's vertical position */
2544 bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1];
2545 if ((bezt->h1==HD_AUTO) || (bezt->h1==HD_VECT)) bezt->h1= HD_ALIGN;
2546 if ((bezt->h2==HD_AUTO) || (bezt->h2==HD_VECT)) bezt->h2= HD_ALIGN;
2548 /* add value to total */
2553 /* if any points were selected, allocate tSmooth_Bezt points to work on */
2555 tSmooth_Bezt *tarray, *tsb;
2557 /* allocate memory in one go */
2558 tsb= tarray= MEM_callocN(totSel*sizeof(tSmooth_Bezt), "tSmooth_Bezt Array");
2560 /* populate tarray with data of selected points */
2562 for (i=0, x=0; (i < icu->totvert) && (x < totSel); i++, bezt++) {
2563 if (BEZSELECTED(bezt)) {
2564 /* tsb simply needs pointer to vec, and index */
2565 tsb->h1 = &bezt->vec[0][1];
2566 tsb->h2 = &bezt->vec[1][1];
2567 tsb->h3 = &bezt->vec[2][1];
2569 /* advance to the next tsb to populate */
2577 /* calculate the new smoothed ipo's with weighted averages:
2578 * - this is done with two passes
2579 * - uses 5 points for each operation (which stores in the relevant handles)
2580 * - previous: w/a ratio = 3:5:2:1:1
2581 * - next: w/a ratio = 1:1:2:5:3
2584 /* round 1: calculate previous and next */
2586 for (i=0; i < totSel; i++, tsb++) {
2587 /* don't touch end points (otherwise, curves slowly explode) */
2588 if (ELEM(i, 0, (totSel-1)) == 0) {
2589 tSmooth_Bezt *tP1 = tsb - 1;
2590 tSmooth_Bezt *tP2 = (i-2 > 0) ? (tsb - 2) : (NULL);
2591 tSmooth_Bezt *tN1 = tsb + 1;
2592 tSmooth_Bezt *tN2 = (i+2 < totSel) ? (tsb + 2) : (NULL);
2594 float p1 = *tP1->h2;
2595 float p2 = (tP2) ? (*tP2->h2) : (*tP1->h2);
2596 float c1 = *tsb->h2;
2597 float n1 = *tN1->h2;
2598 float n2 = (tN2) ? (*tN2->h2) : (*tN1->h2);
2600 /* calculate previous and next */
2601 *tsb->h1= (3*p2 + 5*p1 + 2*c1 + n1 + n2) / 12;
2602 *tsb->h3= (p2 + p1 + 2*c1 + 5*n1 + 3*n2) / 12;
2606 /* round 2: calculate new values and reset handles */
2608 for (i=0; i < totSel; i++, tsb++) {
2609 /* calculate new position by averaging handles */
2610 *tsb->h2 = (*tsb->h1 + *tsb->h3) / 2;
2612 /* reset handles now */
2613 *tsb->h1 = *tsb->h2;
2614 *tsb->h3 = *tsb->h2;
2617 /* free memory required for tarray */
2622 /* recalculate handles */
2623 calchandles_ipocurve(icu);
2628 editipo_changed(G.sipo, 1);
2629 BIF_undo_push("Smooth IPO");
2632 void join_ipo_menu(void)
2635 mode= pupmenu("Join %t|All Selected %x1|Selected Doubles %x2");
2637 if (mode == -1) return;
2642 void join_ipo(int mode)
2647 BezTriple *bezt, *beztn, *newb;
2651 get_status_editipo();
2655 * Selected Doubles: 2
2659 remove_doubles_ipo();
2663 /* first: multiple selected verts in 1 curve */
2664 ei= G.sipo->editipo;
2665 for(a=0; a<G.sipo->totipo; a++, ei++) {
2666 if (ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt)) {
2667 if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
2670 /* how many points */
2675 if(bezt->f2 & SELECT) tot++;
2683 newb= MEM_mallocN(icu->totvert*sizeof(BezTriple), "bezt");
2684 /* the first point is the new one */
2689 b= icu->totvert+tot+1;
2692 if(bezt->f2 & SELECT) {
2693 if(tot==0) *newb= *bezt;
2695 VecAddf(newb->vec[0], newb->vec[0], bezt->vec[0]);
2696 VecAddf(newb->vec[1], newb->vec[1], bezt->vec[1]);
2697 VecAddf(newb->vec[2], newb->vec[2], bezt->vec[2]);
2708 VecMulf(newb->vec[0], (float)(1.0/((float)tot)));
2709 VecMulf(newb->vec[1], (float)(1.0/((float)tot)));
2710 VecMulf(newb->vec[2], (float)(1.0/((float)tot)));
2712 MEM_freeN(icu->bezt);
2715 sort_time_ipocurve(icu);
2716 calchandles_ipocurve(icu);
2722 /* next: in keymode: join multiple selected keys */
2724 editipo_changed(G.sipo, 1); /* makes ipokeys again! */
2726 if(G.sipo->showkey) {
2727 ik= G.sipo->ipokey.first;
2732 for(a=0; a<G.sipo->totipo; a++) {
2734 val+= ik->data[a]->vec[1][0];
2745 ik= G.sipo->ipokey.first;
2748 for(a=0; a<G.sipo->totipo; a++) {
2750 ik->data[a]->vec[1][0]= val;
2756 editipo_changed(G.sipo, 0);
2759 deselectall_editipo();
2760 BIF_undo_push("Join Ipo");
2763 void ipo_snap_menu(void)
2767 event= pupmenu("Snap %t|Horizontal %x1|To Next %x2|To Frame %x3|To Current Frame%x4");
2768 if(event < 1) return;
2773 void ipo_snap(short event)
2785 * To Current Frame: 4
2788 get_status_editipo();
2790 /* map ipo-points for editing if scaled ipo */
2791 if (NLA_IPO_SCALED) {
2792 actstrip_map_ipo_keys(OBACT, G.sipo->ipo, 0, 0);
2795 ei= G.sipo->editipo;
2796 for(b=0; b<G.sipo->totipo; b++, ei++) {
2797 if (ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt)) {
2800 if(G.sipo->showkey) ok2= 1;
2801 else if(totipo_vert && (ei->flag & IPO_EDIT)) ok2= 2;
2802 else if(totipo_vert==0 && (ei->flag & IPO_SELECT)) ok2= 3;
2805 bezt= ei->icu->bezt;
2806 a= ei->icu->totvert;
2810 if(bezt->f2 & SELECT) ok= 1;
2816 bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1];
2817 if(bezt->h1==HD_AUTO || bezt->h1==HD_VECT) bezt->h1= HD_ALIGN;
2818 if(bezt->h2==HD_AUTO || bezt->h2==HD_VECT) bezt->h2= HD_ALIGN;
2822 bezt->vec[0][1]= bezt->vec[1][1]= bezt->vec[2][1]= (bezt+1)->vec[1][1];
2823 if(bezt->h1==HD_AUTO || bezt->h1==HD_VECT) bezt->h1= HD_ALIGN;
2824 if(bezt->h2==HD_AUTO || bezt->h2==HD_VECT) bezt->h2= HD_ALIGN;
2828 bezt->vec[1][0]= (float)(floor(bezt->vec[1][0]+0.5));
2830 else if(event==4) { /* to current frame */
2832 if(ok2==1 || ok2==2) {
2834 if(G.sipo->blocktype==ID_SEQ) {
2837 seq= (Sequence *)G.sipo->from;
2838 if(seq && (seq->flag & SEQ_IPO_FRAME_LOCKED) == 0) {
2839 dx= (float)(CFRA-seq->startdisp);
2840 dx= (float)(100.0*dx/((float)(seq->enddisp-seq->startdisp)));
2842 dx-= bezt->vec[1][0];
2844 dx= G.scene->r.framelen*CFRA - bezt->vec[1][0];
2847 else dx= G.scene->r.framelen*CFRA - bezt->vec[1][0];
2849 bezt->vec[0][0]+= dx;
2850 bezt->vec[1][0]+= dx;
2851 bezt->vec[2][0]+= dx;