most unused arg warnings corrected.
[blender.git] / source / blender / editors / interface / interface_icons.c
index 6b566012525663fe262113040ac617b0c866f943..6d1a72fcd1a3af9446daccc9ce2026a0d9ce343b 100644 (file)
@@ -15,7 +15,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
 #else
 #include <io.h>
 #include <direct.h>
+#include "BLI_winstuff.h"
 #endif   
 #include "MEM_guardedalloc.h"
 
-#include "BLI_arithb.h"
+#include "GPU_extensions.h"
+
+#include "BLI_math.h"
 #include "BLI_blenlib.h"
 #include "BLI_storage_types.h"
 
-#include "DNA_material_types.h"
+#include "DNA_brush_types.h"
+#include "DNA_object_types.h"
 #include "DNA_screen_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_userdef_types.h"
 
-#include "BKE_image.h"
+#include "RNA_access.h"
+#include "RNA_enum_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
 #include "BKE_icons.h"
 #include "BKE_utildefines.h"
 
 #include "BIF_glutil.h"
 
 #include "ED_datafiles.h"
-#include "ED_previewrender.h"
+#include "ED_render.h"
 
 #include "UI_interface.h"
 #include "UI_interface_icons.h"
-#include "UI_resources.h" /* elubie: should be removed once the enum for the ICONS is in BIF_preview_icons.h */
 
 #include "interface_intern.h"
 
@@ -84,23 +89,45 @@ typedef struct IconImage {
 
 typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha);
 
+#define ICON_TYPE_PREVIEW      0
+#define ICON_TYPE_TEXTURE      1
+#define ICON_TYPE_BUFFER       2
+#define ICON_TYPE_VECTOR       3
+
 typedef struct DrawInfo {
+       int type;
+
+       union {
+               /* type specific data */
+               struct {
+                       VectorDrawFunc func;
+               } vector;
+               struct {
+                       IconImage* image;
+               } buffer;
+               struct {
+                       int x, y, w, h;
+               } texture;
+       } data;
+} DrawInfo;
+
+typedef struct IconTexture {
+       GLuint id;
        int w;
        int h;
-       float aspect;
-       VectorDrawFunc drawFunc; /* If drawFunc is defined then it is a vector icon, otherwise use rect */              
-       IconImage* icon;
-} DrawInfo;
+       float invw;
+       float invh;
+} IconTexture;
 
 /* ******************* STATIC LOCAL VARS ******************* */
 /* static here to cache results of icon directory scan, so it's not 
  * scanning the filesystem each time the menu is drawn */
 static struct ListBase iconfilelist = {0, 0};
-
+static IconTexture icongltex = {0, 0, 0, 0.0f, 0.0f};
 
 /* **************************************************** */
 
