UI
[blender.git] / source / blender / editors / interface / interface_widgets.c
1 /**
2 * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  *
18  * The Original Code is Copyright (C) 2009 Blender Foundation.
19  * All rights reserved.
20  * 
21  * Contributor(s): Blender Foundation
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 #include <limits.h>
27 #include <math.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "MEM_guardedalloc.h"
32
33 #include "DNA_ID.h"
34 #include "DNA_screen_types.h"
35 #include "DNA_userdef_types.h"
36 #include "DNA_windowmanager_types.h"
37
38 #include "BLI_arithb.h"
39 #include "BLI_listbase.h"
40 #include "BLI_rect.h"
41
42 #include "BKE_context.h"
43 #include "BKE_curve.h"
44 #include "BKE_global.h"
45 #include "BKE_utildefines.h"
46
47 #include "BIF_gl.h"
48 #include "BIF_glutil.h"
49
50 #include "BLF_api.h"
51
52 #include "UI_interface.h"
53 #include "UI_interface_icons.h"
54 #include "UI_resources.h"
55 #include "UI_view2d.h"
56
57 #include "ED_util.h"
58 #include "ED_types.h"
59
60 #include "interface_intern.h"
61
62 /* ************** widget base functions ************** */
63 /*
64      - in: roundbox codes for corner types and radius
65      - return: array of [size][2][x,y] points, the edges of the roundbox, + UV coords
66  
67      - draw black box with alpha 0 on exact button boundbox
68      - for ever AA step:
69         - draw the inner part for a round filled box, with color blend codes or texture coords
70         - draw outline in outline color
71         - draw outer part, bottom half, extruded 1 pixel to bottom, for emboss shadow
72         - draw extra decorations
73      - draw background color box with alpha 1 on exact button boundbox
74  
75  */
76
77 /* fill this struct with polygon info to draw AA'ed */
78 /* it has outline, back, and two optional tria meshes */
79
80 typedef struct uiWidgetTrias {
81         int tot;
82         
83         float vec[32][2];
84         int (*index)[3];
85         
86 } uiWidgetTrias;
87
88 typedef struct uiWidgetStateColors {
89         char inner_anim[4];
90         char inner_anim_sel[4];
91         char inner_key[4];
92         char inner_key_sel[4];
93         char inner_driven[4];
94         char inner_driven_sel[4];
95 } uiWidgetStateColors;
96
97 typedef struct uiWidgetBase {
98         
99         int totvert, halfwayvert;
100         float outer_v[64][2];
101         float inner_v[64][2];
102         float inner_uv[64][2];
103         
104         short inner, outline, emboss; /* set on/off */
105         
106         uiWidgetTrias tria1;
107         uiWidgetTrias tria2;
108         
109 } uiWidgetBase;
110
111 /* uiWidgetType: for time being only for visual appearance,
112    later, a handling callback can be added too 
113 */
114 typedef struct uiWidgetType {
115         
116         /* pointer to theme color definition */
117         uiWidgetColors *wcol_theme;
118         
119         /* converted colors for state */
120         uiWidgetColors wcol;
121         
122         void (*state)(struct uiWidgetType *, int state);
123         void (*draw)(uiWidgetColors *, rcti *, int state, int roundboxalign);
124         void (*custom)(uiBut *, uiWidgetColors *, rcti *, int state, int roundboxalign);
125         void (*text)(uiFontStyle *, uiWidgetColors *, uiBut *, rcti *);
126         
127 } uiWidgetType;
128
129
130 /* *********************** draw data ************************** */
131
132 static float cornervec[9][2]= {{0.0, 0.0}, {0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, 
133 {0.707, 0.293}, {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}, {1.0, 1.0}};
134
135 static float jit[8][2]= {{0.468813 , -0.481430}, {-0.155755 , -0.352820}, 
136 {0.219306 , -0.238501},  {-0.393286 , -0.110949}, {-0.024699 , 0.013908}, 
137 {0.343805 , 0.147431}, {-0.272855 , 0.269918}, {0.095909 , 0.388710}};
138
139 static float num_tria_vert[19][2]= {
140 {0.382684, 0.923879}, {0.000001, 1.000000}, {-0.382683, 0.923880}, {-0.707107, 0.707107},
141 {-0.923879, 0.382684}, {-1.000000, 0.000000}, {-0.923880, -0.382684}, {-0.707107, -0.707107},
142 {-0.382683, -0.923880}, {0.000000, -1.000000}, {0.382684, -0.923880}, {0.707107, -0.707107},
143 {0.923880, -0.382684}, {1.000000, -0.000000}, {0.923880, 0.382683}, {0.707107, 0.707107}, 
144 {-0.352077, 0.532607}, {-0.352077, -0.549313}, {0.729843, -0.008353}};
145
146 static int num_tria_face[19][3]= {
147 {13, 14, 18}, {17, 5, 6}, {12, 13, 18}, {17, 6, 7}, {15, 18, 14}, {16, 4, 5}, {16, 5, 17}, {18, 11, 12}, 
148 {18, 17, 10}, {18, 10, 11}, {17, 9, 10}, {15, 0, 18}, {18, 0, 16}, {3, 4, 16}, {8, 9, 17}, {8, 17, 7}, 
149 {2, 3, 16}, {1, 2, 16}, {16, 0, 1}};
150
151 static float menu_tria_vert[6][2]= {
152 {-0.41, 0.16}, {0.41, 0.16}, {0, 0.82}, 
153 {0, -0.82}, {-0.41, -0.16}, {0.41, -0.16}};
154
155 static int menu_tria_face[2][3]= {{2, 0, 1}, {3, 5, 4}};
156
157 static float check_tria_vert[6][2]= {
158 {-0.578579, 0.253369},  {-0.392773, 0.412794},  {-0.004241, -0.328551}, 
159 {-0.003001, 0.034320},  {1.055313, 0.864744},   {0.866408, 1.026895}};
160
161 static int check_tria_face[4][3]= {
162 {3, 2, 4}, {3, 4, 5}, {1, 0, 3}, {0, 2, 3}};
163
164 /* ************************************************* */
165
166 void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3)
167 {
168         float color[4];
169         int j;
170         
171         glEnable(GL_BLEND);
172         glGetFloatv(GL_CURRENT_COLOR, color);
173         color[3]= 0.125;
174         glColor4fv(color);
175         
176         /* for each AA step */
177         for(j=0; j<8; j++) {
178                 glTranslatef(1.0*jit[j][0], 1.0*jit[j][1], 0.0f);
179
180                 glBegin(GL_POLYGON);
181                 glVertex2f(x1, y1);
182                 glVertex2f(x2, y2);
183                 glVertex2f(x3, y3);
184                 glEnd();
185                 
186                 glTranslatef(-1.0*jit[j][0], -1.0*jit[j][1], 0.0f);
187         }
188
189         glDisable(GL_BLEND);
190         
191 }
192
193 static void widget_init(uiWidgetBase *wtb)
194 {
195         wtb->totvert= wtb->halfwayvert= 0;
196         wtb->tria1.tot= 0;
197         wtb->tria2.tot= 0;
198         
199         wtb->inner= 1;
200         wtb->outline= 1;
201         wtb->emboss= 1;
202 }
203
204 /* helper call, makes shadow rect, with 'sun' above menu, so only shadow to left/right/bottom */
205 /* return tot */
206 static int round_box_shadow_edges(float (*vert)[2], rcti *rect, float rad, int roundboxalign, float step)
207 {
208         float vec[9][2];
209         float minx, miny, maxx, maxy;
210         int a, tot= 0;
211         
212         rad+= step;
213         
214         if(2.0f*rad > rect->ymax-rect->ymin)
215                 rad= 0.5f*(rect->ymax-rect->ymin);
216         
217         minx= rect->xmin-step;
218         miny= rect->ymin-step;
219         maxx= rect->xmax+step;
220         maxy= rect->ymax+step;
221         
222         /* mult */
223         for(a=0; a<9; a++) {
224                 vec[a][0]= rad*cornervec[a][0]; 
225                 vec[a][1]= rad*cornervec[a][1]; 
226         }
227         
228         /* start with left-top, anti clockwise */
229         if(roundboxalign & 1) {
230                 for(a=0; a<9; a++, tot++) {
231                         vert[tot][0]= minx+rad-vec[a][0];
232                         vert[tot][1]= maxy-vec[a][1];
233                 }
234         }
235         else {
236                 for(a=0; a<9; a++, tot++) {
237                         vert[tot][0]= minx;
238                         vert[tot][1]= maxy;
239                 }
240         }
241         
242         if(roundboxalign & 8) {
243                 for(a=0; a<9; a++, tot++) {
244                         vert[tot][0]= minx+vec[a][1];
245                         vert[tot][1]= miny+rad-vec[a][0];
246                 }
247         }
248         else {
249                 for(a=0; a<9; a++, tot++) {
250                         vert[tot][0]= minx;
251                         vert[tot][1]= miny;
252                 }
253         }
254         
255         if(roundboxalign & 4) {
256                 for(a=0; a<9; a++, tot++) {
257                         vert[tot][0]= maxx-rad+vec[a][0];
258                         vert[tot][1]= miny+vec[a][1];
259                 }
260         }
261         else {
262                 for(a=0; a<9; a++, tot++) {
263                         vert[tot][0]= maxx;
264                         vert[tot][1]= miny;
265                 }
266         }
267         
268         if(roundboxalign & 2) {
269                 for(a=0; a<9; a++, tot++) {
270                         vert[tot][0]= maxx-vec[a][1];
271                         vert[tot][1]= maxy-rad+vec[a][0];
272                 }
273         }
274         else {
275                 for(a=0; a<9; a++, tot++) {
276                         vert[tot][0]= maxx;
277                         vert[tot][1]= maxy;
278                 }
279         }
280         return tot;
281 }
282
283 /* this call has 1 extra arg to allow mask outline */
284 static void round_box__edges(uiWidgetBase *wt, int roundboxalign, rcti *rect, float rad, float radi)
285 {
286         float vec[9][2], veci[9][2];
287         float minx= rect->xmin, miny= rect->ymin, maxx= rect->xmax, maxy= rect->ymax;
288         float minxi= minx + 1.0f; /* boundbox inner */
289         float maxxi= maxx - 1.0f;
290         float minyi= miny + 1.0f;
291         float maxyi= maxy - 1.0f;
292         float facxi= 1.0f/(maxxi-minxi); /* for uv */
293         float facyi= 1.0f/(maxyi-minyi);
294         int a, tot= 0;
295         
296         if(2.0f*rad > rect->ymax-rect->ymin)
297                 rad= 0.5f*(rect->ymax-rect->ymin);
298
299         if(2.0f*(radi+1.0f) > rect->ymax-rect->ymin)
300                 radi= 0.5f*(rect->ymax-rect->ymin) - 1.0f;
301         
302         /* mult */
303         for(a=0; a<9; a++) {
304                 veci[a][0]= radi*cornervec[a][0]; 
305                 veci[a][1]= radi*cornervec[a][1]; 
306                 vec[a][0]= rad*cornervec[a][0]; 
307                 vec[a][1]= rad*cornervec[a][1]; 
308         }
309         
310         /* corner left-bottom */
311         if(roundboxalign & 8) {
312                 
313                 for(a=0; a<9; a++, tot++) {
314                         wt->inner_v[tot][0]= minxi+veci[a][1];
315                         wt->inner_v[tot][1]= minyi+radi-veci[a][0];
316                         
317                         wt->outer_v[tot][0]= minx+vec[a][1];
318                         wt->outer_v[tot][1]= miny+rad-vec[a][0];
319                         
320                         wt->inner_uv[tot][0]= facxi*(wt->inner_v[tot][0] - minxi);
321                         wt->inner_uv[tot][1]= facyi*(wt->inner_v[tot][1] - minyi);
322                 }
323         }
324         else {
325                 wt->inner_v[tot][0]= minxi;
326                 wt->inner_v[tot][1]= minyi;
327                 
328                 wt->outer_v[tot][0]= minx;
329                 wt->outer_v[tot][1]= miny;
330
331                 wt->inner_uv[tot][0]= 0.0f;
332                 wt->inner_uv[tot][1]= 0.0f;
333                 
334                 tot++;
335         }
336         
337         /* corner right-bottom */
338         if(roundboxalign & 4) {
339                 
340                 for(a=0; a<9; a++, tot++) {
341                         wt->inner_v[tot][0]= maxxi-radi+veci[a][0];
342                         wt->inner_v[tot][1]= minyi+veci[a][1];
343                         
344                         wt->outer_v[tot][0]= maxx-rad+vec[a][0];
345                         wt->outer_v[tot][1]= miny+vec[a][1];
346                         
347                         wt->inner_uv[tot][0]= facxi*(wt->inner_v[tot][0] - minxi);
348                         wt->inner_uv[tot][1]= facyi*(wt->inner_v[tot][1] - minyi);
349                 }
350         }
351         else {
352                 wt->inner_v[tot][0]= maxxi;
353                 wt->inner_v[tot][1]= minyi;
354                 
355                 wt->outer_v[tot][0]= maxx;
356                 wt->outer_v[tot][1]= miny;
357
358                 wt->inner_uv[tot][0]= 1.0f;
359                 wt->inner_uv[tot][1]= 0.0f;
360                 
361                 tot++;
362         }
363         
364         wt->halfwayvert= tot;
365         
366         /* corner right-top */
367         if(roundboxalign & 2) {
368                 
369                 for(a=0; a<9; a++, tot++) {
370                         wt->inner_v[tot][0]= maxxi-veci[a][1];
371                         wt->inner_v[tot][1]= maxyi-radi+veci[a][0];
372                         
373                         wt->outer_v[tot][0]= maxx-vec[a][1];
374                         wt->outer_v[tot][1]= maxy-rad+vec[a][0];
375                         
376                         wt->inner_uv[tot][0]= facxi*(wt->inner_v[tot][0] - minxi);
377                         wt->inner_uv[tot][1]= facyi*(wt->inner_v[tot][1] - minyi);
378                 }
379         }
380         else {
381                 wt->inner_v[tot][0]= maxxi;
382                 wt->inner_v[tot][1]= maxyi;
383                 
384                 wt->outer_v[tot][0]= maxx;
385                 wt->outer_v[tot][1]= maxy;
386                 
387                 wt->inner_uv[tot][0]= 1.0f;
388                 wt->inner_uv[tot][1]= 1.0f;
389                 
390                 tot++;
391         }
392         
393         /* corner left-top */
394         if(roundboxalign & 1) {
395                 
396                 for(a=0; a<9; a++, tot++) {
397                         wt->inner_v[tot][0]= minxi+radi-veci[a][0];
398                         wt->inner_v[tot][1]= maxyi-veci[a][1];
399                         
400                         wt->outer_v[tot][0]= minx+rad-vec[a][0];
401                         wt->outer_v[tot][1]= maxy-vec[a][1];
402                         
403                         wt->inner_uv[tot][0]= facxi*(wt->inner_v[tot][0] - minxi);
404                         wt->inner_uv[tot][1]= facyi*(wt->inner_v[tot][1] - minyi);
405                 }
406                 
407         }
408         else {
409                 
410                 wt->inner_v[tot][0]= minxi;
411                 wt->inner_v[tot][1]= maxyi;
412                 
413                 wt->outer_v[tot][0]= minx;
414                 wt->outer_v[tot][1]= maxy;
415                 
416                 wt->inner_uv[tot][0]= 0.0f;
417                 wt->inner_uv[tot][1]= 1.0f;
418                 
419                 tot++;
420         }
421                 
422         wt->totvert= tot;
423 }
424
425 static void round_box_edges(uiWidgetBase *wt, int roundboxalign, rcti *rect, float rad)
426 {
427         round_box__edges(wt, roundboxalign, rect, rad, rad-1.0f);
428 }
429
430
431 /* based on button rect, return scaled array of triangles */
432 static void widget_num_tria(uiWidgetTrias *tria, rcti *rect, float triasize, char where)
433 {
434         float centx, centy, size;
435         int a;
436         
437         /* center position and size */
438         centx= (float)rect->xmin + 0.5f*(rect->ymax-rect->ymin);
439         centy= (float)rect->ymin + 0.5f*(rect->ymax-rect->ymin);
440         size= -0.5f*triasize*(rect->ymax-rect->ymin);
441
442         if(where=='r') {
443                 centx= (float)rect->xmax - 0.5f*(rect->ymax-rect->ymin);
444                 size= -size;
445         }       
446         
447         for(a=0; a<19; a++) {
448                 tria->vec[a][0]= size*num_tria_vert[a][0] + centx;
449                 tria->vec[a][1]= size*num_tria_vert[a][1] + centy;
450         }
451         
452         tria->tot= 19;
453         tria->index= num_tria_face;
454 }
455
456 static void widget_trias_draw(uiWidgetTrias *tria)
457 {
458         int a;
459         
460         glBegin(GL_TRIANGLES);
461         for(a=0; a<tria->tot; a++) {
462                 glVertex2fv(tria->vec[ tria->index[a][0] ]);
463                 glVertex2fv(tria->vec[ tria->index[a][1] ]);
464                 glVertex2fv(tria->vec[ tria->index[a][2] ]);
465         }
466         glEnd();
467         
468 }
469
470 static void widget_menu_trias(uiWidgetTrias *tria, rcti *rect)
471 {
472         float centx, centy, size, asp;
473         int a;
474                 
475         /* center position and size */
476         centx= rect->xmax - 0.5f*(rect->ymax-rect->ymin);
477         centy= rect->ymin + 0.5f*(rect->ymax-rect->ymin);
478         size= 0.4f*(rect->ymax-rect->ymin);
479         
480         /* XXX exception */
481         asp= ((float)rect->xmax-rect->xmin)/((float)rect->ymax-rect->ymin);
482         if(asp > 1.2f && asp < 2.6f)
483                 centx= rect->xmax - 0.3f*(rect->ymax-rect->ymin);
484         
485         for(a=0; a<6; a++) {
486                 tria->vec[a][0]= size*menu_tria_vert[a][0] + centx;
487                 tria->vec[a][1]= size*menu_tria_vert[a][1] + centy;
488         }
489
490         tria->tot= 2;
491         tria->index= menu_tria_face;
492 }
493
494 static void widget_check_trias(uiWidgetTrias *tria, rcti *rect)
495 {
496         float centx, centy, size;
497         int a;
498         
499         /* center position and size */
500         centx= rect->xmin + 0.5f*(rect->ymax-rect->ymin);
501         centy= rect->ymin + 0.5f*(rect->ymax-rect->ymin);
502         size= 0.5f*(rect->ymax-rect->ymin);
503         
504         for(a=0; a<6; a++) {
505                 tria->vec[a][0]= size*check_tria_vert[a][0] + centx;
506                 tria->vec[a][1]= size*check_tria_vert[a][1] + centy;
507         }
508         
509         tria->tot= 4;
510         tria->index= check_tria_face;
511 }
512
513
514 /* prepares shade colors */
515 static void shadecolors4(char *coltop, char *coldown, char *color, short shadetop, short shadedown)
516 {
517         
518         coltop[0]= CLAMPIS(color[0]+shadetop, 0, 255);
519         coltop[1]= CLAMPIS(color[1]+shadetop, 0, 255);
520         coltop[2]= CLAMPIS(color[2]+shadetop, 0, 255);
521         coltop[3]= color[3];
522
523         coldown[0]= CLAMPIS(color[0]+shadedown, 0, 255);
524         coldown[1]= CLAMPIS(color[1]+shadedown, 0, 255);
525         coldown[2]= CLAMPIS(color[2]+shadedown, 0, 255);
526         coldown[3]= color[3];
527 }
528
529 static void round_box_shade_col4(char *col1, char *col2, float fac)
530 {
531         int faci, facm;
532         char col[4];
533         
534         faci= floor(255.1f*fac);
535         facm= 255-faci;
536         
537         col[0]= (faci*col1[0] + facm*col2[0])>>8;
538         col[1]= (faci*col1[1] + facm*col2[1])>>8;
539         col[2]= (faci*col1[2] + facm*col2[2])>>8;
540         col[3]= (faci*col1[3] + facm*col2[3])>>8;
541         
542         glColor4ubv(col);
543 }
544
545 static void widgetbase_outline(uiWidgetBase *wtb)
546 {
547         int a;
548         
549         /* outline */
550         glBegin(GL_QUAD_STRIP);
551         for(a=0; a<wtb->totvert; a++) {
552                 glVertex2fv(wtb->outer_v[a]);
553                 glVertex2fv(wtb->inner_v[a]);
554         }
555         glVertex2fv(wtb->outer_v[0]);
556         glVertex2fv(wtb->inner_v[0]);
557         glEnd();
558 }
559
560 static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
561 {
562         int j, a;
563         
564         glEnable(GL_BLEND);
565
566         /* backdrop non AA */
567         if(wtb->inner) {
568                 if(wcol->shaded==0) {
569                         
570                         /* filled center, solid */
571                         glColor4ubv(wcol->inner);
572                         glBegin(GL_POLYGON);
573                         for(a=0; a<wtb->totvert; a++)
574                                 glVertex2fv(wtb->inner_v[a]);
575                         glEnd();
576
577                 }
578                 else {
579                         char col1[4], col2[4];
580                         
581                         shadecolors4(col1, col2, wcol->inner, wcol->shadetop, wcol->shadedown);
582                         
583                         glShadeModel(GL_SMOOTH);
584                         glBegin(GL_POLYGON);
585                         for(a=0; a<wtb->totvert; a++) {
586                                 round_box_shade_col4(col1, col2, wtb->inner_uv[a][1]);
587                                 glVertex2fv(wtb->inner_v[a]);
588                         }
589                         glEnd();
590                         glShadeModel(GL_FLAT);
591                 }
592         }
593         
594         /* for each AA step */
595         if(wtb->outline) {
596                 for(j=0; j<8; j++) {
597                         glTranslatef(1.0*jit[j][0], 1.0*jit[j][1], 0.0f);
598                         
599                         /* outline */
600                         glColor4ub(wcol->outline[0], wcol->outline[1], wcol->outline[2], 32);
601                         glBegin(GL_QUAD_STRIP);
602                         for(a=0; a<wtb->totvert; a++) {
603                                 glVertex2fv(wtb->outer_v[a]);
604                                 glVertex2fv(wtb->inner_v[a]);
605                         }
606                         glVertex2fv(wtb->outer_v[0]);
607                         glVertex2fv(wtb->inner_v[0]);
608                         glEnd();
609                 
610                         /* emboss bottom shadow */
611                         if(wtb->emboss) {
612                                 glColor4f(1.0f, 1.0f, 1.0f, 0.02f);
613                                 glBegin(GL_QUAD_STRIP);
614                                 for(a=0; a<wtb->halfwayvert; a++) {
615                                         glVertex2fv(wtb->outer_v[a]);
616                                         glVertex2f(wtb->outer_v[a][0], wtb->outer_v[a][1]-1.0f);
617                                 }
618                                 glEnd();
619                         }
620                         
621                         glTranslatef(-1.0*jit[j][0], -1.0*jit[j][1], 0.0f);
622                 }
623         }
624         
625         /* decoration */
626         if(wtb->tria1.tot || wtb->tria2.tot) {
627                 /* for each AA step */
628                 for(j=0; j<8; j++) {
629                         glTranslatef(1.0*jit[j][0], 1.0*jit[j][1], 0.0f);
630
631                         if(wtb->tria1.tot) {
632                                 glColor4ub(wcol->item[0], wcol->item[1], wcol->item[2], 32);
633                                 widget_trias_draw(&wtb->tria1);
634                         }
635                         if(wtb->tria2.tot) {
636                                 glColor4ub(wcol->item[0], wcol->item[1], wcol->item[2], 32);
637                                 widget_trias_draw(&wtb->tria2);
638                         }
639                 
640                         glTranslatef(-1.0*jit[j][0], -1.0*jit[j][1], 0.0f);
641                 }
642         }
643
644         glDisable(GL_BLEND);
645         
646 }
647
648 /* *********************** text/icon ************************************** */
649
650
651 /* icons have been standardized... and this call draws in untransformed coordinates */
652 #define ICON_HEIGHT             16.0f
653
654 static void widget_draw_icon(uiBut *but, BIFIconID icon, int blend, rcti *rect)
655 {
656         int xs=0, ys=0;
657         float aspect, height;
658         
659         /* this icon doesn't need draw... */
660         if(icon==ICON_BLANK1 && (but->flag & UI_ICON_SUBMENU)==0) return;
661         
662         /* we need aspect from block, for menus... these buttons are scaled in uiPositionBlock() */
663         aspect= but->block->aspect;
664         if(aspect != but->aspect) {
665                 /* prevent scaling up icon in pupmenu */
666                 if (aspect < 1.0f) {                    
667                         height= ICON_HEIGHT;
668                         aspect = 1.0f;
669                         
670                 }
671                 else 
672                         height= ICON_HEIGHT/aspect;
673         }
674         else
675                 height= ICON_HEIGHT;
676         
677         /* calculate blend color */
678         if ELEM3(but->type, TOG, ROW, TOGN) {
679                 if(but->flag & UI_SELECT);
680                 else if(but->flag & UI_ACTIVE);
681                 else blend= -60;
682         }
683         
684         glEnable(GL_BLEND);
685         
686         if(icon && icon!=ICON_BLANK1) {
687                 if(but->flag & UI_ICON_LEFT) {
688                         if (but->type==BUT_TOGDUAL) {
689                                 if (but->drawstr[0]) {
690                                         xs= rect->xmin-1;
691                                 } else {
692                                         xs= (rect->xmin+rect->xmax- height)/2;
693                                 }
694                         }
695                         else if (but->block->flag & UI_BLOCK_LOOP) {
696                                 if(but->type==SEARCH_MENU)
697                                         xs= rect->xmin+4;
698                                 else
699                                         xs= rect->xmin+1;
700                         }
701                         else if ((but->type==ICONROW) || (but->type==ICONTEXTROW)) {
702                                 xs= rect->xmin+3;
703                         }
704                         else {
705                                 xs= rect->xmin+4;
706                         }
707                         ys= (rect->ymin+rect->ymax- height)/2;
708                 }
709                 else {
710                         xs= (rect->xmin+rect->xmax- height)/2;
711                         ys= (rect->ymin+rect->ymax- height)/2;
712                 }
713         
714                 UI_icon_draw_aspect_blended(xs, ys, icon, aspect, blend);
715         }
716         
717         if(but->flag & UI_ICON_SUBMENU) {
718                 xs= rect->xmax-17;
719                 ys= (rect->ymin+rect->ymax- height)/2;
720                 
721                 UI_icon_draw_aspect_blended(xs, ys, ICON_RIGHTARROW_THIN, aspect, blend);
722         }
723         
724         glDisable(GL_BLEND);
725 }
726
727 /* sets but->ofs to make sure text is correctly visible */
728 static void ui_text_leftclip(uiFontStyle *fstyle, uiBut *but, rcti *rect)
729 {
730         int okwidth= rect->xmax-rect->xmin;
731         
732         /* need to set this first */
733         uiStyleFontSet(fstyle);
734
735         but->strwidth= BLF_width(but->drawstr);
736         but->ofs= 0;
737         
738         while(but->strwidth > okwidth ) {
739                 
740                 but->ofs++;
741                 but->strwidth= BLF_width(but->drawstr+but->ofs);
742                 
743                 /* textbut exception */
744                 if(but->editstr && but->pos != -1) {
745                         int pos= but->pos+strlen(but->str);
746                         
747                         if(pos-1 < but->ofs) {
748                                 pos= but->ofs-pos+1;
749                                 but->ofs -= pos;
750                                 if(but->ofs<0) {
751                                         but->ofs= 0;
752                                         pos--;
753                                 }
754                                 but->drawstr[ strlen(but->drawstr)-pos ]= 0;
755                         }
756                 }
757                 
758                 if(but->strwidth < 10) break;
759         }
760 }
761
762 static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, rcti *rect)
763 {
764 //      int transopts;
765         char *cpoin = NULL;
766         
767         uiStyleFontSet(fstyle);
768         
769         if(but->editstr || (but->flag & UI_TEXT_LEFT))
770                 fstyle->align= UI_STYLE_TEXT_LEFT;
771         else
772                 fstyle->align= UI_STYLE_TEXT_CENTER;                    
773                 
774         /* text button selection and cursor */
775         if(but->editstr && but->pos != -1) {
776                 short t, pos, ch;
777                 short selsta_tmp, selend_tmp, selsta_draw, selwidth_draw;
778                 
779                 if ((but->selend - but->selsta) > 0) {
780                         /* XXX weak, why is this? (ton) */
781                         t= but->str[0]?1:-2;
782                         
783                         /* text button selection */
784                         selsta_tmp = but->selsta + strlen(but->str);
785                         selend_tmp = but->selend + strlen(but->str);
786                         
787                         if(but->drawstr[0]!=0) {
788                                 ch= but->drawstr[selsta_tmp];
789                                 but->drawstr[selsta_tmp]= 0;
790                                 
791                                 selsta_draw = BLF_width(but->drawstr+but->ofs) + t;
792                                 
793                                 but->drawstr[selsta_tmp]= ch;
794                                 
795                                 ch= but->drawstr[selend_tmp];
796                                 but->drawstr[selend_tmp]= 0;
797                                 
798                                 selwidth_draw = BLF_width(but->drawstr+but->ofs) + t;
799                                 
800                                 but->drawstr[selend_tmp]= ch;
801                                 
802                                 glColor3ubv(wcol->item);
803                                 glRects(rect->xmin+selsta_draw+1, rect->ymin+2, rect->xmin+selwidth_draw+1, rect->ymax-2);
804                         }
805                 } else {
806                         /* text cursor */
807                         pos= but->pos+strlen(but->str);
808                         if(pos >= but->ofs) {
809                                 if(but->drawstr[0]!=0) {
810                                         ch= but->drawstr[pos];
811                                         but->drawstr[pos]= 0;
812                                         
813                                         t= BLF_width(but->drawstr+but->ofs) + 1;
814                                         
815                                         but->drawstr[pos]= ch;
816                                 }
817                                 else t= 1;
818                                 
819                                 glColor3ub(255,0,0);
820                                 glRects(rect->xmin+t, rect->ymin+2, rect->xmin+t+2, rect->ymax-2);
821                         }
822                 }
823         }
824         //      ui_rasterpos_safe(x, y, but->aspect);
825 //      if(but->type==IDPOIN) transopts= 0;     // no translation, of course!
826 //      else transopts= ui_translate_buttons();
827         
828         /* cut string in 2 parts - only for menu entries */
829         if(ELEM5(but->type, SLI, NUM, TEX, NUMSLI, NUMABS)==0) {
830                 cpoin= strchr(but->drawstr, '|');
831                 if(cpoin) *cpoin= 0;            
832         }
833         
834         glColor3ubv(wcol->text);
835         uiStyleFontDraw(fstyle, rect, but->drawstr+but->ofs);
836
837         /* part text right aligned */
838         if(cpoin) {
839                 fstyle->align= UI_STYLE_TEXT_RIGHT;
840                 rect->xmax-=5;
841                 uiStyleFontDraw(fstyle, rect, cpoin+1);
842                 *cpoin= '|';
843         }
844 }
845
846 /* draws text and icons for buttons */
847 static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, rcti *rect)
848 {
849         
850         if(but==NULL) return;
851         
852         /* cutting off from left part */
853         if ELEM3(but->type, NUM, NUMABS, TEX) { 
854                 ui_text_leftclip(fstyle, but, rect);
855         }
856         else but->ofs= 0;
857         
858         /* check for button text label */
859         if (but->type == ICONTEXTROW) {
860                 widget_draw_icon(but, (BIFIconID) (but->icon+but->iconadd), 0, rect);
861         }
862         else {
863                                 
864                 if(but->type==BUT_TOGDUAL) {
865                         int dualset= 0;
866                         if(but->pointype==SHO)
867                                 dualset= BTST( *(((short *)but->poin)+1), but->bitnr);
868                         else if(but->pointype==INT)
869                                 dualset= BTST( *(((int *)but->poin)+1), but->bitnr);
870                         
871                         widget_draw_icon(but, ICON_DOT, dualset?0:-100, rect);
872                 }
873                 
874                 /* If there's an icon too (made with uiDefIconTextBut) then draw the icon
875                 and offset the text label to accomodate it */
876                 
877                 if (but->flag & UI_HAS_ICON) {
878                         widget_draw_icon(but, but->icon+but->iconadd, 0, rect);
879                         
880                         rect->xmin += UI_icon_get_width(but->icon+but->iconadd);
881                         
882                         if(but->editstr || (but->flag & UI_TEXT_LEFT)) 
883                                 rect->xmin += 5;
884                 }
885                 else if(but->flag & UI_TEXT_LEFT)
886                         rect->xmin += 5;
887                 
888                 /* always draw text for textbutton cursor */
889                 widget_draw_text(fstyle, wcol, but, rect);
890
891         }
892 }
893
894
895
896 /* *********************** widget types ************************************* */
897
898
899 /*   uiWidgetStateColors
900  char inner_anim[4];
901  char inner_anim_sel[4];
902  char inner_key[4];
903  char inner_key_sel[4];
904  char inner_driven[4];
905  char inner_driven_sel[4];
906  
907 */
908
909 static struct uiWidgetStateColors wcol_state= {
910         {115, 190, 76, 255},
911         {90, 166, 51, 255},
912         {240, 235, 100, 255},
913         {148, 204, 76, 255},
914         {180, 0, 255, 255},
915         {153, 0, 230, 255}
916 };
917
918 /*  uiWidgetColors
919  float outline[3];
920  float inner[4];
921  float inner_sel[4];
922  float item[3];
923  float text[3];
924  float text_sel[3];
925
926  short shaded;
927  float shadetop, shadedown;
928 */      
929
930 static struct uiWidgetColors wcol_num= {
931         {25, 25, 25, 255},
932         {180, 180, 180, 255},
933         {153, 153, 153, 255},
934         {90, 90, 90, 255},
935         
936         {0, 0, 0, 255},
937         {255, 255, 255, 255},
938         
939         1,
940         -20, 0
941 };
942
943 static struct uiWidgetColors wcol_numslider= {
944         {25, 25, 25, 255},
945         {180, 180, 180, 255},
946         {153, 153, 153, 255},
947         {128, 128, 128, 255},
948         
949         {0, 0, 0, 255},
950         {255, 255, 255, 255},
951         
952         1,
953         -20, 0
954 };
955
956 static struct uiWidgetColors wcol_text= {
957         {25, 25, 25, 255},
958         {153, 153, 153, 255},
959         {153, 153, 153, 255},
960         {90, 90, 90, 255},
961         
962         {0, 0, 0, 255},
963         {255, 255, 255, 255},
964         
965         1,
966         0, 25
967 };
968
969 static struct uiWidgetColors wcol_option= {
970         {0, 0, 0, 255},
971         {70, 70, 70, 255},
972         {70, 70, 70, 255},
973         {255, 255, 255, 255},
974         
975         {0, 0, 0, 255},
976         {255, 255, 255, 255},
977         
978         1,
979         15, -15
980 };
981
982 /* button that shows popup */
983 static struct uiWidgetColors wcol_menu= {
984         {0, 0, 0, 255},
985         {70, 70, 70, 255},
986         {70, 70, 70, 255},
987         {255, 255, 255, 255},
988         
989         {255, 255, 255, 255},
990         {204, 204, 204, 255},
991         
992         1,
993         15, -15
994 };
995
996 /* button that starts pulldown */
997 static struct uiWidgetColors wcol_pulldown= {
998         {0, 0, 0, 255},
999         {63, 63, 63, 255},
1000         {86, 128, 194, 255},
1001         {255, 255, 255, 255},
1002         
1003         {0, 0, 0, 255},
1004         {0, 0, 0, 255},
1005         
1006         0,
1007         25, -20
1008 };
1009
1010 /* button inside menu */
1011 static struct uiWidgetColors wcol_menu_item= {
1012         {0, 0, 0, 255},
1013         {0, 0, 0, 0},
1014         {86, 128, 194, 255},
1015         {255, 255, 255, 255},
1016         
1017         {255, 255, 255, 255},
1018         {0, 0, 0, 255},
1019         
1020         0,
1021         38, 0
1022 };
1023
1024 /* backdrop menu + title text color */
1025 static struct uiWidgetColors wcol_menu_back= {
1026         {0, 0, 0, 255},
1027         {25, 25, 25, 230},
1028         {45, 45, 45, 230},
1029         {255, 255, 255, 255},
1030         
1031         {255, 255, 255, 255},
1032         {255, 255, 255, 255},
1033         
1034         0,
1035         25, -20
1036 };
1037
1038
1039 static struct uiWidgetColors wcol_radio= {
1040         {0, 0, 0, 255},
1041         {70, 70, 70, 255},
1042         {86, 128, 194, 255},
1043         {255, 255, 255, 255},
1044         
1045         {255, 255, 255, 255},
1046         {0, 0, 0, 255},
1047         
1048         1,
1049         15, -15
1050 };
1051
1052 static struct uiWidgetColors wcol_regular= {
1053         {25, 25, 25, 255},
1054         {153, 153, 153, 255},
1055         {100, 100, 100, 255},
1056         {25, 25, 25, 255},
1057         
1058         {0, 0, 0, 255},
1059         {255, 255, 255, 255},
1060         
1061         0,
1062         0, 0
1063 };
1064
1065 static struct uiWidgetColors wcol_tool= {
1066         {25, 25, 25, 255},
1067         {153, 153, 153, 255},
1068         {100, 100, 100, 255},
1069         {25, 25, 25, 255},
1070         
1071         {0, 0, 0, 255},
1072         {255, 255, 255, 255},
1073         
1074         1,
1075         25, -25
1076 };
1077
1078 static struct uiWidgetColors wcol_box= {
1079         {25, 25, 25, 255},
1080         {128, 128, 128, 255},
1081         {100, 100, 100, 255},
1082         {25, 25, 25, 255},
1083         
1084         {0, 0, 0, 255},
1085         {255, 255, 255, 255},
1086         
1087         0,
1088         0, 0
1089 };
1090
1091 /* free wcol struct to play with */
1092 static struct uiWidgetColors wcol_tmp= {
1093         {0, 0, 0, 255},
1094         {128, 128, 128, 255},
1095         {100, 100, 100, 255},
1096         {25, 25, 25, 255},
1097         
1098         {0, 0, 0, 255},
1099         {255, 255, 255, 255},
1100         
1101         0,
1102         0, 0
1103 };
1104
1105
1106 /* called for theme init (new theme) and versions */
1107 void ui_widget_color_init(ThemeUI *tui)
1108 {
1109
1110         tui->wcol_regular= wcol_regular;
1111         tui->wcol_tool= wcol_tool;
1112         tui->wcol_radio= wcol_radio;
1113         tui->wcol_text= wcol_text;
1114         tui->wcol_option= wcol_option;
1115         tui->wcol_num= wcol_num;
1116         tui->wcol_numslider= wcol_numslider;
1117         tui->wcol_menu= wcol_menu;
1118         tui->wcol_pulldown= wcol_pulldown;
1119         tui->wcol_menu_back= wcol_menu_back;
1120         tui->wcol_menu_item= wcol_menu_item;
1121         tui->wcol_box= wcol_box;
1122 }
1123
1124 /* ************ button callbacks, state ***************** */
1125
1126 /* copy colors from theme, and set changes in it based on state */
1127 static void widget_state(uiWidgetType *wt, int state)
1128 {
1129         wt->wcol= *(wt->wcol_theme);
1130         
1131         if(state & UI_SELECT) {
1132                 if(state & UI_BUT_ANIMATED_KEY)
1133                         QUATCOPY(wt->wcol.inner, wcol_state.inner_key_sel)
1134                 else if(state & UI_BUT_ANIMATED)
1135                         QUATCOPY(wt->wcol.inner, wcol_state.inner_anim_sel)
1136                 else if(state & UI_BUT_DRIVEN)
1137                         QUATCOPY(wt->wcol.inner, wcol_state.inner_driven_sel)
1138                 else
1139                         QUATCOPY(wt->wcol.inner, wt->wcol.inner_sel)
1140
1141                 VECCOPY(wt->wcol.text, wt->wcol.text_sel);
1142                 
1143                 /* only flip shade if it's not "pushed in" already */
1144                 if(wt->wcol.shaded && wt->wcol.shadetop>wt->wcol.shadedown) {
1145                         SWAP(short, wt->wcol.shadetop, wt->wcol.shadedown);
1146                 }
1147         }
1148         else {
1149                 if(state & UI_BUT_ANIMATED_KEY)
1150                         QUATCOPY(wt->wcol.inner, wcol_state.inner_key)
1151                 else if(state & UI_BUT_ANIMATED)
1152                         QUATCOPY(wt->wcol.inner, wcol_state.inner_anim)
1153                 else if(state & UI_BUT_DRIVEN)
1154                         QUATCOPY(wt->wcol.inner, wcol_state.inner_driven)
1155
1156                 if(state & UI_ACTIVE) { /* mouse over? */
1157                         wt->wcol.inner[0]= wt->wcol.inner[0]>=240? 255 : wt->wcol.inner[0]+15;
1158                         wt->wcol.inner[1]= wt->wcol.inner[1]>=240? 255 : wt->wcol.inner[1]+15;
1159                         wt->wcol.inner[2]= wt->wcol.inner[2]>=240? 255 : wt->wcol.inner[2]+15;
1160                 }
1161         }
1162 }
1163
1164 /* labels use theme colors for text */
1165 static void widget_state_label(uiWidgetType *wt, int state)
1166 {
1167         /* call this for option button */
1168         widget_state(wt, state);
1169
1170         if(state & UI_SELECT)
1171                 UI_GetThemeColor4ubv(TH_TEXT_HI, wt->wcol.text);
1172         else
1173                 UI_GetThemeColor4ubv(TH_TEXT, wt->wcol.text);
1174         
1175 }
1176
1177
1178 /* special case, button that calls pulldown */
1179 static void widget_state_pulldown(uiWidgetType *wt, int state)
1180 {
1181         wt->wcol= *(wt->wcol_theme);
1182         
1183         QUATCOPY(wt->wcol.inner, wt->wcol.inner_sel);
1184         VECCOPY(wt->wcol.outline, wt->wcol.inner);
1185
1186         if(state & UI_ACTIVE)
1187                 VECCOPY(wt->wcol.text, wt->wcol.text_sel);
1188 }
1189
1190 /* special case, menu items */
1191 static void widget_state_menu_item(uiWidgetType *wt, int state)
1192 {
1193         wt->wcol= *(wt->wcol_theme);
1194         
1195         if(state & (UI_BUT_DISABLED|UI_BUT_INACTIVE)) {
1196                 wt->wcol.text[0]= 0.5f*(wt->wcol.text[0]+wt->wcol.text_sel[0]);
1197                 wt->wcol.text[1]= 0.5f*(wt->wcol.text[1]+wt->wcol.text_sel[1]);
1198                 wt->wcol.text[2]= 0.5f*(wt->wcol.text[2]+wt->wcol.text_sel[2]);
1199         }
1200         else if(state & UI_ACTIVE) {
1201                 QUATCOPY(wt->wcol.inner, wt->wcol.inner_sel);
1202                 VECCOPY(wt->wcol.text, wt->wcol.text_sel);
1203                 
1204                 wt->wcol.shaded= 1;
1205         }
1206 }
1207
1208
1209 /* ************ menu backdrop ************************* */
1210
1211 /* outside of rect, rad to left/bottom/right */
1212 static void widget_softshadow(rcti *rect, int roundboxalign, float radin, float radout)
1213 {
1214         uiWidgetBase wtb;
1215         rcti rect1= *rect;
1216         float alpha, alphastep;
1217         int step, tot, a;
1218         
1219         /* prevent tooltips to not show round shadow */
1220         if( 2.0f*radout > 0.2f*(rect1.ymax-rect1.ymin) )
1221                 rect1.ymax -= 0.2f*(rect1.ymax-rect1.ymin);
1222         else
1223                 rect1.ymax -= 2.0f*radout;
1224         
1225         /* inner part */
1226         tot= round_box_shadow_edges(wtb.inner_v, &rect1, radin, roundboxalign & 12, 0.0f);
1227         
1228         /* inverse linear shadow alpha */
1229         alpha= 0.15;
1230         alphastep= 0.67;
1231         
1232         for(step= 1; step<=radout; step++, alpha*=alphastep) {
1233                 round_box_shadow_edges(wtb.outer_v, &rect1, radin, 15, (float)step);
1234                 
1235                 glColor4f(0.0f, 0.0f, 0.0f, alpha);
1236                 
1237                 glBegin(GL_QUAD_STRIP);
1238                 for(a=0; a<tot; a++) {
1239                         glVertex2fv(wtb.outer_v[a]);
1240                         glVertex2fv(wtb.inner_v[a]);
1241                 }
1242                 glEnd();
1243         }
1244         
1245 }
1246
1247 static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int direction)
1248 {
1249         uiWidgetBase wtb;
1250         int roundboxalign= 15;
1251         
1252         widget_init(&wtb);
1253         
1254         /* menu is 2nd level or deeper */
1255         if (flag & UI_BLOCK_POPUP) {
1256                 //rect->ymin -= 4.0;
1257                 //rect->ymax += 4.0;
1258         }
1259         else if (direction == UI_DOWN) {
1260                 roundboxalign= 12;
1261                 rect->ymin -= 4.0;
1262         } 
1263         else if (direction == UI_TOP) {
1264                 roundboxalign= 3;
1265                 rect->ymax += 4.0;
1266         }
1267         
1268         glEnable(GL_BLEND);
1269         widget_softshadow(rect, roundboxalign, 5.0f, 8.0f);
1270         
1271         round_box_edges(&wtb, roundboxalign, rect, 5.0f);
1272         wtb.emboss= 0;
1273         widgetbase_draw(&wtb, wcol);
1274         
1275         glDisable(GL_BLEND);
1276 }
1277
1278
1279 static void ui_hsv_cursor(float x, float y)
1280 {
1281         
1282         glPushMatrix();
1283         glTranslatef(x, y, 0.0f);
1284         
1285         glColor3f(1.0f, 1.0f, 1.0f);
1286         glutil_draw_filled_arc(0.0f, M_PI*2.0, 3.0f, 8);
1287         
1288         glEnable(GL_BLEND);
1289         glEnable(GL_LINE_SMOOTH );
1290         glColor3f(0.0f, 0.0f, 0.0f);
1291         glutil_draw_lined_arc(0.0f, M_PI*2.0, 3.0f, 12);
1292         glDisable(GL_BLEND);
1293         glDisable(GL_LINE_SMOOTH );
1294         
1295         glPopMatrix();
1296         
1297 }
1298
1299 void ui_hsvcircle_vals_from_pos(float *valrad, float *valdist, rcti *rect, float mx, float my)
1300 {
1301         /* duplication of code... well, simple is better now */
1302         float centx= (float)(rect->xmin + rect->xmax)/2;
1303         float centy= (float)(rect->ymin + rect->ymax)/2;
1304         float radius, dist;
1305         
1306         if( rect->xmax-rect->xmin > rect->ymax-rect->ymin )
1307                 radius= (float)(rect->ymax - rect->ymin)/2; 
1308         else
1309                 radius= (float)(rect->xmax - rect->xmin)/2; 
1310
1311         mx-= centx;
1312         my-= centy;
1313         dist= sqrt( mx*mx + my*my);
1314         if(dist < radius)
1315                 *valdist= dist/radius;
1316         else
1317                 *valdist= 1.0f;
1318         
1319         *valrad= atan2(mx, my)/(2.0f*M_PI) + 0.5f;
1320 }
1321
1322 void ui_draw_but_HSVCIRCLE(uiBut *but, rcti *rect)
1323 {
1324         /* gouraud triangle fan */
1325         float radstep, ang= 0.0f;
1326         float centx, centy, radius;
1327         float hsv[3], col[3], colcent[3];
1328         int a, tot= 32;
1329         
1330         radstep= 2.0f*M_PI/(float)tot;
1331         centx= (float)(rect->xmin + rect->xmax)/2;
1332         centy= (float)(rect->ymin + rect->ymax)/2;
1333         
1334         if( rect->xmax-rect->xmin > rect->ymax-rect->ymin )
1335                 radius= (float)(rect->ymax - rect->ymin)/2; 
1336         else
1337                 radius= (float)(rect->xmax - rect->xmin)/2; 
1338         
1339         /* color */
1340         VECCOPY(hsv, but->hsv);
1341         hsv[0]= hsv[1]= 0.0f;
1342         hsv_to_rgb(hsv[0], hsv[1], hsv[2], colcent, colcent+1, colcent+2);
1343         
1344         glShadeModel(GL_SMOOTH);
1345
1346         glBegin(GL_TRIANGLE_FAN);
1347         glColor3fv(colcent);
1348         glVertex2f( centx, centy);
1349         
1350         for(a=0; a<=tot; a++, ang+=radstep) {
1351                 float si= sin(ang);
1352                 float co= cos(ang);
1353                 
1354                 ui_hsvcircle_vals_from_pos(hsv, hsv+1, rect, centx + co*radius, centy + si*radius);
1355                 hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col+1, col+2);
1356                 glColor3fv(col);
1357                 glVertex2f( centx + co*radius, centy + si*radius);
1358         }
1359         glEnd();
1360         
1361         glShadeModel(GL_FLAT);
1362         
1363         /* fully rounded outline */
1364         glPushMatrix();
1365         glTranslatef(centx, centy, 0.0f);
1366         glEnable(GL_BLEND);
1367         glEnable(GL_LINE_SMOOTH );
1368         glColor3f(0.0f, 0.0f, 0.0f);
1369         glutil_draw_lined_arc(0.0f, M_PI*2.0, radius, tot);
1370         glDisable(GL_BLEND);
1371         glDisable(GL_LINE_SMOOTH );
1372         glPopMatrix();
1373
1374         /* cursor */
1375         ang= 2.0f*M_PI*but->hsv[0] + 0.5f*M_PI;
1376         radius= but->hsv[1]*radius;
1377         ui_hsv_cursor(centx + cos(-ang)*radius, centy + sin(-ang)*radius);
1378         
1379 }
1380
1381 /* ************ custom buttons, old stuff ************** */
1382
1383 /* draws in resolution of 20x4 colors */
1384 static void ui_draw_but_HSVCUBE(uiBut *but, rcti *rect)
1385 {
1386         int a;
1387         float h,s,v;
1388         float dx, dy, sx1, sx2, sy, x, y;
1389         float col0[4][3];       // left half, rect bottom to top
1390         float col1[4][3];       // right half, rect bottom to top
1391         
1392         h= but->hsv[0];
1393         s= but->hsv[1];
1394         v= but->hsv[2];
1395         
1396         /* draw series of gouraud rects */
1397         glShadeModel(GL_SMOOTH);
1398         
1399         if(but->a1==0) {        // H and V vary
1400                 hsv_to_rgb(0.0, s, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1401                 hsv_to_rgb(0.0, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
1402                 hsv_to_rgb(0.0, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
1403                 hsv_to_rgb(0.0, s, 1.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
1404                 x= h; y= v;
1405         }
1406         else if(but->a1==1) {   // H and S vary
1407                 hsv_to_rgb(0.0, 0.0, v,   &col1[0][0], &col1[0][1], &col1[0][2]);
1408                 hsv_to_rgb(0.0, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
1409                 hsv_to_rgb(0.0, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
1410                 hsv_to_rgb(0.0, 1.0, v,   &col1[3][0], &col1[3][1], &col1[3][2]);
1411                 x= h; y= s;
1412         }
1413         else if(but->a1==2) {   // S and V vary
1414                 hsv_to_rgb(h, 0.0, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1415                 hsv_to_rgb(h, 0.333, 0.0, &col1[1][0], &col1[1][1], &col1[1][2]);
1416                 hsv_to_rgb(h, 0.666, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]);
1417                 hsv_to_rgb(h, 1.0, 0.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
1418                 x= v; y= s;
1419         }
1420         else if(but->a1==3) {           // only hue slider
1421                 hsv_to_rgb(0.0, 1.0, 1.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1422                 VECCOPY(col1[1], col1[0]);
1423                 VECCOPY(col1[2], col1[0]);
1424                 VECCOPY(col1[3], col1[0]);
1425                 x= h; y= 0.5;
1426         }
1427         
1428         for(dx=0.0; dx<1.0; dx+= 0.05) {
1429                 // previous color
1430                 VECCOPY(col0[0], col1[0]);
1431                 VECCOPY(col0[1], col1[1]);
1432                 VECCOPY(col0[2], col1[2]);
1433                 VECCOPY(col0[3], col1[3]);
1434                 
1435                 // new color
1436                 if(but->a1==0) {        // H and V vary
1437                         hsv_to_rgb(dx, s, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1438                         hsv_to_rgb(dx, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
1439                         hsv_to_rgb(dx, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
1440                         hsv_to_rgb(dx, s, 1.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
1441                 }
1442                 else if(but->a1==1) {   // H and S vary
1443                         hsv_to_rgb(dx, 0.0, v,   &col1[0][0], &col1[0][1], &col1[0][2]);
1444                         hsv_to_rgb(dx, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
1445                         hsv_to_rgb(dx, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
1446                         hsv_to_rgb(dx, 1.0, v,   &col1[3][0], &col1[3][1], &col1[3][2]);
1447                 }
1448                 else if(but->a1==2) {   // S and V vary
1449                         hsv_to_rgb(h, 0.0, dx,   &col1[0][0], &col1[0][1], &col1[0][2]);
1450                         hsv_to_rgb(h, 0.333, dx, &col1[1][0], &col1[1][1], &col1[1][2]);
1451                         hsv_to_rgb(h, 0.666, dx, &col1[2][0], &col1[2][1], &col1[2][2]);
1452                         hsv_to_rgb(h, 1.0, dx,   &col1[3][0], &col1[3][1], &col1[3][2]);
1453                 }
1454                 else if(but->a1==3) {   // only H
1455                         hsv_to_rgb(dx, 1.0, 1.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1456                         VECCOPY(col1[1], col1[0]);
1457                         VECCOPY(col1[2], col1[0]);
1458                         VECCOPY(col1[3], col1[0]);
1459                 }
1460                 
1461                 // rect
1462                 sx1= rect->xmin + dx*(rect->xmax-rect->xmin);
1463                 sx2= rect->xmin + (dx+0.05)*(rect->xmax-rect->xmin);
1464                 sy= rect->ymin;
1465                 dy= (rect->ymax-rect->ymin)/3.0;
1466                 
1467                 glBegin(GL_QUADS);
1468                 for(a=0; a<3; a++, sy+=dy) {
1469                         glColor3fv(col0[a]);
1470                         glVertex2f(sx1, sy);
1471                         
1472                         glColor3fv(col1[a]);
1473                         glVertex2f(sx2, sy);
1474                         
1475                         glColor3fv(col1[a+1]);
1476                         glVertex2f(sx2, sy+dy);
1477                         
1478                         glColor3fv(col0[a+1]);
1479                         glVertex2f(sx1, sy+dy);
1480                 }
1481                 glEnd();
1482         }
1483         
1484         glShadeModel(GL_FLAT);
1485         
1486         /* cursor */
1487         x= rect->xmin + x*(rect->xmax-rect->xmin);
1488         y= rect->ymin + y*(rect->ymax-rect->ymin);
1489         CLAMP(x, rect->xmin+3.0, rect->xmax-3.0);
1490         CLAMP(y, rect->ymin+3.0, rect->ymax-3.0);
1491         
1492         ui_hsv_cursor(x, y);
1493         
1494         /* outline */
1495         glColor3ub(0,  0,  0);
1496         fdrawbox((rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax));
1497 }
1498
1499 /* vertical 'value' slider, using new widget code */
1500 static void ui_draw_but_HSV_v(uiBut *but, rcti *rect)
1501 {
1502         uiWidgetBase wtb;
1503         float rad= 0.5f*(rect->xmax - rect->xmin);
1504         float x, y;
1505         
1506         widget_init(&wtb);
1507         
1508         /* fully rounded */
1509         round_box_edges(&wtb, 15, rect, rad);
1510         
1511         /* setup temp colors */
1512         wcol_tmp.outline[0]= wcol_tmp.outline[1]= wcol_tmp.outline[2]= 0;
1513         wcol_tmp.inner[0]= wcol_tmp.inner[1]= wcol_tmp.inner[2]= 128;
1514         wcol_tmp.shadetop= 127;
1515         wcol_tmp.shadedown= -128;
1516         wcol_tmp.shaded= 1;
1517         
1518         widgetbase_draw(&wtb, &wcol_tmp);
1519
1520         /* cursor */
1521         x= rect->xmin + 0.5f*(rect->xmax-rect->xmin);
1522         y= rect->ymin + but->hsv[2]*(rect->ymax-rect->ymin);
1523         CLAMP(y, rect->ymin+3.0, rect->ymax-3.0);
1524         
1525         ui_hsv_cursor(x, y);
1526         
1527 }
1528
1529 /* ************ button callbacks, draw ***************** */
1530
1531 static void widget_numbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
1532 {
1533         uiWidgetBase wtb;
1534         float rad= 0.5f*(rect->ymax - rect->ymin);
1535         
1536         widget_init(&wtb);
1537         
1538         /* fully rounded */
1539         round_box_edges(&wtb, roundboxalign, rect, rad);
1540         
1541         /* decoration */
1542         if(!(state & UI_TEXTINPUT)) {
1543                 widget_num_tria(&wtb.tria1, rect, 0.6f, 0);
1544                 widget_num_tria(&wtb.tria2, rect, 0.6f, 'r');
1545         }       
1546         widgetbase_draw(&wtb, wcol);
1547         
1548         /* text space */
1549         rect->xmin += (rect->ymax-rect->ymin);
1550         rect->xmax -= (rect->ymax-rect->ymin);
1551
1552 }
1553
1554
1555 static int ui_link_bezier_points(rcti *rect, float coord_array[][2], int resol)
1556 {
1557         float dist, vec[4][2];
1558
1559         vec[0][0]= rect->xmin;
1560         vec[0][1]= rect->ymin;
1561         vec[3][0]= rect->xmax;
1562         vec[3][1]= rect->ymax;
1563         
1564         dist= 0.5f*ABS(vec[0][0] - vec[3][0]);
1565         
1566         vec[1][0]= vec[0][0]+dist;
1567         vec[1][1]= vec[0][1];
1568         
1569         vec[2][0]= vec[3][0]-dist;
1570         vec[2][1]= vec[3][1];
1571         
1572         forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0], coord_array[0], resol, 2);
1573         forward_diff_bezier(vec[0][1], vec[1][1], vec[2][1], vec[3][1], coord_array[0]+1, resol, 2);
1574         
1575         return 1;
1576 }
1577
1578 #define LINK_RESOL      24
1579 void ui_draw_link_bezier(rcti *rect)
1580 {
1581         float coord_array[LINK_RESOL+1][2];
1582         
1583         if(ui_link_bezier_points(rect, coord_array, LINK_RESOL)) {
1584                 float dist;
1585                 int i;
1586                 
1587                 /* we can reuse the dist variable here to increment the GL curve eval amount*/
1588                 dist = 1.0f/(float)LINK_RESOL;
1589                 
1590                 glEnable(GL_BLEND);
1591                 glEnable(GL_LINE_SMOOTH);
1592                 
1593                 glBegin(GL_LINE_STRIP);
1594                 for(i=0; i<=LINK_RESOL; i++) {
1595                         glVertex2fv(coord_array[i]);
1596                 }
1597                 glEnd();
1598                 
1599                 glDisable(GL_BLEND);
1600                 glDisable(GL_LINE_SMOOTH);
1601
1602         }
1603 }
1604
1605
1606 static void widget_link(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
1607 {
1608
1609         if(but->flag & UI_SELECT) {
1610                 rcti rectlink;
1611                 
1612                 UI_ThemeColor(TH_TEXT_HI);
1613                 
1614                 rectlink.xmin= (rect->xmin+rect->xmax)/2;
1615                 rectlink.ymin= (rect->ymin+rect->ymax)/2;
1616                 rectlink.xmax= but->linkto[0];
1617                 rectlink.ymax= but->linkto[1];
1618                 
1619                 ui_draw_link_bezier(&rectlink);
1620         }
1621 }
1622
1623
1624 static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
1625 {
1626         uiWidgetBase wtb, wtb1;
1627         rcti rect1;
1628         double value;
1629         float offs, fac;
1630         char outline[3];
1631         
1632         widget_init(&wtb);
1633         widget_init(&wtb1);
1634         
1635         /* backdrop first */
1636         
1637         /* fully rounded */
1638         offs= 0.5f*(rect->ymax - rect->ymin);
1639         round_box_edges(&wtb, roundboxalign, rect, offs);
1640
1641         wtb.outline= 0;
1642         widgetbase_draw(&wtb, wcol);
1643         
1644         /* slider part */
1645         VECCOPY(outline, wcol->outline);
1646         VECCOPY(wcol->outline, wcol->item);
1647         VECCOPY(wcol->inner, wcol->item);
1648         SWAP(short, wcol->shadetop, wcol->shadedown);
1649         
1650         rect1= *rect;
1651         
1652         value= ui_get_but_val(but);
1653         fac= (value-but->softmin)*(rect1.xmax - rect1.xmin - offs)/(but->softmax - but->softmin);
1654         
1655         /* left part of slider, always rounded */
1656         rect1.xmax= rect1.xmin + ceil(offs+1.0f);
1657         round_box_edges(&wtb1, roundboxalign & ~6, &rect1, offs);
1658         wtb1.outline= 0;
1659         widgetbase_draw(&wtb1, wcol);
1660         
1661         /* right part of slider, interpolate roundness */
1662         rect1.xmax= rect1.xmin + fac + offs;
1663         rect1.xmin+=  floor(offs-1.0f);
1664         if(rect1.xmax + offs > rect->xmax)
1665                 offs*= (rect1.xmax + offs - rect->xmax)/offs;
1666         else 
1667                 offs= 0.0f;
1668         round_box_edges(&wtb1, roundboxalign & ~9, &rect1, offs);
1669         
1670         widgetbase_draw(&wtb1, wcol);
1671         VECCOPY(wcol->outline, outline);
1672         SWAP(short, wcol->shadetop, wcol->shadedown);
1673         
1674         /* outline */
1675         wtb.outline= 1;
1676         wtb.inner= 0;
1677         widgetbase_draw(&wtb, wcol);
1678         
1679         /* text space */
1680         rect->xmin += (rect->ymax-rect->ymin);
1681         rect->xmax -= (rect->ymax-rect->ymin);
1682         
1683 }
1684
1685 static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
1686 {
1687         uiWidgetBase wtb;
1688         float col[4];
1689         
1690         widget_init(&wtb);
1691         
1692         /* half rounded */
1693         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
1694                 
1695         ui_get_but_vectorf(but, col);
1696         wcol->inner[0]= FTOCHAR(col[0]);
1697         wcol->inner[1]= FTOCHAR(col[1]);
1698         wcol->inner[2]= FTOCHAR(col[2]);
1699         
1700         widgetbase_draw(&wtb, wcol);
1701         
1702 }
1703
1704
1705 static void widget_textbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
1706 {
1707         uiWidgetBase wtb;
1708         
1709         widget_init(&wtb);
1710         
1711         /* half rounded */
1712         round_box_edges(&wtb, roundboxalign, rect, 5.0f);
1713         
1714         widgetbase_draw(&wtb, wcol);
1715
1716 }
1717
1718
1719 static void widget_menubut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
1720 {
1721         uiWidgetBase wtb;
1722         
1723         widget_init(&wtb);
1724         
1725         /* half rounded */
1726         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
1727         
1728         /* decoration */
1729         widget_menu_trias(&wtb.tria1, rect);
1730         
1731         widgetbase_draw(&wtb, wcol);
1732         
1733         /* text space */
1734         rect->xmax -= (rect->ymax-rect->ymin);
1735         
1736 }
1737
1738 static void widget_pulldownbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
1739 {
1740         if(state & UI_ACTIVE) {
1741                 uiWidgetBase wtb;
1742                 float rad= 0.5f*(rect->ymax - rect->ymin);
1743                 
1744                 widget_init(&wtb);
1745                 
1746                 /* fully rounded */
1747                 round_box_edges(&wtb, roundboxalign, rect, rad);
1748                 
1749                 widgetbase_draw(&wtb, wcol);
1750         }
1751 }
1752
1753 static void widget_menu_itembut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
1754 {
1755         uiWidgetBase wtb;
1756         
1757         widget_init(&wtb);
1758         
1759         /* not rounded, no outline */
1760         wtb.outline= 0;
1761         round_box_edges(&wtb, 0, rect, 0.0f);
1762         
1763         widgetbase_draw(&wtb, wcol);
1764 }
1765
1766
1767 static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
1768 {
1769         uiWidgetBase wtb;
1770         rcti recttemp= *rect;
1771         int delta;
1772         
1773         widget_init(&wtb);
1774         
1775         /* square */
1776         recttemp.xmax= recttemp.xmin + (recttemp.ymax-recttemp.ymin);
1777         
1778         /* smaller */
1779         delta= 1 + (recttemp.ymax-recttemp.ymin)/8;
1780         recttemp.xmin+= delta;
1781         recttemp.ymin+= delta;
1782         recttemp.xmax-= delta;
1783         recttemp.ymax-= delta;
1784         
1785         /* half rounded */
1786         round_box_edges(&wtb, 15, &recttemp, 4.0f);
1787         
1788         /* decoration */
1789         if(state & UI_SELECT) {
1790                 widget_check_trias(&wtb.tria1, &recttemp);
1791         }
1792         
1793         widgetbase_draw(&wtb, wcol);
1794         
1795         /* text space */
1796         rect->xmin += (rect->ymax-rect->ymin)*0.7 + delta;
1797 }
1798
1799
1800 static void widget_radiobut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
1801 {
1802         uiWidgetBase wtb;
1803         
1804         widget_init(&wtb);
1805         
1806         /* half rounded */
1807         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
1808         
1809         widgetbase_draw(&wtb, wcol);
1810
1811 }
1812
1813 static void widget_but(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
1814 {
1815         uiWidgetBase wtb;
1816         
1817         widget_init(&wtb);
1818         
1819         /* half rounded */
1820         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
1821                 
1822         widgetbase_draw(&wtb, wcol);
1823
1824 }
1825
1826 static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
1827 {
1828         uiWidgetBase wtb;
1829         float rad= 0.5f*(rect->ymax - rect->ymin);
1830         
1831         widget_init(&wtb);
1832         
1833         /* fully rounded */
1834         round_box_edges(&wtb, roundboxalign, rect, rad);
1835
1836         widgetbase_draw(&wtb, wcol);
1837 }
1838
1839 static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *wt, rcti *rect)
1840 {
1841         uiWidgetBase wtb;
1842         char col[4];
1843         
1844         /* state copy! */
1845         wt->wcol= *(wt->wcol_theme);
1846         
1847         widget_init(&wtb);
1848         
1849         if(but->block->drawextra) {
1850                 /* note: drawextra can change rect +1 or -1, to match round errors of existing previews */
1851                 but->block->drawextra(C, but->poin, rect);
1852                 
1853                 /* make mask to draw over image */
1854                 UI_GetThemeColor3ubv(TH_BACK, col);
1855                 glColor3ubv(col);
1856                 
1857                 round_box__edges(&wtb, 15, rect, 0.0f, 4.0);
1858                 widgetbase_outline(&wtb);
1859         }
1860         
1861         /* outline */
1862         round_box_edges(&wtb, 15, rect, 5.0f);
1863         wtb.outline= 1;
1864         wtb.inner= 0;
1865         widgetbase_draw(&wtb, &wt->wcol);
1866         
1867 }
1868
1869
1870 static void widget_disabled(rcti *rect)
1871 {
1872         float col[4];
1873         
1874         glEnable(GL_BLEND);
1875         
1876         /* can't use theme TH_BACK or TH_PANEL... undefined */
1877         glGetFloatv(GL_COLOR_CLEAR_VALUE, col);
1878         glColor4f(col[0], col[1], col[2], 0.5f);
1879         /* need -1 and +1 to make it work right for aligned buttons,
1880          * but problem may be somewhere else? */
1881         glRectf(rect->xmin-1, rect->ymin, rect->xmax, rect->ymax+1);
1882
1883         glDisable(GL_BLEND);
1884 }
1885
1886 static uiWidgetType *widget_type(uiWidgetTypeEnum type)
1887 {
1888         bTheme *btheme= U.themes.first;
1889         static uiWidgetType wt;
1890         
1891         /* defaults */
1892         wt.wcol_theme= &btheme->tui.wcol_regular;
1893         wt.state= widget_state;
1894         wt.draw= widget_but;
1895         wt.custom= NULL;
1896         wt.text= widget_draw_text_icon;
1897         
1898         switch(type) {
1899                 case UI_WTYPE_LABEL:
1900                         wt.draw= NULL;
1901                         wt.state= widget_state_label;
1902                         break;
1903                         
1904                 case UI_WTYPE_TOGGLE:
1905                         break;
1906                         
1907                 case UI_WTYPE_OPTION:
1908                         wt.wcol_theme= &btheme->tui.wcol_option;
1909                         wt.draw= widget_optionbut;
1910                         wt.state= widget_state_label;
1911                         break;
1912                         
1913                 case UI_WTYPE_RADIO:
1914                         wt.wcol_theme= &btheme->tui.wcol_radio;
1915                         wt.draw= widget_radiobut;
1916                         break;
1917                         
1918                 case UI_WTYPE_NUMBER:
1919                         wt.wcol_theme= &btheme->tui.wcol_num;
1920                         wt.draw= widget_numbut;
1921                         break;
1922                         
1923                 case UI_WTYPE_SLIDER:
1924                         wt.wcol_theme= &btheme->tui.wcol_numslider;
1925                         wt.custom= widget_numslider;
1926                         break;
1927                         
1928                 case UI_WTYPE_EXEC:
1929                         wt.wcol_theme= &btheme->tui.wcol_tool;
1930                         wt.draw= widget_roundbut;
1931                         break;
1932                         
1933                         
1934                         /* strings */
1935                 case UI_WTYPE_NAME:
1936                         wt.wcol_theme= &btheme->tui.wcol_text;
1937                         wt.draw= widget_textbut;
1938                         break;
1939                         
1940                 case UI_WTYPE_NAME_LINK:
1941                         break;
1942                         
1943                 case UI_WTYPE_POINTER_LINK:
1944                         break;
1945                         
1946                 case UI_WTYPE_FILENAME:
1947                         break;
1948                         
1949                         
1950                         /* start menus */
1951                 case UI_WTYPE_MENU_RADIO:
1952                         wt.wcol_theme= &btheme->tui.wcol_menu;
1953                         wt.draw= widget_menubut;
1954                         break;
1955                         
1956                 case UI_WTYPE_MENU_POINTER_LINK:
1957                         wt.wcol_theme= &btheme->tui.wcol_menu;
1958                         wt.draw= widget_menubut;
1959                         break;
1960                         
1961                         
1962                 case UI_WTYPE_PULLDOWN:
1963                         wt.wcol_theme= &btheme->tui.wcol_pulldown;
1964                         wt.draw= widget_pulldownbut;
1965                         wt.state= widget_state_pulldown;
1966                         break;
1967                         
1968                         /* in menus */
1969                 case UI_WTYPE_MENU_ITEM:
1970                         wt.wcol_theme= &btheme->tui.wcol_menu_item;
1971                         wt.draw= widget_menu_itembut;
1972                         wt.state= widget_state_menu_item;
1973                         break;
1974                         
1975                 case UI_WTYPE_MENU_BACK:
1976                         wt.wcol_theme= &btheme->tui.wcol_menu_back;
1977                         wt.draw= widget_menu_back;
1978                         break;
1979                         
1980                         /* specials */
1981                 case UI_WTYPE_ICON:
1982                         wt.draw= NULL;
1983                         break;
1984                         
1985                 case UI_WTYPE_SWATCH:
1986                         wt.custom= widget_swatch;
1987                         break;
1988                         
1989                 case UI_WTYPE_BOX:
1990                         wt.wcol_theme= &btheme->tui.wcol_box;
1991                         break;
1992                         
1993                 case UI_WTYPE_RGB_PICKER:
1994                         break;
1995                         
1996                 case UI_WTYPE_NORMAL:
1997                         break;
1998         }
1999         
2000         return &wt;
2001 }
2002
2003
2004 static int widget_roundbox_set(uiBut *but, rcti *rect)
2005 {
2006         /* alignment */
2007         if(but->flag & UI_BUT_ALIGN) {
2008                 
2009                 if(but->flag & UI_BUT_ALIGN_TOP)
2010                         rect->ymax+= 1;
2011                 if(but->flag & UI_BUT_ALIGN_LEFT)
2012                         rect->xmin-= 1;
2013                 
2014                 switch(but->flag & UI_BUT_ALIGN) {
2015                         case UI_BUT_ALIGN_TOP:
2016                                 return (12);
2017                                 break;
2018                         case UI_BUT_ALIGN_DOWN:
2019                                 return (3);
2020                                 break;
2021                         case UI_BUT_ALIGN_LEFT:
2022                                 return (6);
2023                                 break;
2024                         case UI_BUT_ALIGN_RIGHT:
2025                                 return (9);
2026                                 break;
2027                                 
2028                         case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT:
2029                                 return (1);
2030                                 break;
2031                         case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT:
2032                                 return (2);
2033                                 break;
2034                         case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT:
2035                                 return (8);
2036                                 break;
2037                         case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT:
2038                                 return (4);
2039                                 break;
2040                                 
2041                         default:
2042                                 return (0);
2043                                 break;
2044                 }
2045         } 
2046         return 15;
2047 }
2048
2049 /* conversion from old to new buttons, so still messy */
2050 void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rcti *rect)
2051 {
2052         bTheme *btheme= U.themes.first;
2053         ThemeUI *tui= &btheme->tui;
2054         uiFontStyle *fstyle= &style->widget;
2055         uiWidgetType *wt= NULL;
2056         
2057         /* handle menus seperately */
2058         if(but->dt==UI_EMBOSSP) {
2059                 switch (but->type) {
2060                         case LABEL:
2061                                 widget_draw_text_icon(&style->widgetlabel, &tui->wcol_menu_back, but, rect);
2062                                 break;
2063                         case SEPR:
2064                                 break;
2065                                 
2066                         default:
2067                                 wt= widget_type(UI_WTYPE_MENU_ITEM);
2068                 }
2069         }
2070         else if(but->dt==UI_EMBOSSN) {
2071                 /* "nothing" */
2072                 wt= widget_type(UI_WTYPE_ICON);
2073         }
2074         else {
2075                 
2076                 switch (but->type) {
2077                         case LABEL:
2078                                 if(but->block->flag & UI_BLOCK_LOOP)
2079                                         widget_draw_text_icon(&style->widgetlabel, &tui->wcol_menu_back, but, rect);
2080                                 else {
2081                                         wt= widget_type(UI_WTYPE_LABEL);
2082                                         fstyle= &style->widgetlabel;
2083                                 }
2084                                 break;
2085                                 
2086                         case SEPR:
2087                                 break;
2088                                 
2089                         case BUT:
2090                                 wt= widget_type(UI_WTYPE_EXEC);
2091                                 break;
2092                         case NUM:
2093                                 wt= widget_type(UI_WTYPE_NUMBER);
2094                                 break;
2095                                 
2096                         case NUMSLI:
2097                         case HSVSLI:
2098                                 wt= widget_type(UI_WTYPE_SLIDER);
2099                                 break;
2100                                 
2101                         case ROW:
2102                                 wt= widget_type(UI_WTYPE_RADIO);
2103                                 break;
2104                                 
2105                         case TEX:
2106                                 wt= widget_type(UI_WTYPE_NAME);
2107                                 break;
2108                                 
2109                         case SEARCH_MENU:
2110                                 wt= widget_type(UI_WTYPE_NAME);
2111                                 if(but->block->flag & UI_BLOCK_LOOP)
2112                                         wt->wcol_theme= &btheme->tui.wcol_menu_back;
2113                                 break;
2114                                 
2115                         case TOGBUT:
2116                         case TOG:
2117                         case TOGN:
2118                         case TOG3:
2119                                 wt= widget_type(UI_WTYPE_TOGGLE);
2120                                 break;
2121                                 
2122                         case OPTION:
2123                         case OPTIONN:
2124                                 if (!(but->flag & UI_HAS_ICON)) {
2125                                         wt= widget_type(UI_WTYPE_OPTION);
2126                                         but->flag |= UI_TEXT_LEFT;
2127                                 }
2128                                 else
2129                                         wt= widget_type(UI_WTYPE_TOGGLE);
2130                                 break;
2131                                 
2132                         case MENU:
2133                         case BLOCK:
2134                         case ICONTEXTROW:
2135                                 wt= widget_type(UI_WTYPE_MENU_RADIO);
2136                                 break;
2137                                 
2138                         case PULLDOWN:
2139                                 wt= widget_type(UI_WTYPE_PULLDOWN);
2140                                 break;
2141                         
2142                         case BUTM:
2143                                 wt= widget_type(UI_WTYPE_MENU_ITEM);
2144                                 break;
2145                                 
2146                         case COL:
2147                                 wt= widget_type(UI_WTYPE_SWATCH);
2148                                 break;
2149                                 
2150                         case ROUNDBOX:
2151                                 wt= widget_type(UI_WTYPE_BOX);
2152                                 break;
2153                                 
2154                         case LINK:
2155                         case INLINK:
2156                                 wt= widget_type(UI_WTYPE_ICON);
2157                                 wt->custom= widget_link;
2158                                 
2159                                 break;
2160                         
2161                         case BUT_EXTRA:
2162                                 widget_draw_extra_mask(C, but, widget_type(UI_WTYPE_BOX), rect);
2163                                 break;
2164                                 
2165                         case HSVCUBE:
2166                                 if(but->a1==4) // vertical V slider, uses new widget draw now
2167                                         ui_draw_but_HSV_v(but, rect);
2168                                 else  // other HSV pickers...
2169                                         ui_draw_but_HSVCUBE(but, rect);
2170                                 break;
2171                                 
2172                         case HSVCIRCLE:
2173                                 ui_draw_but_HSVCIRCLE(but, rect);
2174                                 break;
2175                                 
2176                         case BUT_COLORBAND:
2177                                 ui_draw_but_COLORBAND(but, &tui->wcol_regular, rect);
2178                                 break;
2179                                 
2180                         case BUT_NORMAL:
2181                                 ui_draw_but_NORMAL(but, &tui->wcol_regular, rect);
2182                                 break;
2183                                 
2184                         case BUT_CURVE:
2185                                 ui_draw_but_CURVE(ar, but, &tui->wcol_regular, rect);
2186                                 break;
2187                                 
2188                         default:
2189                                 wt= widget_type(UI_WTYPE_TOGGLE);
2190                 }
2191         }
2192         
2193         if(wt) {
2194                 rcti disablerect= *rect; /* rect gets clipped smaller for text */
2195                 int roundboxalign, state;
2196                 
2197                 roundboxalign= widget_roundbox_set(but, rect);
2198                 state= but->flag;
2199                 if(but->editstr) state |= UI_TEXTINPUT;
2200                 
2201                 wt->state(wt, state);
2202                 if(wt->custom)
2203                         wt->custom(but, &wt->wcol, rect, state, roundboxalign);
2204                 else if(wt->draw)
2205                         wt->draw(&wt->wcol, rect, state, roundboxalign);
2206                 wt->text(fstyle, &wt->wcol, but, rect);
2207                 
2208                 if(state & (UI_BUT_DISABLED|UI_BUT_INACTIVE))
2209                         if(but->dt!=UI_EMBOSSP)
2210                                 widget_disabled(&disablerect);
2211         }
2212 }
2213
2214 void ui_draw_menu_back(uiStyle *style, uiBlock *block, rcti *rect)
2215 {
2216         uiWidgetType *wt= widget_type(UI_WTYPE_MENU_BACK);
2217         
2218         wt->state(wt, 0);
2219         if(block)
2220                 wt->draw(&wt->wcol, rect, block->flag, block->direction);
2221         else
2222                 wt->draw(&wt->wcol, rect, 0, 0);
2223         
2224 }
2225
2226 void ui_draw_search_back(uiStyle *style, uiBlock *block, rcti *rect)
2227 {
2228         uiWidgetType *wt= widget_type(UI_WTYPE_BOX);
2229         
2230         glEnable(GL_BLEND);
2231         widget_softshadow(rect, 15, 5.0f, 8.0f);
2232         glDisable(GL_BLEND);
2233
2234         wt->state(wt, 0);
2235         if(block)
2236                 wt->draw(&wt->wcol, rect, block->flag, 15);
2237         else
2238                 wt->draw(&wt->wcol, rect, 0, 15);
2239         
2240 }
2241
2242
2243 /* helper call to draw a menu item without button */
2244 /* state: UI_ACTIVE or 0 */
2245 void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, char *name, int state)
2246 {
2247         uiWidgetType *wt= widget_type(UI_WTYPE_MENU_ITEM);
2248         rcti _rect= *rect;
2249         char *cpoin;
2250         
2251         wt->state(wt, state);
2252         wt->draw(&wt->wcol, rect, 0, 0);
2253         
2254         uiStyleFontSet(fstyle);
2255         fstyle->align= UI_STYLE_TEXT_LEFT;
2256         
2257         /* text location offset */
2258         rect->xmin+=5;
2259
2260         /* cut string in 2 parts? */
2261         cpoin= strchr(name, '|');
2262         if(cpoin) {
2263                 *cpoin= 0;
2264                 rect->xmax -= BLF_width(cpoin+1) + 10;
2265         }
2266         
2267         glColor3ubv(wt->wcol.text);
2268         uiStyleFontDraw(fstyle, rect, name);
2269         
2270         /* part text right aligned */
2271         if(cpoin) {
2272                 fstyle->align= UI_STYLE_TEXT_RIGHT;
2273                 rect->xmax= _rect.xmax - 5;
2274                 uiStyleFontDraw(fstyle, rect, cpoin+1);
2275                 *cpoin= '|';
2276         }
2277         
2278         /* restore rect, was messed with */
2279         *rect= _rect;
2280
2281 }
2282