2014-02-10 02:10:30 +01:00
|
|
|
/*************************************************************************/
|
2019-03-13 13:51:55 +01:00
|
|
|
/* java_godot_lib_jni.cpp */
|
2014-02-10 02:10:30 +01:00
|
|
|
/*************************************************************************/
|
|
|
|
/* This file is part of: */
|
|
|
|
/* GODOT ENGINE */
|
2017-08-27 14:16:55 +02:00
|
|
|
/* https://godotengine.org */
|
2014-02-10 02:10:30 +01:00
|
|
|
/*************************************************************************/
|
2020-01-01 11:16:22 +01:00
|
|
|
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
|
|
|
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
2014-02-10 02:10:30 +01:00
|
|
|
/* */
|
|
|
|
/* 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. */
|
|
|
|
/*************************************************************************/
|
2018-01-05 00:50:27 +01:00
|
|
|
|
2019-03-13 13:51:55 +01:00
|
|
|
#include "java_godot_lib_jni.h"
|
|
|
|
#include "java_godot_io_wrapper.h"
|
|
|
|
#include "java_godot_wrapper.h"
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
#include "android/asset_manager_jni.h"
|
2020-01-19 20:02:40 +01:00
|
|
|
#include "api/java_class_wrapper.h"
|
2014-02-10 02:10:30 +01:00
|
|
|
#include "audio_driver_jandroid.h"
|
2018-09-11 18:13:45 +02:00
|
|
|
#include "core/engine.h"
|
2014-02-10 02:10:30 +01:00
|
|
|
#include "core/os/keyboard.h"
|
2018-09-11 18:13:45 +02:00
|
|
|
#include "core/project_settings.h"
|
2017-03-05 16:44:50 +01:00
|
|
|
#include "dir_access_jandroid.h"
|
|
|
|
#include "file_access_android.h"
|
|
|
|
#include "file_access_jandroid.h"
|
2016-01-24 05:11:59 +01:00
|
|
|
#include "main/input_default.h"
|
2017-03-05 16:44:50 +01:00
|
|
|
#include "main/main.h"
|
2019-11-25 15:01:44 +01:00
|
|
|
#include "net_socket_android.h"
|
2017-03-05 16:44:50 +01:00
|
|
|
#include "os_android.h"
|
2019-02-26 21:54:45 +01:00
|
|
|
#include "string_android.h"
|
2017-03-05 16:44:50 +01:00
|
|
|
#include "thread_jandroid.h"
|
|
|
|
#include <unistd.h>
|
2014-09-03 04:13:40 +02:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
static JavaClassWrapper *java_class_wrapper = NULL;
|
|
|
|
static OS_Android *os_android = NULL;
|
2019-03-13 13:51:55 +01:00
|
|
|
static GodotJavaWrapper *godot_java = NULL;
|
|
|
|
static GodotIOJavaWrapper *godot_io_java = NULL;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2015-03-03 18:39:13 +01:00
|
|
|
struct jvalret {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2015-03-03 18:39:13 +01:00
|
|
|
jobject obj;
|
|
|
|
jvalue val;
|
2017-03-05 16:44:50 +01:00
|
|
|
jvalret() { obj = NULL; }
|
2015-03-03 18:39:13 +01:00
|
|
|
};
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
jvalret _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant *p_arg, bool force_jobject = false) {
|
2015-03-03 18:39:13 +01:00
|
|
|
|
|
|
|
jvalret v;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
switch (p_type) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
case Variant::BOOL: {
|
|
|
|
|
|
|
|
if (force_jobject) {
|
|
|
|
jclass bclass = env->FindClass("java/lang/Boolean");
|
|
|
|
jmethodID ctor = env->GetMethodID(bclass, "<init>", "(Z)V");
|
|
|
|
jvalue val;
|
|
|
|
val.z = (bool)(*p_arg);
|
|
|
|
jobject obj = env->NewObjectA(bclass, ctor, &val);
|
2015-03-03 18:39:13 +01:00
|
|
|
v.val.l = obj;
|
2017-03-05 16:44:50 +01:00
|
|
|
v.obj = obj;
|
2015-03-03 18:39:13 +01:00
|
|
|
env->DeleteLocalRef(bclass);
|
2014-02-10 02:10:30 +01:00
|
|
|
} else {
|
2017-03-05 16:44:50 +01:00
|
|
|
v.val.z = *p_arg;
|
2014-02-10 02:10:30 +01:00
|
|
|
};
|
|
|
|
} break;
|
|
|
|
case Variant::INT: {
|
|
|
|
|
|
|
|
if (force_jobject) {
|
|
|
|
|
|
|
|
jclass bclass = env->FindClass("java/lang/Integer");
|
|
|
|
jmethodID ctor = env->GetMethodID(bclass, "<init>", "(I)V");
|
|
|
|
jvalue val;
|
|
|
|
val.i = (int)(*p_arg);
|
|
|
|
jobject obj = env->NewObjectA(bclass, ctor, &val);
|
2015-03-03 18:39:13 +01:00
|
|
|
v.val.l = obj;
|
2017-03-05 16:44:50 +01:00
|
|
|
v.obj = obj;
|
2015-03-03 18:39:13 +01:00
|
|
|
env->DeleteLocalRef(bclass);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
} else {
|
2017-03-05 16:44:50 +01:00
|
|
|
v.val.i = *p_arg;
|
2014-02-10 02:10:30 +01:00
|
|
|
};
|
|
|
|
} break;
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
case Variant::FLOAT: {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
if (force_jobject) {
|
|
|
|
|
|
|
|
jclass bclass = env->FindClass("java/lang/Double");
|
|
|
|
jmethodID ctor = env->GetMethodID(bclass, "<init>", "(D)V");
|
|
|
|
jvalue val;
|
|
|
|
val.d = (double)(*p_arg);
|
|
|
|
jobject obj = env->NewObjectA(bclass, ctor, &val);
|
2015-03-03 18:39:13 +01:00
|
|
|
v.val.l = obj;
|
2017-03-05 16:44:50 +01:00
|
|
|
v.obj = obj;
|
2015-03-03 18:39:13 +01:00
|
|
|
env->DeleteLocalRef(bclass);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
} else {
|
2017-03-05 16:44:50 +01:00
|
|
|
v.val.f = *p_arg;
|
2014-02-10 02:10:30 +01:00
|
|
|
};
|
|
|
|
} break;
|
|
|
|
case Variant::STRING: {
|
|
|
|
|
|
|
|
String s = *p_arg;
|
|
|
|
jstring jStr = env->NewStringUTF(s.utf8().get_data());
|
2017-03-05 16:44:50 +01:00
|
|
|
v.val.l = jStr;
|
|
|
|
v.obj = jStr;
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
2020-02-17 22:06:54 +01:00
|
|
|
case Variant::PACKED_STRING_ARRAY: {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-02-17 22:06:54 +01:00
|
|
|
Vector<String> sarray = *p_arg;
|
2017-03-05 16:44:50 +01:00
|
|
|
jobjectArray arr = env->NewObjectArray(sarray.size(), env->FindClass("java/lang/String"), env->NewStringUTF(""));
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
for (int j = 0; j < sarray.size(); j++) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
jstring str = env->NewStringUTF(sarray[j].utf8().get_data());
|
|
|
|
env->SetObjectArrayElement(arr, j, str);
|
2015-03-03 18:39:13 +01:00
|
|
|
env->DeleteLocalRef(str);
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
2017-03-05 16:44:50 +01:00
|
|
|
v.val.l = arr;
|
|
|
|
v.obj = arr;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case Variant::DICTIONARY: {
|
|
|
|
|
|
|
|
Dictionary dict = *p_arg;
|
2016-01-08 21:53:00 +01:00
|
|
|
jclass dclass = env->FindClass("org/godotengine/godot/Dictionary");
|
2014-02-10 02:10:30 +01:00
|
|
|
jmethodID ctor = env->GetMethodID(dclass, "<init>", "()V");
|
|
|
|
jobject jdict = env->NewObject(dclass, ctor);
|
|
|
|
|
|
|
|
Array keys = dict.keys();
|
|
|
|
|
|
|
|
jobjectArray jkeys = env->NewObjectArray(keys.size(), env->FindClass("java/lang/String"), env->NewStringUTF(""));
|
2017-03-05 16:44:50 +01:00
|
|
|
for (int j = 0; j < keys.size(); j++) {
|
2015-03-03 18:39:13 +01:00
|
|
|
jstring str = env->NewStringUTF(String(keys[j]).utf8().get_data());
|
|
|
|
env->SetObjectArrayElement(jkeys, j, str);
|
|
|
|
env->DeleteLocalRef(str);
|
2014-02-10 02:10:30 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
jmethodID set_keys = env->GetMethodID(dclass, "set_keys", "([Ljava/lang/String;)V");
|
|
|
|
jvalue val;
|
|
|
|
val.l = jkeys;
|
|
|
|
env->CallVoidMethodA(jdict, set_keys, &val);
|
2015-03-03 18:39:13 +01:00
|
|
|
env->DeleteLocalRef(jkeys);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
jobjectArray jvalues = env->NewObjectArray(keys.size(), env->FindClass("java/lang/Object"), NULL);
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
for (int j = 0; j < keys.size(); j++) {
|
2014-02-10 02:10:30 +01:00
|
|
|
Variant var = dict[keys[j]];
|
2015-03-03 18:39:13 +01:00
|
|
|
jvalret v = _variant_to_jvalue(env, var.get_type(), &var, true);
|
|
|
|
env->SetObjectArrayElement(jvalues, j, v.val.l);
|
|
|
|
if (v.obj) {
|
|
|
|
env->DeleteLocalRef(v.obj);
|
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
jmethodID set_values = env->GetMethodID(dclass, "set_values", "([Ljava/lang/Object;)V");
|
|
|
|
val.l = jvalues;
|
|
|
|
env->CallVoidMethodA(jdict, set_values, &val);
|
2015-03-03 18:39:13 +01:00
|
|
|
env->DeleteLocalRef(jvalues);
|
|
|
|
env->DeleteLocalRef(dclass);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2015-03-03 18:39:13 +01:00
|
|
|
v.val.l = jdict;
|
2017-03-05 16:44:50 +01:00
|
|
|
v.obj = jdict;
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
|
|
|
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
case Variant::PACKED_INT32_ARRAY: {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-02-17 22:06:54 +01:00
|
|
|
Vector<int> array = *p_arg;
|
2014-02-10 02:10:30 +01:00
|
|
|
jintArray arr = env->NewIntArray(array.size());
|
2020-02-17 22:06:54 +01:00
|
|
|
const int *r = array.ptr();
|
2017-03-05 16:44:50 +01:00
|
|
|
env->SetIntArrayRegion(arr, 0, array.size(), r.ptr());
|
|
|
|
v.val.l = arr;
|
|
|
|
v.obj = arr;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2014-06-04 05:32:49 +02:00
|
|
|
} break;
|
2020-02-17 22:06:54 +01:00
|
|
|
case Variant::PACKED_BYTE_ARRAY: {
|
|
|
|
Vector<uint8_t> array = *p_arg;
|
2014-06-04 05:32:49 +02:00
|
|
|
jbyteArray arr = env->NewByteArray(array.size());
|
2020-02-17 22:06:54 +01:00
|
|
|
const uint8_t *r = array.ptr();
|
2017-03-05 16:44:50 +01:00
|
|
|
env->SetByteArrayRegion(arr, 0, array.size(), reinterpret_cast<const signed char *>(r.ptr()));
|
|
|
|
v.val.l = arr;
|
|
|
|
v.obj = arr;
|
2014-06-04 05:32:49 +02:00
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
case Variant::PACKED_FLOAT32_ARRAY: {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-02-17 22:06:54 +01:00
|
|
|
Vector<float> array = *p_arg;
|
2014-02-10 02:10:30 +01:00
|
|
|
jfloatArray arr = env->NewFloatArray(array.size());
|
2020-02-17 22:06:54 +01:00
|
|
|
const float *r = array.ptr();
|
2017-03-05 16:44:50 +01:00
|
|
|
env->SetFloatArrayRegion(arr, 0, array.size(), r.ptr());
|
|
|
|
v.val.l = arr;
|
|
|
|
v.obj = arr;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
} break;
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
#ifndef _MSC_VER
|
|
|
|
#warning This is missing 64 bits arrays, I have no idea how to do it in JNI
|
|
|
|
#endif
|
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
default: {
|
|
|
|
|
2015-03-03 18:39:13 +01:00
|
|
|
v.val.i = 0;
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
|
|
|
}
|
|
|
|
return v;
|
2016-07-21 12:07:01 +02:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
String _get_class_name(JNIEnv *env, jclass cls, bool *array) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
jclass cclass = env->FindClass("java/lang/Class");
|
|
|
|
jmethodID getName = env->GetMethodID(cclass, "getName", "()Ljava/lang/String;");
|
2017-03-05 16:44:50 +01:00
|
|
|
jstring clsName = (jstring)env->CallObjectMethod(cls, getName);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
if (array) {
|
|
|
|
jmethodID isArray = env->GetMethodID(cclass, "isArray", "()Z");
|
|
|
|
jboolean isarr = env->CallBooleanMethod(cls, isArray);
|
|
|
|
(*array) = isarr ? true : false;
|
|
|
|
}
|
2019-02-26 21:54:45 +01:00
|
|
|
String name = jstring_to_string(clsName, env);
|
2015-03-03 18:39:13 +01:00
|
|
|
env->DeleteLocalRef(clsName);
|
|
|
|
|
|
|
|
return name;
|
2016-07-21 12:07:01 +02:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
Variant _jobject_to_variant(JNIEnv *env, jobject obj) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2016-07-04 21:41:46 +02:00
|
|
|
if (obj == NULL) {
|
|
|
|
return Variant();
|
|
|
|
}
|
2017-03-05 16:44:50 +01:00
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
jclass c = env->GetObjectClass(obj);
|
|
|
|
bool array;
|
|
|
|
String name = _get_class_name(env, c, &array);
|
|
|
|
|
|
|
|
if (name == "java.lang.String") {
|
|
|
|
|
2019-02-26 21:54:45 +01:00
|
|
|
return jstring_to_string((jstring)obj, env);
|
2014-02-10 02:10:30 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
if (name == "[Ljava.lang.String;") {
|
|
|
|
|
|
|
|
jobjectArray arr = (jobjectArray)obj;
|
|
|
|
int stringCount = env->GetArrayLength(arr);
|
2020-02-17 22:06:54 +01:00
|
|
|
Vector<String> sarr;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
for (int i = 0; i < stringCount; i++) {
|
|
|
|
jstring string = (jstring)env->GetObjectArrayElement(arr, i);
|
2019-02-26 21:54:45 +01:00
|
|
|
sarr.push_back(jstring_to_string(string, env));
|
2015-03-03 18:39:13 +01:00
|
|
|
env->DeleteLocalRef(string);
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return sarr;
|
|
|
|
};
|
|
|
|
|
|
|
|
if (name == "java.lang.Boolean") {
|
|
|
|
|
|
|
|
jmethodID boolValue = env->GetMethodID(c, "booleanValue", "()Z");
|
|
|
|
bool ret = env->CallBooleanMethod(obj, boolValue);
|
|
|
|
return ret;
|
|
|
|
};
|
|
|
|
|
2018-11-20 13:07:24 +01:00
|
|
|
if (name == "java.lang.Integer" || name == "java.lang.Long") {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
jclass nclass = env->FindClass("java/lang/Number");
|
2018-11-20 13:07:24 +01:00
|
|
|
jmethodID longValue = env->GetMethodID(nclass, "longValue", "()J");
|
|
|
|
jlong ret = env->CallLongMethod(obj, longValue);
|
2014-02-10 02:10:30 +01:00
|
|
|
return ret;
|
|
|
|
};
|
|
|
|
|
|
|
|
if (name == "[I") {
|
|
|
|
|
|
|
|
jintArray arr = (jintArray)obj;
|
|
|
|
int fCount = env->GetArrayLength(arr);
|
2020-02-17 22:06:54 +01:00
|
|
|
Vector<int> sarr;
|
2014-02-10 02:10:30 +01:00
|
|
|
sarr.resize(fCount);
|
|
|
|
|
2020-02-17 22:06:54 +01:00
|
|
|
int *w = sarr.ptrw();
|
2017-03-05 16:44:50 +01:00
|
|
|
env->GetIntArrayRegion(arr, 0, fCount, w.ptr());
|
2019-07-05 19:08:43 +02:00
|
|
|
w.release();
|
2014-02-10 02:10:30 +01:00
|
|
|
return sarr;
|
|
|
|
};
|
|
|
|
|
2014-06-04 05:32:49 +02:00
|
|
|
if (name == "[B") {
|
|
|
|
|
|
|
|
jbyteArray arr = (jbyteArray)obj;
|
|
|
|
int fCount = env->GetArrayLength(arr);
|
2020-02-17 22:06:54 +01:00
|
|
|
Vector<uint8_t> sarr;
|
2014-06-04 05:32:49 +02:00
|
|
|
sarr.resize(fCount);
|
|
|
|
|
2020-02-17 22:06:54 +01:00
|
|
|
uint8_t *w = sarr.ptrw();
|
2017-03-05 16:44:50 +01:00
|
|
|
env->GetByteArrayRegion(arr, 0, fCount, reinterpret_cast<signed char *>(w.ptr()));
|
2019-07-05 19:08:43 +02:00
|
|
|
w.release();
|
2014-06-04 05:32:49 +02:00
|
|
|
return sarr;
|
|
|
|
};
|
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
if (name == "java.lang.Float" || name == "java.lang.Double") {
|
|
|
|
|
|
|
|
jclass nclass = env->FindClass("java/lang/Number");
|
|
|
|
jmethodID doubleValue = env->GetMethodID(nclass, "doubleValue", "()D");
|
|
|
|
double ret = env->CallDoubleMethod(obj, doubleValue);
|
|
|
|
return ret;
|
|
|
|
};
|
|
|
|
|
|
|
|
if (name == "[D") {
|
|
|
|
|
|
|
|
jdoubleArray arr = (jdoubleArray)obj;
|
|
|
|
int fCount = env->GetArrayLength(arr);
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
PackedFloat32Array sarr;
|
2014-02-10 02:10:30 +01:00
|
|
|
sarr.resize(fCount);
|
|
|
|
|
2020-02-17 22:06:54 +01:00
|
|
|
real_t *w = sarr.ptrw();
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
for (int i = 0; i < fCount; i++) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
double n;
|
|
|
|
env->GetDoubleArrayRegion(arr, i, 1, &n);
|
|
|
|
w.ptr()[i] = n;
|
|
|
|
};
|
|
|
|
return sarr;
|
|
|
|
};
|
|
|
|
|
|
|
|
if (name == "[F") {
|
|
|
|
|
|
|
|
jfloatArray arr = (jfloatArray)obj;
|
|
|
|
int fCount = env->GetArrayLength(arr);
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
PackedFloat32Array sarr;
|
2014-02-10 02:10:30 +01:00
|
|
|
sarr.resize(fCount);
|
|
|
|
|
2020-02-17 22:06:54 +01:00
|
|
|
real_t *w = sarr.ptrw();
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
for (int i = 0; i < fCount; i++) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
float n;
|
|
|
|
env->GetFloatArrayRegion(arr, i, 1, &n);
|
|
|
|
w.ptr()[i] = n;
|
|
|
|
};
|
|
|
|
return sarr;
|
|
|
|
};
|
|
|
|
|
|
|
|
if (name == "[Ljava.lang.Object;") {
|
|
|
|
|
|
|
|
jobjectArray arr = (jobjectArray)obj;
|
|
|
|
int objCount = env->GetArrayLength(arr);
|
2017-03-21 03:31:41 +01:00
|
|
|
Array varr;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
for (int i = 0; i < objCount; i++) {
|
2014-02-10 02:10:30 +01:00
|
|
|
jobject jobj = env->GetObjectArrayElement(arr, i);
|
|
|
|
Variant v = _jobject_to_variant(env, jobj);
|
|
|
|
varr.push_back(v);
|
2015-03-03 18:39:13 +01:00
|
|
|
env->DeleteLocalRef(jobj);
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return varr;
|
|
|
|
};
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
if (name == "java.util.HashMap" || name == "org.godotengine.godot.Dictionary") {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-03-21 03:31:41 +01:00
|
|
|
Dictionary ret;
|
2014-02-10 02:10:30 +01:00
|
|
|
jclass oclass = c;
|
|
|
|
jmethodID get_keys = env->GetMethodID(oclass, "get_keys", "()[Ljava/lang/String;");
|
|
|
|
jobjectArray arr = (jobjectArray)env->CallObjectMethod(obj, get_keys);
|
|
|
|
|
2020-02-17 22:06:54 +01:00
|
|
|
PackedStringArray keys = _jobject_to_variant(env, arr);
|
2015-03-03 18:39:13 +01:00
|
|
|
env->DeleteLocalRef(arr);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
jmethodID get_values = env->GetMethodID(oclass, "get_values", "()[Ljava/lang/Object;");
|
|
|
|
arr = (jobjectArray)env->CallObjectMethod(obj, get_values);
|
|
|
|
|
|
|
|
Array vals = _jobject_to_variant(env, arr);
|
2015-03-03 18:39:13 +01:00
|
|
|
env->DeleteLocalRef(arr);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
for (int i = 0; i < keys.size(); i++) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
ret[keys[i]] = vals[i];
|
|
|
|
};
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
};
|
|
|
|
|
2015-03-03 18:39:13 +01:00
|
|
|
env->DeleteLocalRef(c);
|
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
return Variant();
|
2016-07-21 12:07:01 +02:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
class JNISingleton : public Object {
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
GDCLASS(JNISingleton, Object);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
struct MethodData {
|
|
|
|
|
|
|
|
jmethodID method;
|
|
|
|
Variant::Type ret_type;
|
|
|
|
Vector<Variant::Type> argtypes;
|
|
|
|
};
|
|
|
|
|
|
|
|
jobject instance;
|
2017-03-05 16:44:50 +01:00
|
|
|
Map<StringName, MethodData> method_map;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
public:
|
2020-02-19 20:27:19 +01:00
|
|
|
virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
ERR_FAIL_COND_V(!instance, Variant());
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-02-19 20:27:19 +01:00
|
|
|
r_error.error = Callable::CallError::CALL_OK;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
Map<StringName, MethodData>::Element *E = method_map.find(p_method);
|
2014-02-10 02:10:30 +01:00
|
|
|
if (!E) {
|
|
|
|
|
2020-02-19 20:27:19 +01:00
|
|
|
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
|
2014-02-10 02:10:30 +01:00
|
|
|
return Variant();
|
|
|
|
}
|
|
|
|
|
|
|
|
int ac = E->get().argtypes.size();
|
2017-03-05 16:44:50 +01:00
|
|
|
if (ac < p_argcount) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-02-19 20:27:19 +01:00
|
|
|
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
|
2017-03-05 16:44:50 +01:00
|
|
|
r_error.argument = ac;
|
2014-02-10 02:10:30 +01:00
|
|
|
return Variant();
|
|
|
|
}
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
if (ac > p_argcount) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-02-19 20:27:19 +01:00
|
|
|
r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
|
2017-03-05 16:44:50 +01:00
|
|
|
r_error.argument = ac;
|
2014-02-10 02:10:30 +01:00
|
|
|
return Variant();
|
|
|
|
}
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
for (int i = 0; i < p_argcount; i++) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
if (!Variant::can_convert(p_args[i]->get_type(), E->get().argtypes[i])) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-02-19 20:27:19 +01:00
|
|
|
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
|
2017-03-05 16:44:50 +01:00
|
|
|
r_error.argument = i;
|
|
|
|
r_error.expected = E->get().argtypes[i];
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
jvalue *v = NULL;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
if (p_argcount) {
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
v = (jvalue *)alloca(sizeof(jvalue) * p_argcount);
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
JNIEnv *env = ThreadAndroid::get_env();
|
|
|
|
|
2015-05-18 17:45:53 +02:00
|
|
|
int res = env->PushLocalFrame(16);
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
ERR_FAIL_COND_V(res != 0, Variant());
|
2015-05-18 17:45:53 +02:00
|
|
|
|
2015-03-03 18:39:13 +01:00
|
|
|
List<jobject> to_erase;
|
2017-03-05 16:44:50 +01:00
|
|
|
for (int i = 0; i < p_argcount; i++) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2015-03-03 18:39:13 +01:00
|
|
|
jvalret vr = _variant_to_jvalue(env, E->get().argtypes[i], p_args[i]);
|
|
|
|
v[i] = vr.val;
|
|
|
|
if (vr.obj)
|
|
|
|
to_erase.push_back(vr.obj);
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Variant ret;
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
switch (E->get().ret_type) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
case Variant::NIL: {
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
env->CallVoidMethodA(instance, E->get().method, v);
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
|
|
|
case Variant::BOOL: {
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
ret = env->CallBooleanMethodA(instance, E->get().method, v) == JNI_TRUE;
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
|
|
|
case Variant::INT: {
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
ret = env->CallIntMethodA(instance, E->get().method, v);
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
case Variant::FLOAT: {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
ret = env->CallFloatMethodA(instance, E->get().method, v);
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
|
|
|
case Variant::STRING: {
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
jobject o = env->CallObjectMethodA(instance, E->get().method, v);
|
2019-02-26 21:54:45 +01:00
|
|
|
ret = jstring_to_string((jstring)o, env);
|
2015-03-03 18:39:13 +01:00
|
|
|
env->DeleteLocalRef(o);
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
2020-02-17 22:06:54 +01:00
|
|
|
case Variant::PACKED_STRING_ARRAY: {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
jobjectArray arr = (jobjectArray)env->CallObjectMethodA(instance, E->get().method, v);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
ret = _jobject_to_variant(env, arr);
|
|
|
|
|
2015-03-03 18:39:13 +01:00
|
|
|
env->DeleteLocalRef(arr);
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
case Variant::PACKED_INT32_ARRAY: {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
jintArray arr = (jintArray)env->CallObjectMethodA(instance, E->get().method, v);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
int fCount = env->GetArrayLength(arr);
|
2020-02-17 22:06:54 +01:00
|
|
|
Vector<int> sarr;
|
2014-02-10 02:10:30 +01:00
|
|
|
sarr.resize(fCount);
|
|
|
|
|
2020-02-17 22:06:54 +01:00
|
|
|
int *w = sarr.ptrw();
|
2017-03-05 16:44:50 +01:00
|
|
|
env->GetIntArrayRegion(arr, 0, fCount, w.ptr());
|
2019-07-05 19:08:43 +02:00
|
|
|
w.release();
|
2017-03-05 16:44:50 +01:00
|
|
|
ret = sarr;
|
2015-03-03 18:39:13 +01:00
|
|
|
env->DeleteLocalRef(arr);
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
case Variant::PACKED_FLOAT32_ARRAY: {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
jfloatArray arr = (jfloatArray)env->CallObjectMethodA(instance, E->get().method, v);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
int fCount = env->GetArrayLength(arr);
|
2020-02-17 22:06:54 +01:00
|
|
|
Vector<float> sarr;
|
2014-02-10 02:10:30 +01:00
|
|
|
sarr.resize(fCount);
|
|
|
|
|
2020-02-17 22:06:54 +01:00
|
|
|
float *w = sarr.ptrw();
|
2017-03-05 16:44:50 +01:00
|
|
|
env->GetFloatArrayRegion(arr, 0, fCount, w.ptr());
|
2019-07-05 19:08:43 +02:00
|
|
|
w.release();
|
2017-03-05 16:44:50 +01:00
|
|
|
ret = sarr;
|
2015-03-03 18:39:13 +01:00
|
|
|
env->DeleteLocalRef(arr);
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
|
|
|
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
#ifndef _MSC_VER
|
|
|
|
#warning This is missing 64 bits arrays, I have no idea how to do it in JNI
|
|
|
|
#endif
|
2014-02-10 02:10:30 +01:00
|
|
|
case Variant::DICTIONARY: {
|
|
|
|
|
|
|
|
jobject obj = env->CallObjectMethodA(instance, E->get().method, v);
|
|
|
|
ret = _jobject_to_variant(env, obj);
|
2015-03-03 18:39:13 +01:00
|
|
|
env->DeleteLocalRef(obj);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
} break;
|
|
|
|
default: {
|
|
|
|
|
2015-05-18 17:45:53 +02:00
|
|
|
env->PopLocalFrame(NULL);
|
2014-02-10 02:10:30 +01:00
|
|
|
ERR_FAIL_V(Variant());
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
|
2015-03-03 18:39:13 +01:00
|
|
|
while (to_erase.size()) {
|
|
|
|
env->DeleteLocalRef(to_erase.front()->get());
|
|
|
|
to_erase.pop_front();
|
|
|
|
}
|
2015-05-18 17:45:53 +02:00
|
|
|
|
|
|
|
env->PopLocalFrame(NULL);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
jobject get_instance() const {
|
|
|
|
|
|
|
|
return instance;
|
|
|
|
}
|
|
|
|
void set_instance(jobject p_instance) {
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
instance = p_instance;
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
void add_method(const StringName &p_name, jmethodID p_method, const Vector<Variant::Type> &p_args, Variant::Type p_ret_type) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
MethodData md;
|
2017-03-05 16:44:50 +01:00
|
|
|
md.method = p_method;
|
|
|
|
md.argtypes = p_args;
|
|
|
|
md.ret_type = p_ret_type;
|
|
|
|
method_map[p_name] = md;
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
2014-05-24 18:25:56 +02:00
|
|
|
JNISingleton() {
|
2017-03-05 16:44:50 +01:00
|
|
|
instance = NULL;
|
2014-05-24 18:25:56 +02:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
struct TST {
|
|
|
|
|
|
|
|
int a;
|
|
|
|
TST() {
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
a = 5;
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
TST tst;
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
static bool initialized = false;
|
|
|
|
static int step = 0;
|
2019-03-13 13:51:55 +01:00
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
static Size2 new_size;
|
|
|
|
static Vector3 accelerometer;
|
2017-11-10 23:42:23 +01:00
|
|
|
static Vector3 gravity;
|
2016-05-27 19:29:37 +02:00
|
|
|
static Vector3 magnetometer;
|
2016-07-15 09:31:34 +02:00
|
|
|
static Vector3 gyroscope;
|
2017-03-05 16:44:50 +01:00
|
|
|
static HashMap<String, JNISingleton *> jni_singletons;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2014-03-14 02:57:24 +01:00
|
|
|
// virtual Error native_video_play(String p_path);
|
|
|
|
// virtual bool native_video_is_playing();
|
|
|
|
// virtual void native_video_pause();
|
|
|
|
// virtual void native_video_stop();
|
|
|
|
|
2017-10-04 10:39:31 +02:00
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHeight(JNIEnv *env, jobject obj, jint p_height) {
|
2019-03-13 13:51:55 +01:00
|
|
|
if (godot_io_java) {
|
|
|
|
godot_io_java->set_vk_height(p_height);
|
|
|
|
}
|
2017-10-04 10:39:31 +02:00
|
|
|
}
|
|
|
|
|
2019-03-05 23:29:44 +01:00
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jobject obj, jobject activity, jobject p_asset_manager, jboolean p_use_apk_expansion) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
initialized = true;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
JavaVM *jvm;
|
|
|
|
env->GetJavaVM(&jvm);
|
|
|
|
|
2019-03-13 13:51:55 +01:00
|
|
|
// create our wrapper classes
|
|
|
|
godot_java = new GodotJavaWrapper(env, activity); // our activity is our godot instance is our activity..
|
|
|
|
godot_io_java = new GodotIOJavaWrapper(env, godot_java->get_member_object("io", "Lorg/godotengine/godot/GodotIO;", env));
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2019-03-13 13:51:55 +01:00
|
|
|
ThreadAndroid::make_default(jvm);
|
2015-09-04 04:24:55 +02:00
|
|
|
#ifdef USE_JAVA_FILE_ACCESS
|
2019-03-13 13:51:55 +01:00
|
|
|
FileAccessJAndroid::setup(godot_io_java->get_instance());
|
2015-09-04 04:24:55 +02:00
|
|
|
#else
|
|
|
|
|
2019-03-13 13:51:55 +01:00
|
|
|
jobject amgr = env->NewGlobalRef(p_asset_manager);
|
2015-09-04 04:24:55 +02:00
|
|
|
|
2019-03-13 13:51:55 +01:00
|
|
|
FileAccessAndroid::asset_manager = AAssetManager_fromJava(env, amgr);
|
2015-09-04 04:24:55 +02:00
|
|
|
#endif
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2019-03-13 13:51:55 +01:00
|
|
|
DirAccessJAndroid::setup(godot_io_java->get_instance());
|
|
|
|
AudioDriverAndroid::setup(godot_io_java->get_instance());
|
2019-11-25 15:01:44 +01:00
|
|
|
NetSocketAndroid::setup(godot_java->get_member_object("netUtils", "Lorg/godotengine/godot/utils/GodotNetUtils;", env));
|
2019-03-13 13:51:55 +01:00
|
|
|
|
|
|
|
os_android = new OS_Android(godot_java, godot_io_java, p_use_apk_expansion);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
char wd[500];
|
2017-03-05 16:44:50 +01:00
|
|
|
getcwd(wd, 500);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2019-03-13 13:51:55 +01:00
|
|
|
godot_java->on_video_init(env);
|
|
|
|
}
|
|
|
|
|
2019-08-27 02:47:13 +02:00
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jobject obj, jobject activity) {
|
2019-03-13 13:51:55 +01:00
|
|
|
// lets cleanup
|
|
|
|
if (godot_io_java) {
|
|
|
|
delete godot_io_java;
|
|
|
|
}
|
|
|
|
if (godot_java) {
|
|
|
|
delete godot_java;
|
|
|
|
}
|
|
|
|
if (os_android) {
|
|
|
|
delete os_android;
|
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void _initialize_java_modules() {
|
|
|
|
|
2017-10-05 20:34:34 +02:00
|
|
|
if (!ProjectSettings::get_singleton()->has_setting("android/modules")) {
|
2017-03-24 00:14:12 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-07-19 22:00:46 +02:00
|
|
|
String modules = ProjectSettings::get_singleton()->get("android/modules");
|
2017-03-24 00:14:12 +01:00
|
|
|
modules = modules.strip_edges();
|
|
|
|
if (modules == String()) {
|
|
|
|
return;
|
|
|
|
}
|
2017-03-05 16:44:50 +01:00
|
|
|
Vector<String> mods = modules.split(",", false);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
if (mods.size()) {
|
2019-03-13 13:51:55 +01:00
|
|
|
jobject cls = godot_java->get_class_loader();
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2019-03-13 13:51:55 +01:00
|
|
|
// TODO create wrapper for class loader
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2019-03-13 13:51:55 +01:00
|
|
|
JNIEnv *env = ThreadAndroid::get_env();
|
2014-02-10 02:10:30 +01:00
|
|
|
jclass classLoader = env->FindClass("java/lang/ClassLoader");
|
|
|
|
jmethodID findClass = env->GetMethodID(classLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
for (int i = 0; i < mods.size(); i++) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
String m = mods[i];
|
|
|
|
|
2019-03-07 10:40:44 +01:00
|
|
|
print_line("Loading Android module: " + m);
|
2014-02-10 02:10:30 +01:00
|
|
|
jstring strClassName = env->NewStringUTF(m.utf8().get_data());
|
|
|
|
jclass singletonClass = (jclass)env->CallObjectMethod(cls, findClass, strClassName);
|
2019-08-09 06:49:33 +02:00
|
|
|
ERR_CONTINUE_MSG(!singletonClass, "Couldn't find singleton for class: " + m + ".");
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2016-01-08 21:53:00 +01:00
|
|
|
jmethodID initialize = env->GetStaticMethodID(singletonClass, "initialize", "(Landroid/app/Activity;)Lorg/godotengine/godot/Godot$SingletonBase;");
|
2019-08-09 06:49:33 +02:00
|
|
|
ERR_CONTINUE_MSG(!initialize, "Couldn't find proper initialize function 'public static Godot.SingletonBase Class::initialize(Activity p_activity)' initializer for singleton class: " + m + ".");
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2019-03-13 13:51:55 +01:00
|
|
|
jobject obj = env->CallStaticObjectMethod(singletonClass, initialize, godot_java->get_activity());
|
2018-10-15 02:07:09 +02:00
|
|
|
env->NewGlobalRef(obj);
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-18 16:17:35 +02:00
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jobject obj, jobjectArray p_cmdline) {
|
2014-02-10 02:10:30 +01:00
|
|
|
ThreadAndroid::setup_thread();
|
|
|
|
|
2017-08-18 16:17:35 +02:00
|
|
|
const char **cmdline = NULL;
|
2019-02-26 21:54:45 +01:00
|
|
|
jstring *j_cmdline = NULL;
|
2017-08-18 16:17:35 +02:00
|
|
|
int cmdlen = 0;
|
|
|
|
if (p_cmdline) {
|
|
|
|
cmdlen = env->GetArrayLength(p_cmdline);
|
|
|
|
if (cmdlen) {
|
2019-02-26 21:54:45 +01:00
|
|
|
cmdline = (const char **)malloc((cmdlen + 1) * sizeof(const char *));
|
2017-08-18 16:17:35 +02:00
|
|
|
cmdline[cmdlen] = NULL;
|
2019-02-26 21:54:45 +01:00
|
|
|
j_cmdline = (jstring *)malloc(cmdlen * sizeof(jstring));
|
2017-08-18 16:17:35 +02:00
|
|
|
|
|
|
|
for (int i = 0; i < cmdlen; i++) {
|
|
|
|
|
|
|
|
jstring string = (jstring)env->GetObjectArrayElement(p_cmdline, i);
|
|
|
|
const char *rawString = env->GetStringUTFChars(string, 0);
|
|
|
|
|
|
|
|
cmdline[i] = rawString;
|
2019-02-26 21:54:45 +01:00
|
|
|
j_cmdline[i] = string;
|
2017-08-18 16:17:35 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Error err = Main::setup("apk", cmdlen, (char **)cmdline, false);
|
|
|
|
if (cmdline) {
|
2019-02-26 21:54:45 +01:00
|
|
|
if (j_cmdline) {
|
|
|
|
for (int i = 0; i < cmdlen; ++i) {
|
|
|
|
env->ReleaseStringUTFChars(j_cmdline[i], cmdline[i]);
|
|
|
|
}
|
|
|
|
free(j_cmdline);
|
|
|
|
}
|
2017-08-18 16:17:35 +02:00
|
|
|
free(cmdline);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (err != OK) {
|
|
|
|
return; //should exit instead and print the error
|
|
|
|
}
|
|
|
|
|
2019-03-13 13:51:55 +01:00
|
|
|
java_class_wrapper = memnew(JavaClassWrapper(godot_java->get_activity()));
|
2017-08-18 16:17:35 +02:00
|
|
|
_initialize_java_modules();
|
|
|
|
}
|
|
|
|
|
2019-03-05 23:29:44 +01:00
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jobject obj, jint width, jint height) {
|
2017-08-18 16:17:35 +02:00
|
|
|
|
|
|
|
if (os_android)
|
|
|
|
os_android->set_display_size(Size2(width, height));
|
|
|
|
}
|
|
|
|
|
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jobject obj, bool p_32_bits) {
|
|
|
|
|
|
|
|
if (os_android) {
|
2019-03-05 23:29:44 +01:00
|
|
|
if (step == 0) {
|
|
|
|
// During startup
|
|
|
|
os_android->set_context_is_16_bits(!p_32_bits);
|
|
|
|
} else {
|
|
|
|
// GL context recreated because it was lost; restart app to let it reload everything
|
|
|
|
os_android->main_loop_end();
|
2019-03-13 13:51:55 +01:00
|
|
|
godot_java->restart(env);
|
2019-03-05 23:29:44 +01:00
|
|
|
step = -1; // Ensure no further steps are attempted
|
|
|
|
}
|
2017-08-18 16:17:35 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, jobject obj) {
|
2018-03-27 17:03:44 +02:00
|
|
|
if (step == 0)
|
|
|
|
return;
|
|
|
|
|
2017-10-02 11:40:16 +02:00
|
|
|
os_android->main_loop_request_go_back();
|
2017-08-18 16:17:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jobject obj) {
|
2019-03-05 23:29:44 +01:00
|
|
|
if (step == -1)
|
|
|
|
return;
|
|
|
|
|
2017-08-18 16:17:35 +02:00
|
|
|
if (step == 0) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-08-22 17:21:41 +02:00
|
|
|
// Since Godot is initialized on the UI thread, _main_thread_id was set to that thread's id,
|
|
|
|
// but for Godot purposes, the main thread is the one running the game loop
|
|
|
|
Main::setup2(Thread::get_caller_id());
|
2014-02-10 02:10:30 +01:00
|
|
|
++step;
|
|
|
|
return;
|
2017-08-18 16:17:35 +02:00
|
|
|
}
|
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
if (step == 1) {
|
|
|
|
if (!Main::start()) {
|
|
|
|
return; //should exit instead and print the error
|
|
|
|
}
|
|
|
|
|
|
|
|
os_android->main_loop_begin();
|
|
|
|
++step;
|
|
|
|
}
|
|
|
|
|
|
|
|
os_android->process_accelerometer(accelerometer);
|
2017-11-10 23:42:23 +01:00
|
|
|
os_android->process_gravity(gravity);
|
2016-05-27 19:29:37 +02:00
|
|
|
os_android->process_magnetometer(magnetometer);
|
2016-07-15 09:31:34 +02:00
|
|
|
os_android->process_gyroscope(gyroscope);
|
|
|
|
|
2018-10-03 19:40:37 +02:00
|
|
|
if (os_android->main_loop_iterate()) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2019-03-13 13:51:55 +01:00
|
|
|
godot_java->force_quit(env);
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch(JNIEnv *env, jobject obj, jint ev, jint pointer, jint count, jintArray positions) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2018-03-27 17:03:44 +02:00
|
|
|
if (step == 0)
|
|
|
|
return;
|
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
Vector<OS_Android::TouchPos> points;
|
2017-03-05 16:44:50 +01:00
|
|
|
for (int i = 0; i < count; i++) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
jint p[3];
|
2017-03-05 16:44:50 +01:00
|
|
|
env->GetIntArrayRegion(positions, i * 3, 3, p);
|
2014-02-10 02:10:30 +01:00
|
|
|
OS_Android::TouchPos tp;
|
2017-03-05 16:44:50 +01:00
|
|
|
tp.pos = Point2(p[1], p[2]);
|
|
|
|
tp.id = p[0];
|
2014-02-10 02:10:30 +01:00
|
|
|
points.push_back(tp);
|
|
|
|
}
|
|
|
|
|
2017-10-02 11:40:16 +02:00
|
|
|
os_android->process_touch(ev, pointer, points);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-01-14 12:26:56 +01:00
|
|
|
/*
|
|
|
|
if (os_android)
|
|
|
|
os_android->process_touch(ev,pointer,points);
|
|
|
|
*/
|
2018-08-29 17:06:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hover(JNIEnv *env, jobject obj, jint p_type, jint p_x, jint p_y) {
|
|
|
|
if (step == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
os_android->process_hover(p_type, Point2(p_x, p_y));
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
2020-01-13 12:46:33 +01:00
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_doubletap(JNIEnv *env, jobject obj, jint p_x, jint p_y) {
|
2019-11-15 00:34:50 +01:00
|
|
|
if (step == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
os_android->process_double_tap(Point2(p_x, p_y));
|
|
|
|
}
|
|
|
|
|
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_scroll(JNIEnv *env, jobject obj, jint p_x, jint p_y) {
|
|
|
|
if (step == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
os_android->process_scroll(Point2(p_x, p_y));
|
|
|
|
}
|
|
|
|
|
2014-03-12 13:41:09 +01:00
|
|
|
/*
|
|
|
|
* Android Key codes.
|
|
|
|
*/
|
|
|
|
enum {
|
2017-03-05 16:44:50 +01:00
|
|
|
AKEYCODE_UNKNOWN = 0,
|
|
|
|
AKEYCODE_SOFT_LEFT = 1,
|
|
|
|
AKEYCODE_SOFT_RIGHT = 2,
|
|
|
|
AKEYCODE_HOME = 3,
|
|
|
|
AKEYCODE_BACK = 4,
|
|
|
|
AKEYCODE_CALL = 5,
|
|
|
|
AKEYCODE_ENDCALL = 6,
|
|
|
|
AKEYCODE_0 = 7,
|
|
|
|
AKEYCODE_1 = 8,
|
|
|
|
AKEYCODE_2 = 9,
|
|
|
|
AKEYCODE_3 = 10,
|
|
|
|
AKEYCODE_4 = 11,
|
|
|
|
AKEYCODE_5 = 12,
|
|
|
|
AKEYCODE_6 = 13,
|
|
|
|
AKEYCODE_7 = 14,
|
|
|
|
AKEYCODE_8 = 15,
|
|
|
|
AKEYCODE_9 = 16,
|
|
|
|
AKEYCODE_STAR = 17,
|
|
|
|
AKEYCODE_POUND = 18,
|
|
|
|
AKEYCODE_DPAD_UP = 19,
|
|
|
|
AKEYCODE_DPAD_DOWN = 20,
|
|
|
|
AKEYCODE_DPAD_LEFT = 21,
|
|
|
|
AKEYCODE_DPAD_RIGHT = 22,
|
|
|
|
AKEYCODE_DPAD_CENTER = 23,
|
|
|
|
AKEYCODE_VOLUME_UP = 24,
|
|
|
|
AKEYCODE_VOLUME_DOWN = 25,
|
|
|
|
AKEYCODE_POWER = 26,
|
|
|
|
AKEYCODE_CAMERA = 27,
|
|
|
|
AKEYCODE_CLEAR = 28,
|
|
|
|
AKEYCODE_A = 29,
|
|
|
|
AKEYCODE_B = 30,
|
|
|
|
AKEYCODE_C = 31,
|
|
|
|
AKEYCODE_D = 32,
|
|
|
|
AKEYCODE_E = 33,
|
|
|
|
AKEYCODE_F = 34,
|
|
|
|
AKEYCODE_G = 35,
|
|
|
|
AKEYCODE_H = 36,
|
|
|
|
AKEYCODE_I = 37,
|
|
|
|
AKEYCODE_J = 38,
|
|
|
|
AKEYCODE_K = 39,
|
|
|
|
AKEYCODE_L = 40,
|
|
|
|
AKEYCODE_M = 41,
|
|
|
|
AKEYCODE_N = 42,
|
|
|
|
AKEYCODE_O = 43,
|
|
|
|
AKEYCODE_P = 44,
|
|
|
|
AKEYCODE_Q = 45,
|
|
|
|
AKEYCODE_R = 46,
|
|
|
|
AKEYCODE_S = 47,
|
|
|
|
AKEYCODE_T = 48,
|
|
|
|
AKEYCODE_U = 49,
|
|
|
|
AKEYCODE_V = 50,
|
|
|
|
AKEYCODE_W = 51,
|
|
|
|
AKEYCODE_X = 52,
|
|
|
|
AKEYCODE_Y = 53,
|
|
|
|
AKEYCODE_Z = 54,
|
|
|
|
AKEYCODE_COMMA = 55,
|
|
|
|
AKEYCODE_PERIOD = 56,
|
|
|
|
AKEYCODE_ALT_LEFT = 57,
|
|
|
|
AKEYCODE_ALT_RIGHT = 58,
|
|
|
|
AKEYCODE_SHIFT_LEFT = 59,
|
|
|
|
AKEYCODE_SHIFT_RIGHT = 60,
|
|
|
|
AKEYCODE_TAB = 61,
|
|
|
|
AKEYCODE_SPACE = 62,
|
|
|
|
AKEYCODE_SYM = 63,
|
|
|
|
AKEYCODE_EXPLORER = 64,
|
|
|
|
AKEYCODE_ENVELOPE = 65,
|
|
|
|
AKEYCODE_ENTER = 66,
|
|
|
|
AKEYCODE_DEL = 67,
|
|
|
|
AKEYCODE_GRAVE = 68,
|
|
|
|
AKEYCODE_MINUS = 69,
|
|
|
|
AKEYCODE_EQUALS = 70,
|
|
|
|
AKEYCODE_LEFT_BRACKET = 71,
|
|
|
|
AKEYCODE_RIGHT_BRACKET = 72,
|
|
|
|
AKEYCODE_BACKSLASH = 73,
|
|
|
|
AKEYCODE_SEMICOLON = 74,
|
|
|
|
AKEYCODE_APOSTROPHE = 75,
|
|
|
|
AKEYCODE_SLASH = 76,
|
|
|
|
AKEYCODE_AT = 77,
|
|
|
|
AKEYCODE_NUM = 78,
|
|
|
|
AKEYCODE_HEADSETHOOK = 79,
|
|
|
|
AKEYCODE_FOCUS = 80, // *Camera* focus
|
|
|
|
AKEYCODE_PLUS = 81,
|
|
|
|
AKEYCODE_MENU = 82,
|
|
|
|
AKEYCODE_NOTIFICATION = 83,
|
|
|
|
AKEYCODE_SEARCH = 84,
|
|
|
|
AKEYCODE_MEDIA_PLAY_PAUSE = 85,
|
|
|
|
AKEYCODE_MEDIA_STOP = 86,
|
|
|
|
AKEYCODE_MEDIA_NEXT = 87,
|
|
|
|
AKEYCODE_MEDIA_PREVIOUS = 88,
|
|
|
|
AKEYCODE_MEDIA_REWIND = 89,
|
|
|
|
AKEYCODE_MEDIA_FAST_FORWARD = 90,
|
|
|
|
AKEYCODE_MUTE = 91,
|
|
|
|
AKEYCODE_PAGE_UP = 92,
|
|
|
|
AKEYCODE_PAGE_DOWN = 93,
|
|
|
|
AKEYCODE_PICTSYMBOLS = 94,
|
|
|
|
AKEYCODE_SWITCH_CHARSET = 95,
|
|
|
|
AKEYCODE_BUTTON_A = 96,
|
|
|
|
AKEYCODE_BUTTON_B = 97,
|
|
|
|
AKEYCODE_BUTTON_C = 98,
|
|
|
|
AKEYCODE_BUTTON_X = 99,
|
|
|
|
AKEYCODE_BUTTON_Y = 100,
|
|
|
|
AKEYCODE_BUTTON_Z = 101,
|
|
|
|
AKEYCODE_BUTTON_L1 = 102,
|
|
|
|
AKEYCODE_BUTTON_R1 = 103,
|
|
|
|
AKEYCODE_BUTTON_L2 = 104,
|
|
|
|
AKEYCODE_BUTTON_R2 = 105,
|
|
|
|
AKEYCODE_BUTTON_THUMBL = 106,
|
|
|
|
AKEYCODE_BUTTON_THUMBR = 107,
|
|
|
|
AKEYCODE_BUTTON_START = 108,
|
|
|
|
AKEYCODE_BUTTON_SELECT = 109,
|
|
|
|
AKEYCODE_BUTTON_MODE = 110,
|
|
|
|
|
|
|
|
// NOTE: If you add a new keycode here you must also add it to several other files.
|
|
|
|
// Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
|
2014-03-12 13:41:09 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
struct _WinTranslatePair {
|
|
|
|
|
|
|
|
unsigned int keysym;
|
|
|
|
unsigned int keycode;
|
|
|
|
};
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
static _WinTranslatePair _ak_to_keycode[] = {
|
|
|
|
{ KEY_TAB, AKEYCODE_TAB },
|
|
|
|
{ KEY_ENTER, AKEYCODE_ENTER },
|
|
|
|
{ KEY_SHIFT, AKEYCODE_SHIFT_LEFT },
|
|
|
|
{ KEY_SHIFT, AKEYCODE_SHIFT_RIGHT },
|
|
|
|
{ KEY_ALT, AKEYCODE_ALT_LEFT },
|
|
|
|
{ KEY_ALT, AKEYCODE_ALT_RIGHT },
|
|
|
|
{ KEY_MENU, AKEYCODE_MENU },
|
|
|
|
{ KEY_PAUSE, AKEYCODE_MEDIA_PLAY_PAUSE },
|
|
|
|
{ KEY_ESCAPE, AKEYCODE_BACK },
|
|
|
|
{ KEY_SPACE, AKEYCODE_SPACE },
|
|
|
|
{ KEY_PAGEUP, AKEYCODE_PAGE_UP },
|
|
|
|
{ KEY_PAGEDOWN, AKEYCODE_PAGE_DOWN },
|
|
|
|
{ KEY_HOME, AKEYCODE_HOME }, //(0x24)
|
|
|
|
{ KEY_LEFT, AKEYCODE_DPAD_LEFT },
|
|
|
|
{ KEY_UP, AKEYCODE_DPAD_UP },
|
|
|
|
{ KEY_RIGHT, AKEYCODE_DPAD_RIGHT },
|
|
|
|
{ KEY_DOWN, AKEYCODE_DPAD_DOWN },
|
|
|
|
{ KEY_PERIODCENTERED, AKEYCODE_DPAD_CENTER },
|
|
|
|
{ KEY_BACKSPACE, AKEYCODE_DEL },
|
|
|
|
{ KEY_0, AKEYCODE_0 }, ////0 key
|
|
|
|
{ KEY_1, AKEYCODE_1 }, ////1 key
|
|
|
|
{ KEY_2, AKEYCODE_2 }, ////2 key
|
|
|
|
{ KEY_3, AKEYCODE_3 }, ////3 key
|
|
|
|
{ KEY_4, AKEYCODE_4 }, ////4 key
|
|
|
|
{ KEY_5, AKEYCODE_5 }, ////5 key
|
|
|
|
{ KEY_6, AKEYCODE_6 }, ////6 key
|
|
|
|
{ KEY_7, AKEYCODE_7 }, ////7 key
|
|
|
|
{ KEY_8, AKEYCODE_8 }, ////8 key
|
|
|
|
{ KEY_9, AKEYCODE_9 }, ////9 key
|
|
|
|
{ KEY_A, AKEYCODE_A }, ////A key
|
|
|
|
{ KEY_B, AKEYCODE_B }, ////B key
|
|
|
|
{ KEY_C, AKEYCODE_C }, ////C key
|
|
|
|
{ KEY_D, AKEYCODE_D }, ////D key
|
|
|
|
{ KEY_E, AKEYCODE_E }, ////E key
|
|
|
|
{ KEY_F, AKEYCODE_F }, ////F key
|
|
|
|
{ KEY_G, AKEYCODE_G }, ////G key
|
|
|
|
{ KEY_H, AKEYCODE_H }, ////H key
|
|
|
|
{ KEY_I, AKEYCODE_I }, ////I key
|
|
|
|
{ KEY_J, AKEYCODE_J }, ////J key
|
|
|
|
{ KEY_K, AKEYCODE_K }, ////K key
|
|
|
|
{ KEY_L, AKEYCODE_L }, ////L key
|
|
|
|
{ KEY_M, AKEYCODE_M }, ////M key
|
|
|
|
{ KEY_N, AKEYCODE_N }, ////N key
|
|
|
|
{ KEY_O, AKEYCODE_O }, ////O key
|
|
|
|
{ KEY_P, AKEYCODE_P }, ////P key
|
|
|
|
{ KEY_Q, AKEYCODE_Q }, ////Q key
|
|
|
|
{ KEY_R, AKEYCODE_R }, ////R key
|
|
|
|
{ KEY_S, AKEYCODE_S }, ////S key
|
|
|
|
{ KEY_T, AKEYCODE_T }, ////T key
|
|
|
|
{ KEY_U, AKEYCODE_U }, ////U key
|
|
|
|
{ KEY_V, AKEYCODE_V }, ////V key
|
|
|
|
{ KEY_W, AKEYCODE_W }, ////W key
|
|
|
|
{ KEY_X, AKEYCODE_X }, ////X key
|
|
|
|
{ KEY_Y, AKEYCODE_Y }, ////Y key
|
|
|
|
{ KEY_Z, AKEYCODE_Z }, ////Z key
|
|
|
|
{ KEY_HOMEPAGE, AKEYCODE_EXPLORER },
|
|
|
|
{ KEY_LAUNCH0, AKEYCODE_BUTTON_A },
|
|
|
|
{ KEY_LAUNCH1, AKEYCODE_BUTTON_B },
|
|
|
|
{ KEY_LAUNCH2, AKEYCODE_BUTTON_C },
|
|
|
|
{ KEY_LAUNCH3, AKEYCODE_BUTTON_X },
|
|
|
|
{ KEY_LAUNCH4, AKEYCODE_BUTTON_Y },
|
|
|
|
{ KEY_LAUNCH5, AKEYCODE_BUTTON_Z },
|
|
|
|
{ KEY_LAUNCH6, AKEYCODE_BUTTON_L1 },
|
|
|
|
{ KEY_LAUNCH7, AKEYCODE_BUTTON_R1 },
|
|
|
|
{ KEY_LAUNCH8, AKEYCODE_BUTTON_L2 },
|
|
|
|
{ KEY_LAUNCH9, AKEYCODE_BUTTON_R2 },
|
|
|
|
{ KEY_LAUNCHA, AKEYCODE_BUTTON_THUMBL },
|
|
|
|
{ KEY_LAUNCHB, AKEYCODE_BUTTON_THUMBR },
|
|
|
|
{ KEY_LAUNCHC, AKEYCODE_BUTTON_START },
|
|
|
|
{ KEY_LAUNCHD, AKEYCODE_BUTTON_SELECT },
|
|
|
|
{ KEY_LAUNCHE, AKEYCODE_BUTTON_MODE },
|
|
|
|
{ KEY_VOLUMEMUTE, AKEYCODE_MUTE },
|
|
|
|
{ KEY_VOLUMEDOWN, AKEYCODE_VOLUME_DOWN },
|
|
|
|
{ KEY_VOLUMEUP, AKEYCODE_VOLUME_UP },
|
|
|
|
{ KEY_BACK, AKEYCODE_MEDIA_REWIND },
|
|
|
|
{ KEY_FORWARD, AKEYCODE_MEDIA_FAST_FORWARD },
|
|
|
|
{ KEY_MEDIANEXT, AKEYCODE_MEDIA_NEXT },
|
|
|
|
{ KEY_MEDIAPREVIOUS, AKEYCODE_MEDIA_PREVIOUS },
|
|
|
|
{ KEY_MEDIASTOP, AKEYCODE_MEDIA_STOP },
|
|
|
|
{ KEY_PLUS, AKEYCODE_PLUS },
|
|
|
|
{ KEY_EQUAL, AKEYCODE_EQUALS }, // the '+' key
|
|
|
|
{ KEY_COMMA, AKEYCODE_COMMA }, // the ',' key
|
|
|
|
{ KEY_MINUS, AKEYCODE_MINUS }, // the '-' key
|
|
|
|
{ KEY_SLASH, AKEYCODE_SLASH }, // the '/?' key
|
|
|
|
{ KEY_BACKSLASH, AKEYCODE_BACKSLASH },
|
|
|
|
{ KEY_BRACKETLEFT, AKEYCODE_LEFT_BRACKET },
|
|
|
|
{ KEY_BRACKETRIGHT, AKEYCODE_RIGHT_BRACKET },
|
|
|
|
{ KEY_UNKNOWN, 0 }
|
|
|
|
};
|
2014-03-12 13:41:09 +01:00
|
|
|
/*
|
|
|
|
TODO: map these android key:
|
|
|
|
AKEYCODE_SOFT_LEFT = 1,
|
|
|
|
AKEYCODE_SOFT_RIGHT = 2,
|
|
|
|
AKEYCODE_CALL = 5,
|
|
|
|
AKEYCODE_ENDCALL = 6,
|
|
|
|
AKEYCODE_STAR = 17,
|
|
|
|
AKEYCODE_POUND = 18,
|
|
|
|
AKEYCODE_POWER = 26,
|
|
|
|
AKEYCODE_CAMERA = 27,
|
|
|
|
AKEYCODE_CLEAR = 28,
|
|
|
|
AKEYCODE_SYM = 63,
|
|
|
|
AKEYCODE_ENVELOPE = 65,
|
|
|
|
AKEYCODE_GRAVE = 68,
|
|
|
|
AKEYCODE_SEMICOLON = 74,
|
|
|
|
AKEYCODE_APOSTROPHE = 75,
|
|
|
|
AKEYCODE_AT = 77,
|
|
|
|
AKEYCODE_NUM = 78,
|
|
|
|
AKEYCODE_HEADSETHOOK = 79,
|
|
|
|
AKEYCODE_FOCUS = 80, // *Camera* focus
|
|
|
|
AKEYCODE_NOTIFICATION = 83,
|
|
|
|
AKEYCODE_SEARCH = 84,
|
|
|
|
AKEYCODE_PICTSYMBOLS = 94,
|
|
|
|
AKEYCODE_SWITCH_CHARSET = 95,
|
|
|
|
*/
|
|
|
|
|
|
|
|
static unsigned int android_get_keysym(unsigned int p_code) {
|
2017-03-05 16:44:50 +01:00
|
|
|
for (int i = 0; _ak_to_keycode[i].keysym != KEY_UNKNOWN; i++) {
|
2014-03-12 13:41:09 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
if (_ak_to_keycode[i].keycode == p_code) {
|
2014-03-12 13:41:09 +01:00
|
|
|
|
|
|
|
return _ak_to_keycode[i].keysym;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return KEY_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env, jobject obj, jint p_device, jint p_button, jboolean p_pressed) {
|
2018-03-27 17:03:44 +02:00
|
|
|
if (step == 0)
|
|
|
|
return;
|
2014-07-02 05:09:36 +02:00
|
|
|
|
2017-01-08 21:05:51 +01:00
|
|
|
OS_Android::JoypadEvent jevent;
|
2016-01-24 05:11:59 +01:00
|
|
|
jevent.device = p_device;
|
|
|
|
jevent.type = OS_Android::JOY_EVENT_BUTTON;
|
|
|
|
jevent.index = p_button;
|
2017-06-07 05:29:19 +02:00
|
|
|
jevent.pressed = p_pressed;
|
2014-07-02 05:09:36 +02:00
|
|
|
|
2017-10-02 11:40:16 +02:00
|
|
|
os_android->process_joy_event(jevent);
|
2016-07-21 12:07:01 +02:00
|
|
|
}
|
2014-07-02 05:09:36 +02:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env, jobject obj, jint p_device, jint p_axis, jfloat p_value) {
|
2018-03-27 17:03:44 +02:00
|
|
|
if (step == 0)
|
|
|
|
return;
|
2014-07-02 05:09:36 +02:00
|
|
|
|
2017-01-08 21:05:51 +01:00
|
|
|
OS_Android::JoypadEvent jevent;
|
2016-01-24 05:11:59 +01:00
|
|
|
jevent.device = p_device;
|
|
|
|
jevent.type = OS_Android::JOY_EVENT_AXIS;
|
|
|
|
jevent.index = p_axis;
|
|
|
|
jevent.value = p_value;
|
2014-07-02 05:09:36 +02:00
|
|
|
|
2017-10-02 11:40:16 +02:00
|
|
|
os_android->process_joy_event(jevent);
|
2016-07-21 12:07:01 +02:00
|
|
|
}
|
2014-07-02 05:09:36 +02:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, jobject obj, jint p_device, jint p_hat_x, jint p_hat_y) {
|
2018-03-27 17:03:44 +02:00
|
|
|
if (step == 0)
|
|
|
|
return;
|
|
|
|
|
2017-01-08 21:05:51 +01:00
|
|
|
OS_Android::JoypadEvent jevent;
|
2016-01-24 05:11:59 +01:00
|
|
|
jevent.device = p_device;
|
|
|
|
jevent.type = OS_Android::JOY_EVENT_HAT;
|
|
|
|
int hat = 0;
|
|
|
|
if (p_hat_x != 0) {
|
2017-03-05 16:44:50 +01:00
|
|
|
if (p_hat_x < 0)
|
|
|
|
hat |= InputDefault::HAT_MASK_LEFT;
|
|
|
|
else
|
|
|
|
hat |= InputDefault::HAT_MASK_RIGHT;
|
2016-01-24 05:11:59 +01:00
|
|
|
}
|
|
|
|
if (p_hat_y != 0) {
|
2017-03-05 16:44:50 +01:00
|
|
|
if (p_hat_y < 0)
|
|
|
|
hat |= InputDefault::HAT_MASK_UP;
|
|
|
|
else
|
|
|
|
hat |= InputDefault::HAT_MASK_DOWN;
|
2016-01-24 05:11:59 +01:00
|
|
|
}
|
|
|
|
jevent.hat = hat;
|
2017-10-02 11:40:16 +02:00
|
|
|
|
|
|
|
os_android->process_joy_event(jevent);
|
2016-01-24 05:11:59 +01:00
|
|
|
}
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged(JNIEnv *env, jobject obj, jint p_device, jboolean p_connected, jstring p_name) {
|
2016-01-24 05:11:59 +01:00
|
|
|
if (os_android) {
|
2019-02-26 21:54:45 +01:00
|
|
|
String name = jstring_to_string(p_name, env);
|
2016-01-24 05:11:59 +01:00
|
|
|
os_android->joy_connection_changed(p_device, p_connected, name);
|
|
|
|
}
|
|
|
|
}
|
2014-07-02 05:09:36 +02:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jobject obj, jint p_scancode, jint p_unicode_char, jboolean p_pressed) {
|
2018-03-27 17:03:44 +02:00
|
|
|
if (step == 0)
|
|
|
|
return;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-05-20 17:38:03 +02:00
|
|
|
Ref<InputEventKey> ievent;
|
2017-10-02 11:40:16 +02:00
|
|
|
ievent.instance();
|
2014-02-10 02:10:30 +01:00
|
|
|
int val = p_unicode_char;
|
2014-03-12 13:41:09 +01:00
|
|
|
int scancode = android_get_keysym(p_scancode);
|
2017-05-20 17:38:03 +02:00
|
|
|
ievent->set_scancode(scancode);
|
|
|
|
ievent->set_unicode(val);
|
|
|
|
ievent->set_pressed(p_pressed);
|
2014-03-12 13:41:09 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
if (val == '\n') {
|
2017-05-20 17:38:03 +02:00
|
|
|
ievent->set_scancode(KEY_ENTER);
|
2017-03-05 16:44:50 +01:00
|
|
|
} else if (val == 61448) {
|
2017-05-20 17:38:03 +02:00
|
|
|
ievent->set_scancode(KEY_BACKSPACE);
|
|
|
|
ievent->set_unicode(KEY_BACKSPACE);
|
2014-03-13 11:31:30 +01:00
|
|
|
} else if (val == 61453) {
|
2017-05-20 17:38:03 +02:00
|
|
|
ievent->set_scancode(KEY_ENTER);
|
|
|
|
ievent->set_unicode(KEY_ENTER);
|
2017-03-05 16:44:50 +01:00
|
|
|
} else if (p_scancode == 4) {
|
2014-06-28 04:21:45 +02:00
|
|
|
|
2017-10-02 11:40:16 +02:00
|
|
|
os_android->main_loop_request_go_back();
|
2017-03-05 16:44:50 +01:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-10-02 11:40:16 +02:00
|
|
|
os_android->process_event(ievent);
|
2016-07-21 12:07:01 +02:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_accelerometer(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z) {
|
|
|
|
accelerometer = Vector3(x, y, z);
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
2017-11-10 23:42:23 +01:00
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_gravity(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z) {
|
|
|
|
gravity = Vector3(x, y, z);
|
|
|
|
}
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_magnetometer(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z) {
|
|
|
|
magnetometer = Vector3(x, y, z);
|
2016-05-27 19:29:37 +02:00
|
|
|
}
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_gyroscope(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z) {
|
|
|
|
gyroscope = Vector3(x, y, z);
|
2016-07-15 09:31:34 +02:00
|
|
|
}
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusin(JNIEnv *env, jobject obj) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2018-03-27 17:03:44 +02:00
|
|
|
if (step == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
os_android->main_loop_focusin();
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusout(JNIEnv *env, jobject obj) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2018-03-27 17:03:44 +02:00
|
|
|
if (step == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
os_android->main_loop_focusout();
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_audio(JNIEnv *env, jobject obj) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
ThreadAndroid::setup_thread();
|
|
|
|
AudioDriverAndroid::thread_func(env);
|
|
|
|
}
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_singleton(JNIEnv *env, jobject obj, jstring name, jobject p_object) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2019-02-26 21:54:45 +01:00
|
|
|
String singname = jstring_to_string(name, env);
|
2017-03-05 16:44:50 +01:00
|
|
|
JNISingleton *s = memnew(JNISingleton);
|
2014-02-10 02:10:30 +01:00
|
|
|
s->set_instance(env->NewGlobalRef(p_object));
|
2017-03-05 16:44:50 +01:00
|
|
|
jni_singletons[singname] = s;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-11-13 21:46:57 +01:00
|
|
|
Engine::get_singleton()->add_singleton(Engine::Singleton(singname, s));
|
2017-07-19 22:00:46 +02:00
|
|
|
ProjectSettings::get_singleton()->set(singname, s);
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
static Variant::Type get_jni_type(const String &p_type) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
static struct {
|
|
|
|
const char *name;
|
|
|
|
Variant::Type type;
|
2017-03-05 16:44:50 +01:00
|
|
|
} _type_to_vtype[] = {
|
|
|
|
{ "void", Variant::NIL },
|
|
|
|
{ "boolean", Variant::BOOL },
|
|
|
|
{ "int", Variant::INT },
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
{ "float", Variant::FLOAT },
|
|
|
|
{ "double", Variant::FLOAT },
|
2017-03-05 16:44:50 +01:00
|
|
|
{ "java.lang.String", Variant::STRING },
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
{ "[I", Variant::PACKED_INT32_ARRAY },
|
2020-02-17 22:06:54 +01:00
|
|
|
{ "[B", Variant::PACKED_BYTE_ARRAY },
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
{ "[F", Variant::PACKED_FLOAT32_ARRAY },
|
2020-02-17 22:06:54 +01:00
|
|
|
{ "[Ljava.lang.String;", Variant::PACKED_STRING_ARRAY },
|
2017-03-05 16:44:50 +01:00
|
|
|
{ "org.godotengine.godot.Dictionary", Variant::DICTIONARY },
|
|
|
|
{ NULL, Variant::NIL }
|
2014-02-10 02:10:30 +01:00
|
|
|
};
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
int idx = 0;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
while (_type_to_vtype[idx].name) {
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
if (p_type == _type_to_vtype[idx].name)
|
2014-02-10 02:10:30 +01:00
|
|
|
return _type_to_vtype[idx].type;
|
|
|
|
|
|
|
|
idx++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Variant::NIL;
|
|
|
|
}
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
static const char *get_jni_sig(const String &p_type) {
|
2014-06-28 04:21:45 +02:00
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
static struct {
|
|
|
|
const char *name;
|
|
|
|
const char *sig;
|
2017-03-05 16:44:50 +01:00
|
|
|
} _type_to_vtype[] = {
|
|
|
|
{ "void", "V" },
|
|
|
|
{ "boolean", "Z" },
|
|
|
|
{ "int", "I" },
|
|
|
|
{ "float", "F" },
|
|
|
|
{ "double", "D" },
|
|
|
|
{ "java.lang.String", "Ljava/lang/String;" },
|
|
|
|
{ "org.godotengine.godot.Dictionary", "Lorg/godotengine/godot/Dictionary;" },
|
|
|
|
{ "[I", "[I" },
|
|
|
|
{ "[B", "[B" },
|
|
|
|
{ "[F", "[F" },
|
|
|
|
{ "[Ljava.lang.String;", "[Ljava/lang/String;" },
|
|
|
|
{ NULL, "V" }
|
2014-02-10 02:10:30 +01:00
|
|
|
};
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
int idx = 0;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
while (_type_to_vtype[idx].name) {
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
if (p_type == _type_to_vtype[idx].name)
|
2014-02-10 02:10:30 +01:00
|
|
|
return _type_to_vtype[idx].sig;
|
|
|
|
|
|
|
|
idx++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return "Ljava/lang/Object;";
|
|
|
|
}
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
JNIEXPORT jstring JNICALL Java_org_godotengine_godot_GodotLib_getGlobal(JNIEnv *env, jobject obj, jstring path) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2019-02-26 21:54:45 +01:00
|
|
|
String js = jstring_to_string(path, env);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-07-19 22:00:46 +02:00
|
|
|
return env->NewStringUTF(ProjectSettings::get_singleton()->get(js).operator String().utf8().get_data());
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_method(JNIEnv *env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2019-02-26 21:54:45 +01:00
|
|
|
String singname = jstring_to_string(sname, env);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
ERR_FAIL_COND(!jni_singletons.has(singname));
|
|
|
|
|
|
|
|
JNISingleton *s = jni_singletons.get(singname);
|
|
|
|
|
2019-02-26 21:54:45 +01:00
|
|
|
String mname = jstring_to_string(name, env);
|
|
|
|
String retval = jstring_to_string(ret, env);
|
2014-02-10 02:10:30 +01:00
|
|
|
Vector<Variant::Type> types;
|
2017-03-05 16:44:50 +01:00
|
|
|
String cs = "(";
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
int stringCount = env->GetArrayLength(args);
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
for (int i = 0; i < stringCount; i++) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
jstring string = (jstring)env->GetObjectArrayElement(args, i);
|
2019-02-26 21:54:45 +01:00
|
|
|
const String rawString = jstring_to_string(string, env);
|
|
|
|
types.push_back(get_jni_type(rawString));
|
|
|
|
cs += get_jni_sig(rawString);
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
cs += ")";
|
|
|
|
cs += get_jni_sig(retval);
|
2014-02-10 02:10:30 +01:00
|
|
|
jclass cls = env->GetObjectClass(s->get_instance());
|
|
|
|
jmethodID mid = env->GetMethodID(cls, mname.ascii().get_data(), cs.ascii().get_data());
|
|
|
|
if (!mid) {
|
|
|
|
|
2018-02-17 22:34:08 +01:00
|
|
|
print_line("Failed getting method ID " + mname);
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
s->add_method(mname, mid, types, get_jni_type(retval));
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_callobject(JNIEnv *env, jobject p_obj, jint ID, jstring method, jobjectArray params) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
Object *obj = ObjectDB::get_instance(ID);
|
2014-02-10 02:10:30 +01:00
|
|
|
ERR_FAIL_COND(!obj);
|
|
|
|
|
2015-05-18 17:45:53 +02:00
|
|
|
int res = env->PushLocalFrame(16);
|
2017-03-05 16:44:50 +01:00
|
|
|
ERR_FAIL_COND(res != 0);
|
2015-05-18 17:45:53 +02:00
|
|
|
|
2019-02-26 21:54:45 +01:00
|
|
|
String str_method = jstring_to_string(method, env);
|
2015-05-18 17:45:53 +02:00
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
int count = env->GetArrayLength(params);
|
2017-03-05 16:44:50 +01:00
|
|
|
Variant *vlist = (Variant *)alloca(sizeof(Variant) * count);
|
|
|
|
Variant **vptr = (Variant **)alloca(sizeof(Variant *) * count);
|
|
|
|
for (int i = 0; i < count; i++) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
jobject obj = env->GetObjectArrayElement(params, i);
|
2014-08-02 03:10:38 +02:00
|
|
|
Variant v;
|
|
|
|
if (obj)
|
2017-03-05 16:44:50 +01:00
|
|
|
v = _jobject_to_variant(env, obj);
|
2014-02-10 02:10:30 +01:00
|
|
|
memnew_placement(&vlist[i], Variant);
|
|
|
|
vlist[i] = v;
|
|
|
|
vptr[i] = &vlist[i];
|
2015-03-03 18:39:13 +01:00
|
|
|
env->DeleteLocalRef(obj);
|
2014-02-10 02:10:30 +01:00
|
|
|
};
|
|
|
|
|
2020-02-19 20:27:19 +01:00
|
|
|
Callable::CallError err;
|
2017-03-05 16:44:50 +01:00
|
|
|
obj->call(str_method, (const Variant **)vptr, count, err);
|
2014-02-10 02:10:30 +01:00
|
|
|
// something
|
2015-05-18 17:45:53 +02:00
|
|
|
|
|
|
|
env->PopLocalFrame(NULL);
|
2016-07-21 12:07:01 +02:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv *env, jobject p_obj, jint ID, jstring method, jobjectArray params) {
|
2014-02-13 22:03:28 +01:00
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
Object *obj = ObjectDB::get_instance(ID);
|
2014-02-13 22:03:28 +01:00
|
|
|
ERR_FAIL_COND(!obj);
|
|
|
|
|
2015-05-18 17:45:53 +02:00
|
|
|
int res = env->PushLocalFrame(16);
|
2017-03-05 16:44:50 +01:00
|
|
|
ERR_FAIL_COND(res != 0);
|
2015-05-18 17:45:53 +02:00
|
|
|
|
2019-02-26 21:54:45 +01:00
|
|
|
String str_method = jstring_to_string(method, env);
|
2015-05-18 17:45:53 +02:00
|
|
|
|
2014-02-13 22:03:28 +01:00
|
|
|
int count = env->GetArrayLength(params);
|
|
|
|
Variant args[VARIANT_ARG_MAX];
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
for (int i = 0; i < MIN(count, VARIANT_ARG_MAX); i++) {
|
2014-02-13 22:03:28 +01:00
|
|
|
|
|
|
|
jobject obj = env->GetObjectArrayElement(params, i);
|
2014-08-02 03:10:38 +02:00
|
|
|
if (obj)
|
|
|
|
args[i] = _jobject_to_variant(env, obj);
|
2015-03-03 18:39:13 +01:00
|
|
|
env->DeleteLocalRef(obj);
|
2014-02-13 22:03:28 +01:00
|
|
|
};
|
|
|
|
|
2017-03-05 16:44:50 +01:00
|
|
|
obj->call_deferred(str_method, args[0], args[1], args[2], args[3], args[4]);
|
2014-02-13 22:03:28 +01:00
|
|
|
// something
|
2015-05-18 17:45:53 +02:00
|
|
|
env->PopLocalFrame(NULL);
|
2016-07-21 12:07:01 +02:00
|
|
|
}
|
2019-03-05 03:06:37 +01:00
|
|
|
|
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_requestPermissionResult(JNIEnv *env, jobject p_obj, jstring p_permission, jboolean p_result) {
|
|
|
|
String permission = jstring_to_string(p_permission, env);
|
|
|
|
if (permission == "android.permission.RECORD_AUDIO" && p_result) {
|
|
|
|
AudioDriver::get_singleton()->capture_start();
|
|
|
|
}
|
2019-10-06 20:17:44 +02:00
|
|
|
|
|
|
|
if (os_android->get_main_loop()) {
|
|
|
|
os_android->get_main_loop()->emit_signal("on_request_permissions_result", permission, p_result == JNI_TRUE);
|
|
|
|
}
|
2019-03-05 03:06:37 +01:00
|
|
|
}
|
2019-09-09 23:42:17 +02:00
|
|
|
|
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererResumed(JNIEnv *env, jclass clazz) {
|
|
|
|
if (step == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (os_android->get_main_loop()) {
|
|
|
|
os_android->get_main_loop()->notification(MainLoop::NOTIFICATION_APP_RESUMED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererPaused(JNIEnv *env, jclass clazz) {
|
|
|
|
if (step == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (os_android->get_main_loop()) {
|
|
|
|
os_android->get_main_loop()->notification(MainLoop::NOTIFICATION_APP_PAUSED);
|
|
|
|
}
|
|
|
|
}
|