-static void def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int size)
+static void def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int size, int type)
 {
        Icon *new_icon = NULL;
        IconImage *iimg = NULL;
@@ -114,23 +141,28 @@ static void def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int
        new_icon->type = 0;     
 
        di = MEM_callocN(sizeof(DrawInfo), "drawinfo");
-       di->drawFunc = 0;
-       di->w = size;
-       di->h = size;
-       di->aspect = 1.0f;
-       
-       iimg = MEM_mallocN(sizeof(IconImage), "icon_img");
-       iimg->rect = MEM_mallocN(size*size*sizeof(unsigned int), "icon_rect");
-       iimg->w = size;
-       iimg->h = size;
+       di->type= type;
 
-       /* Here we store the rect in the icon - same as before */
-       imgsize = bbuf->x;
-       for (y=0; y<size; y++) {
-               memcpy(&iimg->rect[y*size], &bbuf->rect[(y+yofs)*imgsize+xofs], size*sizeof(int));
+       if(type == ICON_TYPE_TEXTURE) {
+               di->data.texture.x= xofs;
+               di->data.texture.y= yofs;
+               di->data.texture.w= size;
+               di->data.texture.h= size;
        }
+       else if(type == ICON_TYPE_BUFFER) {
+               iimg = MEM_mallocN(sizeof(IconImage), "icon_img");
+               iimg->rect = MEM_mallocN(size*size*sizeof(unsigned int), "icon_rect");
+               iimg->w = size;
+               iimg->h = size;
+
+               /* Here we store the rect in the icon - same as before */
+               imgsize = bbuf->x;
+               for (y=0; y<size; y++) {
+                       memcpy(&iimg->rect[y*size], &bbuf->rect[(y+yofs)*imgsize+xofs], size*sizeof(int));
+               }
 
-       di->icon = iimg;
+               di->data.buffer.image = iimg;
+       }
 
        new_icon->drawinfo_free = UI_icons_free_drawinfo;
        new_icon->drawinfo = di;
@@ -149,11 +181,8 @@ static void def_internal_vicon( int icon_id, VectorDrawFunc drawFunc)
        new_icon->type = 0;
 
        di = MEM_callocN(sizeof(DrawInfo), "drawinfo");
-       di->drawFunc =drawFunc;
-       di->w = ICON_DEFAULT_HEIGHT;
-       di->h = ICON_DEFAULT_HEIGHT;
-       di->aspect = 1.0f;
-       di->icon = NULL;
+       di->type= ICON_TYPE_VECTOR;
+       di->data.vector.func =drawFunc;
 
        new_icon->drawinfo_free = 0;
        new_icon->drawinfo = di;
@@ -302,7 +331,7 @@ static void vicon_editmode_hlt_draw(int x, int y, int w, int h, float alpha)
        viconutil_draw_points(pts, 3, 1);
 }
 
-static void vicon_editmode_dehlt_draw(int x, int y, int w, int h, float alpha)
+static void vicon_editmode_dehlt_draw(int x, int y, int w, int h, float UNUSED(alpha))
 {
        GLint pts[3][2];
 
@@ -317,7 +346,7 @@ static void vicon_editmode_dehlt_draw(int x, int y, int w, int h, float alpha)
        viconutil_draw_points(pts, 3, 1);
 }
 
-static void vicon_disclosure_tri_right_draw(int x, int y, int w, int h, float alpha)
+static void vicon_disclosure_tri_right_draw(int x, int y, int w, int UNUSED(h), float alpha)
 {
        GLint pts[3][2];
        int cx = x+w/2;
@@ -342,7 +371,29 @@ static void vicon_disclosure_tri_right_draw(int x, int y, int w, int h, float al
        viconutil_draw_lineloop_smooth(pts, 3);
 }
 
-static void vicon_disclosure_tri_down_draw(int x, int y, int w, int h, float alpha)
+static void vicon_small_tri_right_draw(int x, int y, int w, int UNUSED(h), float alpha)
+{
+       GLint pts[3][2];
+       int cx = x+w/2-4;
+       int cy = y+w/2;
+       int d = w/5, d2 = w/7;
+
+       viconutil_set_point(pts[0], cx-d2, cy+d);
+       viconutil_set_point(pts[1], cx-d2, cy-d);
+       viconutil_set_point(pts[2], cx+d2, cy);
+
+       glColor4f(0.2f, 0.2f, 0.2f, alpha);
+
+       glShadeModel(GL_SMOOTH);
+       glBegin(GL_TRIANGLES);
+       glVertex2iv(pts[0]);
+       glVertex2iv(pts[1]);
+       glVertex2iv(pts[2]);
+       glEnd();
+       glShadeModel(GL_FLAT);
+}
+
+static void vicon_disclosure_tri_down_draw(int x, int y, int w, int UNUSED(h), float alpha)
 {
        GLint pts[3][2];
        int cx = x+w/2;
@@ -367,7 +418,7 @@ static void vicon_disclosure_tri_down_draw(int x, int y, int w, int h, float alp
        viconutil_draw_lineloop_smooth(pts, 3);
 }
 
-static void vicon_move_up_draw(int x, int y, int w, int h, float alpha)
+static void vicon_move_up_draw(int x, int y, int w, int h, float UNUSED(alpha))
 {
        int d=-2;
 
@@ -385,7 +436,7 @@ static void vicon_move_up_draw(int x, int y, int w, int h, float alpha)
        glDisable(GL_LINE_SMOOTH);
 }
 
-static void vicon_move_down_draw(int x, int y, int w, int h, float alpha)
+static void vicon_move_down_draw(int x, int y, int w, int h, float UNUSED(alpha))
 {
        int d=2;
 
@@ -403,53 +454,134 @@ static void vicon_move_down_draw(int x, int y, int w, int h, float alpha)
        glDisable(GL_LINE_SMOOTH);
 }
 
+static void init_brush_icons()
+{
+
+#define INIT_BRUSH_ICON(icon_id, name)                                      \
+       bbuf = IMB_ibImageFromMemory((unsigned char*)datatoc_ ##name## _png, \
+                                    datatoc_ ##name## _png_size, IB_rect);  \
+       def_internal_icon(bbuf, icon_id, 0, 0, w, ICON_TYPE_BUFFER);         \
+       IMB_freeImBuf(bbuf);
+       // end INIT_BRUSH_ICON
+
+       ImBuf *bbuf;
+       const int w = 96;
+
+       INIT_BRUSH_ICON(ICON_BRUSH_ADD, add);
+       INIT_BRUSH_ICON(ICON_BRUSH_BLOB, blob);
+       INIT_BRUSH_ICON(ICON_BRUSH_BLUR, blur);
+       INIT_BRUSH_ICON(ICON_BRUSH_CLAY, clay);
+       INIT_BRUSH_ICON(ICON_BRUSH_CLONE, clone);
+       INIT_BRUSH_ICON(ICON_BRUSH_CREASE, crease);
+       INIT_BRUSH_ICON(ICON_BRUSH_DARKEN, darken);
+       INIT_BRUSH_ICON(ICON_BRUSH_SCULPT_DRAW, draw);
+       INIT_BRUSH_ICON(ICON_BRUSH_FILL, fill);
+       INIT_BRUSH_ICON(ICON_BRUSH_FLATTEN, flatten);
+       INIT_BRUSH_ICON(ICON_BRUSH_GRAB, grab);
+       INIT_BRUSH_ICON(ICON_BRUSH_INFLATE, inflate);
+       INIT_BRUSH_ICON(ICON_BRUSH_LAYER, layer);
+       INIT_BRUSH_ICON(ICON_BRUSH_LIGHTEN, lighten);
+       INIT_BRUSH_ICON(ICON_BRUSH_MIX, mix);
+       INIT_BRUSH_ICON(ICON_BRUSH_MULTIPLY, multiply);
+       INIT_BRUSH_ICON(ICON_BRUSH_NUDGE, nudge);
+       INIT_BRUSH_ICON(ICON_BRUSH_PINCH, pinch);
+       INIT_BRUSH_ICON(ICON_BRUSH_SCRAPE, scrape);
+       INIT_BRUSH_ICON(ICON_BRUSH_SMEAR, smear);
+       INIT_BRUSH_ICON(ICON_BRUSH_SMOOTH, smooth);
+       INIT_BRUSH_ICON(ICON_BRUSH_SNAKE_HOOK, snake_hook);
+       INIT_BRUSH_ICON(ICON_BRUSH_SOFTEN, soften);
+       INIT_BRUSH_ICON(ICON_BRUSH_SUBTRACT, subtract);
+       INIT_BRUSH_ICON(ICON_BRUSH_TEXDRAW, texdraw);
+       INIT_BRUSH_ICON(ICON_BRUSH_THUMB, thumb);
+       INIT_BRUSH_ICON(ICON_BRUSH_ROTATE, twist);
+       INIT_BRUSH_ICON(ICON_BRUSH_VERTEXDRAW, vertexdraw);
+
+#undef INIT_BRUSH_ICON
+}
+
 static void init_internal_icons()
 {
        bTheme *btheme= U.themes.first;
        ImBuf *bbuf= NULL;
-       int x, y;
+       int x, y, icontype;
        char iconfilestr[FILE_MAXDIR+FILE_MAXFILE];
-       char filenamestr[FILE_MAXFILE+16];      // 16 == strlen(".blender/icons/")+1
        
        if ((btheme!=NULL) && (strlen(btheme->tui.iconfile) > 0)) {
-       
-#ifdef WIN32
-               sprintf(filenamestr, "icons/%s", btheme->tui.iconfile);
-#else
-               sprintf(filenamestr, ".blender/icons/%s", btheme->tui.iconfile);
-#endif
-               
-               BLI_make_file_string("/", iconfilestr, BLI_gethome(), filenamestr);
-               
-               if (BLI_exists(iconfilestr)) {
-                       bbuf = IMB_loadiffname(iconfilestr, IB_rect);
-                       if(bbuf->x < ICON_IMAGE_W || bbuf->y < ICON_IMAGE_H) {
-                               printf("\n***WARNING***\nIcons file %s too small.\nUsing built-in Icons instead\n", iconfilestr);
-                               IMB_freeImBuf(bbuf);
-                               bbuf= NULL;
+               char *datadir= BLI_get_folder(BLENDER_DATAFILES, NULL);
+               if (datadir) {
+                       BLI_make_file_string("/", iconfilestr, datadir, btheme->tui.iconfile);
+                       
+                       if (BLI_exists(iconfilestr)) {
+                               bbuf = IMB_loadiffname(iconfilestr, IB_rect);
+                               if(bbuf->x < ICON_IMAGE_W || bbuf->y < ICON_IMAGE_H) {
+                                       if (G.f & G_DEBUG)
+                                               printf("\n***WARNING***\nIcons file %s too small.\nUsing built-in Icons instead\n", iconfilestr);
+                                       IMB_freeImBuf(bbuf);
+                                       bbuf= NULL;
+                               }
+                       }
                }
        }
-       }
        if(bbuf==NULL)
-               bbuf = IMB_ibImageFromMemory((int *)datatoc_blenderbuttons, datatoc_blenderbuttons_size, IB_rect);
+               bbuf = IMB_ibImageFromMemory((unsigned char*)datatoc_blenderbuttons, datatoc_blenderbuttons_size, IB_rect);
+
+       if(bbuf) {
+               /* free existing texture if any */
+               if(icongltex.id) {
+                       glDeleteTextures(1, &icongltex.id);
+                       icongltex.id= 0;
+               }
+
+               /* we only use a texture for cards with non-power of two */
+               if(GPU_non_power_of_two_support()) {
+                       glGenTextures(1, &icongltex.id);
+
+                       if(icongltex.id) {
+                               icongltex.w = bbuf->x;
+                               icongltex.h = bbuf->y;
+                               icongltex.invw = 1.0f/bbuf->x;
+                               icongltex.invh = 1.0f/bbuf->y;
+
+                               glBindTexture(GL_TEXTURE_2D, icongltex.id);
+                               glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bbuf->x, bbuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, bbuf->rect);
+                               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+                               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+                               glBindTexture(GL_TEXTURE_2D, 0);
+
+                               if(glGetError() == GL_OUT_OF_MEMORY) {
+                                       glDeleteTextures(1, &icongltex.id);
+                                       icongltex.id= 0;
+                               }
+                       }
+               }
+       }
 
-       for (y=0; y<ICON_GRID_ROWS; y++) {
-               for (x=0; x<ICON_GRID_COLS; x++) {
-                       def_internal_icon(bbuf, BIFICONID_FIRST + y*ICON_GRID_COLS + x,
-                               x*(ICON_GRID_W+ICON_GRID_MARGIN)+ICON_GRID_MARGIN,
-                               y*(ICON_GRID_H+ICON_GRID_MARGIN)+ICON_GRID_MARGIN, ICON_GRID_W);
+       if(icongltex.id)
+               icontype= ICON_TYPE_TEXTURE;
+       else
+               icontype= ICON_TYPE_BUFFER;
+       
+       if(bbuf) {
+               for (y=0; y<ICON_GRID_ROWS; y++) {
+                       for (x=0; x<ICON_GRID_COLS; x++) {
+                               def_internal_icon(bbuf, BIFICONID_FIRST + y*ICON_GRID_COLS + x,
+                                       x*(ICON_GRID_W+ICON_GRID_MARGIN)+ICON_GRID_MARGIN,
+                                       y*(ICON_GRID_H+ICON_GRID_MARGIN)+ICON_GRID_MARGIN, ICON_GRID_W,
+                                       icontype);
+                       }
                }
        }
 
-       def_internal_vicon(VICON_VIEW3D, vicon_view3d_draw);
-       def_internal_vicon(VICON_EDIT, vicon_edit_draw);
-       def_internal_vicon(VICON_EDITMODE_DEHLT, vicon_editmode_dehlt_draw);
-       def_internal_vicon(VICON_EDITMODE_HLT, vicon_editmode_hlt_draw);
-       def_internal_vicon(VICON_DISCLOSURE_TRI_RIGHT, vicon_disclosure_tri_right_draw);
-       def_internal_vicon(VICON_DISCLOSURE_TRI_DOWN, vicon_disclosure_tri_down_draw);
-       def_internal_vicon(VICON_MOVE_UP, vicon_move_up_draw);
-       def_internal_vicon(VICON_MOVE_DOWN, vicon_move_down_draw);
-       def_internal_vicon(VICON_X, vicon_x_draw);
+       def_internal_vicon(VICO_VIEW3D_VEC, vicon_view3d_draw);
+       def_internal_vicon(VICO_EDIT_VEC, vicon_edit_draw);
+       def_internal_vicon(VICO_EDITMODE_DEHLT, vicon_editmode_dehlt_draw);
+       def_internal_vicon(VICO_EDITMODE_HLT, vicon_editmode_hlt_draw);
+       def_internal_vicon(VICO_DISCLOSURE_TRI_RIGHT_VEC, vicon_disclosure_tri_right_draw);
+       def_internal_vicon(VICO_DISCLOSURE_TRI_DOWN_VEC, vicon_disclosure_tri_down_draw);
+       def_internal_vicon(VICO_MOVE_UP_VEC, vicon_move_up_draw);
+       def_internal_vicon(VICO_MOVE_DOWN_VEC, vicon_move_down_draw);
+       def_internal_vicon(VICO_X_VEC, vicon_x_draw);
+       def_internal_vicon(VICO_SMALL_TRI_RIGHT_VEC, vicon_small_tri_right_draw);
 
        IMB_freeImBuf(bbuf);
 }
@@ -466,14 +598,14 @@ static void init_iconfile_list(struct ListBase *list)
        char icondirstr[FILE_MAX];
        char iconfilestr[FILE_MAX+16]; /* allow 256 chars for file+dir */
        char olddir[FILE_MAX];
-       
+       char *datadir= NULL;
+
        list->first = list->last = NULL;
+       datadir = BLI_get_folder(BLENDER_DATAFILES, NULL);
 
-#ifdef WIN32
-       BLI_make_file_string("/", icondirstr, BLI_gethome(), "icons");
-#else
-       BLI_make_file_string("/", icondirstr, BLI_gethome(), ".blender/icons");
-#endif
+       if (!datadir) return;
+
+       BLI_make_file_string("/", icondirstr, datadir, "");
        
        if(BLI_exists(icondirstr)==0)
                return;
@@ -483,28 +615,37 @@ static void init_iconfile_list(struct ListBase *list)
        if(!BLI_getwdN(olddir)) 
                restoredir = 0;
        totfile = BLI_getdir(icondirstr, &dir);
-       if (restoredir)
-               chdir(olddir);
+       if (restoredir && !chdir(olddir)) {} /* fix warning about checking return value */
 
        for(i=0; i<totfile; i++) {
                if( (dir[i].type & S_IFREG) ) {
                        char *filename = dir[i].relname;
                        
                        if(BLI_testextensie(filename, ".png")) {
-                       
+
                                /* check to see if the image is the right size, continue if not */
                                /* copying strings here should go ok, assuming that we never get back
                                   a complete path to file longer than 256 chars */
                                sprintf(iconfilestr, "%s/%s", icondirstr, filename);
-                               if(BLI_exists(iconfilestr)) bbuf = IMB_loadiffname(iconfilestr, IB_rect);
-                               
-                               ifilex = bbuf->x;
-                               ifiley = bbuf->y;
-                               IMB_freeImBuf(bbuf);
+                               if(BLI_exists(iconfilestr))
+                                       bbuf= IMB_loadiffname(iconfilestr, IB_rect);
+                               else
+                                       bbuf= NULL;
+
+
+                               if(bbuf) {
+                                       ifilex = bbuf->x;
+                                       ifiley = bbuf->y;
+                                       IMB_freeImBuf(bbuf);
+                               }
+                               else {
+                                       ifilex= ifiley= 0;
+                               }
                                
+                               /* bad size or failed to load */
                                if ((ifilex != ICON_IMAGE_W) || (ifiley != ICON_IMAGE_H))
                                        continue;
-                       
+
                                /* found a potential icon file, so make an entry for it in the cache list */
                                ifile = MEM_callocN(sizeof(IconFile), "IconFile");
                                
@@ -523,6 +664,7 @@ static void init_iconfile_list(struct ListBase *list)
        
        for(; i>=0; i--){
                MEM_freeN(dir[i].relname);
+               MEM_freeN(dir[i].path);
                if (dir[i].string) MEM_freeN(dir[i].string);
        }
        free(dir);
@@ -563,6 +705,11 @@ ListBase *UI_iconfile_list(void)
 
 void UI_icons_free()
 {
+       if(icongltex.id) {
+               glDeleteTextures(1, &icongltex.id);
+               icongltex.id= 0;
+       }
+
        free_iconfile_list(&iconfilelist);
        BKE_icons_free();
 }
@@ -571,12 +718,14 @@ void UI_icons_free_drawinfo(void *drawinfo)
 {
        DrawInfo *di = drawinfo;
 
-       if (di)
-       {
-               if (di->icon) {
-                       MEM_freeN(di->icon->rect);
-                       MEM_freeN(di->icon);
+       if(di) {
+               if(di->type == ICON_TYPE_BUFFER) {
+                       if(di->data.buffer.image) {
+                               MEM_freeN(di->data.buffer.image->rect);
+                               MEM_freeN(di->data.buffer.image);
+                       }
                }
+
                MEM_freeN(di);
        }
 }
@@ -586,12 +735,7 @@ static DrawInfo *icon_create_drawinfo()
        DrawInfo *di = NULL;
 
        di = MEM_callocN(sizeof(DrawInfo), "di_icon");
-       
-       di->drawFunc = 0;
-       di->w = ICON_DEFAULT_HEIGHT;
-       di->h = ICON_DEFAULT_HEIGHT;
-       di->icon = NULL;
-       di->aspect = 1.0f;
+       di->type= ICON_TYPE_PREVIEW;
 
        return di;
 }
@@ -604,7 +748,8 @@ int UI_icon_get_width(int icon_id)
        icon = BKE_icon_get(icon_id);
        
        if (!icon) {
-               printf("UI_icon_get_width: Internal error, no icon for icon ID: %d\n", icon_id);
+               if (G.f & G_DEBUG)
+                       printf("UI_icon_get_width: Internal error, no icon for icon ID: %d\n", icon_id);
                return 0;
        }
        
@@ -615,7 +760,7 @@ int UI_icon_get_width(int icon_id)
        }
 
        if (di)
-               return di->w;
+               return ICON_DEFAULT_WIDTH;
 
        return 0;
 }
@@ -628,7 +773,8 @@ int UI_icon_get_height(int icon_id)
        icon = BKE_icon_get(icon_id);
        
        if (!icon) {
-               printf("UI_icon_get_height: Internal error, no icon for icon ID: %d\n", icon_id);
+               if (G.f & G_DEBUG)
+                       printf("UI_icon_get_height: Internal error, no icon for icon ID: %d\n", icon_id);
                return 0;
        }
        
@@ -640,7 +786,7 @@ int UI_icon_get_height(int icon_id)
        }
        
        if (di)
-               return di->h;
+               return ICON_DEFAULT_HEIGHT;
 
        return 0;
 }
@@ -650,56 +796,7 @@ void UI_icons_init(int first_dyn_id)
        init_iconfile_list(&iconfilelist);
        BKE_icons_init(first_dyn_id);
        init_internal_icons();
-}
-
-static void icon_copy_rect(ImBuf *ibuf, unsigned int w, unsigned int h, unsigned int *rect)
-{
-       struct ImBuf *ima;
-       unsigned int *drect, *srect;
-       float scaledx, scaledy;
-       short ex, ey, dx, dy;
-
-       /* paranoia test */
-       if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL))
-               return;
-       
-       /* waste of cpu cyles... but the imbuf API has no other way to scale fast (ton) */
-       ima = IMB_dupImBuf(ibuf);
-       
-       if (!ima) 
-               return;
-       
-       if (ima->x > ima->y) {
-               scaledx = (float)w;
-               scaledy =  ( (float)ima->y/(float)ima->x )*(float)w;
-       }
-       else {                  
-               scaledx =  ( (float)ima->x/(float)ima->y )*(float)h;
-               scaledy = (float)h;
-       }
-       
-       ex = (short)scaledx;
-       ey = (short)scaledy;
-       
-       dx = (w - ex) / 2;
-       dy = (h - ey) / 2;
-       
-       IMB_scalefastImBuf(ima, ex, ey);
-       
-       /* if needed, convert to 32 bits */
-       if(ima->rect==NULL)
-               IMB_rect_from_float(ima);
-
-       srect = ima->rect;
-       drect = rect;
-
-       drect+= dy*w+dx;
-       for (;ey > 0; ey--){            
-               memcpy(drect,srect, ex * sizeof(int));
-               drect += w;
-               srect += ima->x;
-       }
-       IMB_freeImBuf(ima);
+       init_brush_icons();
 }
 
 /* Render size for preview images at level miplevel */
@@ -717,140 +814,135 @@ static void icon_create_mipmap(struct PreviewImage* prv_img, int miplevel)
        unsigned int size = preview_render_size(miplevel);
 
        if (!prv_img) {
-               printf("Error: requested preview image does not exist");
+               if (G.f & G_DEBUG)
+                       printf("Error: requested preview image does not exist");
        }
        if (!prv_img->rect[miplevel]) {
                prv_img->w[miplevel] = size;
                prv_img->h[miplevel] = size;
                prv_img->changed[miplevel] = 1;
+               prv_img->changed_timestamp[miplevel] = 0;
                prv_img->rect[miplevel] = MEM_callocN(size*size*sizeof(unsigned int), "prv_rect"); 
        }
 }
 
-/* create single icon from jpg, png etc. */
-static void icon_from_image(Image *img, int miplevel)
-{
-       unsigned int pr_size;
-       short image_loaded = 0;
-       struct ImBuf* ibuf=NULL;
-       PreviewImage* pi;
-
-       /* img->ok is zero when Image cannot load */
-       if (img==NULL || img->ok==0)
-               return;
-
-       /* elubie: this needs to be changed: here image is always loaded if not
-          already there. Very expensive for large images. Need to find a way to 
-          only get existing ibuf */
-       ibuf = BKE_image_get_ibuf(img, NULL);
-       if(ibuf==NULL || ibuf->rect==NULL) {
-               return;
-       }
-       
-       pi = BKE_previewimg_get((ID*)img);      
-       
-       if(!pi) {
-               printf("preview image could'nt be allocated");
-               return;
-       }
-       /* we can only create the preview rect here, since loading possibly deallocated
-          old preview */
-       icon_create_mipmap(pi, miplevel);
-
-       pr_size = img->preview->w[miplevel]*img->preview->h[miplevel]*sizeof(unsigned int);
-
-       image_loaded = 1;
-       icon_copy_rect(ibuf, img->preview->w[miplevel], img->preview->h[miplevel], img->preview->rect[miplevel]);       
-}
-
-static void set_alpha(char* cp, int sizex, int sizey, char alpha) 
-{
-       int x,y;
-       for(y=0; y<sizey; y++) {
-               for(x=0; x<sizex; x++, cp+=4) {
-                       cp[3]= alpha;
-               }
-       }
-}
-
 /* only called when icon has changed */
 /* only call with valid pointer from UI_icon_draw */
-static void icon_set_image(Scene *scene, ID *id, PreviewImage* prv_img, int miplevel)
+static void icon_set_image(bContext *C, ID *id, PreviewImage* prv_img, int miplevel)
 {
-       RenderInfo ri;  
-       unsigned int pr_size = 0;
-       
        if (!prv_img) {
-               printf("No preview image for this ID: %s\n", id->name);
+               if (G.f & G_DEBUG)
+                       printf("No preview image for this ID: %s\n", id->name);
                return;
        }       
 
-       /* no drawing (see last parameter doDraw, just calculate preview image 
-               - hopefully small enough to be fast */
-       if (GS(id->name) == ID_IM)
-               icon_from_image((struct Image*)id, miplevel);
-       else {  
-               /* create the preview rect */
-               icon_create_mipmap(prv_img, miplevel);
-
-               ri.curtile= 0;
-               ri.tottile= 0;
-               ri.pr_rectx = prv_img->w[miplevel];
-               ri.pr_recty = prv_img->h[miplevel];
-               pr_size = ri.pr_rectx*ri.pr_recty*sizeof(unsigned int);
-               ri.rect = MEM_callocN(pr_size, "pr icon rect");
-
-               ED_preview_iconrender(scene, id, ri.rect, ri.pr_rectx, ri.pr_recty);
-
-               /* world is rendered with alpha=0, so it wasn't displayed 
-                  this could be render option for sky to, for later */
-               if (GS(id->name) == ID_WO) { 
-                       set_alpha( (char*) ri.rect, ri.pr_rectx, ri.pr_recty, 255);
-               } 
-               else if (GS(id->name) == ID_MA) {
-                       Material* mat = (Material*)id;
-                       if (mat->material_type == MA_TYPE_HALO) {
-                               set_alpha( (char*) ri.rect, ri.pr_rectx, ri.pr_recty, 255);
-                       }
-               }
-
-               memcpy(prv_img->rect[miplevel], ri.rect, pr_size);
+       /* create the preview rect */
+       icon_create_mipmap(prv_img, miplevel);
 
-               /* and clean up */
-               MEM_freeN(ri.rect);
-       }
+       ED_preview_icon_job(C, prv_img, id, prv_img->rect[miplevel],
+               prv_img->w[miplevel], prv_img->h[miplevel]);
 }
 
-static void icon_draw_rect(float x, float y, int w, int h, float aspect, int rw, int rh, unsigned int *rect)
+static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), int rw, int rh, unsigned int *rect, float alpha, float *rgb, short is_preview)
 {
+       /* modulate color */
+       if(alpha != 1.0f)
+               glPixelTransferf(GL_ALPHA_SCALE, alpha);
+
+       if(rgb) {
+               glPixelTransferf(GL_RED_SCALE, rgb[0]);
+               glPixelTransferf(GL_GREEN_SCALE, rgb[1]);
+               glPixelTransferf(GL_BLUE_SCALE, rgb[2]);
+       }
        
-       glRasterPos2f(x, y);
-       // XXX ui_rasterpos_safe(x, y, aspect);
-       
+       if(is_preview == 0) {
+               /* position */
+               glRasterPos2f(x,y);
+       }
+
+       /* draw */
        if((w<1 || h<1)) {
                // XXX - TODO 2.5 verify whether this case can happen
-               // and only print in debug
-               printf("what the heck! - icons are %i x %i pixels?\n", w, h);
+               if (G.f & G_DEBUG)
+                       printf("what the heck! - icons are %i x %i pixels?\n", w, h);
        }
        /* rect contains image in 'rendersize', we only scale if needed */
        else if(rw!=w && rh!=h) {
-               ImBuf *ima;
                if(w>2000 || h>2000) { /* something has gone wrong! */
-                       printf("insane icon size w=%d h=%d\n",w,h);
-                       return;
+                       if (G.f & G_DEBUG)
+                               printf("insane icon size w=%d h=%d\n",w,h);
+               }
+               else {
+                       ImBuf *ima;
+
+                       /* first allocate imbuf for scaling and copy preview into it */
+                       ima = IMB_allocImBuf(rw, rh, 32, IB_rect);
+                       memcpy(ima->rect, rect, rw*rh*sizeof(unsigned int));    
+                       
+                       /* scale it */
+                       IMB_scaleImBuf(ima, w, h);
+
+                       if(is_preview) {
+                               glaDrawPixelsSafe(x, y, w, h, w, GL_RGBA, GL_UNSIGNED_BYTE, ima->rect);
+                       }
+                       else {
+                               glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, ima->rect);
+                       }
+
+                       IMB_freeImBuf(ima);
                }
-               /* first allocate imbuf for scaling and copy preview into it */
-               ima = IMB_allocImBuf(rw, rh, 32, IB_rect, 0);
-               memcpy(ima->rect, rect, rw*rh*sizeof(unsigned int));    
-               
-               /* scale it */
-               IMB_scaleImBuf(ima, w, h);
-               glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, ima->rect);
-               
-               IMB_freeImBuf(ima);
        }
