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