godot_android.cpp 28 KB

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