mirror of
				https://github.com/godotengine/godot.git
				synced 2025-11-04 07:31:16 +00:00 
			
		
		
		
	
		
			
	
	
		
			994 lines
		
	
	
	
		
			27 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			994 lines
		
	
	
	
		
			27 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
								 | 
							
								/*************************************************************************/
							 | 
						||
| 
								 | 
							
								/*  godot_android.cpp                                                    */
							 | 
						||
| 
								 | 
							
								/*************************************************************************/
							 | 
						||
| 
								 | 
							
								/*                       This file is part of:                           */
							 | 
						||
| 
								 | 
							
								/*                           GODOT ENGINE                                */
							 | 
						||
| 
								 | 
							
								/*                    http://www.godotengine.org                         */
							 | 
						||
| 
								 | 
							
								/*************************************************************************/
							 | 
						||
| 
								 | 
							
								/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                 */
							 | 
						||
| 
								 | 
							
								/*                                                                       */
							 | 
						||
| 
								 | 
							
								/* Permission is hereby granted, free of charge, to any person obtaining */
							 | 
						||
| 
								 | 
							
								/* a copy of this software and associated documentation files (the       */
							 | 
						||
| 
								 | 
							
								/* "Software"), to deal in the Software without restriction, including   */
							 | 
						||
| 
								 | 
							
								/* without limitation the rights to use, copy, modify, merge, publish,   */
							 | 
						||
| 
								 | 
							
								/* distribute, sublicense, and/or sell copies of the Software, and to    */
							 | 
						||
| 
								 | 
							
								/* permit persons to whom the Software is furnished to do so, subject to */
							 | 
						||
| 
								 | 
							
								/* the following conditions:                                             */
							 | 
						||
| 
								 | 
							
								/*                                                                       */
							 | 
						||
| 
								 | 
							
								/* The above copyright notice and this permission notice shall be        */
							 | 
						||
| 
								 | 
							
								/* included in all copies or substantial portions of the Software.       */
							 | 
						||
| 
								 | 
							
								/*                                                                       */
							 | 
						||
| 
								 | 
							
								/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
							 | 
						||
| 
								 | 
							
								/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
							 | 
						||
| 
								 | 
							
								/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
							 | 
						||
| 
								 | 
							
								/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
							 | 
						||
| 
								 | 
							
								/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
							 | 
						||
| 
								 | 
							
								/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
							 | 
						||
| 
								 | 
							
								/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
							 | 
						||
| 
								 | 
							
								/*************************************************************************/
							 | 
						||
| 
								 | 
							
								#ifdef ANDROID_NATIVE_ACTIVITY
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <jni.h>
							 | 
						||
| 
								 | 
							
								#include <errno.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <EGL/egl.h>
							 | 
						||
| 
								 | 
							
								#include <GLES2/gl2.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <android/sensor.h>
							 | 
						||
| 
								 | 
							
								#include <android/window.h>
							 | 
						||
| 
								 | 
							
								#include <android/log.h>
							 | 
						||
| 
								 | 
							
								#include <android_native_app_glue.h>
							 | 
						||
| 
								 | 
							
								#include "file_access_android.h"
							 | 
						||
| 
								 | 
							
								#include <string.h>
							 | 
						||
| 
								 | 
							
								#include <unistd.h>
							 | 
						||
| 
								 | 
							
								#include <stdlib.h>
							 | 
						||
| 
								 | 
							
								#include "os_android.h"
							 | 
						||
| 
								 | 
							
								#include "globals.h"
							 | 
						||
| 
								 | 
							
								#include "main/main.h"
							 | 
						||
| 
								 | 
							
								#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "godot", __VA_ARGS__))
							 | 
						||
| 
								 | 
							
								#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "godot", __VA_ARGS__))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								extern "C" {
							 | 
						||
| 
								 | 
							
								    JNIEXPORT void JNICALL Java_com_android_godot_Godot_registerSingleton(JNIEnv * env, jobject obj, jstring name,jobject p_object);
							 | 
						||
| 
								 | 
							
								    JNIEXPORT void JNICALL Java_com_android_godot_Godot_registerMethod(JNIEnv * env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args);
							 | 
						||
| 
								 | 
							
								    JNIEXPORT jstring JNICALL Java_com_android_godot_Godot_getGlobal(JNIEnv * env, jobject obj, jstring path);
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class JNISingleton : public Object {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									OBJ_TYPE( JNISingleton, Object );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									struct MethodData {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										jmethodID method;
							 | 
						||
| 
								 | 
							
										Variant::Type ret_type;
							 | 
						||
| 
								 | 
							
										Vector<Variant::Type> argtypes;
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									jobject instance;
							 | 
						||
| 
								 | 
							
									Map<StringName,MethodData> method_map;
							 | 
						||
| 
								 | 
							
									JNIEnv *env;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									void update_env(JNIEnv *p_env) { env=p_env; }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									virtual Variant call(const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										print_line("attempt to call "+String(p_method));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										r_error.error=Variant::CallError::CALL_OK;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										Map<StringName,MethodData >::Element *E=method_map.find(p_method);
							 | 
						||
| 
								 | 
							
										if (!E) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											print_line("no exists");
							 | 
						||
| 
								 | 
							
											r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
							 | 
						||
| 
								 | 
							
											return Variant();
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										int ac = E->get().argtypes.size();
							 | 
						||
| 
								 | 
							
										if (ac<p_argcount) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											print_line("fewargs");
							 | 
						||
| 
								 | 
							
											r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
							 | 
						||
| 
								 | 
							
											r_error.argument=ac;
							 | 
						||
| 
								 | 
							
											return Variant();
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (ac>p_argcount) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											print_line("manyargs");
							 | 
						||
| 
								 | 
							
											r_error.error=Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
							 | 
						||
| 
								 | 
							
											r_error.argument=ac;
							 | 
						||
| 
								 | 
							
											return Variant();
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for(int i=0;i<p_argcount;i++) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (!Variant::can_convert(p_args[i]->get_type(),E->get().argtypes[i])) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
							 | 
						||
| 
								 | 
							
												r_error.argument=i;
							 | 
						||
| 
								 | 
							
												r_error.expected=E->get().argtypes[i];
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										jvalue *v=NULL;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (p_argcount) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											v=(jvalue*)alloca( sizeof(jvalue)*p_argcount );
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for(int i=0;i<p_argcount;i++) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											switch(E->get().argtypes[i]) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												case Variant::BOOL: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													v[i].z=*p_args[i];
							 | 
						||
| 
								 | 
							
												} break;
							 | 
						||
| 
								 | 
							
												case Variant::INT: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													v[i].i=*p_args[i];
							 | 
						||
| 
								 | 
							
												} break;
							 | 
						||
| 
								 | 
							
												case Variant::REAL: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													v[i].f=*p_args[i];
							 | 
						||
| 
								 | 
							
												} break;
							 | 
						||
