|
|
@@ -16,22 +16,24 @@
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
-int __width;
|
|
|
-int __height;
|
|
|
+struct android_app* __state;
|
|
|
+AAssetManager* __assetManager;
|
|
|
+std::string __assetsPath;
|
|
|
+bool __initialized = false;
|
|
|
+bool __destroyed = false;
|
|
|
+
|
|
|
static EGLDisplay __eglDisplay = EGL_NO_DISPLAY;
|
|
|
static EGLContext __eglContext = EGL_NO_CONTEXT;
|
|
|
static EGLSurface __eglSurface = EGL_NO_SURFACE;
|
|
|
static EGLConfig __eglConfig = 0;
|
|
|
-
|
|
|
+int __width;
|
|
|
+int __height;
|
|
|
|
|
|
struct timespec __timespec;
|
|
|
static long __timeStart;
|
|
|
static long __timeAbsolute;
|
|
|
static bool __vsync = WINDOW_VSYNC;
|
|
|
|
|
|
-struct android_app* __state;
|
|
|
-extern std::string __assetsPath;
|
|
|
-
|
|
|
ASensorManager* __sensorManager;
|
|
|
ASensorEventQueue* __sensorEventQueue;
|
|
|
ASensorEvent __sensorEvent;
|
|
|
@@ -39,7 +41,7 @@ const ASensor* __accelerometerSensor;
|
|
|
|
|
|
static int __orientationAngle;
|
|
|
static bool __multiTouch = false;
|
|
|
-extern bool __displayKeyboard;
|
|
|
+bool __displayKeyboard = false;
|
|
|
|
|
|
static const char* __glExtensions;
|
|
|
PFNGLBINDVERTEXARRAYOESPROC glBindVertexArray = NULL;
|
|
|
@@ -50,7 +52,149 @@ PFNGLISVERTEXARRAYOESPROC glIsVertexArray = NULL;
|
|
|
namespace gameplay
|
|
|
{
|
|
|
|
|
|
-extern void displayKeyboard(android_app* state, bool pShow)
|
|
|
+long timespec2millis(struct timespec *a)
|
|
|
+{
|
|
|
+ return a->tv_sec*1000 + a->tv_nsec/1000000;
|
|
|
+}
|
|
|
+
|
|
|
+extern void printError(const char* format, ...)
|
|
|
+{
|
|
|
+ va_list argptr;
|
|
|
+ va_start(argptr, format);
|
|
|
+ LOGI(format, argptr);
|
|
|
+ va_end(argptr);
|
|
|
+}
|
|
|
+
|
|
|
+EGLenum checkErrorEGL(const char* msg)
|
|
|
+{
|
|
|
+ static const char* errmsg[] =
|
|
|
+ {
|
|
|
+ "EGL function succeeded",
|
|
|
+ "EGL is not initialized, or could not be initialized, for the specified display",
|
|
|
+ "EGL cannot access a requested resource",
|
|
|
+ "EGL failed to allocate resources for the requested operation",
|
|
|
+ "EGL fail to access an unrecognized attribute or attribute value was passed in an attribute list",
|
|
|
+ "EGLConfig argument does not name a valid EGLConfig",
|
|
|
+ "EGLContext argument does not name a valid EGLContext",
|
|
|
+ "EGL current surface of the calling thread is no longer valid",
|
|
|
+ "EGLDisplay argument does not name a valid EGLDisplay",
|
|
|
+ "EGL arguments are inconsistent",
|
|
|
+ "EGLNativePixmapType argument does not refer to a valid native pixmap",
|
|
|
+ "EGLNativeWindowType argument does not refer to a valid native window",
|
|
|
+ "EGL one or more argument values are invalid",
|
|
|
+ "EGLSurface argument does not name a valid surface configured for rendering",
|
|
|
+ "EGL power management event has occurred",
|
|
|
+ };
|
|
|
+ EGLenum error = eglGetError();
|
|
|
+ LOGI("%s: %s\n", msg, errmsg[error - EGL_SUCCESS]);
|
|
|
+ return error;
|
|
|
+}
|
|
|
+
|
|
|
+// Initialized EGL resources.
|
|
|
+bool initEGL()
|
|
|
+{
|
|
|
+ // Hard-coded to 32-bit/OpenGL ES 2.0.
|
|
|
+ const EGLint eglConfigAttrs[] =
|
|
|
+ {
|
|
|
+ EGL_RED_SIZE, 8,
|
|
|
+ EGL_GREEN_SIZE, 8,
|
|
|
+ EGL_BLUE_SIZE, 8,
|
|
|
+ EGL_ALPHA_SIZE, 8,
|
|
|
+ EGL_DEPTH_SIZE, 24,
|
|
|
+ EGL_STENCIL_SIZE, 8,
|
|
|
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
|
|
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
|
|
+ EGL_NONE
|
|
|
+ };
|
|
|
+
|
|
|
+ EGLint eglConfigCount;
|
|
|
+ const EGLint eglContextAttrs[] =
|
|
|
+ {
|
|
|
+ EGL_CONTEXT_CLIENT_VERSION, 2,
|
|
|
+ EGL_NONE
|
|
|
+ };
|
|
|
+
|
|
|
+ const EGLint eglSurfaceAttrs[] =
|
|
|
+ {
|
|
|
+ EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
|
|
|
+ EGL_NONE
|
|
|
+ };
|
|
|
+
|
|
|
+ // Get the EGL display and initialize.
|
|
|
+ __eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
|
|
+ if (__eglDisplay == EGL_NO_DISPLAY)
|
|
|
+ {
|
|
|
+ checkErrorEGL("eglGetDisplay");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (eglInitialize(__eglDisplay, NULL, NULL) != EGL_TRUE)
|
|
|
+ {
|
|
|
+ checkErrorEGL("eglInitialize");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (eglChooseConfig(__eglDisplay, eglConfigAttrs, &__eglConfig, 1, &eglConfigCount) != EGL_TRUE || eglConfigCount == 0)
|
|
|
+ {
|
|
|
+ checkErrorEGL("eglChooseConfig");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+
|
|
|
+ __eglContext = eglCreateContext(__eglDisplay, __eglConfig, EGL_NO_CONTEXT, eglContextAttrs);
|
|
|
+ if (__eglContext == EGL_NO_CONTEXT)
|
|
|
+ {
|
|
|
+ checkErrorEGL("eglCreateContext");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+
|
|
|
+ // EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
|
|
|
+ // guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
|
|
|
+ // As soon as we picked a EGLConfig, we can safely reconfigure the
|
|
|
+ // ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID.
|
|
|
+ EGLint format;
|
|
|
+ eglGetConfigAttrib(__eglDisplay, __eglConfig, EGL_NATIVE_VISUAL_ID, &format);
|
|
|
+ ANativeWindow_setBuffersGeometry(__state->window, 0, 0, format);
|
|
|
+
|
|
|
+ __eglSurface = eglCreateWindowSurface(__eglDisplay, __eglConfig, __state->window, eglSurfaceAttrs);
|
|
|
+ if (__eglSurface == EGL_NO_SURFACE)
|
|
|
+ {
|
|
|
+ checkErrorEGL("eglCreateWindowSurface");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (eglMakeCurrent(__eglDisplay, __eglSurface, __eglSurface, __eglContext) != EGL_TRUE)
|
|
|
+ {
|
|
|
+ checkErrorEGL("eglMakeCurrent");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+
|
|
|
+ eglQuerySurface(__eglDisplay, __eglSurface, EGL_WIDTH, &__width);
|
|
|
+ eglQuerySurface(__eglDisplay, __eglSurface, EGL_HEIGHT, &__height);
|
|
|
+
|
|
|
+ // Set vsync.
|
|
|
+ eglSwapInterval(__eglDisplay, WINDOW_VSYNC ? 1 : 0);
|
|
|
+
|
|
|
+ // Initialize OpenGL ES extensions.
|
|
|
+ __glExtensions = (const char*)glGetString(GL_EXTENSIONS);
|
|
|
+
|
|
|
+ if (strstr(__glExtensions, "GL_OES_vertex_array_object") || strstr(__glExtensions, "GL_ARB_vertex_array_object"))
|
|
|
+ {
|
|
|
+ // Disable VAO extension for now.
|
|
|
+ glBindVertexArray = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress("glBindVertexArrayOES");
|
|
|
+ glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress("glDeleteVertexArrays");
|
|
|
+ glGenVertexArrays = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress("glGenVertexArraysOES");
|
|
|
+ glIsVertexArray = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress("glIsVertexArrayOES");
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+
|
|
|
+error:
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+// Display the android virtual keyboard.
|
|
|
+void displayKeyboard(android_app* state, bool pShow)
|
|
|
{
|
|
|
|
|
|
// The following functions is supposed to show / hide functins from a native activity.. but currently
|
|
|
@@ -116,7 +260,7 @@ extern void displayKeyboard(android_app* state, bool pShow)
|
|
|
}
|
|
|
|
|
|
// Gets the Keyboard::Key enumeration constant that corresponds to the given Android key code.
|
|
|
-extern Keyboard::Key getKey(int keycode, int metastate)
|
|
|
+Keyboard::Key getKey(int keycode, int metastate)
|
|
|
{
|
|
|
bool shiftOn = (metastate == AMETA_SHIFT_ON);
|
|
|
|
|
|
@@ -259,38 +403,90 @@ extern Keyboard::Key getKey(int keycode, int metastate)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-extern void printError(const char* format, ...)
|
|
|
+// Process the next input event.
|
|
|
+static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
|
|
|
{
|
|
|
- va_list argptr;
|
|
|
- va_start(argptr, format);
|
|
|
- LOGI(format, argptr);
|
|
|
- va_end(argptr);
|
|
|
+ if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION)
|
|
|
+ {
|
|
|
+ int32_t data = AMotionEvent_getAction(event);
|
|
|
+ int contactIndex = data >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
|
|
|
+ Touch::TouchEvent touchEvent;
|
|
|
+ switch (data & AMOTION_EVENT_ACTION_MASK)
|
|
|
+ {
|
|
|
+ case AMOTION_EVENT_ACTION_DOWN:
|
|
|
+ touchEvent = Touch::TOUCH_PRESS;
|
|
|
+ break;
|
|
|
+ case AMOTION_EVENT_ACTION_UP:
|
|
|
+ touchEvent = Touch::TOUCH_RELEASE;
|
|
|
+ break;
|
|
|
+ case AMOTION_EVENT_ACTION_MOVE:
|
|
|
+ touchEvent = Touch::TOUCH_MOVE;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ Game::getInstance()->touchEvent(touchEvent, AMotionEvent_getX(event, 0), AMotionEvent_getY(event, 0), contactIndex);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY)
|
|
|
+ {
|
|
|
+ int32_t action = AKeyEvent_getAction(event);
|
|
|
+ int32_t keycode = AKeyEvent_getKeyCode(event);
|
|
|
+ int32_t metastate = AKeyEvent_getMetaState(event);
|
|
|
+
|
|
|
+ switch(action)
|
|
|
+ {
|
|
|
+ case AKEY_EVENT_ACTION_DOWN:
|
|
|
+ Game::getInstance()->keyEvent(Keyboard::KEY_PRESS, getKey(keycode, metastate));
|
|
|
+ break;
|
|
|
+
|
|
|
+ case AKEY_EVENT_ACTION_UP:
|
|
|
+ Game::getInstance()->keyEvent(Keyboard::KEY_RELEASE, getKey(keycode, metastate));
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
-EGLenum checkErrorEGL(const char* msg)
|
|
|
+// Process the next main command.
|
|
|
+static void engine_handle_cmd(struct android_app* app, int32_t cmd)
|
|
|
{
|
|
|
- static const char* errmsg[] =
|
|
|
+ switch (cmd)
|
|
|
{
|
|
|
- "EGL function succeeded",
|
|
|
- "EGL is not initialized, or could not be initialized, for the specified display",
|
|
|
- "EGL cannot access a requested resource",
|
|
|
- "EGL failed to allocate resources for the requested operation",
|
|
|
- "EGL fail to access an unrecognized attribute or attribute value was passed in an attribute list",
|
|
|
- "EGLConfig argument does not name a valid EGLConfig",
|
|
|
- "EGLContext argument does not name a valid EGLContext",
|
|
|
- "EGL current surface of the calling thread is no longer valid",
|
|
|
- "EGLDisplay argument does not name a valid EGLDisplay",
|
|
|
- "EGL arguments are inconsistent",
|
|
|
- "EGLNativePixmapType argument does not refer to a valid native pixmap",
|
|
|
- "EGLNativeWindowType argument does not refer to a valid native window",
|
|
|
- "EGL one or more argument values are invalid",
|
|
|
- "EGLSurface argument does not name a valid surface configured for rendering",
|
|
|
- "EGL power management event has occurred",
|
|
|
- };
|
|
|
- EGLenum error = eglGetError();
|
|
|
- LOGI("%s: %s\n", msg, errmsg[error - EGL_SUCCESS]);
|
|
|
- return error;
|
|
|
+ case APP_CMD_SAVE_STATE:
|
|
|
+ // TODO
|
|
|
+ break;
|
|
|
+ case APP_CMD_INIT_WINDOW:
|
|
|
+ // The window is being shown, get it ready.
|
|
|
+ if (app->window != NULL)
|
|
|
+ {
|
|
|
+ __initialized = true;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case APP_CMD_TERM_WINDOW:
|
|
|
+ {
|
|
|
+ __destroyed = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case APP_CMD_GAINED_FOCUS:
|
|
|
+ // When our app gains focus, we start monitoring the accelerometer.
|
|
|
+ if (__accelerometerSensor != NULL)
|
|
|
+ {
|
|
|
+ ASensorEventQueue_enableSensor(__sensorEventQueue, __accelerometerSensor);
|
|
|
+ // We'd like to get 60 events per second (in us).
|
|
|
+ ASensorEventQueue_setEventRate(__sensorEventQueue, __accelerometerSensor, (1000L/60)*1000);
|
|
|
+ }
|
|
|
+ Game::getInstance()->resume();
|
|
|
+ break;
|
|
|
+ case APP_CMD_LOST_FOCUS:
|
|
|
+ // When our app loses focus, we stop monitoring the accelerometer.
|
|
|
+ // This is to avoid consuming battery while not being used.
|
|
|
+ if (__accelerometerSensor != NULL)
|
|
|
+ {
|
|
|
+ ASensorEventQueue_disableSensor(__sensorEventQueue, __accelerometerSensor);
|
|
|
+ }
|
|
|
+ Game::getInstance()->pause();
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
Platform::Platform(Game* game)
|
|
|
@@ -331,172 +527,123 @@ Platform::~Platform()
|
|
|
|
|
|
Platform* Platform::create(Game* game)
|
|
|
{
|
|
|
- FileSystem::setResourcePath(__assetsPath.c_str());
|
|
|
-
|
|
|
Platform* platform = new Platform(game);
|
|
|
-
|
|
|
- // Hard-coded to 32-bit/OpenGL ES 2.0.
|
|
|
- const EGLint eglConfigAttrs[] =
|
|
|
- {
|
|
|
- EGL_RED_SIZE, 8,
|
|
|
- EGL_GREEN_SIZE, 8,
|
|
|
- EGL_BLUE_SIZE, 8,
|
|
|
- EGL_ALPHA_SIZE, 8,
|
|
|
- EGL_DEPTH_SIZE, 24,
|
|
|
- EGL_STENCIL_SIZE, 8,
|
|
|
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
|
|
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
|
|
- EGL_NONE
|
|
|
- };
|
|
|
-
|
|
|
- EGLint eglConfigCount;
|
|
|
- const EGLint eglContextAttrs[] =
|
|
|
- {
|
|
|
- EGL_CONTEXT_CLIENT_VERSION, 2,
|
|
|
- EGL_NONE
|
|
|
- };
|
|
|
-
|
|
|
- const EGLint eglSurfaceAttrs[] =
|
|
|
- {
|
|
|
- EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
|
|
|
- EGL_NONE
|
|
|
- };
|
|
|
-
|
|
|
- // Get the EGL display and initialize.
|
|
|
- __eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
|
|
- if (__eglDisplay == EGL_NO_DISPLAY)
|
|
|
- {
|
|
|
- checkErrorEGL("eglGetDisplay");
|
|
|
- goto error;
|
|
|
- }
|
|
|
-
|
|
|
- if (eglInitialize(__eglDisplay, NULL, NULL) != EGL_TRUE)
|
|
|
- {
|
|
|
- checkErrorEGL("eglInitialize");
|
|
|
- goto error;
|
|
|
- }
|
|
|
-
|
|
|
- if (eglChooseConfig(__eglDisplay, eglConfigAttrs, &__eglConfig, 1, &eglConfigCount) != EGL_TRUE || eglConfigCount == 0)
|
|
|
- {
|
|
|
- checkErrorEGL("eglChooseConfig");
|
|
|
- goto error;
|
|
|
- }
|
|
|
-
|
|
|
- __eglContext = eglCreateContext(__eglDisplay, __eglConfig, EGL_NO_CONTEXT, eglContextAttrs);
|
|
|
- if (__eglContext == EGL_NO_CONTEXT)
|
|
|
- {
|
|
|
- checkErrorEGL("eglCreateContext");
|
|
|
- goto error;
|
|
|
- }
|
|
|
-
|
|
|
- // EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
|
|
|
- // guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
|
|
|
- // As soon as we picked a EGLConfig, we can safely reconfigure the
|
|
|
- // ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID.
|
|
|
- EGLint format;
|
|
|
- eglGetConfigAttrib(__eglDisplay, __eglConfig, EGL_NATIVE_VISUAL_ID, &format);
|
|
|
- ANativeWindow_setBuffersGeometry(__state->window, 0, 0, format);
|
|
|
-
|
|
|
- __eglSurface = eglCreateWindowSurface(__eglDisplay, __eglConfig, __state->window, eglSurfaceAttrs);
|
|
|
- if (__eglSurface == EGL_NO_SURFACE)
|
|
|
- {
|
|
|
- checkErrorEGL("eglCreateWindowSurface");
|
|
|
- goto error;
|
|
|
- }
|
|
|
-
|
|
|
- if (eglMakeCurrent(__eglDisplay, __eglSurface, __eglSurface, __eglContext) != EGL_TRUE)
|
|
|
- {
|
|
|
- checkErrorEGL("eglMakeCurrent");
|
|
|
- goto error;
|
|
|
- }
|
|
|
-
|
|
|
- eglQuerySurface(__eglDisplay, __eglSurface, EGL_WIDTH, &__width);
|
|
|
- eglQuerySurface(__eglDisplay, __eglSurface, EGL_HEIGHT, &__height);
|
|
|
-
|
|
|
- // Set vsync.
|
|
|
- eglSwapInterval(__eglDisplay, WINDOW_VSYNC ? 1 : 0);
|
|
|
-
|
|
|
- // Initialize OpenGL ES extensions.
|
|
|
- __glExtensions = (const char*)glGetString(GL_EXTENSIONS);
|
|
|
-
|
|
|
- if (strstr(__glExtensions, "GL_OES_vertex_array_object") || strstr(__glExtensions, "GL_ARB_vertex_array_object"))
|
|
|
- {
|
|
|
- // Disable VAO extension for now.
|
|
|
- glBindVertexArray = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress("glBindVertexArrayOES");
|
|
|
- glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress("glDeleteVertexArrays");
|
|
|
- glGenVertexArrays = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress("glGenVertexArraysOES");
|
|
|
- glIsVertexArray = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress("glIsVertexArrayOES");
|
|
|
- }
|
|
|
-
|
|
|
|
|
|
// TODO: Determine initial orientation angle.
|
|
|
//orientation_direction_t direction;
|
|
|
//orientation_get(&direction, &__orientationAngle);
|
|
|
|
|
|
return platform;
|
|
|
-
|
|
|
-error:
|
|
|
-
|
|
|
- // TODO: cleanup.
|
|
|
-
|
|
|
- return NULL;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Convert the timespec into milliseconds.
|
|
|
- */
|
|
|
-long timespec2millis(struct timespec *a)
|
|
|
-{
|
|
|
- return a->tv_sec*1000 + a->tv_nsec/1000000;
|
|
|
}
|
|
|
|
|
|
int Platform::enterMessagePump()
|
|
|
{
|
|
|
- static int state = 0;
|
|
|
+ // Get the android application's activity.
|
|
|
+ ANativeActivity* activity = __state->activity;
|
|
|
+ JNIEnv* env = activity->env;
|
|
|
+
|
|
|
+ // Get the package name for this app from Java.
|
|
|
+ jclass clazz = env->GetObjectClass(activity->clazz);
|
|
|
+ jmethodID methodID = env->GetMethodID(clazz, "getPackageName", "()Ljava/lang/String;");
|
|
|
+ jobject result = env->CallObjectMethod(activity->clazz, methodID);
|
|
|
+
|
|
|
+ const char* packageName;
|
|
|
+ jboolean isCopy;
|
|
|
+ packageName = env->GetStringUTFChars((jstring)result, &isCopy);
|
|
|
|
|
|
- switch (state)
|
|
|
+ // Set the default path to store the resources.
|
|
|
+ __assetsPath = "/mnt/sdcard/android/data/";
|
|
|
+ __assetsPath += packageName;
|
|
|
+ __assetsPath += "/";
|
|
|
+ FileSystem::setResourcePath(__assetsPath.c_str());
|
|
|
+
|
|
|
+ // Get the asset manager to get the resources from the .apk file.
|
|
|
+ __assetManager = __state->activity->assetManager;
|
|
|
+
|
|
|
+ // Set the event call back functions.
|
|
|
+ __state->onAppCmd = engine_handle_cmd;
|
|
|
+ __state->onInputEvent = engine_handle_input;
|
|
|
+
|
|
|
+ // Prepare to monitor accelerometer.
|
|
|
+ __sensorManager = ASensorManager_getInstance();
|
|
|
+ __accelerometerSensor = ASensorManager_getDefaultSensor(__sensorManager, ASENSOR_TYPE_ACCELEROMETER);
|
|
|
+ __sensorEventQueue = ASensorManager_createEventQueue(__sensorManager, __state->looper, LOOPER_ID_USER, NULL, NULL);
|
|
|
+
|
|
|
+ // Get the initial time.
|
|
|
+ clock_gettime(CLOCK_REALTIME, &__timespec);
|
|
|
+ __timeStart = timespec2millis(&__timespec);
|
|
|
+ __timeAbsolute = 0L;
|
|
|
+
|
|
|
+ bool initializeGame = true;
|
|
|
+
|
|
|
+ while (true)
|
|
|
{
|
|
|
- case 0:
|
|
|
- // Get the initial time.
|
|
|
- clock_gettime(CLOCK_REALTIME, &__timespec);
|
|
|
- __timeStart = timespec2millis(&__timespec);
|
|
|
- __timeAbsolute = 0L;
|
|
|
- _game->run(__width, __height);
|
|
|
+ // Read all pending events.
|
|
|
+ int ident;
|
|
|
+ int events;
|
|
|
+ struct android_poll_source* source;
|
|
|
+
|
|
|
+ bool _shouldPoll = !(__initialized && Game::getInstance()->getState() == Game::UNINITIALIZED) && (Game::getInstance()->getState() != Game::PAUSED);
|
|
|
+
|
|
|
+ while ((ident=ALooper_pollAll( _shouldPoll ? 0 : -1, NULL, &events, (void**)&source)) >= 0)
|
|
|
+ {
|
|
|
+ // Process this event.
|
|
|
+ if (source != NULL)
|
|
|
+ source->process(__state, source);
|
|
|
|
|
|
- state = 1;
|
|
|
- break;
|
|
|
- case 1:
|
|
|
- // Idle time (no events left to process) is spent rendering.
|
|
|
- // We skip rendering when the app is paused.
|
|
|
- if (_game->getState() != Game::PAUSED)
|
|
|
+ // If a sensor has data, process it now.
|
|
|
+ if (ident == LOOPER_ID_USER && __accelerometerSensor != NULL)
|
|
|
+ ASensorEventQueue_getEvents(__sensorEventQueue, &__sensorEvent, 1);
|
|
|
+
|
|
|
+ if (__state->destroyRequested != 0)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (__initialized && initializeGame)
|
|
|
+ {
|
|
|
+ gameplay::initEGL();
|
|
|
+ WARN_VARG("Platform::enterMessagePump() - width: %d height: %d assetsPath: %s", __width, __height, __assetsPath.c_str());
|
|
|
+ _game->run(__width, __height);
|
|
|
+ initializeGame = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Idle time (no events left to process) is spent rendering.
|
|
|
+ // We skip rendering when the app is paused.
|
|
|
+ if (__initialized && _game->getState() != Game::PAUSED)
|
|
|
+ {
|
|
|
+ _game->frame();
|
|
|
+
|
|
|
+ // Post the new frame to the display.
|
|
|
+ // Note that there are a couple cases where eglSwapBuffers could fail
|
|
|
+ // with an error code that requires a certain level of re-initialization:
|
|
|
+ //
|
|
|
+ // 1) EGL_BAD_NATIVE_WINDOW - Called when the surface we're currently using
|
|
|
+ // is invalidated. This would require us to destroy our EGL surface,
|
|
|
+ // close our OpenKODE window, and start again.
|
|
|
+ //
|
|
|
+ // 2) EGL_CONTEXT_LOST - Power management event that led to our EGL context
|
|
|
+ // being lost. Requires us to re-create and re-initalize our EGL context
|
|
|
+ // and all OpenGL ES state.
|
|
|
+ //
|
|
|
+ // For now, if we get these, we'll simply exit.
|
|
|
+ int rc = eglSwapBuffers(__eglDisplay, __eglSurface);
|
|
|
+ if (rc != EGL_TRUE)
|
|
|
{
|
|
|
- _game->frame();
|
|
|
-
|
|
|
- // Post the new frame to the display.
|
|
|
- // Note that there are a couple cases where eglSwapBuffers could fail
|
|
|
- // with an error code that requires a certain level of re-initialization:
|
|
|
- //
|
|
|
- // 1) EGL_BAD_NATIVE_WINDOW - Called when the surface we're currently using
|
|
|
- // is invalidated. This would require us to destroy our EGL surface,
|
|
|
- // close our OpenKODE window, and start again.
|
|
|
- //
|
|
|
- // 2) EGL_CONTEXT_LOST - Power management event that led to our EGL context
|
|
|
- // being lost. Requires us to re-create and re-initalize our EGL context
|
|
|
- // and all OpenGL ES state.
|
|
|
- //
|
|
|
- // For now, if we get these, we'll simply exit.
|
|
|
- int rc = eglSwapBuffers(__eglDisplay, __eglSurface);
|
|
|
- if (rc != EGL_TRUE)
|
|
|
- {
|
|
|
- perror("eglSwapBuffers");
|
|
|
- _game->exit();
|
|
|
- break;
|
|
|
- }
|
|
|
+ perror("eglSwapBuffers");
|
|
|
+ _game->exit();
|
|
|
+ break;
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
+ // Check if we are exiting.
|
|
|
+ if ((__state->destroyRequested != 0) || (__initialized && Game::getInstance()->getState() == Game::UNINITIALIZED))
|
|
|
+ {
|
|
|
break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Display the keyboard.
|
|
|
+ gameplay::displayKeyboard(__state, __displayKeyboard);
|
|
|
}
|
|
|
-
|
|
|
- return 0;
|
|
|
}
|
|
|
|
|
|
long Platform::getAbsoluteTime()
|