godot_android.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993
  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-2014 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 "globals.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_com_android_godot_Godot_registerSingleton(JNIEnv * env, jobject obj, jstring name,jobject p_object);
  49. JNIEXPORT void JNICALL Java_com_android_godot_Godot_registerMethod(JNIEnv * env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args);
  50. JNIEXPORT jstring JNICALL Java_com_android_godot_Godot_getGlobal(JNIEnv * env, jobject obj, jstring path);
  51. };
  52. class JNISingleton : public Object {
  53. OBJ_TYPE( 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. DVector<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. DVector<int> array = *p_args[i];
  123. jintArray arr = env->NewIntArray(array.size());
  124. DVector<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. DVector<float> array = *p_args[i];
  130. jfloatArray arr = env->NewFloatArray(array.size());
  131. DVector<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. DVector<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. DVector<int> sarr;
  177. sarr.resize(fCount);
  178. DVector<int>::Write w = sarr.write();
  179. env->GetIntArrayRegion(arr,0,fCount,w.ptr());
  180. w = DVector<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. DVector<float> sarr;
  187. sarr.resize(fCount);
  188. DVector<float>::Write w = sarr.write();
  189. env->GetFloatArrayRegion(arr,0,fCount,w.ptr());
  190. w = DVector<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. ASensorEventQueue* sensorEventQueue;
  225. bool display_active;
  226. bool requested_quit;
  227. int animating;
  228. EGLDisplay display;
  229. EGLSurface surface;
  230. EGLContext context;
  231. int32_t width;
  232. int32_t height;
  233. };
  234. /**
  235. * Initialize an EGL context for the current display.
  236. */
  237. static int engine_init_display(struct engine* engine,bool p_gl2) {
  238. // initialize OpenGL ES and EGL
  239. /*
  240. * Here specify the attributes of the desired configuration.
  241. * Below, we select an EGLConfig with at least 8 bits per color
  242. * component compatible with on-screen windows
  243. */
  244. const EGLint gl2_attribs[] = {
  245. // EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
  246. EGL_BLUE_SIZE, 4,
  247. EGL_GREEN_SIZE, 4,
  248. EGL_RED_SIZE, 4,
  249. EGL_ALPHA_SIZE, 0,
  250. EGL_DEPTH_SIZE, 16,
  251. EGL_STENCIL_SIZE, EGL_DONT_CARE,
  252. EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
  253. EGL_NONE
  254. };
  255. const EGLint gl1_attribs[] = {
  256. // EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
  257. EGL_BLUE_SIZE, 4,
  258. EGL_GREEN_SIZE, 4,
  259. EGL_RED_SIZE, 4,
  260. EGL_ALPHA_SIZE, 0,
  261. EGL_DEPTH_SIZE, 16,
  262. EGL_STENCIL_SIZE, EGL_DONT_CARE,
  263. EGL_NONE
  264. };
  265. const EGLint *attribs=p_gl2?gl2_attribs:gl1_attribs;
  266. EGLint w, h, dummy, format;
  267. EGLint numConfigs;
  268. EGLConfig config;
  269. EGLSurface surface;
  270. EGLContext context;
  271. EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  272. eglInitialize(display, 0, 0);
  273. /* Here, the application chooses the configuration it desires. In this
  274. * sample, we have a very simplified selection process, where we pick
  275. * the first EGLConfig that matches our criteria */
  276. eglChooseConfig(display, attribs, &config, 1, &numConfigs);
  277. LOGI("Num configs: %i\n",numConfigs);
  278. /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
  279. * guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
  280. * As soon as we picked a EGLConfig, we can safely reconfigure the
  281. * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
  282. eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
  283. ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format);
  284. //ANativeWindow_setFlags(engine->app->window, 0, 0, format|);
  285. surface = eglCreateWindowSurface(display, config, engine->app->window, NULL);
  286. const EGLint context_attribs[] = {
  287. EGL_CONTEXT_CLIENT_VERSION,2,
  288. EGL_NONE
  289. };
  290. context = eglCreateContext(display, config, EGL_NO_CONTEXT, p_gl2?context_attribs:NULL);
  291. if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
  292. LOGW("Unable to eglMakeCurrent");
  293. return -1;
  294. }
  295. eglQuerySurface(display, surface, EGL_WIDTH, &w);
  296. eglQuerySurface(display, surface, EGL_HEIGHT, &h);
  297. print_line("INIT VIDEO MODE: "+itos(w)+","+itos(h));
  298. //engine->os->set_egl_extensions(eglQueryString(display,EGL_EXTENSIONS));
  299. engine->os->init_video_mode(w,h);
  300. engine->display = display;
  301. engine->context = context;
  302. engine->surface = surface;
  303. engine->width = w;
  304. engine->height = h;
  305. engine->display_active=true;
  306. //engine->state.angle = 0;
  307. // Initialize GL state.
  308. //glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
  309. glEnable(GL_CULL_FACE);
  310. // glShadeModel(GL_SMOOTH);
  311. glDisable(GL_DEPTH_TEST);
  312. LOGI("GL Version: %s - %s %s\n", glGetString(GL_VERSION),glGetString(GL_VENDOR), glGetString(GL_RENDERER));
  313. return 0;
  314. }
  315. static void engine_draw_frame(struct engine* engine) {
  316. if (engine->display == NULL) {
  317. // No display.
  318. return;
  319. }
  320. // Just fill the screen with a color.
  321. //glClearColor(0,1,0,1);
  322. //glClear(GL_COLOR_BUFFER_BIT);
  323. if (engine->os && engine->os->main_loop_iterate()==true) {
  324. engine->requested_quit=true;
  325. return; //should exit instead
  326. }
  327. eglSwapBuffers(engine->display, engine->surface);
  328. }
  329. static void engine_term_display(struct engine* engine) {
  330. if (engine->display != EGL_NO_DISPLAY) {
  331. eglMakeCurrent(engine->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
  332. if (engine->context != EGL_NO_CONTEXT) {
  333. eglDestroyContext(engine->display, engine->context);
  334. }
  335. if (engine->surface != EGL_NO_SURFACE) {
  336. eglDestroySurface(engine->display, engine->surface);
  337. }
  338. eglTerminate(engine->display);
  339. }
  340. engine->animating = 0;
  341. engine->display = EGL_NO_DISPLAY;
  342. engine->context = EGL_NO_CONTEXT;
  343. engine->surface = EGL_NO_SURFACE;
  344. engine->display_active=false;
  345. }
  346. /**
  347. * Process the next input event.
  348. */
  349. static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) {
  350. struct engine* engine = (struct engine*)app->userData;
  351. if (!engine->os)
  352. return 0;
  353. switch(AInputEvent_getType(event)) {
  354. case AINPUT_EVENT_TYPE_KEY: {
  355. int ac = AKeyEvent_getAction(event);
  356. switch(ac) {
  357. case AKEY_EVENT_ACTION_DOWN: {
  358. int32_t code = AKeyEvent_getKeyCode(event);
  359. if (code==AKEYCODE_BACK) {
  360. //AInputQueue_finishEvent(AInputQueue* queue, AInputEvent* event, int handled);
  361. if (engine->os)
  362. engine->os->main_loop_request_quit();
  363. return 1;
  364. }
  365. } break;
  366. case AKEY_EVENT_ACTION_UP: {
  367. } break;
  368. }
  369. } break;
  370. case AINPUT_EVENT_TYPE_MOTION: {
  371. Vector<OS_Android::TouchPos> touchvec;
  372. int pc = AMotionEvent_getPointerCount(event);
  373. touchvec.resize(pc);
  374. for(int i=0;i<pc;i++) {
  375. touchvec[i].pos.x=AMotionEvent_getX(event,i);
  376. touchvec[i].pos.y=AMotionEvent_getY(event,i);
  377. touchvec[i].id=AMotionEvent_getPointerId(event,i);
  378. }
  379. //System.out.printf("gaction: %d\n",event.getAction());
  380. int pidx=(AMotionEvent_getAction(event)&AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)>>8;
  381. switch(AMotionEvent_getAction(event)&AMOTION_EVENT_ACTION_MASK) {
  382. case AMOTION_EVENT_ACTION_DOWN: {
  383. engine->os->process_touch(0,0,touchvec);
  384. //System.out.printf("action down at: %f,%f\n", event.getX(),event.getY());
  385. } break;
  386. case AMOTION_EVENT_ACTION_MOVE: {
  387. engine->os->process_touch(1,0,touchvec);
  388. //for(int i=0;i<event.getPointerCount();i++) {
  389. // System.out.printf("%d - moved to: %f,%f\n",i, event.getX(i),event.getY(i));
  390. //}
  391. } break;
  392. case AMOTION_EVENT_ACTION_POINTER_UP: {
  393. engine->os->process_touch(4,pidx,touchvec);
  394. //System.out.printf("%d - s.up at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
  395. } break;
  396. case AMOTION_EVENT_ACTION_POINTER_DOWN: {
  397. engine->os->process_touch(3,pidx,touchvec);
  398. //System.out.printf("%d - s.down at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
  399. } break;
  400. case AMOTION_EVENT_ACTION_CANCEL:
  401. case AMOTION_EVENT_ACTION_UP: {
  402. engine->os->process_touch(2,0,touchvec);
  403. //for(int i=0;i<event.getPointerCount();i++) {
  404. // System.out.printf("%d - up! %f,%f\n",i, event.getX(i),event.getY(i));
  405. //}
  406. } break;
  407. }
  408. return 1;
  409. } break;
  410. }
  411. return 0;
  412. }
  413. /**
  414. * Process the next main command.
  415. */
  416. static void _gfx_init(void *ud,bool p_gl2) {
  417. struct engine* engine = (struct engine*)ud;
  418. engine_init_display(engine,p_gl2);
  419. }
  420. static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
  421. struct engine* engine = (struct engine*)app->userData;
  422. // LOGI("**** CMD %i\n",cmd);
  423. switch (cmd) {
  424. case APP_CMD_SAVE_STATE:
  425. // The system has asked us to save our current state. Do so.
  426. //engine->app->savedState = malloc(sizeof(struct saved_state));
  427. //*((struct saved_state*)engine->app->savedState) = engine->state;
  428. //engine->app->savedStateSize = sizeof(struct saved_state);
  429. break;
  430. case APP_CMD_CONFIG_CHANGED:
  431. case APP_CMD_WINDOW_RESIZED: {
  432. #if 0
  433. // android blows
  434. if (engine->display_active) {
  435. EGLint w,h;
  436. eglQuerySurface(engine->display, engine->surface, EGL_WIDTH, &w);
  437. eglQuerySurface(engine->display, engine->surface, EGL_HEIGHT, &h);
  438. engine->os->init_video_mode(w,h);
  439. //print_line("RESIZED VIDEO MODE: "+itos(w)+","+itos(h));
  440. engine_draw_frame(engine);
  441. }
  442. #else
  443. if (engine->display_active) {
  444. EGLint w,h;
  445. eglQuerySurface(engine->display, engine->surface, EGL_WIDTH, &w);
  446. eglQuerySurface(engine->display, engine->surface, EGL_HEIGHT, &h);
  447. // if (w==engine->os->get_video_mode().width && h==engine->os->get_video_mode().height)
  448. // break;
  449. engine_term_display(engine);
  450. }
  451. engine->os->reload_gfx();
  452. engine_draw_frame(engine);
  453. engine->animating=1;
  454. /*
  455. EGLint w,h;
  456. eglQuerySurface(engine->display, engine->surface, EGL_WIDTH, &w);
  457. eglQuerySurface(engine->display, engine->surface, EGL_HEIGHT, &h);
  458. engine->os->init_video_mode(w,h);
  459. //print_line("RESIZED VIDEO MODE: "+itos(w)+","+itos(h));
  460. }*/
  461. #endif
  462. } break;
  463. case APP_CMD_INIT_WINDOW:
  464. //The window is being shown, get it ready.
  465. // LOGI("INIT WINDOW");
  466. if (engine->app->window != NULL) {
  467. if (engine->os==NULL) {
  468. //do initialization here, when there's OpenGL! hackish but the only way
  469. engine->os = new OS_Android(_gfx_init,engine);
  470. // char *args[]={"-test","gui",NULL};
  471. __android_log_print(ANDROID_LOG_INFO,"godot","pre asdasd setup...");
  472. #if 0
  473. Error err = Main::setup("apk",2,args);
  474. #else
  475. Error err = Main::setup("apk",0,NULL);
  476. String modules = Globals::get_singleton()->get("android/modules");
  477. Vector<String> mods = modules.split(",",false);
  478. mods.push_back("GodotOS");
  479. __android_log_print(ANDROID_LOG_INFO,"godot","mod count: %i",mods.size());
  480. if (mods.size()) {
  481. jclass activityClass = engine->jni->FindClass("android/app/NativeActivity");
  482. jmethodID getClassLoader = engine->jni->GetMethodID(activityClass,"getClassLoader", "()Ljava/lang/ClassLoader;");
  483. jobject cls = engine->jni->CallObjectMethod(app->activity->clazz, getClassLoader);
  484. jclass classLoader = engine->jni->FindClass("java/lang/ClassLoader");
  485. jmethodID findClass = engine->jni->GetMethodID(classLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
  486. static JNINativeMethod methods[] = {
  487. {"registerSingleton", "(Ljava/lang/String;Ljava/lang/Object;)V",(void *)&Java_com_android_godot_Godot_registerSingleton},
  488. {"registerMethod", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V",(void *)&Java_com_android_godot_Godot_registerMethod},
  489. {"getGlobal", "(Ljava/lang/String;)Ljava/lang/String;", (void *)&Java_com_android_godot_Godot_getGlobal},
  490. };
  491. jstring gstrClassName = engine->jni->NewStringUTF("com/android/godot/Godot");
  492. jclass GodotClass = (jclass)engine->jni->CallObjectMethod(cls, findClass, gstrClassName);
  493. __android_log_print(ANDROID_LOG_INFO,"godot","godot ****^*^*?^*^*class data %x",GodotClass);
  494. engine->jni->RegisterNatives(GodotClass,methods,sizeof(methods)/sizeof(methods[0]));
  495. for (int i=0;i<mods.size();i++) {
  496. String m = mods[i];
  497. //jclass singletonClass = engine->jni->FindClass(m.utf8().get_data());
  498. jstring strClassName = engine->jni->NewStringUTF(m.utf8().get_data());
  499. jclass singletonClass = (jclass)engine->jni->CallObjectMethod(cls, findClass, strClassName);
  500. __android_log_print(ANDROID_LOG_INFO,"godot","****^*^*?^*^*class data %x",singletonClass);
  501. jmethodID initialize = engine->jni->GetStaticMethodID(singletonClass, "initialize", "(Landroid/app/Activity;)Lcom/android/godot/Godot$SingletonBase;");
  502. jobject obj = engine->jni->CallStaticObjectMethod(singletonClass,initialize,app->activity->clazz);
  503. __android_log_print(ANDROID_LOG_INFO,"godot","****^*^*?^*^*class instance %x",obj);
  504. jobject gob = engine->jni->NewGlobalRef(obj);
  505. }
  506. }
  507. #endif
  508. if (!Main::start())
  509. return; //should exit instead and print the error
  510. engine->os->main_loop_begin();
  511. } else {
  512. //i guess recreate resources?
  513. engine->os->reload_gfx();
  514. }
  515. engine->animating=1;
  516. engine_draw_frame(engine);
  517. }
  518. break;
  519. case APP_CMD_TERM_WINDOW:
  520. // The window is being hidden or closed, clean it up.
  521. // LOGI("TERM WINDOW");
  522. engine_term_display(engine);
  523. break;
  524. case APP_CMD_GAINED_FOCUS:
  525. // When our app gains focus, we start monitoring the accelerometer.
  526. if (engine->accelerometerSensor != NULL) {
  527. ASensorEventQueue_enableSensor(engine->sensorEventQueue,
  528. engine->accelerometerSensor);
  529. // We'd like to get 60 events per second (in us).
  530. ASensorEventQueue_setEventRate(engine->sensorEventQueue,
  531. engine->accelerometerSensor, (1000L/60)*1000);
  532. }
  533. engine->animating = 1;
  534. break;
  535. case APP_CMD_LOST_FOCUS:
  536. // When our app loses focus, we stop monitoring the accelerometer.
  537. // This is to avoid consuming battery while not being used.
  538. if (engine->accelerometerSensor != NULL) {
  539. ASensorEventQueue_disableSensor(engine->sensorEventQueue,
  540. engine->accelerometerSensor);
  541. }
  542. // Also stop animating.
  543. engine->animating = 0;
  544. engine_draw_frame(engine);
  545. break;
  546. }
  547. }
  548. void android_main(struct android_app* state) {
  549. struct engine engine;
  550. // Make sure glue isn't stripped.
  551. app_dummy();
  552. memset(&engine, 0, sizeof(engine));
  553. state->userData = &engine;
  554. state->onAppCmd = engine_handle_cmd;
  555. state->onInputEvent = engine_handle_input;
  556. engine.app = state;
  557. engine.requested_quit=false;
  558. engine.os=NULL;
  559. engine.display_active=false;
  560. FileAccessAndroid::asset_manager=state->activity->assetManager;
  561. // Prepare to monitor accelerometer
  562. engine.sensorManager = ASensorManager_getInstance();
  563. engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
  564. ASENSOR_TYPE_ACCELEROMETER);
  565. engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager,
  566. state->looper, LOOPER_ID_USER, NULL, NULL);
  567. ANativeActivity_setWindowFlags(state->activity,AWINDOW_FLAG_FULLSCREEN|AWINDOW_FLAG_KEEP_SCREEN_ON,0);
  568. state->activity->vm->AttachCurrentThread(&engine.jni, NULL);
  569. // loop waiting for stuff to do.
  570. while (1) {
  571. // Read all pending events.
  572. int ident;
  573. int events;
  574. struct android_poll_source* source;
  575. // If not animating, we will block forever waiting for events.
  576. // If animating, we loop until all events are read, then continue
  577. // to draw the next frame of animation.
  578. int nullmax=50;
  579. while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events,
  580. (void**)&source)) >= 0) {
  581. // Process this event.
  582. if (source != NULL) {
  583. // LOGI("process\n");
  584. source->process(state, source);
  585. } else {
  586. nullmax--;
  587. if (nullmax<0)
  588. break;
  589. }
  590. // If a sensor has data, process it now.
  591. // LOGI("events\n");
  592. if (ident == LOOPER_ID_USER) {
  593. if (engine.accelerometerSensor != NULL) {
  594. ASensorEvent event;
  595. while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
  596. &event, 1) > 0) {
  597. if (engine.os) {
  598. engine.os->process_accelerometer(Vector3(event.acceleration.x, event.acceleration.y,
  599. event.acceleration.z));
  600. }
  601. }
  602. }
  603. }
  604. // Check if we are exiting.
  605. if (state->destroyRequested != 0) {
  606. if (engine.os) {
  607. engine.os->main_loop_request_quit();
  608. }
  609. state->destroyRequested=0;
  610. }
  611. if (engine.requested_quit) {
  612. engine_term_display(&engine);
  613. exit(0);
  614. return;
  615. }
  616. // LOGI("end\n");
  617. }
  618. // LOGI("engine animating? %i\n",engine.animating);
  619. if (engine.animating) {
  620. //do os render
  621. engine_draw_frame(&engine);
  622. //LOGI("TERM WINDOW");
  623. }
  624. }
  625. }
  626. JNIEXPORT void JNICALL Java_com_android_godot_Godot_registerSingleton(JNIEnv * env, jobject obj, jstring name,jobject p_object){
  627. String singname = env->GetStringUTFChars( name, NULL );
  628. JNISingleton *s = memnew( JNISingleton );
  629. s->update_env(env);
  630. s->set_instance(env->NewGlobalRef(p_object));
  631. jni_singletons[singname]=s;
  632. Globals::get_singleton()->add_singleton(Globals::Singleton(singname,s));
  633. }
  634. static Variant::Type get_jni_type(const String& p_type) {
  635. static struct {
  636. const char *name;
  637. Variant::Type type;
  638. } _type_to_vtype[]={
  639. {"void",Variant::NIL},
  640. {"boolean",Variant::BOOL},
  641. {"int",Variant::INT},
  642. {"float",Variant::REAL},
  643. {"java.lang.String",Variant::STRING},
  644. {"[I",Variant::INT_ARRAY},
  645. {"[F",Variant::REAL_ARRAY},
  646. {"[java.lang.String",Variant::STRING_ARRAY},
  647. {NULL,Variant::NIL}
  648. };
  649. int idx=0;
  650. while (_type_to_vtype[idx].name) {
  651. if (p_type==_type_to_vtype[idx].name)
  652. return _type_to_vtype[idx].type;
  653. idx++;
  654. }
  655. return Variant::NIL;
  656. }
  657. static const char* get_jni_sig(const String& p_type) {
  658. static struct {
  659. const char *name;
  660. const char *sig;
  661. } _type_to_vtype[]={
  662. {"void","V"},
  663. {"boolean","Z"},
  664. {"int","I"},
  665. {"float","F"},
  666. {"java.lang.String","Ljava/lang/String;"},
  667. {"[I","[I"},
  668. {"[F","[F"},
  669. {"[java.lang.String","[Ljava/lang/String;"},
  670. {NULL,"V"}
  671. };
  672. int idx=0;
  673. while (_type_to_vtype[idx].name) {
  674. if (p_type==_type_to_vtype[idx].name)
  675. return _type_to_vtype[idx].sig;
  676. idx++;
  677. }
  678. return "";
  679. }
  680. JNIEXPORT jstring JNICALL Java_com_android_godot_Godot_getGlobal(JNIEnv * env, jobject obj, jstring path) {
  681. String js = env->GetStringUTFChars( path, NULL );
  682. return env->NewStringUTF(Globals::get_singleton()->get(js).operator String().utf8().get_data());
  683. }
  684. JNIEXPORT void JNICALL Java_com_android_godot_Godot_registerMethod(JNIEnv * env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args){
  685. String singname = env->GetStringUTFChars( sname, NULL );
  686. ERR_FAIL_COND(!jni_singletons.has(singname));
  687. JNISingleton *s = jni_singletons.get(singname);
  688. String mname = env->GetStringUTFChars( name, NULL );
  689. String retval = env->GetStringUTFChars( ret, NULL );
  690. Vector<Variant::Type> types;
  691. String cs="(";
  692. int stringCount = env->GetArrayLength(args);
  693. print_line("Singl: "+singname+" Method: "+mname+" RetVal: "+retval);
  694. for (int i=0; i<stringCount; i++) {
  695. jstring string = (jstring) env->GetObjectArrayElement(args, i);
  696. const char *rawString = env->GetStringUTFChars(string, 0);
  697. types.push_back(get_jni_type(String(rawString)));
  698. cs+=get_jni_sig(String(rawString));
  699. }
  700. cs+=")";
  701. cs+=get_jni_sig(retval);
  702. jclass cls = env->GetObjectClass(s->get_instance());
  703. print_line("METHOD: "+mname+" sig: "+cs);
  704. jmethodID mid = env->GetMethodID(cls, mname.ascii().get_data(), cs.ascii().get_data());
  705. if (!mid) {
  706. print_line("FAILED GETTING METHOID "+mname);
  707. }
  708. s->add_method(mname,mid,types,get_jni_type(retval));
  709. }
  710. #endif