main_android.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. /*
  2. * Copyright (c) 2012-2022 Daniele Bartolini et al.
  3. * License: https://github.com/crownengine/crown/blob/master/LICENSE
  4. */
  5. #include "config.h"
  6. #if CROWN_PLATFORM_ANDROID
  7. #include "core/error/error.inl"
  8. #include "core/guid.h"
  9. #include "core/memory/globals.h"
  10. #include "core/memory/memory.inl"
  11. #include "core/thread/spsc_queue.inl"
  12. #include "core/thread/thread.h"
  13. #include "device/device.h"
  14. #include "device/device_event_queue.inl"
  15. #include <android/sensor.h>
  16. #include <android/window.h>
  17. #include <bgfx/platform.h>
  18. #include <jni.h>
  19. #include <stdlib.h>
  20. #define STB_SPRINTF_IMPLEMENTATION
  21. #include <stb_sprintf.h>
  22. extern "C"
  23. {
  24. #include <android_native_app_glue.c>
  25. }
  26. namespace crown
  27. {
  28. static bool push_event(const OsEvent &ev);
  29. struct AndroidDevice
  30. {
  31. SPSCQueue<OsEvent, CROWN_MAX_OS_EVENTS> _events;
  32. DeviceEventQueue _queue;
  33. Thread _main_thread;
  34. DeviceOptions *_opts;
  35. explicit AndroidDevice(Allocator &a)
  36. : _events(a)
  37. , _queue(push_event)
  38. , _opts(NULL)
  39. {
  40. }
  41. void run(struct android_app *app, DeviceOptions &opts)
  42. {
  43. _opts = &opts;
  44. app->userData = this;
  45. app->onAppCmd = crown::AndroidDevice::on_app_cmd;
  46. app->onInputEvent = crown::AndroidDevice::on_input_event;
  47. ANativeActivity_setWindowFlags(app->activity
  48. , AWINDOW_FLAG_FULLSCREEN | AWINDOW_FLAG_KEEP_SCREEN_ON
  49. , 0
  50. );
  51. while (app->destroyRequested == 0) {
  52. s32 num;
  53. android_poll_source *source;
  54. ALooper_pollAll(-1, NULL, &num, (void **)&source);
  55. if (source != NULL)
  56. source->process(app, source);
  57. }
  58. _main_thread.stop();
  59. }
  60. void process_command(struct android_app *app, s32 cmd)
  61. {
  62. switch (cmd) {
  63. case APP_CMD_SAVE_STATE:
  64. break;
  65. case APP_CMD_INIT_WINDOW: {
  66. CE_ASSERT(app->window != NULL, "Android window is NULL");
  67. bgfx::PlatformData pd;
  68. pd.ndt = NULL;
  69. pd.nwh = app->window;
  70. pd.context = NULL;
  71. pd.backBuffer = NULL;
  72. pd.backBufferDS = NULL;
  73. bgfx::setPlatformData(pd);
  74. // Push metrics here since Android does not trigger APP_CMD_WINDOW_RESIZED
  75. const s32 width = ANativeWindow_getWidth(app->window);
  76. const s32 height = ANativeWindow_getHeight(app->window);
  77. _queue.push_resolution_event(width, height);
  78. if (!_main_thread.is_running()) {
  79. _main_thread.start([](void *user_data) {
  80. crown::run(*((DeviceOptions *)user_data));
  81. return EXIT_SUCCESS;
  82. }
  83. , _opts
  84. );
  85. }
  86. break;
  87. }
  88. case APP_CMD_TERM_WINDOW:
  89. // The window is being hidden or closed, clean it up.
  90. break;
  91. case APP_CMD_WINDOW_RESIZED:
  92. // Not triggered by Android
  93. break;
  94. case APP_CMD_GAINED_FOCUS:
  95. break;
  96. case APP_CMD_LOST_FOCUS:
  97. break;
  98. case APP_CMD_DESTROY:
  99. _queue.push_exit_event();
  100. break;
  101. }
  102. }
  103. s32 process_input(struct android_app *app, AInputEvent *event)
  104. {
  105. if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
  106. const s32 action = AMotionEvent_getAction(event);
  107. const s32 pointer_index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
  108. const s32 pointer_count = AMotionEvent_getPointerCount(event);
  109. const s32 pointer_id = AMotionEvent_getPointerId(event, pointer_index);
  110. const f32 x = AMotionEvent_getX(event, pointer_index);
  111. const f32 y = AMotionEvent_getY(event, pointer_index);
  112. const s32 actionMasked = (action & AMOTION_EVENT_ACTION_MASK);
  113. switch (actionMasked) {
  114. case AMOTION_EVENT_ACTION_DOWN:
  115. case AMOTION_EVENT_ACTION_POINTER_DOWN:
  116. _queue.push_button_event(InputDeviceType::TOUCHSCREEN
  117. , 0
  118. , pointer_id
  119. , true
  120. );
  121. break;
  122. case AMOTION_EVENT_ACTION_UP:
  123. case AMOTION_EVENT_ACTION_POINTER_UP:
  124. _queue.push_button_event(InputDeviceType::TOUCHSCREEN
  125. , 0
  126. , pointer_id
  127. , false
  128. );
  129. break;
  130. case AMOTION_EVENT_ACTION_OUTSIDE:
  131. case AMOTION_EVENT_ACTION_CANCEL:
  132. _queue.push_button_event(InputDeviceType::TOUCHSCREEN
  133. , 0
  134. , pointer_id
  135. , false
  136. );
  137. break;
  138. case AMOTION_EVENT_ACTION_MOVE:
  139. for (int index = 0; index < pointer_count; index++) {
  140. const f32 xx = AMotionEvent_getX(event, index);
  141. const f32 yy = AMotionEvent_getY(event, index);
  142. const s32 id = AMotionEvent_getPointerId(event, index);
  143. _queue.push_axis_event(InputDeviceType::TOUCHSCREEN
  144. , 0
  145. , id
  146. , xx
  147. , yy
  148. , 0
  149. );
  150. }
  151. break;
  152. }
  153. return 1;
  154. } else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) {
  155. const s32 keycode = AKeyEvent_getKeyCode(event);
  156. const s32 keyaction = AKeyEvent_getAction(event);
  157. if (keycode == AKEYCODE_BACK) {
  158. _queue.push_button_event(InputDeviceType::KEYBOARD
  159. , 0
  160. , KeyboardButton::ESCAPE
  161. , keyaction == AKEY_EVENT_ACTION_DOWN ? true : false
  162. );
  163. }
  164. return 1;
  165. }
  166. return 0;
  167. }
  168. static s32 on_input_event(struct android_app *app, AInputEvent *event)
  169. {
  170. return static_cast<AndroidDevice *>(app->userData)->process_input(app, event);
  171. }
  172. static void on_app_cmd(struct android_app *app, s32 cmd)
  173. {
  174. static_cast<AndroidDevice *>(app->userData)->process_command(app, cmd);
  175. }
  176. };
  177. struct WindowAndroid : public Window
  178. {
  179. WindowAndroid()
  180. {
  181. }
  182. void open(u16 /*x*/, u16 /*y*/, u16 /*width*/, u16 /*height*/, u32 /*parent*/) override
  183. {
  184. }
  185. void close() override
  186. {
  187. }
  188. void bgfx_setup() override
  189. {
  190. }
  191. void show() override
  192. {
  193. }
  194. void hide() override
  195. {
  196. }
  197. void resize(u16 /*width*/, u16 /*height*/) override
  198. {
  199. }
  200. void move(u16 /*x*/, u16 /*y*/) override
  201. {
  202. }
  203. void minimize() override
  204. {
  205. }
  206. void maximize() override
  207. {
  208. }
  209. void restore() override
  210. {
  211. }
  212. const char *title() override
  213. {
  214. return NULL;
  215. }
  216. void set_title(const char * /*title*/) override
  217. {
  218. }
  219. void show_cursor(bool /*show*/) override
  220. {
  221. }
  222. void set_fullscreen(bool /*fullscreen*/) override
  223. {
  224. }
  225. void set_cursor(MouseCursor::Enum /*cursor*/) override
  226. {
  227. }
  228. void set_cursor_mode(CursorMode::Enum /*mode*/) override
  229. {
  230. }
  231. void *handle() override
  232. {
  233. return NULL;
  234. }
  235. };
  236. namespace window
  237. {
  238. Window *create(Allocator &a)
  239. {
  240. return CE_NEW(a, WindowAndroid)();
  241. }
  242. void destroy(Allocator &a, Window &w)
  243. {
  244. CE_DELETE(a, &w);
  245. }
  246. } // namespace window
  247. struct DisplayAndroid : public Display
  248. {
  249. void modes(Array<DisplayMode> & /*modes*/) override
  250. {
  251. }
  252. void set_mode(u32 /*id*/) override
  253. {
  254. }
  255. };
  256. namespace display
  257. {
  258. Display *create(Allocator &a)
  259. {
  260. return CE_NEW(a, DisplayAndroid)();
  261. }
  262. void destroy(Allocator &a, Display &d)
  263. {
  264. CE_DELETE(a, &d);
  265. }
  266. } // namespace display
  267. static AndroidDevice *s_android_device;
  268. static bool push_event(const OsEvent &ev)
  269. {
  270. return s_android_device->_events.push(ev);
  271. }
  272. bool next_event(OsEvent &ev)
  273. {
  274. return s_android_device->_events.pop(ev);
  275. }
  276. } // namespace crown
  277. void android_main(struct android_app *app)
  278. {
  279. using namespace crown;
  280. memory_globals::init();
  281. guid_globals::init();
  282. DeviceOptions opts(default_allocator(), 0, NULL);
  283. opts._asset_manager = app->activity->assetManager;
  284. s_android_device = CE_NEW(default_allocator(), AndroidDevice)(default_allocator());
  285. s_android_device->run(app, opts);
  286. CE_DELETE(default_allocator(), s_android_device);
  287. guid_globals::shutdown();
  288. memory_globals::shutdown();
  289. }
  290. #endif // if CROWN_PLATFORM_ANDROID