Stage two of the giant animation recode project; Ipo/Action/NLA cleanup
[blender.git] / source / blender / src / drawipo.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
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
12  * about this.
13  *
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.
18  *
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.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <stdio.h>
34 #include <math.h>
35 #include <string.h>
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #ifndef _WIN32
42 #include <unistd.h>
43 #else
44 #include <io.h>
45 #endif   
46
47 #include "BMF_Api.h"
48 #include "MEM_guardedalloc.h"
49
50 #include "BLI_blenlib.h"
51 #include "BLI_arithb.h"
52
53 #include "DNA_curve_types.h"
54 #include "DNA_ipo_types.h"
55 #include "DNA_key_types.h"
56 #include "DNA_object_types.h"
57 #include "DNA_scene_types.h"
58 #include "DNA_screen_types.h"
59 #include "DNA_space_types.h"
60 #include "DNA_sequence_types.h"
61 #include "DNA_userdef_types.h"
62
63 #include "BKE_curve.h"
64 #include "BKE_depsgraph.h"
65 #include "BKE_global.h"
66 #include "BKE_ipo.h"
67 #include "BKE_key.h"
68 #include "BKE_utildefines.h"
69
70 #include "BIF_gl.h"
71 #include "BIF_resources.h"
72 #include "BIF_screen.h"
73 #include "BIF_interface.h"
74 #include "BIF_mywindow.h"
75 #include "BIF_space.h"
76 #include "BIF_toolbox.h"
77 #include "BIF_glutil.h"
78
79 #include "BSE_drawipo.h"
80 #include "BSE_view.h"
81 #include "BSE_editipo.h"
82 #include "BSE_editipo_types.h"
83 #include "BSE_editnla_types.h"
84
85 #include "mydevice.h"
86 #include "blendef.h"
87 #include "butspace.h"   // shouldnt be...
88
89 /* local define... also used in editipo ... */
90 #define ISPOIN(a, b, c)                       ( (a->b) && (a->c) )  
91 #define ISPOIN3(a, b, c, d)           ( (a->b) && (a->c) && (a->d) )
92 #define ISPOIN4(a, b, c, d, e)        ( (a->b) && (a->c) && (a->d) && (a->e) )   
93
94 #define IPOBUTX 65
95                 /* minimum pixels per gridstep */
96 #define IPOSTEP 35
97
98 static float ipogrid_dx, ipogrid_dy, ipogrid_startx, ipogrid_starty;
99 static int ipomachtx, ipomachty;
100
101 static int vertymin, vertymax, horxmin, horxmax;        /* globals to test LEFTMOUSE for scrollbar */
102
103 extern short ACTWIDTH;          /* this is ugly! */
104
105 static void scroll_prstr(float x, float y, float val, char dir, int disptype)
106 {
107         int len, macht;
108         char str[32];
109         
110         if(dir=='v') {
111                 macht= ipomachty;
112                 if ELEM(disptype, IPO_DISPDEGR, IPO_DISPTIME) {
113                         macht+=1;
114                         val *= 10;
115                 }
116         }
117         else macht= ipomachtx;
118         
119         if (macht<=0) sprintf(str, "%.*f", 1-macht, val);
120         else sprintf(str, "%d", (int)floor(val + 0.375));
121         
122         len= strlen(str);
123         if(dir=='h') x-= 4*len;
124         
125         if(dir=='v' && disptype==IPO_DISPDEGR) {
126                 str[len]= 186; /* Degree symbol */
127                 str[len+1]= 0;
128         }
129         
130         glRasterPos2f(x,  y);
131         BMF_DrawString(G.fonts, str);
132 }
133
134 static void step_to_grid(float *step, int *macht)
135 {
136         float loga, rem;
137         
138         /* try to write step as a power of 10 */
139         
140         loga= log10(*step);
141         *macht= (int)(loga);
142
143         rem= loga- *macht;
144         rem= pow(10.0, rem);
145         
146         if(loga<0.0) {
147                 if(rem < 0.2) rem= 0.2;
148                 else if(rem < 0.5) rem= 0.5;
149                 else rem= 1.0;
150
151                 *step= rem*pow(10.0, (float)*macht);
152                 
153                 // partial of a frame have no meaning
154                 if(curarea->spacetype==SPACE_TIME) {
155                         SpaceTime *stime= curarea->spacedata.first;
156                         if(stime->flag & TIME_DRAWFRAMES) {
157                                 rem = 1.0;
158                                 *step = 1.0;
159                         }
160                 }
161                 
162                 if(rem==1.0) (*macht)++;        // prevents printing 1.0 2.0 3.0 etc
163         }
164         else {
165                 if(rem < 2.0) rem= 2.0;
166                 else if(rem < 5.0) rem= 5.0;
167                 else rem= 10.0;
168                 
169                 *step= rem*pow(10.0, (float)*macht);
170                 
171                 (*macht)++;
172                 if(rem==10.0) (*macht)++;       // prevents printing 1.0 2.0 3.0 etc
173         }
174 }
175
176 void calc_ipogrid()
177 {
178         float space, pixels, secondiv=1.0;
179         int secondgrid= 0;
180         /* rule: gridstep is minimal IPOSTEP pixels */
181         /* how large is IPOSTEP pixels? */
182         
183         if(G.v2d==0) return;
184         
185         /* detect of we have seconds or frames, should become argument */
186         if(curarea->spacetype==SPACE_TIME) {
187                 SpaceTime *stime= curarea->spacedata.first;
188                 if(!(stime->flag & TIME_DRAWFRAMES)) {
189                         secondgrid= 1;
190                         secondiv= 0.01 * (float)G.scene->r.frs_sec;
191                 }
192         }
193         
194         space= G.v2d->cur.xmax - G.v2d->cur.xmin;
195         pixels= G.v2d->mask.xmax-G.v2d->mask.xmin;
196         
197         ipogrid_dx= IPOSTEP*space/(secondiv*pixels);
198         step_to_grid(&ipogrid_dx, &ipomachtx);
199         ipogrid_dx*= secondiv;
200         
201         if ELEM3(curarea->spacetype, SPACE_SEQ, SPACE_SOUND, SPACE_TIME) {
202                 if(ipogrid_dx < 0.1) ipogrid_dx= 0.1;
203                 ipomachtx-= 2;
204                 if(ipomachtx<-2) ipomachtx= -2;
205         }
206         
207         space= (G.v2d->cur.ymax - G.v2d->cur.ymin);
208         pixels= curarea->winy;
209         ipogrid_dy= IPOSTEP*space/pixels;
210         step_to_grid(&ipogrid_dy, &ipomachty);
211         
212         if ELEM3(curarea->spacetype, SPACE_SEQ, SPACE_SOUND, SPACE_TIME) {
213                 if(ipogrid_dy < 1.0) ipogrid_dy= 1.0;
214                 if(ipomachty<1) ipomachty= 1;
215         }
216         
217         ipogrid_startx= secondiv*(G.v2d->cur.xmin/secondiv - fmod(G.v2d->cur.xmin/secondiv, ipogrid_dx/secondiv));
218         if(G.v2d->cur.xmin<0.0) ipogrid_startx-= ipogrid_dx;
219         
220         ipogrid_starty= (G.v2d->cur.ymin-fmod(G.v2d->cur.ymin, ipogrid_dy));
221         if(G.v2d->cur.ymin<0.0) ipogrid_starty-= ipogrid_dy;
222         
223 }
224
225 void draw_ipogrid(void)
226 {
227         float vec1[2], vec2[2];
228         int a, step;
229         
230         vec1[0]= vec2[0]= ipogrid_startx;
231         vec1[1]= ipogrid_starty;
232         vec2[1]= G.v2d->cur.ymax;
233         
234         step= (G.v2d->mask.xmax-G.v2d->mask.xmin+1)/IPOSTEP;
235         
236         BIF_ThemeColor(TH_GRID);
237         
238         for(a=0; a<step; a++) {
239                 glBegin(GL_LINE_STRIP);
240                 glVertex2fv(vec1); glVertex2fv(vec2);
241                 glEnd();
242                 vec2[0]= vec1[0]+= ipogrid_dx;
243         }
244         
245         vec2[0]= vec1[0]-= 0.5*ipogrid_dx;
246         
247         BIF_ThemeColorShade(TH_GRID, 16);
248         
249         step++;
250         for(a=0; a<=step; a++) {
251                 glBegin(GL_LINE_STRIP);
252                 glVertex2fv(vec1); glVertex2fv(vec2);
253                 glEnd();
254                 vec2[0]= vec1[0]-= ipogrid_dx;
255         }
256         
257         if ELEM4(curarea->spacetype, SPACE_SOUND, SPACE_ACTION, SPACE_NLA, SPACE_TIME);
258         else {
259                 vec1[0]= ipogrid_startx;
260                 vec1[1]= vec2[1]= ipogrid_starty;
261                 vec2[0]= G.v2d->cur.xmax;
262                 
263                 step= (curarea->winy+1)/IPOSTEP;
264                 
265                 BIF_ThemeColor(TH_GRID);
266                 for(a=0; a<=step; a++) {
267                         glBegin(GL_LINE_STRIP);
268                         glVertex2fv(vec1); glVertex2fv(vec2);
269                         glEnd();
270                         vec2[1]= vec1[1]+= ipogrid_dy;
271                 }
272                 vec2[1]= vec1[1]-= 0.5*ipogrid_dy;
273                 step++;
274                 
275                 if(curarea->spacetype==SPACE_IPO) {
276                         BIF_ThemeColorShade(TH_GRID, 16);
277                         for(a=0; a<step; a++) {
278                                 glBegin(GL_LINE_STRIP);
279                                 glVertex2fv(vec1); glVertex2fv(vec2);
280                                 glEnd();
281                                 vec2[1]= vec1[1]-= ipogrid_dy;
282                         }
283                 }
284         }
285         
286         BIF_ThemeColorShade(TH_GRID, -50);
287         
288         if (curarea->spacetype!=SPACE_ACTION && curarea->spacetype!=SPACE_NLA)
289         {       /* Horizontal axis */
290                 vec1[0]= G.v2d->cur.xmin;
291                 vec2[0]= G.v2d->cur.xmax;
292                 vec1[1]= vec2[1]= 0.0;
293                 glBegin(GL_LINE_STRIP);
294                 
295                 glVertex2fv(vec1);
296                 glVertex2fv(vec2);
297                 
298                 glEnd();
299         }
300         
301         /* Vertical axis */
302         
303         vec1[1]= G.v2d->cur.ymin;
304         vec2[1]= G.v2d->cur.ymax;
305         vec1[0]= vec2[0]= 0.0;
306         glBegin(GL_LINE_STRIP);
307         glVertex2fv(vec1); glVertex2fv(vec2);
308         glEnd();
309         
310         /* Limits box */
311         if(curarea->spacetype==SPACE_IPO) {
312                 if(G.sipo->blocktype==ID_SEQ) {
313                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
314                         glRectf(0.0,  0.0,  100.0,  1.0); 
315                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
316                 }
317                 else if(ELEM(G.sipo->blocktype, ID_CU, ID_CO)) {
318                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
319                         glRectf(0.0,  1.0,  G.v2d->cur.xmax,  1.0); 
320                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
321                 }
322         }
323 }
324
325 void areamouseco_to_ipoco(View2D *v2d, short *mval, float *x, float *y)
326 {
327         float div, ofs;
328         
329         div= v2d->mask.xmax-v2d->mask.xmin;
330         ofs= v2d->mask.xmin;
331         
332         *x= v2d->cur.xmin+ (v2d->cur.xmax-v2d->cur.xmin)*(mval[0]-ofs)/div;
333         
334         div= v2d->mask.ymax-v2d->mask.ymin;
335         ofs= v2d->mask.ymin;
336         
337         *y= v2d->cur.ymin+ (v2d->cur.ymax-v2d->cur.ymin)*(mval[1]-ofs)/div;
338 }
339
340 void ipoco_to_areaco(View2D *v2d, float *vec, short *mval)
341 {
342         float x, y;
343         
344         mval[0]= IS_CLIPPED;
345         
346         x= (vec[0] - v2d->cur.xmin)/(v2d->cur.xmax-v2d->cur.xmin);
347         y= (vec[1] - v2d->cur.ymin)/(v2d->cur.ymax-v2d->cur.ymin);
348
349         if(x>=0.0 && x<=1.0) {
350                 if(y>=0.0 && y<=1.0) {
351                         mval[0]= v2d->mask.xmin + x*(v2d->mask.xmax-v2d->mask.xmin);
352                         mval[1]= v2d->mask.ymin + y*(v2d->mask.ymax-v2d->mask.ymin);
353                 }
354         }
355 }
356
357 void ipoco_to_areaco_noclip(View2D *v2d, float *vec, short *mval)
358 {
359         float x, y;
360         
361         x= (vec[0] - v2d->cur.xmin)/(v2d->cur.xmax-v2d->cur.xmin);
362         y= (vec[1] - v2d->cur.ymin)/(v2d->cur.ymax-v2d->cur.ymin);
363         
364         x= v2d->mask.xmin + x*(v2d->mask.xmax-v2d->mask.xmin);
365         y= v2d->mask.ymin + y*(v2d->mask.ymax-v2d->mask.ymin);
366         
367         if(x<-32760) mval[0]= -32760;
368         else if(x>32760) mval[0]= 32760;
369         else mval[0]= x;
370         
371         if(y<-32760) mval[1]= -32760;
372         else if(y>32760) mval[1]= 32760;
373         else mval[1]= y;
374 }
375
376 int in_ipo_buttons(void)
377 {
378         short mval[2];
379         
380         getmouseco_areawin(mval);
381         
382         if(mval[0]< G.v2d->mask.xmax) return 0;
383         else return 1;
384 }
385
386
387 void view2d_zoom(View2D *v2d, float factor, int winx, int winy) 
388 {
389         float dx= factor*(v2d->cur.xmax-v2d->cur.xmin);
390         float dy= factor*(v2d->cur.ymax-v2d->cur.ymin);
391         if ((v2d->keepzoom & V2D_LOCKZOOM_X)==0) {
392                 v2d->cur.xmin+= dx;
393                 v2d->cur.xmax-= dx;
394         }
395         if ((v2d->keepzoom & V2D_LOCKZOOM_Y)==0) {
396                 v2d->cur.ymin+= dy;
397                 v2d->cur.ymax-= dy;
398         }
399         test_view2d(v2d, winx, winy);
400 }
401
402
403 void test_view2d(View2D *v2d, int winx, int winy)
404 {
405         /* cur is not allowed to be larger than max, smaller than min, or outside of tot */
406         rctf *cur, *tot;
407         float dx, dy, temp, fac, zoom;
408         
409         /* correct winx for scroll */
410         if(v2d->scroll & L_SCROLL) winx-= SCROLLB;
411         if(v2d->scroll & B_SCROLL) winy-= SCROLLH;
412         
413         cur= &v2d->cur;
414         tot= &v2d->tot;
415         
416         dx= cur->xmax-cur->xmin;
417         dy= cur->ymax-cur->ymin;
418
419
420         /* Reevan's test */
421         if (v2d->keepzoom & V2D_LOCKZOOM_Y)
422                 v2d->cur.ymax=v2d->cur.ymin+((float)winy);
423
424         if (v2d->keepzoom & V2D_LOCKZOOM_X)
425                 v2d->cur.xmax=v2d->cur.xmin+((float)winx);
426
427         if(v2d->keepzoom) {
428                 
429                 zoom= ((float)winx)/dx;
430                 
431                 if(zoom<v2d->minzoom || zoom>v2d->maxzoom) {
432                         if(zoom<v2d->minzoom) fac= zoom/v2d->minzoom;
433                         else fac= zoom/v2d->maxzoom;
434                         
435                         dx*= fac;
436                         temp= 0.5*(cur->xmax+cur->xmin);
437                         
438                         cur->xmin= temp-0.5*dx;
439                         cur->xmax= temp+0.5*dx;
440                 }
441                 
442                 zoom= ((float)winy)/dy;
443                 
444                 if(zoom<v2d->minzoom || zoom>v2d->maxzoom) {
445                         if(zoom<v2d->minzoom) fac= zoom/v2d->minzoom;
446                         else fac= zoom/v2d->maxzoom;
447                         
448                         dy*= fac;
449                         temp= 0.5*(cur->ymax+cur->ymin);
450                         cur->ymin= temp-0.5*dy;
451                         cur->ymax= temp+0.5*dy;
452                 }
453         }
454         else {
455                 if(dx<G.v2d->min[0]) {
456                         dx= G.v2d->min[0];
457                         temp= 0.5*(cur->xmax+cur->xmin);
458                         cur->xmin= temp-0.5*dx;
459                         cur->xmax= temp+0.5*dx;
460                 }
461                 else if(dx>G.v2d->max[0]) {
462                         dx= G.v2d->max[0];
463                         temp= 0.5*(cur->xmax+cur->xmin);
464                         cur->xmin= temp-0.5*dx;
465                         cur->xmax= temp+0.5*dx;
466                 }
467                 
468                 if(dy<G.v2d->min[1]) {
469                         dy= G.v2d->min[1];
470                         temp= 0.5*(cur->ymax+cur->ymin);
471                         cur->ymin= temp-0.5*dy;
472                         cur->ymax= temp+0.5*dy;
473                 }
474                 else if(dy>G.v2d->max[1]) {
475                         dy= G.v2d->max[1];
476                         temp= 0.5*(cur->ymax+cur->ymin);
477                         cur->ymin= temp-0.5*dy;
478                         cur->ymax= temp+0.5*dy;
479                 }
480         }
481
482         if(v2d->keepaspect) {
483                 short do_x=0, do_y=0;
484                 
485                 /* when a window edge changes, the aspect ratio can't be used to
486                    find which is the best new 'cur' rect. thats why it stores 'old' */
487                 if(winx!=v2d->oldwinx) do_x= 1;
488                 if(winy!=v2d->oldwiny) do_y= 1;
489                 
490                 dx= (cur->ymax-cur->ymin)/(cur->xmax-cur->xmin);
491                 dy= ((float)winy)/((float)winx);
492                 
493                 if(do_x==do_y) {        // both sizes change, ctrl+uparrow
494                         if(do_x==1 && do_y==1) {
495                                 if( ABS(winx-v2d->oldwinx)>ABS(winy-v2d->oldwiny)) do_y= 0;
496                                 else do_x= 0;
497                         }
498                         else if( dy > 1.0) do_x= 0; else do_x= 1;
499                 }
500                 
501                 v2d->oldwinx= winx; 
502                 v2d->oldwiny= winy;
503                 
504                 if( do_x ) {
505                         
506                         /* portrait window: correct for x */
507                         dx= cur->ymax-cur->ymin;
508                         temp= (cur->xmax+cur->xmin);
509                         
510                         cur->xmin= temp/2.0 - 0.5*dx/dy;
511                         cur->xmax= temp/2.0 + 0.5*dx/dy;
512                 }
513                 else {
514                         dx= cur->xmax-cur->xmin;
515                         temp= (cur->ymax+cur->ymin);
516                         
517                         cur->ymin= temp/2.0 - 0.5*dy*dx;
518                         cur->ymax= temp/2.0 + 0.5*dy*dx;
519                 }
520         }
521         
522         if(v2d->keeptot) {
523                 dx= cur->xmax-cur->xmin;
524                 dy= cur->ymax-cur->ymin;
525                 
526                 if(dx > tot->xmax-tot->xmin) {
527                         if(v2d->keepzoom==0) {
528                                 if(cur->xmin<tot->xmin) cur->xmin= tot->xmin;
529                                 if(cur->xmax>tot->xmax) cur->xmax= tot->xmax;
530                         }
531                         else {
532                                 if(cur->xmax < tot->xmax) {
533                                         dx= tot->xmax-cur->xmax;
534                                         cur->xmin+= dx;
535                                         cur->xmax+= dx;
536                                 }
537                                 else if(cur->xmin > tot->xmin) {
538                                         dx= cur->xmin-tot->xmin;
539                                         cur->xmin-= dx;
540                                         cur->xmax-= dx;
541                                 }
542                         }
543                 }
544                 else {
545                         if(cur->xmin < tot->xmin) {
546                                 dx= tot->xmin-cur->xmin;
547                                 cur->xmin+= dx;
548                                 cur->xmax+= dx;
549                         }
550                         else if(cur->xmax > tot->xmax) {
551                                 dx= cur->xmax-tot->xmax;
552                                 cur->xmin-= dx;
553                                 cur->xmax-= dx;
554                         }
555                 }
556                 
557                 if(dy > tot->ymax-tot->ymin) {
558                         if(v2d->keepzoom==0) {
559                                 if(cur->ymin<tot->ymin) cur->ymin= tot->ymin;
560                                 if(cur->ymax>tot->ymax) cur->ymax= tot->ymax;
561                         }
562                         else {
563                                 if(cur->ymax < tot->ymax) {
564                                         dy= tot->ymax-cur->ymax;
565                                         cur->ymin+= dy;
566                                         cur->ymax+= dy;
567                                 }
568                                 else if(cur->ymin > tot->ymin) {
569                                         dy= cur->ymin-tot->ymin;
570                                         cur->ymin-= dy;
571                                         cur->ymax-= dy;
572                                 }
573                         }
574                 }
575                 else {
576                         if(cur->ymin < tot->ymin) {
577                                 dy= tot->ymin-cur->ymin;
578                                 cur->ymin+= dy;
579                                 cur->ymax+= dy;
580                         }
581                         else if(cur->ymax > tot->ymax) {
582                                 dy= cur->ymax-tot->ymax;
583                                 cur->ymin-= dy;
584                                 cur->ymax-= dy;
585                         }
586                 }
587         }
588 }
589
590
591 void calc_scrollrcts(ScrArea *sa, View2D *v2d, int winx, int winy)
592 {
593         v2d->mask.xmin= v2d->mask.ymin= 0;
594         v2d->mask.xmax= winx;
595         v2d->mask.ymax= winy;
596         
597         if(sa->spacetype==SPACE_ACTION) {
598                 if(sa->winx > ACTWIDTH+50) { 
599                         v2d->mask.xmin+= ACTWIDTH;
600                         v2d->hor.xmin+=ACTWIDTH;
601                 }
602         }
603         else if(sa->spacetype==SPACE_NLA){
604                 if(sa->winx > NLAWIDTH+50) { 
605                         v2d->mask.xmin+= NLAWIDTH;
606                         v2d->hor.xmin+=NLAWIDTH;
607                 }
608         }
609         else if(sa->spacetype==SPACE_IPO) {
610                 v2d->mask.xmax-= IPOBUTX;
611                 
612                 if(v2d->mask.xmax<IPOBUTX)
613                         v2d->mask.xmax= winx;
614         }
615         
616         if(v2d->scroll) {
617                 if(v2d->scroll & L_SCROLL) {
618                         v2d->vert= v2d->mask;
619                         v2d->vert.xmax= SCROLLB;
620                         v2d->mask.xmin= SCROLLB;
621                 }
622                 else if(v2d->scroll & R_SCROLL) {
623                         v2d->vert= v2d->mask;
624                         v2d->vert.xmin= v2d->vert.xmax-SCROLLB;
625                         v2d->mask.xmax= v2d->vert.xmin;
626                 }
627                 
628                 if(v2d->scroll & B_SCROLL) {
629                         v2d->hor= v2d->mask;
630                         v2d->hor.ymax= SCROLLH;
631                         v2d->mask.ymin= SCROLLH;
632                 }
633                 else if(v2d->scroll & T_SCROLL) {
634                         v2d->hor= v2d->mask;
635                         v2d->hor.ymin= v2d->hor.ymax-SCROLLH;
636                         v2d->mask.ymax= v2d->hor.ymin;
637                 }
638         }
639 }
640
641         /* draws a line in left vertical scrollbar at the given height */
642 static void draw_solution_line(View2D *v2d, float h)
643 {
644         float vec[2];
645         short mval[2];
646
647         vec[0]= v2d->cur.xmin;
648         vec[1]= h;
649         ipoco_to_areaco(v2d, vec, mval);
650         if(mval[0]!=IS_CLIPPED) {
651                 glBegin(GL_LINES);
652                 glVertex2f(v2d->vert.xmin, mval[1]);
653                 glVertex2f(v2d->vert.xmax, mval[1]);
654                 glEnd();
655         }
656 }
657
658 static void draw_solution(SpaceIpo *sipo)
659 {
660         View2D *v2d= &sipo->v2d;
661         EditIpo *ei;
662         int a;
663
664         if (!(v2d->scroll & VERT_SCROLL)) return;
665
666         ei= sipo->editipo;
667         for(a=0; a<sipo->totipo; a++, ei++) {
668                 if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
669                         cpack(ei->col);
670                                 
671                                 /* DISPBITS ipos have 'multiple' values. */
672                         if(ei->disptype==IPO_DISPBITS) {
673                                 int b, val= ei->icu->curval;
674                                         
675                                 for (b=0; b<31; b++)
676                                         if (val & (1<<b))
677                                                 draw_solution_line(v2d, b+1);
678                         } else {
679                                 draw_solution_line(v2d, ei->icu->curval);
680                         }
681                 }
682         }
683 }
684
685 /* used for drawing timeline */
686 void draw_view2d_numbers_horiz(int drawframes)
687 {
688         float fac, fac2, dfac, val;
689         
690         /* the numbers: convert ipogrid_startx and -dx to scroll coordinates */
691         
692         fac= (ipogrid_startx- G.v2d->cur.xmin)/(G.v2d->cur.xmax-G.v2d->cur.xmin);
693         fac= G.v2d->mask.xmin+fac*(G.v2d->mask.xmax-G.v2d->mask.xmin);
694         
695         dfac= (ipogrid_dx)/(G.v2d->cur.xmax-G.v2d->cur.xmin);
696         dfac= dfac*(G.v2d->mask.xmax-G.v2d->mask.xmin);
697         
698         BIF_ThemeColor(TH_TEXT);
699         val= ipogrid_startx;
700         while(fac < G.v2d->mask.xmax) {
701                 
702                 if(drawframes) {
703                         ipomachtx= 1;
704                         scroll_prstr(fac, 2.0+(float)(G.v2d->mask.ymin), val, 'h', 0);
705                 }
706                 else {
707                         fac2= val/(float)G.scene->r.frs_sec;
708                         scroll_prstr(fac, 2.0+(float)(G.v2d->mask.ymin), fac2, 'h', 0);
709                 }
710                 
711                 fac+= dfac;
712                 val+= ipogrid_dx;
713         }
714 }
715
716
717 void drawscroll(int disptype)
718 {
719         rcti vert, hor;
720         float fac, dfac, val, fac2, tim;
721         int darker, dark, light, lighter;
722         
723         vert= (G.v2d->vert);
724         hor= (G.v2d->hor);
725         
726         darker= -40;
727         dark= 0;
728         light= 20;
729         lighter= 50;
730         
731         if(G.v2d->scroll & HOR_SCROLL) {
732                 
733                 BIF_ThemeColorShade(TH_SHADE1, light);
734                 glRecti(hor.xmin,  hor.ymin,  hor.xmax,  hor.ymax);
735                 
736                 /* slider */
737                 fac= (G.v2d->cur.xmin- G.v2d->tot.xmin)/(G.v2d->tot.xmax-G.v2d->tot.xmin);
738                 if(fac<0.0) fac= 0.0;
739                 horxmin= hor.xmin+fac*(hor.xmax-hor.xmin);
740                 
741                 fac= (G.v2d->cur.xmax- G.v2d->tot.xmin)/(G.v2d->tot.xmax-G.v2d->tot.xmin);
742                 if(fac>1.0) fac= 1.0;
743                 horxmax= hor.xmin+fac*(hor.xmax-hor.xmin);
744                 
745                 if(horxmin > horxmax) horxmin= horxmax;
746                 
747                 BIF_ThemeColorShade(TH_SHADE1, dark);
748                 glRecti(horxmin,  hor.ymin,  horxmax,  hor.ymax);
749
750                 /* decoration bright line */
751                 BIF_ThemeColorShade(TH_SHADE1, lighter);
752                 sdrawline(hor.xmin, hor.ymax, hor.xmax, hor.ymax);
753
754                 /* the numbers: convert ipogrid_startx and -dx to scroll coordinates */
755                 fac= (ipogrid_startx- G.v2d->cur.xmin)/(G.v2d->cur.xmax-G.v2d->cur.xmin);
756                 fac= hor.xmin+fac*(hor.xmax-hor.xmin);
757                 
758                 dfac= (ipogrid_dx)/(G.v2d->cur.xmax-G.v2d->cur.xmin);
759                 dfac= dfac*(hor.xmax-hor.xmin);
760                 
761                 BIF_ThemeColor(TH_TEXT);
762                 val= ipogrid_startx;
763                 while(fac < hor.xmax) {
764                         
765                         if(curarea->spacetype==SPACE_OOPS);
766                         else if(curarea->spacetype==SPACE_SEQ) {
767                                 fac2= val/(float)G.scene->r.frs_sec;
768                                 tim= floor(fac2);
769                                 fac2= fac2-tim;
770                                 scroll_prstr(fac, 3.0+(float)(hor.ymin), tim+G.scene->r.frs_sec*fac2/100.0, 'h', disptype);
771                         }
772                         else if (curarea->spacetype==SPACE_SOUND) {
773                                 SpaceSound *ssound= curarea->spacedata.first;
774                                 
775                                 if(ssound->flag & SND_DRAWFRAMES) {
776                                         ipomachtx= 1;
777                                         scroll_prstr(fac, 3.0+(float)(hor.ymin), val, 'h', disptype);
778                                 }
779                                 else {
780                                         fac2= val/(float)G.scene->r.frs_sec;
781                                         scroll_prstr(fac, 3.0+(float)(hor.ymin), fac2, 'h', disptype);
782                                 }
783                         }
784                         else if (curarea->spacetype==SPACE_TIME) {
785                                 SpaceTime *stime= curarea->spacedata.first;
786                                 
787                                 if(stime->flag & TIME_DRAWFRAMES) {
788                                         ipomachtx= 1;
789                                         scroll_prstr(fac, 3.0+(float)(hor.ymin), val, 'h', disptype);
790                                 }
791                                 else {
792                                         fac2= val/(float)G.scene->r.frs_sec;
793                                         scroll_prstr(fac, 3.0+(float)(hor.ymin), fac2, 'h', disptype);
794                                 }
795                         }
796                         else if (curarea->spacetype==SPACE_IPO) {
797                                 EditIpo *ei= get_active_editipo();
798                                 
799                                 if(ei && ei->icu && ei->icu->driver) {
800                                         int adrcode= ei->icu->driver->adrcode;
801                                         
802                                         if(adrcode==OB_ROT_X || adrcode==OB_ROT_Y || adrcode==OB_ROT_Z) {
803                                                 scroll_prstr(fac, 3.0+(float)(hor.ymin), val, 'v', IPO_DISPDEGR);
804                                         }
805                                         else 
806                                                 scroll_prstr(fac, 3.0+(float)(hor.ymin), val, 'h', disptype);
807                                 }
808                                 else 
809                                         scroll_prstr(fac, 3.0+(float)(hor.ymin), val, 'h', disptype);
810                         }
811                         else {
812                                 scroll_prstr(fac, 3.0+(float)(hor.ymin), val, 'h', disptype);
813                         }
814                         
815                         fac+= dfac;
816                         val+= ipogrid_dx;
817                 }
818         }
819         
820         if(G.v2d->scroll & VERT_SCROLL) {
821                 BIF_ThemeColorShade(TH_SHADE1, light);
822                 glRecti(vert.xmin,  vert.ymin,  vert.xmax,  vert.ymax);
823                 
824                 /* slider */
825                 fac= (G.v2d->cur.ymin- G.v2d->tot.ymin)/(G.v2d->tot.ymax-G.v2d->tot.ymin);
826                 if(fac<0.0) fac= 0.0;
827                 vertymin= vert.ymin+fac*(vert.ymax-vert.ymin);
828                 
829                 fac= (G.v2d->cur.ymax- G.v2d->tot.ymin)/(G.v2d->tot.ymax-G.v2d->tot.ymin);
830                 if(fac>1.0) fac= 1.0;
831                 vertymax= vert.ymin+fac*(vert.ymax-vert.ymin);
832                 
833                 if(vertymin > vertymax) vertymin= vertymax;
834                 
835                 BIF_ThemeColorShade(TH_SHADE1, dark);
836                 glRecti(vert.xmin,  vertymin,  vert.xmax,  vertymax);
837
838                 /* decoration black line */
839                 BIF_ThemeColorShade(TH_SHADE1, darker);
840                 if(G.v2d->scroll & HOR_SCROLL) 
841                         sdrawline(vert.xmax, vert.ymin+SCROLLH, vert.xmax, vert.ymax);
842                 else 
843                         sdrawline(vert.xmax, vert.ymin, vert.xmax, vert.ymax);
844
845                 /* the numbers: convert ipogrid_starty and -dy to scroll coordinates */
846                 fac= (ipogrid_starty- G.v2d->cur.ymin)/(G.v2d->cur.ymax-G.v2d->cur.ymin);
847                 fac= vert.ymin+SCROLLH+fac*(vert.ymax-vert.ymin-SCROLLH);
848                 
849                 dfac= (ipogrid_dy)/(G.v2d->cur.ymax-G.v2d->cur.ymin);
850                 dfac= dfac*(vert.ymax-vert.ymin-SCROLLH);
851                 
852                 if(curarea->spacetype==SPACE_OOPS);
853                 else if(curarea->spacetype==SPACE_SEQ) {
854                         BIF_ThemeColor(TH_TEXT);
855                         val= ipogrid_starty;
856                         fac+= 0.5*dfac;
857                         while(fac < vert.ymax) {
858                                 scroll_prstr((float)(vert.xmax)-14.0, fac, val, 'v', disptype);
859                                 fac+= dfac;
860                                 val+= ipogrid_dy;
861                         }
862                 }
863                 else if (curarea->spacetype==SPACE_NLA){
864                 }
865                 else if (curarea->spacetype==SPACE_ACTION){
866                         /* No digits on vertical axis in action mode! */
867                 }
868                 else {
869                         BIF_ThemeColor(TH_TEXT);
870                         val= ipogrid_starty;
871                         while(fac < vert.ymax) {
872                                 scroll_prstr((float)(vert.xmax)-14.0, fac, val, 'v', disptype);
873                                 fac+= dfac;
874                                 val+= ipogrid_dy;
875                         }
876                 }
877         }
878 }
879
880 static void draw_ipobuts(SpaceIpo *sipo)
881 {
882         ScrArea *area= sipo->area;
883         View2D *v2d= &sipo->v2d;
884         Object *ob= OBACT;
885         uiBlock *block;
886         uiBut *but;
887         EditIpo *ei;
888         int a, y, sel, tot;
889         char naam[20];
890         
891         if(area->winx<IPOBUTX) return;
892         
893         if(sipo->butofs) {
894                 tot= 30+IPOBUTY*sipo->totipo;
895                 if(tot<area->winy) sipo->butofs= 0;
896         }
897         
898         BIF_ThemeColor(TH_SHADE2);
899         glRects(v2d->mask.xmax,  0,  area->winx,  area->winy);
900         
901         cpack(0x0);
902         sdrawline(v2d->mask.xmax, 0, v2d->mask.xmax, area->winy);
903
904         if(sipo->totipo==0) return;
905         if(sipo->editipo==0) return;
906         
907         sprintf(naam, "ipowin %d", area->win);
908         block= uiNewBlock(&area->uiblocks, naam, UI_EMBOSSN, UI_HELV, area->win);
909
910         ei= sipo->editipo;
911         y= area->winy-30+sipo->butofs;
912         
913         if(sipo->blocktype==ID_KE) {
914                 int icon;
915                 if(ob->shapeflag & OB_SHAPE_LOCK) icon= ICON_PIN_HLT; else icon= ICON_PIN_DEHLT;
916                 uiDefIconButBitC(block, TOG, OB_SHAPE_LOCK, B_SETKEY, icon, 
917                                                  v2d->mask.xmax+18,y,25,20, &ob->shapeflag, 0, 0, 0, 0, "Always show the current Shape for this Object");
918                 y-= IPOBUTY;
919         }
920         
921         for(a=0; a<sipo->totipo; a++, ei++, y-=IPOBUTY) {
922                 // this button defines visiblity, bit zero of flag (IPO_VISIBLE)
923                 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, "");
924                 // no hilite, its not visible, but most of all the winmatrix is not correct later on...
925                 uiButSetFlag(but, UI_TEXT_LEFT|UI_NO_HILITE);
926                 
927                 // this fake button defines selection of curves
928                 if(ei->icu) {
929                         cpack(ei->col);
930                         
931                         glRects(v2d->mask.xmax+8,  y+2,  v2d->mask.xmax+15, y+IPOBUTY-2);
932                         sel= ei->flag & (IPO_SELECT + IPO_EDIT);
933                         
934                         uiEmboss((float)(v2d->mask.xmax+8), (float)(y+2), (float)(v2d->mask.xmax+15), (float)(y+IPOBUTY-2), sel);
935                         
936                         if(ei->icu->driver) {
937                                 cpack(0x0);
938                                 fdrawbox((float)v2d->mask.xmax+11,  (float)y+8,  (float)v2d->mask.xmax+12.5, (float)y+9.5);
939                         }
940                 }
941                 
942                 if(ei->flag & IPO_ACTIVE) {
943                         cpack(0x0);
944                         fdrawbox(v2d->mask.xmax+7,  y+1,  v2d->mask.xmax+16, y+IPOBUTY-1);
945                 }
946         }
947         uiDrawBlock(block);
948 }
949
950 static void calc_ipoverts(SpaceIpo *sipo)
951 {
952         View2D *v2d= &sipo->v2d;
953         EditIpo *ei;
954         BezTriple *bezt;
955         BPoint *bp;
956         int a, b;
957         
958         ei= G.sipo->editipo;
959         for(a=0; a<sipo->totipo; a++, ei++) {
960                 if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
961                         if(ei->icu->bezt) {
962                                 bezt= ei->icu->bezt;
963                                 b= ei->icu->totvert;
964                                 while(b--) {
965                                         ipoco_to_areaco(v2d, bezt->vec[0], bezt->s[0]);
966                                         ipoco_to_areaco(v2d, bezt->vec[1], bezt->s[1]);
967                                         ipoco_to_areaco(v2d, bezt->vec[2], bezt->s[2]);
968                                         bezt++;
969                                 }
970                         }
971                         else if(ei->icu->bp) {
972                                 bp= ei->icu->bp;
973                                 b= ei->icu->totvert;
974                                 while(b--) {
975                                         ipoco_to_areaco(v2d, bp->vec, bp->s);
976                                         bp++;
977                                 }
978                         }
979                 }
980         }
981 }
982
983
984 static void draw_ipovertices(int sel)
985 {
986         EditIpo *ei;
987         BezTriple *bezt;
988         float v1[2];
989         int val, ok, nr, a, b;
990         
991         if(G.f & G_PICKSEL) return;
992         
993         glPointSize(3.0);
994         
995         ei= G.sipo->editipo;
996         for(nr=0; nr<G.sipo->totipo; nr++, ei++) {
997                 if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
998                         
999                         if(G.sipo->showkey) {
1000                                 if(sel) BIF_ThemeColor(TH_TEXT_HI);
1001                                  else BIF_ThemeColor(TH_TEXT);
1002                         } else if(ei->flag & IPO_EDIT) {
1003                                 if(sel) BIF_ThemeColor(TH_VERTEX_SELECT); 
1004                                 else BIF_ThemeColor(TH_VERTEX);
1005                         } else {
1006                                 if(sel) BIF_ThemeColor(TH_TEXT_HI);
1007                                  else BIF_ThemeColor(TH_TEXT);
1008                                  
1009                                 val= (ei->icu->flag & IPO_SELECT)!=0;
1010                                 if(sel != val) continue;
1011                         }
1012
1013                         /* We can't change the color in the middle of
1014                          * GL_POINTS because then Blender will segfault
1015                          * on TNT2 / Linux with NVidia's drivers
1016                          * (at least up to ver. 4349) */                
1017                         
1018                         bglBegin(GL_POINTS);
1019                         
1020                         bezt= ei->icu->bezt;
1021                         a= ei->icu->totvert;
1022                         while(a--) {                            
1023                                 
1024                                 if(ei->disptype==IPO_DISPBITS) {
1025                                         ok= 0;
1026                                         if(ei->flag & IPO_EDIT) {
1027                                                 if( (bezt->f2 & 1) == sel ) ok= 1;
1028                                         }
1029                                         else ok= 1;
1030                                         
1031                                         if(ok) {
1032                                                 val= bezt->vec[1][1];
1033                                                 b= 0;
1034                                                 v1[0]= bezt->vec[1][0];
1035                                                 
1036                                                 while(b<31) {
1037                                                         if(val & (1<<b)) {      
1038                                                                 v1[1]= b+1;
1039                                                                 bglVertex3fv(v1);
1040                                                         }
1041                                                         b++;
1042                                                 }
1043                                         }
1044                                 }
1045                                 else {
1046                                         
1047                                         if(ei->flag & IPO_EDIT) {
1048                                                 if(ei->icu->ipo==IPO_BEZ) {
1049                                                         if( (bezt->f1 & 1) == sel )     
1050                                                                 bglVertex3fv(bezt->vec[0]);
1051                                                         if( (bezt->f3 & 1) == sel )     
1052                                                                 bglVertex3fv(bezt->vec[2]);
1053                                                 }
1054                                                 if( (bezt->f2 & 1) == sel )     
1055                                                         bglVertex3fv(bezt->vec[1]);
1056                                                 
1057                                         }
1058                                         else {
1059                                                 bglVertex3fv(bezt->vec[1]);
1060                                         }
1061                                 }
1062                                 
1063                                 bezt++;
1064                         }
1065
1066                         bglEnd();
1067                 }
1068         }
1069         
1070         glPointSize(1.0);
1071 }
1072
1073 static void draw_ipohandles(int sel)
1074 {
1075         extern unsigned int nurbcol[];
1076         EditIpo *ei;
1077         BezTriple *bezt;
1078         float *fp;
1079         unsigned int *col;
1080         int a, b;
1081         
1082         if(sel) col= nurbcol+4;
1083         else col= nurbcol;
1084         
1085         ei= G.sipo->editipo;
1086         for(a=0; a<G.sipo->totipo; a++, ei++) {
1087                 if ISPOIN4(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu, disptype!=IPO_DISPBITS) {
1088                         if(ei->icu->ipo==IPO_BEZ) {
1089                                 bezt= ei->icu->bezt;
1090                                 b= ei->icu->totvert;
1091                                 while(b--) {
1092                                         
1093                                         if( (bezt->f2 & 1)==sel) {
1094                                                 fp= bezt->vec[0];
1095                                                 cpack(col[bezt->h1]);
1096                                                 
1097                                                 glBegin(GL_LINE_STRIP); 
1098                                                 glVertex2fv(fp); glVertex2fv(fp+3); 
1099                                                 glEnd();
1100                                                 cpack(col[bezt->h2]);
1101                                                 
1102                                                 glBegin(GL_LINE_STRIP); 
1103                                                 glVertex2fv(fp+3); glVertex2fv(fp+6); 
1104                                                 glEnd();
1105                                         }
1106                                         else if( (bezt->f1 & 1)==sel) {
1107                                                 fp= bezt->vec[0];
1108                                                 cpack(col[bezt->h1]);
1109                                                 
1110                                                 glBegin(GL_LINE_STRIP); 
1111                                                 glVertex2fv(fp); glVertex2fv(fp+3); 
1112                                                 glEnd();
1113                                         }
1114                                         else if( (bezt->f3 & 1)==sel) {
1115                                                 fp= bezt->vec[1];
1116                                                 cpack(col[bezt->h2]);
1117                                                 
1118                                                 glBegin(GL_LINE_STRIP); 
1119                                                 glVertex2fv(fp); glVertex2fv(fp+3); 
1120                                                 glEnd();
1121                                         }
1122                                         
1123                                         bezt++;
1124                                 }
1125                         }
1126                 }
1127         }
1128 }
1129
1130 int pickselcode;
1131
1132 static void init_pickselcode(void)
1133 {
1134         pickselcode= 1;
1135 }
1136
1137 static void draw_ipocurves(int sel)
1138 {
1139         EditIpo *ei;
1140         IpoCurve *icu;
1141         BezTriple *bezt, *prevbezt;
1142         float *fp, fac, data[120], v1[2], v2[2], v3[2], v4[2];
1143         float cycdx=0, cycdy=0, cycxofs, cycyofs;
1144         int a, b, resol, cycount, val, nr;
1145         
1146         
1147         ei= G.sipo->editipo;
1148         for(nr=0; nr<G.sipo->totipo; nr++, ei++) {
1149                 if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
1150                         
1151                         if(G.f & G_PICKSEL) {
1152                                 glLoadName(pickselcode++);
1153                                 val= 1;
1154                         }
1155                         else {
1156                                 val= (ei->flag & (IPO_SELECT+IPO_EDIT))!=0;
1157                                 val= (val==sel);
1158                         }
1159                         
1160                         if(val) {
1161                                 
1162                                 cycyofs= cycxofs= 0.0;
1163                                 cycount= 1;
1164                                 
1165                                 icu= ei->icu;   
1166                                 
1167                                 /* curve */
1168                                 if(G.sipo->showkey) BIF_ThemeColor(TH_TEXT); 
1169                                 else cpack(ei->col);
1170                                 
1171                                 /* cyclic */
1172                                 if(icu->extrap & IPO_CYCL) {
1173                                         cycdx= (icu->bezt+icu->totvert-1)->vec[1][0] - icu->bezt->vec[1][0];
1174                                         cycdy= (icu->bezt+icu->totvert-1)->vec[1][1] - icu->bezt->vec[1][1];
1175                                         if(cycdx>0.01) {
1176                                                 
1177                                                 while(icu->bezt->vec[1][0]+cycxofs > G.v2d->cur.xmin) {
1178                                                         cycxofs-= cycdx;
1179                                                         if(icu->extrap & IPO_DIR) cycyofs-= cycdy;
1180                                                         cycount++;
1181                                                 }
1182                                                 bezt= icu->bezt+(icu->totvert-1);
1183                                                 fac= 0.0;
1184                                                 while(bezt->vec[1][0]+fac < G.v2d->cur.xmax) {
1185                                                         cycount++;
1186                                                         fac+= cycdx;
1187                                                 }
1188                                         }
1189                                 }
1190                                 
1191                                 while(cycount--) {
1192                                         
1193                                         if(ei->disptype==IPO_DISPBITS) {
1194                                                 
1195                                                 /* lines */
1196                                                 cpack(ei->col);
1197                                                 bezt= icu->bezt;
1198                                                 a= icu->totvert;
1199                                                 
1200                                                 while(a--) {
1201                                                         val= bezt->vec[1][1];
1202                                                         b= 0;
1203                                                         
1204                                                         while(b<31) {
1205                                                                 if(val & (1<<b)) {
1206                                                                         v1[1]= b+1;
1207                                                                         
1208                                                                         glBegin(GL_LINE_STRIP);
1209                                                                         if(icu->extrap & IPO_CYCL) ;
1210                                                                         else if(a==icu->totvert-1) {
1211                                                                                 v1[0]= G.v2d->cur.xmin+cycxofs;
1212                                                                                 glVertex2fv(v1);
1213                                                                         }
1214                                                                         v1[0]= bezt->vec[1][0]+cycxofs;
1215                                                                         glVertex2fv(v1); 
1216                                                                         
1217                                                                         if(a) v1[0]= (bezt+1)->vec[1][0]+cycxofs;
1218                                                                         else if(icu->extrap & IPO_CYCL) ;
1219                                                                         else v1[0]= G.v2d->cur.xmax+cycxofs;
1220                                                                         
1221                                                                         glVertex2fv(v1);
1222                                                                         glEnd();
1223                                                                 }
1224                                                                 b++;
1225                                                         }
1226                                                         bezt++;
1227                                                 }
1228                                                 
1229                                         }
1230                                         else {
1231                                                 
1232                                                 b= icu->totvert-1;
1233                                                 prevbezt= icu->bezt;
1234                                                 bezt= prevbezt+1;
1235                                                 
1236                                                 glBegin(GL_LINE_STRIP);
1237                                                 
1238                                                 /* extrapolate to left? */
1239                                                 if( (icu->extrap & IPO_CYCL)==0) {
1240                                                         if(prevbezt->vec[1][0] > G.v2d->cur.xmin) {
1241                                                                 v1[0]= G.v2d->cur.xmin;
1242                                                                 if(icu->extrap==IPO_HORIZ || icu->ipo==IPO_CONST) v1[1]= prevbezt->vec[1][1];
1243                                                                 else {
1244                                                                         fac= (prevbezt->vec[0][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
1245                                                                         if(fac!=0.0) fac= 1.0/fac;
1246                                                                         v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[0][1]-prevbezt->vec[1][1]);
1247                                                                 }
1248                                                                 glVertex2fv(v1);
1249                                                         }
1250                                                 }
1251                                                 
1252                                                 if(b==0) {
1253                                                         v1[0]= prevbezt->vec[1][0]+cycxofs;
1254                                                         v1[1]= prevbezt->vec[1][1]+cycyofs;
1255                                                         glVertex2fv(v1);
1256                                                 }
1257                                                 
1258                                                 while(b--) {
1259                                                         if(icu->ipo==IPO_CONST) {
1260                                                                 v1[0]= prevbezt->vec[1][0]+cycxofs;
1261                                                                 v1[1]= prevbezt->vec[1][1]+cycyofs;
1262                                                                 glVertex2fv(v1);
1263                                                                 v1[0]= bezt->vec[1][0]+cycxofs;
1264                                                                 v1[1]= prevbezt->vec[1][1]+cycyofs;
1265                                                                 glVertex2fv(v1);
1266                                                         }
1267                                                         else if(icu->ipo==IPO_LIN) {
1268                                                                 v1[0]= prevbezt->vec[1][0]+cycxofs;
1269                                                                 v1[1]= prevbezt->vec[1][1]+cycyofs;
1270                                                                 glVertex2fv(v1);
1271                                                         }
1272                                                         else {
1273                                                                 /* resol not depending on horizontal resolution anymore, drivers for example... */
1274                                                                 if(icu->driver) resol= 32;
1275                                                                 else resol= 3.0*sqrt(bezt->vec[1][0] - prevbezt->vec[1][0]);
1276                                                                 
1277                                                                 if(resol<2) {
1278                                                                         v1[0]= prevbezt->vec[1][0]+cycxofs;
1279                                                                         v1[1]= prevbezt->vec[1][1]+cycyofs;
1280                                                                         glVertex2fv(v1);
1281                                                                 }
1282                                                                 else {
1283                                                                         if(resol>32) resol= 32;
1284                                                                         
1285                                                                         v1[0]= prevbezt->vec[1][0]+cycxofs;
1286                                                                         v1[1]= prevbezt->vec[1][1]+cycyofs;
1287                                                                         v2[0]= prevbezt->vec[2][0]+cycxofs;
1288                                                                         v2[1]= prevbezt->vec[2][1]+cycyofs;
1289                                                                         
1290                                                                         v3[0]= bezt->vec[0][0]+cycxofs;
1291                                                                         v3[1]= bezt->vec[0][1]+cycyofs;
1292                                                                         v4[0]= bezt->vec[1][0]+cycxofs;
1293                                                                         v4[1]= bezt->vec[1][1]+cycyofs;
1294                                                                         
1295                                                                         correct_bezpart(v1, v2, v3, v4);
1296                                                                         
1297                                                                         forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, 3);
1298                                                                         forward_diff_bezier(v1[1], v2[1], v3[1], v4[1], data+1, resol, 3);
1299                                                                         
1300                                                                         fp= data;
1301                                                                         while(resol--) {
1302                                                                                 glVertex2fv(fp);
1303                                                                                 fp+= 3;
1304                                                                         }
1305                                                                 }
1306                                                         }
1307                                                         prevbezt= bezt;
1308                                                         bezt++;
1309                                                         
1310                                                         /* last point? */
1311                                                         if(b==0) {
1312                                                                 v1[0]= prevbezt->vec[1][0]+cycxofs;
1313                                                                 v1[1]= prevbezt->vec[1][1]+cycyofs;
1314                                                                 glVertex2fv(v1);
1315                                                         }
1316                                                 }
1317                                                 
1318                                                 /* extrapolate to right? */
1319                                                 if( (icu->extrap & IPO_CYCL)==0) {
1320                                                         if(prevbezt->vec[1][0] < G.v2d->cur.xmax) {
1321                                                                 v1[0]= G.v2d->cur.xmax;
1322                                                                 if(icu->extrap==IPO_HORIZ || icu->ipo==IPO_CONST) v1[1]= prevbezt->vec[1][1];
1323                                                                 else {
1324                                                                         fac= (prevbezt->vec[2][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
1325                                                                         if(fac!=0.0) fac= 1.0/fac;
1326                                                                         v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[2][1]-prevbezt->vec[1][1]);
1327                                                                 }
1328                                                                 glVertex2fv(v1);
1329                                                         }
1330                                                 }
1331                                                 
1332                                                 glEnd();
1333                                                 
1334                                         }
1335                                         cycxofs+= cycdx;
1336                                         if(icu->extrap & IPO_DIR) cycyofs+= cycdy;
1337                                 }
1338                                 
1339                                 /* line that indicates the end of a speed curve */
1340                                 if(G.sipo->blocktype==ID_CU && icu->adrcode==CU_SPEED) {
1341                                         b= icu->totvert-1;
1342                                         if(b) {
1343                                                 glColor3ub(0, 0, 0);
1344                                                 bezt= icu->bezt+b;
1345                                                 glBegin(GL_LINES);
1346                                                 glVertex2f(bezt->vec[1][0], 0.0);
1347                                                 glVertex2f(bezt->vec[1][0], bezt->vec[1][1]);
1348                                                 glEnd();
1349                                         }
1350                                 }
1351                         }
1352                 }
1353         }
1354 }
1355
1356 static void draw_cfra(SpaceIpo *sipo)
1357 {
1358         View2D *v2d= &sipo->v2d;
1359         Object *ob;
1360         float vec[2];
1361         
1362         vec[0]= (G.scene->r.cfra);
1363         vec[0]*= G.scene->r.framelen;
1364         
1365         vec[1]= v2d->cur.ymin;
1366         glColor3ub(0x60, 0xc0, 0x40);   // no theme, should be global color once...
1367         glLineWidth(2.0);
1368         
1369         glBegin(GL_LINE_STRIP);
1370         glVertex2fv(vec);
1371         vec[1]= v2d->cur.ymax;
1372         glVertex2fv(vec);
1373         glEnd();
1374         
1375         if(sipo->blocktype==ID_OB) {
1376                 ob= (G.scene->basact) ? (G.scene->basact->object) : 0;
1377                 if(ob && ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
1378                         vec[0]-= ob->sf;
1379                         
1380                         BIF_ThemeColorShade(TH_HILITE, -30);
1381                         
1382                         glBegin(GL_LINE_STRIP);
1383                         glVertex2fv(vec);
1384                         vec[1]= G.v2d->cur.ymin;
1385                         glVertex2fv(vec);
1386                         glEnd();
1387                 }
1388         }
1389         
1390         glLineWidth(1.0);
1391 }
1392
1393 static void draw_ipokey(SpaceIpo *sipo)
1394 {
1395         IpoKey *ik;
1396         
1397         glBegin(GL_LINES);
1398         for (ik= sipo->ipokey.first; ik; ik= ik->next) {
1399                 if(ik->flag & 1) glColor3ub(0xFF, 0xFF, 0x99);
1400                 else glColor3ub(0xAA, 0xAA, 0x55);
1401                 
1402                 glVertex2f(ik->val, G.v2d->cur.ymin);
1403                 glVertex2f(ik->val, G.v2d->cur.ymax);
1404         }
1405         glEnd();
1406 }
1407
1408 static void draw_key(SpaceIpo *sipo, int visible)
1409 {
1410         View2D *v2d= &sipo->v2d;
1411         Key *key;
1412         KeyBlock *kb, *act=NULL;
1413         Object *ob= OBACT;
1414         unsigned int col;
1415         int index;
1416         
1417         key= (Key *)sipo->from;
1418         if(key==NULL)
1419                 return;
1420         
1421         if(key->type== KEY_RELATIVE) if(visible==0) return;
1422         
1423         for(index=1, kb= key->block.first; kb; kb= kb->next, index++) {
1424                 if(kb->type==KEY_LINEAR) setlinestyle(2);
1425                 else if(kb->type==KEY_BSPLINE) setlinestyle(4);
1426                 else setlinestyle(0);
1427                 
1428                 if(kb==key->refkey) col= 0x22FFFF;
1429                 else col= 0xFFFF00;
1430                 
1431                 if(ob->shapenr!=index) col-= 0x225500;
1432                 else act= kb;
1433                 
1434                 cpack(col);
1435                 
1436                 glBegin(GL_LINE_STRIP);
1437                 glVertex2f(v2d->cur.xmin, kb->pos);
1438                 glVertex2f(v2d->cur.xmax, kb->pos);
1439                 glEnd();
1440                 
1441         }
1442         
1443         if(act) {
1444                 if(act->type==KEY_LINEAR) setlinestyle(2);
1445                 else if(act->type==KEY_BSPLINE) setlinestyle(4);
1446                 else setlinestyle(0);
1447                 
1448                 if(act==key->refkey) cpack(0x22FFFF);
1449                 else cpack(0xFFFF00);
1450                 
1451                 glBegin(GL_LINE_STRIP);
1452                 glVertex2f(v2d->cur.xmin, act->pos);
1453                 glVertex2f(v2d->cur.xmax, act->pos);
1454                 glEnd();
1455         }
1456         
1457         setlinestyle(0);
1458 }
1459
1460 /* ************************** buttons *********************** */
1461
1462
1463 #define B_SETSPEED              3401
1464 #define B_MUL_IPO               3402
1465 #define B_TRANS_IPO             3403
1466 #define B_IPO_NONE              3404
1467 #define B_IPO_DRIVER    3405
1468 #define B_IPO_REDR              3406
1469 #define B_IPO_DEPCHANGE 3407
1470
1471 static float hspeed= 0;
1472
1473 static void boundbox_ipo_curves(SpaceIpo *si)
1474 {
1475         EditIpo *ei;
1476         Key *key;
1477         KeyBlock *kb;
1478         int a, first= 1;
1479
1480         ei= si->editipo;
1481         if(ei==0)
1482                 return;
1483
1484         for(a=0; a<si->totipo; a++, ei++) {
1485                 
1486                 if(ei->icu) {
1487                         if(ei->flag & IPO_VISIBLE) {
1488         
1489                                 boundbox_ipocurve(ei->icu);
1490                                 if(first) {
1491                                         si->v2d.tot= ei->icu->totrct;
1492                                         first= 0;
1493                                 }
1494                                 else BLI_union_rctf(&(si->v2d.tot), &(ei->icu->totrct));
1495                         }
1496                 }
1497         }
1498         /* keylines? */
1499         if(si->blocktype==ID_KE) {
1500                 key= (Key *)si->from;
1501                 if(key && key->block.first) {
1502                         kb= key->block.first;
1503                         if(kb->pos < si->v2d.tot.ymin) si->v2d.tot.ymin= kb->pos;
1504                         kb= key->block.last;
1505                         if(kb->pos > si->v2d.tot.ymax) si->v2d.tot.ymax= kb->pos;
1506                 }
1507         }
1508         si->tot= si->v2d.tot;
1509 }
1510
1511
1512 /* is used for both read and write... */
1513 static void ipo_editvertex_buts(uiBlock *block, SpaceIpo *si, float min, float max)
1514 {
1515         Object *ob= OBACT;
1516         EditIpo *ei;
1517         BezTriple *bezt;
1518         float median[3];
1519         int a, b, tot, iskey=0;
1520         
1521         median[0]= median[1]= median[2]= 0.0;
1522         tot= 0;
1523         
1524         ei= G.sipo->editipo;
1525         for(a=0; a<G.sipo->totipo; a++, ei++) {
1526                 
1527                 if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
1528                         if( (ei->flag & IPO_EDIT) || G.sipo->showkey) {
1529
1530                                 if(ei->icu->bezt) {
1531                                         bezt= ei->icu->bezt;
1532                                         b= ei->icu->totvert;
1533                                         while(b--) {
1534                                                 // all three selected 
1535                                                 if(bezt->f2 & 1) {
1536                                                         VecAddf(median, median, bezt->vec[1]);
1537                                                         tot++;
1538                                                 }
1539                                                 else {
1540                                                         if(bezt->f1 & 1) {
1541                                                                 VecAddf(median, median, bezt->vec[0]);
1542                                                                 tot++;
1543                                                         }
1544                                                         if(bezt->f3 & 1) {
1545                                                                 VecAddf(median, median, bezt->vec[2]);
1546                                                                 tot++;
1547                                                         }
1548                                                 }
1549                                                 bezt++;
1550                                         }
1551                                         
1552                                 }
1553                         }
1554                 }
1555         }
1556         /* check for keys */
1557         if(tot==0) {
1558                 if(G.sipo->blocktype==ID_KE) {
1559                         Key *key= (Key *)G.sipo->from;
1560                         KeyBlock *kb;
1561                         
1562                         if(key==NULL || ob->shapenr==0) return;
1563                         iskey= 1;
1564                         
1565                         kb= BLI_findlink(&key->block, ob->shapenr-1);
1566                         median[1]+= kb->pos;
1567                         tot++;
1568                 }
1569         }
1570         if(tot==0) return;
1571
1572         median[0] /= (float)tot;
1573         median[1] /= (float)tot;
1574         median[2] /= (float)tot;
1575         
1576         if(block) {     // buttons
1577         
1578                 VECCOPY(si->median, median);
1579                 
1580                 uiBlockBeginAlign(block);
1581                 if(tot==1) {
1582                         if(iskey) 
1583                                 uiDefButF(block, NUM, B_TRANS_IPO, "Key Y:",    10, 80, 300, 19, &(si->median[1]), min, max, 10, 0, "");
1584                         else {
1585                                 uiDefButF(block, NUM, B_TRANS_IPO, "Vertex X:", 10, 100, 150, 19, &(si->median[0]), min, max, 100, 0, "");
1586                                 uiDefButF(block, NUM, B_TRANS_IPO, "Vertex Y:", 160, 100, 150, 19, &(si->median[1]), min, max, 100, 0, "");
1587                         }
1588                 }
1589                 else {
1590                         if(iskey) 
1591                                 uiDefButF(block, NUM, B_TRANS_IPO, "Median Key Y:",     10, 80, 300, 19, &(si->median[1]), min, max, 10, 0, "");
1592                         else {
1593                                 uiDefButF(block, NUM, B_TRANS_IPO, "Median X:", 10, 100, 150, 19, &(si->median[0]), min, max, 100, 0, "");
1594                                 uiDefButF(block, NUM, B_TRANS_IPO, "Median Y:", 160, 100, 150, 19, &(si->median[1]), min, max, 100, 0, "");
1595                         }
1596                 }
1597         }
1598         else if(iskey) {        // apply
1599                 VecSubf(median, si->median, median);
1600
1601                 if(G.sipo->blocktype==ID_KE) {
1602                         Key *key= (Key *)G.sipo->from;
1603                         KeyBlock *kb;
1604                         
1605                         if(key==NULL || ob->shapenr==0) return;
1606                         
1607                         kb= BLI_findlink(&key->block, ob->shapenr-1);
1608                         kb->pos+= median[1];
1609                         tot++;
1610
1611                         sort_keys(key);
1612                 }
1613         }
1614         else {
1615                 
1616                 VecSubf(median, si->median, median);
1617
1618                 ei= G.sipo->editipo;
1619                 for(a=0; a<G.sipo->totipo; a++, ei++) {
1620                         
1621                         if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
1622                                 if( (ei->flag & IPO_EDIT) || G.sipo->showkey) {
1623
1624                                         if(ei->icu->bezt) {
1625                                                 bezt= ei->icu->bezt;
1626                                                 b= ei->icu->totvert;
1627                                                 while(b--) {
1628                                                         // all three selected
1629                                                         if(bezt->f2 & 1) {
1630                                                                 VecAddf(bezt->vec[0], bezt->vec[0], median);
1631                                                                 VecAddf(bezt->vec[1], bezt->vec[1], median);
1632                                                                 VecAddf(bezt->vec[2], bezt->vec[2], median);
1633                                                         }
1634                                                         else {
1635                                                                 if(bezt->f1 & 1) {
1636                                                                         VecAddf(bezt->vec[0], bezt->vec[0], median);
1637                                                                 }
1638                                                                 if(bezt->f3 & 1) {
1639                                                                         VecAddf(bezt->vec[2], bezt->vec[2], median);
1640                                                                 }
1641                                                         }
1642                                                         bezt++;
1643                                                 }
1644                                                 
1645                                         }
1646                                 }
1647                         }
1648                 }
1649         }
1650 }
1651
1652 void do_ipobuts(unsigned short event)
1653 {
1654         Object *ob= OBACT;
1655         EditIpo *ei;
1656         
1657         if(G.sipo->from==NULL) return;
1658         
1659         switch(event) {
1660         case B_IPO_REDR:
1661                 ei= get_active_editipo();
1662                 if(ei) {
1663                         if(ei->icu->driver) {
1664                                 if(G.sipo->blocktype==ID_KE || G.sipo->blocktype==ID_AC) 
1665                                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1666                                 else
1667                                         DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
1668                         }
1669                 }
1670                 allqueue(REDRAWIPO, 0);
1671                 allqueue(REDRAWVIEW3D, 0);
1672                 break;
1673         case B_SETSPEED:
1674                 set_speed_editipo(hspeed);
1675                 break;
1676         case B_MUL_IPO:
1677                 scale_editipo();
1678                 allqueue(REDRAWIPO, 0);
1679                 break;
1680         case B_TRANS_IPO:
1681                 ipo_editvertex_buts(NULL, G.sipo, 0.0, 0.0);
1682                 editipo_changed(G.sipo, 1);
1683                 allqueue(REDRAWIPO, 0);
1684                 break;
1685         case B_SETKEY:
1686                 ob->shapeflag &= ~OB_SHAPE_TEMPLOCK;
1687                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1688                 allqueue(REDRAWVIEW3D, 0);
1689                 allqueue(REDRAWIPO, 0);
1690                 allqueue(REDRAWBUTSEDIT, 0);
1691                 break;
1692         case B_IPO_DRIVER:
1693                 ei= get_active_editipo();
1694                 if(ei) {
1695                         if(ei->icu==NULL) {
1696                                 ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, ei->adrcode);
1697                                 ei->flag |= IPO_SELECT;
1698                                 ei->icu->flag= ei->flag;
1699                         }
1700                         if(ei->icu->driver) {
1701                                 MEM_freeN(ei->icu->driver);
1702                                 ei->icu->driver= NULL;
1703                                 if(ei->icu->bezt==NULL) {
1704                                         BLI_remlink( &(G.sipo->ipo->curve), ei->icu);
1705                                         free_ipo_curve(ei->icu);
1706                                         ei->icu= NULL;
1707                                 }
1708                         }
1709                         else {
1710                                 ei->icu->driver= MEM_callocN(sizeof(IpoDriver), "ipo driver");
1711                                 ei->icu->driver->blocktype= ID_OB;
1712                                 ei->icu->driver->adrcode= OB_LOC_X;
1713                         }
1714
1715                         allqueue(REDRAWVIEW3D, 0);
1716                         allqueue(REDRAWIPO, 0);
1717                         allqueue(REDRAWBUTSEDIT, 0);
1718                         DAG_scene_sort(G.scene);
1719                         
1720                         BIF_undo_push("Add/Remove Ipo driver");
1721                 }
1722                 break;
1723         case B_IPO_DEPCHANGE:
1724                 ei= get_active_editipo();
1725                 if(ei) {
1726                         if(ei->icu->driver) {
1727                                 IpoDriver *driver= ei->icu->driver;
1728                                 
1729                                 if(driver->ob) {
1730                                         if(ob==driver->ob) {
1731                                                 error("Cannot assign a Driver to own Object");
1732                                                 driver->ob= NULL;
1733                                         }
1734                                         else {
1735                                                 /* check if type is still OK */
1736                                                 if(driver->ob->type==OB_ARMATURE && driver->blocktype==ID_AR);
1737                                                 else driver->blocktype= ID_OB;
1738                                         }
1739                                 }                               
1740                                 DAG_scene_sort(G.scene);
1741                                 
1742                                 if(G.sipo->blocktype==ID_KE || G.sipo->blocktype==ID_AC) 
1743                                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1744                                 else
1745                                         DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
1746                         }
1747                 }
1748                 allqueue(REDRAWVIEW3D, 0);
1749                 allqueue(REDRAWIPO, 0);
1750                 allqueue(REDRAWBUTSEDIT, 0);
1751                 break;
1752         }
1753 }
1754
1755 static char *ipodriver_modeselect_pup(Object *ob)
1756 {
1757         static char string[265];
1758         char tmpstr[64];
1759         char formatstring[64];
1760         
1761         strcpy(string, "Driver type: %t");
1762         
1763         strcpy(formatstring, "|%s %%x%d %%i%d");
1764         
1765         if(ob) {
1766                 sprintf(tmpstr,formatstring,"Object",ID_OB, ICON_OBJECT);
1767                 strcat(string,tmpstr);
1768         }
1769         if(ob && ob->type==OB_ARMATURE) {
1770                 sprintf(tmpstr,formatstring,"Pose",ID_AR, ICON_POSE_DEHLT);
1771                 strcat(string,tmpstr);
1772         }
1773         
1774         return (string);
1775 }
1776
1777 static char *ipodriver_channelselect_pup(void)
1778 {
1779         static char string[1024];
1780         char *tmp;
1781         
1782         strcpy(string, "Driver channel: %t");
1783         tmp= string+strlen(string);
1784         
1785         tmp+= sprintf(tmp, "|Loc X %%x%d", OB_LOC_X);
1786         tmp+= sprintf(tmp, "|Loc Y %%x%d", OB_LOC_Y);
1787         tmp+= sprintf(tmp, "|Loc Z %%x%d", OB_LOC_Z);
1788         tmp+= sprintf(tmp, "|Rot X %%x%d", OB_ROT_X);
1789         tmp+= sprintf(tmp, "|Rot Y %%x%d", OB_ROT_Y);
1790         tmp+= sprintf(tmp, "|Rot Z %%x%d", OB_ROT_Z);
1791         tmp+= sprintf(tmp, "|Size X %%x%d", OB_SIZE_X);
1792         tmp+= sprintf(tmp, "|Size Y %%x%d", OB_SIZE_Y);
1793         tmp+= sprintf(tmp, "|Size Z %%x%d", OB_SIZE_Z);
1794         
1795         return (string);
1796 }
1797
1798 static void ipo_panel_properties(short cntrl)   // IPO_HANDLER_PROPERTIES
1799 {
1800         extern int totipo_curve;        // editipo.c
1801         uiBlock *block;
1802         EditIpo *ei;
1803         char name[48];
1804         
1805         block= uiNewBlock(&curarea->uiblocks, "ipo_panel_properties", UI_EMBOSS, UI_HELV, curarea->win);
1806         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
1807         uiSetPanelHandler(IPO_HANDLER_PROPERTIES);  // for close and esc
1808         if(uiNewPanel(curarea, block, "Transform Properties", "Ipo", 10, 230, 318, 204)==0) return;
1809
1810         /* this is new panel height, newpanel doesnt force new size on existing panels */
1811         uiNewPanelHeight(block, 204);
1812         
1813         /* driver buttons first */
1814         ei= get_active_editipo();
1815         if(ei) {
1816                 
1817                 sprintf(name, "Driven Channel: %s", ei->name);
1818                 uiDefBut(block, LABEL, 0, name,         10, 265, 200, 19, NULL, 1.0, 0.0, 0, 0, "");
1819                 
1820                 if(ei->icu && ei->icu->driver) {
1821                         IpoDriver *driver= ei->icu->driver;
1822                         
1823                         uiDefBut(block, BUT, B_IPO_DRIVER, "Remove",                            210,265,100,19, NULL, 0.0f, 0.0f, 0, 0, "Remove Driver for this Ipo Channel");
1824                         
1825                         uiBlockBeginAlign(block);
1826                         uiDefIDPoinBut(block, test_obpoin_but, B_IPO_DEPCHANGE, "OB:",  10, 240, 150, 20, &(driver->ob), "Driver Object");
1827                         if(driver->ob) {
1828                                 int icon=ICON_OBJECT;
1829                                 
1830                                 if(driver->ob->type==OB_ARMATURE && driver->blocktype==ID_AR) {
1831                                         icon = ICON_POSE_DEHLT;
1832                                         uiDefBut(block, TEX, B_IPO_REDR, "BO:",                         10,220,150,20, driver->name, 0, 31, 0, 0, "Bone name");
1833                                 }
1834                                 else driver->blocktype= ID_OB;  /* safety when switching object button */
1835                                 
1836                                 uiBlockBeginAlign(block);
1837                                 uiDefIconTextButS(block, MENU, B_IPO_DEPCHANGE, icon, 
1838                                                                   ipodriver_modeselect_pup(driver->ob), 165,240,145,20, &(driver->blocktype), 0, 0, 0, 0, "Driver type");
1839
1840                                 uiDefButS(block, MENU, B_IPO_REDR, 
1841                                                         ipodriver_channelselect_pup(),                  165,220,145,20, &(driver->adrcode), 0, 0, 0, 0, "Driver channel");
1842                         }
1843                         uiBlockEndAlign(block);
1844                 }
1845                 else {
1846                         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");
1847                 }
1848         }
1849         else 
1850                 uiDefBut(block, LABEL, 0, " ",          10, 265, 150, 19, NULL, 1.0, 0.0, 0, 0, "");
1851
1852         boundbox_ipo_curves(G.sipo);    // should not be needed... transform/draw calls should update
1853         
1854         /* note ranges for buttons below are idiot... we need 2 ranges, one for sliding scale, one for real clip */
1855         if(G.sipo->ipo && G.sipo->ipo->curve.first && totipo_curve) {
1856                 extern int totipo_vertsel;      // editipo.c
1857                 uiDefBut(block, LABEL, 0, "Visible curves",             10, 200, 150, 19, NULL, 1.0, 0.0, 0, 0, "");
1858                 
1859                 uiBlockBeginAlign(block);
1860                 uiDefButF(block, NUM, B_MUL_IPO, "Xmin:",               10, 180, 150, 19, &G.sipo->tot.xmin, G.sipo->tot.xmin-1000.0, MAXFRAMEF, 100, 0, "");
1861                 uiDefButF(block, NUM, B_MUL_IPO, "Xmax:",               160, 180, 150, 19, &G.sipo->tot.xmax, G.sipo->tot.ymin-1000.0, MAXFRAMEF, 100, 0, "");
1862                 
1863                 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, "");
1864                 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, "");
1865
1866                 /* SPEED BUTTON */
1867                 if(totipo_vertsel) {
1868                         uiBlockBeginAlign(block);
1869                         uiDefButF(block, NUM, B_IPO_NONE, "Speed:",             10,130,150,19, &hspeed, 0.0, 180.0, 1, 0, "");
1870                         uiDefBut(block, BUT, B_SETSPEED,"SET",                  160,130,50,19, 0, 0, 0, 0, 0, "");
1871                 }
1872         }
1873
1874         /* this one also does keypositions */
1875         if(G.sipo->ipo) ipo_editvertex_buts(block, G.sipo, -10000, MAXFRAMEF);
1876 }
1877
1878 static void ipo_blockhandlers(ScrArea *sa)
1879 {
1880         SpaceIpo *sipo= sa->spacedata.first;
1881         short a;
1882
1883         /* warning; blocks need to be freed each time, handlers dont remove (for ipo moved to drawipospace) */
1884
1885         for(a=0; a<SPACE_MAXHANDLER; a+=2) {
1886                 switch(sipo->blockhandler[a]) {
1887
1888                 case IPO_HANDLER_PROPERTIES:
1889                         ipo_panel_properties(sipo->blockhandler[a+1]);
1890                         break;
1891                 
1892                 }
1893                 /* clear action value for event */
1894                 sipo->blockhandler[a+1]= 0;
1895         }
1896         uiDrawBlocksPanels(sa, 0);
1897
1898 }
1899
1900
1901 void drawipospace(ScrArea *sa, void *spacedata)
1902 {
1903         SpaceIpo *sipo= sa->spacedata.first;
1904         View2D *v2d= &sipo->v2d;
1905         EditIpo *ei;
1906         float col[3];
1907         int ofsx, ofsy, a, disptype;
1908
1909         bwin_clear_viewmat(sa->win);    /* clear buttons view */
1910         glLoadIdentity();
1911         
1912         uiFreeBlocksWin(&sa->uiblocks, sa->win);        /* for panel handler to work */
1913         
1914         v2d->hor.xmax+=IPOBUTX;
1915         calc_scrollrcts(sa, G.v2d, sa->winx, sa->winy);
1916
1917         BIF_GetThemeColor3fv(TH_BACK, col);
1918         glClearColor(col[0], col[1], col[2], 0.0); 
1919
1920         if (sipo->pin)
1921                 glClearColor(col[0]+0.05,col[1],col[2], 0.0);   // litepink
1922         else
1923                 glClearColor(col[0],col[1],col[2], 0.0);
1924
1925         glClear(GL_COLOR_BUFFER_BIT);
1926         
1927         if(sa->winx>SCROLLB+10 && sa->winy>SCROLLH+10) {
1928                 if(v2d->scroll) {       
1929                         ofsx= sa->winrct.xmin;  // ivm mywin 
1930                         ofsy= sa->winrct.ymin;
1931                         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); 
1932                         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);
1933                 } 
1934         }
1935
1936         test_editipo(); /* test if current editipo is correct, make_editipo sets v2d->cur */
1937
1938         myortho2(v2d->cur.xmin, v2d->cur.xmax, v2d->cur.ymin, v2d->cur.ymax);
1939  
1940         if(sipo->editipo) {
1941                 
1942                 /* correct scale for degrees? */
1943                 disptype= -1;
1944                 ei= sipo->editipo;
1945                 for(a=0; a<sipo->totipo; a++, ei++) {
1946                         if(ei->flag & IPO_VISIBLE) {
1947                                 if(disptype== -1) disptype= ei->disptype;
1948                                 else if(disptype!=ei->disptype) disptype= 0;
1949                         }
1950                 }
1951                 
1952                 calc_ipogrid(); 
1953                 draw_ipogrid();
1954                 
1955                 calc_ipoverts(sipo);
1956                 
1957                 draw_cfra(sipo);
1958                 
1959                 /* ipokeys */
1960                 if(sipo->showkey) {
1961                         if(sipo->ipokey.first==0) make_ipokey();
1962                         draw_ipokey(sipo);
1963                 }
1964                 
1965                 if(sipo->blocktype==ID_KE) {
1966                         ei= sipo->editipo;
1967                         draw_key(sipo, ei->flag & IPO_VISIBLE);
1968                 }
1969
1970                 /* draw deselect */
1971                 draw_ipocurves(0);
1972                 draw_ipohandles(0);
1973                 draw_ipovertices(0);
1974                 
1975                 /* draw select */
1976                 draw_ipocurves(1);
1977                 draw_ipohandles(1);
1978                 draw_ipovertices(1);
1979                 
1980                 /* restore viewport */
1981                 mywinset(sa->win);
1982                 
1983                 if(sa->winx>SCROLLB+10 && sa->winy>SCROLLH+10) {
1984                         
1985                         /* ortho at pixel level sa */
1986                         myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
1987                         
1988                         if(v2d->scroll) {
1989                                 drawscroll(disptype);
1990                                 draw_solution(sipo);
1991                         }
1992                         
1993                         draw_ipobuts(sipo);
1994                 }
1995         }
1996         else {
1997                 calc_ipogrid();
1998                 draw_ipogrid();
1999         }
2000         
2001         myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
2002         draw_area_emboss(sa);
2003
2004         /* it is important to end a view in a transform compatible with buttons */
2005         bwin_scalematrix(sa->win, sipo->blockscale, sipo->blockscale, sipo->blockscale);
2006         /* only draw panels when relevant */
2007         if(sipo->editipo) ipo_blockhandlers(sa);
2008
2009         sa->win_swap= WIN_BACK_OK;
2010 }
2011
2012 void scroll_ipobuts()
2013 {
2014         int tot;
2015         short yo, mval[2];
2016         
2017         tot= 30+IPOBUTY*G.sipo->totipo;
2018         if(tot<curarea->winy) return;
2019         
2020         getmouseco_areawin(mval);
2021         yo= mval[1];
2022         
2023         while(get_mbut()&M_MOUSE) {
2024                 getmouseco_areawin(mval);
2025                 if(mval[1]!=yo) {
2026                         G.sipo->butofs+= (mval[1]-yo);
2027                         if(G.sipo->butofs<0) G.sipo->butofs= 0;
2028                         else if(G.sipo->butofs+curarea->winy>tot) G.sipo->butofs= tot-curarea->winy;
2029                         
2030                         scrarea_do_windraw(curarea);
2031                         screen_swapbuffers();
2032                         
2033                         yo= mval[1];
2034                 }
2035                 else BIF_wait_for_statechange();
2036         }
2037 }
2038
2039 /* total mess function, especially with mousewheel, needs cleanup badly (ton) */
2040 int view2dzoom(unsigned short event)
2041 {
2042         float fac, dx, dy, wtemp;
2043         short mval[2], mvalo[2];
2044         
2045         areawinset(curarea->win);       /* from buttons */
2046         curarea->head_swap= 0;
2047         getmouseco_areawin(mvalo);
2048         mval[0]= mvalo[0];
2049         mval[1]= mvalo[1];
2050         
2051         while( (get_mbut()&(L_MOUSE|M_MOUSE)) || (event==WHEELUPMOUSE) || (event==WHEELDOWNMOUSE) ) {
2052         
2053                 /* regular mousewheel:   zoom regular
2054                 * alt-shift mousewheel: zoom y only
2055                 * alt-ctrl mousewheel:  zoom x only
2056                 */
2057                 if (event==WHEELUPMOUSE) {
2058                         if(U.uiflag & USER_WHEELZOOMDIR)
2059                                 wtemp = -0.0375;
2060                         else
2061                                 wtemp = 0.03;
2062                         if(curarea->spacetype!=SPACE_BUTS) wtemp*= 3;
2063                         
2064                         dx= (float)(wtemp*(G.v2d->cur.xmax-G.v2d->cur.xmin));
2065                         dy= (float)(wtemp*(G.v2d->cur.ymax-G.v2d->cur.ymin));
2066                         
2067                         switch (G.qual & (LR_CTRLKEY|LR_SHIFTKEY|LR_ALTKEY)) {
2068                         case 0:
2069                                 break;
2070                         case (LR_SHIFTKEY|LR_ALTKEY):
2071                                 dx = 0;
2072                                 break;
2073                         case (LR_CTRLKEY|LR_ALTKEY):
2074                                 dy = 0;
2075                                 break;
2076                         default:
2077                                 if(curarea->spacetype==SPACE_BUTS);     // exception
2078                                 else return 0;
2079                                 break;
2080                         }
2081                 }
2082                 else if (event==WHEELDOWNMOUSE) {
2083                         if(U.uiflag & USER_WHEELZOOMDIR)
2084                                 wtemp = 0.03;
2085                         else
2086                                 wtemp = -0.0375;
2087                         if(curarea->spacetype!=SPACE_BUTS) wtemp*= 3;
2088                         
2089                         dx= (float)(wtemp*(G.v2d->cur.xmax-G.v2d->cur.xmin));
2090                         dy= (float)(wtemp*(G.v2d->cur.ymax-G.v2d->cur.ymin));
2091                         
2092                         switch (G.qual & (LR_CTRLKEY|LR_SHIFTKEY|LR_ALTKEY)) {
2093                                 case 0:
2094                                 break;
2095                         case (LR_SHIFTKEY|LR_ALTKEY):
2096                                 dx = 0;
2097                                 break;
2098                         case (LR_CTRLKEY|LR_ALTKEY):
2099                                 dy = 0;
2100                                 break;
2101                         default:
2102                                 if(curarea->spacetype==SPACE_BUTS);
2103                                 else return 0;
2104                                 break;
2105                         }
2106                 }
2107                 else {
2108                         getmouseco_areawin(mval);
2109                         if(U.viewzoom==USER_ZOOM_SCALE) {
2110                                 float dist;
2111                                 
2112                                 dist = (G.v2d->mask.xmax - G.v2d->mask.xmin)/2.0;
2113                                 dx= 1.0-(fabs(mvalo[0]-dist)+2.0)/(fabs(mval[0]-dist)+2.0);
2114                                 dx*= 0.5*(G.v2d->cur.xmax-G.v2d->cur.xmin);
2115
2116                                 dist = (G.v2d->mask.ymax - G.v2d->mask.ymin)/2.0;
2117                                 dy= 1.0-(fabs(mvalo[1]-dist)+2.0)/(fabs(mval[1]-dist)+2.0);
2118                                 dy*= 0.5*(G.v2d->cur.ymax-G.v2d->cur.ymin);
2119         
2120                         }
2121                         else {
2122                                 fac= 0.01*(mval[0]-mvalo[0]);
2123                                 dx= fac*(G.v2d->cur.xmax-G.v2d->cur.xmin);
2124                                 fac= 0.01*(mval[1]-mvalo[1]);
2125                                 dy= fac*(G.v2d->cur.ymax-G.v2d->cur.ymin);
2126                                 
2127                                 if(U.viewzoom==USER_ZOOM_CONT) {
2128                                         dx/= 20.0;
2129                                         dy/= 20.0;
2130                                 }
2131                         }
2132                 }
2133                 if(ELEM(event, WHEELUPMOUSE, WHEELDOWNMOUSE) || mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
2134                         
2135                         if(U.viewzoom!=USER_ZOOM_CONT) {
2136                                 mvalo[0]= mval[0];
2137                                 mvalo[1]= mval[1];
2138                         }
2139                         
2140                         if( ELEM(curarea->spacetype, SPACE_NLA, SPACE_ACTION) ) {
2141                                 if(mvalo[0] < G.v2d->mask.xmin) {
2142                                         G.v2d->cur.ymin+= dy;
2143                                         G.v2d->cur.ymax-= dy;
2144                                 }
2145                                 else {
2146                                         G.v2d->cur.xmin+= dx;
2147                                         G.v2d->cur.xmax-= dx;
2148                                 }
2149                         }
2150                         else if (ELEM3(curarea->spacetype, SPACE_SEQ, SPACE_SOUND, SPACE_TIME)) {
2151                                 G.v2d->cur.xmin+= dx;
2152                                 G.v2d->cur.xmax-= dx;
2153                         }
2154                         else {
2155                                 G.v2d->cur.xmin+= dx;
2156                                 G.v2d->cur.xmax-= dx;
2157                                 G.v2d->cur.ymin+= dy;
2158                                 G.v2d->cur.ymax-= dy;
2159                         }
2160                 
2161                         test_view2d(G.v2d, curarea->winx, curarea->winy);       /* cur min max rects */
2162                         scrarea_do_windraw(curarea);
2163                         screen_swapbuffers();
2164                 }
2165                 else BIF_wait_for_statechange();
2166                 /* return if we were using the mousewheel
2167                 */
2168                 if ( (event==WHEELUPMOUSE) || (event==WHEELDOWNMOUSE) ) return 1;
2169         }
2170         return 1;
2171 }
2172
2173 void center_currframe(void)
2174 {
2175         /* place the current frame in the
2176          * center of the 2D window.
2177          */
2178         float width;
2179   
2180         areawinset(curarea->win);
2181         curarea->head_swap= 0;
2182
2183         width = G.v2d->cur.xmax - G.v2d->cur.xmin;
2184         G.v2d->cur.xmin = CFRA - 0.5*(width);
2185         G.v2d->cur.xmax = CFRA + 0.5*(width);
2186
2187         test_view2d(G.v2d, curarea->winx, curarea->winy);
2188         scrarea_do_windraw(curarea);
2189         screen_swapbuffers();
2190         curarea->head_swap= 0;
2191 }
2192
2193 /* total mess function, especially with mousewheel, needs cleanup badly (ton) */
2194 int view2dmove(unsigned short event)
2195 {
2196         /* return 1 when something was done */
2197         float facx=0.0, facy=0.0, dx, dy, left=1.0, right=1.0;
2198         short mval[2], mvalo[2], leftret=1, mousebut;
2199         
2200         /* init */
2201         scrarea_do_windraw(curarea);
2202         curarea->head_swap= 0;
2203
2204         /* try to do some zooming if the
2205          * middlemouse and ctrl are pressed
2206          * or if the mousewheel is being used.
2207          * Return if zooming was done.
2208          */
2209         
2210         /* check for left mouse / right mouse button select */
2211         if (U.flag & USER_LMOUSESELECT) mousebut = R_MOUSE;
2212                 else mousebut = L_MOUSE;
2213         
2214         if ( (G.qual & LR_CTRLKEY) || (event==WHEELUPMOUSE) || (event==WHEELDOWNMOUSE) ) {
2215                 /* patch for oops & buttonswin, standard scroll no zoom */
2216                 if(curarea->spacetype==SPACE_OOPS) {
2217                         SpaceOops *soops= curarea->spacedata.first;
2218                         if(soops->type==SO_OUTLINER);
2219                         else if (view2dzoom(event)) {
2220                                 curarea->head_swap= 0;
2221                                 return 0;
2222                         }
2223                 }
2224                 else if(curarea->spacetype==SPACE_BUTS && (G.qual & LR_CTRLKEY)==0);
2225                 else if (view2dzoom(event)) {
2226                         curarea->head_swap= 0;
2227                         return 0;
2228                 }
2229         }
2230         
2231         /* test where mouse is */
2232         getmouseco_areawin(mvalo);
2233         
2234         if ELEM7(curarea->spacetype, SPACE_IPO, SPACE_SEQ, SPACE_OOPS, SPACE_SOUND, SPACE_ACTION, SPACE_NLA, SPACE_TIME) 
2235                 {
2236
2237                         if( BLI_in_rcti(&G.v2d->mask, (int)mvalo[0], (int)mvalo[1]) ) {
2238                                 facx= (G.v2d->cur.xmax-G.v2d->cur.xmin)/(float)(G.v2d->mask.xmax-G.v2d->mask.xmin);
2239                                 facy= (G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)(G.v2d->mask.ymax-G.v2d->mask.ymin);
2240                         }
2241                         /* stoopid exception to allow scroll in lefthand side */
2242                         else if(curarea->spacetype==SPACE_ACTION && BLI_in_rcti(&G.v2d->mask, ACTWIDTH+(int)mvalo[0], (int)mvalo[1]) ) {
2243                                 facx= 0.0f;
2244                                 facy= (G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)(G.v2d->mask.ymax-G.v2d->mask.ymin);
2245                         }
2246                         else if(curarea->spacetype==SPACE_NLA && BLI_in_rcti(&G.v2d->mask, NLAWIDTH+(int)mvalo[0], (int)mvalo[1]) ) {
2247                                 facx= 0.0f;
2248                                 facy= (G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)(G.v2d->mask.ymax-G.v2d->mask.ymin);
2249                         }
2250                         else if(IN_2D_VERT_SCROLL((int)mvalo)) {
2251                                 facy= -(G.v2d->tot.ymax-G.v2d->tot.ymin)/(float)(G.v2d->mask.ymax-G.v2d->mask.ymin);
2252                                 if(get_mbut() & mousebut) {
2253                                         /* which part of scrollbar should move? */
2254                                         if(mvalo[1]< (vertymin+vertymax)/2 ) right= 0.0;
2255                                         else left= 0.0;
2256                                         leftret= 0;
2257                                 }
2258                         }
2259                         else if(IN_2D_HORIZ_SCROLL((int)mvalo)) {
2260                                 facx= -(G.v2d->tot.xmax-G.v2d->tot.xmin)/(float)(G.v2d->mask.xmax-G.v2d->mask.xmin);
2261                                 if(get_mbut() & mousebut) {
2262                                         /* which part of scrollbar should move? */
2263                                         if(mvalo[0]< (horxmin+horxmax)/2 ) right= 0.0;
2264                                         else left= 0.0;
2265                                         leftret= 0;
2266                                 }
2267                         }
2268                 }
2269                 else {
2270                         facx= (G.v2d->cur.xmax-G.v2d->cur.xmin)/(float)(curarea->winx);
2271                         facy= (G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)(curarea->winy);         
2272                 }
2273                 
2274                 /* no x move in outliner */
2275                 if(curarea->spacetype==SPACE_OOPS && G.v2d->scroll) facx= 0.0;
2276                 
2277                 /* no y move in audio & time */
2278                 if ELEM(curarea->spacetype, SPACE_SOUND, SPACE_TIME) facy= 0.0;
2279                 
2280                 if(get_mbut() & mousebut && leftret) return 0;
2281                 if(facx==0.0 && facy==0.0) return 1;
2282                 
2283     while( (get_mbut()&(L_MOUSE|M_MOUSE)) || 
2284            (event==WHEELUPMOUSE) ||
2285            (event==WHEELDOWNMOUSE) ) {
2286
2287       /* If the mousewheel is used with shift key
2288        * the scroll up and down. If the mousewheel
2289        * is used with the ctrl key then scroll left
2290        * and right.
2291        */
2292                 if (event==WHEELUPMOUSE || event==WHEELDOWNMOUSE) {
2293                         if(event==WHEELDOWNMOUSE) {     
2294                                 facx= -facx; facy= -facy;
2295                         }
2296                         switch (G.qual & (LR_CTRLKEY|LR_SHIFTKEY|LR_ALTKEY)) {
2297                         case (LR_SHIFTKEY):
2298                                 dx = 0.0;
2299                                 dy= facy*20.0;
2300                                 break;
2301                         case (LR_CTRLKEY):
2302                                 dx= facx*20.0;
2303                                 dy = 0.0;
2304                                 break;
2305                         default:
2306                                 if(curarea->spacetype==SPACE_OOPS) {
2307                                         dx= 0.0;
2308                                         dy= facy*20;
2309                                 }
2310                                 else if(curarea->spacetype==SPACE_BUTS) {
2311                                         if(G.buts->align==BUT_HORIZONTAL) {
2312                                                 dx= facx*30; dy= 0.0;
2313                                         } else {
2314                                                 dx= 0.0; dy= facy*30;
2315                                         }
2316                                 }
2317                                 else return 0;
2318                                 break;
2319                         }
2320                         mval[0]= mvalo[0]+1; // force redraw below
2321                         mval[1]= mvalo[1]+1;
2322                 }
2323                 else {
2324                         getmouseco_areawin(mval);
2325                         dx= facx*(mvalo[0]-mval[0]);
2326                         dy= facy*(mvalo[1]-mval[1]);
2327                 }
2328
2329                 if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
2330
2331                         G.v2d->cur.xmin+= left*dx;
2332                         G.v2d->cur.xmax+= right*dx;
2333                         G.v2d->cur.ymin+= left*dy;
2334                         G.v2d->cur.ymax+= right*dy;
2335                                 
2336                         test_view2d(G.v2d, curarea->winx, curarea->winy);
2337                                 
2338                         scrarea_do_windraw(curarea);
2339                         screen_swapbuffers();
2340                                 
2341                         mvalo[0]= mval[0];
2342                         mvalo[1]= mval[1];
2343                                 
2344                 }
2345                 else BIF_wait_for_statechange();
2346                         /* return if we were using the mousewheel
2347                         */
2348                 if ( (event==WHEELUPMOUSE) || (event==WHEELDOWNMOUSE) ) return 1;
2349         }
2350
2351     curarea->head_swap= 0;
2352     return 1;
2353 }
2354
2355 void view2dborder(void)
2356 {
2357         
2358 }
2359
2360 EditIpo *select_proj_ipo(rctf *rectf, int event)
2361 {
2362         EditIpo *ei;
2363         float xmin, ymin, xmax, ymax;
2364         /* this was IGLuint, but it's a useless typedef... */
2365         GLuint buffer[MAXPICKBUF];
2366         int a, b;
2367         int hits;
2368         unsigned int code;
2369         short mval[2];
2370         
2371         G.f |= G_PICKSEL;
2372         
2373         if(rectf==0) {
2374                 getmouseco_areawin(mval);
2375                 
2376                 mval[0]-= 6; mval[1]-= 6;
2377                 areamouseco_to_ipoco(G.v2d, mval, &xmin, &ymin);
2378                 mval[0]+= 12; mval[1]+= 12;
2379                 areamouseco_to_ipoco(G.v2d, mval, &xmax, &ymax);
2380                 
2381                 myortho2(xmin, xmax, ymin, ymax);
2382         }
2383         else myortho2(rectf->xmin, rectf->xmax, rectf->ymin, rectf->ymax);
2384         
2385         glSelectBuffer( MAXPICKBUF, buffer); 
2386         glRenderMode(GL_SELECT);
2387         glInitNames();  /* whatfor? but otherwise it does not work */
2388         glPushName(-1);
2389         
2390         /* get rid of buttons view */
2391         glPushMatrix();
2392         glLoadIdentity();
2393         
2394         init_pickselcode();     /* drawipo.c */
2395         draw_ipocurves(0);      
2396         
2397         /* restore buttons view */
2398         glPopMatrix();
2399
2400         G.f -= G_PICKSEL;
2401         
2402         hits= glRenderMode(GL_RENDER);
2403         glPopName();    /* see above (pushname) */
2404         if(hits<1) return 0;
2405         
2406         code= 1;
2407         ei= G.sipo->editipo;
2408         for(a=0; a<G.sipo->totipo; a++, ei++) {
2409                 if ISPOIN(ei, icu, flag & IPO_VISIBLE) {
2410                         if(rectf) {
2411                                 for(b=0; b<hits; b++) {
2412                                         /* conversion for glSelect */
2413                                         if(code == buffer[ (4 * b) + 3] ) {
2414                                                 if(event==LEFTMOUSE) ei->flag |= IPO_SELECT;
2415                                                 else ei->flag &= ~IPO_SELECT;
2416                                                 ei->icu->flag= ei->flag;
2417                                         }
2418                                 }
2419                         }
2420                         else {
2421                                 /* also conversion for glSelect */
2422                                 if(code==buffer[ 3 ]) return ei;
2423                         }
2424                         code++;
2425                 }
2426         }
2427         return 0;
2428 }
2429