/* event.c * * Event Handler * * */ #include #include #include #include "client.h" #include "glframe.h" #include "platform.h" #include "window.h" #include "event.h" extern int program_running; /* an event handler struct that contains a table with function pointers */ static struct event_handler event_handler; /* when user inputs NULL for tbl, generic functions get stubbed */ int event_handler_init(struct platform *plat, struct event_vtbl *tbl) { if (!plat) return -1; event_handler.p = plat; if (tbl) event_handler.funcs = *tbl; else { memset(&event_handler.funcs, 0, sizeof(event_handler.funcs)); fprintf(stdout, "event: generic event handler will be provided\n"); } /* predefined generic handlers that are automatically provided */ if (!event_handler.funcs.keydown) event_handler.funcs.keydown = &event_keydown_gen; if (!event_handler.funcs.windowresize) event_handler.funcs.windowresize = &window_resize; if (!event_handler.funcs.quit) event_handler.funcs.quit = &event_quit_gen; return 0; } /* process SDL events */ void sdl_process_events(void) { SDL_Event event; SDLKey sym; unsigned int *keys_held = event_handler.keys_held; event_handler.key_held = 0; while (SDL_PollEvent(&event)) { sym = event.key.keysym.sym; switch (event.type) { /* keyboard event */ case SDL_KEYUP: { /* reset the key to 0 */ keys_held[sym] = 0; break; } case SDL_KEYDOWN: { keys_held[sym] = 1; if (event_handler.funcs.keydown) event_handler.funcs.keydown(&event.key.keysym); break; } case SDL_VIDEORESIZE: { assert(event_handler.funcs.windowresize); event_handler.funcs.windowresize(event.resize.w, event.resize.h); break; } case SDL_QUIT: { assert(event_handler.funcs.quit); event_handler.funcs.quit(); break; } default: break; } } /* below code has to be placed here, check for keys that are being constantly held */ if (keys_held[SDLK_w] || keys_held[SDLK_s] || keys_held[SDLK_a] || keys_held[SDLK_d] || keys_held[SDLK_UP] || keys_held[SDLK_DOWN] || keys_held[SDLK_LEFT] || keys_held[SDLK_RIGHT] || keys_held[SDLK_n] || keys_held[SDLK_m]) { event_handler.key_held = !event_handler.key_held; event_handler.funcs.keydown(NULL); } } /* generic handler function, an exception is window_resize, it is declared * in window.c */ void event_keydown_gen(SDL_keysym *keysym) { if (!keysym) return; switch (keysym->sym) { case SDLK_ESCAPE: event_handler.funcs.quit(); break; case SDLK_r: glframe_reset(&(*event_handler.p).camera); break; default: break; } } void event_quit_gen(void) { program_running = 0; } /* here are the client event handler functions */ void event_keydown(SDL_keysym *keysym) { const unsigned int *keys_held = event_handler.keys_held; struct platform *p = event_handler.p; /* a flag is toggled on if the keys that we are interested in are being held */ if (event_handler.key_held) { if (keys_held[SDLK_w]) p->c->xrot -= 5.0f; if (keys_held[SDLK_s]) p->c->xrot += 5.0f; if (keys_held[SDLK_a]) p->c->yrot -= 5.0f; if (keys_held[SDLK_d]) p->c->yrot += 5.0f; if (keys_held[SDLK_UP]) glframe_move_forward(&p->camera, 0.05f); if (keys_held[SDLK_DOWN]) glframe_move_forward(&p->camera, -0.05f); if (keys_held[SDLK_LEFT]) glframe_rotate_local_y(&p->camera, 0.02f); if (keys_held[SDLK_RIGHT]) glframe_rotate_local_y(&p->camera, -0.02f); if (keys_held[SDLK_n]) glframe_rotate_local_x(&p->camera, 0.02f); if (keys_held[SDLK_m]) glframe_rotate_local_x(&p->camera, -0.02f); } else { switch (keysym->sym) { case SDLK_ESCAPE: program_running = 0; break; case SDLK_r: glframe_reset(&(*event_handler.p).camera); break; case SDLK_w: p->c->xrot -= 5.0f; break; case SDLK_s: p->c->xrot += 5.0f; break; case SDLK_a: p->c->yrot -= 5.0f; break; case SDLK_d: p->c->yrot += 5.0f; break; case SDLK_UP: glframe_move_forward(&p->camera, 0.5f); break; case SDLK_DOWN: glframe_move_forward(&p->camera, -0.5f); break; case SDLK_LEFT: glframe_rotate_local_y(&p->camera, 0.1f); break; case SDLK_RIGHT: glframe_rotate_local_y(&p->camera, -0.1f); break; case SDLK_n: glframe_rotate_local_x(&p->camera, 0.1f); break; case SDLK_m: glframe_rotate_local_x(&p->camera, -0.1f); break; default: break; } } p->c->xrot = (GLfloat) ((const int) p->c->xrot % 360); p->c->yrot = (GLfloat) ((const int) p->c->yrot % 360); }