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 *****
48 #include "MEM_guardedalloc.h"
50 #include "BLI_blenlib.h"
51 #include "BLI_arithb.h"
53 #include "DNA_action_types.h"
54 #include "DNA_curve_types.h"
55 #include "DNA_ipo_types.h"
56 #include "DNA_key_types.h"
57 #include "DNA_object_types.h"
58 #include "DNA_scene_types.h"
59 #include "DNA_screen_types.h"
60 #include "DNA_space_types.h"
61 #include "DNA_sequence_types.h"
62 #include "DNA_userdef_types.h"
64 #include "BKE_curve.h"
65 #include "BKE_depsgraph.h"
66 #include "BKE_global.h"
69 #include "BKE_utildefines.h"
72 #include "BIF_resources.h"
73 #include "BIF_screen.h"
74 #include "BIF_interface.h"
75 #include "BIF_mywindow.h"
76 #include "BIF_space.h"
77 #include "BIF_toolbox.h"
78 #include "BIF_glutil.h"
80 #include "BSE_drawipo.h"
82 #include "BSE_editipo.h"
83 #include "BSE_editipo_types.h"
84 #include "BSE_editnla_types.h"
88 #include "butspace.h" // shouldnt be...
90 /* local define... also used in editipo ... */
91 #define ISPOIN(a, b, c) ( (a->b) && (a->c) )
92 #define ISPOIN3(a, b, c, d) ( (a->b) && (a->c) && (a->d) )
93 #define ISPOIN4(a, b, c, d, e) ( (a->b) && (a->c) && (a->d) && (a->e) )
96 /* minimum pixels per gridstep */
99 static float ipogrid_dx, ipogrid_dy, ipogrid_startx, ipogrid_starty;
100 static int ipomachtx, ipomachty;
102 static int vertymin, vertymax, horxmin, horxmax; /* globals to test LEFTMOUSE for scrollbar */
104 extern short ACTWIDTH; /* this is ugly! */
106 static void scroll_prstr(float x, float y, float val, char dir, int disptype)
113 if ELEM(disptype, IPO_DISPDEGR, IPO_DISPTIME) {
118 else macht= ipomachtx;
120 if (macht<=0) sprintf(str, "%.*f", 1-macht, val);
121 else sprintf(str, "%d", (int)floor(val + 0.375));
124 if(dir=='h') x-= 4*len;
126 if(dir=='v' && disptype==IPO_DISPDEGR) {
127 str[len]= 186; /* Degree symbol */
132 BMF_DrawString(G.fonts, str);
135 static void step_to_grid(float *step, int *macht)
139 /* try to write step as a power of 10 */
148 if(rem < 0.2) rem= 0.2;
149 else if(rem < 0.5) rem= 0.5;
152 *step= rem*pow(10.0, (float)*macht);
154 // partial of a frame have no meaning
155 if(curarea->spacetype==SPACE_TIME) {
156 SpaceTime *stime= curarea->spacedata.first;
157 if(stime->flag & TIME_DRAWFRAMES) {
163 if(rem==1.0) (*macht)++; // prevents printing 1.0 2.0 3.0 etc
166 if(rem < 2.0) rem= 2.0;
167 else if(rem < 5.0) rem= 5.0;
170 *step= rem*pow(10.0, (float)*macht);
173 if(rem==10.0) (*macht)++; // prevents printing 1.0 2.0 3.0 etc
179 float space, pixels, secondiv=1.0;
181 /* rule: gridstep is minimal IPOSTEP pixels */
182 /* how large is IPOSTEP pixels? */
186 /* detect of we have seconds or frames, should become argument */
187 if(curarea->spacetype==SPACE_TIME) {
188 SpaceTime *stime= curarea->spacedata.first;
189 if(!(stime->flag & TIME_DRAWFRAMES)) {
191 secondiv= 0.01 * (float)G.scene->r.frs_sec;
195 space= G.v2d->cur.xmax - G.v2d->cur.xmin;
196 pixels= G.v2d->mask.xmax-G.v2d->mask.xmin;
198 ipogrid_dx= IPOSTEP*space/(secondiv*pixels);
199 step_to_grid(&ipogrid_dx, &ipomachtx);
200 ipogrid_dx*= secondiv;
202 if ELEM3(curarea->spacetype, SPACE_SEQ, SPACE_SOUND, SPACE_TIME) {
203 if(ipogrid_dx < 0.1) ipogrid_dx= 0.1;
205 if(ipomachtx<-2) ipomachtx= -2;
208 space= (G.v2d->cur.ymax - G.v2d->cur.ymin);
209 pixels= curarea->winy;
210 ipogrid_dy= IPOSTEP*space/pixels;
211 step_to_grid(&ipogrid_dy, &ipomachty);
213 if ELEM3(curarea->spacetype, SPACE_SEQ, SPACE_SOUND, SPACE_TIME) {
214 if(ipogrid_dy < 1.0) ipogrid_dy= 1.0;
215 if(ipomachty<1) ipomachty= 1;
218 ipogrid_startx= secondiv*(G.v2d->cur.xmin/secondiv - fmod(G.v2d->cur.xmin/secondiv, ipogrid_dx/secondiv));
219 if(G.v2d->cur.xmin<0.0) ipogrid_startx-= ipogrid_dx;
221 ipogrid_starty= (G.v2d->cur.ymin-fmod(G.v2d->cur.ymin, ipogrid_dy));
222 if(G.v2d->cur.ymin<0.0) ipogrid_starty-= ipogrid_dy;
226 void draw_ipogrid(void)
228 float vec1[2], vec2[2];
231 vec1[0]= vec2[0]= ipogrid_startx;
232 vec1[1]= ipogrid_starty;
233 vec2[1]= G.v2d->cur.ymax;
235 step= (G.v2d->mask.xmax-G.v2d->mask.xmin+1)/IPOSTEP;
237 BIF_ThemeColor(TH_GRID);
239 for(a=0; a<step; a++) {
240 glBegin(GL_LINE_STRIP);
241 glVertex2fv(vec1); glVertex2fv(vec2);
243 vec2[0]= vec1[0]+= ipogrid_dx;
246 vec2[0]= vec1[0]-= 0.5*ipogrid_dx;
248 BIF_ThemeColorShade(TH_GRID, 16);
251 for(a=0; a<=step; a++) {
252 glBegin(GL_LINE_STRIP);
253 glVertex2fv(vec1); glVertex2fv(vec2);
255 vec2[0]= vec1[0]-= ipogrid_dx;
258 if ELEM4(curarea->spacetype, SPACE_SOUND, SPACE_ACTION, SPACE_NLA, SPACE_TIME);
260 vec1[0]= ipogrid_startx;
261 vec1[1]= vec2[1]= ipogrid_starty;
262 vec2[0]= G.v2d->cur.xmax;
264 step= (curarea->winy+1)/IPOSTEP;
266 BIF_ThemeColor(TH_GRID);
267 for(a=0; a<=step; a++) {
268 glBegin(GL_LINE_STRIP);
269 glVertex2fv(vec1); glVertex2fv(vec2);
271 vec2[1]= vec1[1]+= ipogrid_dy;
273 vec2[1]= vec1[1]-= 0.5*ipogrid_dy;
276 if(curarea->spacetype==SPACE_IPO) {
277 BIF_ThemeColorShade(TH_GRID, 16);
278 for(a=0; a<step; a++) {
279 glBegin(GL_LINE_STRIP);
280 glVertex2fv(vec1); glVertex2fv(vec2);
282 vec2[1]= vec1[1]-= ipogrid_dy;
287 BIF_ThemeColorShade(TH_GRID, -50);
289 if (curarea->spacetype!=SPACE_ACTION && curarea->spacetype!=SPACE_NLA)
290 { /* Horizontal axis */
291 vec1[0]= G.v2d->cur.xmin;
292 vec2[0]= G.v2d->cur.xmax;
293 vec1[1]= vec2[1]= 0.0;
294 glBegin(GL_LINE_STRIP);
304 vec1[1]= G.v2d->cur.ymin;
305 vec2[1]= G.v2d->cur.ymax;
306 vec1[0]= vec2[0]= 0.0;
307 glBegin(GL_LINE_STRIP);
308 glVertex2fv(vec1); glVertex2fv(vec2);
312 if(curarea->spacetype==SPACE_IPO) {
313 if(G.sipo->blocktype==ID_SEQ) {
314 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
315 glRectf(0.0, 0.0, 100.0, 1.0);
316 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
318 else if(ELEM(G.sipo->blocktype, ID_CU, ID_CO)) {
319 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
320 glRectf(0.0, 1.0, G.v2d->cur.xmax, 1.0);
321 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
326 void areamouseco_to_ipoco(View2D *v2d, short *mval, float *x, float *y)
330 div= v2d->mask.xmax-v2d->mask.xmin;
333 *x= v2d->cur.xmin+ (v2d->cur.xmax-v2d->cur.xmin)*(mval[0]-ofs)/div;
335 div= v2d->mask.ymax-v2d->mask.ymin;
338 *y= v2d->cur.ymin+ (v2d->cur.ymax-v2d->cur.ymin)*(mval[1]-ofs)/div;
341 void ipoco_to_areaco(View2D *v2d, float *vec, short *mval)
347 x= (vec[0] - v2d->cur.xmin)/(v2d->cur.xmax-v2d->cur.xmin);
348 y= (vec[1] - v2d->cur.ymin)/(v2d->cur.ymax-v2d->cur.ymin);
350 if(x>=0.0 && x<=1.0) {
351 if(y>=0.0 && y<=1.0) {
352 mval[0]= v2d->mask.xmin + x*(v2d->mask.xmax-v2d->mask.xmin);
353 mval[1]= v2d->mask.ymin + y*(v2d->mask.ymax-v2d->mask.ymin);
358 void ipoco_to_areaco_noclip(View2D *v2d, float *vec, short *mval)
362 x= (vec[0] - v2d->cur.xmin)/(v2d->cur.xmax-v2d->cur.xmin);
363 y= (vec[1] - v2d->cur.ymin)/(v2d->cur.ymax-v2d->cur.ymin);
365 x= v2d->mask.xmin + x*(v2d->mask.xmax-v2d->mask.xmin);
366 y= v2d->mask.ymin + y*(v2d->mask.ymax-v2d->mask.ymin);
368 if(x<-32760) mval[0]= -32760;
369 else if(x>32760) mval[0]= 32760;
372 if(y<-32760) mval[1]= -32760;
373 else if(y>32760) mval[1]= 32760;
377 int in_ipo_buttons(void)
381 getmouseco_areawin(mval);
383 if(mval[0]< G.v2d->mask.xmax) return 0;
387 static View2D *spacelink_get_view2d(SpaceLink *sl)
389 if(sl->spacetype==SPACE_IPO)
390 return &((SpaceIpo *)sl)->v2d;
391 else if(sl->spacetype==SPACE_SOUND)
392 return &((SpaceSound *)sl)->v2d;
393 if(sl->spacetype==SPACE_ACTION)
394 return &((SpaceAction *)sl)->v2d;
395 if(sl->spacetype==SPACE_NLA)
396 return &((SpaceNla *)sl)->v2d;
397 if(sl->spacetype==SPACE_TIME)
398 return &((SpaceTime *)sl)->v2d;
403 /* copies changes in this view from or to all 2d views with lock option open */
404 void view2d_do_locks(ScrArea *cursa, int flag)
407 View2D *v2d, *curv2d;
410 curv2d= spacelink_get_view2d(cursa->spacedata.first);
411 if(curv2d==NULL) return;
412 if((curv2d->flag & V2D_VIEWLOCK)==0) return;
414 for(sa= G.curscreen->areabase.first; sa; sa= sa->next) {
416 for(sl= sa->spacedata.first; sl; sl= sl->next) {
418 v2d= spacelink_get_view2d(sl);
420 if(v2d->flag & V2D_VIEWLOCK) {
421 if(flag & V2D_LOCK_COPY) {
422 v2d->cur.xmin= curv2d->cur.xmin;
423 v2d->cur.xmax= curv2d->cur.xmax;
426 curv2d->cur.xmin= v2d->cur.xmin;
427 curv2d->cur.xmax= v2d->cur.xmax;
428 scrarea_queue_winredraw(sa);
431 if(flag & V2D_LOCK_REDRAW)
432 scrarea_do_windraw(sa);
434 scrarea_queue_winredraw(sa);
442 /* event based, note: curarea is in here... */
443 void view2d_zoom(View2D *v2d, float factor, int winx, int winy)
445 float dx= factor*(v2d->cur.xmax-v2d->cur.xmin);
446 float dy= factor*(v2d->cur.ymax-v2d->cur.ymin);
447 if ((v2d->keepzoom & V2D_LOCKZOOM_X)==0) {
451 if ((v2d->keepzoom & V2D_LOCKZOOM_Y)==0) {
455 test_view2d(v2d, winx, winy);
456 view2d_do_locks(curarea, V2D_LOCK_COPY);
460 void test_view2d(View2D *v2d, int winx, int winy)
462 /* cur is not allowed to be larger than max, smaller than min, or outside of tot */
464 float dx, dy, temp, fac, zoom;
466 /* correct winx for scroll */
467 if(v2d->scroll & L_SCROLL) winx-= SCROLLB;
468 if(v2d->scroll & B_SCROLL) winy-= SCROLLH;
473 dx= cur->xmax-cur->xmin;
474 dy= cur->ymax-cur->ymin;
478 if (v2d->keepzoom & V2D_LOCKZOOM_Y)
479 v2d->cur.ymax=v2d->cur.ymin+((float)winy);
481 if (v2d->keepzoom & V2D_LOCKZOOM_X)
482 v2d->cur.xmax=v2d->cur.xmin+((float)winx);
486 zoom= ((float)winx)/dx;
488 if(zoom<v2d->minzoom || zoom>v2d->maxzoom) {
489 if(zoom<v2d->minzoom) fac= zoom/v2d->minzoom;
490 else fac= zoom/v2d->maxzoom;
493 temp= 0.5*(cur->xmax+cur->xmin);
495 cur->xmin= temp-0.5*dx;
496 cur->xmax= temp+0.5*dx;
499 zoom= ((float)winy)/dy;
501 if(zoom<v2d->minzoom || zoom>v2d->maxzoom) {
502 if(zoom<v2d->minzoom) fac= zoom/v2d->minzoom;
503 else fac= zoom/v2d->maxzoom;
506 temp= 0.5*(cur->ymax+cur->ymin);
507 cur->ymin= temp-0.5*dy;
508 cur->ymax= temp+0.5*dy;
512 if(dx<G.v2d->min[0]) {
514 temp= 0.5*(cur->xmax+cur->xmin);
515 cur->xmin= temp-0.5*dx;
516 cur->xmax= temp+0.5*dx;
518 else if(dx>G.v2d->max[0]) {
520 temp= 0.5*(cur->xmax+cur->xmin);
521 cur->xmin= temp-0.5*dx;
522 cur->xmax= temp+0.5*dx;
525 if(dy<G.v2d->min[1]) {
527 temp= 0.5*(cur->ymax+cur->ymin);
528 cur->ymin= temp-0.5*dy;
529 cur->ymax= temp+0.5*dy;
531 else if(dy>G.v2d->max[1]) {
533 temp= 0.5*(cur->ymax+cur->ymin);
534 cur->ymin= temp-0.5*dy;
535 cur->ymax= temp+0.5*dy;
539 if(v2d->keepaspect) {
540 short do_x=0, do_y=0;
542 /* when a window edge changes, the aspect ratio can't be used to
543 find which is the best new 'cur' rect. thats why it stores 'old' */
544 if(winx!=v2d->oldwinx) do_x= 1;
545 if(winy!=v2d->oldwiny) do_y= 1;
547 dx= (cur->ymax-cur->ymin)/(cur->xmax-cur->xmin);
548 dy= ((float)winy)/((float)winx);
550 if(do_x==do_y) { // both sizes change, ctrl+uparrow
551 if(do_x==1 && do_y==1) {
552 if( ABS(winx-v2d->oldwinx)>ABS(winy-v2d->oldwiny)) do_y= 0;
555 else if( dy > 1.0) do_x= 0; else do_x= 1;
563 /* portrait window: correct for x */
564 dx= cur->ymax-cur->ymin;
565 temp= (cur->xmax+cur->xmin);
567 cur->xmin= temp/2.0 - 0.5*dx/dy;
568 cur->xmax= temp/2.0 + 0.5*dx/dy;
571 dx= cur->xmax-cur->xmin;
572 temp= (cur->ymax+cur->ymin);
574 cur->ymin= temp/2.0 - 0.5*dy*dx;
575 cur->ymax= temp/2.0 + 0.5*dy*dx;
580 dx= cur->xmax-cur->xmin;
581 dy= cur->ymax-cur->ymin;
583 if(dx > tot->xmax-tot->xmin) {
584 if(v2d->keepzoom==0) {
585 if(cur->xmin<tot->xmin) cur->xmin= tot->xmin;
586 if(cur->xmax>tot->xmax) cur->xmax= tot->xmax;
589 if(cur->xmax < tot->xmax) {
590 dx= tot->xmax-cur->xmax;
594 else if(cur->xmin > tot->xmin) {
595 dx= cur->xmin-tot->xmin;
602 if(cur->xmin < tot->xmin) {
603 dx= tot->xmin-cur->xmin;
607 else if(cur->xmax > tot->xmax) {
608 dx= cur->xmax-tot->xmax;
614 if(dy > tot->ymax-tot->ymin) {
615 if(v2d->keepzoom==0) {
616 if(cur->ymin<tot->ymin) cur->ymin= tot->ymin;
617 if(cur->ymax>tot->ymax) cur->ymax= tot->ymax;
620 if(cur->ymax < tot->ymax) {
621 dy= tot->ymax-cur->ymax;
625 else if(cur->ymin > tot->ymin) {
626 dy= cur->ymin-tot->ymin;
633 if(cur->ymin < tot->ymin) {
634 dy= tot->ymin-cur->ymin;
638 else if(cur->ymax > tot->ymax) {
639 dy= cur->ymax-tot->ymax;
648 void calc_scrollrcts(ScrArea *sa, View2D *v2d, int winx, int winy)
650 v2d->mask.xmin= v2d->mask.ymin= 0;
651 v2d->mask.xmax= winx;
652 v2d->mask.ymax= winy;
654 if(sa->spacetype==SPACE_ACTION) {
655 if(sa->winx > ACTWIDTH+50) {
656 v2d->mask.xmin+= ACTWIDTH;
657 v2d->hor.xmin+=ACTWIDTH;
660 else if(sa->spacetype==SPACE_NLA){
661 if(sa->winx > NLAWIDTH+50) {
662 v2d->mask.xmin+= NLAWIDTH;
663 v2d->hor.xmin+=NLAWIDTH;
666 else if(sa->spacetype==SPACE_IPO) {
667 v2d->mask.xmax-= IPOBUTX;
669 if(v2d->mask.xmax<IPOBUTX)
670 v2d->mask.xmax= winx;
674 if(v2d->scroll & L_SCROLL) {
675 v2d->vert= v2d->mask;
676 v2d->vert.xmax= SCROLLB;
677 v2d->mask.xmin= SCROLLB;
679 else if(v2d->scroll & R_SCROLL) {
680 v2d->vert= v2d->mask;
681 v2d->vert.xmin= v2d->vert.xmax-SCROLLB;
682 v2d->mask.xmax= v2d->vert.xmin;
685 if(v2d->scroll & B_SCROLL) {
687 v2d->hor.ymax= SCROLLH;
688 v2d->mask.ymin= SCROLLH;
690 else if(v2d->scroll & T_SCROLL) {
692 v2d->hor.ymin= v2d->hor.ymax-SCROLLH;
693 v2d->mask.ymax= v2d->hor.ymin;
698 /* draws a line in left vertical scrollbar at the given height */
699 static void draw_solution_line(View2D *v2d, float h)
704 vec[0]= v2d->cur.xmin;
706 ipoco_to_areaco(v2d, vec, mval);
707 if(mval[0]!=IS_CLIPPED) {
709 glVertex2f(v2d->vert.xmin, mval[1]);
710 glVertex2f(v2d->vert.xmax, mval[1]);
715 static void draw_solution(SpaceIpo *sipo)
717 View2D *v2d= &sipo->v2d;
721 if (!(v2d->scroll & VERT_SCROLL)) return;
724 for(a=0; a<sipo->totipo; a++, ei++) {
725 if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
728 /* DISPBITS ipos have 'multiple' values. */
729 if(ei->disptype==IPO_DISPBITS) {
730 int b, val= ei->icu->curval;
734 draw_solution_line(v2d, b+1);
736 draw_solution_line(v2d, ei->icu->curval);
742 /* used for drawing timeline */
743 void draw_view2d_numbers_horiz(int drawframes)
745 float fac, fac2, dfac, val;
747 /* the numbers: convert ipogrid_startx and -dx to scroll coordinates */
749 fac= (ipogrid_startx- G.v2d->cur.xmin)/(G.v2d->cur.xmax-G.v2d->cur.xmin);
750 fac= G.v2d->mask.xmin+fac*(G.v2d->mask.xmax-G.v2d->mask.xmin);
752 dfac= (ipogrid_dx)/(G.v2d->cur.xmax-G.v2d->cur.xmin);
753 dfac= dfac*(G.v2d->mask.xmax-G.v2d->mask.xmin);
755 BIF_ThemeColor(TH_TEXT);
757 while(fac < G.v2d->mask.xmax) {
761 scroll_prstr(fac, 2.0+(float)(G.v2d->mask.ymin), val, 'h', 0);
764 fac2= val/(float)G.scene->r.frs_sec;
765 scroll_prstr(fac, 2.0+(float)(G.v2d->mask.ymin), fac2, 'h', 0);
774 void drawscroll(int disptype)
777 float fac, dfac, val, fac2, tim;
778 int darker, dark, light, lighter;
788 if(G.v2d->scroll & HOR_SCROLL) {
790 BIF_ThemeColorShade(TH_SHADE1, light);
791 glRecti(hor.xmin, hor.ymin, hor.xmax, hor.ymax);
794 fac= (G.v2d->cur.xmin- G.v2d->tot.xmin)/(G.v2d->tot.xmax-G.v2d->tot.xmin);
795 if(fac<0.0) fac= 0.0;
796 horxmin= hor.xmin+fac*(hor.xmax-hor.xmin);
798 fac= (G.v2d->cur.xmax- G.v2d->tot.xmin)/(G.v2d->tot.xmax-G.v2d->tot.xmin);
799 if(fac>1.0) fac= 1.0;
800 horxmax= hor.xmin+fac*(hor.xmax-hor.xmin);
802 if(horxmin > horxmax) horxmin= horxmax;
804 BIF_ThemeColorShade(TH_SHADE1, dark);
805 glRecti(horxmin, hor.ymin, horxmax, hor.ymax);
807 /* decoration bright line */
808 BIF_ThemeColorShade(TH_SHADE1, lighter);
809 sdrawline(hor.xmin, hor.ymax, hor.xmax, hor.ymax);
811 /* the numbers: convert ipogrid_startx and -dx to scroll coordinates */
812 fac= (ipogrid_startx- G.v2d->cur.xmin)/(G.v2d->cur.xmax-G.v2d->cur.xmin);
813 fac= hor.xmin+fac*(hor.xmax-hor.xmin);
815 dfac= (ipogrid_dx)/(G.v2d->cur.xmax-G.v2d->cur.xmin);
816 dfac= dfac*(hor.xmax-hor.xmin);
818 BIF_ThemeColor(TH_TEXT);
820 while(fac < hor.xmax) {
822 if(curarea->spacetype==SPACE_OOPS);
823 else if(curarea->spacetype==SPACE_SEQ) {
824 fac2= val/(float)G.scene->r.frs_sec;
827 scroll_prstr(fac, 3.0+(float)(hor.ymin), tim+G.scene->r.frs_sec*fac2/100.0, 'h', disptype);
829 else if (curarea->spacetype==SPACE_SOUND) {
830 SpaceSound *ssound= curarea->spacedata.first;
832 if(ssound->flag & SND_DRAWFRAMES) {
834 scroll_prstr(fac, 3.0+(float)(hor.ymin), val, 'h', disptype);
837 fac2= val/(float)G.scene->r.frs_sec;
838 scroll_prstr(fac, 3.0+(float)(hor.ymin), fac2, 'h', disptype);
841 else if (curarea->spacetype==SPACE_TIME) {
842 SpaceTime *stime= curarea->spacedata.first;
844 if(stime->flag & TIME_DRAWFRAMES) {
846 scroll_prstr(fac, 3.0+(float)(hor.ymin), val, 'h', disptype);
849 fac2= val/(float)G.scene->r.frs_sec;
850 scroll_prstr(fac, 3.0+(float)(hor.ymin), fac2, 'h', disptype);
853 else if (curarea->spacetype==SPACE_IPO) {
854 EditIpo *ei= get_active_editipo();
856 if(ei && ei->icu && ei->icu->driver) {
857 int adrcode= ei->icu->driver->adrcode;
859 if(adrcode==OB_ROT_X || adrcode==OB_ROT_Y || adrcode==OB_ROT_Z) {
860 scroll_prstr(fac, 3.0+(float)(hor.ymin), val, 'v', IPO_DISPDEGR);
863 scroll_prstr(fac, 3.0+(float)(hor.ymin), val, 'h', disptype);
866 scroll_prstr(fac, 3.0+(float)(hor.ymin), val, 'h', disptype);
869 scroll_prstr(fac, 3.0+(float)(hor.ymin), val, 'h', disptype);
877 if(G.v2d->scroll & VERT_SCROLL) {
878 BIF_ThemeColorShade(TH_SHADE1, light);
879 glRecti(vert.xmin, vert.ymin, vert.xmax, vert.ymax);
882 fac= (G.v2d->cur.ymin- G.v2d->tot.ymin)/(G.v2d->tot.ymax-G.v2d->tot.ymin);
883 if(fac<0.0) fac= 0.0;
884 vertymin= vert.ymin+fac*(vert.ymax-vert.ymin);
886 fac= (G.v2d->cur.ymax- G.v2d->tot.ymin)/(G.v2d->tot.ymax-G.v2d->tot.ymin);
887 if(fac>1.0) fac= 1.0;
888 vertymax= vert.ymin+fac*(vert.ymax-vert.ymin);
890 if(vertymin > vertymax) vertymin= vertymax;
892 BIF_ThemeColorShade(TH_SHADE1, dark);
893 glRecti(vert.xmin, vertymin, vert.xmax, vertymax);
895 /* decoration black line */
896 BIF_ThemeColorShade(TH_SHADE1, darker);
897 if(G.v2d->scroll & HOR_SCROLL)
898 sdrawline(vert.xmax, vert.ymin+SCROLLH, vert.xmax, vert.ymax);
900 sdrawline(vert.xmax, vert.ymin, vert.xmax, vert.ymax);
902 /* the numbers: convert ipogrid_starty and -dy to scroll coordinates */
903 fac= (ipogrid_starty- G.v2d->cur.ymin)/(G.v2d->cur.ymax-G.v2d->cur.ymin);
904 fac= vert.ymin+SCROLLH+fac*(vert.ymax-vert.ymin-SCROLLH);
906 dfac= (ipogrid_dy)/(G.v2d->cur.ymax-G.v2d->cur.ymin);
907 dfac= dfac*(vert.ymax-vert.ymin-SCROLLH);
909 if(curarea->spacetype==SPACE_OOPS);
910 else if(curarea->spacetype==SPACE_SEQ) {
911 BIF_ThemeColor(TH_TEXT);
914 while(fac < vert.ymax) {
915 scroll_prstr((float)(vert.xmax)-14.0, fac, val, 'v', disptype);
920 else if (curarea->spacetype==SPACE_NLA){
922 else if (curarea->spacetype==SPACE_ACTION){
923 /* No digits on vertical axis in action mode! */
926 BIF_ThemeColor(TH_TEXT);
928 while(fac < vert.ymax) {
929 scroll_prstr((float)(vert.xmax)-14.0, fac, val, 'v', disptype);
937 static void draw_ipobuts(SpaceIpo *sipo)
939 ScrArea *area= sipo->area;
940 View2D *v2d= &sipo->v2d;
948 if(area->winx<IPOBUTX) return;
951 tot= 30+IPOBUTY*sipo->totipo;
952 if(tot<area->winy) sipo->butofs= 0;
955 BIF_ThemeColor(TH_SHADE2);
956 glRects(v2d->mask.xmax, 0, area->winx, area->winy);
959 sdrawline(v2d->mask.xmax, 0, v2d->mask.xmax, area->winy);
961 if(sipo->totipo==0) return;
962 if(sipo->editipo==0) return;
964 sprintf(naam, "ipowin %d", area->win);
965 block= uiNewBlock(&area->uiblocks, naam, UI_EMBOSSN, UI_HELV, area->win);
968 y= area->winy-30+sipo->butofs;
970 if(sipo->blocktype==ID_KE) {
972 if(ob->shapeflag & OB_SHAPE_LOCK) icon= ICON_PIN_HLT; else icon= ICON_PIN_DEHLT;
973 uiDefIconButBitC(block, TOG, OB_SHAPE_LOCK, B_SETKEY, icon,
974 v2d->mask.xmax+18,y,25,20, &ob->shapeflag, 0, 0, 0, 0, "Always show the current Shape for this Object");
978 for(a=0; a<sipo->totipo; a++, ei++, y-=IPOBUTY) {
979 // this button defines visiblity, bit zero of flag (IPO_VISIBLE)
980 but= uiDefButBitS(block, TOG, IPO_VISIBLE, a+1, ei->name, v2d->mask.xmax+18, y, IPOBUTX-15, IPOBUTY-1, &(ei->flag), 0, 0, 0, 0, "");
981 // no hilite, its not visible, but most of all the winmatrix is not correct later on...
982 uiButSetFlag(but, UI_TEXT_LEFT|UI_NO_HILITE);
984 // this fake button defines selection of curves
988 glRects(v2d->mask.xmax+8, y+2, v2d->mask.xmax+15, y+IPOBUTY-2);
989 sel= ei->flag & (IPO_SELECT + IPO_EDIT);
991 uiEmboss((float)(v2d->mask.xmax+8), (float)(y+2), (float)(v2d->mask.xmax+15), (float)(y+IPOBUTY-2), sel);
993 if(ei->icu->driver) {
995 fdrawbox((float)v2d->mask.xmax+11, (float)y+8, (float)v2d->mask.xmax+12.5, (float)y+9.5);
999 if(ei->flag & IPO_ACTIVE) {
1001 fdrawbox(v2d->mask.xmax+7, y+1, v2d->mask.xmax+16, y+IPOBUTY-1);
1007 static void calc_ipoverts(SpaceIpo *sipo)
1009 View2D *v2d= &sipo->v2d;
1015 ei= G.sipo->editipo;
1016 for(a=0; a<sipo->totipo; a++, ei++) {
1017 if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
1019 bezt= ei->icu->bezt;
1020 b= ei->icu->totvert;
1022 ipoco_to_areaco(v2d, bezt->vec[0], bezt->s[0]);
1023 ipoco_to_areaco(v2d, bezt->vec[1], bezt->s[1]);
1024 ipoco_to_areaco(v2d, bezt->vec[2], bezt->s[2]);
1028 else if(ei->icu->bp) {
1030 b= ei->icu->totvert;
1032 ipoco_to_areaco(v2d, bp->vec, bp->s);
1041 static void draw_ipovertices(int sel)
1046 int val, ok, nr, a, b;
1048 if(G.f & G_PICKSEL) return;
1052 ei= G.sipo->editipo;
1053 for(nr=0; nr<G.sipo->totipo; nr++, ei++) {
1054 if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
1056 if(G.sipo->showkey) {
1057 if(sel) BIF_ThemeColor(TH_TEXT_HI);
1058 else BIF_ThemeColor(TH_TEXT);
1059 } else if(ei->flag & IPO_EDIT) {
1060 if(sel) BIF_ThemeColor(TH_VERTEX_SELECT);
1061 else BIF_ThemeColor(TH_VERTEX);
1063 if(sel) BIF_ThemeColor(TH_TEXT_HI);
1064 else BIF_ThemeColor(TH_TEXT);
1066 val= (ei->icu->flag & IPO_SELECT)!=0;
1067 if(sel != val) continue;
1070 /* We can't change the color in the middle of
1071 * GL_POINTS because then Blender will segfault
1072 * on TNT2 / Linux with NVidia's drivers
1073 * (at least up to ver. 4349) */
1075 bglBegin(GL_POINTS);
1077 bezt= ei->icu->bezt;
1078 a= ei->icu->totvert;
1081 if(ei->disptype==IPO_DISPBITS) {
1083 if(ei->flag & IPO_EDIT) {
1084 if( (bezt->f2 & 1) == sel ) ok= 1;
1089 val= bezt->vec[1][1];
1091 v1[0]= bezt->vec[1][0];
1104 if(ei->flag & IPO_EDIT) {
1105 if(ei->icu->ipo==IPO_BEZ) {
1106 if( (bezt->f1 & 1) == sel )
1107 bglVertex3fv(bezt->vec[0]);
1108 if( (bezt->f3 & 1) == sel )
1109 bglVertex3fv(bezt->vec[2]);
1111 if( (bezt->f2 & 1) == sel )
1112 bglVertex3fv(bezt->vec[1]);
1116 bglVertex3fv(bezt->vec[1]);
1130 static void draw_ipohandles(int sel)
1132 extern unsigned int nurbcol[];
1139 if(sel) col= nurbcol+4;
1142 ei= G.sipo->editipo;
1143 for(a=0; a<G.sipo->totipo; a++, ei++) {
1144 if ISPOIN4(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu, disptype!=IPO_DISPBITS) {
1145 if(ei->icu->ipo==IPO_BEZ) {
1146 bezt= ei->icu->bezt;
1147 b= ei->icu->totvert;
1150 if( (bezt->f2 & 1)==sel) {
1152 cpack(col[bezt->h1]);
1154 glBegin(GL_LINE_STRIP);
1155 glVertex2fv(fp); glVertex2fv(fp+3);
1157 cpack(col[bezt->h2]);
1159 glBegin(GL_LINE_STRIP);
1160 glVertex2fv(fp+3); glVertex2fv(fp+6);
1163 else if( (bezt->f1 & 1)==sel) {
1165 cpack(col[bezt->h1]);
1167 glBegin(GL_LINE_STRIP);
1168 glVertex2fv(fp); glVertex2fv(fp+3);
1171 else if( (bezt->f3 & 1)==sel) {
1173 cpack(col[bezt->h2]);
1175 glBegin(GL_LINE_STRIP);
1176 glVertex2fv(fp); glVertex2fv(fp+3);
1189 static void init_pickselcode(void)
1194 static void draw_ipocurves(int sel)
1198 BezTriple *bezt, *prevbezt;
1199 float *fp, fac, data[120], v1[2], v2[2], v3[2], v4[2];
1200 float cycdx=0, cycdy=0, cycxofs, cycyofs;
1201 int a, b, resol, cycount, val, nr;
1204 ei= G.sipo->editipo;
1205 for(nr=0; nr<G.sipo->totipo; nr++, ei++) {
1206 if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
1208 if(G.f & G_PICKSEL) {
1209 glLoadName(pickselcode++);
1213 val= (ei->flag & (IPO_SELECT+IPO_EDIT))!=0;
1219 cycyofs= cycxofs= 0.0;
1225 if(G.sipo->showkey) BIF_ThemeColor(TH_TEXT);
1226 else cpack(ei->col);
1229 if(icu->extrap & IPO_CYCL) {
1230 cycdx= (icu->bezt+icu->totvert-1)->vec[1][0] - icu->bezt->vec[1][0];
1231 cycdy= (icu->bezt+icu->totvert-1)->vec[1][1] - icu->bezt->vec[1][1];
1234 while(icu->bezt->vec[1][0]+cycxofs > G.v2d->cur.xmin) {
1236 if(icu->extrap & IPO_DIR) cycyofs-= cycdy;
1239 bezt= icu->bezt+(icu->totvert-1);
1241 while(bezt->vec[1][0]+fac < G.v2d->cur.xmax) {
1250 if(ei->disptype==IPO_DISPBITS) {
1258 val= bezt->vec[1][1];
1265 glBegin(GL_LINE_STRIP);
1266 if(icu->extrap & IPO_CYCL) ;
1267 else if(a==icu->totvert-1) {
1268 v1[0]= G.v2d->cur.xmin+cycxofs;
1271 v1[0]= bezt->vec[1][0]+cycxofs;
1274 if(a) v1[0]= (bezt+1)->vec[1][0]+cycxofs;
1275 else if(icu->extrap & IPO_CYCL) ;
1276 else v1[0]= G.v2d->cur.xmax+cycxofs;
1290 prevbezt= icu->bezt;
1293 glBegin(GL_LINE_STRIP);
1295 /* extrapolate to left? */
1296 if( (icu->extrap & IPO_CYCL)==0) {
1297 if(prevbezt->vec[1][0] > G.v2d->cur.xmin) {
1298 v1[0]= G.v2d->cur.xmin;
1299 if(icu->extrap==IPO_HORIZ || icu->ipo==IPO_CONST) v1[1]= prevbezt->vec[1][1];
1301 fac= (prevbezt->vec[0][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
1302 if(fac!=0.0) fac= 1.0/fac;
1303 v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[0][1]-prevbezt->vec[1][1]);
1310 v1[0]= prevbezt->vec[1][0]+cycxofs;
1311 v1[1]= prevbezt->vec[1][1]+cycyofs;
1316 if(icu->ipo==IPO_CONST) {
1317 v1[0]= prevbezt->vec[1][0]+cycxofs;
1318 v1[1]= prevbezt->vec[1][1]+cycyofs;
1320 v1[0]= bezt->vec[1][0]+cycxofs;
1321 v1[1]= prevbezt->vec[1][1]+cycyofs;
1324 else if(icu->ipo==IPO_LIN) {
1325 v1[0]= prevbezt->vec[1][0]+cycxofs;
1326 v1[1]= prevbezt->vec[1][1]+cycyofs;
1330 /* resol not depending on horizontal resolution anymore, drivers for example... */
1331 if(icu->driver) resol= 32;
1332 else resol= 3.0*sqrt(bezt->vec[1][0] - prevbezt->vec[1][0]);
1335 v1[0]= prevbezt->vec[1][0]+cycxofs;
1336 v1[1]= prevbezt->vec[1][1]+cycyofs;
1340 if(resol>32) resol= 32;
1342 v1[0]= prevbezt->vec[1][0]+cycxofs;
1343 v1[1]= prevbezt->vec[1][1]+cycyofs;
1344 v2[0]= prevbezt->vec[2][0]+cycxofs;
1345 v2[1]= prevbezt->vec[2][1]+cycyofs;
1347 v3[0]= bezt->vec[0][0]+cycxofs;
1348 v3[1]= bezt->vec[0][1]+cycyofs;
1349 v4[0]= bezt->vec[1][0]+cycxofs;
1350 v4[1]= bezt->vec[1][1]+cycyofs;
1352 correct_bezpart(v1, v2, v3, v4);
1354 forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, 3);
1355 forward_diff_bezier(v1[1], v2[1], v3[1], v4[1], data+1, resol, 3);
1369 v1[0]= prevbezt->vec[1][0]+cycxofs;
1370 v1[1]= prevbezt->vec[1][1]+cycyofs;
1375 /* extrapolate to right? */
1376 if( (icu->extrap & IPO_CYCL)==0) {
1377 if(prevbezt->vec[1][0] < G.v2d->cur.xmax) {
1378 v1[0]= G.v2d->cur.xmax;
1379 if(icu->extrap==IPO_HORIZ || icu->ipo==IPO_CONST) v1[1]= prevbezt->vec[1][1];
1381 fac= (prevbezt->vec[2][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
1382 if(fac!=0.0) fac= 1.0/fac;
1383 v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[2][1]-prevbezt->vec[1][1]);
1393 if(icu->extrap & IPO_DIR) cycyofs+= cycdy;
1396 /* line that indicates the end of a speed curve */
1397 if(G.sipo->blocktype==ID_CU && icu->adrcode==CU_SPEED) {
1400 glColor3ub(0, 0, 0);
1403 glVertex2f(bezt->vec[1][0], 0.0);
1404 glVertex2f(bezt->vec[1][0], bezt->vec[1][1]);
1413 static void draw_cfra(SpaceIpo *sipo)
1415 View2D *v2d= &sipo->v2d;
1419 vec[0]= (G.scene->r.cfra);
1420 vec[0]*= G.scene->r.framelen;
1422 vec[1]= v2d->cur.ymin;
1423 glColor3ub(0x60, 0xc0, 0x40); // no theme, should be global color once...
1426 glBegin(GL_LINE_STRIP);
1428 vec[1]= v2d->cur.ymax;
1432 if(sipo->blocktype==ID_OB) {
1433 ob= (G.scene->basact) ? (G.scene->basact->object) : 0;
1434 if(ob && ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
1437 BIF_ThemeColorShade(TH_HILITE, -30);
1439 glBegin(GL_LINE_STRIP);
1441 vec[1]= G.v2d->cur.ymin;
1450 static void draw_ipokey(SpaceIpo *sipo)
1455 for (ik= sipo->ipokey.first; ik; ik= ik->next) {
1456 if(ik->flag & 1) glColor3ub(0xFF, 0xFF, 0x99);
1457 else glColor3ub(0xAA, 0xAA, 0x55);
1459 glVertex2f(ik->val, G.v2d->cur.ymin);
1460 glVertex2f(ik->val, G.v2d->cur.ymax);
1465 static void draw_key(SpaceIpo *sipo, int visible)
1467 View2D *v2d= &sipo->v2d;
1469 KeyBlock *kb, *act=NULL;
1474 key= (Key *)sipo->from;
1478 if(key->type== KEY_RELATIVE) if(visible==0) return;
1480 for(index=1, kb= key->block.first; kb; kb= kb->next, index++) {
1481 if(kb->type==KEY_LINEAR) setlinestyle(2);
1482 else if(kb->type==KEY_BSPLINE) setlinestyle(4);
1483 else setlinestyle(0);
1485 if(kb==key->refkey) col= 0x22FFFF;
1488 if(ob->shapenr!=index) col-= 0x225500;
1493 glBegin(GL_LINE_STRIP);
1494 glVertex2f(v2d->cur.xmin, kb->pos);
1495 glVertex2f(v2d->cur.xmax, kb->pos);
1501 if(act->type==KEY_LINEAR) setlinestyle(2);
1502 else if(act->type==KEY_BSPLINE) setlinestyle(4);
1503 else setlinestyle(0);
1505 if(act==key->refkey) cpack(0x22FFFF);
1506 else cpack(0xFFFF00);
1508 glBegin(GL_LINE_STRIP);
1509 glVertex2f(v2d->cur.xmin, act->pos);
1510 glVertex2f(v2d->cur.xmax, act->pos);
1517 /* ************************** buttons *********************** */
1520 #define B_SETSPEED 3401
1521 #define B_MUL_IPO 3402
1522 #define B_TRANS_IPO 3403
1523 #define B_IPO_NONE 3404
1524 #define B_IPO_DRIVER 3405
1525 #define B_IPO_REDR 3406
1526 #define B_IPO_DEPCHANGE 3407
1528 static float hspeed= 0;
1530 static void boundbox_ipo_curves(SpaceIpo *si)
1541 for(a=0; a<si->totipo; a++, ei++) {
1544 if(ei->flag & IPO_VISIBLE) {
1546 boundbox_ipocurve(ei->icu);
1548 si->v2d.tot= ei->icu->totrct;
1551 else BLI_union_rctf(&(si->v2d.tot), &(ei->icu->totrct));
1556 if(si->blocktype==ID_KE) {
1557 key= (Key *)si->from;
1558 if(key && key->block.first) {
1559 kb= key->block.first;
1560 if(kb->pos < si->v2d.tot.ymin) si->v2d.tot.ymin= kb->pos;
1561 kb= key->block.last;
1562 if(kb->pos > si->v2d.tot.ymax) si->v2d.tot.ymax= kb->pos;
1565 si->tot= si->v2d.tot;
1569 /* is used for both read and write... */
1570 static void ipo_editvertex_buts(uiBlock *block, SpaceIpo *si, float min, float max)
1576 int a, b, tot, iskey=0;
1578 median[0]= median[1]= median[2]= 0.0;
1581 ei= G.sipo->editipo;
1582 for(a=0; a<G.sipo->totipo; a++, ei++) {
1584 if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
1585 if( (ei->flag & IPO_EDIT) || G.sipo->showkey) {
1588 bezt= ei->icu->bezt;
1589 b= ei->icu->totvert;
1591 // all three selected
1593 VecAddf(median, median, bezt->vec[1]);
1598 VecAddf(median, median, bezt->vec[0]);
1602 VecAddf(median, median, bezt->vec[2]);
1613 /* check for keys */
1615 if(G.sipo->blocktype==ID_KE) {
1616 Key *key= (Key *)G.sipo->from;
1619 if(key==NULL || ob->shapenr==0) return;
1622 kb= BLI_findlink(&key->block, ob->shapenr-1);
1623 median[1]+= kb->pos;
1629 median[0] /= (float)tot;
1630 median[1] /= (float)tot;
1631 median[2] /= (float)tot;
1633 if(block) { // buttons
1635 VECCOPY(si->median, median);
1637 uiBlockBeginAlign(block);
1640 uiDefButF(block, NUM, B_TRANS_IPO, "Key Y:", 10, 80, 300, 19, &(si->median[1]), min, max, 10, 0, "");
1642 uiDefButF(block, NUM, B_TRANS_IPO, "Vertex X:", 10, 100, 150, 19, &(si->median[0]), min, max, 100, 0, "");
1643 uiDefButF(block, NUM, B_TRANS_IPO, "Vertex Y:", 160, 100, 150, 19, &(si->median[1]), min, max, 100, 0, "");
1648 uiDefButF(block, NUM, B_TRANS_IPO, "Median Key Y:", 10, 80, 300, 19, &(si->median[1]), min, max, 10, 0, "");
1650 uiDefButF(block, NUM, B_TRANS_IPO, "Median X:", 10, 100, 150, 19, &(si->median[0]), min, max, 100, 0, "");
1651 uiDefButF(block, NUM, B_TRANS_IPO, "Median Y:", 160, 100, 150, 19, &(si->median[1]), min, max, 100, 0, "");
1655 else if(iskey) { // apply
1656 VecSubf(median, si->median, median);
1658 if(G.sipo->blocktype==ID_KE) {
1659 Key *key= (Key *)G.sipo->from;
1662 if(key==NULL || ob->shapenr==0) return;
1664 kb= BLI_findlink(&key->block, ob->shapenr-1);
1665 kb->pos+= median[1];
1673 VecSubf(median, si->median, median);
1675 ei= G.sipo->editipo;
1676 for(a=0; a<G.sipo->totipo; a++, ei++) {
1678 if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
1679 if( (ei->flag & IPO_EDIT) || G.sipo->showkey) {
1682 bezt= ei->icu->bezt;
1683 b= ei->icu->totvert;
1685 // all three selected
1687 VecAddf(bezt->vec[0], bezt->vec[0], median);
1688 VecAddf(bezt->vec[1], bezt->vec[1], median);
1689 VecAddf(bezt->vec[2], bezt->vec[2], median);
1693 VecAddf(bezt->vec[0], bezt->vec[0], median);
1696 VecAddf(bezt->vec[2], bezt->vec[2], median);
1709 void do_ipobuts(unsigned short event)
1714 if(G.sipo->from==NULL) return;
1718 ei= get_active_editipo();
1720 if(ei->icu->driver) {
1721 if(G.sipo->blocktype==ID_KE || G.sipo->blocktype==ID_AC)
1722 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1724 DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
1727 allqueue(REDRAWIPO, 0);
1728 allqueue(REDRAWVIEW3D, 0);
1731 set_speed_editipo(hspeed);
1735 allqueue(REDRAWIPO, 0);
1738 ipo_editvertex_buts(NULL, G.sipo, 0.0, 0.0);
1739 editipo_changed(G.sipo, 1);
1740 allqueue(REDRAWIPO, 0);
1743 ob->shapeflag &= ~OB_SHAPE_TEMPLOCK;
1744 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1745 allqueue(REDRAWVIEW3D, 0);
1746 allqueue(REDRAWIPO, 0);
1747 allqueue(REDRAWBUTSEDIT, 0);
1750 ei= get_active_editipo();
1753 ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, ei->adrcode);
1754 ei->flag |= IPO_SELECT;
1755 ei->icu->flag= ei->flag;
1757 if(ei->icu->driver) {
1758 MEM_freeN(ei->icu->driver);
1759 ei->icu->driver= NULL;
1760 if(ei->icu->bezt==NULL) {
1761 BLI_remlink( &(G.sipo->ipo->curve), ei->icu);
1762 free_ipo_curve(ei->icu);
1767 ei->icu->driver= MEM_callocN(sizeof(IpoDriver), "ipo driver");
1768 ei->icu->driver->blocktype= ID_OB;
1769 ei->icu->driver->adrcode= OB_LOC_X;
1772 allqueue(REDRAWVIEW3D, 0);
1773 allqueue(REDRAWIPO, 0);
1774 allqueue(REDRAWBUTSEDIT, 0);
1775 DAG_scene_sort(G.scene);
1777 BIF_undo_push("Add/Remove Ipo driver");
1780 case B_IPO_DEPCHANGE:
1781 ei= get_active_editipo();
1783 if(ei->icu->driver) {
1784 IpoDriver *driver= ei->icu->driver;
1787 if(ob==driver->ob) {
1788 error("Cannot assign a Driver to own Object");
1792 /* check if type is still OK */
1793 if(driver->ob->type==OB_ARMATURE && driver->blocktype==ID_AR);
1794 else driver->blocktype= ID_OB;
1797 DAG_scene_sort(G.scene);
1799 if(G.sipo->blocktype==ID_KE || G.sipo->blocktype==ID_AC)
1800 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1802 DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
1805 allqueue(REDRAWVIEW3D, 0);
1806 allqueue(REDRAWIPO, 0);
1807 allqueue(REDRAWBUTSEDIT, 0);
1812 static char *ipodriver_modeselect_pup(Object *ob)
1814 static char string[265];
1816 char formatstring[64];
1818 strcpy(string, "Driver type: %t");
1820 strcpy(formatstring, "|%s %%x%d %%i%d");
1823 sprintf(tmpstr,formatstring,"Object",ID_OB, ICON_OBJECT);
1824 strcat(string,tmpstr);
1826 if(ob && ob->type==OB_ARMATURE) {
1827 sprintf(tmpstr,formatstring,"Pose",ID_AR, ICON_POSE_DEHLT);
1828 strcat(string,tmpstr);
1834 static char *ipodriver_channelselect_pup(void)
1836 static char string[1024];
1839 strcpy(string, "Driver channel: %t");
1840 tmp= string+strlen(string);
1842 tmp+= sprintf(tmp, "|Loc X %%x%d", OB_LOC_X);
1843 tmp+= sprintf(tmp, "|Loc Y %%x%d", OB_LOC_Y);
1844 tmp+= sprintf(tmp, "|Loc Z %%x%d", OB_LOC_Z);
1845 tmp+= sprintf(tmp, "|Rot X %%x%d", OB_ROT_X);
1846 tmp+= sprintf(tmp, "|Rot Y %%x%d", OB_ROT_Y);
1847 tmp+= sprintf(tmp, "|Rot Z %%x%d", OB_ROT_Z);
1848 tmp+= sprintf(tmp, "|Size X %%x%d", OB_SIZE_X);
1849 tmp+= sprintf(tmp, "|Size Y %%x%d", OB_SIZE_Y);
1850 tmp+= sprintf(tmp, "|Size Z %%x%d", OB_SIZE_Z);
1855 static void ipo_panel_properties(short cntrl) // IPO_HANDLER_PROPERTIES
1857 extern int totipo_curve; // editipo.c
1862 block= uiNewBlock(&curarea->uiblocks, "ipo_panel_properties", UI_EMBOSS, UI_HELV, curarea->win);
1863 uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
1864 uiSetPanelHandler(IPO_HANDLER_PROPERTIES); // for close and esc
1865 if(uiNewPanel(curarea, block, "Transform Properties", "Ipo", 10, 230, 318, 204)==0) return;
1867 /* this is new panel height, newpanel doesnt force new size on existing panels */
1868 uiNewPanelHeight(block, 204);
1870 /* driver buttons first */
1871 ei= get_active_editipo();
1874 sprintf(name, "Driven Channel: %s", ei->name);
1875 uiDefBut(block, LABEL, 0, name, 10, 265, 200, 19, NULL, 1.0, 0.0, 0, 0, "");
1877 if(ei->icu && ei->icu->driver) {
1878 IpoDriver *driver= ei->icu->driver;
1880 uiDefBut(block, BUT, B_IPO_DRIVER, "Remove", 210,265,100,19, NULL, 0.0f, 0.0f, 0, 0, "Remove Driver for this Ipo Channel");
1882 uiBlockBeginAlign(block);
1883 uiDefIDPoinBut(block, test_obpoin_but, B_IPO_DEPCHANGE, "OB:", 10, 240, 150, 20, &(driver->ob), "Driver Object");
1885 int icon=ICON_OBJECT;
1887 if(driver->ob->type==OB_ARMATURE && driver->blocktype==ID_AR) {
1888 icon = ICON_POSE_DEHLT;
1889 uiDefBut(block, TEX, B_IPO_REDR, "BO:", 10,220,150,20, driver->name, 0, 31, 0, 0, "Bone name");
1891 else driver->blocktype= ID_OB; /* safety when switching object button */
1893 uiBlockBeginAlign(block);
1894 uiDefIconTextButS(block, MENU, B_IPO_DEPCHANGE, icon,
1895 ipodriver_modeselect_pup(driver->ob), 165,240,145,20, &(driver->blocktype), 0, 0, 0, 0, "Driver type");
1897 uiDefButS(block, MENU, B_IPO_REDR,
1898 ipodriver_channelselect_pup(), 165,220,145,20, &(driver->adrcode), 0, 0, 0, 0, "Driver channel");
1900 uiBlockEndAlign(block);
1903 uiDefBut(block, BUT, B_IPO_DRIVER, "Add Driver", 210,265,100,19, NULL, 0.0f, 0.0f, 0, 0, "Create a Driver for this Ipo Channel");
1907 uiDefBut(block, LABEL, 0, " ", 10, 265, 150, 19, NULL, 1.0, 0.0, 0, 0, "");
1909 boundbox_ipo_curves(G.sipo); // should not be needed... transform/draw calls should update
1911 /* note ranges for buttons below are idiot... we need 2 ranges, one for sliding scale, one for real clip */
1912 if(G.sipo->ipo && G.sipo->ipo->curve.first && totipo_curve) {
1913 extern int totipo_vertsel; // editipo.c
1914 uiDefBut(block, LABEL, 0, "Visible curves", 10, 200, 150, 19, NULL, 1.0, 0.0, 0, 0, "");
1916 uiBlockBeginAlign(block);
1917 uiDefButF(block, NUM, B_MUL_IPO, "Xmin:", 10, 180, 150, 19, &G.sipo->tot.xmin, G.sipo->tot.xmin-1000.0, MAXFRAMEF, 100, 0, "");
1918 uiDefButF(block, NUM, B_MUL_IPO, "Xmax:", 160, 180, 150, 19, &G.sipo->tot.xmax, G.sipo->tot.ymin-1000.0, MAXFRAMEF, 100, 0, "");
1920 uiDefButF(block, NUM, B_MUL_IPO, "Ymin:", 10, 160, 150, 19, &G.sipo->tot.ymin, G.sipo->tot.ymin-1000.0, 5000.0, 100, 0, "");
1921 uiDefButF(block, NUM, B_MUL_IPO, "Ymax:", 160, 160, 150, 19, &G.sipo->tot.ymax, G.sipo->tot.ymin-1000.0, 5000.0, 100, 0, "");
1924 if(totipo_vertsel) {
1925 uiBlockBeginAlign(block);
1926 uiDefButF(block, NUM, B_IPO_NONE, "Speed:", 10,130,150,19, &hspeed, 0.0, 180.0, 1, 0, "");
1927 uiDefBut(block, BUT, B_SETSPEED,"SET", 160,130,50,19, 0, 0, 0, 0, 0, "");
1931 /* this one also does keypositions */
1932 if(G.sipo->ipo) ipo_editvertex_buts(block, G.sipo, -10000, MAXFRAMEF);
1935 static void ipo_blockhandlers(ScrArea *sa)
1937 SpaceIpo *sipo= sa->spacedata.first;
1940 /* warning; blocks need to be freed each time, handlers dont remove (for ipo moved to drawipospace) */
1942 for(a=0; a<SPACE_MAXHANDLER; a+=2) {
1943 switch(sipo->blockhandler[a]) {
1945 case IPO_HANDLER_PROPERTIES:
1946 ipo_panel_properties(sipo->blockhandler[a+1]);
1950 /* clear action value for event */
1951 sipo->blockhandler[a+1]= 0;
1953 uiDrawBlocksPanels(sa, 0);
1958 void drawipospace(ScrArea *sa, void *spacedata)
1960 SpaceIpo *sipo= sa->spacedata.first;
1961 View2D *v2d= &sipo->v2d;
1964 int ofsx, ofsy, a, disptype;
1966 bwin_clear_viewmat(sa->win); /* clear buttons view */
1969 uiFreeBlocksWin(&sa->uiblocks, sa->win); /* for panel handler to work */
1971 v2d->hor.xmax+=IPOBUTX;
1972 calc_scrollrcts(sa, G.v2d, sa->winx, sa->winy);
1974 BIF_GetThemeColor3fv(TH_BACK, col);
1975 glClearColor(col[0], col[1], col[2], 0.0);
1978 glClearColor(col[0]+0.05,col[1],col[2], 0.0); // litepink
1980 glClearColor(col[0],col[1],col[2], 0.0);
1982 glClear(GL_COLOR_BUFFER_BIT);
1984 if(sa->winx>SCROLLB+10 && sa->winy>SCROLLH+10) {
1986 ofsx= sa->winrct.xmin; // ivm mywin
1987 ofsy= sa->winrct.ymin;
1988 glViewport(ofsx+v2d->mask.xmin, ofsy+v2d->mask.ymin, ( ofsx+v2d->mask.xmax-1)-(ofsx+v2d->mask.xmin)+1, ( ofsy+v2d->mask.ymax-1)-( ofsy+v2d->mask.ymin)+1);
1989 glScissor(ofsx+v2d->mask.xmin, ofsy+v2d->mask.ymin, ( ofsx+v2d->mask.xmax-1)-(ofsx+v2d->mask.xmin)+1, ( ofsy+v2d->mask.ymax-1)-( ofsy+v2d->mask.ymin)+1);
1993 test_editipo(); /* test if current editipo is correct, make_editipo sets v2d->cur */
1995 myortho2(v2d->cur.xmin, v2d->cur.xmax, v2d->cur.ymin, v2d->cur.ymax);
1999 /* correct scale for degrees? */
2002 for(a=0; a<sipo->totipo; a++, ei++) {
2003 if(ei->flag & IPO_VISIBLE) {
2004 if(disptype== -1) disptype= ei->disptype;
2005 else if(disptype!=ei->disptype) disptype= 0;
2012 calc_ipoverts(sipo);
2018 if(sipo->ipokey.first==0) make_ipokey();
2022 if(sipo->blocktype==ID_KE) {
2024 draw_key(sipo, ei->flag & IPO_VISIBLE);
2030 draw_ipovertices(0);
2035 draw_ipovertices(1);
2037 /* restore viewport */
2040 if(sa->winx>SCROLLB+10 && sa->winy>SCROLLH+10) {
2042 /* ortho at pixel level sa */
2043 myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
2046 drawscroll(disptype);
2047 draw_solution(sipo);
2058 myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
2059 draw_area_emboss(sa);
2061 /* it is important to end a view in a transform compatible with buttons */
2062 bwin_scalematrix(sa->win, sipo->blockscale, sipo->blockscale, sipo->blockscale);
2063 /* only draw panels when relevant */
2064 if(sipo->editipo) ipo_blockhandlers(sa);
2066 sa->win_swap= WIN_BACK_OK;
2069 void scroll_ipobuts()
2074 tot= 30+IPOBUTY*G.sipo->totipo;
2075 if(tot<curarea->winy) return;
2077 getmouseco_areawin(mval);
2080 while(get_mbut()&M_MOUSE) {
2081 getmouseco_areawin(mval);
2083 G.sipo->butofs+= (mval[1]-yo);
2084 if(G.sipo->butofs<0) G.sipo->butofs= 0;
2085 else if(G.sipo->butofs+curarea->winy>tot) G.sipo->butofs= tot-curarea->winy;
2087 scrarea_do_windraw(curarea);
2088 screen_swapbuffers();
2092 else BIF_wait_for_statechange();
2096 /* total mess function, especially with mousewheel, needs cleanup badly (ton) */
2097 int view2dzoom(unsigned short event)
2099 float fac, dx, dy, wtemp;
2100 short mval[2], mvalo[2];
2102 areawinset(curarea->win); /* from buttons */
2103 curarea->head_swap= 0;
2104 getmouseco_areawin(mvalo);
2108 while( (get_mbut()&(L_MOUSE|M_MOUSE)) || (event==WHEELUPMOUSE) || (event==WHEELDOWNMOUSE) ) {
2110 /* regular mousewheel: zoom regular
2111 * alt-shift mousewheel: zoom y only
2112 * alt-ctrl mousewheel: zoom x only
2114 if (event==WHEELUPMOUSE) {
2115 if(U.uiflag & USER_WHEELZOOMDIR)
2119 if(curarea->spacetype!=SPACE_BUTS) wtemp*= 3;
2121 dx= (float)(wtemp*(G.v2d->cur.xmax-G.v2d->cur.xmin));
2122 dy= (float)(wtemp*(G.v2d->cur.ymax-G.v2d->cur.ymin));
2124 switch (G.qual & (LR_CTRLKEY|LR_SHIFTKEY|LR_ALTKEY)) {
2127 case (LR_SHIFTKEY|LR_ALTKEY):
2130 case (LR_CTRLKEY|LR_ALTKEY):
2134 if(curarea->spacetype==SPACE_BUTS); // exception
2139 else if (event==WHEELDOWNMOUSE) {
2140 if(U.uiflag & USER_WHEELZOOMDIR)
2144 if(curarea->spacetype!=SPACE_BUTS) wtemp*= 3;
2146 dx= (float)(wtemp*(G.v2d->cur.xmax-G.v2d->cur.xmin));
2147 dy= (float)(wtemp*(G.v2d->cur.ymax-G.v2d->cur.ymin));
2149 switch (G.qual & (LR_CTRLKEY|LR_SHIFTKEY|LR_ALTKEY)) {
2152 case (LR_SHIFTKEY|LR_ALTKEY):
2155 case (LR_CTRLKEY|LR_ALTKEY):
2159 if(curarea->spacetype==SPACE_BUTS);
2165 getmouseco_areawin(mval);
2166 if(U.viewzoom==USER_ZOOM_SCALE) {
2169 dist = (G.v2d->mask.xmax - G.v2d->mask.xmin)/2.0;
2170 dx= 1.0-(fabs(mvalo[0]-dist)+2.0)/(fabs(mval[0]-dist)+2.0);
2171 dx*= 0.5*(G.v2d->cur.xmax-G.v2d->cur.xmin);
2173 dist = (G.v2d->mask.ymax - G.v2d->mask.ymin)/2.0;
2174 dy= 1.0-(fabs(mvalo[1]-dist)+2.0)/(fabs(mval[1]-dist)+2.0);
2175 dy*= 0.5*(G.v2d->cur.ymax-G.v2d->cur.ymin);
2179 fac= 0.01*(mval[0]-mvalo[0]);
2180 dx= fac*(G.v2d->cur.xmax-G.v2d->cur.xmin);
2181 fac= 0.01*(mval[1]-mvalo[1]);
2182 dy= fac*(G.v2d->cur.ymax-G.v2d->cur.ymin);
2184 if(U.viewzoom==USER_ZOOM_CONT) {
2190 if(ELEM(event, WHEELUPMOUSE, WHEELDOWNMOUSE) || mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
2192 if(U.viewzoom!=USER_ZOOM_CONT) {
2197 if( ELEM(curarea->spacetype, SPACE_NLA, SPACE_ACTION) ) {
2198 if(mvalo[0] < G.v2d->mask.xmin) {
2199 G.v2d->cur.ymin+= dy;
2200 G.v2d->cur.ymax-= dy;
2203 G.v2d->cur.xmin+= dx;
2204 G.v2d->cur.xmax-= dx;
2207 else if (ELEM3(curarea->spacetype, SPACE_SEQ, SPACE_SOUND, SPACE_TIME)) {
2208 G.v2d->cur.xmin+= dx;
2209 G.v2d->cur.xmax-= dx;
2212 G.v2d->cur.xmin+= dx;
2213 G.v2d->cur.xmax-= dx;
2214 G.v2d->cur.ymin+= dy;
2215 G.v2d->cur.ymax-= dy;
2218 test_view2d(G.v2d, curarea->winx, curarea->winy); /* cur min max rects */
2219 view2d_do_locks(curarea, V2D_LOCK_COPY|V2D_LOCK_REDRAW);
2221 scrarea_do_windraw(curarea);
2222 screen_swapbuffers();
2224 else BIF_wait_for_statechange();
2225 /* return if we were using the mousewheel
2227 if ( (event==WHEELUPMOUSE) || (event==WHEELDOWNMOUSE) ) return 1;
2232 void center_currframe(void)
2234 /* place the current frame in the
2235 * center of the 2D window.
2239 width = G.v2d->cur.xmax - G.v2d->cur.xmin;
2240 G.v2d->cur.xmin = CFRA - 0.5*(width);
2241 G.v2d->cur.xmax = CFRA + 0.5*(width);
2243 test_view2d(G.v2d, curarea->winx, curarea->winy);
2244 view2d_do_locks(curarea, V2D_LOCK_COPY);
2246 scrarea_queue_winredraw(curarea);
2249 /* total mess function, especially with mousewheel, needs cleanup badly (ton) */
2250 int view2dmove(unsigned short event)
2252 /* return 1 when something was done */
2253 float facx=0.0, facy=0.0, dx, dy, left=1.0, right=1.0;
2254 short mval[2], mvalo[2], leftret=1, mousebut;
2257 scrarea_do_windraw(curarea);
2258 curarea->head_swap= 0;
2260 /* try to do some zooming if the
2261 * middlemouse and ctrl are pressed
2262 * or if the mousewheel is being used.
2263 * Return if zooming was done.
2266 /* check for left mouse / right mouse button select */
2267 if (U.flag & USER_LMOUSESELECT) mousebut = R_MOUSE;
2268 else mousebut = L_MOUSE;
2270 if ( (G.qual & LR_CTRLKEY) || (event==WHEELUPMOUSE) || (event==WHEELDOWNMOUSE) ) {
2271 /* patch for oops & buttonswin, standard scroll no zoom */
2272 if(curarea->spacetype==SPACE_OOPS) {
2273 SpaceOops *soops= curarea->spacedata.first;
2274 if(soops->type==SO_OUTLINER);
2275 else if (view2dzoom(event)) {
2276 curarea->head_swap= 0;
2280 else if(curarea->spacetype==SPACE_BUTS && (G.qual & LR_CTRLKEY)==0);
2281 else if (view2dzoom(event)) {
2282 curarea->head_swap= 0;
2287 /* test where mouse is */
2288 getmouseco_areawin(mvalo);
2290 if ELEM7(curarea->spacetype, SPACE_IPO, SPACE_SEQ, SPACE_OOPS, SPACE_SOUND, SPACE_ACTION, SPACE_NLA, SPACE_TIME)
2293 if( BLI_in_rcti(&G.v2d->mask, (int)mvalo[0], (int)mvalo[1]) ) {
2294 facx= (G.v2d->cur.xmax-G.v2d->cur.xmin)/(float)(G.v2d->mask.xmax-G.v2d->mask.xmin);
2295 facy= (G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)(G.v2d->mask.ymax-G.v2d->mask.ymin);
2297 /* stoopid exception to allow scroll in lefthand side */
2298 else if(curarea->spacetype==SPACE_ACTION && BLI_in_rcti(&G.v2d->mask, ACTWIDTH+(int)mvalo[0], (int)mvalo[1]) ) {
2300 facy= (G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)(G.v2d->mask.ymax-G.v2d->mask.ymin);
2302 else if(curarea->spacetype==SPACE_NLA && BLI_in_rcti(&G.v2d->mask, NLAWIDTH+(int)mvalo[0], (int)mvalo[1]) ) {
2304 facy= (G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)(G.v2d->mask.ymax-G.v2d->mask.ymin);
2306 else if(IN_2D_VERT_SCROLL((int)mvalo)) {
2307 facy= -(G.v2d->tot.ymax-G.v2d->tot.ymin)/(float)(G.v2d->mask.ymax-G.v2d->mask.ymin);
2308 if(get_mbut() & mousebut) {
2309 /* which part of scrollbar should move? */
2310 if(mvalo[1]< (vertymin+vertymax)/2 ) right= 0.0;
2315 else if(IN_2D_HORIZ_SCROLL((int)mvalo)) {
2316 facx= -(G.v2d->tot.xmax-G.v2d->tot.xmin)/(float)(G.v2d->mask.xmax-G.v2d->mask.xmin);
2317 if(get_mbut() & mousebut) {
2318 /* which part of scrollbar should move? */
2319 if(mvalo[0]< (horxmin+horxmax)/2 ) right= 0.0;
2326 facx= (G.v2d->cur.xmax-G.v2d->cur.xmin)/(float)(curarea->winx);
2327 facy= (G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)(curarea->winy);
2330 /* no x move in outliner */
2331 if(curarea->spacetype==SPACE_OOPS && G.v2d->scroll) facx= 0.0;
2333 /* no y move in audio & time */
2334 if ELEM(curarea->spacetype, SPACE_SOUND, SPACE_TIME) facy= 0.0;
2336 if(get_mbut() & mousebut && leftret) return 0;
2337 if(facx==0.0 && facy==0.0) return 1;
2339 while( (get_mbut()&(L_MOUSE|M_MOUSE)) ||
2340 (event==WHEELUPMOUSE) ||
2341 (event==WHEELDOWNMOUSE) ) {
2343 /* If the mousewheel is used with shift key
2344 * the scroll up and down. If the mousewheel
2345 * is used with the ctrl key then scroll left
2348 if (event==WHEELUPMOUSE || event==WHEELDOWNMOUSE) {
2349 if(event==WHEELDOWNMOUSE) {
2350 facx= -facx; facy= -facy;
2352 switch (G.qual & (LR_CTRLKEY|LR_SHIFTKEY|LR_ALTKEY)) {
2362 if(curarea->spacetype==SPACE_OOPS) {
2366 else if(curarea->spacetype==SPACE_BUTS) {
2367 if(G.buts->align==BUT_HORIZONTAL) {
2368 dx= facx*30; dy= 0.0;
2370 dx= 0.0; dy= facy*30;
2376 mval[0]= mvalo[0]+1; // force redraw below
2377 mval[1]= mvalo[1]+1;
2380 getmouseco_areawin(mval);
2381 dx= facx*(mvalo[0]-mval[0]);
2382 dy= facy*(mvalo[1]-mval[1]);
2385 if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
2387 G.v2d->cur.xmin+= left*dx;
2388 G.v2d->cur.xmax+= right*dx;
2389 G.v2d->cur.ymin+= left*dy;
2390 G.v2d->cur.ymax+= right*dy;
2392 test_view2d(G.v2d, curarea->winx, curarea->winy);
2393 view2d_do_locks(curarea, V2D_LOCK_COPY|V2D_LOCK_REDRAW);
2395 scrarea_do_windraw(curarea);
2396 screen_swapbuffers();
2402 else BIF_wait_for_statechange();
2403 /* return if we were using the mousewheel
2405 if ( (event==WHEELUPMOUSE) || (event==WHEELDOWNMOUSE) ) return 1;
2408 curarea->head_swap= 0;
2412 void view2dborder(void)
2417 EditIpo *select_proj_ipo(rctf *rectf, int event)
2420 float xmin, ymin, xmax, ymax;
2421 /* this was IGLuint, but it's a useless typedef... */
2422 GLuint buffer[MAXPICKBUF];
2431 getmouseco_areawin(mval);
2433 mval[0]-= 6; mval[1]-= 6;
2434 areamouseco_to_ipoco(G.v2d, mval, &xmin, &ymin);
2435 mval[0]+= 12; mval[1]+= 12;
2436 areamouseco_to_ipoco(G.v2d, mval, &xmax, &ymax);
2438 myortho2(xmin, xmax, ymin, ymax);
2440 else myortho2(rectf->xmin, rectf->xmax, rectf->ymin, rectf->ymax);
2442 glSelectBuffer( MAXPICKBUF, buffer);
2443 glRenderMode(GL_SELECT);
2444 glInitNames(); /* whatfor? but otherwise it does not work */
2447 /* get rid of buttons view */
2451 init_pickselcode(); /* drawipo.c */
2454 /* restore buttons view */
2459 hits= glRenderMode(GL_RENDER);
2460 glPopName(); /* see above (pushname) */
2461 if(hits<1) return 0;
2464 ei= G.sipo->editipo;
2465 for(a=0; a<G.sipo->totipo; a++, ei++) {
2466 if ISPOIN(ei, icu, flag & IPO_VISIBLE) {
2468 for(b=0; b<hits; b++) {
2469 /* conversion for glSelect */
2470 if(code == buffer[ (4 * b) + 3] ) {
2471 if(event==LEFTMOUSE) ei->flag |= IPO_SELECT;
2472 else ei->flag &= ~IPO_SELECT;
2473 ei->icu->flag= ei->flag;
2478 /* also conversion for glSelect */
2479 if(code==buffer[ 3 ]) return ei;