svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r20855:20928
[blender.git] / source / blender / editors / interface / interface_draw.c
1 /**
2  * $Id: interface_draw.c 15733 2008-07-24 09:23:13Z aligorith $
3  *
4  * ***** BEGIN GPL 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.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include <math.h>
31 #include <string.h>
32
33 #include "DNA_color_types.h"
34 #include "DNA_listBase.h"
35 #include "DNA_object_types.h"
36 #include "DNA_screen_types.h"
37 #include "DNA_texture_types.h"
38 #include "DNA_userdef_types.h"
39
40 #include "BLI_arithb.h"
41
42 #include "BKE_colortools.h"
43 #include "BKE_texture.h"
44 #include "BKE_utildefines.h"
45
46 #include "BIF_gl.h"
47 #include "BIF_glutil.h"
48
49 #include "UI_interface.h"
50 #include "UI_interface_icons.h"
51
52 #include "interface_intern.h"
53
54 #define UI_RB_ALPHA 16
55 #define UI_DISABLED_ALPHA_OFFS  -160
56
57 static int roundboxtype= 15;
58
59 void uiSetRoundBox(int type)
60 {
61         /* Not sure the roundbox function is the best place to change this
62          * if this is undone, its not that big a deal, only makes curves edges
63          * square for the  */
64         roundboxtype= type;
65
66         /* flags to set which corners will become rounded:
67
68         1------2
69         |      |
70         8------4
71         */
72         
73 }
74
75 int uiGetRoundBox(void)
76 {
77         return roundboxtype;
78 }
79
80 void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad)
81 {
82         float vec[7][2]= {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
83                           {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
84         int a;
85         
86         /* mult */
87         for(a=0; a<7; a++) {
88                 vec[a][0]*= rad; vec[a][1]*= rad;
89         }
90
91         glBegin(mode);
92
93         /* start with corner right-bottom */
94         if(roundboxtype & 4) {
95                 glVertex2f(maxx-rad, miny);
96                 for(a=0; a<7; a++) {
97                         glVertex2f(maxx-rad+vec[a][0], miny+vec[a][1]);
98                 }
99                 glVertex2f(maxx, miny+rad);
100         }
101         else glVertex2f(maxx, miny);
102         
103         /* corner right-top */
104         if(roundboxtype & 2) {
105                 glVertex2f(maxx, maxy-rad);
106                 for(a=0; a<7; a++) {
107                         glVertex2f(maxx-vec[a][1], maxy-rad+vec[a][0]);
108                 }
109                 glVertex2f(maxx-rad, maxy);
110         }
111         else glVertex2f(maxx, maxy);
112         
113         /* corner left-top */
114         if(roundboxtype & 1) {
115                 glVertex2f(minx+rad, maxy);
116                 for(a=0; a<7; a++) {
117                         glVertex2f(minx+rad-vec[a][0], maxy-vec[a][1]);
118                 }
119                 glVertex2f(minx, maxy-rad);
120         }
121         else glVertex2f(minx, maxy);
122         
123         /* corner left-bottom */
124         if(roundboxtype & 8) {
125                 glVertex2f(minx, miny+rad);
126                 for(a=0; a<7; a++) {
127                         glVertex2f(minx+vec[a][1], miny+rad-vec[a][0]);
128                 }
129                 glVertex2f(minx+rad, miny);
130         }
131         else glVertex2f(minx, miny);
132         
133         glEnd();
134 }
135
136 static void round_box_shade_col(float *col1, float *col2, float fac)
137 {
138         float col[3];
139
140         col[0]= (fac*col1[0] + (1.0-fac)*col2[0]);
141         col[1]= (fac*col1[1] + (1.0-fac)*col2[1]);
142         col[2]= (fac*col1[2] + (1.0-fac)*col2[2]);
143         
144         glColor3fv(col);
145 }
146
147
148 /* linear horizontal shade within button or in outline */
149 /* view2d scrollers use it */
150 void gl_round_box_shade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown)
151 {
152         float vec[7][2]= {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
153                           {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
154         float div= maxy-miny;
155         float coltop[3], coldown[3], color[4];
156         int a;
157         
158         /* mult */
159         for(a=0; a<7; a++) {
160                 vec[a][0]*= rad; vec[a][1]*= rad;
161         }
162         /* get current color, needs to be outside of glBegin/End */
163         glGetFloatv(GL_CURRENT_COLOR, color);
164
165         /* 'shade' defines strength of shading */       
166         coltop[0]= color[0]+shadetop; if(coltop[0]>1.0) coltop[0]= 1.0;
167         coltop[1]= color[1]+shadetop; if(coltop[1]>1.0) coltop[1]= 1.0;
168         coltop[2]= color[2]+shadetop; if(coltop[2]>1.0) coltop[2]= 1.0;
169         coldown[0]= color[0]+shadedown; if(coldown[0]<0.0) coldown[0]= 0.0;
170         coldown[1]= color[1]+shadedown; if(coldown[1]<0.0) coldown[1]= 0.0;
171         coldown[2]= color[2]+shadedown; if(coldown[2]<0.0) coldown[2]= 0.0;
172
173         glShadeModel(GL_SMOOTH);
174         glBegin(mode);
175
176         /* start with corner right-bottom */
177         if(roundboxtype & 4) {
178                 
179                 round_box_shade_col(coltop, coldown, 0.0);
180                 glVertex2f(maxx-rad, miny);
181                 
182                 for(a=0; a<7; a++) {
183                         round_box_shade_col(coltop, coldown, vec[a][1]/div);
184                         glVertex2f(maxx-rad+vec[a][0], miny+vec[a][1]);
185                 }
186                 
187                 round_box_shade_col(coltop, coldown, rad/div);
188                 glVertex2f(maxx, miny+rad);
189         }
190         else {
191                 round_box_shade_col(coltop, coldown, 0.0);
192                 glVertex2f(maxx, miny);
193         }
194         
195         /* corner right-top */
196         if(roundboxtype & 2) {
197                 
198                 round_box_shade_col(coltop, coldown, (div-rad)/div);
199                 glVertex2f(maxx, maxy-rad);
200                 
201                 for(a=0; a<7; a++) {
202                         round_box_shade_col(coltop, coldown, (div-rad+vec[a][1])/div);
203                         glVertex2f(maxx-vec[a][1], maxy-rad+vec[a][0]);
204                 }
205                 round_box_shade_col(coltop, coldown, 1.0);
206                 glVertex2f(maxx-rad, maxy);
207         }
208         else {
209                 round_box_shade_col(coltop, coldown, 1.0);
210                 glVertex2f(maxx, maxy);
211         }
212         
213         /* corner left-top */
214         if(roundboxtype & 1) {
215                 
216                 round_box_shade_col(coltop, coldown, 1.0);
217                 glVertex2f(minx+rad, maxy);
218                 
219                 for(a=0; a<7; a++) {
220                         round_box_shade_col(coltop, coldown, (div-vec[a][1])/div);
221                         glVertex2f(minx+rad-vec[a][0], maxy-vec[a][1]);
222                 }
223                 
224                 round_box_shade_col(coltop, coldown, (div-rad)/div);
225                 glVertex2f(minx, maxy-rad);
226         }
227         else {
228                 round_box_shade_col(coltop, coldown, 1.0);
229                 glVertex2f(minx, maxy);
230         }
231         
232         /* corner left-bottom */
233         if(roundboxtype & 8) {
234                 
235                 round_box_shade_col(coltop, coldown, rad/div);
236                 glVertex2f(minx, miny+rad);
237                 
238                 for(a=0; a<7; a++) {
239                         round_box_shade_col(coltop, coldown, (rad-vec[a][1])/div);
240                         glVertex2f(minx+vec[a][1], miny+rad-vec[a][0]);
241                 }
242                 
243                 round_box_shade_col(coltop, coldown, 0.0);
244                 glVertex2f(minx+rad, miny);
245         }
246         else {
247                 round_box_shade_col(coltop, coldown, 0.0);
248                 glVertex2f(minx, miny);
249         }
250         
251         glEnd();
252         glShadeModel(GL_FLAT);
253 }
254
255 /* linear vertical shade within button or in outline */
256 /* view2d scrollers use it */
257 void gl_round_box_vertical_shade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadeLeft, float shadeRight)
258 {
259         float vec[7][2]= {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
260                           {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
261         float div= maxx-minx;
262         float colLeft[3], colRight[3], color[4];
263         int a;
264         
265         /* mult */
266         for(a=0; a<7; a++) {
267                 vec[a][0]*= rad; vec[a][1]*= rad;
268         }
269         /* get current color, needs to be outside of glBegin/End */
270         glGetFloatv(GL_CURRENT_COLOR, color);
271
272         /* 'shade' defines strength of shading */       
273         colLeft[0]= color[0]+shadeLeft; if(colLeft[0]>1.0) colLeft[0]= 1.0;
274         colLeft[1]= color[1]+shadeLeft; if(colLeft[1]>1.0) colLeft[1]= 1.0;
275         colLeft[2]= color[2]+shadeLeft; if(colLeft[2]>1.0) colLeft[2]= 1.0;
276         colRight[0]= color[0]+shadeRight; if(colRight[0]<0.0) colRight[0]= 0.0;
277         colRight[1]= color[1]+shadeRight; if(colRight[1]<0.0) colRight[1]= 0.0;
278         colRight[2]= color[2]+shadeRight; if(colRight[2]<0.0) colRight[2]= 0.0;
279
280         glShadeModel(GL_SMOOTH);
281         glBegin(mode);
282
283         /* start with corner right-bottom */
284         if(roundboxtype & 4) {
285                 round_box_shade_col(colLeft, colRight, 0.0);
286                 glVertex2f(maxx-rad, miny);
287                 
288                 for(a=0; a<7; a++) {
289                         round_box_shade_col(colLeft, colRight, vec[a][0]/div);
290                         glVertex2f(maxx-rad+vec[a][0], miny+vec[a][1]);
291                 }
292                 
293                 round_box_shade_col(colLeft, colRight, rad/div);
294                 glVertex2f(maxx, miny+rad);
295         }
296         else {
297                 round_box_shade_col(colLeft, colRight, 0.0);
298                 glVertex2f(maxx, miny);
299         }
300         
301         /* corner right-top */
302         if(roundboxtype & 2) {
303                 round_box_shade_col(colLeft, colRight, 0.0);
304                 glVertex2f(maxx, maxy-rad);
305                 
306                 for(a=0; a<7; a++) {
307                         
308                         round_box_shade_col(colLeft, colRight, (div-rad-vec[a][0])/div);
309                         glVertex2f(maxx-vec[a][1], maxy-rad+vec[a][0]);
310                 }
311                 round_box_shade_col(colLeft, colRight, (div-rad)/div);
312                 glVertex2f(maxx-rad, maxy);
313         }
314         else {
315                 round_box_shade_col(colLeft, colRight, 0.0);
316                 glVertex2f(maxx, maxy);
317         }
318         
319         /* corner left-top */
320         if(roundboxtype & 1) {
321                 round_box_shade_col(colLeft, colRight, (div-rad)/div);
322                 glVertex2f(minx+rad, maxy);
323                 
324                 for(a=0; a<7; a++) {
325                         round_box_shade_col(colLeft, colRight, (div-rad+vec[a][0])/div);
326                         glVertex2f(minx+rad-vec[a][0], maxy-vec[a][1]);
327                 }
328                 
329                 round_box_shade_col(colLeft, colRight, 1.0);
330                 glVertex2f(minx, maxy-rad);
331         }
332         else {
333                 round_box_shade_col(colLeft, colRight, 1.0);
334                 glVertex2f(minx, maxy);
335         }
336         
337         /* corner left-bottom */
338         if(roundboxtype & 8) {
339                 round_box_shade_col(colLeft, colRight, 1.0);
340                 glVertex2f(minx, miny+rad);
341                 
342                 for(a=0; a<7; a++) {
343                         round_box_shade_col(colLeft, colRight, (vec[a][0])/div);
344                         glVertex2f(minx+vec[a][1], miny+rad-vec[a][0]);
345                 }
346                 
347                 round_box_shade_col(colLeft, colRight, 1.0);
348                 glVertex2f(minx+rad, miny);
349         }
350         else {
351                 round_box_shade_col(colLeft, colRight, 1.0);
352                 glVertex2f(minx, miny);
353         }
354         
355         glEnd();
356         glShadeModel(GL_FLAT);
357 }
358
359 /* plain antialiased unfilled rectangle */
360 void uiRoundRect(float minx, float miny, float maxx, float maxy, float rad)
361 {
362         float color[4];
363         
364         if(roundboxtype & UI_RB_ALPHA) {
365                 glGetFloatv(GL_CURRENT_COLOR, color);
366                 color[3]= 0.5;
367                 glColor4fv(color);
368                 glEnable( GL_BLEND );
369         }
370         
371         /* set antialias line */
372         glEnable( GL_LINE_SMOOTH );
373         glEnable( GL_BLEND );
374
375         gl_round_box(GL_LINE_LOOP, minx, miny, maxx, maxy, rad);
376    
377         glDisable( GL_BLEND );
378         glDisable( GL_LINE_SMOOTH );
379 }
380
381 /* plain fake antialiased unfilled round rectangle */
382 void uiRoundRectFakeAA(float minx, float miny, float maxx, float maxy, float rad, float asp)
383 {
384         float color[4], alpha;
385         float raddiff;
386         int i, passes=4;
387         
388         /* get the colour and divide up the alpha */
389         glGetFloatv(GL_CURRENT_COLOR, color);
390         alpha = 1; //color[3];
391         color[3]= 0.5*alpha/(float)passes;
392         glColor4fv(color);
393         
394         /* set the 'jitter amount' */
395         raddiff = (1/(float)passes) * asp;
396         
397         glEnable( GL_BLEND );
398         
399         /* draw lots of lines on top of each other */
400         for (i=passes; i>=(-passes); i--) {
401                 gl_round_box(GL_LINE_LOOP, minx, miny, maxx, maxy, rad+(i*raddiff));
402         }
403         
404         glDisable( GL_BLEND );
405         
406         color[3] = alpha;
407         glColor4fv(color);
408 }
409
410 /* (old, used in outliner) plain antialiased filled box */
411 void uiRoundBox(float minx, float miny, float maxx, float maxy, float rad)
412 {
413         float color[4];
414         
415         if(roundboxtype & UI_RB_ALPHA) {
416                 glGetFloatv(GL_CURRENT_COLOR, color);
417                 color[3]= 0.5;
418                 glColor4fv(color);
419                 glEnable( GL_BLEND );
420         }
421         
422         /* solid part */
423         gl_round_box(GL_POLYGON, minx, miny, maxx, maxy, rad);
424         
425         /* set antialias line */
426         glEnable( GL_LINE_SMOOTH );
427         glEnable( GL_BLEND );
428         
429         gl_round_box(GL_LINE_LOOP, minx, miny, maxx, maxy, rad);
430         
431         glDisable( GL_BLEND );
432         glDisable( GL_LINE_SMOOTH );
433 }
434
435
436 /* ************** generic embossed rect, for window sliders etc ************* */
437
438
439 /* text_draw.c uses this */
440 void uiEmboss(float x1, float y1, float x2, float y2, int sel)
441 {
442         
443         /* below */
444         if(sel) glColor3ub(200,200,200);
445         else glColor3ub(50,50,50);
446         fdrawline(x1, y1, x2, y1);
447
448         /* right */
449         fdrawline(x2, y1, x2, y2);
450         
451         /* top */
452         if(sel) glColor3ub(50,50,50);
453         else glColor3ub(200,200,200);
454         fdrawline(x1, y2, x2, y2);
455
456         /* left */
457         fdrawline(x1, y1, x1, y2);
458         
459 }
460
461 /* ************** TEXT AND ICON DRAWING FUNCTIONS ************* */
462
463
464 #if 0
465 #ifdef INTERNATIONAL
466 static void ui_draw_but_CHARTAB(uiBut *but)
467 {
468         /* XXX 2.50 bad global access */
469         /* Some local variables */
470         float sx, sy, ex, ey;
471         float width, height;
472         float butw, buth;
473         int x, y, cs;
474         wchar_t wstr[2];
475         unsigned char ustr[16];
476         PackedFile *pf;
477         int result = 0;
478         int charmax = G.charmax;
479         
480         /* <builtin> font in use. There are TTF <builtin> and non-TTF <builtin> fonts */
481         if(!strcmp(G.selfont->name, "<builtin>"))
482         {
483                 if(G.ui_international == TRUE)
484                 {
485                         charmax = 0xff;
486                 }
487                 else
488                 {
489                         charmax = 0xff;
490                 }
491         }
492
493         /* Category list exited without selecting the area */
494         if(G.charmax == 0)
495                 charmax = G.charmax = 0xffff;
496
497         /* Calculate the size of the button */
498         width = abs(rect->xmax - rect->xmin);
499         height = abs(rect->ymax - rect->ymin);
500         
501         butw = floor(width / 12);
502         buth = floor(height / 6);
503         
504         /* Initialize variables */
505         sx = rect->xmin;
506         ex = rect->xmin + butw;
507         sy = rect->ymin + height - buth;
508         ey = rect->ymin + height;
509
510         cs = G.charstart;
511
512         /* Set the font, in case it is not <builtin> font */
513         if(G.selfont && strcmp(G.selfont->name, "<builtin>"))
514         {
515                 char tmpStr[256];
516
517                 // Is the font file packed, if so then use the packed file
518                 if(G.selfont->packedfile)
519                 {
520                         pf = G.selfont->packedfile;             
521                         FTF_SetFont(pf->data, pf->size, 14.0);
522                 }
523                 else
524                 {
525                         int err;
526
527                         strcpy(tmpStr, G.selfont->name);
528                         BLI_convertstringcode(tmpStr, G.sce);
529                         err = FTF_SetFont((unsigned char *)tmpStr, 0, 14.0);
530                 }
531         }
532         else
533         {
534                 if(G.ui_international == TRUE)
535                 {
536                         FTF_SetFont((unsigned char *) datatoc_bfont_ttf, datatoc_bfont_ttf_size, 14.0);
537                 }
538         }
539
540         /* Start drawing the button itself */
541         glShadeModel(GL_SMOOTH);
542
543         glColor3ub(200,  200,  200);
544         glRectf((rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax));
545
546         glColor3ub(0,  0,  0);
547         for(y = 0; y < 6; y++)
548         {
549                 // Do not draw more than the category allows
550                 if(cs > charmax) break;
551
552                 for(x = 0; x < 12; x++)
553                 {
554                         // Do not draw more than the category allows
555                         if(cs > charmax) break;
556
557                         // Draw one grid cell
558                         glBegin(GL_LINE_LOOP);
559                                 glVertex2f(sx, sy);
560                                 glVertex2f(ex, sy);
561                                 glVertex2f(ex, ey);
562                                 glVertex2f(sx, ey);                             
563                         glEnd();        
564
565                         // Draw character inside the cell
566                         memset(wstr, 0, sizeof(wchar_t)*2);
567                         memset(ustr, 0, 16);
568
569                         // Set the font to be either unicode or <builtin>                               
570                         wstr[0] = cs;
571                         if(strcmp(G.selfont->name, "<builtin>"))
572                         {
573                                 wcs2utf8s((char *)ustr, (wchar_t *)wstr);
574                         }
575                         else
576                         {
577                                 if(G.ui_international == TRUE)
578                                 {
579                                         wcs2utf8s((char *)ustr, (wchar_t *)wstr);
580                                 }
581                                 else
582                                 {
583                                         ustr[0] = cs;
584                                         ustr[1] = 0;
585                                 }
586                         }
587
588                         if((G.selfont && strcmp(G.selfont->name, "<builtin>")) || (G.selfont && !strcmp(G.selfont->name, "<builtin>") && G.ui_international == TRUE))
589                         {
590                                 float wid;
591                                 float llx, lly, llz, urx, ury, urz;
592                                 float dx, dy;
593                                 float px, py;
594         
595                                 // Calculate the position
596                                 wid = FTF_GetStringWidth((char *) ustr, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
597                                 FTF_GetBoundingBox((char *) ustr, &llx,&lly,&llz,&urx,&ury,&urz, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
598                                 dx = urx-llx;
599                                 dy = ury-lly;
600
601                                 // This isn't fully functional since the but->aspect isn't working like I suspected
602                                 px = sx + ((butw/but->aspect)-dx)/2;
603                                 py = sy + ((buth/but->aspect)-dy)/2;
604
605                                 // Set the position and draw the character
606                                 ui_rasterpos_safe(px, py, but->aspect);
607                                 FTF_DrawString((char *) ustr, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
608                         }
609                         else
610                         {
611                                 ui_rasterpos_safe(sx + butw/2, sy + buth/2, but->aspect);
612                                 UI_DrawString(but->font, (char *) ustr, 0);
613                         }
614         
615                         // Calculate the next position and character
616                         sx += butw; ex +=butw;
617                         cs++;
618                 }
619                 /* Add the y position and reset x position */
620                 sy -= buth; 
621                 ey -= buth;
622                 sx = rect->xmin;
623                 ex = rect->xmin + butw;
624         }       
625         glShadeModel(GL_FLAT);
626
627         /* Return Font Settings to original */
628         if(U.fontsize && U.fontname[0])
629         {
630                 result = FTF_SetFont((unsigned char *)U.fontname, 0, U.fontsize);
631         }
632         else if (U.fontsize)
633         {
634                 result = FTF_SetFont((unsigned char *) datatoc_bfont_ttf, datatoc_bfont_ttf_size, U.fontsize);
635         }
636
637         if (result == 0)
638         {
639                 result = FTF_SetFont((unsigned char *) datatoc_bfont_ttf, datatoc_bfont_ttf_size, 11);
640         }
641         
642         /* resets the font size */
643         if(G.ui_international == TRUE)
644         {
645                 // uiSetCurFont(but->block, UI_HELV);
646         }
647 }
648
649 #endif // INTERNATIONAL
650 #endif
651
652 void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *wcol, rcti *rect)
653 {
654         ColorBand *coba;
655         CBData *cbd;
656         float x1, y1, sizex, sizey;
657         float dx, v3[2], v1[2], v2[2], v1a[2], v2a[2];
658         int a;
659                 
660         coba= (ColorBand *)(but->editcoba? but->editcoba: but->poin);
661         if(coba==NULL) return;
662         
663         x1= rect->xmin;
664         y1= rect->ymin;
665         sizex= rect->xmax-x1;
666         sizey= rect->ymax-y1;
667         
668         /* first background, to show tranparency */
669         dx= sizex/12.0;
670         v1[0]= x1;
671         for(a=0; a<12; a++) {
672                 if(a & 1) glColor3f(0.3, 0.3, 0.3); else glColor3f(0.8, 0.8, 0.8);
673                 glRectf(v1[0], y1, v1[0]+dx, y1+0.5*sizey);
674                 if(a & 1) glColor3f(0.8, 0.8, 0.8); else glColor3f(0.3, 0.3, 0.3);
675                 glRectf(v1[0], y1+0.5*sizey, v1[0]+dx, y1+sizey);
676                 v1[0]+= dx;
677         }
678         
679         glShadeModel(GL_SMOOTH);
680         glEnable(GL_BLEND);
681         
682         cbd= coba->data;
683         
684         v1[0]= v2[0]= x1;
685         v1[1]= y1;
686         v2[1]= y1+sizey;
687         
688         glBegin(GL_QUAD_STRIP);
689         
690         glColor4fv( &cbd->r );
691         glVertex2fv(v1); glVertex2fv(v2);
692         
693         for(a=0; a<coba->tot; a++, cbd++) {
694                 
695                 v1[0]=v2[0]= x1+ cbd->pos*sizex;
696                 
697                 glColor4fv( &cbd->r );
698                 glVertex2fv(v1); glVertex2fv(v2);
699         }
700         
701         v1[0]=v2[0]= x1+ sizex;
702         glVertex2fv(v1); glVertex2fv(v2);
703         
704         glEnd();
705         glShadeModel(GL_FLAT);
706         glDisable(GL_BLEND);
707         
708         /* outline */
709         v1[0]= x1; v1[1]= y1;
710         
711         cpack(0x0);
712         glBegin(GL_LINE_LOOP);
713         glVertex2fv(v1);
714         v1[0]+= sizex;
715         glVertex2fv(v1);
716         v1[1]+= sizey;
717         glVertex2fv(v1);
718         v1[0]-= sizex;
719         glVertex2fv(v1);
720         glEnd();
721         
722         
723         /* help lines */
724         v1[0]= v2[0]=v3[0]= x1;
725         v1[1]= y1;
726         v1a[1]= y1+0.25*sizey;
727         v2[1]= y1+0.5*sizey;
728         v2a[1]= y1+0.75*sizey;
729         v3[1]= y1+sizey;
730         
731         
732         cbd= coba->data;
733         glBegin(GL_LINES);
734         for(a=0; a<coba->tot; a++, cbd++) {
735                 v1[0]=v2[0]=v3[0]=v1a[0]=v2a[0]= x1+ cbd->pos*sizex;
736                 
737                 if(a==coba->cur) {
738                         glColor3ub(0, 0, 0);
739                         glVertex2fv(v1);
740                         glVertex2fv(v3);
741                         glEnd();
742                         
743                         setlinestyle(2);
744                         glBegin(GL_LINES);
745                         glColor3ub(255, 255, 255);
746                         glVertex2fv(v1);
747                         glVertex2fv(v3);
748                         glEnd();
749                         setlinestyle(0);
750                         glBegin(GL_LINES);
751                         
752                         /* glColor3ub(0, 0, 0);
753                         glVertex2fv(v1);
754                         glVertex2fv(v1a);
755                         glColor3ub(255, 255, 255);
756                         glVertex2fv(v1a);
757                         glVertex2fv(v2);
758                         glColor3ub(0, 0, 0);
759                         glVertex2fv(v2);
760                         glVertex2fv(v2a);
761                         glColor3ub(255, 255, 255);
762                         glVertex2fv(v2a);
763                         glVertex2fv(v3);
764                         */
765                 }
766                 else {
767                         glColor3ub(0, 0, 0);
768                         glVertex2fv(v1);
769                         glVertex2fv(v2);
770                         
771                         glColor3ub(255, 255, 255);
772                         glVertex2fv(v2);
773                         glVertex2fv(v3);
774                 }       
775         }
776         glEnd();
777 }
778
779 void ui_draw_but_NORMAL(uiBut *but, uiWidgetColors *wcol, rcti *rect)
780 {
781         static GLuint displist=0;
782         int a, old[8];
783         GLfloat diff[4], diffn[4]={1.0f, 1.0f, 1.0f, 1.0f};
784         float vec0[4]={0.0f, 0.0f, 0.0f, 0.0f};
785         float dir[4], size;
786         
787         /* store stuff */
788         glGetMaterialfv(GL_FRONT, GL_DIFFUSE, diff);
789                 
790         /* backdrop */
791         glColor3ubv(wcol->inner);
792         uiSetRoundBox(15);
793         gl_round_box(GL_POLYGON, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f);
794         
795         /* sphere color */
796         glMaterialfv(GL_FRONT, GL_DIFFUSE, diffn);
797         glCullFace(GL_BACK); glEnable(GL_CULL_FACE);
798         
799         /* disable blender light */
800         for(a=0; a<8; a++) {
801                 old[a]= glIsEnabled(GL_LIGHT0+a);
802                 glDisable(GL_LIGHT0+a);
803         }
804         
805         /* own light */
806         glEnable(GL_LIGHT7);
807         glEnable(GL_LIGHTING);
808         
809         ui_get_but_vectorf(but, dir);
810
811         dir[3]= 0.0f;   /* glLight needs 4 args, 0.0 is sun */
812         glLightfv(GL_LIGHT7, GL_POSITION, dir); 
813         glLightfv(GL_LIGHT7, GL_DIFFUSE, diffn); 
814         glLightfv(GL_LIGHT7, GL_SPECULAR, vec0); 
815         glLightf(GL_LIGHT7, GL_CONSTANT_ATTENUATION, 1.0f);
816         glLightf(GL_LIGHT7, GL_LINEAR_ATTENUATION, 0.0f);
817         
818         /* transform to button */
819         glPushMatrix();
820         glTranslatef(rect->xmin + 0.5f*(rect->xmax-rect->xmin), rect->ymin+ 0.5f*(rect->ymax-rect->ymin), 0.0f);
821         
822         if( rect->xmax-rect->xmin < rect->ymax-rect->ymin)
823                 size= (rect->xmax-rect->xmin)/200.f;
824         else
825                 size= (rect->ymax-rect->ymin)/200.f;
826         
827         glScalef(size, size, size);
828         
829         if(displist==0) {
830                 GLUquadricObj   *qobj;
831                 
832                 displist= glGenLists(1);
833                 glNewList(displist, GL_COMPILE_AND_EXECUTE);
834                 
835                 qobj= gluNewQuadric();
836                 gluQuadricDrawStyle(qobj, GLU_FILL); 
837                 glShadeModel(GL_SMOOTH);
838                 gluSphere( qobj, 100.0, 32, 24);
839                 glShadeModel(GL_FLAT);
840                 gluDeleteQuadric(qobj);  
841                 
842                 glEndList();
843         }
844         else glCallList(displist);
845         
846         /* restore */
847         glDisable(GL_LIGHTING);
848         glDisable(GL_CULL_FACE);
849         glMaterialfv(GL_FRONT, GL_DIFFUSE, diff); 
850         glDisable(GL_LIGHT7);
851         
852         /* AA circle */
853         glEnable(GL_BLEND);
854         glEnable(GL_LINE_SMOOTH );
855         glColor3ubv(wcol->inner);
856         glutil_draw_lined_arc(0.0f, M_PI*2.0, 100.0f, 32);
857         glDisable(GL_BLEND);
858         glDisable(GL_LINE_SMOOTH );
859
860         /* matrix after circle */
861         glPopMatrix();
862
863         /* enable blender light */
864         for(a=0; a<8; a++) {
865                 if(old[a])
866                         glEnable(GL_LIGHT0+a);
867         }
868 }
869
870 static void ui_draw_but_curve_grid(rcti *rect, float zoomx, float zoomy, float offsx, float offsy, float step)
871 {
872         float dx, dy, fx, fy;
873         
874         glBegin(GL_LINES);
875         dx= step*zoomx;
876         fx= rect->xmin + zoomx*(-offsx);
877         if(fx > rect->xmin) fx -= dx*( floor(fx-rect->xmin));
878         while(fx < rect->xmax) {
879                 glVertex2f(fx, rect->ymin); 
880                 glVertex2f(fx, rect->ymax);
881                 fx+= dx;
882         }
883         
884         dy= step*zoomy;
885         fy= rect->ymin + zoomy*(-offsy);
886         if(fy > rect->ymin) fy -= dy*( floor(fy-rect->ymin));
887         while(fy < rect->ymax) {
888                 glVertex2f(rect->xmin, fy); 
889                 glVertex2f(rect->xmax, fy);
890                 fy+= dy;
891         }
892         glEnd();
893         
894 }
895
896 static void glColor3ubvShade(char *col, int shade)
897 {
898         glColor3ub(col[0]-shade>0?col[0]-shade:0, 
899                            col[1]-shade>0?col[1]-shade:0,
900                            col[2]-shade>0?col[2]-shade:0);
901 }
902
903 void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, rcti *rect)
904 {
905         CurveMapping *cumap;
906         CurveMap *cuma;
907         CurveMapPoint *cmp;
908         float fx, fy, fac[2], zoomx, zoomy, offsx, offsy;
909         GLint scissor[4];
910         int a;
911
912         cumap= (CurveMapping *)(but->editcumap? but->editcumap: but->poin);
913         cuma= cumap->cm+cumap->cur;
914         
915         /* need scissor test, curve can draw outside of boundary */
916         glGetIntegerv(GL_VIEWPORT, scissor);
917         glScissor(ar->winrct.xmin + rect->xmin, ar->winrct.ymin+rect->ymin, rect->xmax-rect->xmin, rect->ymax-rect->ymin);
918         
919         /* calculate offset and zoom */
920         zoomx= (rect->xmax-rect->xmin-2.0*but->aspect)/(cumap->curr.xmax - cumap->curr.xmin);
921         zoomy= (rect->ymax-rect->ymin-2.0*but->aspect)/(cumap->curr.ymax - cumap->curr.ymin);
922         offsx= cumap->curr.xmin-but->aspect/zoomx;
923         offsy= cumap->curr.ymin-but->aspect/zoomy;
924         
925         /* backdrop */
926         if(cumap->flag & CUMA_DO_CLIP) {
927                 glColor3ubvShade(wcol->inner, -20);
928                 glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
929                 glColor3ubv(wcol->inner);
930                 glRectf(rect->xmin + zoomx*(cumap->clipr.xmin-offsx),
931                                 rect->ymin + zoomy*(cumap->clipr.ymin-offsy),
932                                 rect->xmin + zoomx*(cumap->clipr.xmax-offsx),
933                                 rect->ymin + zoomy*(cumap->clipr.ymax-offsy));
934         }
935         else {
936                 glColor3ubv(wcol->inner);
937                 glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
938         }
939         
940         /* grid, every .25 step */
941         glColor3ubvShade(wcol->inner, -16);
942         ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 0.25f);
943         /* grid, every 1.0 step */
944         glColor3ubvShade(wcol->inner, -24);
945         ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 1.0f);
946         /* axes */
947         glColor3ubvShade(wcol->inner, -50);
948         glBegin(GL_LINES);
949         glVertex2f(rect->xmin, rect->ymin + zoomy*(-offsy));
950         glVertex2f(rect->xmax, rect->ymin + zoomy*(-offsy));
951         glVertex2f(rect->xmin + zoomx*(-offsx), rect->ymin);
952         glVertex2f(rect->xmin + zoomx*(-offsx), rect->ymax);
953         glEnd();
954         
955         /* cfra option */
956         /* XXX 2.48
957         if(cumap->flag & CUMA_DRAW_CFRA) {
958                 glColor3ub(0x60, 0xc0, 0x40);
959                 glBegin(GL_LINES);
960                 glVertex2f(rect->xmin + zoomx*(cumap->sample[0]-offsx), rect->ymin);
961                 glVertex2f(rect->xmin + zoomx*(cumap->sample[0]-offsx), rect->ymax);
962                 glEnd();
963         }*/
964         /* sample option */
965         /* XXX 2.48
966          * if(cumap->flag & CUMA_DRAW_SAMPLE) {
967                 if(cumap->cur==3) {
968                         float lum= cumap->sample[0]*0.35f + cumap->sample[1]*0.45f + cumap->sample[2]*0.2f;
969                         glColor3ub(240, 240, 240);
970                         
971                         glBegin(GL_LINES);
972                         glVertex2f(rect->xmin + zoomx*(lum-offsx), rect->ymin);
973                         glVertex2f(rect->xmin + zoomx*(lum-offsx), rect->ymax);
974                         glEnd();
975                 }
976                 else {
977                         if(cumap->cur==0)
978                                 glColor3ub(240, 100, 100);
979                         else if(cumap->cur==1)
980                                 glColor3ub(100, 240, 100);
981                         else
982                                 glColor3ub(100, 100, 240);
983                         
984                         glBegin(GL_LINES);
985                         glVertex2f(rect->xmin + zoomx*(cumap->sample[cumap->cur]-offsx), rect->ymin);
986                         glVertex2f(rect->xmin + zoomx*(cumap->sample[cumap->cur]-offsx), rect->ymax);
987                         glEnd();
988                 }
989         }*/
990         
991         /* the curve */
992         glColor3ubv(wcol->item);
993         glEnable(GL_LINE_SMOOTH);
994         glEnable(GL_BLEND);
995         glBegin(GL_LINE_STRIP);
996         
997         if(cuma->table==NULL)
998                 curvemapping_changed(cumap, 0); /* 0 = no remove doubles */
999         cmp= cuma->table;
1000         
1001         /* first point */
1002         if((cuma->flag & CUMA_EXTEND_EXTRAPOLATE)==0)
1003                 glVertex2f(rect->xmin, rect->ymin + zoomy*(cmp[0].y-offsy));
1004         else {
1005                 fx= rect->xmin + zoomx*(cmp[0].x-offsx + cuma->ext_in[0]);
1006                 fy= rect->ymin + zoomy*(cmp[0].y-offsy + cuma->ext_in[1]);
1007                 glVertex2f(fx, fy);
1008         }
1009         for(a=0; a<=CM_TABLE; a++) {
1010                 fx= rect->xmin + zoomx*(cmp[a].x-offsx);
1011                 fy= rect->ymin + zoomy*(cmp[a].y-offsy);
1012                 glVertex2f(fx, fy);
1013         }
1014         /* last point */
1015         if((cuma->flag & CUMA_EXTEND_EXTRAPOLATE)==0)
1016                 glVertex2f(rect->xmax, rect->ymin + zoomy*(cmp[CM_TABLE].y-offsy));     
1017         else {
1018                 fx= rect->xmin + zoomx*(cmp[CM_TABLE].x-offsx - cuma->ext_out[0]);
1019                 fy= rect->ymin + zoomy*(cmp[CM_TABLE].y-offsy - cuma->ext_out[1]);
1020                 glVertex2f(fx, fy);
1021         }
1022         glEnd();
1023         glDisable(GL_LINE_SMOOTH);
1024         glDisable(GL_BLEND);
1025
1026         /* the points, use aspect to make them visible on edges */
1027         cmp= cuma->curve;
1028         glPointSize(3.0f);
1029         bglBegin(GL_POINTS);
1030         for(a=0; a<cuma->totpoint; a++) {
1031                 if(cmp[a].flag & SELECT)
1032                         UI_ThemeColor(TH_TEXT_HI);
1033                 else
1034                         UI_ThemeColor(TH_TEXT);
1035                 fac[0]= rect->xmin + zoomx*(cmp[a].x-offsx);
1036                 fac[1]= rect->ymin + zoomy*(cmp[a].y-offsy);
1037                 bglVertex2fv(fac);
1038         }
1039         bglEnd();
1040         glPointSize(1.0f);
1041         
1042         /* restore scissortest */
1043         glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
1044
1045         /* outline */
1046         glColor3ubv(wcol->outline);
1047         fdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
1048 }
1049
1050
1051 /* ****************************************************** */
1052
1053
1054 static void ui_shadowbox(float minx, float miny, float maxx, float maxy, float shadsize, unsigned char alpha)
1055 {
1056         glEnable(GL_BLEND);
1057         glShadeModel(GL_SMOOTH);
1058         
1059         /* right quad */
1060         glBegin(GL_POLYGON);
1061         glColor4ub(0, 0, 0, alpha);
1062         glVertex2f(maxx, miny);
1063         glVertex2f(maxx, maxy-0.3*shadsize);
1064         glColor4ub(0, 0, 0, 0);
1065         glVertex2f(maxx+shadsize, maxy-0.75*shadsize);
1066         glVertex2f(maxx+shadsize, miny);
1067         glEnd();
1068         
1069         /* corner shape */
1070         glBegin(GL_POLYGON);
1071         glColor4ub(0, 0, 0, alpha);
1072         glVertex2f(maxx, miny);
1073         glColor4ub(0, 0, 0, 0);
1074         glVertex2f(maxx+shadsize, miny);
1075         glVertex2f(maxx+0.7*shadsize, miny-0.7*shadsize);
1076         glVertex2f(maxx, miny-shadsize);
1077         glEnd();
1078         
1079         /* bottom quad */               
1080         glBegin(GL_POLYGON);
1081         glColor4ub(0, 0, 0, alpha);
1082         glVertex2f(minx+0.3*shadsize, miny);
1083         glVertex2f(maxx, miny);
1084         glColor4ub(0, 0, 0, 0);
1085         glVertex2f(maxx, miny-shadsize);
1086         glVertex2f(minx+0.5*shadsize, miny-shadsize);
1087         glEnd();
1088         
1089         glDisable(GL_BLEND);
1090         glShadeModel(GL_FLAT);
1091 }
1092
1093 void uiDrawBoxShadow(unsigned char alpha, float minx, float miny, float maxx, float maxy)
1094 {
1095         /* accumulated outline boxes to make shade not linear, is more pleasant */
1096         ui_shadowbox(minx, miny, maxx, maxy, 11.0, (20*alpha)>>8);
1097         ui_shadowbox(minx, miny, maxx, maxy, 7.0, (40*alpha)>>8);
1098         ui_shadowbox(minx, miny, maxx, maxy, 5.0, (80*alpha)>>8);
1099         
1100 }
1101
1102
1103 void ui_dropshadow(rctf *rct, float radius, float aspect, int select)
1104 {
1105         float rad;
1106         float a;
1107         char alpha= 2;
1108         
1109         glEnable(GL_BLEND);
1110         
1111         if(radius > (rct->ymax-rct->ymin-10.0f)/2.0f)
1112                 rad= (rct->ymax-rct->ymin-10.0f)/2.0f;
1113         else
1114                 rad= radius;
1115         
1116         if(select) a= 12.0f*aspect; else a= 12.0f*aspect;
1117         for(; a>0.0f; a-=aspect) {
1118                 /* alpha ranges from 2 to 20 or so */
1119                 glColor4ub(0, 0, 0, alpha);
1120                 alpha+= 2;
1121                 
1122                 gl_round_box(GL_POLYGON, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax-10.0f + a, rad+a);
1123         }
1124         
1125         /* outline emphasis */
1126         glEnable( GL_LINE_SMOOTH );
1127         glColor4ub(0, 0, 0, 100);
1128         gl_round_box(GL_LINE_LOOP, rct->xmin-0.5f, rct->ymin-0.5f, rct->xmax+0.5f, rct->ymax+0.5f, radius);
1129         glDisable( GL_LINE_SMOOTH );
1130         
1131         glDisable(GL_BLEND);
1132 }
1133