nuclear@1: #include nuclear@1: #include nuclear@1: #include nuclear@1: #include nuclear@11: #include nuclear@1: #include nuclear@1: #include nuclear@1: #include "opengl.h" nuclear@1: #include "thumbs.h" nuclear@11: #include "resman.h" nuclear@1: nuclear@6: #ifndef GL_COMPRESSED_RGB nuclear@6: #define GL_COMPRESSED_RGB 0x84ed nuclear@6: #endif nuclear@6: nuclear@11: struct resman *texman; nuclear@11: nuclear@11: static int load_res_texture(const char *fname, int id, void *cls); nuclear@11: static int done_res_texture(int id, void *cls); nuclear@11: static void free_res_texture(int id, void *cls); nuclear@11: nuclear@11: nuclear@1: struct thumbnail *create_thumbs(const char *dirpath) nuclear@1: { nuclear@1: DIR *dir; nuclear@1: struct dirent *dent; nuclear@1: struct thumbnail *list = 0; nuclear@1: nuclear@11: /*unsigned int intfmt = GL_COMPRESSED_RGB; nuclear@11: if(!strstr((char*)glGetString(GL_EXTENSIONS), "GL_ARB_texture_compression")) { nuclear@2: printf("warning, no texture compression available.\n"); nuclear@2: intfmt = GL_RGB; nuclear@11: }*/ nuclear@11: nuclear@11: if(!texman) { nuclear@11: texman = resman_create(); nuclear@11: resman_set_load_func(texman, load_res_texture, 0); nuclear@11: resman_set_done_func(texman, done_res_texture, 0); nuclear@11: resman_set_destroy_func(texman, free_res_texture, 0); nuclear@2: } nuclear@2: nuclear@1: if(!(dir = opendir(dirpath))) { nuclear@1: fprintf(stderr, "failed to open directory: %s: %s\n", dirpath, strerror(errno)); nuclear@1: return 0; nuclear@1: } nuclear@1: nuclear@1: while((dent = readdir(dir))) { nuclear@11: /*int xsz, ysz; nuclear@11: unsigned char *pixels;*/ nuclear@1: struct thumbnail *node; nuclear@1: nuclear@1: if(!(node = malloc(sizeof *node))) { nuclear@1: perror("failed to allocate thumbnail list node"); nuclear@1: continue; nuclear@1: } nuclear@11: memset(node, 0, sizeof *node); nuclear@1: nuclear@1: if(!(node->fname = malloc(strlen(dirpath) + strlen(dent->d_name) + 2))) { nuclear@1: free(node); nuclear@1: continue; nuclear@1: } nuclear@1: strcpy(node->fname, dirpath); nuclear@1: if(dirpath[strlen(dirpath) - 1] != '/') { nuclear@1: strcat(node->fname, "/"); nuclear@1: } nuclear@1: strcat(node->fname, dent->d_name); nuclear@1: nuclear@11: node->aspect = 1.0;/*(float)xsz / (float)ysz;*/ nuclear@11: nuclear@11: resman_lookup(texman, node->fname, 0); nuclear@11: nuclear@11: /*if(!(pixels = img_load_pixels(node->fname, &xsz, &ysz, IMG_FMT_RGBA32))) { nuclear@1: free(node->fname); nuclear@1: free(node); nuclear@1: continue; nuclear@1: } nuclear@1: nuclear@1: printf("loaded image: %s\n", node->fname); nuclear@1: nuclear@1: glGenTextures(1, &node->tex); nuclear@1: glBindTexture(GL_TEXTURE_2D, node->tex); nuclear@1: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); nuclear@1: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); nuclear@2: glTexImage2D(GL_TEXTURE_2D, 0, intfmt, xsz, ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); nuclear@1: img_free_pixels(pixels); nuclear@11: */ nuclear@1: nuclear@1: node->next = list; nuclear@1: list = node; nuclear@1: } nuclear@1: closedir(dir); nuclear@1: nuclear@1: return list; nuclear@1: } nuclear@1: nuclear@1: void free_thumbs(struct thumbnail *thumbs) nuclear@1: { nuclear@1: if(!thumbs) return; nuclear@1: nuclear@1: while(thumbs) { nuclear@1: struct thumbnail *tmp = thumbs; nuclear@1: thumbs = thumbs->next; nuclear@1: nuclear@1: free(tmp->fname); nuclear@1: free(tmp); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: nuclear@11: void update_thumbs(void) nuclear@11: { nuclear@11: resman_poll(texman); nuclear@11: } nuclear@11: nuclear@1: void draw_thumbs(struct thumbnail *thumbs, float thumb_sz, float start_y) nuclear@1: { nuclear@1: int vp[4]; nuclear@1: float gap = thumb_sz / 4.0; nuclear@1: float x = gap; nuclear@1: float y = gap + start_y; nuclear@1: float view_aspect; nuclear@1: nuclear@1: glGetIntegerv(GL_VIEWPORT, vp); nuclear@1: view_aspect = (float)(vp[2] - vp[0]) / (vp[3] - vp[1]); nuclear@1: nuclear@1: glMatrixMode(GL_PROJECTION); nuclear@1: glPushMatrix(); nuclear@1: glLoadIdentity(); nuclear@1: glOrtho(0, 1, 1.0 / view_aspect, 0, -1, 1); nuclear@1: nuclear@1: glMatrixMode(GL_MODELVIEW); nuclear@1: nuclear@1: while(thumbs) { nuclear@11: if(!thumbs->tex) { nuclear@11: thumbs = thumbs->next; nuclear@11: continue; nuclear@11: } nuclear@1: nuclear@1: glPushMatrix(); nuclear@1: glTranslatef(x, y, 0); nuclear@1: nuclear@1: glScalef(thumb_sz, thumb_sz, 1); nuclear@1: nuclear@1: glBegin(GL_QUADS); nuclear@1: glColor3f(0.25, 0.25, 0.25); nuclear@1: glTexCoord2f(0, 0); glVertex2f(0, 0); nuclear@1: glTexCoord2f(1, 0); glVertex2f(1, 0); nuclear@1: glTexCoord2f(1, 1); glVertex2f(1, 1); nuclear@1: glTexCoord2f(0, 1); glVertex2f(0, 1); nuclear@1: glEnd(); nuclear@1: nuclear@1: if(thumbs->aspect >= 1.0) { nuclear@1: glTranslatef(0, 0.5 - 0.5 / thumbs->aspect, 0); nuclear@1: glScalef(1, 1.0 / thumbs->aspect, 1); nuclear@1: } else { nuclear@1: glTranslatef(0.5 - thumbs->aspect / 2.0, 0, 0); nuclear@1: glScalef(thumbs->aspect, 1, 1); nuclear@1: } nuclear@1: nuclear@1: glEnable(GL_TEXTURE_2D); nuclear@1: glBindTexture(GL_TEXTURE_2D, thumbs->tex); nuclear@1: nuclear@1: glBegin(GL_QUADS); nuclear@1: glColor3f(1, 1, 1); nuclear@1: glTexCoord2f(0, 0); glVertex2f(0, 0); nuclear@1: glTexCoord2f(1, 0); glVertex2f(1, 0); nuclear@1: glTexCoord2f(1, 1); glVertex2f(1, 1); nuclear@1: glTexCoord2f(0, 1); glVertex2f(0, 1); nuclear@1: glEnd(); nuclear@1: nuclear@1: glPopMatrix(); nuclear@1: glDisable(GL_TEXTURE_2D); nuclear@1: nuclear@1: thumbs->layout_pos[0] = x; nuclear@1: thumbs->layout_pos[1] = y; nuclear@1: thumbs->layout_size[0] = thumb_sz; nuclear@1: thumbs->layout_size[1] = thumb_sz; nuclear@1: nuclear@1: x += thumb_sz + gap; nuclear@1: if(x >= 1.0 - thumb_sz) { nuclear@1: x = gap; nuclear@1: y += thumb_sz + gap; nuclear@1: } nuclear@1: nuclear@1: thumbs = thumbs->next; nuclear@1: } nuclear@1: nuclear@1: glMatrixMode(GL_PROJECTION); nuclear@1: glPopMatrix(); nuclear@1: glMatrixMode(GL_MODELVIEW); nuclear@1: } nuclear@11: nuclear@11: static int load_res_texture(const char *fname, int id, void *cls) nuclear@11: { nuclear@11: struct resman *rman = cls; nuclear@11: struct thumbnail *rdata = resman_get_res_data(rman, id); nuclear@11: nuclear@11: assert(rdata); nuclear@11: if(!rdata->img) { nuclear@11: if(!(rdata->img = img_create())) { nuclear@11: return -1; nuclear@11: } nuclear@11: } nuclear@11: nuclear@11: if(!img_load(rdata->img, fname) == -1) { nuclear@11: img_free(rdata->img); nuclear@11: return -1; nuclear@11: } nuclear@11: rdata->aspect = (float)rdata->img->width / (float)rdata->img->height; nuclear@11: nuclear@11: /* set the resource's data to the loaded image, so that we can use nuclear@11: * it in the done callback */ nuclear@11: resman_set_res_data(rman, id, rdata); nuclear@11: return 0; nuclear@11: } nuclear@11: nuclear@11: static int done_res_texture(int id, void *cls) nuclear@11: { nuclear@11: struct thumbnail *rdata; nuclear@11: struct resman *rman = cls; nuclear@11: nuclear@11: rdata = resman_get_res_data(rman, id); nuclear@11: nuclear@11: if(resman_get_res_result(rman, id) != 0 || !rdata) { nuclear@11: fprintf(stderr, "failed to load resource %d (%s)\n", id, resman_get_res_name(rman, id)); nuclear@11: } else { nuclear@11: printf("done loading resource %d (%s)\n", id, resman_get_res_name(rman, id)); nuclear@11: } nuclear@11: nuclear@11: if(!rdata->tex) { nuclear@11: glGenTextures(1, &rdata->tex); nuclear@11: } nuclear@11: glBindTexture(GL_TEXTURE_2D, rdata->tex); nuclear@11: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); nuclear@11: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); nuclear@11: glTexImage2D(GL_TEXTURE_2D, 0, img_glintfmt(rdata->img), nuclear@11: rdata->img->width, rdata->img->height, 0, img_glfmt(rdata->img), nuclear@11: img_gltype(rdata->img), rdata->img->pixels); nuclear@11: return 0; nuclear@11: } nuclear@11: nuclear@11: static void free_res_texture(int id, void *cls) nuclear@11: { nuclear@11: struct resman *rman = cls; nuclear@11: struct thumbnail *rdata = resman_get_res_data(rman, id); nuclear@11: nuclear@11: if(rdata) { nuclear@11: if(rdata->tex) { nuclear@11: glDeleteTextures(1, &rdata->tex); nuclear@11: } nuclear@11: if(rdata->img) { nuclear@11: img_free(rdata->img); nuclear@11: } nuclear@11: } nuclear@11: }