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