-       else
-               glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+       else {
+               if(is_preview) {
+                       glaDrawPixelsSafe(x, y, w, h, w, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+               }
+               else {
+                       glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+               }
+       }
+
+       /* restore color */
+       if(alpha != 0.0f)
+               glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
+       
+       if(rgb) {
+               glPixelTransferf(GL_RED_SCALE, 1.0f);
+               glPixelTransferf(GL_GREEN_SCALE, 1.0f);
+               glPixelTransferf(GL_BLUE_SCALE, 1.0f);
+       }
+}
+
+static void icon_draw_texture(float x, float y, float w, float h, int ix, int iy, int UNUSED(iw), int ih, float alpha, float *rgb)
+{
+       float x1, x2, y1, y2;
+
+       if(rgb) glColor4f(rgb[0], rgb[1], rgb[2], alpha);
+       else glColor4f(1.0f, 1.0f, 1.0f, alpha);
+
+       x1= ix*icongltex.invw;
+       x2= (ix + ih)*icongltex.invw;
+       y1= iy*icongltex.invh;
+       y2= (iy + ih)*icongltex.invh;
+
+       glEnable(GL_TEXTURE_2D);
+       glBindTexture(GL_TEXTURE_2D, icongltex.id);
+
+       glBegin(GL_QUADS);
+       glTexCoord2f(x1, y1);
+       glVertex2f(x, y);
+
+       glTexCoord2f(x2, y1);
+       glVertex2f(x+w, y);
+
+       glTexCoord2f(x2, y2);
+       glVertex2f(x+w, y+h);
+
+       glTexCoord2f(x1, y2);
+       glVertex2f(x, y+h);
+       glEnd();
+
+       glBindTexture(GL_TEXTURE_2D, 0);
+       glDisable(GL_TEXTURE_2D);
 }
 
 /* Drawing size for preview images at level miplevel */
