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