| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360 |
- /*
- * Copyright (c) 2012-2022 Daniele Bartolini et al.
- * License: https://github.com/crownengine/crown/blob/master/LICENSE
- */
- #include "config.h"
- #if CROWN_PLATFORM_ANDROID
- #include "core/error/error.inl"
- #include "core/guid.h"
- #include "core/memory/globals.h"
- #include "core/memory/memory.inl"
- #include "core/thread/spsc_queue.inl"
- #include "core/thread/thread.h"
- #include "device/device.h"
- #include "device/device_event_queue.inl"
- #include <android/sensor.h>
- #include <android/window.h>
- #include <bgfx/platform.h>
- #include <jni.h>
- #include <stdlib.h>
- #define STB_SPRINTF_IMPLEMENTATION
- #include <stb_sprintf.h>
- extern "C"
- {
- #include <android_native_app_glue.c>
- }
- namespace crown
- {
- static bool push_event(const OsEvent &ev);
- struct AndroidDevice
- {
- SPSCQueue<OsEvent, CROWN_MAX_OS_EVENTS> _events;
- DeviceEventQueue _queue;
- Thread _main_thread;
- DeviceOptions *_opts;
- explicit AndroidDevice(Allocator &a)
- : _events(a)
- , _queue(push_event)
- , _opts(NULL)
- {
- }
- void run(struct android_app *app, DeviceOptions &opts)
- {
- _opts = &opts;
- app->userData = this;
- app->onAppCmd = crown::AndroidDevice::on_app_cmd;
- app->onInputEvent = crown::AndroidDevice::on_input_event;
- ANativeActivity_setWindowFlags(app->activity
- , AWINDOW_FLAG_FULLSCREEN | AWINDOW_FLAG_KEEP_SCREEN_ON
- , 0
- );
- while (app->destroyRequested == 0) {
- s32 num;
- android_poll_source *source;
- ALooper_pollAll(-1, NULL, &num, (void **)&source);
- if (source != NULL)
- source->process(app, source);
- }
- _main_thread.stop();
- }
- void process_command(struct android_app *app, s32 cmd)
- {
- switch (cmd) {
- case APP_CMD_SAVE_STATE:
- break;
- case APP_CMD_INIT_WINDOW: {
- CE_ASSERT(app->window != NULL, "Android window is NULL");
- bgfx::PlatformData pd;
- pd.ndt = NULL;
- pd.nwh = app->window;
- pd.context = NULL;
- pd.backBuffer = NULL;
- pd.backBufferDS = NULL;
- bgfx::setPlatformData(pd);
- // Push metrics here since Android does not trigger APP_CMD_WINDOW_RESIZED
- const s32 width = ANativeWindow_getWidth(app->window);
- const s32 height = ANativeWindow_getHeight(app->window);
- _queue.push_resolution_event(width, height);
- if (!_main_thread.is_running()) {
- _main_thread.start([](void *user_data) {
- crown::run(*((DeviceOptions *)user_data));
- return EXIT_SUCCESS;
- }
- , _opts
- );
- }
- break;
- }
- case APP_CMD_TERM_WINDOW:
- // The window is being hidden or closed, clean it up.
- break;
- case APP_CMD_WINDOW_RESIZED:
- // Not triggered by Android
- break;
- case APP_CMD_GAINED_FOCUS:
- break;
- case APP_CMD_LOST_FOCUS:
- break;
- case APP_CMD_DESTROY:
- _queue.push_exit_event();
- break;
- }
- }
- s32 process_input(struct android_app *app, AInputEvent *event)
- {
- if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
- const s32 action = AMotionEvent_getAction(event);
- const s32 pointer_index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
- const s32 pointer_count = AMotionEvent_getPointerCount(event);
- const s32 pointer_id = AMotionEvent_getPointerId(event, pointer_index);
- const f32 x = AMotionEvent_getX(event, pointer_index);
- const f32 y = AMotionEvent_getY(event, pointer_index);
- const s32 actionMasked = (action & AMOTION_EVENT_ACTION_MASK);
- switch (actionMasked) {
- case AMOTION_EVENT_ACTION_DOWN:
- case AMOTION_EVENT_ACTION_POINTER_DOWN:
- _queue.push_button_event(InputDeviceType::TOUCHSCREEN
- , 0
- , pointer_id
- , true
- );
- break;
- case AMOTION_EVENT_ACTION_UP:
- case AMOTION_EVENT_ACTION_POINTER_UP:
- _queue.push_button_event(InputDeviceType::TOUCHSCREEN
- , 0
- , pointer_id
- , false
- );
- break;
- case AMOTION_EVENT_ACTION_OUTSIDE:
- case AMOTION_EVENT_ACTION_CANCEL:
- _queue.push_button_event(InputDeviceType::TOUCHSCREEN
- , 0
- , pointer_id
- , false
- );
- break;
- case AMOTION_EVENT_ACTION_MOVE:
- for (int index = 0; index < pointer_count; index++) {
- const f32 xx = AMotionEvent_getX(event, index);
- const f32 yy = AMotionEvent_getY(event, index);
- const s32 id = AMotionEvent_getPointerId(event, index);
- _queue.push_axis_event(InputDeviceType::TOUCHSCREEN
- , 0
- , id
- , xx
- , yy
- , 0
- );
- }
- break;
- }
- return 1;
- } else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) {
- const s32 keycode = AKeyEvent_getKeyCode(event);
- const s32 keyaction = AKeyEvent_getAction(event);
- if (keycode == AKEYCODE_BACK) {
- _queue.push_button_event(InputDeviceType::KEYBOARD
- , 0
- , KeyboardButton::ESCAPE
- , keyaction == AKEY_EVENT_ACTION_DOWN ? true : false
- );
- }
- return 1;
- }
- return 0;
- }
- static s32 on_input_event(struct android_app *app, AInputEvent *event)
- {
- return static_cast<AndroidDevice *>(app->userData)->process_input(app, event);
- }
- static void on_app_cmd(struct android_app *app, s32 cmd)
- {
- static_cast<AndroidDevice *>(app->userData)->process_command(app, cmd);
- }
- };
- struct WindowAndroid : public Window
- {
- WindowAndroid()
- {
- }
- void open(u16 /*x*/, u16 /*y*/, u16 /*width*/, u16 /*height*/, u32 /*parent*/) override
- {
- }
- void close() override
- {
- }
- void bgfx_setup() override
- {
- }
- void show() override
- {
- }
- void hide() override
- {
- }
- void resize(u16 /*width*/, u16 /*height*/) override
- {
- }
- void move(u16 /*x*/, u16 /*y*/) override
- {
- }
- void minimize() override
- {
- }
- void maximize() override
- {
- }
- void restore() override
- {
- }
- const char *title() override
- {
- return NULL;
- }
- void set_title(const char * /*title*/) override
- {
- }
- void show_cursor(bool /*show*/) override
- {
- }
- void set_fullscreen(bool /*fullscreen*/) override
- {
- }
- void set_cursor(MouseCursor::Enum /*cursor*/) override
- {
- }
- void set_cursor_mode(CursorMode::Enum /*mode*/) override
- {
- }
- void *handle() override
- {
- return NULL;
- }
- };
- namespace window
- {
- Window *create(Allocator &a)
- {
- return CE_NEW(a, WindowAndroid)();
- }
- void destroy(Allocator &a, Window &w)
- {
- CE_DELETE(a, &w);
- }
- } // namespace window
- struct DisplayAndroid : public Display
- {
- void modes(Array<DisplayMode> & /*modes*/) override
- {
- }
- void set_mode(u32 /*id*/) override
- {
- }
- };
- namespace display
- {
- Display *create(Allocator &a)
- {
- return CE_NEW(a, DisplayAndroid)();
- }
- void destroy(Allocator &a, Display &d)
- {
- CE_DELETE(a, &d);
- }
- } // namespace display
- static AndroidDevice *s_android_device;
- static bool push_event(const OsEvent &ev)
- {
- return s_android_device->_events.push(ev);
- }
- bool next_event(OsEvent &ev)
- {
- return s_android_device->_events.pop(ev);
- }
- } // namespace crown
- void android_main(struct android_app *app)
- {
- using namespace crown;
- memory_globals::init();
- guid_globals::init();
- DeviceOptions opts(default_allocator(), 0, NULL);
- opts._asset_manager = app->activity->assetManager;
- s_android_device = CE_NEW(default_allocator(), AndroidDevice)(default_allocator());
- s_android_device->run(app, opts);
- CE_DELETE(default_allocator(), s_android_device);
- guid_globals::shutdown();
- memory_globals::shutdown();
- }
- #endif // if CROWN_PLATFORM_ANDROID
|