| 
								 | 
							
												case Variant::STRING: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													String s = *p_args[i];
							 | 
						||
| 
								 | 
							
													jstring jStr = env->NewStringUTF(s.utf8().get_data());
							 | 
						||
| 
								 | 
							
													v[i].l=jStr;
							 | 
						||
| 
								 | 
							
												} break;
							 | 
						||
| 
								 | 
							
												case Variant::STRING_ARRAY: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													DVector<String> sarray = *p_args[i];
							 | 
						||
| 
								 | 
							
													jobjectArray arr = env->NewObjectArray(sarray.size(),env->FindClass("java/lang/String"),env->NewStringUTF(""));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													for(int j=0;j<sarray.size();j++) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														env->SetObjectArrayElement(arr,j,env->NewStringUTF( sarray[i].utf8().get_data() ));
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													v[i].l=arr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												} break;
							 | 
						||
| 
								 | 
							
												case Variant::INT_ARRAY: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													DVector<int> array = *p_args[i];
							 | 
						||
| 
								 | 
							
													jintArray arr = env->NewIntArray(array.size());
							 | 
						||
| 
								 | 
							
													DVector<int>::Read r = array.read();
							 | 
						||
| 
								 | 
							
													env->SetIntArrayRegion(arr,0,array.size(),r.ptr());
							 | 
						||
| 
								 | 
							
													v[i].l=arr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												} break;
							 | 
						||
| 
								 | 
							
												case Variant::REAL_ARRAY: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													DVector<float> array = *p_args[i];
							 | 
						||
| 
								 | 
							
													jfloatArray arr = env->NewFloatArray(array.size());
							 | 
						||
| 
								 | 
							
													DVector<float>::Read r = array.read();
							 | 
						||
| 
								 | 
							
													env->SetFloatArrayRegion(arr,0,array.size(),r.ptr());
							 | 
						||
| 
								 | 
							
													v[i].l=arr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												} break;
							 | 
						||
| 
								 | 
							
												default: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													ERR_FAIL_V(Variant());
							 | 
						||
| 
								 | 
							
												} break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										print_line("calling method!!");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										Variant ret;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										switch(E->get().ret_type) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											case Variant::NIL: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												print_line("call void");
							 | 
						||
| 
								 | 
							
												env->CallVoidMethodA(instance,E->get().method,v);
							 | 
						||
| 
								 | 
							
											} break;
							 | 
						||
| 
								 | 
							
											case Variant::BOOL: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												ret = env->CallBooleanMethodA(instance,E->get().method,v);
							 | 
						||
| 
								 | 
							
												print_line("call bool");
							 | 
						||
| 
								 | 
							
											} break;
							 | 
						||
| 
								 | 
							
											case Variant::INT: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												ret = env->CallIntMethodA(instance,E->get().method,v);
							 | 
						||
| 
								 | 
							
												print_line("call int");
							 | 
						||
| 
								 | 
							
											} break;
							 | 
						||
| 
								 | 
							
											case Variant::REAL: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												ret = env->CallFloatMethodA(instance,E->get().method,v);
							 | 
						||
| 
								 | 
							
											} break;
							 | 
						||
| 
								 | 
							
											case Variant::STRING: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												jobject o = env->CallObjectMethodA(instance,E->get().method,v);
							 | 
						||
| 
								 | 
							
												String singname = env->GetStringUTFChars((jstring)o, NULL );
							 | 
						||
| 
								 | 
							
											} break;
							 | 
						||
| 
								 | 
							
											case Variant::STRING_ARRAY: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												jobjectArray arr = (jobjectArray)env->CallObjectMethodA(instance,E->get().method,v);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												int stringCount = env->GetArrayLength(arr);
							 | 
						||
| 
								 | 
							
												DVector<String> sarr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												for (int i=0; i<stringCount; i++) {
							 | 
						||
| 
								 | 
							
													jstring string = (jstring) env->GetObjectArrayElement(arr, i);
							 | 
						||
| 
								 | 
							
													const char *rawString = env->GetStringUTFChars(string, 0);
							 | 
						||
| 
								 | 
							
													sarr.push_back(String(rawString));
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												ret=sarr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											} break;
							 | 
						||
| 
								 | 
							
											case Variant::INT_ARRAY: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												jintArray arr = (jintArray)env->CallObjectMethodA(instance,E->get().method,v);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												int fCount = env->GetArrayLength(arr);
							 | 
						||
| 
								 | 
							
												DVector<int> sarr;
							 | 
						||
| 
								 | 
							
												sarr.resize(fCount);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												DVector<int>::Write w = sarr.write();
							 | 
						||
| 
								 | 
							
												env->GetIntArrayRegion(arr,0,fCount,w.ptr());
							 | 
						||
| 
								 | 
							
												w = DVector<int>::Write();
							 | 
						||
