godot_android.cpp 28 KB

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