android_system.c 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272
  1. #include "android_system.h"
  2. #include "android_file_dialog.h"
  3. #include <assert.h>
  4. #include <iron_file.h>
  5. #include <iron_gpu.h>
  6. #include <iron_system.h>
  7. #include <iron_thread.h>
  8. #include <iron_video.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <sys/time.h>
  12. #include <time.h>
  13. #include <unistd.h>
  14. // #include <android/sensor.h>
  15. #include "android_native_app_glue.h"
  16. #include <android/window.h>
  17. #include <vulkan/vulkan_android.h>
  18. #include <vulkan/vulkan_core.h>
  19. typedef struct {
  20. bool available;
  21. int x;
  22. int y;
  23. int width;
  24. int height;
  25. bool primary;
  26. int number;
  27. } iron_display_t;
  28. static iron_display_t display;
  29. static struct android_app *app = NULL;
  30. static ANativeActivity *activity = NULL;
  31. // static ASensorManager *sensorManager = NULL;
  32. // static const ASensor *accelerometerSensor = NULL;
  33. // static const ASensor *gyroSensor = NULL;
  34. // static ASensorEventQueue *sensorEventQueue = NULL;
  35. static bool started = false;
  36. static bool paused = true;
  37. static bool displayIsInitialized = false;
  38. static bool appIsForeground = false;
  39. static bool activityJustResized = false;
  40. static uint16_t unicode_stack[256];
  41. static int unicode_stack_index = 0;
  42. static iron_mutex_t unicode_mutex;
  43. static bool keyboard_active = false;
  44. static const char *videoFormats[] = {"ts", NULL};
  45. static __kernel_time_t start_sec = 0;
  46. static void (*resizeCallback)(int x, int y, void *data) = NULL;
  47. static void *resizeCallbackData = NULL;
  48. char android_title[1024];
  49. #ifdef WITH_GAMEPAD
  50. static float last_x = 0.0f;
  51. static float last_y = 0.0f;
  52. static float last_l = 0.0f;
  53. static float last_r = 0.0f;
  54. static bool last_hat_left = false;
  55. static bool last_hat_right = false;
  56. static bool last_hat_up = false;
  57. static bool last_hat_down = false;
  58. #endif
  59. void iron_vulkan_surface_destroyed();
  60. bool iron_vulkan_get_size(int *width, int *height);
  61. int iron_count_displays(void) {
  62. return 1;
  63. }
  64. int iron_primary_display(void) {
  65. return 0;
  66. }
  67. static int width() {
  68. JNIEnv *env;
  69. JavaVM *vm = iron_android_get_activity()->vm;
  70. (*vm)->AttachCurrentThread(vm, &env, NULL);
  71. jclass ironActivityClass = iron_android_find_class(env, "org.armory3d.IronActivity");
  72. jmethodID ironActivityGetScreenDpi = (*env)->GetStaticMethodID(env, ironActivityClass, "getDisplayWidth", "()I");
  73. int width = (*env)->CallStaticIntMethod(env, ironActivityClass, ironActivityGetScreenDpi);
  74. (*vm)->DetachCurrentThread(vm);
  75. return width;
  76. }
  77. static int height() {
  78. JNIEnv *env;
  79. JavaVM *vm = iron_android_get_activity()->vm;
  80. (*vm)->AttachCurrentThread(vm, &env, NULL);
  81. jclass ironActivityClass = iron_android_find_class(env, "org.armory3d.IronActivity");
  82. jmethodID ironActivityGetScreenDpi = (*env)->GetStaticMethodID(env, ironActivityClass, "getDisplayHeight", "()I");
  83. int height = (*env)->CallStaticIntMethod(env, ironActivityClass, ironActivityGetScreenDpi);
  84. (*vm)->DetachCurrentThread(vm);
  85. return height;
  86. }
  87. static int pixelsPerInch() {
  88. JNIEnv *env;
  89. JavaVM *vm = iron_android_get_activity()->vm;
  90. (*vm)->AttachCurrentThread(vm, &env, NULL);
  91. jclass ironActivityClass = iron_android_find_class(env, "org.armory3d.IronActivity");
  92. jmethodID ironActivityGetScreenDpi = (*env)->GetStaticMethodID(env, ironActivityClass, "getScreenDpi", "()I");
  93. int dpi = (*env)->CallStaticIntMethod(env, ironActivityClass, ironActivityGetScreenDpi);
  94. (*vm)->DetachCurrentThread(vm);
  95. return dpi;
  96. }
  97. static int refreshRate() {
  98. JNIEnv *env;
  99. JavaVM *vm = iron_android_get_activity()->vm;
  100. (*vm)->AttachCurrentThread(vm, &env, NULL);
  101. jclass ironActivityClass = iron_android_find_class(env, "org.armory3d.IronActivity");
  102. jmethodID ironActivityGetScreenDpi = (*env)->GetStaticMethodID(env, ironActivityClass, "getRefreshRate", "()I");
  103. int dpi = (*env)->CallStaticIntMethod(env, ironActivityClass, ironActivityGetScreenDpi);
  104. (*vm)->DetachCurrentThread(vm);
  105. return dpi;
  106. }
  107. void iron_display_init() {}
  108. iron_display_mode_t iron_display_current_mode(int display) {
  109. iron_display_mode_t mode;
  110. mode.x = 0;
  111. mode.y = 0;
  112. mode.width = width();
  113. mode.height = height();
  114. mode.frequency = refreshRate();
  115. mode.bits_per_pixel = 32;
  116. mode.pixels_per_inch = pixelsPerInch();
  117. return mode;
  118. }
  119. VkResult iron_vulkan_create_surface(VkInstance instance, VkSurfaceKHR *surface) {
  120. assert(app->window != NULL);
  121. VkAndroidSurfaceCreateInfoKHR createInfo = {0};
  122. createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
  123. createInfo.pNext = NULL;
  124. createInfo.flags = 0;
  125. createInfo.window = app->window;
  126. return vkCreateAndroidSurfaceKHR(instance, &createInfo, NULL, surface);
  127. }
  128. void iron_vulkan_get_instance_extensions(const char **names, int *index) {
  129. names[(*index)++] = VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
  130. }
  131. VkBool32 iron_vulkan_get_physical_device_presentation_support(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex) {
  132. return true;
  133. }
  134. static void updateAppForegroundStatus(bool displayIsInitializedValue, bool appIsForegroundValue) {
  135. bool oldStatus = displayIsInitialized && appIsForeground;
  136. displayIsInitialized = displayIsInitializedValue;
  137. appIsForeground = appIsForegroundValue;
  138. bool newStatus = displayIsInitialized && appIsForeground;
  139. if (oldStatus != newStatus) {
  140. if (newStatus) {
  141. iron_internal_foreground_callback();
  142. }
  143. else {
  144. iron_internal_background_callback();
  145. }
  146. }
  147. }
  148. static bool isPenEvent(AInputEvent *event) {
  149. return (AInputEvent_getSource(event) & AINPUT_SOURCE_STYLUS) == AINPUT_SOURCE_STYLUS;
  150. }
  151. static void touchInput(AInputEvent *event) {
  152. int action = AMotionEvent_getAction(event);
  153. int index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
  154. int id = AMotionEvent_getPointerId(event, index);
  155. float x = AMotionEvent_getX(event, index);
  156. float y = AMotionEvent_getY(event, index);
  157. switch (action & AMOTION_EVENT_ACTION_MASK) {
  158. case AMOTION_EVENT_ACTION_DOWN:
  159. case AMOTION_EVENT_ACTION_POINTER_DOWN:
  160. if (id == 0) {
  161. iron_internal_mouse_trigger_press(0, x, y);
  162. }
  163. if (isPenEvent(event)) {
  164. iron_internal_pen_trigger_press(x, y, AMotionEvent_getPressure(event, index));
  165. }
  166. iron_internal_surface_trigger_touch_start(id, x, y);
  167. break;
  168. case AMOTION_EVENT_ACTION_MOVE:
  169. case AMOTION_EVENT_ACTION_HOVER_MOVE: {
  170. size_t count = AMotionEvent_getPointerCount(event);
  171. for (int i = 0; i < count; ++i) {
  172. id = AMotionEvent_getPointerId(event, i);
  173. x = AMotionEvent_getX(event, i);
  174. y = AMotionEvent_getY(event, i);
  175. if (id == 0) {
  176. iron_internal_mouse_trigger_move(x, y);
  177. }
  178. if (isPenEvent(event)) {
  179. iron_internal_pen_trigger_move(x, y, AMotionEvent_getPressure(event, index));
  180. }
  181. iron_internal_surface_trigger_move(id, x, y);
  182. }
  183. } break;
  184. case AMOTION_EVENT_ACTION_UP:
  185. case AMOTION_EVENT_ACTION_CANCEL:
  186. case AMOTION_EVENT_ACTION_POINTER_UP:
  187. if (id == 0) {
  188. iron_internal_mouse_trigger_release(0, x, y);
  189. }
  190. if (isPenEvent(event)) {
  191. iron_internal_pen_trigger_release(x, y, AMotionEvent_getPressure(event, index));
  192. }
  193. iron_internal_surface_trigger_touch_end(id, x, y);
  194. break;
  195. case AMOTION_EVENT_ACTION_SCROLL:
  196. if (id == 0) {
  197. float scroll = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_VSCROLL, 0);
  198. iron_internal_mouse_trigger_scroll(-scroll);
  199. }
  200. break;
  201. }
  202. }
  203. static int32_t input(struct android_app *app, AInputEvent *event) {
  204. if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
  205. int source = AInputEvent_getSource(event);
  206. if (((source & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) || ((source & AINPUT_SOURCE_MOUSE) == AINPUT_SOURCE_MOUSE)) {
  207. touchInput(event);
  208. return 1;
  209. }
  210. #ifdef WITH_GAMEPAD
  211. else if ((source & AINPUT_SOURCE_JOYSTICK) == AINPUT_SOURCE_JOYSTICK) {
  212. float x = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_X, 0);
  213. if (x != last_x) {
  214. iron_internal_gamepad_trigger_axis(0, 0, x);
  215. last_x = x;
  216. }
  217. float y = -AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_Y, 0);
  218. if (y != last_y) {
  219. iron_internal_gamepad_trigger_axis(0, 1, y);
  220. last_y = y;
  221. }
  222. float l = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_LTRIGGER, 0);
  223. if (l != last_l) {
  224. iron_internal_gamepad_trigger_button(0, 6, l);
  225. last_l = l;
  226. }
  227. float r = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_RTRIGGER, 0);
  228. if (r != last_r) {
  229. iron_internal_gamepad_trigger_button(0, 7, r);
  230. last_r = r;
  231. }
  232. float hat_x = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_HAT_X, 0);
  233. bool hat_left = false;
  234. bool hat_right = false;
  235. if (hat_x < -0.5f) {
  236. hat_left = true;
  237. }
  238. else if (hat_x > 0.5f) {
  239. hat_right = true;
  240. }
  241. float hat_y = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_HAT_Y, 0);
  242. bool hat_up = false;
  243. bool hat_down = false;
  244. if (hat_y < -0.5f) {
  245. hat_up = true;
  246. }
  247. else if (hat_y > 0.5f) {
  248. hat_down = true;
  249. }
  250. if (hat_left != last_hat_left) {
  251. iron_internal_gamepad_trigger_button(0, 14, hat_left ? 1.0f : 0.0f);
  252. last_hat_left = hat_left;
  253. }
  254. if (hat_right != last_hat_right) {
  255. iron_internal_gamepad_trigger_button(0, 15, hat_right ? 1.0f : 0.0f);
  256. last_hat_right = hat_right;
  257. }
  258. if (hat_up != last_hat_up) {
  259. iron_internal_gamepad_trigger_button(0, 12, hat_up ? 1.0f : 0.0f);
  260. last_hat_up = hat_up;
  261. }
  262. if (hat_down != last_hat_down) {
  263. iron_internal_gamepad_trigger_button(0, 13, hat_down ? 1.0f : 0.0f);
  264. last_hat_down = hat_down;
  265. }
  266. return 1;
  267. }
  268. #endif
  269. }
  270. else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) {
  271. int32_t code = AKeyEvent_getKeyCode(event);
  272. if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN) {
  273. int shift = AKeyEvent_getMetaState(event) & AMETA_SHIFT_ON;
  274. if (shift) {
  275. switch (code) {
  276. case AKEYCODE_1:
  277. iron_internal_keyboard_trigger_key_down(IRON_KEY_EXCLAMATION);
  278. iron_internal_keyboard_trigger_key_press('!');
  279. return 1;
  280. case AKEYCODE_4:
  281. iron_internal_keyboard_trigger_key_down(IRON_KEY_DOLLAR);
  282. iron_internal_keyboard_trigger_key_press('$');
  283. return 1;
  284. case AKEYCODE_5:
  285. iron_internal_keyboard_trigger_key_down(IRON_KEY_PERCENT);
  286. iron_internal_keyboard_trigger_key_press('%');
  287. return 1;
  288. case AKEYCODE_6:
  289. iron_internal_keyboard_trigger_key_down(IRON_KEY_CIRCUMFLEX);
  290. iron_internal_keyboard_trigger_key_press('^');
  291. return 1;
  292. case AKEYCODE_7:
  293. iron_internal_keyboard_trigger_key_down(IRON_KEY_AMPERSAND);
  294. iron_internal_keyboard_trigger_key_press('&');
  295. return 1;
  296. case AKEYCODE_9:
  297. iron_internal_keyboard_trigger_key_down(IRON_KEY_OPEN_PAREN);
  298. iron_internal_keyboard_trigger_key_press('(');
  299. return 1;
  300. case AKEYCODE_0:
  301. iron_internal_keyboard_trigger_key_down(IRON_KEY_CLOSE_PAREN);
  302. iron_internal_keyboard_trigger_key_press(')');
  303. return 1;
  304. case AKEYCODE_COMMA:
  305. iron_internal_keyboard_trigger_key_down(IRON_KEY_LESS_THAN);
  306. iron_internal_keyboard_trigger_key_press('<');
  307. return 1;
  308. case AKEYCODE_PERIOD:
  309. iron_internal_keyboard_trigger_key_down(IRON_KEY_GREATER_THAN);
  310. iron_internal_keyboard_trigger_key_press('>');
  311. return 1;
  312. case AKEYCODE_MINUS:
  313. iron_internal_keyboard_trigger_key_down(IRON_KEY_UNDERSCORE);
  314. iron_internal_keyboard_trigger_key_press('_');
  315. return 1;
  316. case AKEYCODE_SLASH:
  317. iron_internal_keyboard_trigger_key_down(IRON_KEY_QUESTIONMARK);
  318. iron_internal_keyboard_trigger_key_press('?');
  319. return 1;
  320. case AKEYCODE_BACKSLASH:
  321. iron_internal_keyboard_trigger_key_down(IRON_KEY_PIPE);
  322. iron_internal_keyboard_trigger_key_press('|');
  323. return 1;
  324. case AKEYCODE_LEFT_BRACKET:
  325. iron_internal_keyboard_trigger_key_down(IRON_KEY_OPEN_CURLY_BRACKET);
  326. iron_internal_keyboard_trigger_key_press('{');
  327. return 1;
  328. case AKEYCODE_RIGHT_BRACKET:
  329. iron_internal_keyboard_trigger_key_down(IRON_KEY_CLOSE_CURLY_BRACKET);
  330. iron_internal_keyboard_trigger_key_press('}');
  331. return 1;
  332. case AKEYCODE_SEMICOLON:
  333. iron_internal_keyboard_trigger_key_down(IRON_KEY_COLON);
  334. iron_internal_keyboard_trigger_key_press(':');
  335. return 1;
  336. case AKEYCODE_APOSTROPHE:
  337. iron_internal_keyboard_trigger_key_down(IRON_KEY_DOUBLE_QUOTE);
  338. iron_internal_keyboard_trigger_key_press('"');
  339. return 1;
  340. case AKEYCODE_GRAVE:
  341. iron_internal_keyboard_trigger_key_down(IRON_KEY_TILDE);
  342. iron_internal_keyboard_trigger_key_press('~');
  343. return 1;
  344. }
  345. }
  346. switch (code) {
  347. case AKEYCODE_SHIFT_LEFT:
  348. case AKEYCODE_SHIFT_RIGHT:
  349. iron_internal_keyboard_trigger_key_down(IRON_KEY_SHIFT);
  350. return 1;
  351. case AKEYCODE_DEL:
  352. iron_internal_keyboard_trigger_key_down(IRON_KEY_BACKSPACE);
  353. return 1;
  354. case AKEYCODE_ENTER:
  355. case AKEYCODE_NUMPAD_ENTER:
  356. iron_internal_keyboard_trigger_key_down(IRON_KEY_RETURN);
  357. return 1;
  358. case AKEYCODE_BACK:
  359. iron_internal_keyboard_trigger_key_down(IRON_KEY_BACK);
  360. return 1;
  361. #ifdef WITH_GAMEPAD
  362. case AKEYCODE_DPAD_CENTER:
  363. case AKEYCODE_BUTTON_B:
  364. iron_internal_gamepad_trigger_button(0, 1, 1);
  365. return 1;
  366. case AKEYCODE_BUTTON_A:
  367. iron_internal_gamepad_trigger_button(0, 0, 1);
  368. return 1;
  369. case AKEYCODE_BUTTON_Y:
  370. iron_internal_gamepad_trigger_button(0, 3, 1);
  371. return 1;
  372. case AKEYCODE_BUTTON_X:
  373. iron_internal_gamepad_trigger_button(0, 2, 1);
  374. return 1;
  375. case AKEYCODE_BUTTON_L1:
  376. iron_internal_gamepad_trigger_button(0, 4, 1);
  377. return 1;
  378. case AKEYCODE_BUTTON_R1:
  379. iron_internal_gamepad_trigger_button(0, 5, 1);
  380. return 1;
  381. case AKEYCODE_BUTTON_L2:
  382. iron_internal_gamepad_trigger_button(0, 6, 1);
  383. return 1;
  384. case AKEYCODE_BUTTON_R2:
  385. iron_internal_gamepad_trigger_button(0, 7, 1);
  386. return 1;
  387. case AKEYCODE_BUTTON_SELECT:
  388. iron_internal_gamepad_trigger_button(0, 8, 1);
  389. return 1;
  390. case AKEYCODE_BUTTON_START:
  391. iron_internal_gamepad_trigger_button(0, 9, 1);
  392. return 1;
  393. case AKEYCODE_BUTTON_THUMBL:
  394. iron_internal_gamepad_trigger_button(0, 10, 1);
  395. return 1;
  396. case AKEYCODE_BUTTON_THUMBR:
  397. iron_internal_gamepad_trigger_button(0, 11, 1);
  398. return 1;
  399. case AKEYCODE_BUTTON_MODE:
  400. iron_internal_gamepad_trigger_button(0, 16, 1);
  401. return 1;
  402. #endif
  403. case AKEYCODE_DPAD_UP: {
  404. #ifdef WITH_GAMEPAD
  405. if (isGamepadEvent(event)) {
  406. iron_internal_gamepad_trigger_button(0, 12, 1);
  407. return 1;
  408. }
  409. #endif
  410. iron_internal_keyboard_trigger_key_down(IRON_KEY_UP);
  411. return 1;
  412. }
  413. case AKEYCODE_DPAD_DOWN: {
  414. #ifdef WITH_GAMEPAD
  415. if (isGamepadEvent(event)) {
  416. iron_internal_gamepad_trigger_button(0, 13, 1);
  417. return 1;
  418. }
  419. #endif
  420. iron_internal_keyboard_trigger_key_down(IRON_KEY_DOWN);
  421. return 1;
  422. }
  423. case AKEYCODE_DPAD_LEFT: {
  424. #ifdef WITH_GAMEPAD
  425. if (isGamepadEvent(event)) {
  426. iron_internal_gamepad_trigger_button(0, 14, 1);
  427. return 1;
  428. }
  429. #endif
  430. iron_internal_keyboard_trigger_key_down(IRON_KEY_LEFT);
  431. return 1;
  432. }
  433. case AKEYCODE_DPAD_RIGHT: {
  434. #ifdef WITH_GAMEPAD
  435. if (isGamepadEvent(event)) {
  436. iron_internal_gamepad_trigger_button(0, 15, 1);
  437. return 1;
  438. }
  439. #endif
  440. iron_internal_keyboard_trigger_key_down(IRON_KEY_RIGHT);
  441. return 1;
  442. }
  443. case AKEYCODE_STAR:
  444. case AKEYCODE_NUMPAD_MULTIPLY:
  445. iron_internal_keyboard_trigger_key_down(IRON_KEY_MULTIPLY);
  446. iron_internal_keyboard_trigger_key_press('*');
  447. return 1;
  448. case AKEYCODE_POUND:
  449. iron_internal_keyboard_trigger_key_down(IRON_KEY_HASH);
  450. iron_internal_keyboard_trigger_key_press('#');
  451. return 1;
  452. case AKEYCODE_COMMA:
  453. case AKEYCODE_NUMPAD_COMMA:
  454. iron_internal_keyboard_trigger_key_down(IRON_KEY_COMMA);
  455. iron_internal_keyboard_trigger_key_press(',');
  456. return 1;
  457. case AKEYCODE_PERIOD:
  458. case AKEYCODE_NUMPAD_DOT:
  459. iron_internal_keyboard_trigger_key_down(IRON_KEY_PERIOD);
  460. iron_internal_keyboard_trigger_key_press('.');
  461. return 1;
  462. case AKEYCODE_SPACE:
  463. iron_internal_keyboard_trigger_key_down(IRON_KEY_SPACE);
  464. iron_internal_keyboard_trigger_key_press(' ');
  465. return 1;
  466. case AKEYCODE_MINUS:
  467. case AKEYCODE_NUMPAD_SUBTRACT:
  468. iron_internal_keyboard_trigger_key_down(IRON_KEY_HYPHEN_MINUS);
  469. iron_internal_keyboard_trigger_key_press('-');
  470. return 1;
  471. case AKEYCODE_EQUALS:
  472. case AKEYCODE_NUMPAD_EQUALS:
  473. iron_internal_keyboard_trigger_key_down(IRON_KEY_EQUALS);
  474. iron_internal_keyboard_trigger_key_press('=');
  475. return 1;
  476. case AKEYCODE_LEFT_BRACKET:
  477. case AKEYCODE_NUMPAD_LEFT_PAREN:
  478. iron_internal_keyboard_trigger_key_down(IRON_KEY_OPEN_BRACKET);
  479. iron_internal_keyboard_trigger_key_press('[');
  480. return 1;
  481. case AKEYCODE_RIGHT_BRACKET:
  482. case AKEYCODE_NUMPAD_RIGHT_PAREN:
  483. iron_internal_keyboard_trigger_key_down(IRON_KEY_CLOSE_BRACKET);
  484. iron_internal_keyboard_trigger_key_press(']');
  485. return 1;
  486. case AKEYCODE_BACKSLASH:
  487. iron_internal_keyboard_trigger_key_down(IRON_KEY_BACK_SLASH);
  488. iron_internal_keyboard_trigger_key_press('\\');
  489. return 1;
  490. case AKEYCODE_SEMICOLON:
  491. iron_internal_keyboard_trigger_key_down(IRON_KEY_SEMICOLON);
  492. iron_internal_keyboard_trigger_key_press(';');
  493. return 1;
  494. case AKEYCODE_APOSTROPHE:
  495. iron_internal_keyboard_trigger_key_down(IRON_KEY_QUOTE);
  496. iron_internal_keyboard_trigger_key_press('\'');
  497. return 1;
  498. case AKEYCODE_GRAVE:
  499. iron_internal_keyboard_trigger_key_down(IRON_KEY_BACK_QUOTE);
  500. iron_internal_keyboard_trigger_key_press('`');
  501. return 1;
  502. case AKEYCODE_SLASH:
  503. case AKEYCODE_NUMPAD_DIVIDE:
  504. iron_internal_keyboard_trigger_key_down(IRON_KEY_SLASH);
  505. iron_internal_keyboard_trigger_key_press('/');
  506. return 1;
  507. case AKEYCODE_AT:
  508. iron_internal_keyboard_trigger_key_down(IRON_KEY_AT);
  509. iron_internal_keyboard_trigger_key_press('@');
  510. return 1;
  511. case AKEYCODE_PLUS:
  512. case AKEYCODE_NUMPAD_ADD:
  513. iron_internal_keyboard_trigger_key_down(IRON_KEY_PLUS);
  514. iron_internal_keyboard_trigger_key_press('+');
  515. return 1;
  516. default:
  517. if (code >= AKEYCODE_NUMPAD_0 && code <= AKEYCODE_NUMPAD_9) {
  518. iron_internal_keyboard_trigger_key_down(code + IRON_KEY_NUMPAD_0 - AKEYCODE_NUMPAD_0);
  519. iron_internal_keyboard_trigger_key_press(code + IRON_KEY_NUMPAD_0 - AKEYCODE_NUMPAD_0);
  520. return 1;
  521. }
  522. else if (code >= AKEYCODE_0 && code <= AKEYCODE_9) {
  523. iron_internal_keyboard_trigger_key_down(code + IRON_KEY_0 - AKEYCODE_0);
  524. iron_internal_keyboard_trigger_key_press(code + IRON_KEY_0 - AKEYCODE_0);
  525. return 1;
  526. }
  527. else if (code >= AKEYCODE_A && code <= AKEYCODE_Z) {
  528. iron_internal_keyboard_trigger_key_down(code + IRON_KEY_A - AKEYCODE_A);
  529. iron_internal_keyboard_trigger_key_press(code + (shift ? 'A' : 'a') - AKEYCODE_A);
  530. return 1;
  531. }
  532. }
  533. }
  534. else if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_UP) {
  535. int shift = AKeyEvent_getMetaState(event) & AMETA_SHIFT_ON;
  536. if (shift) {
  537. switch (code) {
  538. case AKEYCODE_1:
  539. iron_internal_keyboard_trigger_key_up(IRON_KEY_EXCLAMATION);
  540. return 1;
  541. case AKEYCODE_4:
  542. iron_internal_keyboard_trigger_key_up(IRON_KEY_DOLLAR);
  543. return 1;
  544. case AKEYCODE_5:
  545. iron_internal_keyboard_trigger_key_up(IRON_KEY_PERCENT);
  546. return 1;
  547. case AKEYCODE_6:
  548. iron_internal_keyboard_trigger_key_up(IRON_KEY_CIRCUMFLEX);
  549. return 1;
  550. case AKEYCODE_7:
  551. iron_internal_keyboard_trigger_key_up(IRON_KEY_AMPERSAND);
  552. return 1;
  553. case AKEYCODE_9:
  554. iron_internal_keyboard_trigger_key_up(IRON_KEY_OPEN_PAREN);
  555. return 1;
  556. case AKEYCODE_0:
  557. iron_internal_keyboard_trigger_key_up(IRON_KEY_CLOSE_PAREN);
  558. return 1;
  559. case AKEYCODE_COMMA:
  560. iron_internal_keyboard_trigger_key_up(IRON_KEY_LESS_THAN);
  561. return 1;
  562. case AKEYCODE_PERIOD:
  563. iron_internal_keyboard_trigger_key_up(IRON_KEY_GREATER_THAN);
  564. return 1;
  565. case AKEYCODE_MINUS:
  566. iron_internal_keyboard_trigger_key_up(IRON_KEY_UNDERSCORE);
  567. return 1;
  568. case AKEYCODE_SLASH:
  569. iron_internal_keyboard_trigger_key_up(IRON_KEY_QUESTIONMARK);
  570. return 1;
  571. case AKEYCODE_BACKSLASH:
  572. iron_internal_keyboard_trigger_key_up(IRON_KEY_PIPE);
  573. return 1;
  574. case AKEYCODE_LEFT_BRACKET:
  575. iron_internal_keyboard_trigger_key_up(IRON_KEY_OPEN_CURLY_BRACKET);
  576. return 1;
  577. case AKEYCODE_RIGHT_BRACKET:
  578. iron_internal_keyboard_trigger_key_up(IRON_KEY_CLOSE_CURLY_BRACKET);
  579. return 1;
  580. case AKEYCODE_SEMICOLON:
  581. iron_internal_keyboard_trigger_key_up(IRON_KEY_COLON);
  582. return 1;
  583. case AKEYCODE_APOSTROPHE:
  584. iron_internal_keyboard_trigger_key_up(IRON_KEY_DOUBLE_QUOTE);
  585. return 1;
  586. case AKEYCODE_GRAVE:
  587. iron_internal_keyboard_trigger_key_up(IRON_KEY_TILDE);
  588. return 1;
  589. }
  590. }
  591. switch (code) {
  592. case AKEYCODE_SHIFT_LEFT:
  593. case AKEYCODE_SHIFT_RIGHT:
  594. iron_internal_keyboard_trigger_key_up(IRON_KEY_SHIFT);
  595. return 1;
  596. case AKEYCODE_DEL:
  597. iron_internal_keyboard_trigger_key_up(IRON_KEY_BACKSPACE);
  598. return 1;
  599. case AKEYCODE_ENTER:
  600. iron_internal_keyboard_trigger_key_up(IRON_KEY_RETURN);
  601. return 1;
  602. case AKEYCODE_BACK:
  603. iron_internal_keyboard_trigger_key_up(IRON_KEY_BACK);
  604. return 1;
  605. #ifdef WITH_GAMEPAD
  606. case AKEYCODE_DPAD_CENTER:
  607. case AKEYCODE_BUTTON_B:
  608. iron_internal_gamepad_trigger_button(0, 1, 0);
  609. return 1;
  610. case AKEYCODE_BUTTON_A:
  611. iron_internal_gamepad_trigger_button(0, 0, 0);
  612. return 1;
  613. case AKEYCODE_BUTTON_Y:
  614. iron_internal_gamepad_trigger_button(0, 3, 0);
  615. return 1;
  616. case AKEYCODE_BUTTON_X:
  617. iron_internal_gamepad_trigger_button(0, 2, 0);
  618. return 1;
  619. case AKEYCODE_BUTTON_L1:
  620. iron_internal_gamepad_trigger_button(0, 4, 0);
  621. return 1;
  622. case AKEYCODE_BUTTON_R1:
  623. iron_internal_gamepad_trigger_button(0, 5, 0);
  624. return 1;
  625. case AKEYCODE_BUTTON_L2:
  626. iron_internal_gamepad_trigger_button(0, 6, 0);
  627. return 1;
  628. case AKEYCODE_BUTTON_R2:
  629. iron_internal_gamepad_trigger_button(0, 7, 0);
  630. return 1;
  631. case AKEYCODE_BUTTON_SELECT:
  632. iron_internal_gamepad_trigger_button(0, 8, 0);
  633. return 1;
  634. case AKEYCODE_BUTTON_START:
  635. iron_internal_gamepad_trigger_button(0, 9, 0);
  636. return 1;
  637. case AKEYCODE_BUTTON_THUMBL:
  638. iron_internal_gamepad_trigger_button(0, 10, 0);
  639. return 1;
  640. case AKEYCODE_BUTTON_THUMBR:
  641. iron_internal_gamepad_trigger_button(0, 11, 0);
  642. return 1;
  643. case AKEYCODE_BUTTON_MODE:
  644. iron_internal_gamepad_trigger_button(0, 16, 0);
  645. return 1;
  646. #endif
  647. case AKEYCODE_DPAD_UP: {
  648. #ifdef WITH_GAMEPAD
  649. if (isGamepadEvent(event)) {
  650. iron_internal_gamepad_trigger_button(0, 12, 0);
  651. return 1;
  652. }
  653. #endif
  654. iron_internal_keyboard_trigger_key_up(IRON_KEY_UP);
  655. return 1;
  656. }
  657. case AKEYCODE_DPAD_DOWN: {
  658. #ifdef WITH_GAMEPAD
  659. if (isGamepadEvent(event)) {
  660. iron_internal_gamepad_trigger_button(0, 13, 0);
  661. return 1;
  662. }
  663. #endif
  664. iron_internal_keyboard_trigger_key_up(IRON_KEY_DOWN);
  665. return 1;
  666. }
  667. case AKEYCODE_DPAD_LEFT: {
  668. #ifdef WITH_GAMEPAD
  669. if (isGamepadEvent(event)) {
  670. iron_internal_gamepad_trigger_button(0, 14, 0);
  671. return 1;
  672. }
  673. #endif
  674. iron_internal_keyboard_trigger_key_up(IRON_KEY_LEFT);
  675. return 1;
  676. }
  677. case AKEYCODE_DPAD_RIGHT: {
  678. #ifdef WITH_GAMEPAD
  679. if (isGamepadEvent(event)) {
  680. iron_internal_gamepad_trigger_button(0, 15, 0);
  681. return 1;
  682. }
  683. #endif
  684. iron_internal_keyboard_trigger_key_up(IRON_KEY_RIGHT);
  685. return 1;
  686. }
  687. case AKEYCODE_STAR:
  688. case AKEYCODE_NUMPAD_MULTIPLY:
  689. iron_internal_keyboard_trigger_key_up(IRON_KEY_MULTIPLY);
  690. return 1;
  691. case AKEYCODE_POUND:
  692. iron_internal_keyboard_trigger_key_up(IRON_KEY_HASH);
  693. return 1;
  694. case AKEYCODE_COMMA:
  695. case AKEYCODE_NUMPAD_COMMA:
  696. iron_internal_keyboard_trigger_key_up(IRON_KEY_COMMA);
  697. return 1;
  698. case AKEYCODE_PERIOD:
  699. case AKEYCODE_NUMPAD_DOT:
  700. iron_internal_keyboard_trigger_key_up(IRON_KEY_PERIOD);
  701. return 1;
  702. case AKEYCODE_SPACE:
  703. iron_internal_keyboard_trigger_key_up(IRON_KEY_SPACE);
  704. return 1;
  705. case AKEYCODE_MINUS:
  706. case AKEYCODE_NUMPAD_SUBTRACT:
  707. iron_internal_keyboard_trigger_key_up(IRON_KEY_HYPHEN_MINUS);
  708. return 1;
  709. case AKEYCODE_EQUALS:
  710. case AKEYCODE_NUMPAD_EQUALS:
  711. iron_internal_keyboard_trigger_key_up(IRON_KEY_EQUALS);
  712. return 1;
  713. case AKEYCODE_LEFT_BRACKET:
  714. case AKEYCODE_NUMPAD_LEFT_PAREN:
  715. iron_internal_keyboard_trigger_key_up(IRON_KEY_OPEN_BRACKET);
  716. return 1;
  717. case AKEYCODE_RIGHT_BRACKET:
  718. case AKEYCODE_NUMPAD_RIGHT_PAREN:
  719. iron_internal_keyboard_trigger_key_up(IRON_KEY_CLOSE_BRACKET);
  720. return 1;
  721. case AKEYCODE_BACKSLASH:
  722. iron_internal_keyboard_trigger_key_up(IRON_KEY_BACK_SLASH);
  723. return 1;
  724. case AKEYCODE_SEMICOLON:
  725. iron_internal_keyboard_trigger_key_up(IRON_KEY_SEMICOLON);
  726. return 1;
  727. case AKEYCODE_APOSTROPHE:
  728. iron_internal_keyboard_trigger_key_up(IRON_KEY_QUOTE);
  729. return 1;
  730. case AKEYCODE_GRAVE:
  731. iron_internal_keyboard_trigger_key_up(IRON_KEY_BACK_QUOTE);
  732. return 1;
  733. case AKEYCODE_SLASH:
  734. case AKEYCODE_NUMPAD_DIVIDE:
  735. iron_internal_keyboard_trigger_key_up(IRON_KEY_SLASH);
  736. return 1;
  737. case AKEYCODE_AT:
  738. iron_internal_keyboard_trigger_key_up(IRON_KEY_AT);
  739. return 1;
  740. case AKEYCODE_PLUS:
  741. case AKEYCODE_NUMPAD_ADD:
  742. iron_internal_keyboard_trigger_key_up(IRON_KEY_PLUS);
  743. return 1;
  744. default: {
  745. if (code >= AKEYCODE_NUMPAD_0 && code <= AKEYCODE_NUMPAD_9) {
  746. iron_internal_keyboard_trigger_key_up(code + IRON_KEY_NUMPAD_0 - AKEYCODE_NUMPAD_0);
  747. return 1;
  748. }
  749. else if (code >= AKEYCODE_0 && code <= AKEYCODE_9) {
  750. iron_internal_keyboard_trigger_key_up(code + IRON_KEY_0 - AKEYCODE_0);
  751. return 1;
  752. }
  753. else if (code >= AKEYCODE_A && code <= AKEYCODE_Z) {
  754. iron_internal_keyboard_trigger_key_up(code + IRON_KEY_A - AKEYCODE_A);
  755. return 1;
  756. }
  757. }
  758. }
  759. }
  760. }
  761. return 0;
  762. }
  763. static void cmd(struct android_app *app, int32_t cmd) {
  764. switch (cmd) {
  765. case APP_CMD_SAVE_STATE:
  766. break;
  767. case APP_CMD_INIT_WINDOW:
  768. if (app->window != NULL) {
  769. if (!started) {
  770. started = true;
  771. }
  772. else {
  773. iron_vulkan_surface_destroyed();
  774. }
  775. updateAppForegroundStatus(true, appIsForeground);
  776. }
  777. break;
  778. case APP_CMD_TERM_WINDOW:
  779. updateAppForegroundStatus(false, appIsForeground);
  780. break;
  781. case APP_CMD_GAINED_FOCUS:
  782. // if (accelerometerSensor != NULL) {
  783. // ASensorEventQueue_enableSensor(sensorEventQueue, accelerometerSensor);
  784. // ASensorEventQueue_setEventRate(sensorEventQueue, accelerometerSensor, (1000L / 60) * 1000);
  785. // }
  786. // if (gyroSensor != NULL) {
  787. // ASensorEventQueue_enableSensor(sensorEventQueue, gyroSensor);
  788. // ASensorEventQueue_setEventRate(sensorEventQueue, gyroSensor, (1000L / 60) * 1000);
  789. // }
  790. break;
  791. case APP_CMD_LOST_FOCUS:
  792. // if (accelerometerSensor != NULL) {
  793. // ASensorEventQueue_disableSensor(sensorEventQueue, accelerometerSensor);
  794. // }
  795. // if (gyroSensor != NULL) {
  796. // ASensorEventQueue_disableSensor(sensorEventQueue, gyroSensor);
  797. // }
  798. break;
  799. case APP_CMD_START:
  800. updateAppForegroundStatus(displayIsInitialized, true);
  801. break;
  802. case APP_CMD_RESUME:
  803. iron_internal_resume_callback();
  804. paused = false;
  805. break;
  806. case APP_CMD_PAUSE:
  807. iron_internal_pause_callback();
  808. paused = true;
  809. break;
  810. case APP_CMD_STOP:
  811. updateAppForegroundStatus(displayIsInitialized, false);
  812. break;
  813. case APP_CMD_DESTROY:
  814. iron_internal_shutdown_callback();
  815. break;
  816. case APP_CMD_CONFIG_CHANGED: {
  817. break;
  818. }
  819. }
  820. }
  821. static void resize(ANativeActivity *activity, ANativeWindow *window) {
  822. activityJustResized = true;
  823. }
  824. ANativeActivity *iron_android_get_activity(void) {
  825. return activity;
  826. }
  827. AAssetManager *iron_android_get_asset_manager(void) {
  828. return activity->assetManager;
  829. }
  830. jclass iron_android_find_class(JNIEnv *env, const char *name) {
  831. jobject nativeActivity = activity->clazz;
  832. jclass acl = (*env)->GetObjectClass(env, nativeActivity);
  833. jmethodID getClassLoader = (*env)->GetMethodID(env, acl, "getClassLoader", "()Ljava/lang/ClassLoader;");
  834. jobject cls = (*env)->CallObjectMethod(env, nativeActivity, getClassLoader);
  835. jclass classLoader = (*env)->FindClass(env, "java/lang/ClassLoader");
  836. jmethodID findClass = (*env)->GetMethodID(env, classLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
  837. jstring strClassName = (*env)->NewStringUTF(env, name);
  838. jclass clazz = (jclass)((*env)->CallObjectMethod(env, cls, findClass, strClassName));
  839. (*env)->DeleteLocalRef(env, strClassName);
  840. return clazz;
  841. }
  842. JNIEXPORT void JNICALL Java_org_armory3d_IronActivity_nativeIronKeyPress(JNIEnv *env, jobject jobj, jstring chars) {
  843. const jchar *text = (*env)->GetStringChars(env, chars, NULL);
  844. const jsize length = (*env)->GetStringLength(env, chars);
  845. iron_mutex_lock(&unicode_mutex);
  846. for (jsize i = 0; i < length && unicode_stack_index < 256; ++i) {
  847. unicode_stack[unicode_stack_index++] = text[i];
  848. }
  849. iron_mutex_unlock(&unicode_mutex);
  850. (*env)->ReleaseStringChars(env, chars, text);
  851. }
  852. void IronAndroidKeyboardInit() {
  853. JNIEnv *env;
  854. (*activity->vm)->AttachCurrentThread(activity->vm, &env, NULL);
  855. jclass clazz = iron_android_find_class(env, "org.armory3d.IronActivity");
  856. JNINativeMethod methodTable[] = {{"nativeIronKeyPress", "(Ljava/lang/String;)V", (void *)Java_org_armory3d_IronActivity_nativeIronKeyPress}};
  857. int methodTableSize = sizeof(methodTable) / sizeof(methodTable[0]);
  858. int failure = (*env)->RegisterNatives(env, clazz, methodTable, methodTableSize);
  859. if (failure != 0) {
  860. iron_log("Failed to register IronActivity.nativeIronKeyPress");
  861. }
  862. (*activity->vm)->DetachCurrentThread(activity->vm);
  863. }
  864. void iron_keyboard_show() {
  865. keyboard_active = true;
  866. JNIEnv *env;
  867. (*activity->vm)->AttachCurrentThread(activity->vm, &env, NULL);
  868. jclass ironActivityClass = iron_android_find_class(env, "org.armory3d.IronActivity");
  869. (*env)->CallStaticVoidMethod(env, ironActivityClass, (*env)->GetStaticMethodID(env, ironActivityClass, "showKeyboard", "()V"));
  870. (*activity->vm)->DetachCurrentThread(activity->vm);
  871. }
  872. void iron_keyboard_hide() {
  873. keyboard_active = false;
  874. JNIEnv *env;
  875. (*activity->vm)->AttachCurrentThread(activity->vm, &env, NULL);
  876. jclass ironActivityClass = iron_android_find_class(env, "org.armory3d.IronActivity");
  877. (*env)->CallStaticVoidMethod(env, ironActivityClass, (*env)->GetStaticMethodID(env, ironActivityClass, "hideKeyboard", "()V"));
  878. (*activity->vm)->DetachCurrentThread(activity->vm);
  879. }
  880. bool iron_keyboard_active() {
  881. return keyboard_active;
  882. }
  883. void iron_load_url(const char *url) {
  884. JNIEnv *env;
  885. (*activity->vm)->AttachCurrentThread(activity->vm, &env, NULL);
  886. jclass ironActivityClass = iron_android_find_class(env, "org.armory3d.IronActivity");
  887. jstring jurl = (*env)->NewStringUTF(env, url);
  888. (*env)->CallStaticVoidMethod(env, ironActivityClass, (*env)->GetStaticMethodID(env, ironActivityClass, "loadURL", "(Ljava/lang/String;)V"), jurl);
  889. (*activity->vm)->DetachCurrentThread(activity->vm);
  890. }
  891. const char *iron_language() {
  892. JNIEnv *env;
  893. (*activity->vm)->AttachCurrentThread(activity->vm, &env, NULL);
  894. jclass ironActivityClass = iron_android_find_class(env, "org.armory3d.IronActivity");
  895. jstring s = (jstring)(*env)->CallStaticObjectMethod(env, ironActivityClass,
  896. (*env)->GetStaticMethodID(env, ironActivityClass, "getLanguage", "()Ljava/lang/String;"));
  897. const char *str = (*env)->GetStringUTFChars(env, s, 0);
  898. (*activity->vm)->DetachCurrentThread(activity->vm);
  899. return str;
  900. }
  901. int iron_android_width() {
  902. int width, height;
  903. if (iron_vulkan_get_size(&width, &height)) {
  904. return width;
  905. }
  906. return ANativeWindow_getWidth(app->window);
  907. }
  908. int iron_android_height() {
  909. int width, height;
  910. if (iron_vulkan_get_size(&width, &height)) {
  911. return height;
  912. }
  913. return ANativeWindow_getHeight(app->window);
  914. }
  915. const char *iron_internal_save_path() {
  916. return iron_android_get_activity()->internalDataPath;
  917. }
  918. const char *iron_system_id() {
  919. return "Android";
  920. }
  921. const char **iron_video_formats() {
  922. return videoFormats;
  923. }
  924. void iron_set_keep_screen_on(bool on) {
  925. if (on) {
  926. ANativeActivity_setWindowFlags(activity, AWINDOW_FLAG_KEEP_SCREEN_ON, 0);
  927. }
  928. else {
  929. ANativeActivity_setWindowFlags(activity, 0, AWINDOW_FLAG_KEEP_SCREEN_ON);
  930. }
  931. }
  932. double iron_frequency() {
  933. return 1000000.0;
  934. }
  935. uint64_t iron_timestamp() {
  936. struct timeval now;
  937. gettimeofday(&now, NULL);
  938. return (uint64_t)(now.tv_sec - start_sec) * 1000000 + (uint64_t)(now.tv_usec);
  939. }
  940. double iron_time() {
  941. struct timeval now;
  942. gettimeofday(&now, NULL);
  943. return (double)(now.tv_sec - start_sec) + (now.tv_usec / 1000000.0);
  944. }
  945. bool iron_internal_handle_messages(void) {
  946. iron_mutex_lock(&unicode_mutex);
  947. for (int i = 0; i < unicode_stack_index; ++i) {
  948. iron_internal_keyboard_trigger_key_press(unicode_stack[i]);
  949. }
  950. unicode_stack_index = 0;
  951. iron_mutex_unlock(&unicode_mutex);
  952. int ident;
  953. int events;
  954. struct android_poll_source *source;
  955. while ((ident = ALooper_pollOnce(paused ? -1 : 0, NULL, &events, (void **)&source)) >= 0) {
  956. if (source != NULL) {
  957. source->process(app, source);
  958. }
  959. if (ident == LOOPER_ID_USER) {
  960. // if (accelerometerSensor != NULL) {
  961. // ASensorEvent event;
  962. // while (ASensorEventQueue_getEvents(sensorEventQueue, &event, 1) > 0) {
  963. // if (event.type == ASENSOR_TYPE_ACCELEROMETER) {
  964. // // iron_internal_on_acceleration(event.acceleration.x, event.acceleration.y, event.acceleration.z);
  965. // }
  966. // else if (event.type == ASENSOR_TYPE_GYROSCOPE) {
  967. // // iron_internal_on_rotation(event.vector.x, event.vector.y, event.vector.z);
  968. // }
  969. // }
  970. // }
  971. }
  972. if (app->destroyRequested != 0) {
  973. iron_stop();
  974. return true;
  975. }
  976. }
  977. if (activityJustResized && app->window != NULL) {
  978. activityJustResized = false;
  979. int32_t width = iron_android_width();
  980. int32_t height = iron_android_height();
  981. gpu_resize(width, height);
  982. iron_internal_call_resize_callback(width, height);
  983. }
  984. return true;
  985. }
  986. bool iron_mouse_can_lock(void) {
  987. return false;
  988. }
  989. void iron_mouse_show() {}
  990. void iron_mouse_hide() {}
  991. void iron_mouse_set_position(int x, int y) {}
  992. void iron_mouse_get_position(int *x, int *y) {
  993. x = 0;
  994. y = 0;
  995. }
  996. void iron_mouse_set_cursor(iron_cursor_t cursor_index) {}
  997. void initAndroidFileReader();
  998. // void IronAndroidVideoInit();
  999. void android_main(struct android_app *application) {
  1000. app_dummy();
  1001. struct timeval now;
  1002. gettimeofday(&now, NULL);
  1003. start_sec = now.tv_sec;
  1004. app = application;
  1005. activity = application->activity;
  1006. initAndroidFileReader();
  1007. // IronAndroidVideoInit();
  1008. IronAndroidKeyboardInit();
  1009. application->onAppCmd = cmd;
  1010. application->onInputEvent = input;
  1011. activity->callbacks->onNativeWindowResized = resize;
  1012. // sensorManager = ASensorManager_getInstance();
  1013. // accelerometerSensor = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_ACCELEROMETER);
  1014. // gyroSensor = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_GYROSCOPE);
  1015. // sensorEventQueue = ASensorManager_createEventQueue(sensorManager, application->looper, LOOPER_ID_USER, NULL, NULL);
  1016. JNIEnv *env = NULL;
  1017. (*iron_android_get_activity()->vm)->AttachCurrentThread(iron_android_get_activity()->vm, &env, NULL);
  1018. // jclass ironMoviePlayerClass = iron_android_find_class(env, "org.armory3d.IronMoviePlayer");
  1019. // jmethodID updateAll = (*env)->GetStaticMethodID(env, ironMoviePlayerClass, "updateAll", "()V");
  1020. while (!started) {
  1021. iron_internal_handle_messages();
  1022. // (*env)->CallStaticVoidMethod(env, ironMoviePlayerClass, updateAll);
  1023. }
  1024. (*iron_android_get_activity()->vm)->DetachCurrentThread(iron_android_get_activity()->vm);
  1025. kickstart(0, NULL);
  1026. (*activity->vm)->AttachCurrentThread(activity->vm, &env, NULL);
  1027. jclass ironActivityClass = iron_android_find_class(env, "org.armory3d.IronActivity");
  1028. jmethodID FinishHim = (*env)->GetStaticMethodID(env, ironActivityClass, "stop", "()V");
  1029. (*env)->CallStaticVoidMethod(env, ironActivityClass, FinishHim);
  1030. (*activity->vm)->DetachCurrentThread(activity->vm);
  1031. }
  1032. void iron_init(iron_window_options_t *win) {
  1033. iron_mutex_init(&unicode_mutex);
  1034. gpu_init(win->depth_bits, true);
  1035. android_check_permissions();
  1036. #ifdef WITH_GAMEPAD
  1037. iron_internal_gamepad_trigger_connect(0);
  1038. #endif
  1039. }
  1040. void iron_internal_shutdown(void) {
  1041. #ifdef WITH_GAMEPAD
  1042. iron_internal_gamepad_trigger_disconnect(0);
  1043. #endif
  1044. }
  1045. void initAndroidFileReader(void) {
  1046. if (activity == NULL) {
  1047. iron_error("Android activity is NULL");
  1048. return;
  1049. }
  1050. JNIEnv *env;
  1051. (*activity->vm)->AttachCurrentThread(activity->vm, &env, NULL);
  1052. jclass android_app_NativeActivity = (*env)->FindClass(env, "android/app/NativeActivity");
  1053. jmethodID getExternalFilesDir = (*env)->GetMethodID(env, android_app_NativeActivity, "getExternalFilesDir", "(Ljava/lang/String;)Ljava/io/File;");
  1054. jobject file = (*env)->CallObjectMethod(env, activity->clazz, getExternalFilesDir, NULL);
  1055. jclass java_io_File = (*env)->FindClass(env, "java/io/File");
  1056. jmethodID getPath = (*env)->GetMethodID(env, java_io_File, "getPath", "()Ljava/lang/String;");
  1057. jstring jPath = (*env)->CallObjectMethod(env, file, getPath);
  1058. const char *path = (*env)->GetStringUTFChars(env, jPath, NULL);
  1059. char *externalFilesDir = malloc(strlen(path) + 1);
  1060. strcpy(externalFilesDir, path);
  1061. iron_internal_set_files_location(externalFilesDir);
  1062. (*env)->ReleaseStringUTFChars(env, jPath, path);
  1063. (*env)->DeleteLocalRef(env, jPath);
  1064. (*activity->vm)->DetachCurrentThread(activity->vm);
  1065. }
  1066. static bool iron_aasset_reader_close(iron_file_reader_t *reader) {
  1067. AAsset_close((struct AAsset *)reader->data);
  1068. return true;
  1069. }
  1070. static size_t iron_aasset_reader_read(iron_file_reader_t *reader, void *data, size_t size) {
  1071. return AAsset_read((struct AAsset *)reader->data, data, size);
  1072. }
  1073. static size_t iron_aasset_reader_pos(iron_file_reader_t *reader) {
  1074. return (size_t)AAsset_seek((struct AAsset *)reader->data, 0, SEEK_CUR);
  1075. }
  1076. static bool iron_aasset_reader_seek(iron_file_reader_t *reader, size_t pos) {
  1077. AAsset_seek((struct AAsset *)reader->data, pos, SEEK_SET);
  1078. return true;
  1079. }
  1080. static bool iron_aasset_reader_open(iron_file_reader_t *reader, const char *filename, int type) {
  1081. if (type != IRON_FILE_TYPE_ASSET)
  1082. return false;
  1083. reader->data = AAssetManager_open(iron_android_get_asset_manager(), filename, AASSET_MODE_RANDOM);
  1084. if (reader->data == NULL)
  1085. return false;
  1086. reader->size = AAsset_getLength((struct AAsset *)reader->data);
  1087. reader->close = iron_aasset_reader_close;
  1088. reader->read = iron_aasset_reader_read;
  1089. reader->pos = iron_aasset_reader_pos;
  1090. reader->seek = iron_aasset_reader_seek;
  1091. return true;
  1092. }
  1093. bool iron_file_reader_open(iron_file_reader_t *reader, const char *filename, int type) {
  1094. memset(reader, 0, sizeof(*reader));
  1095. return iron_internal_file_reader_open(reader, filename, type) || iron_aasset_reader_open(reader, filename, type);
  1096. }
  1097. int iron_hardware_threads(void) {
  1098. return sysconf(_SC_NPROCESSORS_ONLN);
  1099. }
  1100. int iron_window_x() {
  1101. return 0;
  1102. }
  1103. int iron_window_y() {
  1104. return 0;
  1105. }
  1106. int iron_android_width();
  1107. int iron_window_width() {
  1108. return iron_android_width();
  1109. }
  1110. int iron_android_height();
  1111. int iron_window_height() {
  1112. return iron_android_height();
  1113. }
  1114. void iron_window_resize(int width, int height) {}
  1115. void iron_window_move(int x, int y) {}
  1116. void iron_window_change_mode(iron_window_mode_t mode) {}
  1117. void iron_window_destroy() {}
  1118. void iron_window_show() {}
  1119. void iron_window_hide() {}
  1120. void iron_window_create(iron_window_options_t *win) {}
  1121. void iron_window_set_title(const char *title) {
  1122. strcpy(android_title, title);
  1123. }
  1124. void iron_window_set_resize_callback(void (*callback)(int x, int y, void *data), void *data) {
  1125. resizeCallback = callback;
  1126. resizeCallbackData = data;
  1127. }
  1128. void iron_internal_call_resize_callback(int width, int height) {
  1129. if (resizeCallback != NULL) {
  1130. resizeCallback(width, height, resizeCallbackData);
  1131. }
  1132. }
  1133. void iron_window_set_close_callback(bool (*callback)(void *), void *data) {}
  1134. iron_window_mode_t iron_window_get_mode() {
  1135. return IRON_WINDOW_MODE_FULLSCREEN;
  1136. }
  1137. int iron_window_display() {
  1138. return 0;
  1139. }
  1140. #ifdef WITH_GAMEPAD
  1141. static bool isGamepadEvent(AInputEvent *event) {
  1142. return ((AInputEvent_getSource(event) & AINPUT_SOURCE_GAMEPAD) == AINPUT_SOURCE_GAMEPAD ||
  1143. (AInputEvent_getSource(event) & AINPUT_SOURCE_JOYSTICK) == AINPUT_SOURCE_JOYSTICK ||
  1144. (AInputEvent_getSource(event) & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD);
  1145. }
  1146. const char *iron_gamepad_vendor(int gamepad) {
  1147. return "Google";
  1148. }
  1149. const char *iron_gamepad_product_name(int gamepad) {
  1150. return "gamepad";
  1151. }
  1152. bool iron_gamepad_connected(int num) {
  1153. return num == 0;
  1154. }
  1155. void iron_gamepad_rumble(int gamepad, float left, float right) {}
  1156. #endif
  1157. bool _save_and_quit_callback_internal() {
  1158. return false;
  1159. }
  1160. volatile int iron_exec_async_done = 1;
  1161. void iron_exec_async(const char *path, char *argv[]) {}