svn merge -r 15392:15551 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / source / blender / src / interface_draw.c
index f06717cfe5eea925b70db72d61166e9fbf0061fc..e7041e6000373b2433e278780822dc7eb9d01aba 100644 (file)
@@ -2,15 +2,12 @@
 /**
  * $Id$
  *
- * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. The Blender
- * Foundation also sells licenses for use in proprietary software under
- * the Blender License.  See http://www.blender.org/BL/ for information
- * about this.
+ * of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -28,7 +25,7 @@
  *
  * Contributor(s): none yet.
  *
- * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * ***** END GPL LICENSE BLOCK *****
  */
 
 /* 
@@ -55,6 +52,8 @@
 #include "BLI_blenlib.h"
 #include "BLI_arithb.h"
 
+#include "DNA_color_types.h"
+#include "DNA_key_types.h"
 #include "DNA_packedFile_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_space_types.h"
 #include "DNA_vfont_types.h"
 
 #include "BKE_blender.h"
+#include "BKE_colortools.h"
 #include "BKE_font.h"
 #include "BKE_global.h"
+#include "BKE_key.h"
 #include "BKE_utildefines.h"
 
 #include "datatoc.h"            /* std font */
@@ -156,30 +157,44 @@ void uiEmboss(float x1, float y1, float x2, float y2, int sel)
 /* icons have been standardized... and this call draws in untransformed coordinates */
 #define ICON_HEIGHT            16.0f
 
