godot_android.cpp 28 KB

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