2
0

godot_android.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966
  1. /*************************************************************************/
  2. /* godot_android.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /*************************************************************************/
  30. #ifdef ANDROID_NATIVE_ACTIVITY
  31. #include <errno.h>
  32. #include <jni.h>
  33. #include <EGL/egl.h>
  34. #include <GLES2/gl2.h>
  35. #include "file_access_android.h"
  36. #include "globals.h"
  37. #include "main/main.h"
  38. #include "os_android.h"
  39. #include <android/log.h>
  40. #include <android/sensor.h>
  41. #include <android/window.h>
  42. #include <android_native_app_glue.h>
  43. #include <stdlib.h>
  44. #include <string.h>
  45. #include <unistd.h>
  46. #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "godot", __VA_ARGS__))
  47. #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "godot", __VA_ARGS__))
  48. extern "C" {
  49. JNIEXPORT void JNICALL Java_org_godotengine_godot_Godot_registerSingleton(JNIEnv *env, jobject obj, jstring name, jobject p_object);
  50. JNIEXPORT void JNICALL Java_org_godotengine_godot_Godot_registerMethod(JNIEnv *env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args);
  51. JNIEXPORT jstring JNICALL Java_org_godotengine_godot_Godot_getGlobal(JNIEnv *env, jobject obj, jstring path);
  52. };
  53. class JNISingleton : public Object {
  54. OBJ_TYPE(JNISingleton, Object);
  55. struct MethodData {
  56. jmethodID method;
  57. Variant::Type ret_type;
  58. Vector<Variant::Type> argtypes;
  59. };
  60. jobject instance;
  61. Map<StringName, MethodData> method_map;
  62. JNIEnv *env;
  63. public:
  64. void update_env(JNIEnv *p_env) { env = p_env; }
  65. virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
  66. r_error.error = Variant::CallError::CALL_OK;
  67. Map<StringName, MethodData>::Element *E = method_map.find(p_method);
  68. if (!E) {
  69. r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
  70. return Variant();
  71. }
  72. int ac = E->get().argtypes.size();
  73. if (ac < p_argcount) {
  74. r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
  75. r_error.argument = ac;
  76. return Variant();
  77. }
  78. if (ac > p_argcount) {
  79. r_error.error = Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
  80. r_error.argument = ac;
  81. return Variant();
  82. }
  83. for (int i = 0; i < p_argcount; i++) {
  84. if (!Variant::can_convert(p_args[i]->get_type(), E->get().argtypes[i])) {
  85. r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
  86. r_error.argument = i;
  87. r_error.expected = E->get().argtypes[i];
  88. }
  89. }
  90. jvalue *v = NULL;
  91. if (p_argcount) {
  92. v = (jvalue *)alloca(sizeof(jvalue) * p_argcount);
  93. }
  94. for (int i = 0; i < p_argcount; i++) {
  95. switch (E->get().argtypes[i]) {
  96. case Variant::BOOL: {
  97. v[i].z = *p_args[i];
  98. } break;
  99. case Variant::INT: {
  100. v[i].i = *p_args[i];
  101. } break;
  102. case Variant::REAL: {
  103. v[i].f = *p_args[i];
  104. } break;
  105. case Variant::STRING: {
  106. String s = *p_args[i];
  107. jstring jStr = env->NewStringUTF(s.utf8().get_data());
  108. v[i].l = jStr;
  109. } break;
  110. case Variant::STRING_ARRAY: {
  111. DVector<String> sarray = *p_args[i];
  112. jobjectArray arr = env->NewObjectArray(sarray.size(), env->FindClass("java/lang/String"), env->NewStringUTF(""));
  113. for (int j = 0; j < sarray.size(); j++) {
  114. env->SetObjectArrayElement(arr, j, env->NewStringUTF(sarray[i].utf8().get_data()));
  115. }
  116. v[i].l = arr;
  117. } break;
  118. case Variant::INT_ARRAY: {
  119. DVector<int> array = *p_args[i];
  120. jintArray arr = env->NewIntArray(array.size());
  121. DVector<int>::Read r = array.read();
  122. env->SetIntArrayRegion(arr, 0, array.size(), r.ptr());
  123. v[i].l = arr;
  124. } break;
  125. case Variant::REAL_ARRAY: {
  126. DVector<float> array = *p_args[i];
  127. jfloatArray arr = env->NewFloatArray(array.size());
  128. DVector<float>::Read r = array.read();
  129. env->SetFloatArrayRegion(arr, 0, array.size(), r.ptr());
  130. v[i].l = arr;
  131. } break;
  132. default: {
  133. ERR_FAIL_V(Variant());
  134. } break;
  135. }
  136. }
  137. Variant ret;
  138. switch (E->get().ret_type) {
  139. case Variant::NIL: {
  140. env->CallVoidMethodA(instance, E->get().method, v);
  141. } break;
  142. case Variant::BOOL: {
  143. ret = env->CallBooleanMethodA(instance, E->get().method, v);
  144. } break;
  145. case Variant::INT: {
  146. ret = env->CallIntMethodA(instance, E->get().method, v);
  147. } break;
  148. case Variant::REAL: {
  149. ret = env->CallFloatMethodA(instance, E->get().method, v);
  150. } break;
  151. case Variant::STRING: {
  152. jobject o = env->CallObjectMethodA(instance, E->get().method, v);
  153. String singname = env->GetStringUTFChars((jstring)o, NULL);
  154. } break;
  155. case Variant::STRING_ARRAY: {
  156. jobjectArray arr = (jobjectArray)env->CallObjectMethodA(instance, E->get().method, v);
  157. int stringCount = env->GetArrayLength(arr);
  158. DVector<String> sarr;
  159. for (int i = 0; i < stringCount; i++) {
  160. jstring string = (jstring)env->GetObjectArrayElement(arr, i);
  161. const char *rawString = env->GetStringUTFChars(string, 0);
  162. sarr.push_back(String(rawString));
  163. }
  164. ret = sarr;
  165. } break;
  166. case Variant::INT_ARRAY: {
  167. jintArray arr = (jintArray)env->CallObjectMethodA(instance, E->get().method, v);
  168. int fCount = env->GetArrayLength(arr);
  169. DVector<int> sarr;
  170. sarr.resize(fCount);
  171. DVector<int>::Write w = sarr.write();
  172. env->GetIntArrayRegion(arr, 0, fCount, w.ptr());
  173. w = DVector<int>::Write();
  174. ret = sarr;
  175. } break;
  176. case Variant::REAL_ARRAY: {
  177. jfloatArray arr = (jfloatArray)env->CallObjectMethodA(instance, E->get().method, v);
  178. int fCount = env->GetArrayLength(arr);
  179. DVector<float> sarr;
  180. sarr.resize(fCount);
  181. DVector<float>::Write w = sarr.write();
  182. env->GetFloatArrayRegion(arr, 0, fCount, w.ptr());
  183. w = DVector<float>::Write();
  184. ret = sarr;
  185. } break;
  186. default: {
  187. ERR_FAIL_V(Variant());
  188. } break;
  189. }
  190. return ret;
  191. }
  192. jobject get_instance() const {
  193. return instance;
  194. }
  195. void set_instance(jobject p_instance) {
  196. instance = p_instance;
  197. }
  198. void add_method(const StringName &p_name, jmethodID p_method, const Vector<Variant::Type> &p_args, Variant::Type p_ret_type) {
  199. MethodData md;
  200. md.method = p_method;
  201. md.argtypes = p_args;
  202. md.ret_type = p_ret_type;
  203. method_map[p_name] = md;
  204. }
  205. JNISingleton() {}
  206. };
  207. //JNIEnv *JNISingleton::env=NULL;
  208. static HashMap<String, JNISingleton *> jni_singletons;
  209. struct engine {
  210. struct android_app *app;
  211. OS_Android *os;
  212. JNIEnv *jni;
  213. ASensorManager *sensorManager;
  214. const ASensor *accelerometerSensor;
  215. const ASensor *gravitySensor;
  216. const ASensor *magnetometerSensor;
  217. const ASensor *gyroscopeSensor;
  218. ASensorEventQueue *sensorEventQueue;
  219. bool display_active;
  220. bool requested_quit;
  221. int animating;
  222. EGLDisplay display;
  223. EGLSurface surface;
  224. EGLContext context;
  225. int32_t width;
  226. int32_t height;
  227. };
  228. /**
  229. * Initialize an EGL context for the current display.
  230. */
  231. static int engine_init_display(struct engine *engine, bool p_gl2) {
  232. // initialize OpenGL ES and EGL
  233. /*
  234. * Here specify the attributes of the desired configuration.
  235. * Below, we select an EGLConfig with at least 8 bits per color
  236. * component compatible with on-screen windows
  237. */
  238. const EGLint gl2_attribs[] = {
  239. // EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
  240. EGL_BLUE_SIZE, 4,
  241. EGL_GREEN_SIZE, 4,
  242. EGL_RED_SIZE, 4,
  243. EGL_ALPHA_SIZE, 0,
  244. EGL_DEPTH_SIZE, 16,
  245. EGL_STENCIL_SIZE, EGL_DONT_CARE,
  246. EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
  247. EGL_NONE
  248. };
  249. const EGLint gl1_attribs[] = {
  250. // EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
  251. EGL_BLUE_SIZE, 4,
  252. EGL_GREEN_SIZE, 4,
  253. EGL_RED_SIZE, 4,
  254. EGL_ALPHA_SIZE, 0,
  255. EGL_DEPTH_SIZE, 16,
  256. EGL_STENCIL_SIZE, EGL_DONT_CARE,
  257. EGL_NONE
  258. };
  259. const EGLint *attribs = p_gl2 ? gl2_attribs : gl1_attribs;
  260. EGLint w, h, dummy, format;
  261. EGLint numConfigs;
  262. EGLConfig config;
  263. EGLSurface surface;
  264. EGLContext context;
  265. EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  266. eglInitialize(display, 0, 0);
  267. /* Here, the application chooses the configuration it desires. In this
  268. * sample, we have a very simplified selection process, where we pick
  269. * the first EGLConfig that matches our criteria */
  270. eglChooseConfig(display, attribs, &config, 1, &numConfigs);
  271. LOGI("Num configs: %i\n", numConfigs);
  272. /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
  273. * guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
  274. * As soon as we picked a EGLConfig, we can safely reconfigure the
  275. * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
  276. eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
  277. ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format);
  278. //ANativeWindow_setFlags(engine->app->window, 0, 0, format|);
  279. surface = eglCreateWindowSurface(display, config, engine->app->window, NULL);
  280. const EGLint context_attribs[] = {
  281. EGL_CONTEXT_CLIENT_VERSION, 2,
  282. EGL_NONE
  283. };
  284. context = eglCreateContext(display, config, EGL_NO_CONTEXT, p_gl2 ? context_attribs : NULL);
  285. if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
  286. LOGW("Unable to eglMakeCurrent");
  287. return -1;
  288. }
  289. eglQuerySurface(display, surface, EGL_WIDTH, &w);
  290. eglQuerySurface(display, surface, EGL_HEIGHT, &h);
  291. //engine->os->set_egl_extensions(eglQueryString(display,EGL_EXTENSIONS));
  292. engine->os->init_video_mode(w, h);
  293. engine->display = display;
  294. engine->context = context;
  295. engine->surface = surface;
  296. engine->width = w;
  297. engine->height = h;
  298. engine->display_active = true;
  299. //engine->state.angle = 0;
  300. // Initialize GL state.
  301. //glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
  302. glEnable(GL_CULL_FACE);
  303. // glShadeModel(GL_SMOOTH);
  304. glDisable(GL_DEPTH_TEST);
  305. LOGI("GL Version: %s - %s %s\n", glGetString(GL_VERSION), glGetString(GL_VENDOR), glGetString(GL_RENDERER));
  306. return 0;
  307. }
  308. static void engine_draw_frame(struct engine *engine) {
  309. if (engine->display == NULL) {
  310. // No display.
  311. return;
  312. }
  313. // Just fill the screen with a color.
  314. //glClearColor(0,1,0,1);
  315. //glClear(GL_COLOR_BUFFER_BIT);
  316. if (engine->os && engine->os->main_loop_iterate() == true) {
  317. engine->requested_quit = true;
  318. return; //should exit instead
  319. }
  320. eglSwapBuffers(engine->display, engine->surface);
  321. }
  322. static void engine_term_display(struct engine *engine) {
  323. if (engine->display != EGL_NO_DISPLAY) {
  324. eglMakeCurrent(engine->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
  325. if (engine->context != EGL_NO_CONTEXT) {
  326. eglDestroyContext(engine->display, engine->context);
  327. }
  328. if (engine->surface != EGL_NO_SURFACE) {
  329. eglDestroySurface(engine->display, engine->surface);
  330. }
  331. eglTerminate(engine->display);
  332. }
  333. engine->animating = 0;
  334. engine->display = EGL_NO_DISPLAY;
  335. engine->context = EGL_NO_CONTEXT;
  336. engine->surface = EGL_NO_SURFACE;
  337. engine->display_active = false;
  338. }
  339. /**
  340. * Process the next input event.
  341. */
  342. static int32_t engine_handle_input(struct android_app *app, AInputEvent *event) {
  343. struct engine *engine = (struct engine *)app->userData;
  344. if (!engine->os)
  345. return 0;
  346. switch (AInputEvent_getType(event)) {
  347. case AINPUT_EVENT_TYPE_KEY: {
  348. int ac = AKeyEvent_getAction(event);
  349. switch (ac) {
  350. case AKEY_EVENT_ACTION_DOWN: {
  351. int32_t code = AKeyEvent_getKeyCode(event);
  352. if (code == AKEYCODE_BACK) {
  353. //AInputQueue_finishEvent(AInputQueue* queue, AInputEvent* event, int handled);
  354. if (engine->os)
  355. engine->os->main_loop_request_quit();
  356. return 1;
  357. }
  358. } break;
  359. case AKEY_EVENT_ACTION_UP: {
  360. } break;
  361. }
  362. } break;
  363. case AINPUT_EVENT_TYPE_MOTION: {
  364. Vector<OS_Android::TouchPos> touchvec;
  365. int pc = AMotionEvent_getPointerCount(event);
  366. touchvec.resize(pc);
  367. for (int i = 0; i < pc; i++) {
  368. touchvec[i].pos.x = AMotionEvent_getX(event, i);
  369. touchvec[i].pos.y = AMotionEvent_getY(event, i);
  370. touchvec[i].id = AMotionEvent_getPointerId(event, i);
  371. }
  372. //System.out.printf("gaction: %d\n",event.getAction());
  373. int pidx = (AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> 8;
  374. switch (AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_MASK) {
  375. case AMOTION_EVENT_ACTION_DOWN: {
  376. engine->os->process_touch(0, 0, touchvec);
  377. //System.out.printf("action down at: %f,%f\n", event.getX(),event.getY());
  378. } break;
  379. case AMOTION_EVENT_ACTION_MOVE: {
  380. engine->os->process_touch(1, 0, touchvec);
  381. //for(int i=0;i<event.getPointerCount();i++) {
  382. // System.out.printf("%d - moved to: %f,%f\n",i, event.getX(i),event.getY(i));
  383. //}
  384. } break;
  385. case AMOTION_EVENT_ACTION_POINTER_UP: {
  386. engine->os->process_touch(4, pidx, touchvec);
  387. //System.out.printf("%d - s.up at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
  388. } break;
  389. case AMOTION_EVENT_ACTION_POINTER_DOWN: {
  390. engine->os->process_touch(3, pidx, touchvec);
  391. //System.out.printf("%d - s.down at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
  392. } break;
  393. case AMOTION_EVENT_ACTION_CANCEL:
  394. case AMOTION_EVENT_ACTION_UP: {
  395. engine->os->process_touch(2, 0, touchvec);
  396. //for(int i=0;i<event.getPointerCount();i++) {
  397. // System.out.printf("%d - up! %f,%f\n",i, event.getX(i),event.getY(i));
  398. //}
  399. } break;
  400. }
  401. return 1;
  402. } break;
  403. }
  404. return 0;
  405. }
  406. /**
  407. * Process the next main command.
  408. */
  409. static void _gfx_init(void *ud, bool p_gl2) {
  410. struct engine *engine = (struct engine *)ud;
  411. engine_init_display(engine, p_gl2);
  412. }
  413. static void engine_handle_cmd(struct android_app *app, int32_t cmd) {
  414. struct engine *engine = (struct engine *)app->userData;
  415. // LOGI("**** CMD %i\n",cmd);
  416. switch (cmd) {
  417. case APP_CMD_SAVE_STATE:
  418. // The system has asked us to save our current state. Do so.
  419. //engine->app->savedState = malloc(sizeof(struct saved_state));
  420. //*((struct saved_state*)engine->app->savedState) = engine->state;
  421. //engine->app->savedStateSize = sizeof(struct saved_state);
  422. break;
  423. case APP_CMD_CONFIG_CHANGED:
  424. case APP_CMD_WINDOW_RESIZED: {
  425. #if 0
  426. // android blows
  427. if (engine->display_active) {
  428. EGLint w,h;
  429. eglQuerySurface(engine->display, engine->surface, EGL_WIDTH, &w);
  430. eglQuerySurface(engine->display, engine->surface, EGL_HEIGHT, &h);
  431. engine->os->init_video_mode(w,h);
  432. engine_draw_frame(engine);
  433. }
  434. #else
  435. if (engine->display_active) {
  436. EGLint w, h;
  437. eglQuerySurface(engine->display, engine->surface, EGL_WIDTH, &w);
  438. eglQuerySurface(engine->display, engine->surface, EGL_HEIGHT, &h);
  439. // if (w==engine->os->get_video_mode().width && h==engine->os->get_video_mode().height)
  440. // break;
  441. engine_term_display(engine);
  442. }
  443. engine->os->reload_gfx();
  444. engine_draw_frame(engine);
  445. engine->animating = 1;
  446. /*
  447. EGLint w,h;
  448. eglQuerySurface(engine->display, engine->surface, EGL_WIDTH, &w);
  449. eglQuerySurface(engine->display, engine->surface, EGL_HEIGHT, &h);
  450. engine->os->init_video_mode(w,h);
  451. }*/
  452. #endif
  453. } break;
  454. case APP_CMD_INIT_WINDOW:
  455. //The window is being shown, get it ready.
  456. // LOGI("INIT WINDOW");
  457. if (engine->app->window != NULL) {
  458. if (engine->os == NULL) {
  459. //do initialization here, when there's OpenGL! hackish but the only way
  460. engine->os = new OS_Android(_gfx_init, engine);
  461. // char *args[]={"-test","gui",NULL};
  462. __android_log_print(ANDROID_LOG_INFO, "godot", "pre asdasd setup...");
  463. #if 0
  464. Error err = Main::setup("apk",2,args);
  465. #else
  466. Error err = Main::setup("apk", 0, NULL);
  467. String modules = Globals::get_singleton()->get("android/modules");
  468. Vector<String> mods = modules.split(",", false);
  469. mods.push_back("GodotOS");
  470. __android_log_print(ANDROID_LOG_INFO, "godot", "mod count: %i", mods.size());
  471. if (mods.size()) {
  472. jclass activityClass = engine->jni->FindClass("android/app/NativeActivity");
  473. jmethodID getClassLoader = engine->jni->GetMethodID(activityClass, "getClassLoader", "()Ljava/lang/ClassLoader;");
  474. jobject cls = engine->jni->CallObjectMethod(app->activity->clazz, getClassLoader);
  475. jclass classLoader = engine->jni->FindClass("java/lang/ClassLoader");
  476. jmethodID findClass = engine->jni->GetMethodID(classLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
  477. static JNINativeMethod methods[] = {
  478. { "registerSingleton", "(Ljava/lang/String;Ljava/lang/Object;)V", (void *)&Java_org_godotengine_godot_Godot_registerSingleton },
  479. { "registerMethod", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V", (void *)&Java_org_godotengine_godot_Godot_registerMethod },
  480. { "getGlobal", "(Ljava/lang/String;)Ljava/lang/String;", (void *)&Java_org_godotengine_godot_Godot_getGlobal },
  481. };
  482. jstring gstrClassName = engine->jni->NewStringUTF("org/godotengine/godot/Godot");
  483. jclass GodotClass = (jclass)engine->jni->CallObjectMethod(cls, findClass, gstrClassName);
  484. __android_log_print(ANDROID_LOG_INFO, "godot", "godot ****^*^*?^*^*class data %x", GodotClass);
  485. engine->jni->RegisterNatives(GodotClass, methods, sizeof(methods) / sizeof(methods[0]));
  486. for (int i = 0; i < mods.size(); i++) {
  487. String m = mods[i];
  488. //jclass singletonClass = engine->jni->FindClass(m.utf8().get_data());
  489. jstring strClassName = engine->jni->NewStringUTF(m.utf8().get_data());
  490. jclass singletonClass = (jclass)engine->jni->CallObjectMethod(cls, findClass, strClassName);
  491. __android_log_print(ANDROID_LOG_INFO, "godot", "****^*^*?^*^*class data %x", singletonClass);
  492. jmethodID initialize = engine->jni->GetStaticMethodID(singletonClass, "initialize", "(Landroid/app/Activity;)Lorg/godotengine/godot/Godot$SingletonBase;");
  493. jobject obj = engine->jni->CallStaticObjectMethod(singletonClass, initialize, app->activity->clazz);
  494. __android_log_print(ANDROID_LOG_INFO, "godot", "****^*^*?^*^*class instance %x", obj);
  495. jobject gob = engine->jni->NewGlobalRef(obj);
  496. }
  497. }
  498. #endif
  499. if (!Main::start())
  500. return; //should exit instead and print the error
  501. engine->os->main_loop_begin();
  502. } else {
  503. //i guess recreate resources?
  504. engine->os->reload_gfx();
  505. }
  506. engine->animating = 1;
  507. engine_draw_frame(engine);
  508. }
  509. break;
  510. case APP_CMD_TERM_WINDOW:
  511. // The window is being hidden or closed, clean it up.
  512. // LOGI("TERM WINDOW");
  513. engine_term_display(engine);
  514. break;
  515. case APP_CMD_GAINED_FOCUS:
  516. // When our app gains focus, we start monitoring the accelerometer.
  517. if (engine->accelerometerSensor != NULL) {
  518. ASensorEventQueue_enableSensor(engine->sensorEventQueue,
  519. engine->accelerometerSensor);
  520. // We'd like to get 60 events per second (in us).
  521. ASensorEventQueue_setEventRate(engine->sensorEventQueue,
  522. engine->accelerometerSensor, (1000L / 60) * 1000);
  523. }
  524. // and start monitoring our gravity vector
  525. if (engine->gravitySensor != NULL) {
  526. ASensorEventQueue_enableSensor(engine->sensorEventQueue,
  527. engine->gravitySensor);
  528. // We'd like to get 60 events per second (in us).
  529. ASensorEventQueue_setEventRate(engine->sensorEventQueue,
  530. engine->gravitySensor, (1000L / 60) * 1000);
  531. }
  532. // Also start monitoring the magnetometer.
  533. if (engine->magnetometerSensor != NULL) {
  534. ASensorEventQueue_enableSensor(engine->sensorEventQueue,
  535. engine->magnetometerSensor);
  536. // We'd like to get 60 events per second (in us).
  537. ASensorEventQueue_setEventRate(engine->sensorEventQueue,
  538. engine->magnetometerSensor, (1000L / 60) * 1000);
  539. }
  540. // And the gyroscope.
  541. if (engine->gyroscopeSensor != NULL) {
  542. ASensorEventQueue_enableSensor(engine->sensorEventQueue,
  543. engine->gyroscopeSensor);
  544. // We'd like to get 60 events per second (in us).
  545. ASensorEventQueue_setEventRate(engine->sensorEventQueue,
  546. engine->gyroscopeSensor, (1000L / 60) * 1000);
  547. }
  548. engine->animating = 1;
  549. break;
  550. case APP_CMD_LOST_FOCUS:
  551. // When our app loses focus, we stop monitoring the sensors.
  552. // This is to avoid consuming battery while not being used.
  553. if (engine->accelerometerSensor != NULL) {
  554. ASensorEventQueue_disableSensor(engine->sensorEventQueue,
  555. engine->accelerometerSensor);
  556. }
  557. if (engine->gravitySensor != NULL) {
  558. ASensorEventQueue_disableSensor(engine->sensorEventQueue,
  559. engine->gravitySensor);
  560. }
  561. if (engine->magnetometerSensor != NULL) {
  562. ASensorEventQueue_disableSensor(engine->sensorEventQueue,
  563. engine->magnetometerSensor);
  564. }
  565. if (engine->gyroscopeSensor != NULL) {
  566. ASensorEventQueue_disableSensor(engine->sensorEventQueue,
  567. engine->gyroscopeSensor);
  568. }
  569. // Also stop animating.
  570. engine->animating = 0;
  571. engine_draw_frame(engine);
  572. break;
  573. }
  574. }
  575. void android_main(struct android_app *state) {
  576. struct engine engine;
  577. // Make sure glue isn't stripped.
  578. app_dummy();
  579. memset(&engine, 0, sizeof(engine));
  580. state->userData = &engine;
  581. state->onAppCmd = engine_handle_cmd;
  582. state->onInputEvent = engine_handle_input;
  583. engine.app = state;
  584. engine.requested_quit = false;
  585. engine.os = NULL;
  586. engine.display_active = false;
  587. FileAccessAndroid::asset_manager = state->activity->assetManager;
  588. // Prepare to monitor sensors
  589. engine.sensorManager = ASensorManager_getInstance();
  590. engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
  591. ASENSOR_TYPE_ACCELEROMETER);
  592. engine.gravitySensor = ASensorManager_getDefaultSensor(engine.sensorManager,
  593. ASENSOR_TYPE_GRAVITY);
  594. engine.magnetometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
  595. ASENSOR_TYPE_MAGNETIC_FIELD);
  596. engine.gyroscopeSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
  597. ASENSOR_TYPE_GYROSCOPE);
  598. engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager,
  599. state->looper, LOOPER_ID_USER, NULL, NULL);
  600. ANativeActivity_setWindowFlags(state->activity, AWINDOW_FLAG_FULLSCREEN | AWINDOW_FLAG_KEEP_SCREEN_ON, 0);
  601. state->activity->vm->AttachCurrentThread(&engine.jni, NULL);
  602. // loop waiting for stuff to do.
  603. while (1) {
  604. // Read all pending events.
  605. int ident;
  606. int events;
  607. struct android_poll_source *source;
  608. // If not animating, we will block forever waiting for events.
  609. // If animating, we loop until all events are read, then continue
  610. // to draw the next frame of animation.
  611. int nullmax = 50;
  612. while ((ident = ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events,
  613. (void **)&source)) >= 0) {
  614. // Process this event.
  615. if (source != NULL) {
  616. // LOGI("process\n");
  617. source->process(state, source);
  618. } else {
  619. nullmax--;
  620. if (nullmax < 0)
  621. break;
  622. }
  623. // If a sensor has data, process it now.
  624. // LOGI("events\n");
  625. if (ident == LOOPER_ID_USER) {
  626. if (engine.accelerometerSensor != NULL || engine.gravitySensor != NULL || engine.magnetometerSensor != NULL || engine.gyroscopeSensor != NULL) {
  627. ASensorEvent event;
  628. while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
  629. &event, 1) > 0) {
  630. if (engine.os) {
  631. if (event.acceleration != NULL) {
  632. engine.os->process_accelerometer(Vector3(event.acceleration.x, event.acceleration.y,
  633. event.acceleration.z));
  634. }
  635. if (event.gravity != NULL) {
  636. engine.os->process_gravitymeter(Vector3(event.gravity.x, event.gravity.y,
  637. event.gravity.z));
  638. }
  639. if (event.magnetic != NULL) {
  640. engine.os->process_magnetometer(Vector3(event.magnetic.x, event.magnetic.y,
  641. event.magnetic.z));
  642. }
  643. if (event.vector != NULL) {
  644. engine.os->process_gyroscope(Vector3(event.vector.x, event.vector.y,
  645. event.vector.z));
  646. }
  647. }
  648. }
  649. }
  650. }
  651. // Check if we are exiting.
  652. if (state->destroyRequested != 0) {
  653. if (engine.os) {
  654. engine.os->main_loop_request_quit();
  655. }
  656. state->destroyRequested = 0;
  657. }
  658. if (engine.requested_quit) {
  659. engine_term_display(&engine);
  660. exit(0);
  661. return;
  662. }
  663. // LOGI("end\n");
  664. }
  665. // LOGI("engine animating? %i\n",engine.animating);
  666. if (engine.animating) {
  667. //do os render
  668. engine_draw_frame(&engine);
  669. //LOGI("TERM WINDOW");
  670. }
  671. }
  672. }
  673. JNIEXPORT void JNICALL Java_org_godotengine_godot_Godot_registerSingleton(JNIEnv *env, jobject obj, jstring name, jobject p_object) {
  674. String singname = env->GetStringUTFChars(name, NULL);
  675. JNISingleton *s = memnew(JNISingleton);
  676. s->update_env(env);
  677. s->set_instance(env->NewGlobalRef(p_object));
  678. jni_singletons[singname] = s;
  679. Globals::get_singleton()->add_singleton(Globals::Singleton(singname, s));
  680. }
  681. static Variant::Type get_jni_type(const String &p_type) {
  682. static struct {
  683. const char *name;
  684. Variant::Type type;
  685. } _type_to_vtype[] = {
  686. { "void", Variant::NIL },
  687. { "boolean", Variant::BOOL },
  688. { "int", Variant::INT },
  689. { "float", Variant::REAL },
  690. { "java.lang.String", Variant::STRING },
  691. { "[I", Variant::INT_ARRAY },
  692. { "[F", Variant::REAL_ARRAY },
  693. { "[Ljava.lang.String;", Variant::STRING_ARRAY },
  694. { NULL, Variant::NIL }
  695. };
  696. int idx = 0;
  697. while (_type_to_vtype[idx].name) {
  698. if (p_type == _type_to_vtype[idx].name)
  699. return _type_to_vtype[idx].type;
  700. idx++;
  701. }
  702. return Variant::NIL;
  703. }
  704. static const char *get_jni_sig(const String &p_type) {
  705. static struct {
  706. const char *name;
  707. const char *sig;
  708. } _type_to_vtype[] = {
  709. { "void", "V" },
  710. { "boolean", "Z" },
  711. { "int", "I" },
  712. { "float", "F" },
  713. { "java.lang.String", "Ljava/lang/String;" },
  714. { "[I", "[I" },
  715. { "[F", "[F" },
  716. { "[Ljava.lang.String;", "[Ljava/lang/String;" },
  717. { NULL, "V" }
  718. };
  719. int idx = 0;
  720. while (_type_to_vtype[idx].name) {
  721. if (p_type == _type_to_vtype[idx].name)
  722. return _type_to_vtype[idx].sig;
  723. idx++;
  724. }
  725. return "";
  726. }
  727. JNIEXPORT jstring JNICALL Java_org_godotengine_godot_Godot_getGlobal(JNIEnv *env, jobject obj, jstring path) {
  728. String js = env->GetStringUTFChars(path, NULL);
  729. return env->NewStringUTF(Globals::get_singleton()->get(js).operator String().utf8().get_data());
  730. }
  731. JNIEXPORT void JNICALL Java_org_godotengine_godot_Godot_registerMethod(JNIEnv *env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args) {
  732. String singname = env->GetStringUTFChars(sname, NULL);
  733. ERR_FAIL_COND(!jni_singletons.has(singname));
  734. JNISingleton *s = jni_singletons.get(singname);
  735. String mname = env->GetStringUTFChars(name, NULL);
  736. String retval = env->GetStringUTFChars(ret, NULL);
  737. Vector<Variant::Type> types;
  738. String cs = "(";
  739. int stringCount = env->GetArrayLength(args);
  740. for (int i = 0; i < stringCount; i++) {
  741. jstring string = (jstring)env->GetObjectArrayElement(args, i);
  742. const char *rawString = env->GetStringUTFChars(string, 0);
  743. types.push_back(get_jni_type(String(rawString)));
  744. cs += get_jni_sig(String(rawString));
  745. }
  746. cs += ")";
  747. cs += get_jni_sig(retval);
  748. jclass cls = env->GetObjectClass(s->get_instance());
  749. jmethodID mid = env->GetMethodID(cls, mname.ascii().get_data(), cs.ascii().get_data());
  750. if (!mid) {
  751. print_line("Failed getting method id: " + mname);
  752. }
  753. s->add_method(mname, mid, types, get_jni_type(retval));
  754. }
  755. #endif