godot_android.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969
  1. /*************************************************************************/
  2. /* godot_android.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* http://www.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 "file_access_android.h"
  36. #include "main/main.h"
  37. #include "os_android.h"
  38. #include "project_settings.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. 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 0
  440. // android blows
  441. if (engine->display_active) {
  442. EGLint w,h;
  443. eglQuerySurface(engine->display, engine->surface, EGL_WIDTH, &w);
  444. eglQuerySurface(engine->display, engine->surface, EGL_HEIGHT, &h);
  445. engine->os->init_video_mode(w,h);
  446. //print_line("RESIZED VIDEO MODE: "+itos(w)+","+itos(h));
  447. engine_draw_frame(engine);
  448. }
  449. #else
  450. if (engine->display_active) {
  451. EGLint w, h;
  452. eglQuerySurface(engine->display, engine->surface, EGL_WIDTH, &w);
  453. eglQuerySurface(engine->display, engine->surface, EGL_HEIGHT, &h);
  454. // if (w==engine->os->get_video_mode().width && h==engine->os->get_video_mode().height)
  455. // break;
  456. engine_term_display(engine);
  457. }
  458. engine->os->reload_gfx();
  459. engine_draw_frame(engine);
  460. engine->animating = 1;
  461. /*
  462. EGLint w,h;
  463. eglQuerySurface(engine->display, engine->surface, EGL_WIDTH, &w);
  464. eglQuerySurface(engine->display, engine->surface, EGL_HEIGHT, &h);
  465. engine->os->init_video_mode(w,h);
  466. //print_line("RESIZED VIDEO MODE: "+itos(w)+","+itos(h));
  467. }*/
  468. #endif
  469. } break;
  470. case APP_CMD_INIT_WINDOW:
  471. //The window is being shown, get it ready.
  472. //LOGI("INIT WINDOW");
  473. if (engine->app->window != NULL) {
  474. if (engine->os == NULL) {
  475. //do initialization here, when there's OpenGL! hackish but the only way
  476. engine->os = new OS_Android(_gfx_init, engine);
  477. //char *args[]={"-test","gui",NULL};
  478. __android_log_print(ANDROID_LOG_INFO, "godot", "pre asdasd setup...");
  479. #if 0
  480. Error err = Main::setup("apk",2,args);
  481. #else
  482. Error err = Main::setup("apk", 0, NULL);
  483. String modules = ProjectSettings::get_singleton()->get("android/modules");
  484. Vector<String> mods = modules.split(",", false);
  485. mods.push_back("GodotOS");
  486. __android_log_print(ANDROID_LOG_INFO, "godot", "mod count: %i", mods.size());
  487. if (mods.size()) {
  488. jclass activityClass = engine->jni->FindClass("android/app/NativeActivity");
  489. jmethodID getClassLoader = engine->jni->GetMethodID(activityClass, "getClassLoader", "()Ljava/lang/ClassLoader;");
  490. jobject cls = engine->jni->CallObjectMethod(app->activity->clazz, getClassLoader);
  491. jclass classLoader = engine->jni->FindClass("java/lang/ClassLoader");
  492. jmethodID findClass = engine->jni->GetMethodID(classLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
  493. static JNINativeMethod methods[] = {
  494. { "registerSingleton", "(Ljava/lang/String;Ljava/lang/Object;)V", (void *)&Java_org_godotengine_godot_Godot_registerSingleton },
  495. { "registerMethod", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V", (void *)&Java_org_godotengine_godot_Godot_registerMethod },
  496. { "getGlobal", "(Ljava/lang/String;)Ljava/lang/String;", (void *)&Java_org_godotengine_godot_Godot_getGlobal },
  497. };
  498. jstring gstrClassName = engine->jni->NewStringUTF("org/godotengine/godot/Godot");
  499. jclass GodotClass = (jclass)engine->jni->CallObjectMethod(cls, findClass, gstrClassName);
  500. __android_log_print(ANDROID_LOG_INFO, "godot", "godot ****^*^*?^*^*class data %x", GodotClass);
  501. engine->jni->RegisterNatives(GodotClass, methods, sizeof(methods) / sizeof(methods[0]));
  502. for (int i = 0; i < mods.size(); i++) {
  503. String m = mods[i];
  504. //jclass singletonClass = engine->jni->FindClass(m.utf8().get_data());
  505. jstring strClassName = engine->jni->NewStringUTF(m.utf8().get_data());
  506. jclass singletonClass = (jclass)engine->jni->CallObjectMethod(cls, findClass, strClassName);
  507. __android_log_print(ANDROID_LOG_INFO, "godot", "****^*^*?^*^*class data %x", singletonClass);
  508. jmethodID initialize = engine->jni->GetStaticMethodID(singletonClass, "initialize", "(Landroid/app/Activity;)Lorg/godotengine/godot/Godot$SingletonBase;");
  509. jobject obj = engine->jni->CallStaticObjectMethod(singletonClass, initialize, app->activity->clazz);
  510. __android_log_print(ANDROID_LOG_INFO, "godot", "****^*^*?^*^*class instance %x", obj);
  511. jobject gob = engine->jni->NewGlobalRef(obj);
  512. }
  513. }
  514. #endif
  515. if (!Main::start())
  516. return; //should exit instead and print the error
  517. engine->os->main_loop_begin();
  518. } else {
  519. //i guess recreate resources?
  520. engine->os->reload_gfx();
  521. }
  522. engine->animating = 1;
  523. engine_draw_frame(engine);
  524. }
  525. break;
  526. case APP_CMD_TERM_WINDOW:
  527. // The window is being hidden or closed, clean it up.
  528. //LOGI("TERM WINDOW");
  529. engine_term_display(engine);
  530. break;
  531. case APP_CMD_GAINED_FOCUS:
  532. // When our app gains focus, we start monitoring the accelerometer.
  533. if (engine->accelerometerSensor != NULL) {
  534. ASensorEventQueue_enableSensor(engine->sensorEventQueue,
  535. engine->accelerometerSensor);
  536. // We'd like to get 60 events per second (in us).
  537. ASensorEventQueue_setEventRate(engine->sensorEventQueue,
  538. engine->accelerometerSensor, (1000L / 60) * 1000);
  539. }
  540. // Also start monitoring the magnetometer.
  541. if (engine->magnetometerSensor != NULL) {
  542. ASensorEventQueue_enableSensor(engine->sensorEventQueue,
  543. engine->magnetometerSensor);
  544. // We'd like to get 60 events per second (in us).
  545. ASensorEventQueue_setEventRate(engine->sensorEventQueue,
  546. engine->magnetometerSensor, (1000L / 60) * 1000);
  547. }
  548. // And the gyroscope.
  549. if (engine->gyroscopeSensor != NULL) {
  550. ASensorEventQueue_enableSensor(engine->sensorEventQueue,
  551. engine->gyroscopeSensor);
  552. // We'd like to get 60 events per second (in us).
  553. ASensorEventQueue_setEventRate(engine->sensorEventQueue,
  554. engine->gyroscopeSensor, (1000L / 60) * 1000);
  555. }
  556. engine->animating = 1;
  557. break;
  558. case APP_CMD_LOST_FOCUS:
  559. // When our app loses focus, we stop monitoring the sensors.
  560. // This is to avoid consuming battery while not being used.
  561. if (engine->accelerometerSensor != NULL) {
  562. ASensorEventQueue_disableSensor(engine->sensorEventQueue,
  563. engine->accelerometerSensor);
  564. }
  565. if (engine->magnetometerSensor != NULL) {
  566. ASensorEventQueue_disableSensor(engine->sensorEventQueue,
  567. engine->magnetometerSensor);
  568. }
  569. if (engine->gyroscopeSensor != NULL) {
  570. ASensorEventQueue_disableSensor(engine->sensorEventQueue,
  571. engine->gyroscopeSensor);
  572. }
  573. // Also stop animating.
  574. engine->animating = 0;
  575. engine_draw_frame(engine);
  576. break;
  577. }
  578. }
  579. void android_main(struct android_app *app) {
  580. struct engine engine;
  581. // Make sure glue isn't stripped.
  582. app_dummy();
  583. memset(&engine, 0, sizeof(engine));
  584. app->userData = &engine;
  585. app->onAppCmd = engine_handle_cmd;
  586. app->onInputEvent = engine_handle_input;
  587. engine.app = app;
  588. engine.requested_quit = false;
  589. engine.os = NULL;
  590. engine.display_active = false;
  591. FileAccessAndroid::asset_manager = app->activity->assetManager;
  592. // Prepare to monitor sensors
  593. engine.sensorManager = ASensorManager_getInstance();
  594. engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
  595. ASENSOR_TYPE_ACCELEROMETER);
  596. engine.magnetometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
  597. ASENSOR_TYPE_MAGNETIC_FIELD);
  598. engine.gyroscopeSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
  599. ASENSOR_TYPE_GYROSCOPE);
  600. engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager,
  601. app->looper, LOOPER_ID_USER, NULL, NULL);
  602. ANativeActivity_setWindowFlags(app->activity, AWINDOW_FLAG_FULLSCREEN | AWINDOW_FLAG_KEEP_SCREEN_ON, 0);
  603. app->activity->vm->AttachCurrentThread(&engine.jni, NULL);
  604. // loop waiting for stuff to do.
  605. while (1) {
  606. // Read all pending events.
  607. int ident;
  608. int events;
  609. struct android_poll_source *source;
  610. // If not animating, we will block forever waiting for events.
  611. // If animating, we loop until all events are read, then continue
  612. // to draw the next frame of animation.
  613. int nullmax = 50;
  614. while ((ident = ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events,
  615. (void **)&source)) >= 0) {
  616. // Process this event.
  617. if (source != NULL) {
  618. // LOGI("process\n");
  619. source->process(app, source);
  620. } else {
  621. nullmax--;
  622. if (nullmax < 0)
  623. break;
  624. }
  625. // If a sensor has data, process it now.
  626. // LOGI("events\n");
  627. if (ident == LOOPER_ID_USER) {
  628. if (engine.accelerometerSensor != NULL || engine.magnetometerSensor != NULL || engine.gyroscopeSensor != NULL) {
  629. ASensorEvent event;
  630. while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
  631. &event, 1) > 0) {
  632. if (engine.os) {
  633. if (event.acceleration != NULL) {
  634. engine.os->process_accelerometer(Vector3(event.acceleration.x, event.acceleration.y,
  635. event.acceleration.z));
  636. }
  637. if (event.magnetic != NULL) {
  638. engine.os->process_magnetometer(Vector3(event.magnetic.x, event.magnetic.y,
  639. event.magnetic.z));
  640. }
  641. if (event.vector != NULL) {
  642. engine.os->process_gyroscope(Vector3(event.vector.x, event.vector.y,
  643. event.vector.z));
  644. }
  645. }
  646. }
  647. }
  648. }
  649. // Check if we are exiting.
  650. if (app->destroyRequested != 0) {
  651. if (engine.os) {
  652. engine.os->main_loop_request_quit();
  653. }
  654. app->destroyRequested = 0;
  655. }
  656. if (engine.requested_quit) {
  657. engine_term_display(&engine);
  658. exit(0);
  659. return;
  660. }
  661. // LOGI("end\n");
  662. }
  663. // LOGI("engine animating? %i\n",engine.animating);
  664. if (engine.animating) {
  665. //do os render
  666. engine_draw_frame(&engine);
  667. //LOGI("TERM WINDOW");
  668. }
  669. }
  670. }
  671. JNIEXPORT void JNICALL Java_org_godotengine_godot_Godot_registerSingleton(JNIEnv *env, jobject obj, jstring name, jobject p_object) {
  672. String singname = env->GetStringUTFChars(name, NULL);
  673. JNISingleton *s = memnew(JNISingleton);
  674. s->update_env(env);
  675. s->set_instance(env->NewGlobalRef(p_object));
  676. jni_singletons[singname] = s;
  677. ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton(singname, s));
  678. }
  679. static Variant::Type get_jni_type(const String &p_type) {
  680. static struct {
  681. const char *name;
  682. Variant::Type type;
  683. } _type_to_vtype[] = {
  684. { "void", Variant::NIL },
  685. { "boolean", Variant::BOOL },
  686. { "int", Variant::INT },
  687. { "float", Variant::REAL },
  688. { "java.lang.String", Variant::STRING },
  689. { "[I", Variant::INT_ARRAY },
  690. { "[F", Variant::REAL_ARRAY },
  691. { "[Ljava.lang.String;", Variant::STRING_ARRAY },
  692. { NULL, Variant::NIL }
  693. };
  694. int idx = 0;
  695. while (_type_to_vtype[idx].name) {
  696. if (p_type == _type_to_vtype[idx].name)
  697. return _type_to_vtype[idx].type;
  698. idx++;
  699. }
  700. return Variant::NIL;
  701. }
  702. static const char *get_jni_sig(const String &p_type) {
  703. static struct {
  704. const char *name;
  705. const char *sig;
  706. } _type_to_vtype[] = {
  707. { "void", "V" },
  708. { "boolean", "Z" },
  709. { "int", "I" },
  710. { "float", "F" },
  711. { "java.lang.String", "Ljava/lang/String;" },
  712. { "[I", "[I" },
  713. { "[F", "[F" },
  714. { "[Ljava.lang.String;", "[Ljava/lang/String;" },
  715. { NULL, "V" }
  716. };
  717. int idx = 0;
  718. while (_type_to_vtype[idx].name) {
  719. if (p_type == _type_to_vtype[idx].name)
  720. return _type_to_vtype[idx].sig;
  721. idx++;
  722. }
  723. return "";
  724. }
  725. JNIEXPORT jstring JNICALL Java_org_godotengine_godot_Godot_getGlobal(JNIEnv *env, jobject obj, jstring path) {
  726. String js = env->GetStringUTFChars(path, NULL);
  727. return env->NewStringUTF(ProjectSettings::get_singleton()->get(js).operator String().utf8().get_data());
  728. }
  729. JNIEXPORT void JNICALL Java_org_godotengine_godot_Godot_registerMethod(JNIEnv *env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args) {
  730. String singname = env->GetStringUTFChars(sname, NULL);
  731. ERR_FAIL_COND(!jni_singletons.has(singname));
  732. JNISingleton *s = jni_singletons.get(singname);
  733. String mname = env->GetStringUTFChars(name, NULL);
  734. String retval = env->GetStringUTFChars(ret, NULL);
  735. Vector<Variant::Type> types;
  736. String cs = "(";
  737. int stringCount = env->GetArrayLength(args);
  738. print_line("Singl: " + singname + " Method: " + mname + " RetVal: " + retval);
  739. for (int i = 0; i < stringCount; i++) {
  740. jstring string = (jstring)env->GetObjectArrayElement(args, i);
  741. const char *rawString = env->GetStringUTFChars(string, 0);
  742. types.push_back(get_jni_type(String(rawString)));
  743. cs += get_jni_sig(String(rawString));
  744. }
  745. cs += ")";
  746. cs += get_jni_sig(retval);
  747. jclass cls = env->GetObjectClass(s->get_instance());
  748. print_line("METHOD: " + mname + " sig: " + cs);
  749. jmethodID mid = env->GetMethodID(cls, mname.ascii().get_data(), cs.ascii().get_data());
  750. if (!mid) {
  751. print_line("FAILED GETTING METHOID " + mname);
  752. }
  753. s->add_method(mname, mid, types, get_jni_type(retval));
  754. }
  755. #endif