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