mirror of
https://github.com/godotengine/godot.git
synced 2024-11-22 12:12:28 +00:00
Merge pull request #10422 from endragor/gdnative-android
Make GDNative work on Android
This commit is contained in:
commit
6f762ad709
@ -1112,10 +1112,20 @@ bool Main::start() {
|
||||
test = args[i + 1];
|
||||
} else if (args[i] == "--export") {
|
||||
editor = true; //needs editor
|
||||
_export_preset = args[i + 1];
|
||||
if (i + 1 < args.size()) {
|
||||
_export_preset = args[i + 1];
|
||||
} else {
|
||||
ERR_PRINT("Export preset name not specified");
|
||||
return false;
|
||||
}
|
||||
} else if (args[i] == "--export-debug") {
|
||||
editor = true; //needs editor
|
||||
_export_preset = args[i + 1];
|
||||
if (i + 1 < args.size()) {
|
||||
_export_preset = args[i + 1];
|
||||
} else {
|
||||
ERR_PRINT("Export preset name not specified");
|
||||
return false;
|
||||
}
|
||||
export_debug = true;
|
||||
} else {
|
||||
// The parameter does not match anything known, don't skip the next argument
|
||||
|
@ -40,7 +40,7 @@
|
||||
const String init_symbol = "godot_gdnative_init";
|
||||
const String terminate_symbol = "godot_gdnative_terminate";
|
||||
|
||||
String GDNativeLibrary::platform_names[NUM_PLATFORMS] = {
|
||||
String GDNativeLibrary::platform_names[NUM_PLATFORMS + 1] = {
|
||||
"X11_32bit",
|
||||
"X11_64bit",
|
||||
"Windows_32bit",
|
||||
@ -48,11 +48,15 @@ String GDNativeLibrary::platform_names[NUM_PLATFORMS] = {
|
||||
"OSX",
|
||||
|
||||
"Android",
|
||||
"iOS",
|
||||
|
||||
"WebAssembly"
|
||||
"iOS_32bit",
|
||||
"iOS_64bit",
|
||||
|
||||
"WebAssembly",
|
||||
|
||||
""
|
||||
};
|
||||
String GDNativeLibrary::platform_lib_ext[NUM_PLATFORMS] = {
|
||||
String GDNativeLibrary::platform_lib_ext[NUM_PLATFORMS + 1] = {
|
||||
"so",
|
||||
"so",
|
||||
"dll",
|
||||
@ -60,21 +64,30 @@ String GDNativeLibrary::platform_lib_ext[NUM_PLATFORMS] = {
|
||||
"dylib",
|
||||
|
||||
"so",
|
||||
|
||||
"dylib",
|
||||
"dylib",
|
||||
|
||||
"wasm"
|
||||
"wasm",
|
||||
|
||||
""
|
||||
};
|
||||
|
||||
// TODO(karroffel): make this actually do the right thing.
|
||||
GDNativeLibrary::Platform GDNativeLibrary::current_platform =
|
||||
#if defined(X11_ENABLED)
|
||||
X11_64BIT;
|
||||
(sizeof(void *) == 8 ? X11_64BIT : X11_32BIT);
|
||||
#elif defined(WINDOWS_ENABLED)
|
||||
WINDOWS_64BIT;
|
||||
(sizeof(void *) == 8 ? WINDOWS_64BIT : WINDOWS_32BIT);
|
||||
#elif defined(OSX_ENABLED)
|
||||
OSX;
|
||||
#elif defined(IPHONE_ENABLED)
|
||||
(sizeof(void *) == 8 ? IOS_64BIT : IOS_32BIT);
|
||||
#elif defined(ANDROID_ENABLED)
|
||||
ANDROID;
|
||||
#elif defined(JAVASCRIPT_ENABLED)
|
||||
WASM;
|
||||
#else
|
||||
X11_64BIT; // need a sensible default..
|
||||
NUM_PLATFORMS;
|
||||
#endif
|
||||
|
||||
GDNativeLibrary::GDNativeLibrary()
|
||||
@ -151,7 +164,10 @@ String GDNativeLibrary::get_library_path(StringName p_platform) const {
|
||||
}
|
||||
|
||||
String GDNativeLibrary::get_active_library_path() const {
|
||||
return library_paths[GDNativeLibrary::current_platform];
|
||||
if (GDNativeLibrary::current_platform != NUM_PLATFORMS) {
|
||||
return library_paths[GDNativeLibrary::current_platform];
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
GDNative::GDNative() {
|
||||
|
@ -48,11 +48,17 @@ class GDNativeLibrary : public Resource {
|
||||
// NOTE(karroffel): I heard OSX 32 bit is dead, so 64 only
|
||||
OSX,
|
||||
|
||||
// TODO(karroffel): all different android versions and archs
|
||||
// Android .so files must be located in directories corresponding to Android ABI names:
|
||||
// https://developer.android.com/ndk/guides/abis.html
|
||||
// Android runtime will select the matching library depending on the device.
|
||||
// The value here must simply point to the .so name, for example:
|
||||
// "res://libmy_gdnative.so" or "libmy_gdnative.so",
|
||||
// while in the project the actual paths can be "lib/android/armeabi-v7a/libmy_gdnative.so",
|
||||
// "lib/android/arm64-v8a/libmy_gdnative.so".
|
||||
ANDROID,
|
||||
|
||||
// TODO(karroffe): all different iOS versions and archs
|
||||
IOS,
|
||||
IOS_32BIT,
|
||||
IOS_64BIT,
|
||||
|
||||
// TODO(karroffel): figure out how to deal with web stuff at all...
|
||||
WASM,
|
||||
@ -64,10 +70,9 @@ class GDNativeLibrary : public Resource {
|
||||
|
||||
};
|
||||
|
||||
static String platform_names[NUM_PLATFORMS];
|
||||
static String platform_lib_ext[NUM_PLATFORMS];
|
||||
static String platform_names[NUM_PLATFORMS + 1];
|
||||
static String platform_lib_ext[NUM_PLATFORMS + 1];
|
||||
|
||||
// TODO(karroffel): make this actually do something lol.
|
||||
static Platform current_platform;
|
||||
|
||||
String library_paths[NUM_PLATFORMS];
|
||||
|
@ -37,7 +37,7 @@ extern "C" {
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define GODOT_ARRAY_SIZE 8
|
||||
#define GODOT_ARRAY_SIZE sizeof(void *)
|
||||
|
||||
#ifndef GODOT_CORE_API_GODOT_ARRAY_TYPE_DEFINED
|
||||
#define GODOT_CORE_API_GODOT_ARRAY_TYPE_DEFINED
|
||||
|
@ -36,7 +36,7 @@ extern "C" {
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define GODOT_DICTIONARY_SIZE 8
|
||||
#define GODOT_DICTIONARY_SIZE sizeof(void *)
|
||||
|
||||
#ifndef GODOT_CORE_API_GODOT_DICTIONARY_TYPE_DEFINED
|
||||
#define GODOT_CORE_API_GODOT_DICTIONARY_TYPE_DEFINED
|
||||
|
@ -56,7 +56,7 @@ extern "C" {
|
||||
#define GDAPI GDCALLINGCONV
|
||||
#endif
|
||||
#else
|
||||
#define GDCALLINGCONV __attribute__((sysv_abi))
|
||||
#define GDCALLINGCONV __attribute__((sysv_abi, visibility("default")))
|
||||
#define GDAPI GDCALLINGCONV
|
||||
#endif
|
||||
|
||||
|
@ -36,7 +36,7 @@ extern "C" {
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define GODOT_NODE_PATH_SIZE 8
|
||||
#define GODOT_NODE_PATH_SIZE sizeof(void *)
|
||||
|
||||
#ifndef GODOT_CORE_API_GODOT_NODE_PATH_TYPE_DEFINED
|
||||
#define GODOT_CORE_API_GODOT_NODE_PATH_TYPE_DEFINED
|
||||
|
@ -38,7 +38,7 @@ extern "C" {
|
||||
|
||||
/////// PoolByteArray
|
||||
|
||||
#define GODOT_POOL_BYTE_ARRAY_SIZE 8
|
||||
#define GODOT_POOL_BYTE_ARRAY_SIZE sizeof(void *)
|
||||
|
||||
#ifndef GODOT_CORE_API_GODOT_POOL_BYTE_ARRAY_TYPE_DEFINED
|
||||
#define GODOT_CORE_API_GODOT_POOL_BYTE_ARRAY_TYPE_DEFINED
|
||||
@ -49,7 +49,7 @@ typedef struct {
|
||||
|
||||
/////// PoolIntArray
|
||||
|
||||
#define GODOT_POOL_INT_ARRAY_SIZE 8
|
||||
#define GODOT_POOL_INT_ARRAY_SIZE sizeof(void *)
|
||||
|
||||
#ifndef GODOT_CORE_API_GODOT_POOL_INT_ARRAY_TYPE_DEFINED
|
||||
#define GODOT_CORE_API_GODOT_POOL_INT_ARRAY_TYPE_DEFINED
|
||||
@ -60,7 +60,7 @@ typedef struct {
|
||||
|
||||
/////// PoolRealArray
|
||||
|
||||
#define GODOT_POOL_REAL_ARRAY_SIZE 8
|
||||
#define GODOT_POOL_REAL_ARRAY_SIZE sizeof(void *)
|
||||
|
||||
#ifndef GODOT_CORE_API_GODOT_POOL_REAL_ARRAY_TYPE_DEFINED
|
||||
#define GODOT_CORE_API_GODOT_POOL_REAL_ARRAY_TYPE_DEFINED
|
||||
@ -71,7 +71,7 @@ typedef struct {
|
||||
|
||||
/////// PoolStringArray
|
||||
|
||||
#define GODOT_POOL_STRING_ARRAY_SIZE 8
|
||||
#define GODOT_POOL_STRING_ARRAY_SIZE sizeof(void *)
|
||||
|
||||
#ifndef GODOT_CORE_API_GODOT_POOL_STRING_ARRAY_TYPE_DEFINED
|
||||
#define GODOT_CORE_API_GODOT_POOL_STRING_ARRAY_TYPE_DEFINED
|
||||
@ -82,7 +82,7 @@ typedef struct {
|
||||
|
||||
/////// PoolVector2Array
|
||||
|
||||
#define GODOT_POOL_VECTOR2_ARRAY_SIZE 8
|
||||
#define GODOT_POOL_VECTOR2_ARRAY_SIZE sizeof(void *)
|
||||
|
||||
#ifndef GODOT_CORE_API_GODOT_POOL_VECTOR2_ARRAY_TYPE_DEFINED
|
||||
#define GODOT_CORE_API_GODOT_POOL_VECTOR2_ARRAY_TYPE_DEFINED
|
||||
@ -93,7 +93,7 @@ typedef struct {
|
||||
|
||||
/////// PoolVector3Array
|
||||
|
||||
#define GODOT_POOL_VECTOR3_ARRAY_SIZE 8
|
||||
#define GODOT_POOL_VECTOR3_ARRAY_SIZE sizeof(void *)
|
||||
|
||||
#ifndef GODOT_CORE_API_GODOT_POOL_VECTOR3_ARRAY_TYPE_DEFINED
|
||||
#define GODOT_CORE_API_GODOT_POOL_VECTOR3_ARRAY_TYPE_DEFINED
|
||||
@ -104,7 +104,7 @@ typedef struct {
|
||||
|
||||
/////// PoolColorArray
|
||||
|
||||
#define GODOT_POOL_COLOR_ARRAY_SIZE 8
|
||||
#define GODOT_POOL_COLOR_ARRAY_SIZE sizeof(void *)
|
||||
|
||||
#ifndef GODOT_CORE_API_GODOT_POOL_COLOR_ARRAY_TYPE_DEFINED
|
||||
#define GODOT_CORE_API_GODOT_POOL_COLOR_ARRAY_TYPE_DEFINED
|
||||
|
@ -36,7 +36,7 @@ extern "C" {
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define GODOT_RID_SIZE 8
|
||||
#define GODOT_RID_SIZE sizeof(void *)
|
||||
|
||||
#ifndef GODOT_CORE_API_GODOT_RID_TYPE_DEFINED
|
||||
#define GODOT_CORE_API_GODOT_RID_TYPE_DEFINED
|
||||
|
@ -37,7 +37,7 @@ extern "C" {
|
||||
#include <stdint.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#define GODOT_STRING_SIZE 8
|
||||
#define GODOT_STRING_SIZE sizeof(void *)
|
||||
|
||||
#ifndef GODOT_CORE_API_GODOT_STRING_TYPE_DEFINED
|
||||
#define GODOT_CORE_API_GODOT_STRING_TYPE_DEFINED
|
||||
|
@ -36,7 +36,7 @@ extern "C" {
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define GODOT_VARIANT_SIZE 24
|
||||
#define GODOT_VARIANT_SIZE (16 + sizeof(void *))
|
||||
|
||||
#ifndef GODOT_CORE_API_GODOT_VARIANT_TYPE_DEFINED
|
||||
#define GODOT_CORE_API_GODOT_VARIANT_TYPE_DEFINED
|
||||
|
@ -58,7 +58,7 @@ extern "C" {
|
||||
#define GDAPI GDCALLINGCONV
|
||||
#endif
|
||||
#else
|
||||
#define GDCALLINGCONV __attribute__((sysv_abi))
|
||||
#define GDCALLINGCONV __attribute__((sysv_abi, visibility("default")))
|
||||
#define GDAPI GDCALLINGCONV
|
||||
#endif
|
||||
|
||||
|
@ -994,6 +994,8 @@ void NativeScriptLanguage::init_library(const Ref<GDNativeLibrary> &lib) {
|
||||
#endif
|
||||
// See if this library was "registered" already.
|
||||
const String &lib_path = lib->get_active_library_path();
|
||||
ERR_EXPLAIN(lib->get_name() + " does not have a library for the current platform");
|
||||
ERR_FAIL_COND(lib_path.length() == 0);
|
||||
Map<String, Ref<GDNative> >::Element *E = library_gdnatives.find(lib_path);
|
||||
|
||||
if (!E) {
|
||||
|
@ -240,7 +240,7 @@ def configure(env):
|
||||
|
||||
env.Append(CPPPATH=['#platform/android'])
|
||||
env.Append(CPPFLAGS=['-DANDROID_ENABLED', '-DUNIX_ENABLED', '-DNO_FCNTL', '-DMPC_FIXED_POINT'])
|
||||
env.Append(LIBS=['OpenSLES', 'EGL', 'GLESv3', 'android', 'log', 'z'])
|
||||
env.Append(LIBS=['OpenSLES', 'EGL', 'GLESv3', 'android', 'log', 'z', 'dl'])
|
||||
|
||||
# TODO: Move that to opus module's config
|
||||
if("module_opus_enabled" in env and env["module_opus_enabled"] != "no"):
|
||||
|
@ -468,11 +468,36 @@ class EditorExportAndroid : public EditorExportPlatform {
|
||||
return zipfi;
|
||||
}
|
||||
|
||||
static Error save_apk_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total) {
|
||||
static Set<String> get_abis() {
|
||||
Set<String> abis;
|
||||
abis.insert("armeabi");
|
||||
abis.insert("armeabi-v7a");
|
||||
abis.insert("arm64-v8a");
|
||||
abis.insert("x86");
|
||||
abis.insert("x86_64");
|
||||
abis.insert("mips");
|
||||
abis.insert("mips64");
|
||||
return abis;
|
||||
}
|
||||
|
||||
static Error save_apk_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total) {
|
||||
APKExportData *ed = (APKExportData *)p_userdata;
|
||||
String dst_path = p_path;
|
||||
dst_path = dst_path.replace_first("res://", "assets/");
|
||||
static Set<String> android_abis = get_abis();
|
||||
|
||||
if (dst_path.ends_with(".so")) {
|
||||
String abi = dst_path.get_base_dir().get_file().strip_edges(); // parent dir name
|
||||
if (android_abis.has(abi)) {
|
||||
dst_path = "lib/" + abi + "/" + dst_path.get_file();
|
||||
} else {
|
||||
String err = "Dynamic libraries must be located in the folder named after Android ABI they were compiled for. " +
|
||||
p_path + " does not follow this convention.";
|
||||
ERR_PRINT(err.utf8().get_data());
|
||||
return ERR_FILE_BAD_PATH;
|
||||
}
|
||||
} else {
|
||||
dst_path = dst_path.replace_first("res://", "assets/");
|
||||
}
|
||||
|
||||
zip_fileinfo zipfi = get_zip_fileinfo();
|
||||
|
||||
@ -1393,15 +1418,15 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
if (file == "lib/x86/libgodot_android.so" && !export_x86) {
|
||||
if (file == "lib/x86/*.so" && !export_x86) {
|
||||
skip = true;
|
||||
}
|
||||
|
||||
if (file.match("lib/armeabi*/libgodot_android.so") && !export_arm) {
|
||||
if (file.match("lib/armeabi*/*.so") && !export_arm) {
|
||||
skip = true;
|
||||
}
|
||||
|
||||
if (file.match("lib/arm64*/libgodot_android.so") && !export_arm64) {
|
||||
if (file.match("lib/arm64*/*.so") && !export_arm64) {
|
||||
skip = true;
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ import android.os.SystemClock;
|
||||
|
||||
|
||||
public class Godot extends Activity implements SensorEventListener, IDownloaderClient
|
||||
{
|
||||
{
|
||||
|
||||
static final int MAX_SINGLETONS = 64;
|
||||
private IStub mDownloaderClientStub;
|
||||
@ -139,9 +139,9 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
||||
com.godot.game.R.string.text_button_pause;
|
||||
mPauseButton.setText(stringResourceID);
|
||||
}
|
||||
|
||||
|
||||
static public class SingletonBase {
|
||||
|
||||
|
||||
protected void registerClass(String p_name, String[] p_methods) {
|
||||
|
||||
GodotLib.singleton(p_name,this);
|
||||
@ -210,6 +210,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
||||
*/
|
||||
|
||||
private String[] command_line;
|
||||
private boolean use_apk_expansion;
|
||||
|
||||
public GodotView mView;
|
||||
private boolean godot_initialized=false;
|
||||
@ -264,27 +265,40 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
||||
layout = new FrameLayout(this);
|
||||
layout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
|
||||
setContentView(layout);
|
||||
|
||||
|
||||
// GodotEditText layout
|
||||
GodotEditText edittext = new GodotEditText(this);
|
||||
GodotEditText edittext = new GodotEditText(this);
|
||||
edittext.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
|
||||
// ...add to FrameLayout
|
||||
layout.addView(edittext);
|
||||
|
||||
|
||||
mView = new GodotView(getApplication(),io,use_gl2,use_32_bits, this);
|
||||
layout.addView(mView,new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
|
||||
setKeepScreenOn(GodotLib.getGlobal("display/driver/keep_screen_on").equals("True"));
|
||||
|
||||
edittext.setView(mView);
|
||||
io.setEdit(edittext);
|
||||
|
||||
edittext.setView(mView);
|
||||
io.setEdit(edittext);
|
||||
|
||||
// Ad layout
|
||||
adLayout = new RelativeLayout(this);
|
||||
adLayout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
|
||||
layout.addView(adLayout);
|
||||
|
||||
|
||||
final String[] current_command_line = command_line;
|
||||
final GodotView view = mView;
|
||||
mView.queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GodotLib.setup(current_command_line);
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
view.setKeepScreenOn("True".equals(GodotLib.getGlobal("display/driver/keep_screen_on")));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void setKeepScreenOn(final boolean p_enabled) {
|
||||
keep_screen_on = p_enabled;
|
||||
if (mView != null){
|
||||
@ -315,13 +329,13 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private static Godot _self;
|
||||
|
||||
|
||||
public static Godot getInstance(){
|
||||
return Godot._self;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private String[] getCommandLine() {
|
||||
InputStream is;
|
||||
@ -402,7 +416,6 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
||||
Log.d("GODOT"," " + command_line[w]);
|
||||
}
|
||||
}*/
|
||||
GodotLib.initialize(this,io.needsReloadHooks(),command_line,getAssets());
|
||||
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
|
||||
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
||||
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
|
||||
@ -411,9 +424,12 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
||||
mGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
|
||||
mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_GAME);
|
||||
|
||||
GodotLib.initialize(this, io.needsReloadHooks(), getAssets(), use_apk_expansion);
|
||||
|
||||
result_callback = null;
|
||||
|
||||
mPaymentsManager = PaymentsManager.createManager(this).initService();
|
||||
|
||||
godot_initialized=true;
|
||||
|
||||
}
|
||||
@ -426,7 +442,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle) {
|
||||
|
||||
Log.d("GODOT", "** GODOT ACTIVITY CREATED HERE ***\n");
|
||||
@ -437,12 +453,10 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
||||
//window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
|
||||
|
||||
|
||||
//check for apk expansion API
|
||||
if (true) {
|
||||
boolean md5mismatch = false;
|
||||
command_line = getCommandLine();
|
||||
boolean use_apk_expansion=false;
|
||||
String main_pack_md5=null;
|
||||
String main_pack_key=null;
|
||||
|
||||
@ -528,23 +542,23 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
||||
|
||||
if (!pack_valid) {
|
||||
Log.d("GODOT", "Pack Invalid, try re-downloading.");
|
||||
|
||||
|
||||
Intent notifierIntent = new Intent(this, this.getClass());
|
||||
notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
|
||||
Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
|
||||
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
|
||||
notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
|
||||
int startResult;
|
||||
try {
|
||||
Log.d("GODOT", "INITIALIZING DOWNLOAD");
|
||||
startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(
|
||||
getApplicationContext(),
|
||||
pendingIntent,
|
||||
getApplicationContext(),
|
||||
pendingIntent,
|
||||
GodotDownloaderService.class);
|
||||
Log.d("GODOT", "DOWNLOAD SERVICE FINISHED:" + startResult);
|
||||
|
||||
|
||||
if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) {
|
||||
Log.d("GODOT", "DOWNLOAD REQUIRED");
|
||||
// This is where you do set up to display the download
|
||||
@ -563,7 +577,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
||||
mCellMessage = findViewById(com.godot.game.R.id.approveCellular);
|
||||
mPauseButton = (Button) findViewById(com.godot.game.R.id.pauseButton);
|
||||
mWiFiSettingsButton = (Button) findViewById(com.godot.game.R.id.wifiSettingsButton);
|
||||
|
||||
|
||||
return;
|
||||
} else{
|
||||
Log.d("GODOT", "NO DOWNLOAD REQUIRED");
|
||||
@ -582,7 +596,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
||||
|
||||
initializeGodot();
|
||||
|
||||
|
||||
|
||||
//instanceSingleton( new GodotFacebook(this) );
|
||||
|
||||
|
||||
@ -590,14 +604,14 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
||||
|
||||
|
||||
@Override protected void onDestroy(){
|
||||
|
||||
|
||||
if(mPaymentsManager != null ) mPaymentsManager.destroy();
|
||||
for(int i=0;i<singleton_count;i++) {
|
||||
singletons[i].onMainDestroy();
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
|
||||
@Override protected void onPause() {
|
||||
super.onPause();
|
||||
if (!godot_initialized){
|
||||
@ -607,8 +621,13 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
||||
return;
|
||||
}
|
||||
mView.onPause();
|
||||
mView.queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GodotLib.focusout();
|
||||
}
|
||||
});
|
||||
mSensorManager.unregisterListener(this);
|
||||
GodotLib.focusout();
|
||||
|
||||
for(int i=0;i<singleton_count;i++) {
|
||||
singletons[i].onMainPause();
|
||||
@ -625,10 +644,16 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
||||
}
|
||||
|
||||
mView.onResume();
|
||||
mView.queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GodotLib.focusin();
|
||||
}
|
||||
});
|
||||
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
|
||||
mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_GAME);
|
||||
mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_GAME);
|
||||
GodotLib.focusin();
|
||||
|
||||
if(use_immersive && Build.VERSION.SDK_INT >= 19.0){ // check if the application runs on an android 4.4+
|
||||
Window window = getWindow();
|
||||
window.getDecorView().setSystemUiVisibility(
|
||||
@ -644,8 +669,8 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
||||
|
||||
singletons[i].onMainResume();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -670,32 +695,39 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
||||
@Override public void onSensorChanged(SensorEvent event) {
|
||||
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
|
||||
int displayRotation = display.getRotation();
|
||||
|
||||
|
||||
float[] adjustedValues = new float[3];
|
||||
final int axisSwap[][] = {
|
||||
{ 1, -1, 0, 1 }, // ROTATION_0
|
||||
{-1, -1, 1, 0 }, // ROTATION_90
|
||||
{-1, 1, 0, 1 }, // ROTATION_180
|
||||
{ 1, 1, 1, 0 } }; // ROTATION_270
|
||||
{ 1, -1, 0, 1 }, // ROTATION_0
|
||||
{-1, -1, 1, 0 }, // ROTATION_90
|
||||
{-1, 1, 0, 1 }, // ROTATION_180
|
||||
{ 1, 1, 1, 0 } }; // ROTATION_270
|
||||
|
||||
final int[] as = axisSwap[displayRotation];
|
||||
adjustedValues[0] = (float)as[0] * event.values[ as[2] ];
|
||||
adjustedValues[1] = (float)as[1] * event.values[ as[3] ];
|
||||
final int[] as = axisSwap[displayRotation];
|
||||
adjustedValues[0] = (float)as[0] * event.values[ as[2] ];
|
||||
adjustedValues[1] = (float)as[1] * event.values[ as[3] ];
|
||||
adjustedValues[2] = event.values[2];
|
||||
|
||||
float x = adjustedValues[0];
|
||||
float y = adjustedValues[1];
|
||||
float z = adjustedValues[2];
|
||||
|
||||
int typeOfSensor = event.sensor.getType();
|
||||
if (typeOfSensor == event.sensor.TYPE_ACCELEROMETER) {
|
||||
GodotLib.accelerometer(x,y,z);
|
||||
}
|
||||
if (typeOfSensor == event.sensor.TYPE_MAGNETIC_FIELD) {
|
||||
GodotLib.magnetometer(x,y,z);
|
||||
}
|
||||
if (typeOfSensor == event.sensor.TYPE_GYROSCOPE) {
|
||||
GodotLib.gyroscope(x,y,z);
|
||||
final float x = adjustedValues[0];
|
||||
final float y = adjustedValues[1];
|
||||
final float z = adjustedValues[2];
|
||||
|
||||
final int typeOfSensor = event.sensor.getType();
|
||||
if (mView != null) {
|
||||
mView.queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (typeOfSensor == Sensor.TYPE_ACCELEROMETER) {
|
||||
GodotLib.accelerometer(x,y,z);
|
||||
}
|
||||
if (typeOfSensor == Sensor.TYPE_MAGNETIC_FIELD) {
|
||||
GodotLib.magnetometer(x,y,z);
|
||||
}
|
||||
if (typeOfSensor == Sensor.TYPE_GYROSCOPE) {
|
||||
GodotLib.gyroscope(x,y,z);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -722,7 +754,14 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
||||
@Override public void onBackPressed() {
|
||||
|
||||
System.out.printf("** BACK REQUEST!\n");
|
||||
//GodotLib.back();
|
||||
if (mView != null) {
|
||||
mView.queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GodotLib.back();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void forceQuit() {
|
||||
@ -733,7 +772,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
||||
|
||||
|
||||
private boolean obbIsCorrupted(String f, String main_pack_md5){
|
||||
|
||||
|
||||
try {
|
||||
|
||||
InputStream fis = new FileInputStream(f);
|
||||
@ -780,58 +819,64 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
||||
}
|
||||
|
||||
//@Override public boolean dispatchTouchEvent (MotionEvent event) {
|
||||
public boolean gotTouchEvent(MotionEvent event) {
|
||||
public boolean gotTouchEvent(final MotionEvent event) {
|
||||
|
||||
super.onTouchEvent(event);
|
||||
int evcount=event.getPointerCount();
|
||||
final int evcount=event.getPointerCount();
|
||||
if (evcount==0)
|
||||
return true;
|
||||
|
||||
int[] arr = new int[event.getPointerCount()*3];
|
||||
if (mView != null) {
|
||||
final int[] arr = new int[event.getPointerCount()*3];
|
||||
|
||||
for(int i=0;i<event.getPointerCount();i++) {
|
||||
for(int i=0;i<event.getPointerCount();i++) {
|
||||
|
||||
arr[i*3+0]=(int)event.getPointerId(i);
|
||||
arr[i*3+1]=(int)event.getX(i);
|
||||
arr[i*3+2]=(int)event.getY(i);
|
||||
}
|
||||
arr[i*3+0]=(int)event.getPointerId(i);
|
||||
arr[i*3+1]=(int)event.getX(i);
|
||||
arr[i*3+2]=(int)event.getY(i);
|
||||
}
|
||||
|
||||
//System.out.printf("gaction: %d\n",event.getAction());
|
||||
switch(event.getAction()&MotionEvent.ACTION_MASK) {
|
||||
|
||||
case MotionEvent.ACTION_DOWN: {
|
||||
GodotLib.touch(0,0,evcount,arr);
|
||||
//System.out.printf("action down at: %f,%f\n", event.getX(),event.getY());
|
||||
} break;
|
||||
case MotionEvent.ACTION_MOVE: {
|
||||
GodotLib.touch(1,0,evcount,arr);
|
||||
/*
|
||||
for(int i=0;i<event.getPointerCount();i++) {
|
||||
System.out.printf("%d - moved to: %f,%f\n",i, event.getX(i),event.getY(i));
|
||||
//System.out.printf("gaction: %d\n",event.getAction());
|
||||
final int action = event.getAction() & MotionEvent.ACTION_MASK;
|
||||
mView.queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
switch(action) {
|
||||
case MotionEvent.ACTION_DOWN: {
|
||||
GodotLib.touch(0,0,evcount,arr);
|
||||
//System.out.printf("action down at: %f,%f\n", event.getX(),event.getY());
|
||||
} break;
|
||||
case MotionEvent.ACTION_MOVE: {
|
||||
GodotLib.touch(1,0,evcount,arr);
|
||||
/*
|
||||
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 MotionEvent.ACTION_POINTER_UP: {
|
||||
final int indexPointUp = event.getActionIndex();
|
||||
final int pointer_idx = event.getPointerId(indexPointUp);
|
||||
GodotLib.touch(4,pointer_idx,evcount,arr);
|
||||
//System.out.printf("%d - s.up at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
|
||||
} break;
|
||||
case MotionEvent.ACTION_POINTER_DOWN: {
|
||||
int pointer_idx = event.getActionIndex();
|
||||
GodotLib.touch(3,pointer_idx,evcount,arr);
|
||||
//System.out.printf("%d - s.down at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
|
||||
} break;
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
case MotionEvent.ACTION_UP: {
|
||||
GodotLib.touch(2,0,evcount,arr);
|
||||
/*
|
||||
for(int i=0;i<event.getPointerCount();i++) {
|
||||
System.out.printf("%d - up! %f,%f\n",i, event.getX(i),event.getY(i));
|
||||
}
|
||||
*/
|
||||
} break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
} break;
|
||||
case MotionEvent.ACTION_POINTER_UP: {
|
||||
final int indexPointUp = event.getActionIndex();
|
||||
final int pointer_idx = event.getPointerId(indexPointUp);
|
||||
GodotLib.touch(4,pointer_idx,evcount,arr);
|
||||
//System.out.printf("%d - s.up at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
|
||||
} break;
|
||||
case MotionEvent.ACTION_POINTER_DOWN: {
|
||||
int pointer_idx = event.getActionIndex();
|
||||
GodotLib.touch(3,pointer_idx,evcount,arr);
|
||||
//System.out.printf("%d - s.down at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
|
||||
} break;
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
case MotionEvent.ACTION_UP: {
|
||||
GodotLib.touch(2,0,evcount,arr);
|
||||
/*
|
||||
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 true;
|
||||
}
|
||||
@ -864,7 +909,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
||||
|
||||
private void queueEvent(Runnable runnable) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
|
||||
}
|
||||
|
||||
public PaymentsManager getPaymentsManager() {
|
||||
@ -988,7 +1033,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
|
||||
mProgressFraction.setText(Helpers.getDownloadProgressString
|
||||
(progress.mOverallProgress,
|
||||
progress.mOverallTotal));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ public class GodotLib {
|
||||
public static GodotIO io;
|
||||
|
||||
static {
|
||||
System.loadLibrary("godot_android");
|
||||
System.loadLibrary("godot_android");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -45,7 +45,8 @@ public class GodotLib {
|
||||
* @param height the current view height
|
||||
*/
|
||||
|
||||
public static native void initialize(Godot p_instance,boolean need_reload_hook,String[] p_cmdline,Object p_asset_manager);
|
||||
public static native void initialize(Godot p_instance,boolean need_reload_hook,Object p_asset_manager, boolean use_apk_expansion);
|
||||
public static native void setup(String[] p_cmdline);
|
||||
public static native void resize(int width, int height,boolean reload);
|
||||
public static native void newcontext(boolean p_32_bits);
|
||||
public static native void back();
|
||||
|
@ -89,7 +89,7 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
|
||||
}
|
||||
|
||||
public void callbackSuccess(String ticket, String signature, String sku) {
|
||||
GodotLib.callobject(purchaseCallbackId, "purchase_success", new Object[]{ticket, signature, sku});
|
||||
GodotLib.calldeferred(purchaseCallbackId, "purchase_success", new Object[]{ticket, signature, sku});
|
||||
}
|
||||
|
||||
public void callbackSuccessProductMassConsumed(String ticket, String signature, String sku) {
|
||||
|
@ -208,8 +208,9 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
|
||||
@Override public void onInputDeviceAdded(int deviceId) {
|
||||
joystick joy = new joystick();
|
||||
joy.device_id = deviceId;
|
||||
int id = joy_devices.size();
|
||||
final int id = joy_devices.size();
|
||||
InputDevice device = mInputManager.getInputDevice(deviceId);
|
||||
final String name = device.getName();
|
||||
joy.name = device.getName();
|
||||
joy.axes = new ArrayList<InputDevice.MotionRange>();
|
||||
joy.hats = new ArrayList<InputDevice.MotionRange>();
|
||||
@ -224,19 +225,29 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
|
||||
}
|
||||
}
|
||||
joy_devices.add(joy);
|
||||
GodotLib.joyconnectionchanged(id, true, joy.name);
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GodotLib.joyconnectionchanged(id, true, name);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override public void onInputDeviceRemoved(int deviceId) {
|
||||
int id = find_joy_device(deviceId);
|
||||
final int id = find_joy_device(deviceId);
|
||||
joy_devices.remove(id);
|
||||
GodotLib.joyconnectionchanged(id, false, "");
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GodotLib.joyconnectionchanged(id, false, "");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override public void onInputDeviceChanged(int deviceId) {
|
||||
|
||||
}
|
||||
@Override public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
@Override public boolean onKeyUp(final int keyCode, KeyEvent event) {
|
||||
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
return true;
|
||||
@ -249,22 +260,38 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
|
||||
int source = event.getSource();
|
||||
if ((source & InputDevice.SOURCE_JOYSTICK) != 0 || (source & InputDevice.SOURCE_DPAD) != 0 || (source & InputDevice.SOURCE_GAMEPAD) != 0) {
|
||||
|
||||
int button = get_godot_button(keyCode);
|
||||
int device = find_joy_device(event.getDeviceId());
|
||||
final int button = get_godot_button(keyCode);
|
||||
final int device = find_joy_device(event.getDeviceId());
|
||||
|
||||
GodotLib.joybutton(device, button, false);
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GodotLib.joybutton(device, button, false);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
} else {
|
||||
|
||||
GodotLib.key(keyCode, event.getUnicodeChar(0), false);
|
||||
final int chr = event.getUnicodeChar(0);
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GodotLib.key(keyCode, chr, false);
|
||||
}
|
||||
});
|
||||
};
|
||||
return super.onKeyUp(keyCode, event);
|
||||
};
|
||||
|
||||
@Override public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
@Override public boolean onKeyDown(final int keyCode, KeyEvent event) {
|
||||
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
GodotLib.back();
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GodotLib.back();
|
||||
}
|
||||
});
|
||||
|
||||
// press 'back' button should not terminate program
|
||||
//normal handle 'back' event in game logic
|
||||
return true;
|
||||
@ -281,16 +308,26 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
|
||||
|
||||
if (event.getRepeatCount() > 0) // ignore key echo
|
||||
return true;
|
||||
int button = get_godot_button(keyCode);
|
||||
int device = find_joy_device(event.getDeviceId());
|
||||
final int button = get_godot_button(keyCode);
|
||||
final int device = find_joy_device(event.getDeviceId());
|
||||
|
||||
//Log.e(TAG, String.format("joy button down! button %x, %d, device %d", keyCode, button, device));
|
||||
|
||||
GodotLib.joybutton(device, button, true);
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GodotLib.joybutton(device, button, true);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
|
||||
} else {
|
||||
GodotLib.key(keyCode, event.getUnicodeChar(0), true);
|
||||
final int chr = event.getUnicodeChar(0);
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GodotLib.key(keyCode, chr, true);
|
||||
}
|
||||
});
|
||||
};
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
@ -299,21 +336,32 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
|
||||
|
||||
if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK && event.getAction() == MotionEvent.ACTION_MOVE) {
|
||||
|
||||
int device_id = find_joy_device(event.getDeviceId());
|
||||
final int device_id = find_joy_device(event.getDeviceId());
|
||||
joystick joy = joy_devices.get(device_id);
|
||||
|
||||
for (int i = 0; i < joy.axes.size(); i++) {
|
||||
InputDevice.MotionRange range = joy.axes.get(i);
|
||||
float value = (event.getAxisValue(range.getAxis()) - range.getMin() ) / range.getRange() * 2.0f - 1.0f;
|
||||
final float value = (event.getAxisValue(range.getAxis()) - range.getMin() ) / range.getRange() * 2.0f - 1.0f;
|
||||
//Log.e(TAG, String.format("axis event: %d, value %f", i, value));
|
||||
GodotLib.joyaxis(device_id, i, value);
|
||||
final int idx = i;
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GodotLib.joyaxis(device_id, idx, value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (int i = 0; i < joy.hats.size(); i+=2) {
|
||||
int hatX = Math.round(event.getAxisValue(joy.hats.get(i).getAxis()));
|
||||
int hatY = Math.round(event.getAxisValue(joy.hats.get(i+1).getAxis()));
|
||||
final int hatX = Math.round(event.getAxisValue(joy.hats.get(i).getAxis()));
|
||||
final int hatY = Math.round(event.getAxisValue(joy.hats.get(i+1).getAxis()));
|
||||
//Log.e(TAG, String.format("HAT EVENT %d, %d", hatX, hatY));
|
||||
GodotLib.joyhat(device_id, hatX, hatY);
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GodotLib.joyhat(device_id, hatX, hatY);
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
@ -89,8 +89,13 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
|
||||
//Log.d(TAG, "beforeTextChanged(" + pCharSequence + ")start: " + start + ",count: " + count + ",after: " + after);
|
||||
|
||||
for (int i=0;i<count;i++){
|
||||
GodotLib.key(KeyEvent.KEYCODE_DEL, 0, true);
|
||||
GodotLib.key(KeyEvent.KEYCODE_DEL, 0, false);
|
||||
mView.queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GodotLib.key(KeyEvent.KEYCODE_DEL, 0, true);
|
||||
GodotLib.key(KeyEvent.KEYCODE_DEL, 0, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,9 +104,14 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
|
||||
//Log.d(TAG, "onTextChanged(" + pCharSequence + ")start: " + start + ",count: " + count + ",before: " + before);
|
||||
|
||||
for (int i=start;i<start+count;i++){
|
||||
int ch = pCharSequence.charAt(i);
|
||||
GodotLib.key(0, ch, true);
|
||||
GodotLib.key(0, ch, false);
|
||||
final int ch = pCharSequence.charAt(i);
|
||||
mView.queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GodotLib.key(0, ch, true);
|
||||
GodotLib.key(0, ch, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@ -111,8 +121,14 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
|
||||
if (this.mEdit == pTextView && this.isFullScreenEdit()) {
|
||||
// user press the action button, delete all old text and insert new text
|
||||
for (int i = this.mOriginText.length(); i > 0; i--) {
|
||||
GodotLib.key(KeyEvent.KEYCODE_DEL, 0, true);
|
||||
GodotLib.key(KeyEvent.KEYCODE_DEL, 0, false);
|
||||
mView.queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GodotLib.key(KeyEvent.KEYCODE_DEL, 0, true);
|
||||
GodotLib.key(KeyEvent.KEYCODE_DEL, 0, false);
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.d(TAG, "deleteBackward");
|
||||
@ -131,9 +147,14 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
|
||||
}
|
||||
|
||||
for(int i = 0; i < text.length(); i++) {
|
||||
int ch = text.codePointAt(i);
|
||||
GodotLib.key(0, ch, true);
|
||||
GodotLib.key(0, ch, false);
|
||||
final int ch = text.codePointAt(i);
|
||||
mView.queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GodotLib.key(0, ch, true);
|
||||
GodotLib.key(0, ch, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
/*
|
||||
if (BuildConfig.DEBUG) {
|
||||
@ -141,7 +162,7 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
if (pActionID == EditorInfo.IME_ACTION_DONE) {
|
||||
this.mView.requestFocus();
|
||||
}
|
||||
|
@ -613,8 +613,6 @@ static List<JAndroidPointerEvent> pointer_events;
|
||||
static List<Ref<InputEvent> > key_events;
|
||||
static List<OS_Android::JoypadEvent> joy_events;
|
||||
static bool initialized = false;
|
||||
static Mutex *input_mutex = NULL;
|
||||
static Mutex *suspend_mutex = NULL;
|
||||
static int step = 0;
|
||||
static bool resized = false;
|
||||
static bool resized_reload = false;
|
||||
@ -756,7 +754,7 @@ static void _alert(const String &p_message, const String &p_title) {
|
||||
env->CallVoidMethod(_godot_instance, _alertDialog, jStrMessage, jStrTitle);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jobject obj, jobject activity, jboolean p_need_reload_hook, jobjectArray p_cmdline, jobject p_asset_manager) {
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jobject obj, jobject activity, jboolean p_need_reload_hook, jobject p_asset_manager, jboolean p_use_apk_expansion) {
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "godot", "**INIT EVENT! - %p\n", env);
|
||||
|
||||
@ -826,36 +824,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en
|
||||
AudioDriverAndroid::setup(gob);
|
||||
}
|
||||
|
||||
const char **cmdline = NULL;
|
||||
int cmdlen = 0;
|
||||
bool use_apk_expansion = false;
|
||||
if (p_cmdline) {
|
||||
cmdlen = env->GetArrayLength(p_cmdline);
|
||||
if (cmdlen) {
|
||||
cmdline = (const char **)malloc((env->GetArrayLength(p_cmdline) + 1) * sizeof(const char *));
|
||||
cmdline[cmdlen] = NULL;
|
||||
|
||||
for (int i = 0; i < cmdlen; i++) {
|
||||
|
||||
jstring string = (jstring)env->GetObjectArrayElement(p_cmdline, i);
|
||||
const char *rawString = env->GetStringUTFChars(string, 0);
|
||||
if (!rawString) {
|
||||
__android_log_print(ANDROID_LOG_INFO, "godot", "cmdline arg %i is null\n", i);
|
||||
} else {
|
||||
//__android_log_print(ANDROID_LOG_INFO,"godot","cmdline arg %i is: %s\n",i,rawString);
|
||||
|
||||
if (strcmp(rawString, "--main_pack") == 0)
|
||||
use_apk_expansion = true;
|
||||
}
|
||||
|
||||
cmdline[i] = rawString;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "godot", "CMDLINE LEN %i - APK EXPANSION %I\n", cmdlen, int(use_apk_expansion));
|
||||
|
||||
os_android = new OS_Android(_gfx_init_func, env, _open_uri, _get_data_dir, _get_locale, _get_model, _get_screen_dpi, _show_vk, _hide_vk, _set_screen_orient, _get_unique_id, _get_system_dir, _play_video, _is_video_playing, _pause_video, _stop_video, _set_keep_screen_on, _alert, use_apk_expansion);
|
||||
os_android = new OS_Android(_gfx_init_func, env, _open_uri, _get_data_dir, _get_locale, _get_model, _get_screen_dpi, _show_vk, _hide_vk, _set_screen_orient, _get_unique_id, _get_system_dir, _play_video, _is_video_playing, _pause_video, _stop_video, _set_keep_screen_on, _alert, p_use_apk_expansion);
|
||||
os_android->set_need_reload_hooks(p_need_reload_hook);
|
||||
|
||||
char wd[500];
|
||||
@ -864,62 +833,10 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en
|
||||
__android_log_print(ANDROID_LOG_INFO, "godot", "test construction %i\n", tst.a);
|
||||
__android_log_print(ANDROID_LOG_INFO, "godot", "running from dir %s\n", wd);
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "godot", "**SETUP");
|
||||
|
||||
Error err = Main::setup("apk", cmdlen, (char **)cmdline, false);
|
||||
|
||||
if (err != OK) {
|
||||
__android_log_print(ANDROID_LOG_INFO, "godot", "*****UNABLE TO SETUP");
|
||||
|
||||
return; //should exit instead and print the error
|
||||
}
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "godot", "*****SETUP OK");
|
||||
|
||||
//video driver is determined here, because once initialized, it can't be changed
|
||||
String vd = ProjectSettings::get_singleton()->get("display/driver");
|
||||
// String vd = ProjectSettings::get_singleton()->get("display/driver");
|
||||
|
||||
env->CallVoidMethod(_godot_instance, _on_video_init, (jboolean) true);
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "godot", "**START");
|
||||
|
||||
input_mutex = Mutex::create();
|
||||
suspend_mutex = Mutex::create();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jobject obj, jint width, jint height, jboolean reload) {
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "godot", "^_^_^_^_^ resize %lld, %i, %i\n", Thread::get_caller_id(), width, height);
|
||||
if (os_android)
|
||||
os_android->set_display_size(Size2(width, height));
|
||||
|
||||
/*input_mutex->lock();
|
||||
resized=true;
|
||||
if (reload)
|
||||
resized_reload=true;
|
||||
new_size=Size2(width,height);
|
||||
input_mutex->unlock();*/
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jobject obj, bool p_32_bits) {
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "godot", "^_^_^_^_^ newcontext %lld\n", Thread::get_caller_id());
|
||||
|
||||
if (os_android) {
|
||||
os_android->set_context_is_16_bits(!p_32_bits);
|
||||
}
|
||||
|
||||
if (os_android && step > 0) {
|
||||
|
||||
os_android->reload_gfx();
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, jobject obj) {
|
||||
|
||||
input_mutex->lock();
|
||||
go_back_request = true;
|
||||
input_mutex->unlock();
|
||||
}
|
||||
|
||||
static void _initialize_java_modules() {
|
||||
@ -985,36 +902,106 @@ static void _initialize_java_modules() {
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jobject obj) {
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jobject obj, jobjectArray p_cmdline) {
|
||||
ThreadAndroid::setup_thread();
|
||||
|
||||
//__android_log_print(ANDROID_LOG_INFO,"godot","**STEP EVENT! - %p-%i\n",env,Thread::get_caller_id());
|
||||
__android_log_print(ANDROID_LOG_INFO, "godot", "**SETUP");
|
||||
|
||||
suspend_mutex->lock();
|
||||
input_mutex->lock();
|
||||
//first time step happens, initialize
|
||||
const char **cmdline = NULL;
|
||||
int cmdlen = 0;
|
||||
bool use_apk_expansion = false;
|
||||
if (p_cmdline) {
|
||||
cmdlen = env->GetArrayLength(p_cmdline);
|
||||
if (cmdlen) {
|
||||
cmdline = (const char **)malloc((env->GetArrayLength(p_cmdline) + 1) * sizeof(const char *));
|
||||
cmdline[cmdlen] = NULL;
|
||||
|
||||
for (int i = 0; i < cmdlen; i++) {
|
||||
|
||||
jstring string = (jstring)env->GetObjectArrayElement(p_cmdline, i);
|
||||
const char *rawString = env->GetStringUTFChars(string, 0);
|
||||
if (!rawString) {
|
||||
__android_log_print(ANDROID_LOG_INFO, "godot", "cmdline arg %i is null\n", i);
|
||||
} else {
|
||||
//__android_log_print(ANDROID_LOG_INFO,"godot","cmdline arg %i is: %s\n",i,rawString);
|
||||
|
||||
if (strcmp(rawString, "-main_pack") == 0)
|
||||
use_apk_expansion = true;
|
||||
}
|
||||
|
||||
cmdline[i] = rawString;
|
||||
}
|
||||
}
|
||||
}
|
||||
__android_log_print(ANDROID_LOG_INFO, "godot", "CMDLINE LEN %i - APK EXPANSION %i\n", cmdlen, int(use_apk_expansion));
|
||||
|
||||
#if 0
|
||||
char *args[]={"-test","render",NULL};
|
||||
__android_log_print(ANDROID_LOG_INFO,"godot","pre asdasd setup...");
|
||||
Error err = Main::setup("apk",2,args,false);
|
||||
#else
|
||||
Error err = Main::setup("apk", cmdlen, (char **)cmdline, false);
|
||||
#endif
|
||||
if (cmdline) {
|
||||
free(cmdline);
|
||||
}
|
||||
|
||||
if (err != OK) {
|
||||
__android_log_print(ANDROID_LOG_INFO, "godot", "*****UNABLE TO SETUP");
|
||||
return; //should exit instead and print the error
|
||||
}
|
||||
__android_log_print(ANDROID_LOG_INFO, "godot", "*****SETUP OK");
|
||||
|
||||
java_class_wrapper = memnew(JavaClassWrapper(_godot_instance));
|
||||
ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("JavaClassWrapper", java_class_wrapper));
|
||||
_initialize_java_modules();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jobject obj, jint width, jint height, jboolean reload) {
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "godot", "^_^_^_^_^ resize %lld, %i, %i\n", Thread::get_caller_id(), width, height);
|
||||
if (os_android)
|
||||
os_android->set_display_size(Size2(width, height));
|
||||
|
||||
/*input_mutex->lock();
|
||||
resized=true;
|
||||
if (reload)
|
||||
resized_reload=true;
|
||||
new_size=Size2(width,height);
|
||||
input_mutex->unlock();*/
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jobject obj, bool p_32_bits) {
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "godot", "^_^_^_^_^ newcontext %lld\n", Thread::get_caller_id());
|
||||
|
||||
if (os_android) {
|
||||
os_android->set_context_is_16_bits(!p_32_bits);
|
||||
}
|
||||
|
||||
if (os_android && step > 0) {
|
||||
|
||||
os_android->reload_gfx();
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, jobject obj) {
|
||||
go_back_request = true;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jobject obj) {
|
||||
if (step == 0) {
|
||||
// ugly hack to initialize the rest of the engine
|
||||
// because of the way android forces you to do everything with threads
|
||||
|
||||
java_class_wrapper = memnew(JavaClassWrapper(_godot_instance));
|
||||
ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("JavaClassWrapper", java_class_wrapper));
|
||||
_initialize_java_modules();
|
||||
__android_log_print(ANDROID_LOG_INFO, "godot", "**FIRST_STEP");
|
||||
|
||||
// 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());
|
||||
++step;
|
||||
suspend_mutex->unlock();
|
||||
input_mutex->unlock();
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
if (step == 1) {
|
||||
if (!Main::start()) {
|
||||
|
||||
input_mutex->unlock();
|
||||
suspend_mutex->lock();
|
||||
return; //should exit instead and print the error
|
||||
}
|
||||
|
||||
@ -1022,6 +1009,8 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, job
|
||||
++step;
|
||||
}
|
||||
|
||||
//__android_log_print(ANDROID_LOG_INFO,"godot","**STEP EVENT! - %p-%i\n",env,Thread::get_caller_id());
|
||||
|
||||
while (pointer_events.size()) {
|
||||
|
||||
JAndroidPointerEvent jpe = pointer_events.front()->get();
|
||||
@ -1052,8 +1041,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, job
|
||||
go_back_request = false;
|
||||
}
|
||||
|
||||
input_mutex->unlock();
|
||||
|
||||
os_android->process_accelerometer(accelerometer);
|
||||
|
||||
os_android->process_magnetometer(magnetometer);
|
||||
@ -1067,8 +1054,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, job
|
||||
env->CallVoidMethod(_godot_instance, _finish);
|
||||
__android_log_print(ANDROID_LOG_INFO, "godot", "**FINISH REQUEST!!! - %p-%i\n", env, Thread::get_caller_id());
|
||||
}
|
||||
|
||||
suspend_mutex->unlock();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch(JNIEnv *env, jobject obj, jint ev, jint pointer, jint count, jintArray positions) {
|
||||
@ -1091,11 +1076,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch(JNIEnv *env, jo
|
||||
jpe.points = points;
|
||||
jpe.what = ev;
|
||||
|
||||
input_mutex->lock();
|
||||
|
||||
pointer_events.push_back(jpe);
|
||||
|
||||
input_mutex->unlock();
|
||||
/*
|
||||
if (os_android)
|
||||
os_android->process_touch(ev,pointer,points);
|
||||
@ -1365,9 +1346,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env
|
||||
jevent.index = p_button;
|
||||
jevent.pressed = p_pressed;
|
||||
|
||||
input_mutex->lock();
|
||||
joy_events.push_back(jevent);
|
||||
input_mutex->unlock();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env, jobject obj, jint p_device, jint p_axis, jfloat p_value) {
|
||||
@ -1378,9 +1357,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env,
|
||||
jevent.index = p_axis;
|
||||
jevent.value = p_value;
|
||||
|
||||
input_mutex->lock();
|
||||
joy_events.push_back(jevent);
|
||||
input_mutex->unlock();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, jobject obj, jint p_device, jint p_hat_x, jint p_hat_y) {
|
||||
@ -1401,9 +1378,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, j
|
||||
hat |= InputDefault::HAT_MASK_DOWN;
|
||||
}
|
||||
jevent.hat = hat;
|
||||
input_mutex->lock();
|
||||
joy_events.push_back(jevent);
|
||||
input_mutex->unlock();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged(JNIEnv *env, jobject obj, jint p_device, jboolean p_connected, jstring p_name) {
|
||||
@ -1437,54 +1412,31 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jobj
|
||||
go_back_request = true;
|
||||
}
|
||||
|
||||
input_mutex->lock();
|
||||
key_events.push_back(ievent);
|
||||
input_mutex->unlock();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_accelerometer(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z) {
|
||||
|
||||
input_mutex->lock();
|
||||
accelerometer = Vector3(x, y, z);
|
||||
input_mutex->unlock();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_magnetometer(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z) {
|
||||
|
||||
input_mutex->lock();
|
||||
magnetometer = Vector3(x, y, z);
|
||||
input_mutex->unlock();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_gyroscope(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z) {
|
||||
|
||||
input_mutex->lock();
|
||||
gyroscope = Vector3(x, y, z);
|
||||
input_mutex->unlock();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusin(JNIEnv *env, jobject obj) {
|
||||
|
||||
if (!suspend_mutex)
|
||||
return;
|
||||
suspend_mutex->lock();
|
||||
|
||||
if (os_android && step > 0)
|
||||
os_android->main_loop_focusin();
|
||||
|
||||
suspend_mutex->unlock();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusout(JNIEnv *env, jobject obj) {
|
||||
|
||||
if (!suspend_mutex)
|
||||
return;
|
||||
suspend_mutex->lock();
|
||||
|
||||
if (os_android && step > 0)
|
||||
os_android->main_loop_focusout();
|
||||
|
||||
suspend_mutex->unlock();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_audio(JNIEnv *env, jobject obj) {
|
||||
|
@ -36,7 +36,8 @@
|
||||
#include <jni.h>
|
||||
|
||||
extern "C" {
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jobject obj, jobject activity, jboolean p_need_reload_hook, jobjectArray p_cmdline, jobject p_asset_manager);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jobject obj, jobject activity, jboolean p_need_reload_hook, jobject p_asset_manager, jboolean p_use_apk_expansion);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jobject obj, jobjectArray p_cmdline);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jobject obj, jint width, jint height, jboolean reload);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jobject obj, bool p_32_bits);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jobject obj);
|
||||
|
Loading…
Reference in New Issue
Block a user