android_system.c 39 KB

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