1a3d8d20d4794cbe31a3351747764da98e40bd31
[blender.git] / source / blender / editors / interface / interface_icons.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributors: Blender Foundation, full recode
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/interface/interface_icons.c
27  *  \ingroup edinterface
28  */
29
30
31 #include <math.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #ifndef WIN32
36 #  include <unistd.h>
37 #else
38 #  include <io.h>
39 #  include <direct.h>
40 #  include "BLI_winstuff.h"
41 #endif
42
43 #include "MEM_guardedalloc.h"
44
45 #include "GPU_extensions.h"
46
47 #include "BLI_math.h"
48 #include "BLI_blenlib.h"
49 #include "BLI_utildefines.h"
50
51 #include "DNA_brush_types.h"
52 #include "DNA_dynamicpaint_types.h"
53 #include "DNA_object_types.h"
54 #include "DNA_screen_types.h"
55 #include "DNA_space_types.h"
56
57 #include "RNA_access.h"
58 #include "RNA_enum_types.h"
59
60 #include "BKE_context.h"
61 #include "BKE_global.h"
62 #include "BKE_icons.h"
63
64 #include "IMB_imbuf.h"
65 #include "IMB_imbuf_types.h"
66
67 #include "BIF_gl.h"
68 #include "BIF_glutil.h"
69
70 #include "ED_datafiles.h"
71 #include "ED_render.h"
72
73 #include "UI_interface.h"
74 #include "UI_interface_icons.h"
75
76 #include "interface_intern.h"
77
78 #define ICON_GRID_COLS      26
79 #define ICON_GRID_ROWS      30
80
81 #define ICON_GRID_MARGIN    10
82 #define ICON_GRID_W         32
83 #define ICON_GRID_H         32
84
85 typedef struct IconImage {
86         int w;
87         int h;
88         unsigned int *rect;
89         unsigned char *datatoc_rect;
90         int datatoc_size;
91 } IconImage;
92
93 typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha);
94
95 #define ICON_TYPE_PREVIEW   0
96 #define ICON_TYPE_TEXTURE   1
97 #define ICON_TYPE_BUFFER    2
98 #define ICON_TYPE_VECTOR    3
99
100 typedef struct DrawInfo {
101         int type;
102
103         union {
104                 /* type specific data */
105                 struct {
106                         VectorDrawFunc func;
107                 } vector;
108                 struct {
109                         IconImage *image;
110                 } buffer;
111                 struct {
112                         int x, y, w, h;
113                 } texture;
114         } data;
115 } DrawInfo;
116
117 typedef struct IconTexture {
118         GLuint id;
119         int w;
120         int h;
121         float invw;
122         float invh;
123 } IconTexture;
124
125 /* ******************* STATIC LOCAL VARS ******************* */
126 /* static here to cache results of icon directory scan, so it's not 
127  * scanning the filesystem each time the menu is drawn */
128 static struct ListBase iconfilelist = {NULL, NULL};
129 static IconTexture icongltex = {0, 0, 0, 0.0f, 0.0f};
130
131 /* **************************************************** */
132
133 #ifndef WITH_HEADLESS
134
135 static DrawInfo *def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int size, int type)
136 {
137         Icon *new_icon = NULL;
138         IconImage *iimg = NULL;
139         DrawInfo *di;
140
141         new_icon = MEM_callocN(sizeof(Icon), "texicon");
142
143         new_icon->obj = NULL; /* icon is not for library object */
144         new_icon->type = 0;
145
146         di = MEM_callocN(sizeof(DrawInfo), "drawinfo");
147         di->type = type;
148
149         if (type == ICON_TYPE_TEXTURE) {
150                 di->data.texture.x = xofs;
151                 di->data.texture.y = yofs;
152                 di->data.texture.w = size;
153                 di->data.texture.h = size;
154         }
155         else if (type == ICON_TYPE_BUFFER) {
156                 iimg = MEM_callocN(sizeof(IconImage), "icon_img");
157                 iimg->w = size;
158                 iimg->h = size;
159
160                 /* icon buffers can get initialized runtime now, via datatoc */
161                 if (bbuf) {
162                         int y, imgsize;
163                         
164                         iimg->rect = MEM_mallocN(size * size * sizeof(unsigned int), "icon_rect");
165                         
166                         /* Here we store the rect in the icon - same as before */
167                         if (size == bbuf->x && size == bbuf->y && xofs == 0 && yofs == 0)
168                                 memcpy(iimg->rect, bbuf->rect, size * size * sizeof(int));
169                         else {
170                                 /* this code assumes square images */
171                                 imgsize = bbuf->x;
172                                 for (y = 0; y < size; y++) {
173                                         memcpy(&iimg->rect[y * size], &bbuf->rect[(y + yofs) * imgsize + xofs], size * sizeof(int));
174                                 }
175                         }
176                 }
177                 di->data.buffer.image = iimg;
178         }
179
180         new_icon->drawinfo_free = UI_icons_free_drawinfo;
181         new_icon->drawinfo = di;
182
183         BKE_icon_set(icon_id, new_icon);
184         
185         return di;
186 }
187
188 static void def_internal_vicon(int icon_id, VectorDrawFunc drawFunc)
189 {
190         Icon *new_icon = NULL;
191         DrawInfo *di;
192
193         new_icon = MEM_callocN(sizeof(Icon), "texicon");
194
195         new_icon->obj = NULL; /* icon is not for library object */
196         new_icon->type = 0;
197
198         di = MEM_callocN(sizeof(DrawInfo), "drawinfo");
199         di->type = ICON_TYPE_VECTOR;
200         di->data.vector.func = drawFunc;
201
202         new_icon->drawinfo_free = NULL;
203         new_icon->drawinfo = di;
204
205         BKE_icon_set(icon_id, new_icon);
206 }
207
208 /* Vector Icon Drawing Routines */
209
210 /* Utilities */
211
212 static void viconutil_set_point(GLint pt[2], int x, int y)
213 {
214         pt[0] = x;
215         pt[1] = y;
216 }
217
218 static void viconutil_draw_tri(GLint(*pts)[2])
219 {
220         glBegin(GL_TRIANGLES);
221         glVertex2iv(pts[0]);
222         glVertex2iv(pts[1]);
223         glVertex2iv(pts[2]);
224         glEnd();
225 }
226
227 static void viconutil_draw_lineloop(GLint(*pts)[2], int numPoints)
228 {
229         int i;
230
231         glBegin(GL_LINE_LOOP);
232         for (i = 0; i < numPoints; i++) {
233                 glVertex2iv(pts[i]);
234         }
235         glEnd();
236 }
237
238 static void viconutil_draw_lineloop_smooth(GLint(*pts)[2], int numPoints)
239 {
240         glEnable(GL_LINE_SMOOTH);
241         viconutil_draw_lineloop(pts, numPoints);
242         glDisable(GL_LINE_SMOOTH);
243 }
244
245 static void viconutil_draw_points(GLint(*pts)[2], int numPoints, int pointSize)
246 {
247         int i;
248
249         glBegin(GL_QUADS);
250         for (i = 0; i < numPoints; i++) {
251                 int x = pts[i][0], y = pts[i][1];
252
253                 glVertex2i(x - pointSize, y - pointSize);
254                 glVertex2i(x + pointSize, y - pointSize);
255                 glVertex2i(x + pointSize, y + pointSize);
256                 glVertex2i(x - pointSize, y + pointSize);
257         }
258         glEnd();
259 }
260
261 /* Drawing functions */
262
263 static void vicon_x_draw(int x, int y, int w, int h, float alpha)
264 {
265         x += 3;
266         y += 3;
267         w -= 6;
268         h -= 6;
269
270         glEnable(GL_LINE_SMOOTH);
271
272         glLineWidth(2.5);
273         
274         glColor4f(0.0, 0.0, 0.0, alpha);
275         glBegin(GL_LINES);
276         glVertex2i(x, y);
277         glVertex2i(x + w, y + h);
278         glVertex2i(x + w, y);
279         glVertex2i(x, y + h);
280         glEnd();
281
282         glLineWidth(1.0);
283         
284         glDisable(GL_LINE_SMOOTH);
285 }
286
287 static void vicon_view3d_draw(int x, int y, int w, int h, float alpha)
288 {
289         int cx = x + w / 2;
290         int cy = y + h / 2;
291         int d = MAX2(2, h / 3);
292
293         glColor4f(0.5, 0.5, 0.5, alpha);
294         glBegin(GL_LINES);
295         glVertex2i(x, cy - d);
296         glVertex2i(x + w, cy - d);
297         glVertex2i(x, cy + d);
298         glVertex2i(x + w, cy + d);
299
300         glVertex2i(cx - d, y);
301         glVertex2i(cx - d, y + h);
302         glVertex2i(cx + d, y);
303         glVertex2i(cx + d, y + h);
304         glEnd();
305         
306         glColor4f(0.0, 0.0, 0.0, alpha);
307         glBegin(GL_LINES);
308         glVertex2i(x, cy);
309         glVertex2i(x + w, cy);
310         glVertex2i(cx, y);
311         glVertex2i(cx, y + h);
312         glEnd();
313 }
314
315 static void vicon_edit_draw(int x, int y, int w, int h, float alpha)
316 {
317         GLint pts[4][2];
318
319         viconutil_set_point(pts[0], x + 3,     y + 3);
320         viconutil_set_point(pts[1], x + w - 3, y + 3);
321         viconutil_set_point(pts[2], x + w - 3, y + h - 3);
322         viconutil_set_point(pts[3], x + 3,     y + h - 3);
323
324         glColor4f(0.0, 0.0, 0.0, alpha);
325         viconutil_draw_lineloop(pts, 4);
326
327         glColor3f(1, 1, 0.0);
328         viconutil_draw_points(pts, 4, 1);
329 }
330
331 static void vicon_editmode_hlt_draw(int x, int y, int w, int h, float alpha)
332 {
333         GLint pts[3][2];
334
335         viconutil_set_point(pts[0], x + w / 2, y + h - 2);
336         viconutil_set_point(pts[1], x + 3,     y + 4);
337         viconutil_set_point(pts[2], x + w - 3, y + 4);
338
339         glColor4f(0.5, 0.5, 0.5, alpha);
340         viconutil_draw_tri(pts);
341
342         glColor4f(0.0, 0.0, 0.0, 1);
343         viconutil_draw_lineloop_smooth(pts, 3);
344
345         glColor3f(1, 1, 0.0);
346         viconutil_draw_points(pts, 3, 1);
347 }
348
349 static void vicon_editmode_dehlt_draw(int x, int y, int w, int h, float UNUSED(alpha))
350 {
351         GLint pts[3][2];
352
353         viconutil_set_point(pts[0], x + w / 2, y + h - 2);
354         viconutil_set_point(pts[1], x + 3,     y + 4);
355         viconutil_set_point(pts[2], x + w - 3, y + 4);
356
357         glColor4f(0.0f, 0.0f, 0.0f, 1);
358         viconutil_draw_lineloop_smooth(pts, 3);
359
360         glColor3f(0.9f, 0.9f, 0.9f);
361         viconutil_draw_points(pts, 3, 1);
362 }
363
364 static void vicon_disclosure_tri_right_draw(int x, int y, int w, int UNUSED(h), float alpha)
365 {
366         GLint pts[3][2];
367         int cx = x + w / 2;
368         int cy = y + w / 2;
369         int d = w / 3, d2 = w / 5;
370
371         viconutil_set_point(pts[0], cx - d2, cy + d);
372         viconutil_set_point(pts[1], cx - d2, cy - d);
373         viconutil_set_point(pts[2], cx + d2, cy);
374
375         glShadeModel(GL_SMOOTH);
376         glBegin(GL_TRIANGLES);
377         glColor4f(0.8f, 0.8f, 0.8f, alpha);
378         glVertex2iv(pts[0]);
379         glVertex2iv(pts[1]);
380         glColor4f(0.3f, 0.3f, 0.3f, alpha);
381         glVertex2iv(pts[2]);
382         glEnd();
383         glShadeModel(GL_FLAT);
384
385         glColor4f(0.0f, 0.0f, 0.0f, 1);
386         viconutil_draw_lineloop_smooth(pts, 3);
387 }
388
389 static void vicon_small_tri_right_draw(int x, int y, int w, int UNUSED(h), float alpha)
390 {
391         GLint pts[3][2];
392         int cx = x + w / 2 - 4;
393         int cy = y + w / 2;
394         int d = w / 5, d2 = w / 7;
395
396         viconutil_set_point(pts[0], cx - d2, cy + d);
397         viconutil_set_point(pts[1], cx - d2, cy - d);
398         viconutil_set_point(pts[2], cx + d2, cy);
399
400         glColor4f(0.2f, 0.2f, 0.2f, alpha);
401
402         glShadeModel(GL_SMOOTH);
403         glBegin(GL_TRIANGLES);
404         glVertex2iv(pts[0]);
405         glVertex2iv(pts[1]);
406         glVertex2iv(pts[2]);
407         glEnd();
408         glShadeModel(GL_FLAT);
409 }
410
411 static void vicon_disclosure_tri_down_draw(int x, int y, int w, int UNUSED(h), float alpha)
412 {
413         GLint pts[3][2];
414         int cx = x + w / 2;
415         int cy = y + w / 2;
416         int d = w / 3, d2 = w / 5;
417
418         viconutil_set_point(pts[0], cx + d, cy + d2);
419         viconutil_set_point(pts[1], cx - d, cy + d2);
420         viconutil_set_point(pts[2], cx, cy - d2);
421
422         glShadeModel(GL_SMOOTH);
423         glBegin(GL_TRIANGLES);
424         glColor4f(0.8f, 0.8f, 0.8f, alpha);
425         glVertex2iv(pts[0]);
426         glVertex2iv(pts[1]);
427         glColor4f(0.3f, 0.3f, 0.3f, alpha);
428         glVertex2iv(pts[2]);
429         glEnd();
430         glShadeModel(GL_FLAT);
431
432         glColor4f(0.0f, 0.0f, 0.0f, 1);
433         viconutil_draw_lineloop_smooth(pts, 3);
434 }
435
436 static void vicon_move_up_draw(int x, int y, int w, int h, float UNUSED(alpha))
437 {
438         int d = -2;
439
440         glEnable(GL_LINE_SMOOTH);
441         glLineWidth(1);
442         glColor3f(0.0, 0.0, 0.0);
443
444         glBegin(GL_LINE_STRIP);
445         glVertex2i(x + w / 2 - d * 2, y + h / 2 + d);
446         glVertex2i(x + w / 2, y + h / 2 - d + 1);
447         glVertex2i(x + w / 2 + d * 2, y + h / 2 + d);
448         glEnd();
449
450         glLineWidth(1.0);
451         glDisable(GL_LINE_SMOOTH);
452 }
453
454 static void vicon_move_down_draw(int x, int y, int w, int h, float UNUSED(alpha))
455 {
456         int d = 2;
457
458         glEnable(GL_LINE_SMOOTH);
459         glLineWidth(1);
460         glColor3f(0.0, 0.0, 0.0);
461
462         glBegin(GL_LINE_STRIP);
463         glVertex2i(x + w / 2 - d * 2, y + h / 2 + d);
464         glVertex2i(x + w / 2, y + h / 2 - d - 1);
465         glVertex2i(x + w / 2 + d * 2, y + h / 2 + d);
466         glEnd();
467
468         glLineWidth(1.0);
469         glDisable(GL_LINE_SMOOTH);
470 }
471
472 #ifndef WITH_HEADLESS
473
474 static void init_brush_icons(void)
475 {
476
477 #define INIT_BRUSH_ICON(icon_id, name)                                          \
478         {                                                                           \
479                 unsigned char *rect = (unsigned char *)datatoc_ ##name## _png;                  \
480                 int size = datatoc_ ##name## _png_size;                                                                 \
481                 DrawInfo *di;                                                                                                                   \
482                 \
483                 di = def_internal_icon(NULL, icon_id, 0, 0, w, ICON_TYPE_BUFFER);               \
484                 di->data.buffer.image->datatoc_rect = rect;                                                             \
485                 di->data.buffer.image->datatoc_size = size;                                                             \
486         }
487         /* end INIT_BRUSH_ICON */
488
489         const int w = 96; /* warning, brush size hardcoded in C, but it gets scaled */
490
491         INIT_BRUSH_ICON(ICON_BRUSH_ADD, add);
492         INIT_BRUSH_ICON(ICON_BRUSH_BLOB, blob);
493         INIT_BRUSH_ICON(ICON_BRUSH_BLUR, blur);
494         INIT_BRUSH_ICON(ICON_BRUSH_CLAY, clay);
495         INIT_BRUSH_ICON(ICON_BRUSH_CLAY_STRIPS, claystrips);
496         INIT_BRUSH_ICON(ICON_BRUSH_CLONE, clone);
497         INIT_BRUSH_ICON(ICON_BRUSH_CREASE, crease);
498         INIT_BRUSH_ICON(ICON_BRUSH_DARKEN, darken);
499         INIT_BRUSH_ICON(ICON_BRUSH_SCULPT_DRAW, draw);
500         INIT_BRUSH_ICON(ICON_BRUSH_FILL, fill);
501         INIT_BRUSH_ICON(ICON_BRUSH_FLATTEN, flatten);
502         INIT_BRUSH_ICON(ICON_BRUSH_GRAB, grab);
503         INIT_BRUSH_ICON(ICON_BRUSH_INFLATE, inflate);
504         INIT_BRUSH_ICON(ICON_BRUSH_LAYER, layer);
505         INIT_BRUSH_ICON(ICON_BRUSH_LIGHTEN, lighten);
506         INIT_BRUSH_ICON(ICON_BRUSH_MASK, mask);
507         INIT_BRUSH_ICON(ICON_BRUSH_MIX, mix);
508         INIT_BRUSH_ICON(ICON_BRUSH_MULTIPLY, multiply);
509         INIT_BRUSH_ICON(ICON_BRUSH_NUDGE, nudge);
510         INIT_BRUSH_ICON(ICON_BRUSH_PINCH, pinch);
511         INIT_BRUSH_ICON(ICON_BRUSH_SCRAPE, scrape);
512         INIT_BRUSH_ICON(ICON_BRUSH_SMEAR, smear);
513         INIT_BRUSH_ICON(ICON_BRUSH_SMOOTH, smooth);
514         INIT_BRUSH_ICON(ICON_BRUSH_SNAKE_HOOK, snake_hook);
515         INIT_BRUSH_ICON(ICON_BRUSH_SOFTEN, soften);
516         INIT_BRUSH_ICON(ICON_BRUSH_SUBTRACT, subtract);
517         INIT_BRUSH_ICON(ICON_BRUSH_TEXDRAW, texdraw);
518         INIT_BRUSH_ICON(ICON_BRUSH_THUMB, thumb);
519         INIT_BRUSH_ICON(ICON_BRUSH_ROTATE, twist);
520         INIT_BRUSH_ICON(ICON_BRUSH_VERTEXDRAW, vertexdraw);
521
522 #undef INIT_BRUSH_ICON
523 }
524
525 static void icon_verify_datatoc(IconImage *iimg)
526 {
527         /* if it has own rect, things are all OK */
528         if (iimg->rect)
529                 return;
530         
531         if (iimg->datatoc_rect) {
532                 ImBuf *bbuf = IMB_ibImageFromMemory(iimg->datatoc_rect,
533                                                     iimg->datatoc_size, IB_rect, NULL, "<matcap icon>");
534                 /* w and h were set on initialize */
535                 if (bbuf->x != iimg->h && bbuf->y != iimg->w)
536                         IMB_scalefastImBuf(bbuf, iimg->w, iimg->h);
537                 
538                 iimg->rect = bbuf->rect;
539                 bbuf->rect = NULL;
540                 IMB_freeImBuf(bbuf);
541         }
542 }
543
544 static void init_matcap_icons(void)
545 {
546         /* dynamic allocation now, tucking datatoc pointers in DrawInfo */
547 #define INIT_MATCAP_ICON(icon_id, name)                                       \
548         {                                                                         \
549                 unsigned char *rect = (unsigned char *)datatoc_ ##name## _jpg;        \
550                 int size = datatoc_ ##name## _jpg_size;                               \
551                 DrawInfo *di;                                                         \
552                                                                                       \
553                 di = def_internal_icon(NULL, icon_id, 0, 0, 128, ICON_TYPE_BUFFER);   \
554                 di->data.buffer.image->datatoc_rect = rect;                           \
555                 di->data.buffer.image->datatoc_size = size;                           \
556         } (void)0
557
558         INIT_MATCAP_ICON(ICON_MATCAP_01, mc01);
559         INIT_MATCAP_ICON(ICON_MATCAP_02, mc02);
560         INIT_MATCAP_ICON(ICON_MATCAP_03, mc03);
561         INIT_MATCAP_ICON(ICON_MATCAP_04, mc04);
562         INIT_MATCAP_ICON(ICON_MATCAP_05, mc05);
563         INIT_MATCAP_ICON(ICON_MATCAP_06, mc06);
564         INIT_MATCAP_ICON(ICON_MATCAP_07, mc07);
565         INIT_MATCAP_ICON(ICON_MATCAP_08, mc08);
566         INIT_MATCAP_ICON(ICON_MATCAP_09, mc09);
567         INIT_MATCAP_ICON(ICON_MATCAP_10, mc10);
568         INIT_MATCAP_ICON(ICON_MATCAP_11, mc11);
569         INIT_MATCAP_ICON(ICON_MATCAP_12, mc12);
570         INIT_MATCAP_ICON(ICON_MATCAP_13, mc13);
571         INIT_MATCAP_ICON(ICON_MATCAP_14, mc14);
572         INIT_MATCAP_ICON(ICON_MATCAP_15, mc15);
573         INIT_MATCAP_ICON(ICON_MATCAP_16, mc16);
574
575 #undef INIT_MATCAP_ICON
576
577 }
578
579 static void init_internal_icons(void)
580 {
581 //      bTheme *btheme = UI_GetTheme();
582         ImBuf *b16buf = NULL, *b32buf = NULL;
583         int x, y, icontype;
584
585 #if 0 // temp disabled
586         if ((btheme != NULL) && btheme->tui.iconfile[0]) {
587                 char *icondir = BLI_get_folder(BLENDER_DATAFILES, "icons");
588                 char iconfilestr[FILE_MAX];
589                 
590                 if (icondir) {
591                         BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, btheme->tui.iconfile);
592                         bbuf = IMB_loadiffname(iconfilestr, IB_rect, NULL); /* if the image is missing bbuf will just be NULL */
593                         if (bbuf && (bbuf->x < ICON_IMAGE_W || bbuf->y < ICON_IMAGE_H)) {
594                                 printf("\n***WARNING***\nIcons file %s too small.\nUsing built-in Icons instead\n", iconfilestr);
595                                 IMB_freeImBuf(bbuf);
596                                 bbuf = NULL;
597                         }
598                 }
599                 else {
600                         printf("%s: 'icons' data path not found, continuing\n", __func__);
601                 }
602         }
603 #endif
604         if (b16buf == NULL)
605                 b16buf = IMB_ibImageFromMemory((unsigned char *)datatoc_blender_icons16_png,
606                                              datatoc_blender_icons16_png_size, IB_rect, NULL, "<blender icons>");
607         if (b16buf)
608                 IMB_premultiply_alpha(b16buf);
609
610         if (b32buf == NULL)
611                 b32buf = IMB_ibImageFromMemory((unsigned char *)datatoc_blender_icons32_png,
612                                              datatoc_blender_icons32_png_size, IB_rect, NULL, "<blender icons>");
613         if (b32buf)
614                 IMB_premultiply_alpha(b32buf);
615         
616         if (b16buf && b32buf) {
617                 /* free existing texture if any */
618                 if (icongltex.id) {
619                         glDeleteTextures(1, &icongltex.id);
620                         icongltex.id = 0;
621                 }
622
623                 /* we only use a texture for cards with non-power of two */
624                 if (GPU_non_power_of_two_support()) {
625                         glGenTextures(1, &icongltex.id);
626
627                         if (icongltex.id) {
628                                 int level = 2;
629                                 
630                                 icongltex.w = b32buf->x;
631                                 icongltex.h = b32buf->y;
632                                 icongltex.invw = 1.0f / b32buf->x;
633                                 icongltex.invh = 1.0f / b32buf->y;
634
635                                 glBindTexture(GL_TEXTURE_2D, icongltex.id);
636                                 
637                                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, b32buf->x, b32buf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, b32buf->rect);
638                                 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, b16buf->x, b16buf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, b16buf->rect);
639                                 
640                                 while (b16buf->x > 1) {
641                                         ImBuf *nbuf = IMB_onehalf(b16buf);
642                                         glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, nbuf->x, nbuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nbuf->rect);
643                                         level++;
644                                         IMB_freeImBuf(b16buf);
645                                         b16buf = nbuf;
646                                 }
647                                 
648                                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
649                                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
650                                 
651                                 glBindTexture(GL_TEXTURE_2D, 0);
652                                 
653                                 if (glGetError() == GL_OUT_OF_MEMORY) {
654                                         glDeleteTextures(1, &icongltex.id);
655                                         icongltex.id = 0;
656                                 }
657                         }
658                 }
659         }
660
661         if (icongltex.id)
662                 icontype = ICON_TYPE_TEXTURE;
663         else
664                 icontype = ICON_TYPE_BUFFER;
665         
666         if (b32buf) {
667                 for (y = 0; y < ICON_GRID_ROWS; y++) {
668                         for (x = 0; x < ICON_GRID_COLS; x++) {
669                                 def_internal_icon(b32buf, BIFICONID_FIRST + y * ICON_GRID_COLS + x,
670                                                   x * (ICON_GRID_W + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
671                                                   y * (ICON_GRID_H + ICON_GRID_MARGIN) + ICON_GRID_MARGIN, ICON_GRID_W,
672                                                   icontype);
673                         }
674                 }
675         }
676
677         def_internal_vicon(VICO_VIEW3D_VEC, vicon_view3d_draw);
678         def_internal_vicon(VICO_EDIT_VEC, vicon_edit_draw);
679         def_internal_vicon(VICO_EDITMODE_VEC_DEHLT, vicon_editmode_dehlt_draw);
680         def_internal_vicon(VICO_EDITMODE_VEC_HLT, vicon_editmode_hlt_draw);
681         def_internal_vicon(VICO_DISCLOSURE_TRI_RIGHT_VEC, vicon_disclosure_tri_right_draw);
682         def_internal_vicon(VICO_DISCLOSURE_TRI_DOWN_VEC, vicon_disclosure_tri_down_draw);
683         def_internal_vicon(VICO_MOVE_UP_VEC, vicon_move_up_draw);
684         def_internal_vicon(VICO_MOVE_DOWN_VEC, vicon_move_down_draw);
685         def_internal_vicon(VICO_X_VEC, vicon_x_draw);
686         def_internal_vicon(VICO_SMALL_TRI_RIGHT_VEC, vicon_small_tri_right_draw);
687
688         IMB_freeImBuf(b16buf);
689         IMB_freeImBuf(b32buf);
690         
691 }
692 #endif  /* WITH_HEADLESS */
693
694 static void init_iconfile_list(struct ListBase *list)
695 {
696         IconFile *ifile;
697         struct direntry *dir;
698         int restoredir = 1; /* restore to current directory */
699         int totfile, i, index = 1;
700         const char *icondir;
701         char olddir[FILE_MAX];
702
703         list->first = list->last = NULL;
704         icondir = BLI_get_folder(BLENDER_DATAFILES, "icons");
705
706         if (icondir == NULL)
707                 return;
708         
709         /* since BLI_dir_contents changes the current working directory, restore it 
710          * back to old value afterwards */
711         if (!BLI_current_working_dir(olddir, sizeof(olddir))) 
712                 restoredir = 0;
713         totfile = BLI_dir_contents(icondir, &dir);
714         if (restoredir && !chdir(olddir)) {} /* fix warning about checking return value */
715
716         for (i = 0; i < totfile; i++) {
717                 if ((dir[i].type & S_IFREG)) {
718                         char *filename = dir[i].relname;
719                         
720                         if (BLI_testextensie(filename, ".png")) {
721                                 /* loading all icons on file start is overkill & slows startup
722                                  * its possible they change size after blender load anyway. */
723 #if 0
724                                 int ifilex, ifiley;
725                                 char iconfilestr[FILE_MAX + 16]; /* allow 256 chars for file+dir */
726                                 ImBuf *bbuf = NULL;
727                                 /* check to see if the image is the right size, continue if not */
728                                 /* copying strings here should go ok, assuming that we never get back
729                                  * a complete path to file longer than 256 chars */
730                                 BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, filename);
731                                 bbuf = IMB_loadiffname(iconfilestr, IB_rect);
732
733                                 if (bbuf) {
734                                         ifilex = bbuf->x;
735                                         ifiley = bbuf->y;
736                                         IMB_freeImBuf(bbuf);
737                                 }
738                                 else {
739                                         ifilex = ifiley = 0;
740                                 }
741                                 
742                                 /* bad size or failed to load */
743                                 if ((ifilex != ICON_IMAGE_W) || (ifiley != ICON_IMAGE_H)) {
744                                         printf("icon '%s' is wrong size %dx%d\n", iconfilestr, ifilex, ifiley);
745                                         continue;
746                                 }
747 #endif          /* removed */
748
749                                 /* found a potential icon file, so make an entry for it in the cache list */
750                                 ifile = MEM_callocN(sizeof(IconFile), "IconFile");
751                                 
752                                 BLI_strncpy(ifile->filename, filename, sizeof(ifile->filename));
753                                 ifile->index = index;
754
755                                 BLI_addtail(list, ifile);
756                                 
757                                 index++;
758                         }
759                 }
760         }
761         
762         /* free temporary direntry structure that's been created by BLI_dir_contents() */
763         i = totfile - 1;
764         
765         for (; i >= 0; i--) {
766                 MEM_freeN(dir[i].relname);
767                 MEM_freeN(dir[i].path);
768                 if (dir[i].string) {
769                         MEM_freeN(dir[i].string);
770                 }
771         }
772         free(dir);
773         dir = NULL;
774 }
775
776 static void free_iconfile_list(struct ListBase *list)
777 {
778         IconFile *ifile = NULL, *next_ifile = NULL;
779         
780         for (ifile = list->first; ifile; ifile = next_ifile) {
781                 next_ifile = ifile->next;
782                 BLI_freelinkN(list, ifile);
783         }
784 }
785
786 #endif  /* WITH_HEADLESS */
787
788 int UI_iconfile_get_index(const char *filename)
789 {
790         IconFile *ifile;
791         ListBase *list = &(iconfilelist);
792         
793         for (ifile = list->first; ifile; ifile = ifile->next) {
794                 if (BLI_path_cmp(filename, ifile->filename) == 0) {
795                         return ifile->index;
796                 }
797         }
798         
799         return 0;
800 }
801
802 ListBase *UI_iconfile_list(void)
803 {
804         ListBase *list = &(iconfilelist);
805         
806         return list;
807 }
808
809
810 void UI_icons_free(void)
811 {
812 #ifndef WITH_HEADLESS
813         if (icongltex.id) {
814                 glDeleteTextures(1, &icongltex.id);
815                 icongltex.id = 0;
816         }
817
818         free_iconfile_list(&iconfilelist);
819         BKE_icons_free();
820 #endif
821 }
822
823 void UI_icons_free_drawinfo(void *drawinfo)
824 {
825         DrawInfo *di = drawinfo;
826
827         if (di) {
828                 if (di->type == ICON_TYPE_BUFFER) {
829                         if (di->data.buffer.image) {
830                                 if (di->data.buffer.image->rect)
831                                         MEM_freeN(di->data.buffer.image->rect);
832                                 MEM_freeN(di->data.buffer.image);
833                         }
834                 }
835
836                 MEM_freeN(di);
837         }
838 }
839
840 static DrawInfo *icon_create_drawinfo(void)
841 {
842         DrawInfo *di = NULL;
843
844         di = MEM_callocN(sizeof(DrawInfo), "di_icon");
845         di->type = ICON_TYPE_PREVIEW;
846
847         return di;
848 }
849
850 /* note!, returns unscaled by DPI */
851 int UI_icon_get_width(int icon_id)
852 {
853         Icon *icon = NULL;
854         DrawInfo *di = NULL;
855
856         icon = BKE_icon_get(icon_id);
857         
858         if (icon == NULL) {
859                 if (G.debug & G_DEBUG)
860                         printf("%s: Internal error, no icon for icon ID: %d\n", __func__, icon_id);
861                 return 0;
862         }
863         
864         di = (DrawInfo *)icon->drawinfo;
865         if (!di) {
866                 di = icon_create_drawinfo();
867                 icon->drawinfo = di;
868         }
869
870         if (di)
871                 return ICON_DEFAULT_WIDTH;
872
873         return 0;
874 }
875
876 int UI_icon_get_height(int icon_id)
877 {
878         Icon *icon = NULL;
879         DrawInfo *di = NULL;
880
881         icon = BKE_icon_get(icon_id);
882         
883         if (icon == NULL) {
884                 if (G.debug & G_DEBUG)
885                         printf("%s: Internal error, no icon for icon ID: %d\n", __func__, icon_id);
886                 return 0;
887         }
888         
889         di = (DrawInfo *)icon->drawinfo;
890
891         if (!di) {
892                 di = icon_create_drawinfo();
893                 icon->drawinfo = di;
894         }
895         
896         if (di)
897                 return ICON_DEFAULT_HEIGHT;
898
899         return 0;
900 }
901
902 void UI_icons_init(int first_dyn_id)
903 {
904 #ifdef WITH_HEADLESS
905         (void)first_dyn_id;
906 #else
907         init_iconfile_list(&iconfilelist);
908         BKE_icons_init(first_dyn_id);
909         init_internal_icons();
910         init_brush_icons();
911         init_matcap_icons();
912 #endif
913 }
914
915 /* Render size for preview images and icons
916  */
917 static int preview_render_size(enum eIconSizes size)
918 {
919         switch (size) {
920                 case ICON_SIZE_ICON:    return 32;
921                 case ICON_SIZE_PREVIEW: return PREVIEW_DEFAULT_HEIGHT;
922         }
923         return 0;
924 }
925
926 /* Create rect for the icon
927  */
928 static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size)
929 {
930         unsigned int render_size = preview_render_size(size);
931
932         if (!prv_img) {
933                 if (G.debug & G_DEBUG)
934                         printf("%s, error: requested preview image does not exist", __func__);
935         }
936         else if (!prv_img->rect[size]) {
937                 prv_img->w[size] = render_size;
938                 prv_img->h[size] = render_size;
939                 prv_img->changed[size] = 1;
940                 prv_img->changed_timestamp[size] = 0;
941                 prv_img->rect[size] = MEM_callocN(render_size * render_size * sizeof(unsigned int), "prv_rect");
942         }
943 }
944
945 /* only called when icon has changed */
946 /* only call with valid pointer from UI_icon_draw */
947 static void icon_set_image(bContext *C, ID *id, PreviewImage *prv_img, enum eIconSizes size)
948 {
949         if (!prv_img) {
950                 if (G.debug & G_DEBUG)
951                         printf("%s: no preview image for this ID: %s\n", __func__, id->name);
952                 return;
953         }
954
955         icon_create_rect(prv_img, size);
956
957         ED_preview_icon_job(C, prv_img, id, prv_img->rect[size],
958                             prv_img->w[size], prv_img->h[size]);
959 }
960
961 PreviewImage *UI_icon_to_preview(int icon_id)
962 {
963         Icon *icon = BKE_icon_get(icon_id);
964         
965         if (icon) {
966                 DrawInfo *di = (DrawInfo *)icon->drawinfo;
967                 if (di && di->data.buffer.image) {
968                         ImBuf *bbuf;
969                         
970                         bbuf = IMB_ibImageFromMemory(di->data.buffer.image->datatoc_rect, di->data.buffer.image->datatoc_size, IB_rect, NULL, "<matcap buffer>");
971                         if (bbuf) {
972                                 PreviewImage *prv = BKE_previewimg_create();
973                                 
974                                 prv->rect[0] = bbuf->rect;
975
976                                 prv->w[0] = bbuf->x;
977                                 prv->h[0] = bbuf->y;
978                                 
979                                 bbuf->rect = NULL;
980                                 IMB_freeImBuf(bbuf);
981                                 
982                                 return prv;
983                         }
984                 }
985         }
986         return NULL;
987 }
988
989 static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), int rw, int rh,
990                            unsigned int *rect, float alpha, const float rgb[3], short is_preview)
991 {
992         ImBuf *ima = NULL;
993
994         /* sanity check */
995         if (w <= 0 || h <= 0 || w > 2000 || h > 2000) {
996                 printf("%s: icons are %i x %i pixels?\n", __func__, w, h);
997                 BLI_assert(!"invalid icon size");
998                 return;
999         }
1000
1001         /* modulate color */
1002         if (alpha != 1.0f)
1003                 glPixelTransferf(GL_ALPHA_SCALE, alpha);
1004
1005         if (rgb) {
1006                 glPixelTransferf(GL_RED_SCALE, rgb[0]);
1007                 glPixelTransferf(GL_GREEN_SCALE, rgb[1]);
1008                 glPixelTransferf(GL_BLUE_SCALE, rgb[2]);
1009         }
1010
1011         /* rect contains image in 'rendersize', we only scale if needed */
1012         if (rw != w && rh != h) {
1013                 /* first allocate imbuf for scaling and copy preview into it */
1014                 ima = IMB_allocImBuf(rw, rh, 32, IB_rect);
1015                 memcpy(ima->rect, rect, rw * rh * sizeof(unsigned int));
1016                 IMB_scaleImBuf(ima, w, h); /* scale it */
1017                 rect = ima->rect;
1018         }
1019
1020         /* draw */
1021         if (is_preview) {
1022                 glaDrawPixelsSafe(x, y, w, h, w, GL_RGBA, GL_UNSIGNED_BYTE, rect);
1023         }
1024         else {
1025                 glRasterPos2f(x, y);
1026                 glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, rect);
1027         }
1028
1029         if (ima)
1030                 IMB_freeImBuf(ima);
1031
1032         /* restore color */
1033         if (alpha != 0.0f)
1034                 glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
1035         
1036         if (rgb) {
1037                 glPixelTransferf(GL_RED_SCALE, 1.0f);
1038                 glPixelTransferf(GL_GREEN_SCALE, 1.0f);
1039                 glPixelTransferf(GL_BLUE_SCALE, 1.0f);
1040         }
1041 }
1042
1043 static void icon_draw_texture(float x, float y, float w, float h, int ix, int iy,
1044                               int UNUSED(iw), int ih, float alpha, const float rgb[3])
1045 {
1046         float x1, x2, y1, y2;
1047
1048         if (rgb) glColor4f(rgb[0], rgb[1], rgb[2], alpha);
1049         else     glColor4f(alpha, alpha, alpha, alpha);
1050
1051         x1 = ix * icongltex.invw;
1052         x2 = (ix + ih) * icongltex.invw;
1053         y1 = iy * icongltex.invh;
1054         y2 = (iy + ih) * icongltex.invh;
1055
1056         glEnable(GL_TEXTURE_2D);
1057         glBindTexture(GL_TEXTURE_2D, icongltex.id);
1058
1059         /* sharper downscaling, has no effect when scale matches with a mip level */
1060         glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, -0.5f);
1061
1062         glBegin(GL_QUADS);
1063         glTexCoord2f(x1, y1);
1064         glVertex2f(x, y);
1065
1066         glTexCoord2f(x2, y1);
1067         glVertex2f(x + w, y);
1068
1069         glTexCoord2f(x2, y2);
1070         glVertex2f(x + w, y + h);
1071
1072         glTexCoord2f(x1, y2);
1073         glVertex2f(x, y + h);
1074         glEnd();
1075
1076         glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, 0.0f);
1077
1078         glBindTexture(GL_TEXTURE_2D, 0);
1079         glDisable(GL_TEXTURE_2D);
1080 }
1081
1082 /* Drawing size for preview images */
1083 static int get_draw_size(enum eIconSizes size)
1084 {
1085         switch (size) {
1086                 case ICON_SIZE_ICON: return ICON_DEFAULT_HEIGHT;
1087                 case ICON_SIZE_PREVIEW: return PREVIEW_DEFAULT_HEIGHT;
1088         }
1089         return 0;
1090 }
1091
1092
1093
1094 static void icon_draw_size(float x, float y, int icon_id, float aspect, float alpha, const float rgb[3],
1095                            enum eIconSizes size, int draw_size, int UNUSED(nocreate), short is_preview)
1096 {
1097         bTheme *btheme = UI_GetTheme();
1098         Icon *icon = NULL;
1099         DrawInfo *di = NULL;
1100         IconImage *iimg;
1101         const float fdraw_size = (float)draw_size;
1102         int w, h;
1103         
1104         icon = BKE_icon_get(icon_id);
1105         alpha *= btheme->tui.icon_alpha;
1106         
1107         if (icon == NULL) {
1108                 if (G.debug & G_DEBUG)
1109                         printf("%s: Internal error, no icon for icon ID: %d\n", __func__, icon_id);
1110                 return;
1111         }
1112
1113         di = (DrawInfo *)icon->drawinfo;
1114         
1115         if (!di) {
1116                 di = icon_create_drawinfo();
1117         
1118                 icon->drawinfo = di;
1119                 icon->drawinfo_free = UI_icons_free_drawinfo;
1120         }
1121         
1122         /* scale width and height according to aspect */
1123         w = (int)(fdraw_size / aspect + 0.5f);
1124         h = (int)(fdraw_size / aspect + 0.5f);
1125         
1126         if (di->type == ICON_TYPE_VECTOR) {
1127                 /* vector icons use the uiBlock transformation, they are not drawn
1128                  * with untransformed coordinates like the other icons */
1129                 di->data.vector.func((int)x, (int)y, w, h, 1.0f);
1130         }
1131         else if (di->type == ICON_TYPE_TEXTURE) {
1132                 /* texture image use premul alpha for correct scaling */
1133                 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1134                 icon_draw_texture(x, y, (float)w, (float)h, di->data.texture.x, di->data.texture.y,
1135                                   di->data.texture.w, di->data.texture.h, alpha, rgb);
1136                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1137         }
1138         else if (di->type == ICON_TYPE_BUFFER) {
1139                 /* it is a builtin icon */
1140                 iimg = di->data.buffer.image;
1141 #ifndef WITH_HEADLESS
1142                 icon_verify_datatoc(iimg);
1143 #endif
1144                 if (!iimg->rect) return;  /* something has gone wrong! */
1145
1146                 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1147                 icon_draw_rect(x, y, w, h, aspect, iimg->w, iimg->h, iimg->rect, alpha, rgb, is_preview);
1148                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1149         }
1150         else if (di->type == ICON_TYPE_PREVIEW) {
1151                 PreviewImage *pi = BKE_previewimg_get((ID *)icon->obj);
1152
1153                 if (pi) {
1154                         /* no create icon on this level in code */
1155                         if (!pi->rect[size]) return;  /* something has gone wrong! */
1156                         
1157                         /* preview images use premul alpha ... */
1158                         glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1159                         icon_draw_rect(x, y, w, h, aspect, pi->w[size], pi->h[size], pi->rect[size], 1.0f, NULL, is_preview);
1160                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1161                 }
1162         }
1163 }
1164
1165 static void ui_id_preview_image_render_size(bContext *C, ID *id, PreviewImage *pi, int size)
1166 {
1167         if ((pi->changed[size] || !pi->rect[size])) { /* changed only ever set by dynamic icons */
1168                 /* create the rect if necessary */
1169                 icon_set_image(C, id, pi, size);
1170
1171                 pi->changed[size] = 0;
1172         }
1173 }
1174
1175 static void ui_id_icon_render(bContext *C, ID *id, int big)
1176 {
1177         PreviewImage *pi = BKE_previewimg_get(id);
1178
1179         if (pi) {
1180                 if (big)
1181                         ui_id_preview_image_render_size(C, id, pi, ICON_SIZE_PREVIEW);  /* bigger preview size */
1182                 else
1183                         ui_id_preview_image_render_size(C, id, pi, ICON_SIZE_ICON);     /* icon size */
1184         }
1185 }
1186
1187 static void ui_id_brush_render(bContext *C, ID *id)
1188 {
1189         PreviewImage *pi = BKE_previewimg_get(id); 
1190         enum eIconSizes i;
1191         
1192         if (!pi)
1193                 return;
1194         
1195         for (i = 0; i < NUM_ICON_SIZES; i++) {
1196                 /* check if rect needs to be created; changed
1197                  * only set by dynamic icons */
1198                 if ((pi->changed[i] || !pi->rect[i])) {
1199                         icon_set_image(C, id, pi, i);
1200                         pi->changed[i] = 0;
1201                 }
1202         }
1203 }
1204
1205
1206 static int ui_id_brush_get_icon(bContext *C, ID *id)
1207 {
1208         Brush *br = (Brush *)id;
1209
1210         if (br->flag & BRUSH_CUSTOM_ICON) {
1211                 BKE_icon_getid(id);
1212                 ui_id_brush_render(C, id);
1213         }
1214         else {
1215                 Object *ob = CTX_data_active_object(C);
1216                 SpaceImage *sima;
1217                 EnumPropertyItem *items = NULL;
1218                 int tool, mode = 0;
1219
1220                 /* XXX: this is not nice, should probably make brushes
1221                  * be strictly in one paint mode only to avoid
1222                  * checking various context stuff here */
1223
1224                 if (CTX_wm_view3d(C) && ob) {
1225                         if (ob->mode & OB_MODE_SCULPT)
1226                                 mode = OB_MODE_SCULPT;
1227                         else if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT))
1228                                 mode = OB_MODE_VERTEX_PAINT;
1229                         else if (ob->mode & OB_MODE_TEXTURE_PAINT)
1230                                 mode = OB_MODE_TEXTURE_PAINT;
1231                 }
1232                 else if ((sima = CTX_wm_space_image(C)) &&
1233                          (sima->mode == SI_MODE_PAINT))
1234                 {
1235                         mode = OB_MODE_TEXTURE_PAINT;
1236                 }
1237
1238                 /* reset the icon */
1239                 if (mode == OB_MODE_SCULPT) {
1240                         items = brush_sculpt_tool_items;
1241                         tool = br->sculpt_tool;
1242                 }
1243                 else if (mode == OB_MODE_VERTEX_PAINT) {
1244                         items = brush_vertex_tool_items;
1245                         tool = br->vertexpaint_tool;
1246                 }
1247                 else if (mode == OB_MODE_TEXTURE_PAINT) {
1248                         items = brush_image_tool_items;
1249                         tool = br->imagepaint_tool;
1250                 }
1251
1252                 if (!items || !RNA_enum_icon_from_value(items, tool, &id->icon_id))
1253                         id->icon_id = 0;
1254         }
1255
1256         return id->icon_id;
1257 }
1258
1259 int ui_id_icon_get(bContext *C, ID *id, int big)
1260 {
1261         int iconid = 0;
1262         
1263         /* icon */
1264         switch (GS(id->name)) {
1265                 case ID_BR:
1266                         iconid = ui_id_brush_get_icon(C, id);
1267                         break;
1268                 case ID_MA: /* fall through */
1269                 case ID_TE: /* fall through */
1270                 case ID_IM: /* fall through */
1271                 case ID_WO: /* fall through */
1272                 case ID_LA: /* fall through */
1273                         iconid = BKE_icon_getid(id);
1274                         /* checks if not exists, or changed */
1275                         ui_id_icon_render(C, id, big);
1276                         break;
1277                 default:
1278                         break;
1279         }
1280
1281         return iconid;
1282 }
1283
1284 int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, int big)
1285 {
1286         ID *id = NULL;
1287
1288         if (!ptr->data)
1289                 return rnaicon;
1290
1291         /* try ID, material, texture or dynapaint slot */
1292         if (RNA_struct_is_ID(ptr->type)) {
1293                 id = ptr->id.data;
1294         }
1295         else if (RNA_struct_is_a(ptr->type, &RNA_MaterialSlot)) {
1296                 id = RNA_pointer_get(ptr, "material").data;
1297         }
1298         else if (RNA_struct_is_a(ptr->type, &RNA_TextureSlot)) {
1299                 id = RNA_pointer_get(ptr, "texture").data;
1300         }
1301         else if (RNA_struct_is_a(ptr->type, &RNA_DynamicPaintSurface)) {
1302                 DynamicPaintSurface *surface = (DynamicPaintSurface *)ptr->data;
1303
1304                 if (surface->format == MOD_DPAINT_SURFACE_F_PTEX)
1305                         return ICON_TEXTURE_SHADED;
1306                 else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX)
1307                         return ICON_OUTLINER_DATA_MESH;
1308                 else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ)
1309                         return ICON_FILE_IMAGE;
1310         }
1311
1312         /* get icon from ID */
1313         if (id) {
1314                 int icon = ui_id_icon_get(C, id, big);
1315
1316                 return icon ? icon : rnaicon;
1317         }
1318
1319         return rnaicon;
1320 }
1321
1322 static void icon_draw_at_size(float x, float y, int icon_id, float aspect, float alpha, enum eIconSizes size, int nocreate)
1323 {
1324         int draw_size = get_draw_size(size);
1325         icon_draw_size(x, y, icon_id, aspect, alpha, NULL, size, draw_size, nocreate, FALSE);
1326 }
1327
1328 void UI_icon_draw_aspect(float x, float y, int icon_id, float aspect, float alpha)
1329 {
1330         icon_draw_at_size(x, y, icon_id, aspect, alpha, ICON_SIZE_ICON, 0);
1331 }
1332
1333 void UI_icon_draw_aspect_color(float x, float y, int icon_id, float aspect, const float rgb[3])
1334 {
1335         int draw_size = get_draw_size(ICON_SIZE_ICON);
1336         icon_draw_size(x, y, icon_id, aspect, 1.0f, rgb, ICON_SIZE_ICON, draw_size, FALSE, FALSE);
1337 }
1338
1339 /* draws icon with dpi scale factor */
1340 void UI_icon_draw(float x, float y, int icon_id)
1341 {
1342         UI_icon_draw_aspect(x, y, icon_id, 1.0f / UI_DPI_FAC, 1.0f);
1343 }
1344
1345 void UI_icon_draw_size(float x, float y, int size, int icon_id, float alpha)
1346 {
1347         icon_draw_size(x, y, icon_id, 1.0f, alpha, NULL, ICON_SIZE_ICON, size, TRUE, FALSE);
1348 }
1349
1350 void UI_icon_draw_preview(float x, float y, int icon_id)
1351 {
1352         icon_draw_at_size(x, y, icon_id, 1.0f, 1.0f, ICON_SIZE_PREVIEW, 0);
1353 }
1354
1355 void UI_icon_draw_preview_aspect(float x, float y, int icon_id, float aspect)
1356 {
1357         icon_draw_at_size(x, y, icon_id, aspect, 1.0f, ICON_SIZE_PREVIEW, 0);
1358 }
1359
1360 void UI_icon_draw_preview_aspect_size(float x, float y, int icon_id, float aspect, int size)
1361 {
1362         icon_draw_size(x, y, icon_id, aspect, 1.0f, NULL, ICON_SIZE_PREVIEW, size, FALSE, TRUE);
1363 }
1364