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