@@ -863,18 +955,21 @@ static int preview_size(int miplevel)
        return 0;
 }
 
-static void icon_draw_size(float x, float y, int icon_id, float aspect, int miplevel, int draw_size, int nocreate)
+static void icon_draw_size(float x, float y, int icon_id, float aspect, float alpha, float *rgb, int miplevel, int draw_size, int UNUSED(nocreate), int is_preview)
 {
        Icon *icon = NULL;
        DrawInfo *di = NULL;
+       IconImage *iimg;
+       int w, h;
        
        icon = BKE_icon_get(icon_id);
        
        if (!icon) {
-               printf("icon_draw_mipmap: Internal error, no icon for icon ID: %d\n", icon_id);
+               if (G.f & G_DEBUG)
+                       printf("icon_draw_mipmap: Internal error, no icon for icon ID: %d\n", icon_id);
                return;
        }
-       
+
        di = (DrawInfo*)icon->drawinfo;
        
        if (!di) {
@@ -884,36 +979,43 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, int mipl
                icon->drawinfo_free = UI_icons_free_drawinfo;           
        }
        
-       di->aspect = aspect;
        /* scale width and height according to aspect */
-       di->w = (int)(draw_size/di->aspect + 0.5f);
-       di->h = (int)(draw_size/di->aspect + 0.5f);
+       w = (int)(draw_size/aspect + 0.5f);
+       h = (int)(draw_size/aspect + 0.5f);
        
-       if (di->drawFunc) {
+       if(di->type == ICON_TYPE_VECTOR) {
                /* vector icons use the uiBlock transformation, they are not drawn
                with untransformed coordinates like the other icons */
-               di->drawFunc(x, y, ICON_DEFAULT_HEIGHT, ICON_DEFAULT_HEIGHT, 1.0f); 
+               di->data.vector.func(x, y, ICON_DEFAULT_HEIGHT, ICON_DEFAULT_HEIGHT, 1.0f); 
        } 
-       else if (di->icon) {
+       else if(di->type == ICON_TYPE_TEXTURE) {
+               icon_draw_texture(x, y, w, h, di->data.texture.x, di->data.texture.y,
+                       di->data.texture.w, di->data.texture.h, alpha, rgb);
+       }
+       else if(di->type == ICON_TYPE_BUFFER) {
                /* it is a builtin icon */              
-               if (!di->icon->rect) return; /* something has gone wrong! */
+               iimg= di->data.buffer.image;
+
+               if(!iimg->rect) return; /* something has gone wrong! */
 
-               icon_draw_rect(x,y,di->w, di->h, di->aspect, di->icon->w, di->icon->h, di->icon->rect);
+               icon_draw_rect(x, y, w, h, aspect, iimg->w, iimg->h, iimg->rect, alpha, rgb, is_preview);
        }
-       else {
+       else if(di->type == ICON_TYPE_PREVIEW) {
                PreviewImage* pi = BKE_previewimg_get((ID*)icon->obj); 
 
-               if (pi) {                       
+               if(pi) {                        
                        /* no create icon on this level in code */
+                       if(!pi->rect[miplevel]) return; /* something has gone wrong! */
                        
-                       if (!pi->rect[miplevel]) return; /* something has gone wrong! */
-                       
-                       icon_draw_rect(x,y,di->w, di->h, di->aspect, pi->w[miplevel], pi->h[miplevel], pi->rect[miplevel]);             
+                       /* preview images use premul alpha ... */
+                       glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+                       icon_draw_rect(x, y, w, h, aspect, pi->w[miplevel], pi->h[miplevel], pi->rect[miplevel], 1.0f, NULL, is_preview);
+                       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                }
        }
 }
 
-void ui_id_icon_render(Scene *scene, ID *id)
+void ui_id_icon_render(bContext *C, ID *id, int preview)
 {
        PreviewImage *pi = BKE_previewimg_get(id); 
                
@@ -921,58 +1023,118 @@ void ui_id_icon_render(Scene *scene, ID *id)
                if ((pi->changed[0] ||!pi->rect[0])) /* changed only ever set by dynamic icons */
                {
                        /* create the preview rect if necessary */                              
-                       icon_set_image(scene, id, pi, 0);
+                       
+                       icon_set_image(C, id, pi, 0);           /* icon size */
+                       if (preview)
+                               icon_set_image(C, id, pi, 1);   /* preview size */
+                       
                        pi->changed[0] = 0;
                }
        }
 }
 
+static int ui_id_brush_get_icon(bContext *C, ID *id, int preview)
+{
+       Brush *br = (Brush*)id;
 
+       if(br->flag & BRUSH_CUSTOM_ICON) {
+               BKE_icon_getid(id);
+               ui_id_icon_render(C, id, preview);
+       }
+       else if(!id->icon_id) {
+               /* no icon found, reset it */
+               
+               /* this is not nice, should probably make
+                  brushes be strictly in one paint mode only
+                  to avoid this kind of thing */
+               Object *ob = CTX_data_active_object(C);
+               EnumPropertyItem *items;
+               int tool;
+               
+               if(ob && (ob->mode & OB_MODE_SCULPT)) {
+                       items = brush_sculpt_tool_items;
+                       tool = br->sculpt_tool;
+               }
+               else if(ob && (ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT))) {
+                       items = brush_vertexpaint_tool_items;
+                       tool = br->vertexpaint_tool;
+               }
+               else {
+                       items = brush_imagepaint_tool_items;
+                       tool = br->imagepaint_tool;
+               }
 
-static void icon_draw_mipmap(float x, float y, int icon_id, float aspect, int miplevel, int nocreate)
+               RNA_enum_icon_from_value(items, tool, &id->icon_id);
+       }
+
+       return id->icon_id;
+}
+
+int ui_id_icon_get(bContext *C, ID *id, int preview)
+{
+       int iconid= 0;
+       
+       /* icon */
+       switch(GS(id->name))
+       {
+               case ID_BR:
+                       iconid= ui_id_brush_get_icon(C, id, preview);
+                       break;
+               case ID_MA: /* fall through */
+               case ID_TE: /* fall through */
+               case ID_IM: /* fall through */
+               case ID_WO: /* fall through */
+               case ID_LA: /* fall through */
+                       iconid= BKE_icon_getid(id);
+                       /* checks if not exists, or changed */
+                       ui_id_icon_render(C, id, preview);
+                       break;
+               default:
+                       break;
+       }
+
+       return iconid;
+}
+
+static void icon_draw_mipmap(float x, float y, int icon_id, float aspect, float alpha, int miplevel, int nocreate)
 {
        int draw_size = preview_size(miplevel);
-       icon_draw_size(x,y,icon_id, aspect, miplevel, draw_size, nocreate);
+       icon_draw_size(x, y, icon_id, aspect, alpha, NULL, miplevel, draw_size, nocreate, FALSE);
 }
 
+void UI_icon_draw_aspect(float x, float y, int icon_id, float aspect, float alpha)
+{
+       icon_draw_mipmap(x, y, icon_id, aspect, alpha, PREVIEW_MIPMAP_ZERO, 0);
+}
 
-void UI_icon_draw_aspect(float x, float y, int icon_id, float aspect)
+void UI_icon_draw_aspect_color(float x, float y, int icon_id, float aspect, float *rgb)
 {
-       icon_draw_mipmap(x,y,icon_id, aspect, PREVIEW_MIPMAP_ZERO, 0);
+       int draw_size = preview_size(PREVIEW_MIPMAP_ZERO);
+       icon_draw_size(x, y, icon_id, aspect, 1.0f, rgb, PREVIEW_MIPMAP_ZERO, draw_size, FALSE, FALSE);
 }
 
 void UI_icon_draw(float x, float y, int icon_id)
 {
-       UI_icon_draw_aspect(x, y, icon_id, 1.0f);
+       UI_icon_draw_aspect(x, y, icon_id, 1.0f, 1.0f);
 }
 
-void UI_icon_draw_size_blended(float x, float y, int size, int icon_id, int shade)
+void UI_icon_draw_size(float x, float y, int size, int icon_id, float alpha)
 {
-       if(shade < 0) {
-               float r= (128+shade)/128.0f;
-               glPixelTransferf(GL_ALPHA_SCALE, r);
-       }
-
-       icon_draw_size(x,y,icon_id, 1.0f, 0, size, 1);
-
-       if(shade < 0)
-               glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
+       icon_draw_size(x, y, icon_id, 1.0f, alpha, NULL, PREVIEW_MIPMAP_ZERO, size, TRUE, FALSE);
 }
 
-void UI_icon_draw_preview(float x, float y, int icon_id, int nocreate)
+void UI_icon_draw_preview(float x, float y, int icon_id)
 {
-       icon_draw_mipmap(x,y,icon_id, 1.0f, PREVIEW_MIPMAP_LARGE, nocreate);
+       icon_draw_mipmap(x, y, icon_id, 1.0f, 1.0f, PREVIEW_MIPMAP_LARGE, 0);
 }
 
-void UI_icon_draw_aspect_blended(float x, float y, int icon_id, float aspect, int shade)
+void UI_icon_draw_preview_aspect(float x, float y, int icon_id, float aspect)
 {
-       if(shade < 0) {
-               float r= (128+shade)/128.0f;
-               glPixelTransferf(GL_ALPHA_SCALE, r);
-       }
-
-       UI_icon_draw_aspect(x, y, icon_id, aspect);
+       icon_draw_mipmap(x, y, icon_id, aspect, 1.0f, PREVIEW_MIPMAP_LARGE, 0);
+}
 
-       if(shade < 0)
-               glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
+void UI_icon_draw_preview_aspect_size(float x, float y, int icon_id, float aspect, int size)
+{
+       icon_draw_size(x, y, icon_id, aspect, 1.0f, NULL, PREVIEW_MIPMAP_LARGE, size, FALSE, TRUE);
 }
+