| 
								 | 
							
												ret=sarr;
							 | 
						||
| 
								 | 
							
											} break;
							 | 
						||
| 
								 | 
							
											case Variant::REAL_ARRAY: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												jfloatArray arr = (jfloatArray)env->CallObjectMethodA(instance,E->get().method,v);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												int fCount = env->GetArrayLength(arr);
							 | 
						||
| 
								 | 
							
												DVector<float> sarr;
							 | 
						||
| 
								 | 
							
												sarr.resize(fCount);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												DVector<float>::Write w = sarr.write();
							 | 
						||
| 
								 | 
							
												env->GetFloatArrayRegion(arr,0,fCount,w.ptr());
							 | 
						||
| 
								 | 
							
												w = DVector<float>::Write();
							 | 
						||
| 
								 | 
							
												ret=sarr;
							 | 
						||
| 
								 | 
							
											} break;
							 | 
						||
| 
								 | 
							
											default: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												print_line("failure..");
							 | 
						||
| 
								 | 
							
												ERR_FAIL_V(Variant());
							 | 
						||
| 
								 | 
							
											} break;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										print_line("success");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return ret;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									jobject get_instance() const {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return instance;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									void set_instance(jobject p_instance) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										instance=p_instance;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									void add_method(const StringName& p_name, jmethodID p_method,const Vector<Variant::Type>& p_args, Variant::Type p_ret_type) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										MethodData md;
							 | 
						||
| 
								 | 
							
										md.method=p_method;
							 | 
						||
| 
								 | 
							
										md.argtypes=p_args;
							 | 
						||
| 
								 | 
							
										md.ret_type=p_ret_type;
							 | 
						||
| 
								 | 
							
										method_map[p_name]=md;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									JNISingleton() {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//JNIEnv *JNISingleton::env=NULL;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static HashMap<String,JNISingleton*> jni_singletons;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct engine {
							 | 
						||
| 
								 | 
							
								    struct android_app* app;
							 | 
						||
| 
								 | 
							
								    OS_Android *os;
							 | 
						||
| 
								 | 
							
								    JNIEnv *jni;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ASensorManager* sensorManager;
							 | 
						||
| 
								 | 
							
								    const ASensor* accelerometerSensor;
							 | 
						||
| 
								 | 
							
								    ASensorEventQueue* sensorEventQueue;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    bool display_active;
							 | 
						||
| 
								 | 
							
								    bool requested_quit;
							 | 
						||
| 
								 | 
							
								    int animating;
							 | 
						||
| 
								 | 
							
								    EGLDisplay display;
							 | 
						||
| 
								 | 
							
								    EGLSurface surface;
							 | 
						||
| 
								 | 
							
								    EGLContext context;
							 | 
						||
| 
								 | 
							
								    int32_t width;
							 | 
						||
| 
								 | 
							
								    int32_t height;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Initialize an EGL context for the current display.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static int engine_init_display(struct engine* engine,bool p_gl2) {
							 | 
						||
| 
								 | 
							
								    // initialize OpenGL ES and EGL
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /*
							 | 
						||
| 
								 | 
							
								     * Here specify the attributes of the desired configuration.
							 | 
						||
| 
								 | 
							
								     * Below, we select an EGLConfig with at least 8 bits per color
							 | 
						||
| 
								 | 
							
								     * component compatible with on-screen windows
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    const EGLint gl2_attribs[] = {
							 | 
						||
| 
								 | 
							
									  //  EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
							 | 
						||
| 
								 | 
							
									    EGL_BLUE_SIZE, 4,
							 | 
						||
| 
								 | 
							
									    EGL_GREEN_SIZE, 4,
							 | 
						||
| 
								 | 
							
									    EGL_RED_SIZE, 4,
							 | 
						||
| 
								 | 
							
									    EGL_ALPHA_SIZE, 0,
							 | 
						||
| 
								 | 
							
									    EGL_DEPTH_SIZE,     16,
							 | 
						||
| 
								 | 
							
									    EGL_STENCIL_SIZE,   EGL_DONT_CARE,
							 | 
						||
| 
								 | 
							
									    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
							 | 
						||
| 
								 | 
							
									    EGL_NONE
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const EGLint gl1_attribs[] = {
							 | 
						||
| 
								 | 
							
									  //  EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
							 | 
						||
| 
								 | 
							
									    EGL_BLUE_SIZE, 4,
							 | 
						||
| 
								 | 
							
									    EGL_GREEN_SIZE, 4,
							 | 
						||
| 
								 | 
							
									    EGL_RED_SIZE, 4,
							 | 
						||
| 
								 | 
							
									    EGL_ALPHA_SIZE, 0,
							 | 
						||
| 
								 | 
							
									    EGL_DEPTH_SIZE,     16,
							 | 
						||
| 
								 | 
							
									    EGL_STENCIL_SIZE,   EGL_DONT_CARE,
							 | 
						||
| 
								 | 
							
									    EGL_NONE
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const EGLint *attribs=p_gl2?gl2_attribs:gl1_attribs;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    EGLint w, h, dummy, format;
							 | 
						||
| 
								 | 
							
								    EGLint numConfigs;
							 | 
						||
| 
								 | 
							
								    EGLConfig config;
							 | 
						||
| 
								 | 
							
								    EGLSurface surface;
							 | 
						||
| 
								 | 
							
								    EGLContext context;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    eglInitialize(display, 0, 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Here, the application chooses the configuration it desires. In this
							 | 
						||
| 
								 | 
							
								     * sample, we have a very simplified selection process, where we pick
							 | 
						||
| 
								 | 
							
								     * the first EGLConfig that matches our criteria */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    eglChooseConfig(display, attribs, &config, 1, &numConfigs);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    LOGI("Num configs: %i\n",numConfigs);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
							 | 
						||
| 
								 | 
							
								     * guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
							 | 
						||
| 
								 | 
							
								     * As soon as we picked a EGLConfig, we can safely reconfigure the
							 | 
						||
| 
								 | 
							
								     * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
							 | 
						||
| 
								 | 
							
								    eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format);
							 | 
						||
| 
								 | 
							
								    //ANativeWindow_setFlags(engine->app->window, 0, 0, format|);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    surface = eglCreateWindowSurface(display, config, engine->app->window, NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const EGLint context_attribs[] = {
							 | 
						||
| 
								 | 
							
									    EGL_CONTEXT_CLIENT_VERSION,2,
							 | 
						||
| 
								 | 
							
									    EGL_NONE
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								    context = eglCreateContext(display, config, EGL_NO_CONTEXT, p_gl2?context_attribs:NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
							 | 
						||
| 
								 | 
							
									LOGW("Unable to eglMakeCurrent");
							 | 
						||
| 
								 | 
							
									return -1;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    eglQuerySurface(display, surface, EGL_WIDTH, &w);
							 | 
						||
| 
								 | 
							
								    eglQuerySurface(display, surface, EGL_HEIGHT, &h);
							 | 
						||
| 
								 | 
							
								    print_line("INIT VIDEO MODE: "+itos(w)+","+itos(h));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    //engine->os->set_egl_extensions(eglQueryString(display,EGL_EXTENSIONS));
							 | 
						||
| 
								 | 
							
								    engine->os->init_video_mode(w,h);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    engine->display = display;
							 | 
						||
| 
								 | 
							
								    engine->context = context;
							 | 
						||
| 
								 | 
							
								    engine->surface = surface;
							 | 
						||
| 
								 | 
							
								    engine->width = w;
							 | 
						||
| 
								 | 
							
								    engine->height = h;
							 | 
						||
| 
								 | 
							
								    engine->display_active=true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    //engine->state.angle = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Initialize GL state.
							 | 
						||
| 
								 | 
							
								    //glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
							 | 
						||
| 
								 | 
							
								    glEnable(GL_CULL_FACE);
							 | 
						||
| 
								 | 
							
								  //  glShadeModel(GL_SMOOTH);
							 | 
						||
| 
								 | 
							
								    glDisable(GL_DEPTH_TEST);
							 | 
						||
| 
								 | 
							
								    LOGI("GL Version: %s - %s %s\n", glGetString(GL_VERSION),glGetString(GL_VENDOR), glGetString(GL_RENDERER));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void engine_draw_frame(struct engine* engine) {
							 | 
						||
| 
								 | 
							
								    if (engine->display == NULL) {
							 | 
						||
| 
								 | 
							
									// No display.
							 | 
						||
| 
								 | 
							
									return;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Just fill the screen with a color.
							 | 
						||
| 
								 | 
							
								    //glClearColor(0,1,0,1);
							 | 
						||
| 
								 | 
							
								    //glClear(GL_COLOR_BUFFER_BIT);
							 | 
						||
| 
								 | 
							
								    if (engine->os && engine->os->main_loop_iterate()==true) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    engine->requested_quit=true;
							 | 
						||
| 
								 | 
							
									    return; //should exit instead
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    eglSwapBuffers(engine->display, engine->surface);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void engine_term_display(struct engine* engine) {
							 | 
						||
| 
								 | 
							
								    if (engine->display != EGL_NO_DISPLAY) {
							 | 
						||
| 
								 | 
							
									eglMakeCurrent(engine->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
							 | 
						||
| 
								 | 
							
									if (engine->context != EGL_NO_CONTEXT) {
							 | 
						||
| 
								 | 
							
									    eglDestroyContext(engine->display, engine->context);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if (engine->surface != EGL_NO_SURFACE) {
							 | 
						||
| 
								 | 
							
									    eglDestroySurface(engine->display, engine->surface);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									eglTerminate(engine->display);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    engine->animating = 0;
							 | 
						||
| 
								 | 
							
								    engine->display = EGL_NO_DISPLAY;
							 | 
						||
| 
								 | 
							
								    engine->context = EGL_NO_CONTEXT;
							 | 
						||
| 
								 | 
							
								    engine->surface = EGL_NO_SURFACE;
							 | 
						||
| 
								 | 
							
								    engine->display_active=false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Process the next input event.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) {
							 | 
						||
| 
								 | 
							
									struct engine* engine = (struct engine*)app->userData;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (!engine->os)
							 | 
						||
| 
								 | 
							
										return 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									switch(AInputEvent_getType(event)) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										case AINPUT_EVENT_TYPE_KEY: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											int ac = AKeyEvent_getAction(event);
							 | 
						||
| 
								 | 
							
											switch(ac) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												case AKEY_EVENT_ACTION_DOWN: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													int32_t code = AKeyEvent_getKeyCode(event);
							 | 
						||
| 
								 | 
							
													if (code==AKEYCODE_BACK) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														//AInputQueue_finishEvent(AInputQueue* queue, AInputEvent* event, int handled);
							 | 
						||
| 
								 | 
							
														if (engine->os)
							 | 
						||
| 
								 | 
							
															engine->os->main_loop_request_quit();
							 | 
						||
| 
								 | 
							
														return 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												} break;
							 | 
						||
| 
								 | 
							
												case AKEY_EVENT_ACTION_UP: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												} break;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										} break;
							 | 
						||
| 
								 | 
							
										case AINPUT_EVENT_TYPE_MOTION: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											Vector<OS_Android::TouchPos> touchvec;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											int pc = AMotionEvent_getPointerCount(event);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											touchvec.resize(pc);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											for(int i=0;i<pc;i++) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												touchvec[i].pos.x=AMotionEvent_getX(event,i);
							 | 
						||
| 
								 | 
							
												touchvec[i].pos.y=AMotionEvent_getY(event,i);
							 | 
						||
| 
								 | 
							
												touchvec[i].id=AMotionEvent_getPointerId(event,i);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											//System.out.printf("gaction: %d\n",event.getAction());
							 | 
						||
| 
								 | 
							
											int pidx=(AMotionEvent_getAction(event)&AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)>>8;
							 | 
						||
| 
								 | 
							
											switch(AMotionEvent_getAction(event)&AMOTION_EVENT_ACTION_MASK) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												case AMOTION_EVENT_ACTION_DOWN: {
							 | 
						||
| 
								 | 
							
													engine->os->process_touch(0,0,touchvec);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												    //System.out.printf("action down at: %f,%f\n", event.getX(),event.getY());
							 | 
						||
| 
								 | 
							
												} break;
							 | 
						||
| 
								 | 
							
												case AMOTION_EVENT_ACTION_MOVE: {
							 | 
						||
| 
								 | 
							
													engine->os->process_touch(1,0,touchvec);
							 | 
						||
| 
								 | 
							
												    //for(int i=0;i<event.getPointerCount();i++) {
							 | 
						||
| 
								 | 
							
												    //	System.out.printf("%d - moved to: %f,%f\n",i, event.getX(i),event.getY(i));
							 | 
						||
| 
								 | 
							
												    //}
							 | 
						||
| 
								 | 
							
												} break;
							 | 
						||
| 
								 | 
							
												case AMOTION_EVENT_ACTION_POINTER_UP: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													engine->os->process_touch(4,pidx,touchvec);
							 | 
						||
| 
								 | 
							
												    //System.out.printf("%d - s.up at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
							 | 
						||
| 
								 | 
							
												} break;
							 | 
						||
| 
								 | 
							
												case AMOTION_EVENT_ACTION_POINTER_DOWN: {
							 | 
						||
| 
								 | 
							
													engine->os->process_touch(3,pidx,touchvec);
							 | 
						||
| 
								 | 
							
												    //System.out.printf("%d - s.down at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
							 | 
						||
| 
								 | 
							
												} break;
							 | 
						||
| 
								 | 
							
												case AMOTION_EVENT_ACTION_CANCEL:
							 | 
						||
| 
								 | 
							
												case AMOTION_EVENT_ACTION_UP: {
							 | 
						||
| 
								 | 
							
													engine->os->process_touch(2,0,touchvec);
							 | 
						||
| 
								 | 
							
												    //for(int i=0;i<event.getPointerCount();i++) {
							 | 
						||
| 
								 | 
							
												    //	System.out.printf("%d - up! %f,%f\n",i, event.getX(i),event.getY(i));
							 | 
						||
| 
								 | 
							
												    //}
							 | 
						||
| 
								 | 
							
												} break;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											return 1;
							 | 
						||
| 
								 | 
							
										} break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Process the next main command.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void _gfx_init(void *ud,bool p_gl2) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									struct engine* engine = (struct engine*)ud;
							 | 
						||
| 
								 | 
							
									engine_init_display(engine,p_gl2);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
							 | 
						||
| 
								 | 
							
								    struct engine* engine = (struct engine*)app->userData;
							 | 
						||
| 
								 | 
							
								  // LOGI("**** CMD %i\n",cmd);
							 | 
						||
| 
								 | 
							
								    switch (cmd) {
							 | 
						||
| 
								 | 
							
									case APP_CMD_SAVE_STATE:
							 | 
						||
| 
								 | 
							
									    // The system has asked us to save our current state.  Do so.
							 | 
						||
| 
								 | 
							
									    //engine->app->savedState = malloc(sizeof(struct saved_state));
							 | 
						||
| 
								 | 
							
									    //*((struct saved_state*)engine->app->savedState) = engine->state;
							 | 
						||
| 
								 | 
							
									    //engine->app->savedStateSize = sizeof(struct saved_state);
							 | 
						||
| 
								 | 
							
									    break;
							 | 
						||
| 
								 | 
							
									case APP_CMD_CONFIG_CHANGED:
							 | 
						||
| 
								 | 
							
									case APP_CMD_WINDOW_RESIZED: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if 0
							 | 
						||
| 
								 | 
							
								// android blows
							 | 
						||
| 
								 | 
							
										if (engine->display_active) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											EGLint w,h;
							 | 
						||
| 
								 | 
							
											eglQuerySurface(engine->display, engine->surface, EGL_WIDTH, &w);
							 | 
						||
| 
								 | 
							
											eglQuerySurface(engine->display, engine->surface, EGL_HEIGHT, &h);
							 | 
						||
| 
								 | 
							
											engine->os->init_video_mode(w,h);
							 | 
						||
| 
								 | 
							
											//print_line("RESIZED VIDEO MODE: "+itos(w)+","+itos(h));
							 | 
						||
| 
								 | 
							
											engine_draw_frame(engine);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										    if (engine->display_active) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											    EGLint w,h;
							 | 
						||
| 
								 | 
							
											    eglQuerySurface(engine->display, engine->surface, EGL_WIDTH, &w);
							 | 
						||
| 
								 | 
							
											    eglQuerySurface(engine->display, engine->surface, EGL_HEIGHT, &h);
							 | 
						||
| 
								 | 
							
											  //  if (w==engine->os->get_video_mode().width && h==engine->os->get_video_mode().height)
							 | 
						||
| 
								 | 
							
												//    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											    engine_term_display(engine);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										    engine->os->reload_gfx();
							 | 
						||
| 
								 | 
							
										    engine_draw_frame(engine);
							 | 
						||
| 
								 | 
							
										    engine->animating=1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										    /*
							 | 
						||
| 
								 | 
							
											    EGLint w,h;
							 | 
						||
| 
								 | 
							
											    eglQuerySurface(engine->display, engine->surface, EGL_WIDTH, &w);
							 | 
						||
| 
								 | 
							
											    eglQuerySurface(engine->display, engine->surface, EGL_HEIGHT, &h);
							 | 
						||
| 
								 | 
							
											    engine->os->init_video_mode(w,h);
							 | 
						||
| 
								 | 
							
											    //print_line("RESIZED VIDEO MODE: "+itos(w)+","+itos(h));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										    }*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									} break;
							 | 
						||
| 
								 | 
							
									case APP_CMD_INIT_WINDOW:
							 | 
						||
| 
								 | 
							
									     //The window is being shown, get it ready.
							 | 
						||
| 
								 | 
							
									//	LOGI("INIT WINDOW");
							 | 
						||
| 
								 | 
							
										if (engine->app->window != NULL) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (engine->os==NULL) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												//do initialization here, when there's OpenGL! hackish but the only way
							 | 
						||
| 
								 | 
							
												engine->os = new OS_Android(_gfx_init,engine);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											//	char *args[]={"-test","gui",NULL};
							 | 
						||
| 
								 | 
							
												__android_log_print(ANDROID_LOG_INFO,"godot","pre asdasd setup...");
							 | 
						||
| 
								 | 
							
								#if 0
							 | 
						||
| 
								 | 
							
												Error err  = Main::setup("apk",2,args);
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
												Error err  = Main::setup("apk",0,NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												String modules = Globals::get_singleton()->get("android/modules");
							 | 
						||
| 
								 | 
							
												Vector<String> mods = modules.split(",",false);
							 | 
						||
| 
								 | 
							
												mods.push_back("GodotOS");
							 | 
						||
| 
								 | 
							
												__android_log_print(ANDROID_LOG_INFO,"godot","mod count: %i",mods.size());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if (mods.size()) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													jclass activityClass = engine->jni->FindClass("android/app/NativeActivity");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													jmethodID getClassLoader = engine->jni->GetMethodID(activityClass,"getClassLoader", "()Ljava/lang/ClassLoader;");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													jobject cls = engine->jni->CallObjectMethod(app->activity->clazz, getClassLoader);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													jclass classLoader = engine->jni->FindClass("java/lang/ClassLoader");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													jmethodID findClass = engine->jni->GetMethodID(classLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													static JNINativeMethod methods[] = {
							 | 
						||
| 
								 | 
							
													    {"registerSingleton",    "(Ljava/lang/String;Ljava/lang/Object;)V",(void *)&Java_com_android_godot_Godot_registerSingleton},
							 | 
						||
| 
								 | 
							
													    {"registerMethod",        "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V",(void *)&Java_com_android_godot_Godot_registerMethod},
							 | 
						||
| 
								 | 
							
													    {"getGlobal",      "(Ljava/lang/String;)Ljava/lang/String;",                    (void *)&Java_com_android_godot_Godot_getGlobal},
							 | 
						||
| 
								 | 
							
													};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													jstring gstrClassName = engine->jni->NewStringUTF("com/android/godot/Godot");
							 | 
						||
| 
								 | 
							
													jclass GodotClass = (jclass)engine->jni->CallObjectMethod(cls, findClass, gstrClassName);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													__android_log_print(ANDROID_LOG_INFO,"godot","godot ****^*^*?^*^*class data %x",GodotClass);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													engine->jni->RegisterNatives(GodotClass,methods,sizeof(methods)/sizeof(methods[0]));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													for (int i=0;i<mods.size();i++) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														String m = mods[i];
							 | 
						||
| 
								 | 
							
														//jclass singletonClass = engine->jni->FindClass(m.utf8().get_data());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														jstring strClassName = engine->jni->NewStringUTF(m.utf8().get_data());
							 | 
						||
| 
								 | 
							
														jclass singletonClass = (jclass)engine->jni->CallObjectMethod(cls, findClass, strClassName);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														__android_log_print(ANDROID_LOG_INFO,"godot","****^*^*?^*^*class data %x",singletonClass);
							 | 
						||
| 
								 | 
							
														jmethodID initialize = engine->jni->GetStaticMethodID(singletonClass, "initialize", "(Landroid/app/Activity;)Lcom/android/godot/Godot$SingletonBase;");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														jobject obj = engine->jni->CallStaticObjectMethod(singletonClass,initialize,app->activity->clazz);
							 | 
						||
| 
								 | 
							
														__android_log_print(ANDROID_LOG_INFO,"godot","****^*^*?^*^*class instance %x",obj);
							 | 
						||
| 
								 | 
							
														jobject gob = engine->jni->NewGlobalRef(obj);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if (!Main::start())
							 | 
						||
| 
								 | 
							
													 return; //should exit instead and print the error
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												engine->os->main_loop_begin();
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
												//i guess recreate resources?
							 | 
						||
| 
								 | 
							
												engine->os->reload_gfx();
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											engine->animating=1;
							 | 
						||
| 
								 | 
							
											engine_draw_frame(engine);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									    break;
							 | 
						||
| 
								 | 
							
									case APP_CMD_TERM_WINDOW:
							 | 
						||
| 
								 | 
							
									    // The window is being hidden or closed, clean it up.
							 | 
						||
| 
								 | 
							
									//    LOGI("TERM WINDOW");
							 | 
						||
| 
								 | 
							
									    engine_term_display(engine);
							 | 
						||
| 
								 | 
							
									    break;
							 | 
						||
| 
								 | 
							
									case APP_CMD_GAINED_FOCUS:
							 | 
						||
| 
								 | 
							
									    // When our app gains focus, we start monitoring the accelerometer.
							 | 
						||
| 
								 | 
							
									    if (engine->accelerometerSensor != NULL) {
							 | 
						||
| 
								 | 
							
										ASensorEventQueue_enableSensor(engine->sensorEventQueue,
							 | 
						||
| 
								 | 
							
											engine->accelerometerSensor);
							 | 
						||
| 
								 | 
							
										// We'd like to get 60 events per second (in us).
							 | 
						||
| 
								 | 
							
										ASensorEventQueue_setEventRate(engine->sensorEventQueue,
							 | 
						||
| 
								 | 
							
											engine->accelerometerSensor, (1000L/60)*1000);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    }
							 | 
						||
| 
								 | 
							
									    engine->animating = 1;
							 | 
						||
| 
								 | 
							
									    break;
							 | 
						||
| 
								 | 
							
									case APP_CMD_LOST_FOCUS:
							 | 
						||
| 
								 | 
							
									    // When our app loses focus, we stop monitoring the accelerometer.
							 | 
						||
| 
								 | 
							
									    // This is to avoid consuming battery while not being used.
							 | 
						||
| 
								 | 
							
									    if (engine->accelerometerSensor != NULL) {
							 | 
						||
| 
								 | 
							
										ASensorEventQueue_disableSensor(engine->sensorEventQueue,
							 | 
						||
| 
								 | 
							
											engine->accelerometerSensor);
							 | 
						||
| 
								 | 
							
									    }
							 | 
						||
| 
								 | 
							
									    // Also stop animating.
							 | 
						||
| 
								 | 
							
									    engine->animating = 0;
							 | 
						||
| 
								 | 
							
									    engine_draw_frame(engine);
							 | 
						||
| 
								 | 
							
									    break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void android_main(struct android_app* state) {
							 | 
						||
| 
								 | 
							
								    struct engine engine;
							 | 
						||
| 
								 | 
							
								    // Make sure glue isn't stripped.
							 | 
						||
| 
								 | 
							
								    app_dummy();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     memset(&engine, 0, sizeof(engine));
							 | 
						||
| 
								 | 
							
								     state->userData = &engine;
							 | 
						||
| 
								 | 
							
								     state->onAppCmd = engine_handle_cmd;
							 | 
						||
| 
								 | 
							
								     state->onInputEvent = engine_handle_input;
							 | 
						||
| 
								 | 
							
								     engine.app = state;
							 | 
						||
| 
								 | 
							
								     engine.requested_quit=false;
							 | 
						||
| 
								 | 
							
								     engine.os=NULL;
							 | 
						||
| 
								 | 
							
								     engine.display_active=false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     FileAccessAndroid::asset_manager=state->activity->assetManager;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     // Prepare to monitor accelerometer
							 | 
						||
| 
								 | 
							
								     engine.sensorManager = ASensorManager_getInstance();
							 | 
						||
| 
								 | 
							
								     engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
							 | 
						||
| 
								 | 
							
									     ASENSOR_TYPE_ACCELEROMETER);
							 | 
						||
| 
								 | 
							
								     engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager,
							 | 
						||
| 
								 | 
							
									     state->looper, LOOPER_ID_USER, NULL, NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									ANativeActivity_setWindowFlags(state->activity,AWINDOW_FLAG_FULLSCREEN|AWINDOW_FLAG_KEEP_SCREEN_ON,0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									state->activity->vm->AttachCurrentThread(&engine.jni, NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     // loop waiting for stuff to do.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     while (1) {
							 | 
						||
| 
								 | 
							
									 // Read all pending events.
							 | 
						||
| 
								 | 
							
									 int ident;
							 | 
						||
| 
								 | 
							
									 int events;
							 | 
						||
| 
								 | 
							
									 struct android_poll_source* source;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									 // If not animating, we will block forever waiting for events.
							 | 
						||
| 
								 | 
							
									 // If animating, we loop until all events are read, then continue
							 | 
						||
| 
								 | 
							
									 // to draw the next frame of animation.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									 int nullmax=50;
							 | 
						||
| 
								 | 
							
									 while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events,
							 | 
						||
| 
								 | 
							
										 (void**)&source)) >= 0) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									     // Process this event.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									     if (source != NULL) {
							 | 
						||
| 
								 | 
							
									//	 LOGI("process\n");
							 | 
						||
| 
								 | 
							
										 source->process(state, source);
							 | 
						||
| 
								 | 
							
									     } else {
							 | 
						||
| 
								 | 
							
										     nullmax--;
							 | 
						||
| 
								 | 
							
										     if (nullmax<0)
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
									     }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									     // If a sensor has data, process it now.
							 | 
						||
| 
								 | 
							
									    // LOGI("events\n");
							 | 
						||
| 
								 | 
							
									     if (ident == LOOPER_ID_USER) {
							 | 
						||
| 
								 | 
							
										 if (engine.accelerometerSensor != NULL) {
							 | 
						||
| 
								 | 
							
										     ASensorEvent event;
							 | 
						||
| 
								 | 
							
										     while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
							 | 
						||
| 
								 | 
							
											     &event, 1) > 0) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											     if (engine.os) {
							 | 
						||
| 
								 | 
							
												     engine.os->process_accelerometer(Vector3(event.acceleration.x, event.acceleration.y,
							 | 
						||
| 
								 | 
							
																	      event.acceleration.z));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											     }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										     }
							 | 
						||
| 
								 | 
							
										 }
							 | 
						||
| 
								 | 
							
									     }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									     // Check if we are exiting.
							 | 
						||
| 
								 | 
							
									     if (state->destroyRequested != 0) {
							 | 
						||
| 
								 | 
							
										     if (engine.os) {
							 | 
						||
| 
								 | 
							
											     engine.os->main_loop_request_quit();
							 | 
						||
| 
								 | 
							
										     }
							 | 
						||
| 
								 | 
							
										    state->destroyRequested=0;
							 | 
						||
| 
								 | 
							
									     }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									     if (engine.requested_quit) {
							 | 
						||
| 
								 | 
							
										engine_term_display(&engine);
							 | 
						||
| 
								 | 
							
										exit(0);
							 | 
						||
| 
								 | 
							
										return;
							 | 
						||
| 
								 | 
							
									     }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//	     LOGI("end\n");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									 }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//	 LOGI("engine animating? %i\n",engine.animating);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									 if (engine.animating) {
							 | 
						||
| 
								 | 
							
									     //do os render
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									     engine_draw_frame(&engine);
							 | 
						||
| 
								 | 
							
									     //LOGI("TERM WINDOW");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									 }
							 | 
						||
| 
								 | 
							
								     }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								JNIEXPORT void JNICALL Java_com_android_godot_Godot_registerSingleton(JNIEnv * env, jobject obj, jstring name,jobject p_object){
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									String singname = env->GetStringUTFChars( name, NULL );
							 | 
						||
| 
								 | 
							
									JNISingleton *s = memnew( JNISingleton );
							 | 
						||
| 
								 | 
							
									s->update_env(env);
							 | 
						||
| 
								 | 
							
									s->set_instance(env->NewGlobalRef(p_object));
							 | 
						||
| 
								 | 
							
									jni_singletons[singname]=s;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									Globals::get_singleton()->add_singleton(Globals::Singleton(singname,s));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static Variant::Type get_jni_type(const String& p_type) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									static struct {
							 | 
						||
| 
								 | 
							
										const char *name;
							 | 
						||
| 
								 | 
							
										Variant::Type type;
							 | 
						||
| 
								 | 
							
									} _type_to_vtype[]={
							 | 
						||
| 
								 | 
							
										{"void",Variant::NIL},
							 | 
						||
| 
								 | 
							
										{"boolean",Variant::BOOL},
							 | 
						||
| 
								 | 
							
										{"int",Variant::INT},
							 | 
						||
| 
								 | 
							
										{"float",Variant::REAL},
							 | 
						||
| 
								 | 
							
										{"java.lang.String",Variant::STRING},
							 | 
						||
| 
								 | 
							
										{"[I",Variant::INT_ARRAY},
							 | 
						||
| 
								 | 
							
										{"[F",Variant::REAL_ARRAY},
							 | 
						||
| 
								 | 
							
										{"[java.lang.String",Variant::STRING_ARRAY},
							 | 
						||
| 
								 | 
							
										{NULL,Variant::NIL}
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int idx=0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									while (_type_to_vtype[idx].name) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (p_type==_type_to_vtype[idx].name)
							 | 
						||
| 
								 | 
							
											return _type_to_vtype[idx].type;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										idx++;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return Variant::NIL;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static const char* get_jni_sig(const String& p_type) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									static struct {
							 | 
						||
| 
								 | 
							
										const char *name;
							 | 
						||
| 
								 | 
							
										const char *sig;
							 | 
						||
| 
								 | 
							
									} _type_to_vtype[]={
							 | 
						||
| 
								 | 
							
										{"void","V"},
							 | 
						||
| 
								 | 
							
										{"boolean","Z"},
							 | 
						||
| 
								 | 
							
										{"int","I"},
							 | 
						||
| 
								 | 
							
										{"float","F"},
							 | 
						||
| 
								 | 
							
										{"java.lang.String","Ljava/lang/String;"},
							 | 
						||
| 
								 | 
							
										{"[I","[I"},
							 | 
						||
| 
								 | 
							
										{"[F","[F"},
							 | 
						||
| 
								 | 
							
										{"[java.lang.String","[Ljava/lang/String;"},
							 | 
						||
| 
								 | 
							
										{NULL,"V"}
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int idx=0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									while (_type_to_vtype[idx].name) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (p_type==_type_to_vtype[idx].name)
							 | 
						||
| 
								 | 
							
											return _type_to_vtype[idx].sig;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										idx++;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return "";
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								JNIEXPORT jstring JNICALL Java_com_android_godot_Godot_getGlobal(JNIEnv * env, jobject obj, jstring path) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									String js = env->GetStringUTFChars( path, NULL );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return env->NewStringUTF(Globals::get_singleton()->get(js).operator String().utf8().get_data());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								JNIEXPORT void JNICALL Java_com_android_godot_Godot_registerMethod(JNIEnv * env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args){
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									String singname = env->GetStringUTFChars( sname, NULL );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									ERR_FAIL_COND(!jni_singletons.has(singname));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									JNISingleton *s = jni_singletons.get(singname);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									String mname = env->GetStringUTFChars( name, NULL );
							 | 
						||
| 
								 | 
							
									String retval = env->GetStringUTFChars( ret, NULL );
							 | 
						||
| 
								 | 
							
									Vector<Variant::Type> types;
							 | 
						||
| 
								 | 
							
									String cs="(";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int stringCount = env->GetArrayLength(args);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									print_line("Singl:  "+singname+" Method: "+mname+" RetVal: "+retval);
							 | 
						||
| 
								 | 
							
									for (int i=0; i<stringCount; i++) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										jstring string = (jstring) env->GetObjectArrayElement(args, i);
							 | 
						||
| 
								 | 
							
										const char *rawString = env->GetStringUTFChars(string, 0);
							 | 
						||
| 
								 | 
							
										types.push_back(get_jni_type(String(rawString)));
							 | 
						||
| 
								 | 
							
										cs+=get_jni_sig(String(rawString));
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									cs+=")";
							 | 
						||
| 
								 | 
							
									cs+=get_jni_sig(retval);
							 | 
						||
| 
								 | 
							
									jclass cls = env->GetObjectClass(s->get_instance());
							 | 
						||
| 
								 | 
							
									print_line("METHOD: "+mname+" sig: "+cs);
							 | 
						||
| 
								 | 
							
									jmethodID mid = env->GetMethodID(cls, mname.ascii().get_data(), cs.ascii().get_data());
							 | 
						||
| 
								 | 
							
									if (!mid) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										print_line("FAILED GETTING METHOID "+mname);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									s->add_method(mname,mid,types,get_jni_type(retval));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif
							 |