nuclear@1: #include nuclear@1: #include nuclear@1: #include nuclear@11: #include nuclear@1: #include "opengl.h" nuclear@1: #include "resman.h" nuclear@1: #include "thumbs.h" nuclear@1: nuclear@1: static int init(void); nuclear@1: static void cleanup(void); nuclear@1: static void display(void); nuclear@16: static void idle(void); nuclear@1: static void reshape(int x, int y); nuclear@1: static void keyb(unsigned char key, int x, int y); nuclear@1: static void mouse(int bn, int st, int x, int y); nuclear@1: static void motion(int x, int y); nuclear@2: static void sball_motion(int x, int y, int z); nuclear@1: static struct thumbnail *find_thumb(int x, int y); nuclear@1: nuclear@1: const char *path = "."; nuclear@1: int win_width, win_height; nuclear@1: float win_aspect; nuclear@1: float pan_x, pan_y; nuclear@1: float show_pan_x, show_pan_y; nuclear@1: float show_zoom = 1.0; nuclear@1: float thumbs_size = 0.25; nuclear@1: nuclear@1: struct thumbnail *thumbs, *show_thumb; nuclear@1: nuclear@1: int main(int argc, char **argv) nuclear@1: { nuclear@4: glutInitWindowSize(1024, 768); nuclear@1: glutInit(&argc, argv); nuclear@1: nuclear@1: if(argv[1]) { nuclear@1: path = argv[1]; nuclear@1: } nuclear@1: nuclear@1: glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); nuclear@1: glutCreateWindow("imgthumbs"); nuclear@1: nuclear@1: glutDisplayFunc(display); nuclear@16: glutIdleFunc(idle); nuclear@1: glutReshapeFunc(reshape); nuclear@1: glutKeyboardFunc(keyb); nuclear@1: glutMouseFunc(mouse); nuclear@1: glutMotionFunc(motion); nuclear@2: glutSpaceballMotionFunc(sball_motion); nuclear@1: nuclear@1: if(init() == -1) { nuclear@1: return 1; nuclear@1: } nuclear@1: atexit(cleanup); nuclear@1: nuclear@1: glutMainLoop(); nuclear@1: return 0; nuclear@1: } nuclear@1: nuclear@1: static int init(void) nuclear@1: { nuclear@1: thumbs = create_thumbs(path); nuclear@1: return 0; nuclear@1: } nuclear@1: nuclear@1: static void cleanup(void) nuclear@1: { nuclear@1: free_thumbs(thumbs); nuclear@1: } nuclear@1: nuclear@1: static void display(void) nuclear@1: { nuclear@11: update_thumbs(); nuclear@11: nuclear@1: glClear(GL_COLOR_BUFFER_BIT); nuclear@1: nuclear@1: glMatrixMode(GL_MODELVIEW); nuclear@1: glLoadIdentity(); nuclear@1: nuclear@1: if(show_thumb) { nuclear@1: glEnable(GL_TEXTURE_2D); nuclear@1: glBindTexture(GL_TEXTURE_2D, show_thumb->tex); nuclear@1: nuclear@1: glScalef(show_zoom, show_zoom, 1); nuclear@1: glTranslatef(2.0 * show_pan_x, 2.0 * show_pan_y, 0); nuclear@4: if(show_thumb->aspect >= win_aspect) { nuclear@1: glScalef(1, 1.0 / show_thumb->aspect, 1); nuclear@1: } else { nuclear@3: glScalef(show_thumb->aspect / win_aspect, 1.0 / win_aspect, 1); nuclear@1: } nuclear@1: nuclear@1: glBegin(GL_QUADS); nuclear@1: glColor3f(1, 1, 1); nuclear@1: glTexCoord2f(0, 0); glVertex2f(-1, -1); nuclear@1: glTexCoord2f(1, 0); glVertex2f(1, -1); nuclear@1: glTexCoord2f(1, 1); glVertex2f(1, 1); nuclear@1: glTexCoord2f(0, 1); glVertex2f(-1, 1); nuclear@1: glEnd(); nuclear@1: nuclear@1: glDisable(GL_TEXTURE_2D); nuclear@1: } else { nuclear@1: draw_thumbs(thumbs, thumbs_size, pan_y); nuclear@1: } nuclear@1: nuclear@1: glutSwapBuffers(); nuclear@1: assert(glGetError() == GL_NO_ERROR); nuclear@1: } nuclear@1: nuclear@1: static void idle(void) nuclear@1: { nuclear@1: glutPostRedisplay(); nuclear@1: } nuclear@1: nuclear@1: static void reshape(int x, int y) nuclear@1: { nuclear@1: win_aspect = (float)x / (float)y; nuclear@1: nuclear@1: glViewport(0, 0, x, y); nuclear@1: nuclear@1: glMatrixMode(GL_PROJECTION); nuclear@1: glLoadIdentity(); nuclear@1: glOrtho(-1, 1, 1.0 / win_aspect, -1.0 / win_aspect, -1, 1); nuclear@1: nuclear@1: win_width = x; nuclear@1: win_height = y; nuclear@1: } nuclear@1: nuclear@1: static void keyb(unsigned char key, int x, int y) nuclear@1: { nuclear@1: switch(key) { nuclear@1: case 27: nuclear@3: if(show_thumb) { nuclear@3: show_thumb = 0; nuclear@3: glutPostRedisplay(); nuclear@3: } else { nuclear@3: exit(0); nuclear@3: } nuclear@3: break; nuclear@1: nuclear@1: case ' ': nuclear@1: show_zoom = 1.0; nuclear@1: thumbs_size = 0.25; nuclear@1: pan_x = pan_y = show_pan_x = show_pan_y = 0; nuclear@1: glutPostRedisplay(); nuclear@1: break; nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: static int bnstate[32]; nuclear@1: static int prev_x, prev_y; nuclear@1: static int click_x[32], click_y[32]; nuclear@1: nuclear@1: static void mouse(int bn, int st, int x, int y) nuclear@1: { nuclear@1: int bidx = bn - GLUT_LEFT_BUTTON; nuclear@1: int state = st == GLUT_DOWN ? 1 : 0; nuclear@1: nuclear@1: bnstate[bidx] = state; nuclear@1: nuclear@1: prev_x = x; nuclear@1: prev_y = y; nuclear@1: nuclear@1: if(state) { nuclear@1: click_x[bidx] = x; nuclear@1: click_y[bidx] = y; nuclear@1: } else { nuclear@1: int is_drag = abs(x - click_x[bidx]) > 3 || abs(y - click_y[bidx]) > 3; nuclear@1: nuclear@1: if(bidx == 0) { nuclear@1: if(!show_thumb) { nuclear@1: if(!is_drag) { nuclear@1: struct thumbnail *sel = find_thumb(x, y); nuclear@1: if(sel) { nuclear@1: show_thumb = sel; nuclear@1: show_pan_x = show_pan_y = 0; nuclear@1: glutPostRedisplay(); nuclear@1: } nuclear@1: } nuclear@1: } nuclear@1: } else { nuclear@1: if(!is_drag) { nuclear@1: show_thumb = 0; nuclear@1: glutPostRedisplay(); nuclear@1: } nuclear@1: } nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: static void motion(int x, int y) nuclear@1: { nuclear@1: int dx = x - prev_x; nuclear@1: int dy = y - prev_y; nuclear@1: prev_x = x; nuclear@1: prev_y = y; nuclear@1: nuclear@1: if(!dx && !dy) return; nuclear@1: nuclear@1: if(bnstate[0]) { nuclear@1: float fdx = dx / (float)win_width; nuclear@1: float fdy = dy / (float)win_height / win_aspect; nuclear@1: nuclear@1: if(show_thumb) { nuclear@1: show_pan_x += fdx / show_zoom; nuclear@1: show_pan_y += fdy / show_zoom; nuclear@1: } else { nuclear@1: pan_x += fdx; nuclear@1: pan_y += fdy; nuclear@1: } nuclear@1: glutPostRedisplay(); nuclear@1: } nuclear@1: nuclear@1: if(bnstate[2]) { nuclear@1: if(show_thumb) { nuclear@1: show_zoom -= dy * 0.0075; nuclear@1: if(show_zoom <= 0) show_zoom = 0; nuclear@1: } else { nuclear@1: thumbs_size -= dy * 0.005; nuclear@1: if(thumbs_size <= 0.01) thumbs_size = 0.01; nuclear@1: } nuclear@1: glutPostRedisplay(); nuclear@1: } nuclear@1: } nuclear@1: nuclear@2: static void sball_motion(int x, int y, int z) nuclear@2: { nuclear@2: float fx = -x * 0.0004; nuclear@2: float fy = z * 0.0004; nuclear@2: float fz = -y * 0.0005; nuclear@2: nuclear@2: if(show_thumb) { nuclear@2: show_pan_x += fx / show_zoom; nuclear@2: show_pan_y += fy / show_zoom; nuclear@2: show_zoom += fz; nuclear@2: if(show_zoom <= 0) show_zoom = 0; nuclear@2: } else { nuclear@2: pan_x += fx; nuclear@2: pan_y += fy; nuclear@2: thumbs_size += fz; nuclear@2: if(thumbs_size <= 0.01) thumbs_size = 0.01; nuclear@2: } nuclear@2: glutPostRedisplay(); nuclear@2: } nuclear@2: nuclear@1: static struct thumbnail *find_thumb(int x, int y) nuclear@1: { nuclear@1: float fx = (float)x / (float)win_width; nuclear@1: float fy = (float)y / (float)win_height / win_aspect; nuclear@1: struct thumbnail *node; nuclear@1: nuclear@1: node = thumbs; nuclear@1: while(node) { nuclear@1: float nx = node->layout_pos[0]; nuclear@1: float ny = node->layout_pos[1]; nuclear@1: nuclear@1: if(fx >= nx && fx < nx + node->layout_size[0] && nuclear@1: fy >= ny && fy < ny + node->layout_size[1]) { nuclear@1: return node; nuclear@1: } nuclear@1: node = node->next; nuclear@1: } nuclear@1: return 0; nuclear@1: }