nuclear@3: #include nuclear@3: #include nuclear@3: #include nuclear@3: #include nuclear@3: #include "logger.h" nuclear@3: #include "game.h" nuclear@3: #include "timer.h" nuclear@3: nuclear@3: nuclear@3: static void handle_command(struct android_app *app, int32_t cmd); nuclear@3: static int handle_input(struct android_app *app, AInputEvent *ev); nuclear@3: static int handle_touch_input(struct android_app *app, AInputEvent *ev); nuclear@3: static int init_gl(void); nuclear@3: static void destroy_gl(void); nuclear@3: nuclear@3: static EGLDisplay dpy; nuclear@3: static EGLSurface surf; nuclear@3: static EGLContext ctx; nuclear@3: nuclear@3: static struct android_app *app; nuclear@3: static int win_width, win_height; nuclear@8: static int init_done; nuclear@3: nuclear@3: void android_main(struct android_app *app_ptr) nuclear@3: { nuclear@3: app_dummy(); nuclear@3: app = app_ptr; nuclear@3: nuclear@3: app->onAppCmd = handle_command; nuclear@3: app->onInputEvent = handle_input; nuclear@3: nuclear@3: start_logger(); nuclear@3: nuclear@3: for(;;) { nuclear@3: int num_events; nuclear@3: struct android_poll_source *pollsrc; nuclear@3: nuclear@3: while(ALooper_pollAll(0, 0, &num_events, (void**)&pollsrc) >= 0) { nuclear@3: if(pollsrc) { nuclear@3: pollsrc->process(app, pollsrc); nuclear@3: } nuclear@3: } nuclear@3: nuclear@3: if(app->destroyRequested) { nuclear@3: return; nuclear@3: } nuclear@3: nuclear@8: if(init_done) { nuclear@8: game_display(get_time_msec()); nuclear@8: eglSwapBuffers(dpy, surf); nuclear@8: } nuclear@3: } nuclear@3: } nuclear@3: nuclear@3: void set_mouse_pos(int x, int y) nuclear@3: { nuclear@3: } nuclear@3: nuclear@3: void set_mouse_cursor(int enable) nuclear@3: { nuclear@3: } nuclear@3: nuclear@3: static void handle_command(struct android_app *app, int32_t cmd) nuclear@3: { nuclear@3: switch(cmd) { nuclear@3: case APP_CMD_SAVE_STATE: nuclear@3: /* save the application state to be reloaded on restart if needed */ nuclear@3: break; nuclear@3: nuclear@3: case APP_CMD_INIT_WINDOW: nuclear@3: if(init_gl() == -1) { nuclear@3: exit(1); nuclear@3: } nuclear@3: /* initialize the application */ nuclear@3: if(game_init() == -1) { nuclear@3: exit(1); /* initialization failed, quit */ nuclear@3: } nuclear@8: init_done = 1; nuclear@3: break; nuclear@3: nuclear@3: case APP_CMD_TERM_WINDOW: nuclear@3: /* cleanup */ nuclear@8: init_done = 0; nuclear@3: game_shutdown(); nuclear@3: destroy_gl(); nuclear@3: break; nuclear@3: nuclear@3: case APP_CMD_GAINED_FOCUS: nuclear@3: /* app focused */ nuclear@3: break; nuclear@3: nuclear@3: case APP_CMD_LOST_FOCUS: nuclear@3: /* app lost focus */ nuclear@3: break; nuclear@3: nuclear@3: case APP_CMD_WINDOW_RESIZED: nuclear@3: case APP_CMD_CONFIG_CHANGED: nuclear@3: { nuclear@3: int nx = ANativeWindow_getWidth(app->window); nuclear@3: int ny = ANativeWindow_getHeight(app->window); nuclear@3: if(nx != win_width || ny != win_height) { nuclear@3: game_reshape(nx, ny); nuclear@3: win_width = nx; nuclear@3: win_height = ny; nuclear@3: } nuclear@3: } nuclear@3: break; nuclear@3: nuclear@3: default: nuclear@3: break; nuclear@3: } nuclear@3: } nuclear@3: nuclear@3: static int handle_input(struct android_app *app, AInputEvent *ev) nuclear@3: { nuclear@3: int evtype = AInputEvent_getType(ev); nuclear@3: nuclear@3: switch(evtype) { nuclear@3: case AINPUT_EVENT_TYPE_MOTION: nuclear@3: return handle_touch_input(app, ev); nuclear@3: nuclear@3: default: nuclear@3: break; nuclear@3: } nuclear@3: return 0; nuclear@3: } nuclear@3: nuclear@3: #define MAX_TOUCH_IDS 32 nuclear@3: nuclear@3: static int handle_touch_input(struct android_app *app, AInputEvent *ev) nuclear@3: { nuclear@3: int x, y, idx, touch_id; nuclear@3: unsigned int action; nuclear@3: static int prev_pos[MAX_TOUCH_IDS][2]; nuclear@3: nuclear@3: action = AMotionEvent_getAction(ev); nuclear@3: nuclear@3: idx = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> nuclear@3: AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; nuclear@3: touch_id = AMotionEvent_getPointerId(ev, idx); nuclear@3: nuclear@3: x = AMotionEvent_getX(ev, idx); nuclear@3: y = AMotionEvent_getY(ev, idx); nuclear@3: nuclear@3: switch(action & AMOTION_EVENT_ACTION_MASK) { nuclear@3: case AMOTION_EVENT_ACTION_DOWN: nuclear@3: case AMOTION_EVENT_ACTION_POINTER_DOWN: nuclear@3: game_mouse_button(touch_id, 0, 1, x, y); nuclear@3: if(touch_id < MAX_TOUCH_IDS) { nuclear@3: prev_pos[touch_id][0] = x; nuclear@3: prev_pos[touch_id][1] = y; nuclear@3: } nuclear@3: break; nuclear@3: nuclear@3: case AMOTION_EVENT_ACTION_UP: nuclear@3: case AMOTION_EVENT_ACTION_POINTER_UP: nuclear@3: game_mouse_button(touch_id, 0, 0, x, y); nuclear@3: if(touch_id < MAX_TOUCH_IDS) { nuclear@3: prev_pos[touch_id][0] = x; nuclear@3: prev_pos[touch_id][1] = y; nuclear@3: } nuclear@3: break; nuclear@3: nuclear@3: case AMOTION_EVENT_ACTION_MOVE: nuclear@3: { nuclear@3: int i, pcount = AMotionEvent_getPointerCount(ev); nuclear@3: for(i=0; iwindow, 0, 0, vis); nuclear@3: nuclear@3: if(!(surf = eglCreateWindowSurface(dpy, eglcfg, app->window, 0))) { nuclear@3: fprintf(stderr, "failed to create window\n"); nuclear@3: destroy_gl(); nuclear@3: return -1; nuclear@3: } nuclear@3: nuclear@3: if(!(ctx = eglCreateContext(dpy, eglcfg, EGL_NO_CONTEXT, ctxattr))) { nuclear@3: fprintf(stderr, "failed to create OpenGL ES context\n"); nuclear@3: destroy_gl(); nuclear@3: return -1; nuclear@3: } nuclear@3: eglMakeCurrent(dpy, surf, surf, ctx); nuclear@3: nuclear@3: eglQuerySurface(dpy, surf, EGL_WIDTH, &win_width); nuclear@3: eglQuerySurface(dpy, surf, EGL_HEIGHT, &win_height); nuclear@3: game_reshape(win_width, win_height); nuclear@3: nuclear@3: return 0; nuclear@3: } nuclear@3: nuclear@3: static void destroy_gl(void) nuclear@3: { nuclear@3: if(!dpy) return; nuclear@3: nuclear@3: eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); nuclear@3: nuclear@3: if(ctx) { nuclear@3: eglDestroyContext(dpy, ctx); nuclear@3: ctx = 0; nuclear@3: } nuclear@3: if(surf) { nuclear@3: eglDestroySurface(dpy, surf); nuclear@3: surf = 0; nuclear@3: } nuclear@3: nuclear@3: eglTerminate(dpy); nuclear@3: dpy = 0; nuclear@3: } nuclear@3: