rev |
line source |
nuclear@1
|
1 #include <stdio.h>
|
nuclear@1
|
2 #include <stdlib.h>
|
nuclear@1
|
3 #include <string.h>
|
nuclear@1
|
4 #include <errno.h>
|
nuclear@11
|
5 #include <assert.h>
|
nuclear@1
|
6 #include <dirent.h>
|
nuclear@1
|
7 #include <imago2.h>
|
nuclear@1
|
8 #include "opengl.h"
|
nuclear@1
|
9 #include "thumbs.h"
|
nuclear@11
|
10 #include "resman.h"
|
nuclear@1
|
11
|
nuclear@6
|
12 #ifndef GL_COMPRESSED_RGB
|
nuclear@6
|
13 #define GL_COMPRESSED_RGB 0x84ed
|
nuclear@6
|
14 #endif
|
nuclear@6
|
15
|
nuclear@11
|
16 struct resman *texman;
|
nuclear@11
|
17
|
nuclear@11
|
18 static int load_res_texture(const char *fname, int id, void *cls);
|
nuclear@11
|
19 static int done_res_texture(int id, void *cls);
|
nuclear@11
|
20 static void free_res_texture(int id, void *cls);
|
nuclear@11
|
21
|
nuclear@11
|
22
|
nuclear@1
|
23 struct thumbnail *create_thumbs(const char *dirpath)
|
nuclear@1
|
24 {
|
nuclear@1
|
25 DIR *dir;
|
nuclear@1
|
26 struct dirent *dent;
|
nuclear@1
|
27 struct thumbnail *list = 0;
|
nuclear@1
|
28
|
nuclear@11
|
29 /*unsigned int intfmt = GL_COMPRESSED_RGB;
|
nuclear@11
|
30 if(!strstr((char*)glGetString(GL_EXTENSIONS), "GL_ARB_texture_compression")) {
|
nuclear@2
|
31 printf("warning, no texture compression available.\n");
|
nuclear@2
|
32 intfmt = GL_RGB;
|
nuclear@11
|
33 }*/
|
nuclear@11
|
34
|
nuclear@11
|
35 if(!texman) {
|
nuclear@11
|
36 texman = resman_create();
|
nuclear@11
|
37 resman_set_load_func(texman, load_res_texture, 0);
|
nuclear@11
|
38 resman_set_done_func(texman, done_res_texture, 0);
|
nuclear@11
|
39 resman_set_destroy_func(texman, free_res_texture, 0);
|
nuclear@2
|
40 }
|
nuclear@2
|
41
|
nuclear@1
|
42 if(!(dir = opendir(dirpath))) {
|
nuclear@1
|
43 fprintf(stderr, "failed to open directory: %s: %s\n", dirpath, strerror(errno));
|
nuclear@1
|
44 return 0;
|
nuclear@1
|
45 }
|
nuclear@1
|
46
|
nuclear@1
|
47 while((dent = readdir(dir))) {
|
nuclear@11
|
48 /*int xsz, ysz;
|
nuclear@11
|
49 unsigned char *pixels;*/
|
nuclear@1
|
50 struct thumbnail *node;
|
nuclear@1
|
51
|
nuclear@1
|
52 if(!(node = malloc(sizeof *node))) {
|
nuclear@1
|
53 perror("failed to allocate thumbnail list node");
|
nuclear@1
|
54 continue;
|
nuclear@1
|
55 }
|
nuclear@11
|
56 memset(node, 0, sizeof *node);
|
nuclear@1
|
57
|
nuclear@1
|
58 if(!(node->fname = malloc(strlen(dirpath) + strlen(dent->d_name) + 2))) {
|
nuclear@1
|
59 free(node);
|
nuclear@1
|
60 continue;
|
nuclear@1
|
61 }
|
nuclear@1
|
62 strcpy(node->fname, dirpath);
|
nuclear@1
|
63 if(dirpath[strlen(dirpath) - 1] != '/') {
|
nuclear@1
|
64 strcat(node->fname, "/");
|
nuclear@1
|
65 }
|
nuclear@1
|
66 strcat(node->fname, dent->d_name);
|
nuclear@1
|
67
|
nuclear@11
|
68 node->aspect = 1.0;/*(float)xsz / (float)ysz;*/
|
nuclear@11
|
69
|
nuclear@12
|
70 resman_lookup(texman, node->fname, node);
|
nuclear@11
|
71
|
nuclear@11
|
72 /*if(!(pixels = img_load_pixels(node->fname, &xsz, &ysz, IMG_FMT_RGBA32))) {
|
nuclear@1
|
73 free(node->fname);
|
nuclear@1
|
74 free(node);
|
nuclear@1
|
75 continue;
|
nuclear@1
|
76 }
|
nuclear@1
|
77
|
nuclear@1
|
78 printf("loaded image: %s\n", node->fname);
|
nuclear@1
|
79
|
nuclear@1
|
80 glGenTextures(1, &node->tex);
|
nuclear@1
|
81 glBindTexture(GL_TEXTURE_2D, node->tex);
|
nuclear@1
|
82 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
nuclear@1
|
83 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
nuclear@2
|
84 glTexImage2D(GL_TEXTURE_2D, 0, intfmt, xsz, ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
nuclear@1
|
85 img_free_pixels(pixels);
|
nuclear@11
|
86 */
|
nuclear@1
|
87
|
nuclear@1
|
88 node->next = list;
|
nuclear@1
|
89 list = node;
|
nuclear@1
|
90 }
|
nuclear@1
|
91 closedir(dir);
|
nuclear@1
|
92
|
nuclear@1
|
93 return list;
|
nuclear@1
|
94 }
|
nuclear@1
|
95
|
nuclear@1
|
96 void free_thumbs(struct thumbnail *thumbs)
|
nuclear@1
|
97 {
|
nuclear@1
|
98 if(!thumbs) return;
|
nuclear@1
|
99
|
nuclear@1
|
100 while(thumbs) {
|
nuclear@1
|
101 struct thumbnail *tmp = thumbs;
|
nuclear@1
|
102 thumbs = thumbs->next;
|
nuclear@1
|
103
|
nuclear@1
|
104 free(tmp->fname);
|
nuclear@1
|
105 free(tmp);
|
nuclear@1
|
106 }
|
nuclear@1
|
107 }
|
nuclear@1
|
108
|
nuclear@1
|
109
|
nuclear@11
|
110 void update_thumbs(void)
|
nuclear@11
|
111 {
|
nuclear@11
|
112 resman_poll(texman);
|
nuclear@11
|
113 }
|
nuclear@11
|
114
|
nuclear@1
|
115 void draw_thumbs(struct thumbnail *thumbs, float thumb_sz, float start_y)
|
nuclear@1
|
116 {
|
nuclear@1
|
117 int vp[4];
|
nuclear@1
|
118 float gap = thumb_sz / 4.0;
|
nuclear@1
|
119 float x = gap;
|
nuclear@1
|
120 float y = gap + start_y;
|
nuclear@1
|
121 float view_aspect;
|
nuclear@1
|
122
|
nuclear@1
|
123 glGetIntegerv(GL_VIEWPORT, vp);
|
nuclear@1
|
124 view_aspect = (float)(vp[2] - vp[0]) / (vp[3] - vp[1]);
|
nuclear@1
|
125
|
nuclear@1
|
126 glMatrixMode(GL_PROJECTION);
|
nuclear@1
|
127 glPushMatrix();
|
nuclear@1
|
128 glLoadIdentity();
|
nuclear@1
|
129 glOrtho(0, 1, 1.0 / view_aspect, 0, -1, 1);
|
nuclear@1
|
130
|
nuclear@1
|
131 glMatrixMode(GL_MODELVIEW);
|
nuclear@1
|
132
|
nuclear@1
|
133 while(thumbs) {
|
nuclear@1
|
134 glPushMatrix();
|
nuclear@1
|
135 glTranslatef(x, y, 0);
|
nuclear@1
|
136
|
nuclear@1
|
137 glScalef(thumb_sz, thumb_sz, 1);
|
nuclear@1
|
138
|
nuclear@1
|
139 glBegin(GL_QUADS);
|
nuclear@1
|
140 glColor3f(0.25, 0.25, 0.25);
|
nuclear@1
|
141 glTexCoord2f(0, 0); glVertex2f(0, 0);
|
nuclear@1
|
142 glTexCoord2f(1, 0); glVertex2f(1, 0);
|
nuclear@1
|
143 glTexCoord2f(1, 1); glVertex2f(1, 1);
|
nuclear@1
|
144 glTexCoord2f(0, 1); glVertex2f(0, 1);
|
nuclear@1
|
145 glEnd();
|
nuclear@1
|
146
|
nuclear@12
|
147 if(thumbs->tex) {
|
nuclear@12
|
148 if(thumbs->aspect >= 1.0) {
|
nuclear@12
|
149 glTranslatef(0, 0.5 - 0.5 / thumbs->aspect, 0);
|
nuclear@12
|
150 glScalef(1, 1.0 / thumbs->aspect, 1);
|
nuclear@12
|
151 } else {
|
nuclear@12
|
152 glTranslatef(0.5 - thumbs->aspect / 2.0, 0, 0);
|
nuclear@12
|
153 glScalef(thumbs->aspect, 1, 1);
|
nuclear@12
|
154 }
|
nuclear@12
|
155
|
nuclear@12
|
156 if(glIsTexture(thumbs->tex)) {
|
nuclear@12
|
157 glEnable(GL_TEXTURE_2D);
|
nuclear@12
|
158 glBindTexture(GL_TEXTURE_2D, thumbs->tex);
|
nuclear@12
|
159
|
nuclear@12
|
160 glBegin(GL_QUADS);
|
nuclear@12
|
161 glColor3f(1, 1, 1);
|
nuclear@12
|
162 glTexCoord2f(0, 0); glVertex2f(0, 0);
|
nuclear@12
|
163 glTexCoord2f(1, 0); glVertex2f(1, 0);
|
nuclear@12
|
164 glTexCoord2f(1, 1); glVertex2f(1, 1);
|
nuclear@12
|
165 glTexCoord2f(0, 1); glVertex2f(0, 1);
|
nuclear@12
|
166 glEnd();
|
nuclear@12
|
167 } else {
|
nuclear@12
|
168 fprintf(stderr, "invalid texture: %u\n", thumbs->tex);
|
nuclear@12
|
169 }
|
nuclear@12
|
170
|
nuclear@12
|
171 glPopMatrix();
|
nuclear@12
|
172 glDisable(GL_TEXTURE_2D);
|
nuclear@1
|
173 }
|
nuclear@1
|
174
|
nuclear@1
|
175 thumbs->layout_pos[0] = x;
|
nuclear@1
|
176 thumbs->layout_pos[1] = y;
|
nuclear@1
|
177 thumbs->layout_size[0] = thumb_sz;
|
nuclear@1
|
178 thumbs->layout_size[1] = thumb_sz;
|
nuclear@1
|
179
|
nuclear@1
|
180 x += thumb_sz + gap;
|
nuclear@1
|
181 if(x >= 1.0 - thumb_sz) {
|
nuclear@1
|
182 x = gap;
|
nuclear@1
|
183 y += thumb_sz + gap;
|
nuclear@1
|
184 }
|
nuclear@1
|
185
|
nuclear@1
|
186 thumbs = thumbs->next;
|
nuclear@1
|
187 }
|
nuclear@1
|
188
|
nuclear@1
|
189 glMatrixMode(GL_PROJECTION);
|
nuclear@1
|
190 glPopMatrix();
|
nuclear@1
|
191 glMatrixMode(GL_MODELVIEW);
|
nuclear@1
|
192 }
|
nuclear@11
|
193
|
nuclear@11
|
194 static int load_res_texture(const char *fname, int id, void *cls)
|
nuclear@11
|
195 {
|
nuclear@12
|
196 struct thumbnail *rdata = resman_get_res_data(texman, id);
|
nuclear@11
|
197
|
nuclear@11
|
198 assert(rdata);
|
nuclear@11
|
199 if(!rdata->img) {
|
nuclear@11
|
200 if(!(rdata->img = img_create())) {
|
nuclear@11
|
201 return -1;
|
nuclear@11
|
202 }
|
nuclear@11
|
203 }
|
nuclear@11
|
204
|
nuclear@12
|
205 if(img_load(rdata->img, fname) == -1) {
|
nuclear@11
|
206 img_free(rdata->img);
|
nuclear@11
|
207 return -1;
|
nuclear@11
|
208 }
|
nuclear@11
|
209 rdata->aspect = (float)rdata->img->width / (float)rdata->img->height;
|
nuclear@11
|
210
|
nuclear@11
|
211 /* set the resource's data to the loaded image, so that we can use
|
nuclear@11
|
212 * it in the done callback */
|
nuclear@12
|
213 resman_set_res_data(texman, id, rdata);
|
nuclear@11
|
214 return 0;
|
nuclear@11
|
215 }
|
nuclear@11
|
216
|
nuclear@11
|
217 static int done_res_texture(int id, void *cls)
|
nuclear@11
|
218 {
|
nuclear@11
|
219 struct thumbnail *rdata;
|
nuclear@11
|
220
|
nuclear@12
|
221 rdata = resman_get_res_data(texman, id);
|
nuclear@11
|
222
|
nuclear@12
|
223 if(resman_get_res_result(texman, id) != 0 || !rdata) {
|
nuclear@12
|
224 fprintf(stderr, "failed to load resource %d (%s)\n", id, resman_get_res_name(texman, id));
|
nuclear@11
|
225 } else {
|
nuclear@12
|
226 printf("done loading resource %d (%s)\n", id, resman_get_res_name(texman, id));
|
nuclear@11
|
227 }
|
nuclear@11
|
228
|
nuclear@11
|
229 if(!rdata->tex) {
|
nuclear@11
|
230 glGenTextures(1, &rdata->tex);
|
nuclear@11
|
231 }
|
nuclear@11
|
232 glBindTexture(GL_TEXTURE_2D, rdata->tex);
|
nuclear@11
|
233 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
nuclear@11
|
234 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
nuclear@11
|
235 glTexImage2D(GL_TEXTURE_2D, 0, img_glintfmt(rdata->img),
|
nuclear@11
|
236 rdata->img->width, rdata->img->height, 0, img_glfmt(rdata->img),
|
nuclear@11
|
237 img_gltype(rdata->img), rdata->img->pixels);
|
nuclear@11
|
238 return 0;
|
nuclear@11
|
239 }
|
nuclear@11
|
240
|
nuclear@11
|
241 static void free_res_texture(int id, void *cls)
|
nuclear@11
|
242 {
|
nuclear@12
|
243 struct thumbnail *rdata = resman_get_res_data(texman, id);
|
nuclear@11
|
244
|
nuclear@11
|
245 if(rdata) {
|
nuclear@11
|
246 if(rdata->tex) {
|
nuclear@11
|
247 glDeleteTextures(1, &rdata->tex);
|
nuclear@11
|
248 }
|
nuclear@11
|
249 if(rdata->img) {
|
nuclear@11
|
250 img_free(rdata->img);
|
nuclear@11
|
251 }
|
nuclear@11
|
252 }
|
nuclear@11
|
253 }
|