- further work on theme colors:
[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 #include "BLI_winstuff.h"
46 #endif   
47
48 #include "BMF_Api.h"
49
50 #include "BLI_blenlib.h"
51
52 #include "DNA_curve_types.h"
53 #include "DNA_ipo_types.h"
54 #include "DNA_key_types.h"
55 #include "DNA_object_types.h"
56 #include "DNA_scene_types.h"
57 #include "DNA_screen_types.h"
58 #include "DNA_space_types.h"
59 #include "DNA_sequence_types.h"
60 #include "DNA_userdef_types.h"
61
62 #include "BKE_utildefines.h"
63 #include "BKE_curve.h"
64 #include "BKE_ipo.h"
65 #include "BKE_global.h"
66
67 #include "BIF_gl.h"
68 #include "BIF_resources.h"
69 #include "BIF_screen.h"
70 #include "BIF_interface.h"
71 #include "BIF_mywindow.h"
72 #include "BIF_space.h"
73
74 #include "BSE_drawipo.h"
75 #include "BSE_view.h"
76 #include "BSE_editipo.h"
77 #include "BSE_editaction_types.h"
78 #include "BSE_editnla_types.h"
79
80 #include "mydevice.h"
81 #include "ipo.h" /* retains old stuff */
82 #include "blendef.h"
83
84 /* local define... also used in editipo ... */
85 #define ISPOIN(a, b, c)                       ( (a->b) && (a->c) )  
86 #define ISPOIN3(a, b, c, d)           ( (a->b) && (a->c) && (a->d) )
87 #define ISPOIN4(a, b, c, d, e)        ( (a->b) && (a->c) && (a->d) && (a->e) )   
88
89 #define IPOBUTX 65
90 #define IPOSTEP 35                      /* minimum pixels per gridstep */
91
92 static float ipogrid_dx, ipogrid_dy, ipogrid_startx, ipogrid_starty;
93 static int ipomachtx, ipomachty;
94
95 static int vertymin, vertymax, horxmin, horxmax;        /* globals om LEFTMOUSE op scrollbar te testen */
96
97 extern short ACTWIDTH;
98
99 static void scroll_prstr(float x, float y, float val, char dir, int disptype)
100 {
101         int len, macht;
102         char str[32];
103         
104         if(dir=='v') {
105                 macht= ipomachty;
106                 if ELEM(disptype, IPO_DISPDEGR, IPO_DISPTIME) {
107                         macht+=1;
108                         val *= 10;
109                 }
110         }
111         else macht= ipomachtx;
112         
113         if (macht<=0) sprintf(str, "%.*f", 1-macht, val);
114         else sprintf(str, "%d", (int)val);
115         
116         len= strlen(str);
117         if(dir=='h') x-= 4*len;
118         
119         if(dir=='v' && disptype==IPO_DISPDEGR) {
120                 str[len]= 186; /* Degree symbol */
121                 str[len+1]= 0;
122         }
123         
124         glRasterPos2f(x,  y);
125         BMF_DrawString(G.fonts, str);
126 }
127
128 static void step_to_grid(float *step, int *macht)
129 {
130         float loga, rem;
131         
132         /* try to write step as a power of 10 */
133         
134         loga= log10(*step);
135         *macht= (int)(loga);
136         
137         rem= loga- *macht;
138         rem= pow(10.0, rem);
139         
140         if(loga<0.0) {
141                 if(rem < 0.2) rem= 0.2;
142                 else if(rem < 0.5) rem= 0.5;
143                 else rem= 1.0;
144                 
145                 *step= rem*pow(10.0, (float)*macht);
146         }
147         else {
148                 if(rem < 2.0) rem= 2.0;
149                 else if(rem < 5.0) rem= 5.0;
150                 else rem= 10.0;
151                 
152                 *step= rem*pow(10.0, (float)*macht);
153                 
154                 (*macht)++;
155         }
156         
157 }
158
159 void calc_ipogrid()
160 {
161         float space, pixels;
162         
163         /* rule: gridstep is minimal IPOSTEP pixels */
164         /* how large is IPOSTEP pixels? */
165         
166         if(G.v2d==0) return;
167         
168         space= G.v2d->cur.xmax - G.v2d->cur.xmin;
169         pixels= G.v2d->mask.xmax-G.v2d->mask.xmin;
170         
171         ipogrid_dx= IPOSTEP*space/pixels;
172         step_to_grid(&ipogrid_dx, &ipomachtx);
173         
174         if ELEM(curarea->spacetype, SPACE_SEQ, SPACE_SOUND) {
175                 if(ipogrid_dx < 0.1) ipogrid_dx= 0.1;
176                 ipomachtx-= 2;
177                 if(ipomachtx<-2) ipomachtx= -2;
178         }
179         
180         space= (G.v2d->cur.ymax - G.v2d->cur.ymin);
181         pixels= curarea->winy;
182         ipogrid_dy= IPOSTEP*space/pixels;
183         step_to_grid(&ipogrid_dy, &ipomachty);
184         
185         if ELEM(curarea->spacetype, SPACE_SEQ, SPACE_SOUND) {
186                 if(ipogrid_dy < 1.0) ipogrid_dy= 1.0;
187                 if(ipomachty<1) ipomachty= 1;
188         }
189         
190         ipogrid_startx= G.v2d->cur.xmin-fmod(G.v2d->cur.xmin, ipogrid_dx);
191         if(G.v2d->cur.xmin<0.0) ipogrid_startx-= ipogrid_dx;
192         ipogrid_starty= (G.v2d->cur.ymin-fmod(G.v2d->cur.ymin, ipogrid_dy));
193         if(G.v2d->cur.ymin<0.0) ipogrid_starty-= ipogrid_dy;
194         
195 }
196
197 void draw_ipogrid(void)
198 {
199         float vec1[2], vec2[2];
200         int a, step;
201         
202         vec1[0]= vec2[0]= ipogrid_startx;
203         vec1[1]= ipogrid_starty;
204         vec2[1]= G.v2d->cur.ymax;
205         
206         step= (G.v2d->mask.xmax-G.v2d->mask.xmin+1)/IPOSTEP;
207         
208         if(curarea->spacetype==SPACE_SOUND) glColor3ub(0x70, 0x70, 0x60);
209         else BIF_ThemeColor(curarea, TH_GRID);
210         
211         for(a=0; a<step; a++) {
212                 glBegin(GL_LINE_STRIP);
213                 glVertex2fv(vec1); glVertex2fv(vec2);
214                 glEnd();
215                 vec2[0]= vec1[0]+= ipogrid_dx;
216         }
217         
218         vec2[0]= vec1[0]-= 0.5*ipogrid_dx;
219         
220         if(curarea->spacetype==SPACE_SOUND) glColor3ub(0x80, 0x80, 0x70);
221         else  BIF_ThemeColorShade(curarea, TH_GRID, 16);
222         
223         step++;
224         for(a=0; a<=step; a++) {
225                 glBegin(GL_LINE_STRIP);
226                 glVertex2fv(vec1); glVertex2fv(vec2);
227                 glEnd();
228                 vec2[0]= vec1[0]-= ipogrid_dx;
229         }
230         
231         if(curarea->spacetype!=SPACE_SOUND && curarea->spacetype!=SPACE_ACTION && curarea->spacetype!=SPACE_NLA) {
232                 vec1[0]= ipogrid_startx;
233                 vec1[1]= vec2[1]= ipogrid_starty;
234                 vec2[0]= G.v2d->cur.xmax;
235                 
236                 step= (curarea->winy+1)/IPOSTEP;
237                 
238                 BIF_ThemeColor(curarea, TH_GRID);
239                 for(a=0; a<=step; a++) {
240                         glBegin(GL_LINE_STRIP);
241                         glVertex2fv(vec1); glVertex2fv(vec2);
242                         glEnd();
243                         vec2[1]= vec1[1]+= ipogrid_dy;
244                 }
245                 vec2[1]= vec1[1]-= 0.5*ipogrid_dy;
246                 step++;
247                 
248                 if(curarea->spacetype==SPACE_IPO) {
249                         BIF_ThemeColorShade(curarea, TH_GRID, 16);
250                         for(a=0; a<step; a++) {
251                                 glBegin(GL_LINE_STRIP);
252                                 glVertex2fv(vec1); glVertex2fv(vec2);
253                                 glEnd();
254                                 vec2[1]= vec1[1]-= ipogrid_dy;
255                         }
256                 }
257         }
258         
259         BIF_ThemeColorShade(curarea, TH_GRID, -50);
260         
261         if (curarea->spacetype!=SPACE_ACTION && curarea->spacetype!=SPACE_NLA)
262         {       /* Horizontal axis */
263                 vec1[0]= G.v2d->cur.xmin;
264                 vec2[0]= G.v2d->cur.xmax;
265                 vec1[1]= vec2[1]= 0.0;
266                 glBegin(GL_LINE_STRIP);
267                 
268                 glVertex2fv(vec1);
269                 glVertex2fv(vec2);
270                 
271                 glEnd();
272         }
273         
274         /* Vertical axis */
275         
276         vec1[1]= G.v2d->cur.ymin;
277         vec2[1]= G.v2d->cur.ymax;
278         vec1[0]= vec2[0]= 0.0;
279         glBegin(GL_LINE_STRIP);
280         glVertex2fv(vec1); glVertex2fv(vec2);
281         glEnd();
282         
283         /* Limits box */
284         if(curarea->spacetype==SPACE_IPO) {
285                 if(G.sipo->blocktype==ID_SEQ) {
286                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
287                         glRectf(0.0,  0.0,  100.0,  1.0); 
288                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
289                 }
290                 else if(ELEM(G.sipo->blocktype, ID_CU, IPO_CO)) {
291                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
292                         glRectf(0.0,  1.0,  G.v2d->cur.xmax,  1.0); 
293                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
294                 }
295         }
296 }
297
298 void areamouseco_to_ipoco(View2D *v2d, short *mval, float *x, float *y)
299 {
300         float div, ofs;
301         
302         div= v2d->mask.xmax-v2d->mask.xmin;
303         ofs= v2d->mask.xmin;
304         
305         *x= v2d->cur.xmin+ (v2d->cur.xmax-v2d->cur.xmin)*(mval[0]-ofs)/div;
306         
307         div= v2d->mask.ymax-v2d->mask.ymin;
308         ofs= v2d->mask.ymin;
309         
310         *y= v2d->cur.ymin+ (v2d->cur.ymax-v2d->cur.ymin)*(mval[1]-ofs)/div;
311 }
312
313 void ipoco_to_areaco(View2D *v2d, float *vec, short *mval)
314 {
315         float x, y;
316         
317         mval[0]= 3200;
318         
319         x= (vec[0] - v2d->cur.xmin)/(v2d->cur.xmax-v2d->cur.xmin);
320         y= (vec[1] - v2d->cur.ymin)/(v2d->cur.ymax-v2d->cur.ymin);
321
322         if(x>=0.0 && x<=1.0) {
323                 if(y>=0.0 && y<=1.0) {
324                         mval[0]= v2d->mask.xmin + x*(v2d->mask.xmax-v2d->mask.xmin);
325                         mval[1]= v2d->mask.ymin + y*(v2d->mask.ymax-v2d->mask.ymin);
326                 }
327         }
328 }
329
330 void ipoco_to_areaco_noclip(View2D *v2d, float *vec, short *mval)
331 {
332         float x, y;
333         
334         x= (vec[0] - v2d->cur.xmin)/(v2d->cur.xmax-v2d->cur.xmin);
335         y= (vec[1] - v2d->cur.ymin)/(v2d->cur.ymax-v2d->cur.ymin);
336         
337         x= v2d->mask.xmin + x*(v2d->mask.xmax-v2d->mask.xmin);
338         y= v2d->mask.ymin + y*(v2d->mask.ymax-v2d->mask.ymin);
339         
340         if(x<-32760) mval[0]= -32760;
341         else if(x>32760) mval[0]= 32760;
342         else mval[0]= x;
343         
344         if(y<-32760) mval[1]= -32760;
345         else if(y>32760) mval[1]= 32760;
346         else mval[1]= y;
347 }
348
349 int in_ipo_buttons(void)
350 {
351         short mval[2];
352         
353         getmouseco_areawin(mval);
354         
355         if(mval[0]< G.v2d->mask.xmax) return 0;
356         else return 1;
357 }
358
359
360 void view2d_zoom(View2D *v2d, float factor, int winx, int winy) {
361         float dx= factor*(v2d->cur.xmax-v2d->cur.xmin);
362         float dy= factor*(v2d->cur.ymax-v2d->cur.ymin);
363         v2d->cur.xmin+= dx;
364         v2d->cur.xmax-= dx;
365         v2d->cur.ymin+= dy;
366         v2d->cur.ymax-= dy;
367         test_view2d(v2d, winx, winy);
368 }
369
370
371 void test_view2d(View2D *v2d, int winx, int winy)
372 {
373         /* cur is not allowed to be larger than max, smaller than min, or outside of tot */
374         rctf *cur, *tot;
375         float dx, dy, temp, fac, zoom;
376         
377         cur= &v2d->cur;
378         tot= &v2d->tot;
379         
380         dx= cur->xmax-cur->xmin;
381         dy= cur->ymax-cur->ymin;
382
383
384         /* Reevan's test */
385         if (v2d->keepzoom & V2D_LOCKZOOM_Y)
386                 v2d->cur.ymax=v2d->cur.ymin+((float)winy);
387
388         if (v2d->keepzoom & V2D_LOCKZOOM_X)
389                 v2d->cur.xmax=v2d->cur.xmin+((float)winx);
390
391         if(v2d->keepzoom) {
392                 
393                 zoom= ((float)winx)/dx;
394                 
395                 if(zoom<v2d->minzoom || zoom>v2d->maxzoom) {
396                         if(zoom<v2d->minzoom) fac= zoom/v2d->minzoom;
397                         else fac= zoom/v2d->maxzoom;
398                         
399                         dx*= fac;
400                         temp= 0.5*(cur->xmax+cur->xmin);
401                         
402                         cur->xmin= temp-0.5*dx;
403                         cur->xmax= temp+0.5*dx;
404                 }
405                 
406                 zoom= ((float)winy)/dy;
407                 
408                 if(zoom<v2d->minzoom || zoom>v2d->maxzoom) {
409                         if(zoom<v2d->minzoom) fac= zoom/v2d->minzoom;
410                         else fac= zoom/v2d->maxzoom;
411                         
412                         dy*= fac;
413                         temp= 0.5*(cur->ymax+cur->ymin);
414                         cur->ymin= temp-0.5*dy;
415                         cur->ymax= temp+0.5*dy;
416                 }
417         }
418
419         if(v2d->keepaspect) {
420                 dx= (cur->ymax-cur->ymin)/(cur->xmax-cur->xmin);
421                 dy= ((float)winy)/((float)winx);
422                 
423                 /* dx/dy is the total aspect */
424
425                 if( dx/dy > 1.0) {
426                         
427                         /* portrait window: correct for x */
428                         dx= cur->ymax-cur->ymin;
429                         temp= (cur->xmax+cur->xmin);
430                         
431                         cur->xmin= temp/2.0 - 0.5*dx/dy;
432                         cur->xmax= temp/2.0 + 0.5*dx/dy;
433                 }
434                 else {
435                         dx= cur->xmax-cur->xmin;
436                         temp= (cur->ymax+cur->ymin);
437                         
438                         cur->ymin= temp/2.0 - 0.5*dy*dx;
439                         cur->ymax= temp/2.0 + 0.5*dy*dx;
440                 }
441         }
442         
443         if(v2d->keeptot) {
444                 dx= cur->xmax-cur->xmin;
445                 dy= cur->ymax-cur->ymin;
446                 
447                 if(dx > tot->xmax-tot->xmin) {
448                         if(v2d->keepzoom==0) {
449                                 if(cur->xmin<tot->xmin) cur->xmin= tot->xmin;
450                                 if(cur->xmax>tot->xmax) cur->xmax= tot->xmax;
451                         }
452                         else {
453                                 if(cur->xmax < tot->xmax) {
454                                         dx= tot->xmax-cur->xmax;
455                                         cur->xmin+= dx;
456                                         cur->xmax+= dx;
457                                 }
458                                 else if(cur->xmin > tot->xmin) {
459                                         dx= cur->xmin-tot->xmin;
460                                         cur->xmin-= dx;
461                                         cur->xmax-= dx;
462                                 }
463                         }
464                 }
465                 else {
466                         if(cur->xmin < tot->xmin) {
467                                 dx= tot->xmin-cur->xmin;
468                                 cur->xmin+= dx;
469                                 cur->xmax+= dx;
470                         }
471                         else if(cur->xmax > tot->xmax) {
472                                 dx= cur->xmax-tot->xmax;
473                                 cur->xmin-= dx;
474                                 cur->xmax-= dx;
475                         }
476                 }
477                 
478                 if(dy > tot->ymax-tot->ymin) {
479                         if(v2d->keepzoom==0) {
480                                 if(cur->ymin<tot->ymin) cur->ymin= tot->ymin;
481                                 if(cur->ymax>tot->ymax) cur->ymax= tot->ymax;
482                         }
483                         else {
484                                 if(cur->ymax < tot->ymax) {
485                                         dy= tot->ymax-cur->ymax;
486                                         cur->ymin+= dy;
487                                         cur->ymax+= dy;
488                                 }
489                                 else if(cur->ymin > tot->ymin) {
490                                         dy= cur->ymin-tot->ymin;
491                                         cur->ymin-= dy;
492                                         cur->ymax-= dy;
493                                 }
494                         }
495                 }
496                 else {
497                         if(cur->ymin < tot->ymin) {
498                                 dy= tot->ymin-cur->ymin;
499                                 cur->ymin+= dy;
500                                 cur->ymax+= dy;
501                         }
502                         else if(cur->ymax > tot->ymax) {
503                                 dy= cur->ymax-tot->ymax;
504                                 cur->ymin-= dy;
505                                 cur->ymax-= dy;
506                         }
507                 }
508         }
509 }
510
511
512 void calc_scrollrcts(View2D *v2d, int winx, int winy)
513 {
514         v2d->mask.xmin= v2d->mask.ymin= 0;
515         v2d->mask.xmax= winx;
516         v2d->mask.ymax= winy;
517         
518         if(curarea->spacetype==SPACE_ACTION) {
519                 v2d->mask.xmin+= ACTWIDTH;
520                 v2d->hor.xmin+=ACTWIDTH;
521         }
522         else if(curarea->spacetype==SPACE_NLA){
523                 v2d->mask.xmin+= NLAWIDTH;
524                 v2d->hor.xmin+=NLAWIDTH;
525         }
526         else if(curarea->spacetype==SPACE_IPO) {
527                 v2d->mask.xmax-= IPOBUTX;
528                 
529                 if(v2d->mask.xmax<IPOBUTX)
530                         v2d->mask.xmax= winx;
531         }
532         
533         if(v2d->scroll) {
534                 if(v2d->scroll & L_SCROLL) {
535                         v2d->vert= v2d->mask;
536                         v2d->vert.xmax= SCROLLB;
537                         v2d->mask.xmin= SCROLLB;
538                 }
539                 else if(v2d->scroll & R_SCROLL) {
540                         v2d->vert= v2d->mask;
541                         v2d->vert.xmin= v2d->vert.xmax-SCROLLB;
542                         v2d->mask.xmax= v2d->vert.xmin;
543                 }
544                 
545                 if(v2d->scroll & B_SCROLL) {
546                         v2d->hor= v2d->mask;
547                         v2d->hor.ymax= SCROLLH;
548                         v2d->mask.ymin= SCROLLH;
549                 }
550                 else if(v2d->scroll & T_SCROLL) {
551                         v2d->hor= v2d->mask;
552                         v2d->hor.ymin= v2d->hor.ymax-SCROLLH;
553                         v2d->mask.ymax= v2d->hor.ymin;
554                 }
555         }
556 }
557
558         /* draws a line in left vertical scrollbar at the given height */
559 static void draw_solution_line(View2D *v2d, float h)
560 {
561         float vec[2];
562         short mval[2];
563
564         vec[0]= v2d->cur.xmin;
565         vec[1]= h;
566         ipoco_to_areaco(v2d, vec, mval);
567         if(mval[0]!=3200) {
568                 glBegin(GL_LINES);
569                 glVertex2f(v2d->vert.xmin, mval[1]);
570                 glVertex2f(v2d->vert.xmax, mval[1]);
571                 glEnd();
572         }
573 }
574
575 static void draw_solution(SpaceIpo *sipo)
576 {
577         View2D *v2d= &sipo->v2d;
578         EditIpo *ei;
579         int a;
580
581         if (!(v2d->scroll & VERT_SCROLL)) return;
582
583         ei= sipo->editipo;
584         for(a=0; a<sipo->totipo; a++, ei++) {
585                 if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
586                         cpack(ei->col);
587                                 
588                                 /* DISPBITS ipos have 'multiple' values. */
589                         if(ei->disptype==IPO_DISPBITS) {
590                                 int b, val= ei->icu->curval;
591                                         
592                                 for (b=0; b<31; b++)
593                                         if (val & (1<<b))
594                                                 draw_solution_line(v2d, b+1);
595                         } else {
596                                 draw_solution_line(v2d, ei->icu->curval);
597                         }
598                 }
599         }
600 }
601
602 void drawscroll(int disptype)
603 {
604         rcti vert, hor;
605         float fac, dfac, val, fac2, tim;
606         int darker, dark, light, lighter;
607         
608         vert= (G.v2d->vert);
609         hor= (G.v2d->hor);
610         
611         darker= -40;
612         dark= 0;
613         light= 20;
614         lighter= 50;
615         
616         if(G.v2d->scroll & HOR_SCROLL) {
617                 
618                 BIF_ThemeColorShade(curarea, TH_SHADE1, light);
619                 glRecti(hor.xmin,  hor.ymin,  hor.xmax,  hor.ymax);
620                 
621                 /* slider */
622                 fac= (G.v2d->cur.xmin- G.v2d->tot.xmin)/(G.v2d->tot.xmax-G.v2d->tot.xmin);
623                 if(fac<0.0) fac= 0.0;
624                 horxmin= hor.xmin+fac*(hor.xmax-hor.xmin);
625                 
626                 fac= (G.v2d->cur.xmax- G.v2d->tot.xmin)/(G.v2d->tot.xmax-G.v2d->tot.xmin);
627                 if(fac>1.0) fac= 1.0;
628                 horxmax= hor.xmin+fac*(hor.xmax-hor.xmin);
629                 
630                 if(horxmin > horxmax) horxmin= horxmax;
631                 
632                 BIF_ThemeColorShade(curarea, TH_SHADE1, dark);
633                 glRecti(horxmin,  hor.ymin,  horxmax,  hor.ymax);
634
635                 /* decoration bright line */
636                 BIF_ThemeColorShade(curarea, TH_SHADE1, lighter);
637                 sdrawline(hor.xmin, hor.ymax, hor.xmax, hor.ymax);
638
639                 /* the numbers: convert ipogrid_startx and -dx to scroll coordinates */
640                 fac= (ipogrid_startx- G.v2d->cur.xmin)/(G.v2d->cur.xmax-G.v2d->cur.xmin);
641                 fac= hor.xmin+fac*(hor.xmax-hor.xmin);
642                 
643                 dfac= (ipogrid_dx)/(G.v2d->cur.xmax-G.v2d->cur.xmin);
644                 dfac= dfac*(hor.xmax-hor.xmin);
645                 
646                 BIF_ThemeColor(curarea, TH_TEXT);
647                 val= ipogrid_startx;
648                 while(fac < hor.xmax) {
649                         
650                         if(curarea->spacetype==SPACE_SEQ) {
651                                 fac2= val/(float)G.scene->r.frs_sec;
652                                 tim= floor(fac2);
653                                 fac2= fac2-tim;
654                                 scroll_prstr(fac, 3.0+(float)(hor.ymin), tim+G.scene->r.frs_sec*fac2/100.0, 'h', disptype);
655                         }
656                         else if(curarea->spacetype==SPACE_SOUND) {
657                                 SpaceSound *ssound= curarea->spacedata.first;
658                                 
659                                 if(ssound->flag & SND_DRAWFRAMES) {
660                                         ipomachtx= 1;
661                                         scroll_prstr(fac, 3.0+(float)(hor.ymin), val, 'h', disptype);
662                                 }
663                                 else {
664                                         fac2= val/(float)G.scene->r.frs_sec;
665                                         scroll_prstr(fac, 3.0+(float)(hor.ymin), fac2, 'h', disptype);
666                                 }
667                         }
668                         else {
669                                 scroll_prstr(fac, 3.0+(float)(hor.ymin), val, 'h', disptype);
670                         }
671                         
672                         fac+= dfac;
673                         val+= ipogrid_dx;
674                 }
675         }
676         
677         if(G.v2d->scroll & VERT_SCROLL) {
678                 BIF_ThemeColorShade(curarea, TH_SHADE1, light);
679                 glRecti(vert.xmin,  vert.ymin,  vert.xmax,  vert.ymax);
680                 
681                 /* slider */
682                 fac= (G.v2d->cur.ymin- G.v2d->tot.ymin)/(G.v2d->tot.ymax-G.v2d->tot.ymin);
683                 if(fac<0.0) fac= 0.0;
684                 vertymin= vert.ymin+fac*(vert.ymax-vert.ymin);
685                 
686                 fac= (G.v2d->cur.ymax- G.v2d->tot.ymin)/(G.v2d->tot.ymax-G.v2d->tot.ymin);
687                 if(fac>1.0) fac= 1.0;
688                 vertymax= vert.ymin+fac*(vert.ymax-vert.ymin);
689                 
690                 if(vertymin > vertymax) vertymin= vertymax;
691                 
692                 BIF_ThemeColorShade(curarea, TH_SHADE1, dark);
693                 glRecti(vert.xmin,  vertymin,  vert.xmax,  vertymax);
694
695                 /* decoration black line */
696                 BIF_ThemeColorShade(curarea, TH_SHADE1, darker);
697                 if(G.v2d->scroll & HOR_SCROLL) 
698                         sdrawline(vert.xmax, vert.ymin+SCROLLH, vert.xmax, vert.ymax);
699                 else 
700                         sdrawline(vert.xmax, vert.ymin, vert.xmax, vert.ymax);
701
702                 /* the numbers: convert ipogrid_starty and -dy to scroll coordinates */
703                 fac= (ipogrid_starty- G.v2d->cur.ymin)/(G.v2d->cur.ymax-G.v2d->cur.ymin);
704                 fac= vert.ymin+SCROLLH+fac*(vert.ymax-vert.ymin-SCROLLH);
705                 
706                 dfac= (ipogrid_dy)/(G.v2d->cur.ymax-G.v2d->cur.ymin);
707                 dfac= dfac*(vert.ymax-vert.ymin-SCROLLH);
708                 
709                 if(curarea->spacetype==SPACE_SEQ) {
710                         BIF_ThemeColor(curarea, TH_TEXT);
711                         val= ipogrid_starty;
712                         fac+= 0.5*dfac;
713                         while(fac < vert.ymax) {
714                                 scroll_prstr((float)(vert.xmax)-14.0, fac, val, 'v', disptype);
715                                 fac+= dfac;
716                                 val+= ipogrid_dy;
717                         }
718                 }
719                 else if (curarea->spacetype==SPACE_NLA){
720                 }
721                 else if (curarea->spacetype==SPACE_ACTION){
722                         /* No digits on vertical axis in action mode! */
723                 }
724                 else {
725                         BIF_ThemeColor(curarea, TH_TEXT);
726                         val= ipogrid_starty;
727                         while(fac < vert.ymax) {
728                                 scroll_prstr((float)(vert.xmax)-14.0, fac, val, 'v', disptype);
729                                 fac+= dfac;
730                                 val+= ipogrid_dy;
731                         }
732                 }
733         }
734 }
735
736 static void draw_ipobuts(SpaceIpo *sipo)
737 {
738         ScrArea *area= sipo->area;
739         View2D *v2d= &sipo->v2d;
740         uiBlock *block;
741         uiBut *but;
742         EditIpo *ei;
743         int a, y, sel, tot;
744         char naam[20];
745         
746         if(area->winx<IPOBUTX) return;
747         
748         if(sipo->butofs) {
749                 tot= 30+IPOBUTY*sipo->totipo;
750                 if(tot<area->winy) sipo->butofs= 0;
751         }
752         
753         BIF_ThemeColor(curarea, TH_SHADE2);
754         glRects(v2d->mask.xmax,  0,  area->winx,  area->winy);
755         
756         cpack(0x0);
757         sdrawline(v2d->mask.xmax, 0, v2d->mask.xmax, area->winy);
758
759         if(sipo->totipo==0) return;
760         if(sipo->editipo==0) return;
761         
762         sprintf(naam, "ipowin %d", area->win);
763         block= uiNewBlock(&area->uiblocks, naam, UI_EMBOSSN, UI_HELV, area->win);
764         uiBlockSetCol(block, BUTRUST);
765         
766         ei= sipo->editipo;
767         y= area->winy-30+sipo->butofs;
768         for(a=0; a<sipo->totipo; a++, ei++, y-=IPOBUTY) {
769                 
770                 but= uiDefButI(block, TOG|BIT|a, a+1, ei->name,  v2d->mask.xmax+18, y, IPOBUTX-15, IPOBUTY-1, &(sipo->rowbut), 0, 0, 0, 0, "");
771                         /* XXXXX, is this, the sole caller
772                          * of this function, really necessary?
773                          */
774                 uiButSetFlag(but, UI_TEXT_LEFT);
775                 
776                 if(ei->icu) {
777                         cpack(ei->col);
778                         
779                         glRects(v2d->mask.xmax+8,  y+2,  v2d->mask.xmax+15, y+IPOBUTY-2);
780                         sel= ei->flag & (IPO_SELECT + IPO_EDIT);
781                         
782                         uiEmboss((float)(v2d->mask.xmax+8), (float)(y+2), (float)(v2d->mask.xmax+15), (float)(y+IPOBUTY-2), sel);
783                 }
784                 
785                 if(sipo->blocktype==ID_KE) {
786                         Key *key= (Key *)sipo->from;
787                         if(key==0 || key->type==KEY_NORMAL) break;
788                 }
789         }
790         uiDrawBlock(block);
791 }
792
793 static void calc_ipoverts(SpaceIpo *sipo)
794 {
795         View2D *v2d= &sipo->v2d;
796         EditIpo *ei;
797         BezTriple *bezt;
798         BPoint *bp;
799         int a, b;
800         
801         ei= G.sipo->editipo;
802         for(a=0; a<sipo->totipo; a++, ei++) {
803                 if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
804                         if(ei->icu->bezt) {
805                                 bezt= ei->icu->bezt;
806                                 b= ei->icu->totvert;
807                                 while(b--) {
808                                         ipoco_to_areaco(v2d, bezt->vec[0], bezt->s[0]);
809                                         ipoco_to_areaco(v2d, bezt->vec[1], bezt->s[1]);
810                                         ipoco_to_areaco(v2d, bezt->vec[2], bezt->s[2]);
811                                         bezt++;
812                                 }
813                         }
814                         else if(ei->icu->bp) {
815                                 bp= ei->icu->bp;
816                                 b= ei->icu->totvert;
817                                 while(b--) {
818                                         ipoco_to_areaco(v2d, bp->vec, bp->s);
819                                         bp++;
820                                 }
821                         }
822                 }
823         }
824 }
825
826
827 static void draw_ipovertices(int sel)
828 {
829         EditIpo *ei;
830         BezTriple *bezt;
831         float v1[2];
832         int val, ok, nr, a, b;
833         
834         if(G.f & G_PICKSEL) return;
835         
836         glPointSize(3.0);
837         
838         ei= G.sipo->editipo;
839         for(nr=0; nr<G.sipo->totipo; nr++, ei++) {
840                 if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
841                         
842                         if(G.sipo->showkey) {
843                                 if(sel) BIF_ThemeColor(curarea, TH_TEXT_HI);
844                                  else BIF_ThemeColor(curarea, TH_TEXT);
845                         } else if(ei->flag & IPO_EDIT) {
846                                 if(sel) BIF_ThemeColor(curarea, TH_VERTEX_SELECT); 
847                                 else BIF_ThemeColor(curarea, TH_VERTEX);
848                         } else {
849                                 if(sel) BIF_ThemeColor(curarea, TH_TEXT_HI);
850                                  else BIF_ThemeColor(curarea, TH_TEXT);
851                                  
852                                 val= (ei->icu->flag & IPO_SELECT)!=0;
853                                 if(sel != val) continue;
854                         }
855
856                         /* We can't change the color in the middle of
857                          * GL_POINTS because then Blender will segfault
858                          * on TNT2 / Linux with NVidia's drivers
859                          * (at least up to ver. 4349) */                
860                         
861                         glBegin(GL_POINTS);
862                         
863                         bezt= ei->icu->bezt;
864                         a= ei->icu->totvert;
865                         while(a--) {                            
866                                 
867                                 if(ei->disptype==IPO_DISPBITS) {
868                                         ok= 0;
869                                         if(ei->flag & IPO_EDIT) {
870                                                 if( (bezt->f2 & 1) == sel ) ok= 1;
871                                         }
872                                         else ok= 1;
873                                         
874                                         if(ok) {
875                                                 val= bezt->vec[1][1];
876                                                 b= 0;
877                                                 v1[0]= bezt->vec[1][0];
878                                                 
879                                                 while(b<31) {
880                                                         if(val & (1<<b)) {      
881                                                                 v1[1]= b+1;
882                                                                 glVertex3fv(v1);
883                                                         }
884                                                         b++;
885                                                 }
886                                         }
887                                 }
888                                 else {
889                                         
890                                         if(ei->flag & IPO_EDIT) {
891                                                 if(ei->icu->ipo==IPO_BEZ) {
892                                                         if( (bezt->f1 & 1) == sel )     
893                                                                 glVertex3fv(bezt->vec[0]);
894                                                         if( (bezt->f3 & 1) == sel )     
895                                                                 glVertex3fv(bezt->vec[2]);
896                                                 }
897                                                 if( (bezt->f2 & 1) == sel )     
898                                                         glVertex3fv(bezt->vec[1]);
899                                                 
900                                         }
901                                         else {
902                                                 glVertex3fv(bezt->vec[1]);
903                                         }
904                                 }
905                                 
906                                 bezt++;
907                         }
908
909                         glEnd();
910                 }
911         }
912         
913         glPointSize(1.0);
914 }
915
916 static void draw_ipohandles(int sel)
917 {
918         extern unsigned int nurbcol[];
919         EditIpo *ei;
920         BezTriple *bezt;
921         float *fp;
922         unsigned int *col;
923         int a, b;
924         
925         if(sel) col= nurbcol+4;
926         else col= nurbcol;
927         
928         ei= G.sipo->editipo;
929         for(a=0; a<G.sipo->totipo; a++, ei++) {
930                 if ISPOIN4(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu, disptype!=IPO_DISPBITS) {
931                         if(ei->icu->ipo==IPO_BEZ) {
932                                 bezt= ei->icu->bezt;
933                                 b= ei->icu->totvert;
934                                 while(b--) {
935                                         
936                                         if( (bezt->f2 & 1)==sel) {
937                                                 fp= bezt->vec[0];
938                                                 cpack(col[bezt->h1]);
939                                                 
940                                                 glBegin(GL_LINE_STRIP); 
941                                                 glVertex2fv(fp); glVertex2fv(fp+3); 
942                                                 glEnd();
943                                                 cpack(col[bezt->h2]);
944                                                 
945                                                 glBegin(GL_LINE_STRIP); 
946                                                 glVertex2fv(fp+3); glVertex2fv(fp+6); 
947                                                 glEnd();
948                                         }
949                                         else if( (bezt->f1 & 1)==sel) {
950                                                 fp= bezt->vec[0];
951                                                 cpack(col[bezt->h1]);
952                                                 
953                                                 glBegin(GL_LINE_STRIP); 
954                                                 glVertex2fv(fp); glVertex2fv(fp+3); 
955                                                 glEnd();
956                                         }
957                                         else if( (bezt->f3 & 1)==sel) {
958                                                 fp= bezt->vec[1];
959                                                 cpack(col[bezt->h2]);
960                                                 
961                                                 glBegin(GL_LINE_STRIP); 
962                                                 glVertex2fv(fp); glVertex2fv(fp+3); 
963                                                 glEnd();
964                                         }
965                                         
966                                         bezt++;
967                                 }
968                         }
969                 }
970         }
971 }
972
973 int pickselcode;
974
975 static void init_pickselcode(void)
976 {
977         pickselcode= 1;
978 }
979
980 static void draw_ipocurves(int sel)
981 {
982         EditIpo *ei;
983         IpoCurve *icu;
984         BezTriple *bezt, *prevbezt;
985         float *fp, fac, data[120], v1[2], v2[2], v3[2], v4[2];
986         float cycdx=0, cycdy=0, cycxofs, cycyofs;
987         int a, b, resol, cycount, val, nr;
988         
989         
990         ei= G.sipo->editipo;
991         for(nr=0; nr<G.sipo->totipo; nr++, ei++) {
992                 if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
993                         
994                         if(G.f & G_PICKSEL) {
995                                 glLoadName(pickselcode++);
996                                 val= 1;
997                         }
998                         else {
999                                 val= (ei->flag & (IPO_SELECT+IPO_EDIT))!=0;
1000                                 val= (val==sel);
1001                         }
1002                         
1003                         if(val) {
1004                                 
1005                                 cycyofs= cycxofs= 0.0;
1006                                 cycount= 1;
1007                                 
1008                                 icu= ei->icu;   
1009                                 
1010                                 /* curve */
1011                                 if(G.sipo->showkey) BIF_ThemeColor(curarea, TH_TEXT); 
1012                                 else cpack(ei->col);
1013                                 
1014                                 /* cyclic */
1015                                 if(icu->extrap & IPO_CYCL) {
1016                                         cycdx= (icu->bezt+icu->totvert-1)->vec[1][0] - icu->bezt->vec[1][0];
1017                                         cycdy= (icu->bezt+icu->totvert-1)->vec[1][1] - icu->bezt->vec[1][1];
1018                                         if(cycdx>0.01) {
1019                                                 
1020                                                 while(icu->bezt->vec[1][0]+cycxofs > G.v2d->cur.xmin) {
1021                                                         cycxofs-= cycdx;
1022                                                         if(icu->extrap & IPO_DIR) cycyofs-= cycdy;
1023                                                         cycount++;
1024                                                 }
1025                                                 bezt= icu->bezt+(icu->totvert-1);
1026                                                 fac= 0.0;
1027                                                 while(bezt->vec[1][0]+fac < G.v2d->cur.xmax) {
1028                                                         cycount++;
1029                                                         fac+= cycdx;
1030                                                 }
1031                                         }
1032                                 }
1033                                 
1034                                 while(cycount--) {
1035                                         
1036                                         if(ei->disptype==IPO_DISPBITS) {
1037                                                 
1038                                                 /* lines */
1039                                                 cpack(ei->col);
1040                                                 bezt= icu->bezt;
1041                                                 a= icu->totvert;
1042                                                 
1043                                                 while(a--) {
1044                                                         val= bezt->vec[1][1];
1045                                                         b= 0;
1046                                                         
1047                                                         while(b<31) {
1048                                                                 if(val & (1<<b)) {
1049                                                                         v1[1]= b+1;
1050                                                                         
1051                                                                         glBegin(GL_LINE_STRIP);
1052                                                                         if(icu->extrap & IPO_CYCL) ;
1053                                                                         else if(a==icu->totvert-1) {
1054                                                                                 v1[0]= G.v2d->cur.xmin+cycxofs;
1055                                                                                 glVertex2fv(v1);
1056                                                                         }
1057                                                                         v1[0]= bezt->vec[1][0]+cycxofs;
1058                                                                         glVertex2fv(v1); 
1059                                                                         
1060                                                                         if(a) v1[0]= (bezt+1)->vec[1][0]+cycxofs;
1061                                                                         else if(icu->extrap & IPO_CYCL) ;
1062                                                                         else v1[0]= G.v2d->cur.xmax+cycxofs;
1063                                                                         
1064                                                                         glVertex2fv(v1);
1065                                                                         glEnd();
1066                                                                 }
1067                                                                 b++;
1068                                                         }
1069                                                         bezt++;
1070                                                 }
1071                                                 
1072                                         }
1073                                         else {
1074                                                 
1075                                                 b= icu->totvert-1;
1076                                                 prevbezt= icu->bezt;
1077                                                 bezt= prevbezt+1;
1078                                                 
1079                                                 glBegin(GL_LINE_STRIP);
1080                                                 
1081                                                 /* extrapolate to left? */
1082                                                 if( (icu->extrap & IPO_CYCL)==0) {
1083                                                         if(prevbezt->vec[1][0] > G.v2d->cur.xmin) {
1084                                                                 v1[0]= G.v2d->cur.xmin;
1085                                                                 if(icu->extrap==IPO_HORIZ || icu->ipo==IPO_CONST) v1[1]= prevbezt->vec[1][1];
1086                                                                 else {
1087                                                                         fac= (prevbezt->vec[0][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
1088                                                                         if(fac!=0.0) fac= 1.0/fac;
1089                                                                         v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[0][1]-prevbezt->vec[1][1]);
1090                                                                 }
1091                                                                 glVertex2fv(v1);
1092                                                         }
1093                                                 }
1094                                                 
1095                                                 if(b==0) {
1096                                                         v1[0]= prevbezt->vec[1][0]+cycxofs;
1097                                                         v1[1]= prevbezt->vec[1][1]+cycyofs;
1098                                                         glVertex2fv(v1);
1099                                                 }
1100                                                 
1101                                                 while(b--) {
1102                                                         if(icu->ipo==IPO_CONST) {
1103                                                                 v1[0]= prevbezt->vec[1][0]+cycxofs;
1104                                                                 v1[1]= prevbezt->vec[1][1]+cycyofs;
1105                                                                 glVertex2fv(v1);
1106                                                                 v1[0]= bezt->vec[1][0]+cycxofs;
1107                                                                 v1[1]= prevbezt->vec[1][1]+cycyofs;
1108                                                                 glVertex2fv(v1);
1109                                                         }
1110                                                         else if(icu->ipo==IPO_LIN) {
1111                                                                 v1[0]= prevbezt->vec[1][0]+cycxofs;
1112                                                                 v1[1]= prevbezt->vec[1][1]+cycyofs;
1113                                                                 glVertex2fv(v1);
1114                                                         }
1115                                                         else {
1116                                                                 resol= 3.0*sqrt(bezt->vec[1][0] - prevbezt->vec[1][0]);
1117                                                                 
1118                                                                 if(resol<2) {
1119                                                                         v1[0]= prevbezt->vec[1][0]+cycxofs;
1120                                                                         v1[1]= prevbezt->vec[1][1]+cycyofs;
1121                                                                         glVertex2fv(v1);
1122                                                                 }
1123                                                                 else {
1124                                                                         if(resol>32) resol= 32;
1125                                                                         
1126                                                                         v1[0]= prevbezt->vec[1][0]+cycxofs;
1127                                                                         v1[1]= prevbezt->vec[1][1]+cycyofs;
1128                                                                         v2[0]= prevbezt->vec[2][0]+cycxofs;
1129                                                                         v2[1]= prevbezt->vec[2][1]+cycyofs;
1130                                                                         
1131                                                                         v3[0]= bezt->vec[0][0]+cycxofs;
1132                                                                         v3[1]= bezt->vec[0][1]+cycyofs;
1133                                                                         v4[0]= bezt->vec[1][0]+cycxofs;
1134                                                                         v4[1]= bezt->vec[1][1]+cycyofs;
1135                                                                         
1136                                                                         correct_bezpart(v1, v2, v3, v4);
1137                                                                         
1138                                                                         maakbez(v1[0], v2[0], v3[0], v4[0], data, resol);
1139                                                                         maakbez(v1[1], v2[1], v3[1], v4[1], data+1, resol);
1140                                                                         
1141                                                                         fp= data;
1142                                                                         while(resol--) {
1143                                                                                 glVertex2fv(fp);
1144                                                                                 fp+= 3;
1145                                                                         }
1146                                                                 }
1147                                                         }
1148                                                         prevbezt= bezt;
1149                                                         bezt++;
1150                                                         
1151                                                         /* last point? */
1152                                                         if(b==0) {
1153                                                                 v1[0]= prevbezt->vec[1][0]+cycxofs;
1154                                                                 v1[1]= prevbezt->vec[1][1]+cycyofs;
1155                                                                 glVertex2fv(v1);
1156                                                         }
1157                                                 }
1158                                                 
1159                                                 /* extrapolate to right? */
1160                                                 if( (icu->extrap & IPO_CYCL)==0) {
1161                                                         if(prevbezt->vec[1][0] < G.v2d->cur.xmax) {
1162                                                                 v1[0]= G.v2d->cur.xmax;
1163                                                                 if(icu->extrap==IPO_HORIZ || icu->ipo==IPO_CONST) v1[1]= prevbezt->vec[1][1];
1164                                                                 else {
1165                                                                         fac= (prevbezt->vec[2][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
1166                                                                         if(fac!=0.0) fac= 1.0/fac;
1167                                                                         v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[2][1]-prevbezt->vec[1][1]);
1168                                                                 }
1169                                                                 glVertex2fv(v1);
1170                                                         }
1171                                                 }
1172                                                 
1173                                                 glEnd();
1174                                                 
1175                                         }
1176                                         cycxofs+= cycdx;
1177                                         if(icu->extrap & IPO_DIR) cycyofs+= cycdy;
1178                                 }
1179                                 
1180                                 /* line that indicates the end of a speed curve */
1181                                 if(G.sipo->blocktype==ID_CU && icu->adrcode==CU_SPEED) {
1182                                         b= icu->totvert-1;
1183                                         if(b) {
1184                                                 glColor3ub(0, 0, 0);
1185                                                 bezt= icu->bezt+b;
1186                                                 glBegin(GL_LINES);
1187                                                 glVertex2f(bezt->vec[1][0], 0.0);
1188                                                 glVertex2f(bezt->vec[1][0], bezt->vec[1][1]);
1189                                                 glEnd();
1190                                         }
1191                                 }
1192                         }
1193                 }
1194         }
1195 }
1196
1197 static void draw_cfra(SpaceIpo *sipo)
1198 {
1199         View2D *v2d= &sipo->v2d;
1200         Object *ob;
1201         float vec[2];
1202         
1203         vec[0]= (G.scene->r.cfra);
1204         vec[0]*= G.scene->r.framelen;
1205         
1206         vec[1]= v2d->cur.ymin;
1207         BIF_ThemeColor(curarea, TH_HILITE);
1208         glLineWidth(2.0);
1209         
1210         glBegin(GL_LINE_STRIP);
1211         glVertex2fv(vec);
1212         vec[1]= v2d->cur.ymax;
1213         glVertex2fv(vec);
1214         glEnd();
1215         
1216         if(sipo->blocktype==ID_OB) {
1217                 ob= (G.scene->basact) ? (G.scene->basact->object) : 0;
1218                 if(ob && ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
1219                         vec[0]-= ob->sf;
1220                         
1221                         BIF_ThemeColorShade(curarea, TH_HILITE, -30);
1222                         
1223                         glBegin(GL_LINE_STRIP);
1224                         glVertex2fv(vec);
1225                         vec[1]= G.v2d->cur.ymin;
1226                         glVertex2fv(vec);
1227                         glEnd();
1228                 }
1229         }
1230         
1231         glLineWidth(1.0);
1232 }
1233
1234 static void draw_ipokey(SpaceIpo *sipo)
1235 {
1236         IpoKey *ik;
1237         
1238         glBegin(GL_LINES);
1239         for (ik= sipo->ipokey.first; ik; ik= ik->next) {
1240                 if(ik->flag & 1) glColor3ub(0xFF, 0xFF, 0x99);
1241                 else glColor3ub(0xAA, 0xAA, 0x55);
1242                 
1243                 glVertex2f(ik->val, G.v2d->cur.ymin);
1244                 glVertex2f(ik->val, G.v2d->cur.ymax);
1245         }
1246         glEnd();
1247 }
1248
1249 static void draw_key(SpaceIpo *sipo, int visible)
1250 {
1251         View2D *v2d= &sipo->v2d;
1252         Key *key;
1253         KeyBlock *kb, *act=NULL;
1254         unsigned int col;
1255         
1256         key= (Key *)sipo->from;
1257         if(key==0)
1258                 return;
1259         
1260         if(key->type== KEY_RELATIVE) if(visible==0) return;
1261         
1262         kb= key->block.first;
1263         while(kb) {
1264                 if(kb->type==KEY_LINEAR) setlinestyle(2);
1265                 else if(kb->type==KEY_BSPLINE) setlinestyle(4);
1266                 else setlinestyle(0);
1267                 
1268                 if(kb==key->refkey) col= 0x22FFFF;
1269                 else col= 0xFFFF00;
1270                 
1271                 if( (kb->flag & SELECT)==0)     col-= 0x225500;
1272                 else act= kb;
1273                 
1274                 cpack(col);
1275                 
1276                 glBegin(GL_LINE_STRIP);
1277                 glVertex2f(v2d->cur.xmin, kb->pos);
1278                 glVertex2f(v2d->cur.xmax, kb->pos);
1279                 glEnd();
1280                 
1281                 kb= kb->next;
1282         }
1283         
1284         if(act) {
1285                 if(act->type==KEY_LINEAR) setlinestyle(2);
1286                 else if(act->type==KEY_BSPLINE) setlinestyle(4);
1287                 else setlinestyle(0);
1288                 
1289                 if(act==key->refkey) cpack(0x22FFFF);
1290                 else cpack(0xFFFF00);
1291                 
1292                 glBegin(GL_LINE_STRIP);
1293                 glVertex2f(v2d->cur.xmin, act->pos);
1294                 glVertex2f(v2d->cur.xmax, act->pos);
1295                 glEnd();
1296         }
1297         
1298         setlinestyle(0);
1299 }
1300
1301 void drawipospace(ScrArea *sa, void *spacedata)
1302 {
1303         SpaceIpo *sipo= curarea->spacedata.first;
1304         View2D *v2d= &sipo->v2d;
1305         EditIpo *ei;
1306         float col[3];
1307         int ofsx, ofsy, a, disptype;
1308
1309         v2d->hor.xmax+=IPOBUTX;
1310         calc_scrollrcts(G.v2d, curarea->winx, curarea->winy);
1311
1312         BIF_GetThemeColor3fv(sa, TH_BACK, col);
1313         glClearColor(col[0], col[1], col[2], 0.0); 
1314
1315         if (sipo->pin)
1316                 glClearColor(col[0]+0.05,col[1],col[2], 0.0);   // litepink
1317         else
1318                 glClearColor(col[0],col[1],col[2], 0.0);
1319
1320         glClear(GL_COLOR_BUFFER_BIT);
1321         
1322         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
1323                 if(v2d->scroll) {       
1324                         ofsx= curarea->winrct.xmin;     // ivm mywin 
1325                         ofsy= curarea->winrct.ymin;
1326                         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); 
1327                         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);
1328                 } 
1329         }
1330
1331         test_editipo(); /* test if current editipo is correct, make_editipo sets v2d->cur */
1332
1333         myortho2(v2d->cur.xmin, v2d->cur.xmax, v2d->cur.ymin, v2d->cur.ymax);
1334         
1335  
1336         if(sipo->editipo) {
1337                 
1338                 /* correct scale for degrees? */
1339                 disptype= -1;
1340                 ei= sipo->editipo;
1341                 for(a=0; a<sipo->totipo; a++, ei++) {
1342                         if(ei->flag & IPO_VISIBLE) {
1343                                 if(disptype== -1) disptype= ei->disptype;
1344                                 else if(disptype!=ei->disptype) disptype= 0;
1345                         }
1346                 }
1347                 
1348                 calc_ipogrid(); 
1349                 draw_ipogrid();
1350                 
1351                 calc_ipoverts(sipo);
1352                 
1353                 draw_cfra(sipo);
1354                 
1355                 /* ipokeys */
1356                 if(sipo->showkey) {
1357                         if(sipo->ipokey.first==0) make_ipokey();
1358                         draw_ipokey(sipo);
1359                 }
1360                 
1361                 if(sipo->blocktype==ID_KE) {
1362                         ei= sipo->editipo;
1363                         draw_key(sipo, ei->flag & IPO_VISIBLE);
1364                 }
1365
1366                 /* draw deselect */
1367                 draw_ipocurves(0);
1368                 draw_ipohandles(0);
1369                 draw_ipovertices(0);
1370                 
1371                 /* draw select */
1372                 draw_ipocurves(1);
1373                 draw_ipohandles(1);
1374                 draw_ipovertices(1);
1375                 
1376                 /* restore viewport */
1377                 mywinset(curarea->win);
1378                 
1379                 if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
1380                         
1381                         /* ortho at pixel level curarea */
1382                         myortho2(-0.5, curarea->winx-0.5, -0.5, curarea->winy-0.5);
1383                         
1384                         if(v2d->scroll) {
1385                                 drawscroll(disptype);
1386                                 draw_solution(sipo);
1387                         }
1388                         
1389                         draw_ipobuts(sipo);
1390                 }
1391         }
1392         else {
1393                 calc_ipogrid();
1394                 draw_ipogrid();
1395         }
1396         
1397         myortho2(-0.5, curarea->winx-0.5, -0.5, curarea->winy-0.5);
1398         draw_area_emboss(sa);
1399
1400         curarea->win_swap= WIN_BACK_OK;
1401 }
1402
1403 void scroll_ipobuts()
1404 {
1405         int tot;
1406         short yo, mval[2];
1407         
1408         tot= 30+IPOBUTY*G.sipo->totipo;
1409         if(tot<curarea->winy) return;
1410         
1411         getmouseco_areawin(mval);
1412         yo= mval[1];
1413         
1414         while(get_mbut()&M_MOUSE) {
1415                 getmouseco_areawin(mval);
1416                 if(mval[1]!=yo) {
1417                         G.sipo->butofs+= (mval[1]-yo);
1418                         if(G.sipo->butofs<0) G.sipo->butofs= 0;
1419                         else if(G.sipo->butofs+curarea->winy>tot) G.sipo->butofs= tot-curarea->winy;
1420                         
1421                         scrarea_do_windraw(curarea);
1422                         screen_swapbuffers();
1423                         
1424                         yo= mval[1];
1425                 }
1426                 else BIF_wait_for_statechange();
1427         }
1428 }
1429
1430 /* total mess function, especially with mousewheel, needs cleanup badly (ton) */
1431 int view2dzoom(unsigned short event)
1432 {
1433         float fac, dx, dy, wtemp;
1434         short mval[2], mvalo[2];
1435         
1436         areawinset(curarea->win);       /* from buttons */
1437         curarea->head_swap= 0;
1438         getmouseco_areawin(mvalo);
1439         
1440         while( (get_mbut()&(L_MOUSE|M_MOUSE)) || (event==WHEELUPMOUSE) || (event==WHEELDOWNMOUSE) ) {
1441         
1442                 /* regular mousewheel:   zoom regular
1443                 * alt-shift mousewheel: zoom y only
1444                 * alt-ctrl mousewheel:  zoom x only
1445                 */
1446                 if (event==WHEELUPMOUSE) {
1447                         if(U.uiflag & WHEELZOOMDIR)
1448                                 wtemp = -0.0375;
1449                         else
1450                                 wtemp = 0.03;
1451                         if(curarea->spacetype!=SPACE_BUTS) wtemp*= 3;
1452                         
1453                         dx= (float)(wtemp*(G.v2d->cur.xmax-G.v2d->cur.xmin));
1454                         dy= (float)(wtemp*(G.v2d->cur.ymax-G.v2d->cur.ymin));
1455                         
1456                         switch (G.qual & (LR_CTRLKEY|LR_SHIFTKEY|LR_ALTKEY)) {
1457                         case 0:
1458                                 break;
1459                         case (LR_SHIFTKEY|LR_ALTKEY):
1460                                 dx = 0;
1461                                 break;
1462                         case (LR_CTRLKEY|LR_ALTKEY):
1463                                 dy = 0;
1464                                 break;
1465                         default:
1466                                 if(curarea->spacetype==SPACE_BUTS);     // exception
1467                                 else return 0;
1468                                 break;
1469                         }
1470                 }
1471                 else if (event==WHEELDOWNMOUSE) {
1472                         if(U.uiflag & WHEELZOOMDIR)
1473                                 wtemp = 0.03;
1474                         else
1475                                 wtemp = -0.0375;
1476                         if(curarea->spacetype!=SPACE_BUTS) wtemp*= 3;
1477                         
1478                         dx= (float)(wtemp*(G.v2d->cur.xmax-G.v2d->cur.xmin));
1479                         dy= (float)(wtemp*(G.v2d->cur.ymax-G.v2d->cur.ymin));
1480                         
1481                         switch (G.qual & (LR_CTRLKEY|LR_SHIFTKEY|LR_ALTKEY)) {
1482                                 case 0:
1483                                 break;
1484                         case (LR_SHIFTKEY|LR_ALTKEY):
1485                                 dx = 0;
1486                                 break;
1487                         case (LR_CTRLKEY|LR_ALTKEY):
1488                                 dy = 0;
1489                                 break;
1490                         default:
1491                                 if(curarea->spacetype==SPACE_BUTS);
1492                                 else return 0;
1493                                 break;
1494                         }
1495                 }
1496                 else {
1497                         getmouseco_areawin(mval);
1498                         fac= 0.001*(mval[0]-mvalo[0]);
1499                         dx= fac*(G.v2d->cur.xmax-G.v2d->cur.xmin);
1500                         fac= 0.001*(mval[1]-mvalo[1]);
1501                         dy= fac*(G.v2d->cur.ymax-G.v2d->cur.ymin);
1502                 }
1503                 if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
1504                         
1505                         G.v2d->cur.xmin+= dx;
1506                         G.v2d->cur.xmax-= dx;
1507                         if(curarea->spacetype!=SPACE_SEQ && curarea->spacetype!=SPACE_SOUND && curarea->spacetype!=SPACE_NLA && curarea->spacetype!=SPACE_ACTION) {
1508                                 G.v2d->cur.ymin+= dy;
1509                                 G.v2d->cur.ymax-= dy;
1510                         }
1511                 
1512                         test_view2d(G.v2d, curarea->winx, curarea->winy);       /* cur min max rects */
1513                         scrarea_do_windraw(curarea);
1514                         screen_swapbuffers();
1515                 }
1516                 else BIF_wait_for_statechange();
1517                 /* return if we were using the mousewheel
1518                 */
1519                 if ( (event==WHEELUPMOUSE) || (event==WHEELDOWNMOUSE) ) return 1;
1520         }
1521         return 1;
1522 }
1523
1524 void center_currframe(void)
1525 {
1526         /* place the current frame in the
1527          * center of the 2D window.
1528          */
1529         float width;
1530   
1531         areawinset(curarea->win);
1532         curarea->head_swap= 0;
1533
1534         width = G.v2d->cur.xmax - G.v2d->cur.xmin;
1535         G.v2d->cur.xmin = CFRA - 0.5*(width);
1536         G.v2d->cur.xmax = CFRA + 0.5*(width);
1537
1538         test_view2d(G.v2d, curarea->winx, curarea->winy);
1539         scrarea_do_windraw(curarea);
1540         screen_swapbuffers();
1541         curarea->head_swap= 0;
1542 }
1543
1544 /* total mess function, especially with mousewheel, needs cleanup badly (ton) */
1545 int view2dmove(unsigned short event)
1546 {
1547         /* return 1 when something was done */
1548         float facx=0.0, facy=0.0, dx, dy, left=1.0, right=1.0;
1549         short mval[2], mvalo[2], leftret=1;
1550         
1551         /* init */
1552         scrarea_do_windraw(curarea);
1553         curarea->head_swap= 0;
1554
1555         /* try to do some zooming if the
1556          * middlemouse and ctrl are pressed
1557          * or if the mousewheel is being used.
1558          * Return if zooming was done.
1559          */
1560          
1561          
1562         if ( (G.qual & LR_CTRLKEY) || (event==WHEELUPMOUSE) || (event==WHEELDOWNMOUSE) ) {
1563                 /* patch for buttonswin, standard scroll no zoom */
1564                 if(curarea->spacetype==SPACE_BUTS && (G.qual & LR_CTRLKEY)==0);
1565                 else if (view2dzoom(event)) {
1566                         curarea->head_swap= 0;
1567                         return 0;
1568                 }
1569         }
1570         
1571         /* test where mouse is */
1572         getmouseco_areawin(mvalo);
1573         
1574         if ELEM6(curarea->spacetype, SPACE_IPO, SPACE_SEQ, SPACE_OOPS, SPACE_SOUND, SPACE_ACTION, SPACE_NLA) 
1575                 {
1576                         if( BLI_in_rcti(&G.v2d->mask, (int)mvalo[0], (int)mvalo[1]) ) {
1577                                 facx= (G.v2d->cur.xmax-G.v2d->cur.xmin)/(float)(G.v2d->mask.xmax-G.v2d->mask.xmin);
1578                                 facy= (G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)(G.v2d->mask.ymax-G.v2d->mask.ymin);
1579                         }
1580                         else if(IN_2D_VERT_SCROLL((int)mvalo)) {
1581                                 facy= -(G.v2d->tot.ymax-G.v2d->tot.ymin)/(float)(G.v2d->mask.ymax-G.v2d->mask.ymin);
1582                                 if(get_mbut()&L_MOUSE) {
1583                                         /* which part of scrollbar should move? */
1584                                         if(mvalo[1]< (vertymin+vertymax)/2 ) right= 0.0;
1585                                         else left= 0.0;
1586                                         leftret= 0;
1587                                 }
1588                         }
1589                         else if(IN_2D_HORIZ_SCROLL((int)mvalo)) {
1590                                 facx= -(G.v2d->tot.xmax-G.v2d->tot.xmin)/(float)(G.v2d->mask.xmax-G.v2d->mask.xmin);
1591                                 if(get_mbut()&L_MOUSE) {
1592                                         /* which part of scrollbar should move? */
1593                                         if(mvalo[0]< (horxmin+horxmax)/2 ) right= 0.0;
1594                                         else left= 0.0;
1595                                         leftret= 0;
1596                                 }
1597                         }
1598                 }
1599                 else {
1600                         facx= (G.v2d->cur.xmax-G.v2d->cur.xmin)/(float)(curarea->winx);
1601                         facy= (G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)(curarea->winy);         
1602                 }
1603                 
1604                 
1605                 /* no y move in audio */
1606                 if(curarea->spacetype==SPACE_SOUND) facy= 0.0;
1607                 
1608                 if(get_mbut()&L_MOUSE && leftret) return 0;
1609                 if(facx==0.0 && facy==0.0) return 1;
1610                 
1611     while( (get_mbut()&(L_MOUSE|M_MOUSE)) || 
1612            (event==WHEELUPMOUSE) ||
1613            (event==WHEELDOWNMOUSE) ) {
1614
1615       /* If the mousewheel is used with shift key
1616        * the scroll up and down. If the mousewheel
1617        * is used with the ctrl key then scroll left
1618        * and right.
1619        */
1620                 if (event==WHEELUPMOUSE || event==WHEELDOWNMOUSE) {
1621                         if(event==WHEELDOWNMOUSE) {     
1622                                 facx= -facx; facy= -facy;
1623                         }
1624                         
1625                         switch (G.qual & (LR_CTRLKEY|LR_SHIFTKEY|LR_ALTKEY)) {
1626                         case (LR_SHIFTKEY):
1627                                 dx = 0.0;
1628                                 dy= facy*20.0;
1629                                 break;
1630                         case (LR_CTRLKEY):
1631                                 dx= facx*20.0;
1632                                 dy = 0.0;
1633                                 break;
1634                         default:
1635                                 if(curarea->spacetype==SPACE_BUTS) {
1636                                         if(G.buts->align==BUT_HORIZONTAL) {
1637                                                 dx= facx*30; dy= 0.0;
1638                                         } else {
1639                                                 dx= 0.0; dy= facy*30;
1640                                         }
1641                                 }
1642                                 else return 0;
1643                                 break;
1644                         }
1645                 }
1646                 else {
1647                         getmouseco_areawin(mval);
1648                         dx= facx*(mvalo[0]-mval[0]);
1649                         dy= facy*(mvalo[1]-mval[1]);
1650                 }
1651
1652                 if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
1653
1654                         G.v2d->cur.xmin+= left*dx;
1655                         G.v2d->cur.xmax+= right*dx;
1656                         G.v2d->cur.ymin+= left*dy;
1657                         G.v2d->cur.ymax+= right*dy;
1658                                 
1659                         test_view2d(G.v2d, curarea->winx, curarea->winy);
1660                                 
1661                         scrarea_do_windraw(curarea);
1662                         screen_swapbuffers();
1663                                 
1664                         mvalo[0]= mval[0];
1665                         mvalo[1]= mval[1];
1666                                 
1667                 }
1668                 else BIF_wait_for_statechange();
1669                         /* return if we were using the mousewheel
1670                         */
1671                 if ( (event==WHEELUPMOUSE) || (event==WHEELDOWNMOUSE) ) return 1;
1672         }
1673
1674     curarea->head_swap= 0;
1675     return 1;
1676 }
1677
1678 void view2dborder(void)
1679 {
1680         
1681 }
1682
1683 EditIpo *select_proj_ipo(rctf *rectf, int event)
1684 {
1685         EditIpo *ei;
1686         float xmin, ymin, xmax, ymax;
1687         /* this was IGLuint, but it's a useless typedef... */
1688         GLuint buffer[MAXPICKBUF];
1689         int a, b;
1690         int code, hits;
1691         short mval[2];
1692         
1693         G.f |= G_PICKSEL;
1694         
1695         if(rectf==0) {
1696                 getmouseco_areawin(mval);
1697                 
1698                 mval[0]-= 6; mval[1]-= 6;
1699                 areamouseco_to_ipoco(G.v2d, mval, &xmin, &ymin);
1700                 mval[0]+= 12; mval[1]+= 12;
1701                 areamouseco_to_ipoco(G.v2d, mval, &xmax, &ymax);
1702                 
1703                 myortho2(xmin, xmax, ymin, ymax);
1704         }
1705         else myortho2(rectf->xmin, rectf->xmax, rectf->ymin, rectf->ymax);
1706         
1707         glSelectBuffer( MAXPICKBUF, buffer); 
1708         glRenderMode(GL_SELECT);
1709         glInitNames();  /* whatfor? but otherwise it does not work */
1710         glPushName(-1);
1711         
1712         init_pickselcode();     /* drawipo.c */
1713         draw_ipocurves(0);      
1714         
1715         G.f -= G_PICKSEL;
1716         
1717         hits= glRenderMode(GL_RENDER);
1718         glPopName();    /* see above (pushname) */
1719         if(hits<1) return 0;
1720         
1721         code= 1;
1722         ei= G.sipo->editipo;
1723         for(a=0; a<G.sipo->totipo; a++, ei++) {
1724                 if ISPOIN(ei, icu, flag & IPO_VISIBLE) {
1725                         if(rectf) {
1726                                 for(b=0; b<hits; b++) {
1727                                         /* conversion for glSelect */
1728                                         if(code == buffer[ (4 * b) + 3] ) {
1729                                                 if(event==LEFTMOUSE) ei->flag |= IPO_SELECT;
1730                                                 else ei->flag &= ~IPO_SELECT;
1731                                                 ei->icu->flag= ei->flag;
1732                                         }
1733                                 }
1734                         }
1735                         else {
1736                                 /* also conversion for glSelect */
1737                                 if(code==buffer[ 3 ]) return ei;
1738                         }
1739                         code++;
1740                 }
1741         }
1742         return 0;
1743 }
1744