-static void ui_draw_icon(uiBut *but, BIFIconID icon)
+static void ui_draw_icon(uiBut *but, BIFIconID icon, int blend)
 {
        float xs=0, ys=0, aspect, height;
-       int blend= 0;
 
        /* this icon doesn't need draw... */
        if(icon==ICON_BLANK1) return;
        
        /* we need aspect from block, for menus... these buttons are scaled in uiPositionBlock() */
        aspect= but->block->aspect;
-       if(aspect != but->aspect)
-               height= ICON_HEIGHT/aspect;
+       if(aspect != but->aspect) {
+               /* prevent scaling up icon in pupmenu */
+               if (aspect < 1.0f) {                    
+                       height= ICON_HEIGHT;
+                       aspect = 1.0f;
+                       
+               }
+               else 
+                       height= ICON_HEIGHT/aspect;
+       }
        else
                height= ICON_HEIGHT;
        
        if(but->flag & UI_ICON_LEFT) {
-               if (but->type==BUTM) {
+               if (but->type==BUT_TOGDUAL) {
+                       if (but->drawstr[0]) {
+                               xs= but->x1-1.0;
+                       } else {
+                               xs= (but->x1+but->x2- height)/2.0;
+                       }
+               }
+               else if (but->type==BUTM ) {
                        xs= but->x1+1.0;
                }
                else if ((but->type==ICONROW) || (but->type==ICONTEXTROW)) {
-                       xs= but->x1+4.0;
+                       xs= but->x1+3.0;
                }
                else {
-                       xs= but->x1+6.0;
+                       xs= but->x1+4.0;
                }
                ys= (but->y1+but->y2- height)/2.0;
        }
@@ -192,18 +207,15 @@ static void ui_draw_icon(uiBut *but, BIFIconID icon)
                ys= (but->y1+but->y2- height)/2.0;
        }
 
-       /* aspect for the icon has to be stored */
-       BIF_icon_set_aspect(icon, aspect);
-
        glEnable(GL_BLEND);
 
        /* calculate blend color */
-       if ELEM4(but->type, ICONTOG, TOG, ROW, TOGN) {
+       if ELEM3(but->type, TOG, ROW, TOGN) {
                if(but->flag & UI_SELECT);
                else if(but->flag & UI_ACTIVE);
                else blend= -60;
        }
-       BIF_icon_draw_blended((int)(xs+0.5f), (int)(ys+0.5f), icon, but->themecol, blend);
+       BIF_icon_draw_aspect_blended(xs, ys, icon, aspect, blend);
        
        glDisable(GL_BLEND);
 
@@ -838,6 +850,7 @@ static void ui_default_flat(int type, int colorid, float asp, float x1, float y1
        /* *** EXTRA DRAWING FOR SPECIFIC CONTROL TYPES *** */
        switch(type) {
        case NUM:
+       case NUMABS:
                /* SIDE ARROWS */
                /* left */
                if(flag & UI_SELECT) {
@@ -864,11 +877,12 @@ static void ui_default_slider(int colorid, float fac, float aspect, float x1, fl
        
        if(flag & UI_SELECT) 
                        BIF_ThemeColorShade(TH_BUT_NUM, -5);
-       else
+       else {
                if(flag & UI_ACTIVE) 
                        BIF_ThemeColorShade(TH_BUT_NUM, +35); 
                else
                        BIF_ThemeColorShade(TH_BUT_NUM, +25); 
+       }
 
        glRectf(x1, ymid-yc, x2, ymid+yc);
        
@@ -935,6 +949,7 @@ static void ui_draw_default(int type, int colorid, float aspect, float x1, float
        case TEX:
        case IDPOIN:
        case NUM:
+       case NUMABS:
                ui_default_flat(type, colorid, aspect, x1, y1, x2, y2, flag);
                break;
        case ICONROW: 
@@ -1018,6 +1033,7 @@ static void ui_draw_oldskool(int type, int colorid, float asp, float x1, float y
        /* special type decorations */
        switch(type) {
        case NUM:
+       case NUMABS:
                if(flag & UI_SELECT) BIF_ThemeColorShade(colorid, -60);
                else BIF_ThemeColorShade(colorid, -30);
                ui_default_num_arrows(x1, y1, x2, y2);
@@ -1075,11 +1091,11 @@ static void round_button(float x1, float y1, float x2, float y2, float asp,
        if(col[1]<100) col[1]= 0; else col[1]-= 100;
        if(col[2]<100) col[2]= 0; else col[2]-= 100;
        col[3]= 80;
-       glColor4ubv(col);
+       glColor4ubv((GLubyte *)col);
        gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, rad - asp);
        gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, rad + asp);
        col[3]= 180;
-       glColor4ubv(col);
+       glColor4ubv((GLubyte *)col);
        gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, rad);
 
        glDisable( GL_BLEND );
@@ -1168,6 +1184,7 @@ static void ui_draw_round(int type, int colorid, float asp, float x1, float y1,
        /* special type decorations */
        switch(type) {
        case NUM:
+       case NUMABS:
                BIF_ThemeColorShade(colorid, curshade-60);
                ui_default_num_arrows(x1, y1, x2, y2);
                break;
@@ -1195,12 +1212,19 @@ static void ui_draw_round(int type, int colorid, float asp, float x1, float y1,
 /* super minimal button as used in logic menu */
 static void ui_draw_minimal(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
 {
+       /* too much space between buttons */
+       
+       if (type==TEX || type==IDPOIN) {
+               x1+= asp;
+               x2-= (asp*2);
+               //y1+= asp;
+               y2-= asp;
+       } else {
+               /* Less space between buttons looks nicer */
+               y2-= asp;
+               x2-= asp;
+       }
        
-       x1+= asp;
-       x2-= asp;
-       y1+= asp;
-       y2-= asp;
-
        /* paper */
        if(flag & UI_SELECT) {
                if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, -40);
@@ -1212,39 +1236,65 @@ static void ui_draw_minimal(int type, int colorid, float asp, float x1, float y1
        }
        
        glRectf(x1, y1, x2, y2);
-
-       if(flag & UI_SELECT) {
+       
+       if (type==TEX || type==IDPOIN) {
                BIF_ThemeColorShade(colorid, -60);
 
-               /* top */
-               fdrawline(x1, y2, x2, y2);
-               /* left */
-               fdrawline(x1, y1, x1, y2);
-               BIF_ThemeColorShade(colorid, +40);
-
-               /* below */
-               fdrawline(x1, y1, x2, y1);
-               /* right */
-               fdrawline(x2, y1, x2, y2);
-       }
-       else {
-               BIF_ThemeColorShade(colorid, +40);
-
                /* top */
                fdrawline(x1, y2, x2, y2);
                /* left */
                fdrawline(x1, y1, x1, y2);
                
-               BIF_ThemeColorShade(colorid, -60);
+               
+               /* text underline, some  */ 
+               BIF_ThemeColorShade(colorid, +50);
+               glEnable(GL_LINE_STIPPLE);
+               glLineStipple(1, 0x8888);
+               fdrawline(x1+(asp*2), y1+(asp*3), x2-(asp*2), y1+(asp*3));
+               glDisable(GL_LINE_STIPPLE);
+               
+               
+               BIF_ThemeColorShade(colorid, +60);
                /* below */
                fdrawline(x1, y1, x2, y1);
                /* right */
                fdrawline(x2, y1, x2, y2);
+               
+       } else {
+               if(flag & UI_SELECT) {
+                       BIF_ThemeColorShade(colorid, -60);
+
+                       /* top */
+                       fdrawline(x1, y2, x2, y2);
+                       /* left */
+                       fdrawline(x1, y1, x1, y2);
+                       BIF_ThemeColorShade(colorid, +40);
+
+                       /* below */
+                       fdrawline(x1, y1, x2, y1);
+                       /* right */
+                       fdrawline(x2, y1, x2, y2);
+               }
+               else {
+                       BIF_ThemeColorShade(colorid, +40);
+
+                       /* top */
+                       fdrawline(x1, y2, x2, y2);
+                       /* left */
+                       fdrawline(x1, y1, x1, y2);
+                       
+                       BIF_ThemeColorShade(colorid, -60);
+                       /* below */
+                       fdrawline(x1, y1, x2, y1);
+                       /* right */
+                       fdrawline(x2, y1, x2, y2);
+               }
        }
        
        /* special type decorations */
        switch(type) {
        case NUM:
+       case NUMABS:
                if(flag & UI_SELECT) BIF_ThemeColorShade(colorid, -60);
                else BIF_ThemeColorShade(colorid, -30);
                ui_default_num_arrows(x1, y1, x2, y2);
@@ -1367,11 +1417,11 @@ void uiDrawMenuBox(float minx, float miny, float maxx, float maxy, short flag)
                ui_shadowbox(minx, miny, maxx, maxy, 2.0, (100*col[3])>>8);
                
                glEnable(GL_BLEND);
-               glColor4ubv(col);
+               glColor4ubv((GLubyte *)col);
                glRectf(minx-1, miny, minx, maxy);      // 1 pixel on left, to distinguish sublevel menus
        }
        glEnable(GL_BLEND);
-       glColor4ubv(col);
+       glColor4ubv((GLubyte *)col);
        glRectf(minx, miny, maxx, maxy);
        glDisable(GL_BLEND);
 }
@@ -1440,19 +1490,17 @@ static void ui_draw_text_icon(uiBut *but)
        
        /* check for button text label */
        if (but->type == ICONTEXTROW) {
-               ui_draw_icon(but, (BIFIconID) (but->icon+but->iconadd));
+               ui_draw_icon(but, (BIFIconID) (but->icon+but->iconadd), 0);
        }
        else {
 
                /* text button selection and cursor */
                if(but->pos != -1) {
                
-                       if (SELWIDTH > 0) {
+                       if ((but->selend - but->selsta) > 0) {
                                /* text button selection */
                                selsta_tmp = but->selsta + strlen(but->str);
                                selend_tmp = but->selend + strlen(but->str);
-                               if (but->ofs >= strlen(but->str))
-                                       selsta_tmp += (but->ofs - strlen(but->str));
                                        
                                if(but->drawstr[0]!=0) {
                                        ch= but->drawstr[selsta_tmp];
@@ -1492,6 +1540,17 @@ static void ui_draw_text_icon(uiBut *but)
                                }
                        }
                }
+               
+               if(but->type==BUT_TOGDUAL) {
+                       int dualset= 0;
+                       if(but->pointype==SHO)
+                               dualset= BTST( *(((short *)but->poin)+1), but->bitnr);
+                       else if(but->pointype==INT)
+                               dualset= BTST( *(((int *)but->poin)+1), but->bitnr);
+                       
+                       ui_draw_icon(but, ICON_DOT, dualset?0:-100);
+               }
+               
                if(but->drawstr[0]!=0) {
                        int transopts;
                        int tog3= 0;
@@ -1504,9 +1563,9 @@ static void ui_draw_text_icon(uiBut *but)
                        and offset the text label to accomodate it */
                        
                        if ( (but->flag & UI_HAS_ICON) && (but->flag & UI_ICON_LEFT) ) {
-                               ui_draw_icon(but, but->icon);
+                               ui_draw_icon(but, but->icon, 0);
 
-                               if(but->flag & UI_TEXT_LEFT) x= but->x1 + BIF_icon_get_width(but->icon)+4.0;
+                               if(but->flag & UI_TEXT_LEFT) x= but->x1 + but->aspect*BIF_icon_get_width(but->icon)+5.0;
                                else x= (but->x1+but->x2-but->strwidth+1)/2.0;
                        }
                        else {
@@ -1550,9 +1609,17 @@ static void ui_draw_text_icon(uiBut *but)
                        if(but->type==LABEL && but->min!=0.0) BIF_ThemeColor(TH_BUT_TEXT_HI);
                
                        ui_rasterpos_safe(x, (but->y1+but->y2- 9.0)/2.0, but->aspect);
-                       if(but->type==TEX || but->type==IDPOIN) transopts= 0;   // no translation, of course!
+                       if(but->type==IDPOIN) transopts= 0;     // no translation, of course!
                        else transopts= (U.transopts & USER_TR_BUTTONS);
+                       
+               #ifdef INTERNATIONAL
+                       if (but->type == FTPREVIEW)
+                               FTF_DrawNewFontString (but->drawstr+but->ofs, FTF_INPUT_UTF8);
+                       else
+                               BIF_DrawString(but->font, but->drawstr+but->ofs, transopts);
+               #else
                        BIF_DrawString(but->font, but->drawstr+but->ofs, transopts);
+               #endif
 
                        /* part text right aligned */
                        if(cpoin) {
@@ -1564,7 +1631,7 @@ static void ui_draw_text_icon(uiBut *but)
                }
                /* if there's no text label, then check to see if there's an icon only and draw it */
                else if( but->flag & UI_HAS_ICON ) {
-                       ui_draw_icon(but, (BIFIconID) (but->icon+but->iconadd));
+                       ui_draw_icon(but, (BIFIconID) (but->icon+but->iconadd), 0);
                }
        }
 }
@@ -1732,6 +1799,24 @@ static void ui_draw_but_CHARTAB(uiBut *but)
        unsigned char ustr[16];
        PackedFile *pf;
        int result = 0;
+       int charmax = G.charmax;
+       
+       /* <builtin> font in use. There are TTF <builtin> and non-TTF <builtin> fonts */
+       if(!strcmp(G.selfont->name, "<builtin>"))
+       {
+               if(G.ui_international == TRUE)
+               {
+                       charmax = 0xff;
+               }
+               else
+               {
+                       charmax = 0xff;
+               }
+       }
+
+       /* Category list exited without selecting the area */
+       if(G.charmax == 0)
+               charmax = G.charmax = 0xffff;
 
        /* Calculate the size of the button */
        width = abs(but->x2 - but->x1);
@@ -1748,7 +1833,7 @@ static void ui_draw_but_CHARTAB(uiBut *but)
 
        cs = G.charstart;
 
-       /* Set the font */
+       /* Set the font, in case it is not <builtin> font */
        if(G.selfont && strcmp(G.selfont->name, "<builtin>"))
        {
                char tmpStr[256];
@@ -1764,8 +1849,15 @@ static void ui_draw_but_CHARTAB(uiBut *but)
                        int err;
 
                        strcpy(tmpStr, G.selfont->name);
-                       BLI_convertstringcode(tmpStr, G.sce, 0);
-                       err = FTF_SetFont(tmpStr, 0, 14.0);
+                       BLI_convertstringcode(tmpStr, G.sce);
+                       err = FTF_SetFont((unsigned char *)tmpStr, 0, 14.0);
+               }
+       }
+       else
+       {
+               if(G.ui_international == TRUE)
+               {
+                       FTF_SetFont((unsigned char *) datatoc_bfont_ttf, datatoc_bfont_ttf_size, 14.0);
                }
        }
 
@@ -1779,12 +1871,12 @@ static void ui_draw_but_CHARTAB(uiBut *but)
        for(y = 0; y < 6; y++)
        {
                // Do not draw more than the category allows
-               if(cs > G.charmax) break;
+               if(cs > charmax) break;
 
                for(x = 0; x < 12; x++)
                {
                        // Do not draw more than the category allows
-                       if(cs > G.charmax) break;
+                       if(cs > charmax) break;
 
                        // Draw one grid cell
                        glBegin(GL_LINE_LOOP);
@@ -1797,11 +1889,27 @@ static void ui_draw_but_CHARTAB(uiBut *but)
                        // Draw character inside the cell
                        memset(wstr, 0, sizeof(wchar_t)*2);
                        memset(ustr, 0, 16);
-                       
+
+                       // Set the font to be either unicode or <builtin>                               
                        wstr[0] = cs;
-                       wcs2utf8s(ustr, wstr);
+                       if(strcmp(G.selfont->name, "<builtin>"))
+                       {
+                               wcs2utf8s((char *)ustr, (wchar_t *)wstr);
+                       }
+                       else
+                       {
+                               if(G.ui_international == TRUE)
+                               {
+                                       wcs2utf8s((char *)ustr, (wchar_t *)wstr);
+                               }
+                               else
+                               {
+                                       ustr[0] = cs;
+                                       ustr[1] = 0;
+                               }
+                       }
 
-                       if(G.selfont && strcmp(G.selfont->name, "<builtin>"))
+                       if((G.selfont && strcmp(G.selfont->name, "<builtin>")) || (G.selfont && !strcmp(G.selfont->name, "<builtin>") && G.ui_international == TRUE))
                        {
                                float wid;
                                float llx, lly, llz, urx, ury, urz;
@@ -1809,8 +1917,8 @@ static void ui_draw_but_CHARTAB(uiBut *but)
                                float px, py;
        
                                // Calculate the position
-                               wid = FTF_GetStringWidth(ustr, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
-                               FTF_GetBoundingBox(ustr, &llx,&lly,&llz,&urx,&ury,&urz, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
+                               wid = FTF_GetStringWidth((char *) ustr, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
+                               FTF_GetBoundingBox((char *) ustr, &llx,&lly,&llz,&urx,&ury,&urz, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
                                dx = urx-llx;
                                dy = ury-lly;
 
@@ -1820,12 +1928,12 @@ static void ui_draw_but_CHARTAB(uiBut *but)
 
                                // Set the position and draw the character
                                ui_rasterpos_safe(px, py, but->aspect);
-                               FTF_DrawString(ustr, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
+                               FTF_DrawString((char *) ustr, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
                        }
                        else
                        {
                                ui_rasterpos_safe(sx + butw/2, sy + buth/2, but->aspect);
-                               BIF_DrawString(but->font, ustr, 0);
+                               BIF_DrawString(but->font, (char *) ustr, 0);
                        }
        
                        // Calculate the next position and character
@@ -1843,16 +1951,22 @@ static void ui_draw_but_CHARTAB(uiBut *but)
        /* Return Font Settings to original */
        if(U.fontsize && U.fontname[0])
        {
-               result = FTF_SetFont(U.fontname, 0, U.fontsize);
+               result = FTF_SetFont((unsigned char *)U.fontname, 0, U.fontsize);
        }
        else if (U.fontsize)
        {
-               result = FTF_SetFont(datatoc_bfont_ttf, datatoc_bfont_ttf_size, U.fontsize);
+               result = FTF_SetFont((unsigned char *) datatoc_bfont_ttf, datatoc_bfont_ttf_size, U.fontsize);
        }
 
        if (result == 0)
        {
-               result = FTF_SetFont(datatoc_bfont_ttf, datatoc_bfont_ttf_size, 11);
+               result = FTF_SetFont((unsigned char *) datatoc_bfont_ttf, datatoc_bfont_ttf_size, 11);
+       }
+       
+       /* resets the font size */
+       if(G.ui_international == TRUE)
+       {
+               uiSetCurFont(but->block, UI_HELV);
        }
 }
 
@@ -1863,7 +1977,7 @@ static void ui_draw_but_COLORBAND(uiBut *but)
        ColorBand *coba= (ColorBand *)but->poin;
        CBData *cbd;
        float x1, y1, sizex, sizey;
-       float dx, v3[2], v1[2], v2[2];
+       float dx, v3[2], v1[2], v2[2], v1a[2], v2a[2];
        int a;
                
        if(coba==NULL) return;
@@ -1931,39 +2045,55 @@ static void ui_draw_but_COLORBAND(uiBut *but)
        /* help lines */
        v1[0]= v2[0]=v3[0]= x1;
        v1[1]= y1;
+       v1a[1]= y1+0.25*sizey;
        v2[1]= y1+0.5*sizey;
+       v2a[1]= y1+0.75*sizey;
        v3[1]= y1+sizey;
        
+       
        cbd= coba->data;
        glBegin(GL_LINES);
        for(a=0; a<coba->tot; a++, cbd++) {
-               v1[0]=v2[0]=v3[0]= x1+ cbd->pos*sizex;
-               
-               glColor3ub(0, 0, 0);
-               glVertex2fv(v1);
-               glVertex2fv(v2);
-               
-               if(a==coba->cur) {
-                       glVertex2f(v1[0]-1, v1[1]);
-                       glVertex2f(v2[0]-1, v2[1]);
-                       glVertex2f(v1[0]+1, v1[1]);
-                       glVertex2f(v2[0]+1, v2[1]);
-               }
-               
-               glColor3ub(255, 255, 255);
-               glVertex2fv(v2);
-               glVertex2fv(v3);
+               v1[0]=v2[0]=v3[0]=v1a[0]=v2a[0]= x1+ cbd->pos*sizex;
                
                if(a==coba->cur) {
-                       if(cbd->pos>0.01) {
-                               glVertex2f(v2[0]-1, v2[1]);
-                               glVertex2f(v3[0]-1, v3[1]);
-                       }
-                       if(cbd->pos<0.99) {
-                               glVertex2f(v2[0]+1, v2[1]);
-                               glVertex2f(v3[0]+1, v3[1]);
-                       }
+                       glColor3ub(0, 0, 0);
+                       glVertex2fv(v1);
+                       glVertex2fv(v3);
+                       glEnd();
+                       
+                       setlinestyle(2);
+                       glBegin(GL_LINES);
+                       glColor3ub(255, 255, 255);
+                       glVertex2fv(v1);
+                       glVertex2fv(v3);
+                       glEnd();
+                       setlinestyle(0);
+                       glBegin(GL_LINES);
+                       
+                       /* glColor3ub(0, 0, 0);
+                       glVertex2fv(v1);
+                       glVertex2fv(v1a);
+                       glColor3ub(255, 255, 255);
+                       glVertex2fv(v1a);
+                       glVertex2fv(v2);
+                       glColor3ub(0, 0, 0);
+                       glVertex2fv(v2);
+                       glVertex2fv(v2a);
+                       glColor3ub(255, 255, 255);
+                       glVertex2fv(v2a);
+                       glVertex2fv(v3);
+                       */
                }
+               else {
+                       glColor3ub(0, 0, 0);
+                       glVertex2fv(v1);
+                       glVertex2fv(v2);
+                       
+                       glColor3ub(255, 255, 255);
+                       glVertex2fv(v2);
+                       glVertex2fv(v3);
+               }       
        }
        glEnd();
 }
@@ -2042,6 +2172,178 @@ static void ui_draw_but_NORMAL(uiBut *but)
                if(old[a])
                        glEnable(GL_LIGHT0+a);
        }
+}
+
+static void ui_draw_but_curve_grid(uiBut *but, float zoomx, float zoomy, float offsx, float offsy, float step)
+{
+       float dx, dy, fx, fy;
+       
+       glBegin(GL_LINES);
+       dx= step*zoomx;
+       fx= but->x1 + zoomx*(-offsx);
+       if(fx > but->x1) fx -= dx*( floor(fx-but->x1));
+       while(fx < but->x2) {
+               glVertex2f(fx, but->y1); 
+               glVertex2f(fx, but->y2);
+               fx+= dx;
+       }
+       
+       dy= step*zoomy;
+       fy= but->y1 + zoomy*(-offsy);
+       if(fy > but->y1) fy -= dy*( floor(fy-but->y1));
+       while(fy < but->y2) {
+               glVertex2f(but->x1, fy); 
+               glVertex2f(but->x2, fy);
+               fy+= dy;
+       }
+       glEnd();
+       
+}
+
+static void ui_draw_but_CURVE(uiBut *but)
+{
+       CurveMapping *cumap= (CurveMapping *)but->poin;
+       CurveMap *cuma= cumap->cm+cumap->cur;
+       CurveMapPoint *cmp;
+       float fx, fy, dx, dy, fac[2], zoomx, zoomy, offsx, offsy;
+       GLint scissor[4];
+       int a;
+       
+       /* need scissor test, curve can draw outside of boundary */
+       glGetIntegerv(GL_VIEWPORT, scissor);
+       fx= but->x1; fy= but->y1;
+       ui_graphics_to_window(but->win, &fx, &fy);
+       dx= but->x2; dy= but->y2;
+       ui_graphics_to_window(but->win, &dx, &dy);
+       glScissor((int)floor(fx), (int)floor(fy), (int)ceil(dx-fx), (int)ceil(dy-fy));
+       
+       /* calculate offset and zoom */
+       zoomx= (but->x2-but->x1-2.0*but->aspect)/(cumap->curr.xmax - cumap->curr.xmin);
+       zoomy= (but->y2-but->y1-2.0*but->aspect)/(cumap->curr.ymax - cumap->curr.ymin);
+       offsx= cumap->curr.xmin-but->aspect/zoomx;
+       offsy= cumap->curr.ymin-but->aspect/zoomy;
+       
+       /* backdrop */
+       if(cumap->flag & CUMA_DO_CLIP) {
+               BIF_ThemeColorShade(TH_BUT_NEUTRAL, -20);
+               glRectf(but->x1, but->y1, but->x2, but->y2);
+               BIF_ThemeColor(TH_BUT_NEUTRAL);
+               glRectf(but->x1 + zoomx*(cumap->clipr.xmin-offsx),
+                               but->y1 + zoomy*(cumap->clipr.ymin-offsy),
+                               but->x1 + zoomx*(cumap->clipr.xmax-offsx),
+                               but->y1 + zoomy*(cumap->clipr.ymax-offsy));
+       }
+       else {
+               BIF_ThemeColor(TH_BUT_NEUTRAL);
+               glRectf(but->x1, but->y1, but->x2, but->y2);
+       }
+       
+       /* grid, every .25 step */
+       BIF_ThemeColorShade(TH_BUT_NEUTRAL, -16);
+       ui_draw_but_curve_grid(but, zoomx, zoomy, offsx, offsy, 0.25f);
+       /* grid, every 1.0 step */
+       BIF_ThemeColorShade(TH_BUT_NEUTRAL, -24);
+       ui_draw_but_curve_grid(but, zoomx, zoomy, offsx, offsy, 1.0f);
+       /* axes */
+       BIF_ThemeColorShade(TH_BUT_NEUTRAL, -50);
+       glBegin(GL_LINES);
+       glVertex2f(but->x1, but->y1 + zoomy*(-offsy));
+       glVertex2f(but->x2, but->y1 + zoomy*(-offsy));
+       glVertex2f(but->x1 + zoomx*(-offsx), but->y1);
+       glVertex2f(but->x1 + zoomx*(-offsx), but->y2);
+       glEnd();
+       
+       /* cfra option */
+       if(cumap->flag & CUMA_DRAW_CFRA) {
+               glColor3ub(0x60, 0xc0, 0x40);
+               glBegin(GL_LINES);
+               glVertex2f(but->x1 + zoomx*(cumap->sample[0]-offsx), but->y1);
+               glVertex2f(but->x1 + zoomx*(cumap->sample[0]-offsx), but->y2);
+               glEnd();
+       }
+       /* sample option */
+       if(cumap->flag & CUMA_DRAW_SAMPLE) {
+               if(cumap->cur==3) {
+                       float lum= cumap->sample[0]*0.35f + cumap->sample[1]*0.45f + cumap->sample[2]*0.2f;
+                       glColor3ub(240, 240, 240);
+                       
+                       glBegin(GL_LINES);
+                       glVertex2f(but->x1 + zoomx*(lum-offsx), but->y1);
+                       glVertex2f(but->x1 + zoomx*(lum-offsx), but->y2);
+                       glEnd();
+               }
+               else {
+                       if(cumap->cur==0)
+                               glColor3ub(240, 100, 100);
+                       else if(cumap->cur==1)
+                               glColor3ub(100, 240, 100);
+                       else
+                               glColor3ub(100, 100, 240);
+                       
+                       glBegin(GL_LINES);
+                       glVertex2f(but->x1 + zoomx*(cumap->sample[cumap->cur]-offsx), but->y1);
+                       glVertex2f(but->x1 + zoomx*(cumap->sample[cumap->cur]-offsx), but->y2);
+                       glEnd();
+               }
+       }
+       
+       /* the curve */
+       BIF_ThemeColorBlend(TH_TEXT, TH_BUT_NEUTRAL, 0.35);
+       glEnable(GL_LINE_SMOOTH);
+       glEnable(GL_BLEND);
+       glBegin(GL_LINE_STRIP);
+       
+       if(cuma->table==NULL)
+               curvemapping_changed(cumap, 0); /* 0 = no remove doubles */
+       cmp= cuma->table;
+       
+       /* first point */
+       if((cuma->flag & CUMA_EXTEND_EXTRAPOLATE)==0)
+               glVertex2f(but->x1, but->y1 + zoomy*(cmp[0].y-offsy));
+       else {
+               fx= but->x1 + zoomx*(cmp[0].x-offsx + cuma->ext_in[0]);
+               fy= but->y1 + zoomy*(cmp[0].y-offsy + cuma->ext_in[1]);
+               glVertex2f(fx, fy);
+       }
+       for(a=0; a<=CM_TABLE; a++) {
+               fx= but->x1 + zoomx*(cmp[a].x-offsx);
+               fy= but->y1 + zoomy*(cmp[a].y-offsy);
+               glVertex2f(fx, fy);
+       }
+       /* last point */
+       if((cuma->flag & CUMA_EXTEND_EXTRAPOLATE)==0)
+               glVertex2f(but->x2, but->y1 + zoomy*(cmp[CM_TABLE].y-offsy));   
+       else {
+               fx= but->x1 + zoomx*(cmp[CM_TABLE].x-offsx - cuma->ext_out[0]);
+               fy= but->y1 + zoomy*(cmp[CM_TABLE].y-offsy - cuma->ext_out[1]);
+               glVertex2f(fx, fy);
+       }
+       glEnd();
+       glDisable(GL_LINE_SMOOTH);
+       glDisable(GL_BLEND);
+
+       /* the points, use aspect to make them visible on edges */
+       cmp= cuma->curve;
+       glPointSize(3.0f);
+       bglBegin(GL_POINTS);
+       for(a=0; a<cuma->totpoint; a++) {
+               if(cmp[a].flag & SELECT)
+                       BIF_ThemeColor(TH_TEXT_HI);
+               else
+                       BIF_ThemeColor(TH_TEXT);
+               fac[0]= but->x1 + zoomx*(cmp[a].x-offsx);
+               fac[1]= but->y1 + zoomy*(cmp[a].y-offsy);
+               bglVertex2fv(fac);
+       }
+       bglEnd();
+       glPointSize(1.0f);
+       
+       /* restore scissortest */
+       glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
+
+       /* outline */
+       BIF_ThemeColor(TH_BUT_OUTLINE);
+       fdrawbox(but->x1, but->y1, but->x2, but->y2);
 
 }
 
@@ -2085,19 +2387,22 @@ void ui_set_embossfunc(uiBut *but, int drawtype)
        else {
                int theme= BIF_GetThemeValue(TH_BUT_DRAWTYPE);
                
-               // and the themes
-               if(theme==1) {
-                       but->embossfunc= ui_draw_default;
-                       but->sliderfunc= ui_default_slider;
-               }
-               else if(theme==2) {
+               switch(theme) {
+               
+               case TH_ROUNDED:
                        but->embossfunc= ui_draw_round;
-               }
-               else if(theme==3) {
+                       break;
+               case TH_OLDSKOOL:
                        but->embossfunc= ui_draw_oldskool;
-               }
-               else {
+                       break;
+               case TH_MINIMAL:
                        but->embossfunc= ui_draw_minimal;
+                       break;
+               case TH_SHADED:
+               default:
+                       but->embossfunc= ui_draw_default;
+                       but->sliderfunc= ui_default_slider;
+                       break;
                }
        }
        
@@ -2154,7 +2459,7 @@ void ui_draw_but(uiBut *but)
 
        case LINK:
        case INLINK:
-               ui_draw_icon(but, but->icon);
+               ui_draw_icon(but, but->icon, 0);
                break;
                
        case ROUNDBOX:
@@ -2167,6 +2472,9 @@ void ui_draw_but(uiBut *but)
        case BUT_NORMAL:
                ui_draw_but_NORMAL(but);
                break;
+       case BUT_CURVE:
+               ui_draw_but_CURVE(but);
+               break;
                
        default:
                but->embossfunc(but->type, but->themecol, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag);
@@ -2175,3 +2483,33 @@ void ui_draw_but(uiBut *but)
        }
 }
 
+void ui_dropshadow(rctf *rct, float radius, float aspect, int select)
+{
+       float rad;
+       float a;
+       char alpha= 2;
+       
+       glEnable(GL_BLEND);
+       
+       if(radius > (rct->ymax-rct->ymin-10.0f)/2.0f)
+               rad= (rct->ymax-rct->ymin-10.0f)/2.0f;
+       else
+               rad= radius;
+       
+       if(select) a= 12.0f*aspect; else a= 12.0f*aspect;
+       for(; a>0.0f; a-=aspect) {
+               /* alpha ranges from 2 to 20 or so */
+               glColor4ub(0, 0, 0, alpha);
+               alpha+= 2;
+               
+               gl_round_box(GL_POLYGON, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax-10.0f + a, rad+a);
+       }
+       
+       /* outline emphasis */
+       glEnable( GL_LINE_SMOOTH );
+       glColor4ub(0, 0, 0, 100);
+       gl_round_box(GL_LINE_LOOP, rct->xmin-0.5f, rct->ymin-0.5f, rct->xmax+0.5f, rct->ymax+0.5f, radius);
+       glDisable( GL_LINE_SMOOTH );
+       
+       glDisable(GL_BLEND);
+}