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