godot_android.cpp 28 KB

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