nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include "opengl.h" nuclear@0: nuclear@0: #include "game.h" nuclear@0: #include "input.h" nuclear@0: #include "screen.h" nuclear@0: #include "logger.h" nuclear@0: nuclear@0: /* called by any other part of the game when a redisplay is needed nuclear@0: * (mostly useful for tools which do not redisplay continuously) nuclear@0: */ nuclear@0: void request_redisplay(); nuclear@0: nuclear@0: void swap_buffers(); nuclear@0: nuclear@0: static void display(void); nuclear@0: static void reshape(int x, int y); nuclear@0: static void keydown(unsigned char key, int x, int y); nuclear@0: static void keyup(unsigned char key, int x, int y); nuclear@0: static void skeydown(int key, int x, int y); nuclear@0: static void skeyup(int key, int x, int y); nuclear@0: static void mouse(int bn, int state, int x, int y); nuclear@0: static void motion(int x, int y); nuclear@0: static void passive_motion(int x, int y); nuclear@0: nuclear@0: static long redisp_interval; nuclear@0: nuclear@0: int main(int argc, char **argv) nuclear@0: { nuclear@0: glutInit(&argc, argv); nuclear@0: glutInitWindowSize(800, 600); nuclear@0: glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | GLUT_MULTISAMPLE); nuclear@0: glutCreateWindow("Xmass inferno"); nuclear@0: nuclear@0: glutDisplayFunc(display); nuclear@0: glutReshapeFunc(reshape); nuclear@0: glutKeyboardFunc(keydown); nuclear@0: glutKeyboardUpFunc(keyup); nuclear@0: glutSpecialFunc(skeydown); nuclear@0: glutSpecialUpFunc(skeyup); nuclear@0: glutMouseFunc(mouse); nuclear@0: glutMotionFunc(motion); nuclear@0: glutPassiveMotionFunc(passive_motion); nuclear@0: nuclear@0: game_set_args(argc, argv); nuclear@0: if(!game_init()) { nuclear@0: return 1; nuclear@0: } nuclear@0: atexit(game_cleanup); nuclear@0: nuclear@0: glutMainLoop(); nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: void request_redisplay() nuclear@0: { nuclear@0: glutPostRedisplay(); nuclear@0: } nuclear@0: nuclear@0: void swap_buffers() nuclear@0: { nuclear@0: glUseProgram(0); nuclear@0: glutSwapBuffers(); nuclear@0: } nuclear@0: nuclear@0: static void display() nuclear@0: { nuclear@0: long ival = current_screen()->redisplay_interval(); nuclear@0: if(ival && !redisp_interval) { nuclear@0: debug_log("switching to auto-redisplay (interval: %ld)\n", redisp_interval); nuclear@0: glutIdleFunc(request_redisplay); nuclear@0: } nuclear@0: if(!ival && redisp_interval) { nuclear@0: debug_log("switching to manual redisplay\n"); nuclear@0: glutIdleFunc(0); nuclear@0: } nuclear@0: redisp_interval = ival; nuclear@0: nuclear@0: game_display(); nuclear@0: // TODO implement framerate limiter nuclear@0: } nuclear@0: nuclear@0: nuclear@0: static void reshape(int x, int y) nuclear@0: { nuclear@0: game_reshape(x, y); nuclear@0: } nuclear@0: nuclear@0: /* GLUT doesn't have any callbacks for modifier keys, so we fake it by calling nuclear@0: * this function all over the place, to generate fake events whenever a modifier nuclear@0: * key is detected to have changed state. nuclear@0: * The limitation is that this will only detect modkey changes whenever a regular nuclear@0: * key is pressed or released, or when a mouse button is pressed or released. nuclear@0: */ nuclear@0: static void handle_modkeys() nuclear@0: { nuclear@0: static int modstate; nuclear@0: nuclear@0: int mod = glutGetModifiers(); nuclear@0: if(mod != modstate) { nuclear@0: int diff = mod ^ modstate; nuclear@0: nuclear@0: if(diff & GLUT_ACTIVE_SHIFT) { nuclear@0: bool pressed = mod & GLUT_ACTIVE_SHIFT; nuclear@0: game_key(KEY_LSHIFT, pressed); nuclear@0: } nuclear@0: if(diff & GLUT_ACTIVE_CTRL) { nuclear@0: bool pressed = mod & GLUT_ACTIVE_CTRL; nuclear@0: game_key(KEY_LCTRL, pressed); nuclear@0: } nuclear@0: if(diff & GLUT_ACTIVE_ALT) { nuclear@0: bool pressed = mod & GLUT_ACTIVE_ALT; nuclear@0: game_key(KEY_LALT, pressed); nuclear@0: } nuclear@0: } nuclear@0: modstate = mod; nuclear@0: } nuclear@0: nuclear@0: static int translate_special_key(int key) nuclear@0: { nuclear@0: if(key >= GLUT_KEY_F1 && key <= GLUT_KEY_F12) { nuclear@0: return (key - GLUT_KEY_F1) + KEY_F1; nuclear@0: } nuclear@0: if(key >= GLUT_KEY_LEFT && key <= GLUT_KEY_PAGE_DOWN) { nuclear@0: return (key - GLUT_KEY_LEFT) + KEY_LEFT; nuclear@0: } nuclear@0: nuclear@0: switch(key) { nuclear@0: case GLUT_KEY_HOME: nuclear@0: return KEY_HOME; nuclear@0: case GLUT_KEY_END: nuclear@0: return KEY_END; nuclear@0: case GLUT_KEY_INSERT: nuclear@0: return KEY_INSERT; nuclear@0: nuclear@0: default: nuclear@0: break; nuclear@0: } nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: static void keydown(unsigned char c, int x, int y) nuclear@0: { nuclear@0: int key = c; nuclear@0: if(key == 127) { nuclear@0: key = KEY_DELETE; nuclear@0: } nuclear@0: nuclear@0: handle_modkeys(); nuclear@0: game_key(key, true); nuclear@0: } nuclear@0: nuclear@0: static void keyup(unsigned char c, int x, int y) nuclear@0: { nuclear@0: int key = c; nuclear@0: if(key == 127) { nuclear@0: key = KEY_DELETE; nuclear@0: } nuclear@0: nuclear@0: handle_modkeys(); nuclear@0: game_key(key, false); nuclear@0: } nuclear@0: nuclear@0: static void skeydown(int key, int x, int y) nuclear@0: { nuclear@0: handle_modkeys(); nuclear@0: nuclear@0: if((key = translate_special_key(key)) > 0) { nuclear@0: game_key(key, true); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: static void skeyup(int key, int x, int y) nuclear@0: { nuclear@0: handle_modkeys(); nuclear@0: nuclear@0: if((key = translate_special_key(key)) > 0) { nuclear@0: game_key(key, false); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: static void mouse(int bn, int state, int x, int y) nuclear@0: { nuclear@0: handle_modkeys(); nuclear@0: nuclear@0: int bnidx = bn - GLUT_LEFT_BUTTON; nuclear@0: bool bnstate = state == GLUT_DOWN; nuclear@0: nuclear@0: current_screen()->button(bnidx, bnstate, x, y); nuclear@0: set_mouse_state(x, y, bnidx, bnstate); // this MUST be after the event dispatch nuclear@0: } nuclear@0: nuclear@0: static void motion(int x, int y) nuclear@0: { nuclear@0: set_mouse_state(x, y); nuclear@0: current_screen()->motion(x, y, false); nuclear@0: } nuclear@0: nuclear@0: static void passive_motion(int x, int y) nuclear@0: { nuclear@0: set_mouse_state(x, y); nuclear@0: current_screen()->motion(x, y, true); nuclear@0: }