diff options
Diffstat (limited to 'platform/android')
47 files changed, 457 insertions, 834 deletions
diff --git a/platform/android/SCsub b/platform/android/SCsub index 7e9dac926c..56fbd2f7e4 100644 --- a/platform/android/SCsub +++ b/platform/android/SCsub @@ -9,7 +9,6 @@ android_files = [ "dir_access_jandroid.cpp", "thread_jandroid.cpp", "net_socket_android.cpp", - "audio_driver_jandroid.cpp", "java_godot_lib_jni.cpp", "java_class_wrapper.cpp", "java_godot_wrapper.cpp", diff --git a/platform/android/api/java_class_wrapper.h b/platform/android/api/java_class_wrapper.h index d6c7a1abe5..ff7bf43573 100644 --- a/platform/android/api/java_class_wrapper.h +++ b/platform/android/api/java_class_wrapper.h @@ -31,7 +31,7 @@ #ifndef JAVA_CLASS_WRAPPER_H #define JAVA_CLASS_WRAPPER_H -#include "core/object/reference.h" +#include "core/object/ref_counted.h" #ifdef ANDROID_ENABLED #include <android/log.h> @@ -42,8 +42,8 @@ class JavaObject; #endif -class JavaClass : public Reference { - GDCLASS(JavaClass, Reference); +class JavaClass : public RefCounted { + GDCLASS(JavaClass, RefCounted); #ifdef ANDROID_ENABLED enum ArgumentType{ @@ -184,8 +184,8 @@ public: JavaClass(); }; -class JavaObject : public Reference { - GDCLASS(JavaObject, Reference); +class JavaObject : public RefCounted { + GDCLASS(JavaObject, RefCounted); #ifdef ANDROID_ENABLED Ref<JavaClass> base_class; diff --git a/platform/android/audio_driver_jandroid.cpp b/platform/android/audio_driver_jandroid.cpp deleted file mode 100644 index 3a2ccac481..0000000000 --- a/platform/android/audio_driver_jandroid.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/*************************************************************************/ -/* audio_driver_jandroid.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#include "audio_driver_jandroid.h" - -#include "core/config/project_settings.h" -#include "core/os/os.h" -#include "thread_jandroid.h" - -AudioDriverAndroid *AudioDriverAndroid::s_ad = nullptr; - -jobject AudioDriverAndroid::io; -jmethodID AudioDriverAndroid::_init_audio; -jmethodID AudioDriverAndroid::_write_buffer; -jmethodID AudioDriverAndroid::_quit; -jmethodID AudioDriverAndroid::_pause; -bool AudioDriverAndroid::active = false; -jclass AudioDriverAndroid::cls; -int AudioDriverAndroid::audioBufferFrames = 0; -int AudioDriverAndroid::mix_rate = 44100; -bool AudioDriverAndroid::quit = false; -jobject AudioDriverAndroid::audioBuffer = nullptr; -void *AudioDriverAndroid::audioBufferPinned = nullptr; -Mutex AudioDriverAndroid::mutex; -int32_t *AudioDriverAndroid::audioBuffer32 = nullptr; - -const char *AudioDriverAndroid::get_name() const { - return "Android"; -} - -Error AudioDriverAndroid::init() { - /* - // TODO: pass in/return a (Java) device ID, also whether we're opening for input or output - this->spec.samples = Android_JNI_OpenAudioDevice(this->spec.freq, this->spec.format == AUDIO_U8 ? 0 : 1, this->spec.channels, this->spec.samples); - SDL_CalculateAudioSpec(&this->spec); - - if (this->spec.samples == 0) { - // Init failed? - SDL_SetError("Java-side initialization failed!"); - return 0; - } -*/ - - //Android_JNI_SetupThread(); - - // __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device"); - - JNIEnv *env = get_jni_env(); - int mix_rate = GLOBAL_GET("audio/driver/mix_rate"); - - int latency = GLOBAL_GET("audio/driver/output_latency"); - unsigned int buffer_size = next_power_of_2(latency * mix_rate / 1000); - print_verbose("Audio buffer size: " + itos(buffer_size)); - - audioBuffer = env->CallObjectMethod(io, _init_audio, mix_rate, buffer_size); - - ERR_FAIL_COND_V(audioBuffer == nullptr, ERR_INVALID_PARAMETER); - - audioBuffer = env->NewGlobalRef(audioBuffer); - - jboolean isCopy = JNI_FALSE; - audioBufferPinned = env->GetShortArrayElements((jshortArray)audioBuffer, &isCopy); - audioBufferFrames = env->GetArrayLength((jshortArray)audioBuffer); - audioBuffer32 = memnew_arr(int32_t, audioBufferFrames); - - return OK; -} - -void AudioDriverAndroid::start() { - active = true; -} - -void AudioDriverAndroid::setup(jobject p_io) { - JNIEnv *env = get_jni_env(); - io = p_io; - - jclass c = env->GetObjectClass(io); - cls = (jclass)env->NewGlobalRef(c); - - _init_audio = env->GetMethodID(cls, "audioInit", "(II)Ljava/lang/Object;"); - _write_buffer = env->GetMethodID(cls, "audioWriteShortBuffer", "([S)V"); - _quit = env->GetMethodID(cls, "audioQuit", "()V"); - _pause = env->GetMethodID(cls, "audioPause", "(Z)V"); -} - -void AudioDriverAndroid::thread_func(JNIEnv *env) { - jclass cls = env->FindClass("org/godotengine/godot/Godot"); - if (cls) { - cls = (jclass)env->NewGlobalRef(cls); - } - jfieldID fid = env->GetStaticFieldID(cls, "io", "Lorg/godotengine/godot/GodotIO;"); - jobject ob = env->GetStaticObjectField(cls, fid); - jobject gob = env->NewGlobalRef(ob); - jclass c = env->GetObjectClass(gob); - jclass lcls = (jclass)env->NewGlobalRef(c); - _write_buffer = env->GetMethodID(lcls, "audioWriteShortBuffer", "([S)V"); - - while (!quit) { - int16_t *ptr = (int16_t *)audioBufferPinned; - int fc = audioBufferFrames; - - if (!s_ad->active || mutex.try_lock() != OK) { - for (int i = 0; i < fc; i++) { - ptr[i] = 0; - } - - } else { - s_ad->audio_server_process(fc / 2, audioBuffer32); - - mutex.unlock(); - - for (int i = 0; i < fc; i++) { - ptr[i] = audioBuffer32[i] >> 16; - } - } - env->ReleaseShortArrayElements((jshortArray)audioBuffer, (jshort *)ptr, JNI_COMMIT); - env->CallVoidMethod(gob, _write_buffer, (jshortArray)audioBuffer); - } -} - -int AudioDriverAndroid::get_mix_rate() const { - return mix_rate; -} - -AudioDriver::SpeakerMode AudioDriverAndroid::get_speaker_mode() const { - return SPEAKER_MODE_STEREO; -} - -void AudioDriverAndroid::lock() { - mutex.lock(); -} - -void AudioDriverAndroid::unlock() { - mutex.unlock(); -} - -void AudioDriverAndroid::finish() { - JNIEnv *env = get_jni_env(); - env->CallVoidMethod(io, _quit); - - if (audioBuffer) { - env->DeleteGlobalRef(audioBuffer); - audioBuffer = nullptr; - audioBufferPinned = nullptr; - } - - active = false; -} - -void AudioDriverAndroid::set_pause(bool p_pause) { - JNIEnv *env = get_jni_env(); - env->CallVoidMethod(io, _pause, p_pause); -} - -AudioDriverAndroid::AudioDriverAndroid() { - s_ad = this; - active = false; -} diff --git a/platform/android/audio_driver_jandroid.h b/platform/android/audio_driver_jandroid.h deleted file mode 100644 index 9007fd2f81..0000000000 --- a/platform/android/audio_driver_jandroid.h +++ /dev/null @@ -1,78 +0,0 @@ -/*************************************************************************/ -/* audio_driver_jandroid.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#ifndef AUDIO_DRIVER_ANDROID_H -#define AUDIO_DRIVER_ANDROID_H - -#include "servers/audio_server.h" - -#include "java_godot_lib_jni.h" - -class AudioDriverAndroid : public AudioDriver { - static Mutex mutex; - static AudioDriverAndroid *s_ad; - static jobject io; - static jmethodID _init_audio; - static jmethodID _write_buffer; - static jmethodID _quit; - static jmethodID _pause; - static bool active; - static bool quit; - - static jclass cls; - - static jobject audioBuffer; - static void *audioBufferPinned; - static int32_t *audioBuffer32; - static int audioBufferFrames; - static int mix_rate; - -public: - void set_singleton(); - - virtual const char *get_name() const; - - virtual Error init(); - virtual void start(); - virtual int get_mix_rate() const; - virtual SpeakerMode get_speaker_mode() const; - virtual void lock(); - virtual void unlock(); - virtual void finish(); - - virtual void set_pause(bool p_pause); - - static void setup(jobject p_io); - static void thread_func(JNIEnv *env); - - AudioDriverAndroid(); -}; - -#endif // AUDIO_DRIVER_ANDROID_H diff --git a/platform/android/dir_access_jandroid.h b/platform/android/dir_access_jandroid.h index 7b9cbeea47..cdf98187ed 100644 --- a/platform/android/dir_access_jandroid.h +++ b/platform/android/dir_access_jandroid.h @@ -31,7 +31,7 @@ #ifndef DIR_ACCESS_JANDROID_H #define DIR_ACCESS_JANDROID_H -#include "core/os/dir_access.h" +#include "core/io/dir_access.h" #include "java_godot_lib_jni.h" #include <stdio.h> diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp index ff61eeaee1..1fcc3d4a5c 100644 --- a/platform/android/display_server_android.cpp +++ b/platform/android/display_server_android.cpp @@ -358,8 +358,8 @@ Vector<String> DisplayServerAndroid::get_rendering_drivers_func() { return drivers; } -DisplayServer *DisplayServerAndroid::create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { - DisplayServer *ds = memnew(DisplayServerAndroid(p_rendering_driver, p_mode, p_flags, p_resolution, r_error)); +DisplayServer *DisplayServerAndroid::create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { + DisplayServer *ds = memnew(DisplayServerAndroid(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error)); if (r_error != OK) { ds->alert("Your video card driver does not support any of the supported Vulkan versions.", "Unable to initialize Video driver"); } @@ -377,10 +377,11 @@ void DisplayServerAndroid::reset_window() { ERR_FAIL_COND(!native_window); ERR_FAIL_COND(!context_vulkan); + VSyncMode last_vsync_mode = context_vulkan->get_vsync_mode(MAIN_WINDOW_ID); context_vulkan->window_destroy(MAIN_WINDOW_ID); Size2i display_size = OS_Android::get_singleton()->get_display_size(); - if (context_vulkan->window_create(native_window, display_size.width, display_size.height) == -1) { + if (context_vulkan->window_create(native_window, last_vsync_mode, display_size.width, display_size.height) == -1) { memdelete(context_vulkan); context_vulkan = nullptr; ERR_FAIL_MSG("Failed to reset Vulkan window."); @@ -402,7 +403,7 @@ void DisplayServerAndroid::notify_surface_changed(int p_width, int p_height) { rect_changed_callback.call(reinterpret_cast<const Variant **>(&sizep), 1, ret, ce); } -DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { +DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { rendering_driver = p_rendering_driver; // TODO: rendering_driver is broken, change when different drivers are supported again @@ -410,8 +411,6 @@ DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, Dis keep_screen_on = GLOBAL_GET("display/window/energy_saving/keep_screen_on"); - buttons_state = 0; - #if defined(OPENGL_ENABLED) if (rendering_driver == "opengl") { bool gl_initialization_error = false; @@ -448,7 +447,7 @@ DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, Dis } Size2i display_size = OS_Android::get_singleton()->get_display_size(); - if (context_vulkan->window_create(native_window, display_size.width, display_size.height) == -1) { + if (context_vulkan->window_create(native_window, p_vsync_mode, display_size.width, display_size.height) == -1) { memdelete(context_vulkan); context_vulkan = nullptr; ERR_FAIL_MSG("Failed to create Vulkan window."); @@ -484,16 +483,16 @@ DisplayServerAndroid::~DisplayServerAndroid() { void DisplayServerAndroid::process_joy_event(DisplayServerAndroid::JoypadEvent p_event) { switch (p_event.type) { case JOY_EVENT_BUTTON: - Input::get_singleton()->joy_button(p_event.device, p_event.index, p_event.pressed); + Input::get_singleton()->joy_button(p_event.device, (JoyButton)p_event.index, p_event.pressed); break; case JOY_EVENT_AXIS: Input::JoyAxisValue value; value.min = -1; value.value = p_event.value; - Input::get_singleton()->joy_axis(p_event.device, p_event.index, value); + Input::get_singleton()->joy_axis(p_event.device, (JoyAxis)p_event.index, value); break; case JOY_EVENT_HAT: - Input::get_singleton()->joy_hat(p_event.device, p_event.hat); + Input::get_singleton()->joy_hat(p_event.device, (HatMask)p_event.hat); break; default: return; @@ -528,7 +527,7 @@ void DisplayServerAndroid::process_key_event(int p_keycode, int p_scancode, int } Ref<InputEventKey> ev; - ev.instance(); + ev.instantiate(); int val = unicode; int keycode = android_get_keysym(p_keycode); int phy_keycode = android_get_keysym(p_scancode); @@ -575,7 +574,7 @@ void DisplayServerAndroid::process_touch(int p_event, int p_pointer, const Vecto //end all if exist for (int i = 0; i < touch.size(); i++) { Ref<InputEventScreenTouch> ev; - ev.instance(); + ev.instantiate(); ev->set_index(touch[i].id); ev->set_pressed(false); ev->set_position(touch[i].pos); @@ -592,7 +591,7 @@ void DisplayServerAndroid::process_touch(int p_event, int p_pointer, const Vecto //send touch for (int i = 0; i < touch.size(); i++) { Ref<InputEventScreenTouch> ev; - ev.instance(); + ev.instantiate(); ev->set_index(touch[i].id); ev->set_pressed(true); ev->set_position(touch[i].pos); @@ -618,7 +617,7 @@ void DisplayServerAndroid::process_touch(int p_event, int p_pointer, const Vecto continue; //no move unncesearily Ref<InputEventScreenDrag> ev; - ev.instance(); + ev.instantiate(); ev->set_index(touch[i].id); ev->set_position(p_points[idx].pos); ev->set_relative(p_points[idx].pos - touch[i].pos); @@ -633,7 +632,7 @@ void DisplayServerAndroid::process_touch(int p_event, int p_pointer, const Vecto //end all if exist for (int i = 0; i < touch.size(); i++) { Ref<InputEventScreenTouch> ev; - ev.instance(); + ev.instantiate(); ev->set_index(touch[i].id); ev->set_pressed(false); ev->set_position(touch[i].pos); @@ -649,7 +648,7 @@ void DisplayServerAndroid::process_touch(int p_event, int p_pointer, const Vecto touch.push_back(tp); Ref<InputEventScreenTouch> ev; - ev.instance(); + ev.instantiate(); ev->set_index(tp.id); ev->set_pressed(true); @@ -664,7 +663,7 @@ void DisplayServerAndroid::process_touch(int p_event, int p_pointer, const Vecto for (int i = 0; i < touch.size(); i++) { if (touch[i].id == p_pointer) { Ref<InputEventScreenTouch> ev; - ev.instance(); + ev.instantiate(); ev->set_index(touch[i].id); ev->set_pressed(false); ev->set_position(touch[i].pos); @@ -685,7 +684,7 @@ void DisplayServerAndroid::process_hover(int p_type, Point2 p_pos) { case AMOTION_EVENT_ACTION_HOVER_ENTER: // hover enter case AMOTION_EVENT_ACTION_HOVER_EXIT: { // hover exit Ref<InputEventMouseMotion> ev; - ev.instance(); + ev.instantiate(); _set_key_modifier_state(ev); ev->set_position(p_pos); ev->set_global_position(p_pos); @@ -697,12 +696,12 @@ void DisplayServerAndroid::process_hover(int p_type, Point2 p_pos) { } void DisplayServerAndroid::process_mouse_event(int input_device, int event_action, int event_android_buttons_mask, Point2 event_pos, float event_vertical_factor, float event_horizontal_factor) { - int event_buttons_mask = _android_button_mask_to_godot_button_mask(event_android_buttons_mask); + MouseButton event_buttons_mask = _android_button_mask_to_godot_button_mask(event_android_buttons_mask); switch (event_action) { case AMOTION_EVENT_ACTION_BUTTON_PRESS: case AMOTION_EVENT_ACTION_BUTTON_RELEASE: { Ref<InputEventMouseButton> ev; - ev.instance(); + ev.instantiate(); _set_key_modifier_state(ev); if ((input_device & AINPUT_SOURCE_MOUSE) == AINPUT_SOURCE_MOUSE) { ev->set_position(event_pos); @@ -712,7 +711,7 @@ void DisplayServerAndroid::process_mouse_event(int input_device, int event_actio ev->set_global_position(hover_prev_pos); } ev->set_pressed(event_action == AMOTION_EVENT_ACTION_BUTTON_PRESS); - int changed_button_mask = buttons_state ^ event_buttons_mask; + MouseButton changed_button_mask = MouseButton(buttons_state ^ event_buttons_mask); buttons_state = event_buttons_mask; @@ -723,7 +722,7 @@ void DisplayServerAndroid::process_mouse_event(int input_device, int event_actio case AMOTION_EVENT_ACTION_MOVE: { Ref<InputEventMouseMotion> ev; - ev.instance(); + ev.instantiate(); _set_key_modifier_state(ev); if ((input_device & AINPUT_SOURCE_MOUSE) == AINPUT_SOURCE_MOUSE) { ev->set_position(event_pos); @@ -740,7 +739,7 @@ void DisplayServerAndroid::process_mouse_event(int input_device, int event_actio } break; case AMOTION_EVENT_ACTION_SCROLL: { Ref<InputEventMouseButton> ev; - ev.instance(); + ev.instantiate(); if ((input_device & AINPUT_SOURCE_MOUSE) == AINPUT_SOURCE_MOUSE) { ev->set_position(event_pos); ev->set_global_position(event_pos); @@ -765,11 +764,11 @@ void DisplayServerAndroid::process_mouse_event(int input_device, int event_actio } } -void DisplayServerAndroid::_wheel_button_click(int event_buttons_mask, const Ref<InputEventMouseButton> &ev, int wheel_button, float factor) { +void DisplayServerAndroid::_wheel_button_click(MouseButton event_buttons_mask, const Ref<InputEventMouseButton> &ev, MouseButton wheel_button, float factor) { Ref<InputEventMouseButton> evd = ev->duplicate(); _set_key_modifier_state(evd); evd->set_button_index(wheel_button); - evd->set_button_mask(event_buttons_mask ^ (1 << (wheel_button - 1))); + evd->set_button_mask(MouseButton(event_buttons_mask ^ (1 << (wheel_button - 1)))); evd->set_factor(factor); Input::get_singleton()->accumulate_input_event(evd); Ref<InputEventMouseButton> evdd = evd->duplicate(); @@ -779,9 +778,9 @@ void DisplayServerAndroid::_wheel_button_click(int event_buttons_mask, const Ref } void DisplayServerAndroid::process_double_tap(int event_android_button_mask, Point2 p_pos) { - int event_button_mask = _android_button_mask_to_godot_button_mask(event_android_button_mask); + MouseButton event_button_mask = _android_button_mask_to_godot_button_mask(event_android_button_mask); Ref<InputEventMouseButton> ev; - ev.instance(); + ev.instantiate(); _set_key_modifier_state(ev); ev->set_position(p_pos); ev->set_global_position(p_pos); @@ -792,7 +791,7 @@ void DisplayServerAndroid::process_double_tap(int event_android_button_mask, Poi Input::get_singleton()->accumulate_input_event(ev); } -int DisplayServerAndroid::_button_index_from_mask(int button_mask) { +MouseButton DisplayServerAndroid::_button_index_from_mask(MouseButton button_mask) { switch (button_mask) { case MOUSE_BUTTON_MASK_LEFT: return MOUSE_BUTTON_LEFT; @@ -805,13 +804,13 @@ int DisplayServerAndroid::_button_index_from_mask(int button_mask) { case MOUSE_BUTTON_MASK_XBUTTON2: return MOUSE_BUTTON_XBUTTON2; default: - return 0; + return MOUSE_BUTTON_NONE; } } void DisplayServerAndroid::process_scroll(Point2 p_pos) { Ref<InputEventPanGesture> ev; - ev.instance(); + ev.instantiate(); _set_key_modifier_state(ev); ev->set_position(p_pos); ev->set_delta(p_pos - scroll_prev_pos); @@ -863,12 +862,12 @@ Point2i DisplayServerAndroid::mouse_get_position() const { return hover_prev_pos; } -int DisplayServerAndroid::mouse_get_button_state() const { +MouseButton DisplayServerAndroid::mouse_get_button_state() const { return buttons_state; } -int DisplayServerAndroid::_android_button_mask_to_godot_button_mask(int android_button_mask) { - int godot_button_mask = 0; +MouseButton DisplayServerAndroid::_android_button_mask_to_godot_button_mask(int android_button_mask) { + MouseButton godot_button_mask = MOUSE_BUTTON_NONE; if (android_button_mask & AMOTION_EVENT_BUTTON_PRIMARY) { godot_button_mask |= MOUSE_BUTTON_MASK_LEFT; } @@ -903,3 +902,17 @@ void DisplayServerAndroid::cursor_set_shape(DisplayServer::CursorShape p_shape) DisplayServer::CursorShape DisplayServerAndroid::cursor_get_shape() const { return cursor_shape; } + +void DisplayServerAndroid::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) { +#if defined(VULKAN_ENABLED) + context_vulkan->set_vsync_mode(p_window, p_vsync_mode); +#endif +} + +DisplayServer::VSyncMode DisplayServerAndroid::window_get_vsync_mode(WindowID p_window) const { +#if defined(VULKAN_ENABLED) + return context_vulkan->get_vsync_mode(p_window); +#else + return DisplayServer::VSYNC_ENABLED; +#endif +} diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h index 1379baf154..bd5bed31cd 100644 --- a/platform/android/display_server_android.h +++ b/platform/android/display_server_android.h @@ -68,7 +68,7 @@ private: bool control_mem = false; bool meta_mem = false; - int buttons_state; + MouseButton buttons_state = MOUSE_BUTTON_NONE; // https://developer.android.com/reference/android/view/PointerIcon // mapping between Godot's cursor shape to Android's' @@ -81,7 +81,7 @@ private: 1004, //CURSOR_BUSY 1021, //CURSOR_DRAG 1021, //CURSOR_CAN_DRO - 1000, //CURSOR_FORBIDD (no corresponding icon in Android's icon so fallback to default) + 1000, //CURSOR_FORBIDD (no corresponding icon in Android's icon so fallback to default) 1015, //CURSOR_VSIZE 1014, //CURSOR_HSIZE 1017, //CURSOR_BDIAGSI @@ -92,7 +92,7 @@ private: 1003, //CURSOR_HELP }; const int CURSOR_TYPE_NULL = 0; - MouseMode mouse_mode; + MouseMode mouse_mode = MouseMode::MOUSE_MODE_VISIBLE; bool keep_screen_on; @@ -120,11 +120,11 @@ private: void _set_key_modifier_state(Ref<InputEventWithModifiers> ev); - static int _button_index_from_mask(int button_mask); + static MouseButton _button_index_from_mask(MouseButton button_mask); - static int _android_button_mask_to_godot_button_mask(int android_button_mask); + static MouseButton _android_button_mask_to_godot_button_mask(int android_button_mask); - void _wheel_button_click(int event_buttons_mask, const Ref<InputEventMouseButton> &ev, int wheel_button, float factor); + void _wheel_button_click(MouseButton event_buttons_mask, const Ref<InputEventMouseButton> &ev, MouseButton wheel_button, float factor); public: static DisplayServerAndroid *get_singleton(); @@ -188,6 +188,8 @@ public: virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID); virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const; virtual bool can_any_window_draw() const; + virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID); + virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const; virtual void alert(const String &p_alert, const String &p_title); @@ -211,7 +213,7 @@ public: void mouse_set_mode(MouseMode p_mode); MouseMode mouse_get_mode() const; - static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); + static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); static Vector<String> get_rendering_drivers_func(); static void register_android_driver(); @@ -219,9 +221,9 @@ public: void notify_surface_changed(int p_width, int p_height); virtual Point2i mouse_get_position() const; - virtual int mouse_get_button_state() const; + virtual MouseButton mouse_get_button_state() const; - DisplayServerAndroid(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); + DisplayServerAndroid(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); ~DisplayServerAndroid(); }; diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index c45828e194..6661698d3e 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -31,11 +31,12 @@ #include "export.h" #include "core/config/project_settings.h" +#include "core/io/dir_access.h" +#include "core/io/file_access.h" #include "core/io/image_loader.h" +#include "core/io/json.h" #include "core/io/marshalls.h" #include "core/io/zip_io.h" -#include "core/os/dir_access.h" -#include "core/os/file_access.h" #include "core/os/os.h" #include "core/templates/safe_refcount.h" #include "core/version.h" @@ -206,6 +207,7 @@ static const char *LEGACY_BUILD_SPLASH_IMAGE_EXPORT_PATH = "res/drawable-nodpi-v static const char *SPLASH_BG_COLOR_PATH = "res/drawable-nodpi/splash_bg_color.png"; static const char *LEGACY_BUILD_SPLASH_BG_COLOR_PATH = "res/drawable-nodpi-v4/splash_bg_color.png"; static const char *SPLASH_CONFIG_PATH = "res://android/build/res/drawable/splash_drawable.xml"; +static const char *GDNATIVE_LIBS_PATH = "res://android/build/libs/gdnativelibs.json"; const String SPLASH_CONFIG_XML_CONTENT = R"SPLASH(<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> @@ -277,6 +279,11 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { EditorProgress *ep = nullptr; }; + struct CustomExportData { + bool debug; + Vector<String> libs; + }; + Vector<PluginConfigAndroid> plugins; String last_plugin_names; uint64_t last_custom_build_time = 0; @@ -609,9 +616,9 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { zip_fileinfo zipfi; zipfi.tmz_date.tm_hour = time.hour; zipfi.tmz_date.tm_mday = date.day; - zipfi.tmz_date.tm_min = time.min; + zipfi.tmz_date.tm_min = time.minute; zipfi.tmz_date.tm_mon = date.month - 1; // tm_mon is zero indexed - zipfi.tmz_date.tm_sec = time.sec; + zipfi.tmz_date.tm_sec = time.second; zipfi.tmz_date.tm_year = date.year; zipfi.dosDate = 0; zipfi.external_fa = 0; @@ -757,6 +764,33 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { return OK; } + static Error copy_gradle_so(void *p_userdata, const SharedObject &p_so) { + ERR_FAIL_COND_V_MSG(!p_so.path.get_file().begins_with("lib"), FAILED, + "Android .so file names must start with \"lib\", but got: " + p_so.path); + Vector<String> abis = get_abis(); + CustomExportData *export_data = (CustomExportData *)p_userdata; + bool exported = false; + for (int i = 0; i < p_so.tags.size(); ++i) { + int abi_index = abis.find(p_so.tags[i]); + if (abi_index != -1) { + exported = true; + String base = "res://android/build/libs"; + String type = export_data->debug ? "debug" : "release"; + String abi = abis[abi_index]; + String filename = p_so.path.get_file(); + String dst_path = base.plus_file(type).plus_file(abi).plus_file(filename); + Vector<uint8_t> data = FileAccess::get_file_as_array(p_so.path); + print_verbose("Copying .so file from " + p_so.path + " to " + dst_path); + Error err = store_file_at_path(dst_path, data); + ERR_FAIL_COND_V_MSG(err, err, "Failed to copy .so file from " + p_so.path + " to " + dst_path); + export_data->libs.push_back(dst_path); + } + } + ERR_FAIL_COND_V_MSG(!exported, FAILED, + "Cannot determine ABI for library \"" + p_so.path + "\". One of the supported ABIs must be used as a tag: " + String(" ").join(abis)); + return OK; + } + void _get_permissions(const Ref<EditorExportPreset> &p_preset, bool p_give_internet, Vector<String> &r_permissions) { const char **aperms = android_perms; while (*aperms) { @@ -858,6 +892,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { int xr_mode_index = p_preset->get("xr_features/xr_mode"); bool backup_allowed = p_preset->get("user_data_backup/allow"); + bool classify_as_game = p_preset->get("package/classify_as_game"); Vector<String> perms; // Write permissions into the perms variable. @@ -955,6 +990,10 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { encode_uint32(backup_allowed, &p_manifest.write[iofs + 16]); } + if (tname == "application" && attrname == "isGame") { + encode_uint32(classify_as_game, &p_manifest.write[iofs + 16]); + } + if (tname == "instrumentation" && attrname == "targetPackage") { string_table.write[attr_value] = get_package_name(package_name); } @@ -1461,7 +1500,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { String project_splash_path = ProjectSettings::get_singleton()->get("application/boot_splash/image"); if (!project_splash_path.is_empty()) { - splash_image.instance(); + splash_image.instantiate(); print_verbose("Loading splash image: " + project_splash_path); const Error err = ImageLoader::load_image(project_splash_path, splash_image); if (err) { @@ -1501,7 +1540,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { } print_verbose("Creating splash background color image."); - splash_bg_color_image.instance(); + splash_bg_color_image.instantiate(); splash_bg_color_image->create(splash_image->get_width(), splash_image->get_height(), false, splash_image->get_format()); splash_bg_color_image->fill(bg_color); @@ -1512,9 +1551,9 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { void load_icon_refs(const Ref<EditorExportPreset> &p_preset, Ref<Image> &icon, Ref<Image> &foreground, Ref<Image> &background) { String project_icon_path = ProjectSettings::get_singleton()->get("application/config/icon"); - icon.instance(); - foreground.instance(); - background.instance(); + icon.instantiate(); + foreground.instantiate(); + background.instantiate(); // Regular icon: user selection -> project icon -> default. String path = static_cast<String>(p_preset->get(launcher_icon_option)).strip_edges(); @@ -1673,6 +1712,7 @@ public: r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/unique_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "ext.domain.name"), "org.godotengine.$genname")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name [default if blank]"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "package/signed"), true)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "package/classify_as_game"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_icon_option, PROPERTY_HINT_FILE, "*.png"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_adaptive_icon_foreground_option, PROPERTY_HINT_FILE, "*.png"), "")); @@ -1849,7 +1889,7 @@ public: err = OS::get_singleton()->execute(adb, args, &output, &rv, true); print_verbose(output); if (err || rv != 0) { - EditorNode::add_io_error("Could not install to device."); + EditorNode::add_io_error("Could not install to device: " + output); CLEANUP_AND_RETURN(ERR_CANT_CREATE); } @@ -2380,6 +2420,28 @@ public: } } + void _remove_copied_libs() { + print_verbose("Removing previously installed libraries..."); + Error error; + String libs_json = FileAccess::get_file_as_string(GDNATIVE_LIBS_PATH, &error); + if (error || libs_json.is_empty()) { + print_verbose("No previously installed libraries found"); + return; + } + + JSON json; + error = json.parse(libs_json); + ERR_FAIL_COND_MSG(error, "Error parsing \"" + libs_json + "\" on line " + itos(json.get_error_line()) + ": " + json.get_error_message()); + + Vector<String> libs = json.get_data(); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + for (int i = 0; i < libs.size(); i++) { + print_verbose("Removing previously installed library " + libs[i]); + da->remove(libs[i]); + } + da->remove(GDNATIVE_LIBS_PATH); + } + String join_list(List<String> parts, const String &separator) const { String ret; for (int i = 0; i < parts.size(); ++i) { @@ -2491,13 +2553,22 @@ public: //stores all the project files inside the Gradle project directory. Also includes all ABIs _clear_assets_directory(); + _remove_copied_libs(); if (!apk_expansion) { print_verbose("Exporting project files.."); - err = export_project_files(p_preset, rename_and_store_file_in_gradle_project, nullptr, ignore_so_file); + CustomExportData user_data; + user_data.debug = p_debug; + err = export_project_files(p_preset, rename_and_store_file_in_gradle_project, &user_data, copy_gradle_so); if (err != OK) { EditorNode::add_io_error("Could not export project files to gradle project\n"); return err; } + if (user_data.libs.size() > 0) { + FileAccessRef fa = FileAccess::open(GDNATIVE_LIBS_PATH, FileAccess::WRITE); + JSON json; + fa->store_string(json.stringify(user_data.libs, "\t")); + fa->close(); + } } else { print_verbose("Saving apk expansion file.."); err = save_apk_expansion_file(p_preset, p_path); @@ -2568,19 +2639,35 @@ public: // Sensitive additions must be done below the logging statement. print_verbose("Build Android project using gradle command: " + String("\n") + build_command + " " + join_list(cmdline, String(" "))); - if (should_sign && !p_debug) { - // Pass the release keystore info as well - String release_keystore = p_preset->get("keystore/release"); - String release_username = p_preset->get("keystore/release_user"); - String release_password = p_preset->get("keystore/release_password"); - if (!FileAccess::exists(release_keystore)) { - EditorNode::add_io_error("Could not find keystore, unable to export."); - return ERR_FILE_CANT_OPEN; - } + if (should_sign) { + if (p_debug) { + String debug_keystore = p_preset->get("keystore/debug"); + String debug_password = p_preset->get("keystore/debug_password"); + String debug_user = p_preset->get("keystore/debug_user"); + + if (debug_keystore.is_empty()) { + debug_keystore = EditorSettings::get_singleton()->get("export/android/debug_keystore"); + debug_password = EditorSettings::get_singleton()->get("export/android/debug_keystore_pass"); + debug_user = EditorSettings::get_singleton()->get("export/android/debug_keystore_user"); + } - cmdline.push_back("-Prelease_keystore_file=" + release_keystore); // argument to specify the release keystore file. - cmdline.push_back("-Prelease_keystore_alias=" + release_username); // argument to specify the release keystore alias. - cmdline.push_back("-Prelease_keystore_password=" + release_password); // argument to specity the release keystore password. + cmdline.push_back("-Pdebug_keystore_file=" + debug_keystore); // argument to specify the debug keystore file. + cmdline.push_back("-Pdebug_keystore_alias=" + debug_user); // argument to specify the debug keystore alias. + cmdline.push_back("-Pdebug_keystore_password=" + debug_password); // argument to specify the debug keystore password. + } else { + // Pass the release keystore info as well + String release_keystore = p_preset->get("keystore/release"); + String release_username = p_preset->get("keystore/release_user"); + String release_password = p_preset->get("keystore/release_password"); + if (!FileAccess::exists(release_keystore)) { + EditorNode::add_io_error("Could not find keystore, unable to export."); + return ERR_FILE_CANT_OPEN; + } + + cmdline.push_back("-Prelease_keystore_file=" + release_keystore); // argument to specify the release keystore file. + cmdline.push_back("-Prelease_keystore_alias=" + release_username); // argument to specify the release keystore alias. + cmdline.push_back("-Prelease_keystore_password=" + release_password); // argument to specify the release keystore password. + } } int result = EditorNode::get_singleton()->execute_and_show_output(TTR("Building Android Project (gradle)"), build_command, cmdline); @@ -2941,11 +3028,11 @@ public: EditorExportPlatformAndroid() { Ref<Image> img = memnew(Image(_android_logo)); - logo.instance(); + logo.instantiate(); logo->create_from_image(img); img = Ref<Image>(memnew(Image(_android_run_icon))); - run_icon.instance(); + run_icon.instantiate(); run_icon->create_from_image(img); devices_changed.set(); diff --git a/platform/android/export/gradle_export_util.h b/platform/android/export/gradle_export_util.h index 0bb94dcc97..52a7e4c5cf 100644 --- a/platform/android/export/gradle_export_util.h +++ b/platform/android/export/gradle_export_util.h @@ -31,9 +31,9 @@ #ifndef GODOT_GRADLE_EXPORT_UTIL_H #define GODOT_GRADLE_EXPORT_UTIL_H +#include "core/io/dir_access.h" +#include "core/io/file_access.h" #include "core/io/zip_io.h" -#include "core/os/dir_access.h" -#include "core/os/file_access.h" #include "core/os/os.h" #include "editor/editor_export.h" @@ -96,14 +96,6 @@ Error create_directory(const String &p_dir) { return OK; } -// Implementation of EditorExportSaveSharedObject. -// This method will only be called as an input to export_project_files. -// This method lets the .so files for all ABIs to be copied -// into the gradle project from the .AAR file -Error ignore_so_file(void *p_userdata, const SharedObject &p_so) { - return OK; -} - // Writes p_data into a file at p_path, creating directories if necessary. // Note: this will overwrite the file at p_path if it already exists. Error store_file_at_path(const String &p_path, const Vector<uint8_t> &p_data) { @@ -260,9 +252,13 @@ String _get_activity_tag(const Ref<EditorExportPreset> &p_preset) { String _get_application_tag(const Ref<EditorExportPreset> &p_preset) { String manifest_application_text = vformat( " <application android:label=\"@string/godot_project_name_string\"\n" - " android:allowBackup=\"%s\" tools:ignore=\"GoogleAppIndexingWarning\"\n" - " android:icon=\"@mipmap/icon\">\n\n", - bool_to_string(p_preset->get("user_data_backup/allow"))); + " android:allowBackup=\"%s\"\n" + " android:icon=\"@mipmap/icon\"\n" + " android:isGame=\"%s\"\n" + " tools:replace=\"android:allowBackup,android:isGame\"\n" + " tools:ignore=\"GoogleAppIndexingWarning\">\n\n", + bool_to_string(p_preset->get("user_data_backup/allow")), + bool_to_string(p_preset->get("package/classify_as_game"))); manifest_application_text += _get_activity_tag(p_preset); manifest_application_text += " </application>\n"; diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h index 8890e0f645..bb4ce36947 100644 --- a/platform/android/file_access_android.h +++ b/platform/android/file_access_android.h @@ -31,7 +31,7 @@ #ifndef FILE_ACCESS_ANDROID_H #define FILE_ACCESS_ANDROID_H -#include "core/os/file_access.h" +#include "core/io/file_access.h" #include <android/asset_manager.h> #include <android/log.h> #include <stdio.h> diff --git a/platform/android/java/app/AndroidManifest.xml b/platform/android/java/app/AndroidManifest.xml index 15feea15a4..0874d77645 100644 --- a/platform/android/java/app/AndroidManifest.xml +++ b/platform/android/java/app/AndroidManifest.xml @@ -19,8 +19,9 @@ <application android:label="@string/godot_project_name_string" android:allowBackup="false" - tools:ignore="GoogleAppIndexingWarning" - android:icon="@mipmap/icon" > + android:icon="@mipmap/icon" + android:isGame="true" + tools:ignore="GoogleAppIndexingWarning" > <!-- Records the version of the Godot editor used for building --> <meta-data diff --git a/platform/android/java/app/build.gradle b/platform/android/java/app/build.gradle index 1b1fb47bd8..18e07c3762 100644 --- a/platform/android/java/app/build.gradle +++ b/platform/android/java/app/build.gradle @@ -6,7 +6,7 @@ buildscript { repositories { google() - jcenter() + mavenCentral() } dependencies { classpath libraries.androidGradlePlugin @@ -18,9 +18,8 @@ apply plugin: 'com.android.application' allprojects { repositories { - mavenCentral() google() - jcenter() + mavenCentral() // Godot user plugins custom maven repos String[] mavenRepos = getGodotPluginsMavenRepos() @@ -113,6 +112,15 @@ android { } signingConfigs { + debug { + if (hasCustomDebugKeystore()) { + storeFile new File(getDebugKeystoreFile()) + storePassword getDebugKeystorePassword() + keyAlias getDebugKeyAlias() + keyPassword getDebugKeystorePassword() + } + } + release { File keystoreFile = new File(getReleaseKeystoreFile()) if (keystoreFile.isFile()) { diff --git a/platform/android/java/app/config.gradle b/platform/android/java/app/config.gradle index b278d15bdf..81fc87b7ef 100644 --- a/platform/android/java/app/config.gradle +++ b/platform/android/java/app/config.gradle @@ -1,11 +1,11 @@ ext.versions = [ - androidGradlePlugin: '4.0.1', + androidGradlePlugin: '4.2.1', compileSdk : 29, minSdk : 18, targetSdk : 29, buildTools : '30.0.3', supportCoreUtils : '1.0.0', - kotlinVersion : '1.4.10', + kotlinVersion : '1.5.10', v4Support : '1.0.0', javaVersion : 1.8, ndkVersion : '21.4.7075529' // Also update 'platform/android/detect.py#get_project_ndk_version()' when this is updated. @@ -191,6 +191,35 @@ ext.getGodotPluginsLocalBinaries = { -> return binDeps } +ext.getDebugKeystoreFile = { -> + String keystoreFile = project.hasProperty("debug_keystore_file") ? project.property("debug_keystore_file") : "" + if (keystoreFile == null || keystoreFile.isEmpty()) { + keystoreFile = "." + } + return keystoreFile +} + +ext.hasCustomDebugKeystore = { -> + File keystoreFile = new File(getDebugKeystoreFile()) + return keystoreFile.isFile() +} + +ext.getDebugKeystorePassword = { -> + String keystorePassword = project.hasProperty("debug_keystore_password") ? project.property("debug_keystore_password") : "" + if (keystorePassword == null || keystorePassword.isEmpty()) { + keystorePassword = "android" + } + return keystorePassword +} + +ext.getDebugKeyAlias = { -> + String keyAlias = project.hasProperty("debug_keystore_alias") ? project.property("debug_keystore_alias") : "" + if (keyAlias == null || keyAlias.isEmpty()) { + keyAlias = "androiddebugkey" + } + return keyAlias +} + ext.getReleaseKeystoreFile = { -> String keystoreFile = project.hasProperty("release_keystore_file") ? project.property("release_keystore_file") : "" if (keystoreFile == null || keystoreFile.isEmpty()) { diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle index a7fe500be2..ee24a46d9f 100644 --- a/platform/android/java/build.gradle +++ b/platform/android/java/build.gradle @@ -5,7 +5,7 @@ buildscript { repositories { google() - jcenter() + mavenCentral() } dependencies { classpath libraries.androidGradlePlugin @@ -16,7 +16,6 @@ buildscript { allprojects { repositories { google() - jcenter() mavenCentral() } } @@ -118,8 +117,8 @@ task zipCustomBuild(type: Zip) { } from(fileTree(dir: 'app', excludes: ['**/build/**', '**/.gradle/**', '**/*.iml']), fileTree(dir: '.', includes: ['gradle.properties', 'gradlew', 'gradlew.bat', 'gradle/**'])) include '**/*' - archiveName 'android_source.zip' - destinationDir(file(binDir)) + archiveFileName = 'android_source.zip' + destinationDirectory = file(binDir) } def templateExcludedBuildTask() { diff --git a/platform/android/java/gradle/wrapper/gradle-wrapper.properties b/platform/android/java/gradle/wrapper/gradle-wrapper.properties index a7d8a0f310..74c5636f8a 100644 --- a/platform/android/java/gradle/wrapper/gradle-wrapper.properties +++ b/platform/android/java/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Sep 02 02:44:30 PDT 2019 +#Wed Jun 23 23:42:22 PDT 2021 distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip +zipStoreBase=GRADLE_USER_HOME diff --git a/platform/android/java/gradlew.bat b/platform/android/java/gradlew.bat index f9553162f1..11cc30edb0 100644 --- a/platform/android/java/gradlew.bat +++ b/platform/android/java/gradlew.bat @@ -1,7 +1,7 @@ @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem -@rem Gradle startup script for Windows +@rem Gradle startup script for Windows @rem @rem ########################################################################## @@ -75,7 +75,7 @@ if "%ERRORLEVEL%"=="0" goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 exit /b 1 :mainEnd diff --git a/platform/android/java/lib/res/values/strings.xml b/platform/android/java/lib/res/values/strings.xml index 590b066d8a..010006b81e 100644 --- a/platform/android/java/lib/res/values/strings.xml +++ b/platform/android/java/lib/res/values/strings.xml @@ -6,7 +6,7 @@ <string name="text_button_resume_cellular">Resume download</string> <string name="text_button_wifi_settings">Wi-Fi settings</string> <string name="text_verifying_download">Verifying Download</string> - <string name="text_validation_complete">XAPK File Validation Complete. Select OK to exit.</string> + <string name="text_validation_complete">XAPK File Validation Complete. Select OK to exit.</string> <string name="text_validation_failed">XAPK File Validation Failed.</string> <string name="text_button_pause">Pause Download</string> <string name="text_button_resume">Resume Download</string> diff --git a/platform/android/java/lib/src/org/godotengine/godot/Dictionary.java b/platform/android/java/lib/src/org/godotengine/godot/Dictionary.java index 0572cf3589..b12844702a 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/Dictionary.java +++ b/platform/android/java/lib/src/org/godotengine/godot/Dictionary.java @@ -43,10 +43,10 @@ public class Dictionary extends HashMap<String, Object> { for (String key : keys) { ret[i] = key; i++; - }; + } return ret; - }; + } public Object[] get_values() { Object[] ret = new Object[size()]; @@ -55,21 +55,21 @@ public class Dictionary extends HashMap<String, Object> { for (String key : keys) { ret[i] = get(key); i++; - }; + } return ret; - }; + } public void set_keys(String[] keys) { keys_cache = keys; - }; + } public void set_values(Object[] vals) { int i = 0; for (String key : keys_cache) { put(key, vals[i]); i++; - }; + } keys_cache = null; - }; -}; + } +} diff --git a/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java b/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java index 1ed16e04ca..89497d1526 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java +++ b/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java @@ -96,14 +96,6 @@ public abstract class FullScreenGodotApp extends FragmentActivity implements God } } - @Override - public boolean onKeyMultiple(final int inKeyCode, int repeatCount, KeyEvent event) { - if (godotFragment != null && godotFragment.onKeyMultiple(inKeyCode, repeatCount, event)) { - return true; - } - return super.onKeyMultiple(inKeyCode, repeatCount, event); - } - /** * Used to initialize the Godot fragment instance in {@link FullScreenGodotApp#onCreate(Bundle)}. */ diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java index 0c16214c8a..8ffa4a9249 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java @@ -70,10 +70,8 @@ import android.os.VibrationEffect; import android.os.Vibrator; import android.provider.Settings.Secure; import android.view.Display; -import android.view.InputDevice; import android.view.KeyEvent; import android.view.LayoutInflater; -import android.view.MotionEvent; import android.view.Surface; import android.view.View; import android.view.ViewGroup; @@ -175,7 +173,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC public static GodotNetUtils netUtils; public interface ResultCallback { - public void callback(int requestCode, int resultCode, Intent data); + void callback(int requestCode, int resultCode, Intent data); } public ResultCallback result_callback; @@ -220,7 +218,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC for (int i = 0; i < permissions.length; i++) { GodotLib.requestPermissionResult(permissions[i], grantResults[i] == PackageManager.PERMISSION_GRANTED); } - }; + } /** * Invoked on the render thread when the Godot setup is complete. @@ -281,29 +279,20 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC editText.setView(mRenderView); io.setEdit(editText); - view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - Point fullSize = new Point(); - activity.getWindowManager().getDefaultDisplay().getSize(fullSize); - Rect gameSize = new Rect(); - mRenderView.getView().getWindowVisibleDisplayFrame(gameSize); - - final int keyboardHeight = fullSize.y - gameSize.bottom; - GodotLib.setVirtualKeyboardHeight(keyboardHeight); - } + view.getViewTreeObserver().addOnGlobalLayoutListener(() -> { + Point fullSize = new Point(); + activity.getWindowManager().getDefaultDisplay().getSize(fullSize); + Rect gameSize = new Rect(); + mRenderView.getView().getWindowVisibleDisplayFrame(gameSize); + final int keyboardHeight = fullSize.y - gameSize.bottom; + GodotLib.setVirtualKeyboardHeight(keyboardHeight); }); - mRenderView.queueOnRenderThread(new Runnable() { - @Override - public void run() { - // Must occur after GodotLib.setup has completed. - for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) { - plugin.onRegisterPluginWithGodotNative(); - } - - setKeepScreenOn("True".equals(GodotLib.getGlobal("display/window/energy_saving/keep_screen_on"))); + mRenderView.queueOnRenderThread(() -> { + for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) { + plugin.onRegisterPluginWithGodotNative(); } + setKeepScreenOn("True".equals(GodotLib.getGlobal("display/window/energy_saving/keep_screen_on"))); }); // Include the returned non-null views in the Godot view hierarchy. @@ -316,14 +305,11 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC } public void setKeepScreenOn(final boolean p_enabled) { - runOnUiThread(new Runnable() { - @Override - public void run() { - if (p_enabled) { - getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - } else { - getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - } + runOnUiThread(() -> { + if (p_enabled) { + getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + } else { + getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } }); } @@ -370,21 +356,14 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC public void alert(final String message, final String title) { final Activity activity = getActivity(); - runOnUiThread(new Runnable() { - @Override - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity); - builder.setMessage(message).setTitle(title); - builder.setPositiveButton( - "OK", - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dialog.cancel(); - } - }); - AlertDialog dialog = builder.create(); - dialog.show(); - } + runOnUiThread(() -> { + AlertDialog.Builder builder = new AlertDialog.Builder(activity); + builder.setMessage(message).setTitle(title); + builder.setPositiveButton( + "OK", + (dialog, id) -> dialog.cancel()); + AlertDialog dialog = builder.create(); + dialog.show(); }); } @@ -534,7 +513,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC String main_pack_md5 = null; String main_pack_key = null; - List<String> new_args = new LinkedList<String>(); + List<String> new_args = new LinkedList<>(); for (int i = 0; i < command_line.length; i++) { boolean has_extra = i < command_line.length - 1; @@ -755,19 +734,16 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC public void UiChangeListener() { final View decorView = getActivity().getWindow().getDecorView(); - decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() { - @Override - public void onSystemUiVisibilityChange(int visibility) { - if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - decorView.setSystemUiVisibility( - View.SYSTEM_UI_FLAG_LAYOUT_STABLE | - View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | - View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_FULLSCREEN | - View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); - } + decorView.setOnSystemUiVisibilityChangeListener(visibility -> { + if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + decorView.setSystemUiVisibility( + View.SYSTEM_UI_FLAG_LAYOUT_STABLE | + View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | + View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_FULLSCREEN | + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); } } }); @@ -780,7 +756,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC int displayRotation = display.getRotation(); float[] adjustedValues = new float[3]; - final int axisSwap[][] = { + final int[][] axisSwap = { { 1, -1, 0, 1 }, // ROTATION_0 { -1, -1, 1, 0 }, // ROTATION_90 { -1, 1, 0, 1 }, // ROTATION_180 @@ -798,21 +774,18 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC final int typeOfSensor = event.sensor.getType(); if (mRenderView != null) { - mRenderView.queueOnRenderThread(new Runnable() { - @Override - public void run() { - if (typeOfSensor == Sensor.TYPE_ACCELEROMETER) { - GodotLib.accelerometer(-x, y, -z); - } - if (typeOfSensor == Sensor.TYPE_GRAVITY) { - GodotLib.gravity(-x, y, -z); - } - if (typeOfSensor == Sensor.TYPE_MAGNETIC_FIELD) { - GodotLib.magnetometer(-x, y, -z); - } - if (typeOfSensor == Sensor.TYPE_GYROSCOPE) { - GodotLib.gyroscope(x, -y, z); - } + mRenderView.queueOnRenderThread(() -> { + if (typeOfSensor == Sensor.TYPE_ACCELEROMETER) { + GodotLib.accelerometer(-x, y, -z); + } + if (typeOfSensor == Sensor.TYPE_GRAVITY) { + GodotLib.gravity(-x, y, -z); + } + if (typeOfSensor == Sensor.TYPE_MAGNETIC_FIELD) { + GodotLib.magnetometer(-x, y, -z); + } + if (typeOfSensor == Sensor.TYPE_GYROSCOPE) { + GodotLib.gyroscope(x, -y, z); } }); } @@ -847,12 +820,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC } if (shouldQuit && mRenderView != null) { - mRenderView.queueOnRenderThread(new Runnable() { - @Override - public void run() { - GodotLib.back(); - } - }); + mRenderView.queueOnRenderThread(GodotLib::back); } } @@ -897,7 +865,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC byte[] messageDigest = complete.digest(); // Create Hex String - StringBuffer hexString = new StringBuffer(); + StringBuilder hexString = new StringBuilder(); for (int i = 0; i < messageDigest.length; i++) { String s = Integer.toHexString(0xFF & messageDigest[i]); @@ -918,33 +886,6 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC } } - public boolean onKeyMultiple(final int inKeyCode, int repeatCount, KeyEvent event) { - String s = event.getCharacters(); - if (s == null || s.length() == 0) - return false; - - final char[] cc = s.toCharArray(); - int cnt = 0; - for (int i = cc.length; --i >= 0; cnt += cc[i] != 0 ? 1 : 0) - ; - if (cnt == 0) - return false; - mRenderView.queueOnRenderThread(new Runnable() { - // This method will be called on the rendering thread: - public void run() { - for (int i = 0, n = cc.length; i < n; i++) { - int keyCode; - if ((keyCode = cc[i]) != 0) { - // Simulate key down and up... - GodotLib.key(0, 0, keyCode, true); - GodotLib.key(0, 0, keyCode, false); - } - } - } - }); - return true; - } - public boolean requestPermission(String p_name) { return PermissionsUtil.requestPermission(p_name, getActivity()); } diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java index b3ee55ea64..a9d45c943b 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java @@ -232,13 +232,10 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView public void onResume() { super.onResume(); - queueEvent(new Runnable() { - @Override - public void run() { - // Resume the renderer - godotRenderer.onActivityResumed(); - GodotLib.focusin(); - } + queueEvent(() -> { + // Resume the renderer + godotRenderer.onActivityResumed(); + GodotLib.focusin(); }); } @@ -246,13 +243,10 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView public void onPause() { super.onPause(); - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.focusout(); - // Pause the renderer - godotRenderer.onActivityPaused(); - } + queueEvent(() -> { + GodotLib.focusout(); + // Pause the renderer + godotRenderer.onActivityPaused(); }); } } diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java index c7c7c1b40c..66882e8e72 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java @@ -34,11 +34,9 @@ import org.godotengine.godot.input.*; import android.app.Activity; import android.content.*; -import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.res.AssetManager; import android.graphics.Point; -import android.media.*; import android.net.Uri; import android.os.*; import android.util.DisplayMetrics; @@ -73,7 +71,7 @@ public class GodotIO { public int last_file_id = 1; - class AssetData { + static class AssetData { public boolean eof = false; public String path; public InputStream is; @@ -232,7 +230,7 @@ public class GodotIO { /// DIRECTORIES ///////////////////////// - class AssetDir { + static class AssetDir { public String[] files; public int current; public String path; @@ -323,97 +321,8 @@ public class GodotIO { am = p_activity.getAssets(); activity = p_activity; //streams = new HashMap<Integer, AssetData>(); - streams = new SparseArray<AssetData>(); - dirs = new SparseArray<AssetDir>(); - } - - ///////////////////////// - // AUDIO - ///////////////////////// - - private Object buf; - private Thread mAudioThread; - private AudioTrack mAudioTrack; - - public Object audioInit(int sampleRate, int desiredFrames) { - int channelConfig = AudioFormat.CHANNEL_OUT_STEREO; - int audioFormat = AudioFormat.ENCODING_PCM_16BIT; - int frameSize = 4; - - System.out.printf("audioInit: initializing audio:\n"); - - //Log.v("Godot", "Godot audio: wanted " + (isStereo ? "stereo" : "mono") + " " + (is16Bit ? "16-bit" : "8-bit") + " " + ((float)sampleRate / 1000f) + "kHz, " + desiredFrames + " frames buffer"); - - // Let the user pick a larger buffer if they really want -- but ye - // gods they probably shouldn't, the minimums are horrifyingly high - // latency already - desiredFrames = Math.max(desiredFrames, (AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat) + frameSize - 1) / frameSize); - - mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, - channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM); - - audioStartThread(); - - //Log.v("Godot", "Godot audio: got " + ((mAudioTrack.getChannelCount() >= 2) ? "stereo" : "mono") + " " + ((mAudioTrack.getAudioFormat() == AudioFormat.ENCODING_PCM_16BIT) ? "16-bit" : "8-bit") + " " + ((float)mAudioTrack.getSampleRate() / 1000f) + "kHz, " + desiredFrames + " frames buffer"); - - buf = new short[desiredFrames * 2]; - return buf; - } - - public void audioStartThread() { - mAudioThread = new Thread(new Runnable() { - public void run() { - mAudioTrack.play(); - GodotLib.audio(); - } - }); - - // I'd take REALTIME if I could get it! - mAudioThread.setPriority(Thread.MAX_PRIORITY); - mAudioThread.start(); - } - - public void audioWriteShortBuffer(short[] buffer) { - for (int i = 0; i < buffer.length;) { - int result = mAudioTrack.write(buffer, i, buffer.length - i); - if (result > 0) { - i += result; - } else if (result == 0) { - try { - Thread.sleep(1); - } catch (InterruptedException e) { - // Nom nom - } - } else { - Log.w("Godot", "Godot audio: error return from write(short)"); - return; - } - } - } - - public void audioQuit() { - if (mAudioThread != null) { - try { - mAudioThread.join(); - } catch (Exception e) { - Log.v("Godot", "Problem stopping audio thread: " + e); - } - mAudioThread = null; - - //Log.v("Godot", "Finished waiting for audio thread"); - } - - if (mAudioTrack != null) { - mAudioTrack.stop(); - mAudioTrack = null; - } - } - - public void audioPause(boolean p_pause) { - if (p_pause) - mAudioTrack.pause(); - else - mAudioTrack.play(); + streams = new SparseArray<>(); + dirs = new SparseArray<>(); } ///////////////////////// @@ -452,6 +361,10 @@ public class GodotIO { return activity.getFilesDir().getAbsolutePath(); } + public String getExternalDataDir() { + return activity.getExternalFilesDir(null).getAbsolutePath(); + } + public String getLocale() { return Locale.getDefault().toString(); } @@ -471,7 +384,7 @@ public class GodotIO { Point size = new Point(); display.getRealSize(size); - int result[] = { 0, 0, size.x, size.y }; + int[] result = { 0, 0, size.x, size.y }; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { WindowInsets insets = activity.getWindow().getDecorView().getRootWindowInsets(); DisplayCutout cutout = insets.getDisplayCutout(); @@ -493,12 +406,12 @@ public class GodotIO { //InputMethodManager inputMgr = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE); //inputMgr.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); - }; + } public void hideKeyboard() { if (edit != null) edit.hideKeyboard(); - }; + } public void setScreenOrientation(int p_orientation) { switch (p_orientation) { diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java index 534a50e9ed..95870acda1 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java @@ -34,7 +34,6 @@ import android.app.Activity; import android.hardware.SensorEvent; import android.view.Surface; -import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; /** @@ -175,11 +174,6 @@ public class GodotLib { public static native void focusout(); /** - * Invoked when the audio thread is started. - */ - public static native void audio(); - - /** * Used to access Godot global properties. * @param p_key Property key * @return String value of the property diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java index ac333dd827..79007764a7 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java @@ -35,18 +35,18 @@ import org.godotengine.godot.input.GodotInputHandler; import android.view.SurfaceView; public interface GodotRenderView { - abstract public SurfaceView getView(); + SurfaceView getView(); - abstract public void initInputDevices(); + void initInputDevices(); - abstract public void queueOnRenderThread(Runnable event); + void queueOnRenderThread(Runnable event); - abstract public void onActivityPaused(); - abstract public void onActivityResumed(); + void onActivityPaused(); + void onActivityResumed(); - abstract public void onBackPressed(); + void onBackPressed(); - abstract public GodotInputHandler getInputHandler(); + GodotInputHandler getInputHandler(); - abstract public void setPointerIcon(int pointerType); + void setPointerIcon(int pointerType); } diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderer.java b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderer.java index 59bdbf7f8d..878a119c5c 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderer.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderer.java @@ -34,7 +34,6 @@ import org.godotengine.godot.plugin.GodotPlugin; import org.godotengine.godot.plugin.GodotPluginRegistry; import org.godotengine.godot.utils.GLUtils; -import android.content.Context; import android.opengl.GLSurfaceView; import javax.microedition.khronos.egl.EGLConfig; diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java index 169c6cf770..6fca7f2a57 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java @@ -39,7 +39,6 @@ import android.annotation.SuppressLint; import android.content.Context; import android.os.Build; import android.view.GestureDetector; -import android.view.InputDevice; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.PointerIcon; @@ -150,13 +149,10 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV public void onResume() { super.onResume(); - queueOnVkThread(new Runnable() { - @Override - public void run() { - // Resume the renderer - mRenderer.onVkResume(); - GodotLib.focusin(); - } + queueOnVkThread(() -> { + // Resume the renderer + mRenderer.onVkResume(); + GodotLib.focusin(); }); } @@ -164,13 +160,10 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV public void onPause() { super.onPause(); - queueOnVkThread(new Runnable() { - @Override - public void run() { - GodotLib.focusout(); - // Pause the renderer - mRenderer.onVkPause(); - } + queueOnVkThread(() -> { + GodotLib.focusout(); + // Pause the renderer + mRenderer.onVkPause(); }); } } diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java index 2c39d06832..1d60c21c60 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java +++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java @@ -75,12 +75,7 @@ public class GodotGestureHandler extends GestureDetector.SimpleOnGestureListener final int x = Math.round(event.getX()); final int y = Math.round(event.getY()); final int buttonMask = event.getButtonState(); - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.doubleTap(buttonMask, x, y); - } - }); + queueEvent(() -> GodotLib.doubleTap(buttonMask, x, y)); return true; } @@ -89,12 +84,7 @@ public class GodotGestureHandler extends GestureDetector.SimpleOnGestureListener //Log.i("GodotGesture", "onScroll"); final int x = Math.round(distanceX); final int y = Math.round(distanceY); - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.scroll(x, y); - } - }); + queueEvent(() -> GodotLib.scroll(x, y)); return true; } diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java index 435b8b325f..4dc9157545 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java +++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java @@ -45,13 +45,9 @@ import android.view.InputDevice.MotionRange; import android.view.KeyEvent; import android.view.MotionEvent; -import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; -import java.util.HashMap; import java.util.HashSet; -import java.util.List; -import java.util.Map; import java.util.Set; /** @@ -64,7 +60,7 @@ public class GodotInputHandler implements InputDeviceListener { private final String tag = this.getClass().getSimpleName(); private final SparseIntArray mJoystickIds = new SparseIntArray(4); - private final SparseArray<Joystick> mJoysticksDevices = new SparseArray<Joystick>(4); + private final SparseArray<Joystick> mJoysticksDevices = new SparseArray<>(4); public GodotInputHandler(GodotRenderView godotView) { mRenderView = godotView; @@ -101,22 +97,12 @@ public class GodotInputHandler implements InputDeviceListener { final int button = getGodotButton(keyCode); final int godotJoyId = mJoystickIds.get(deviceId); - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.joybutton(godotJoyId, button, false); - } - }); + queueEvent(() -> GodotLib.joybutton(godotJoyId, button, false)); } } else { final int scanCode = event.getScanCode(); final int chr = event.getUnicodeChar(0); - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.key(keyCode, scanCode, chr, false); - } - }); + queueEvent(() -> GodotLib.key(keyCode, scanCode, chr, false)); } return true; @@ -147,22 +133,12 @@ public class GodotInputHandler implements InputDeviceListener { final int button = getGodotButton(keyCode); final int godotJoyId = mJoystickIds.get(deviceId); - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.joybutton(godotJoyId, button, true); - } - }); + queueEvent(() -> GodotLib.joybutton(godotJoyId, button, true)); } } else { final int scanCode = event.getScanCode(); final int chr = event.getUnicodeChar(0); - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.key(keyCode, scanCode, chr, true); - } - }); + queueEvent(() -> GodotLib.key(keyCode, scanCode, chr, true)); } return true; @@ -194,19 +170,16 @@ public class GodotInputHandler implements InputDeviceListener { final int action = event.getActionMasked(); final int pointer_idx = event.getPointerId(event.getActionIndex()); - mRenderView.queueOnRenderThread(new Runnable() { - @Override - public void run() { - switch (action) { - case MotionEvent.ACTION_DOWN: - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_MOVE: - case MotionEvent.ACTION_POINTER_UP: - case MotionEvent.ACTION_POINTER_DOWN: { - GodotLib.touch(event.getSource(), action, pointer_idx, evcount, arr); - } break; - } + mRenderView.queueOnRenderThread(() -> { + switch (action) { + case MotionEvent.ACTION_DOWN: + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_MOVE: + case MotionEvent.ACTION_POINTER_UP: + case MotionEvent.ACTION_POINTER_DOWN: { + GodotLib.touch(event.getSource(), action, pointer_idx, evcount, arr); + } break; } }); } @@ -232,13 +205,7 @@ public class GodotInputHandler implements InputDeviceListener { // save value to prevent repeats joystick.axesValues.put(axis, value); final int godotAxisIdx = i; - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.joyaxis(godotJoyId, godotAxisIdx, value); - //Log.i(tag, "GodotLib.joyaxis("+godotJoyId+", "+godotAxisIdx+", "+value+");"); - } - }); + queueEvent(() -> GodotLib.joyaxis(godotJoyId, godotAxisIdx, value)); } } @@ -248,13 +215,7 @@ public class GodotInputHandler implements InputDeviceListener { if (joystick.hatX != hatX || joystick.hatY != hatY) { joystick.hatX = hatX; joystick.hatY = hatY; - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.joyhat(godotJoyId, hatX, hatY); - //Log.i(tag, "GodotLib.joyhat("+godotJoyId+", "+hatX+", "+hatY+");"); - } - }); + queueEvent(() -> GodotLib.joyhat(godotJoyId, hatX, hatY)); } } return true; @@ -263,12 +224,7 @@ public class GodotInputHandler implements InputDeviceListener { final float x = event.getX(); final float y = event.getY(); final int type = event.getAction(); - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.hover(type, x, y); - } - }); + queueEvent(() -> GodotLib.hover(type, x, y)); return true; } else if (event.isFromSource(InputDevice.SOURCE_MOUSE) || event.isFromSource(InputDevice.SOURCE_MOUSE_RELATIVE)) { @@ -333,7 +289,7 @@ public class GodotInputHandler implements InputDeviceListener { //Helps with creating new joypad mappings. Log.i(tag, "=== New Input Device: " + joystick.name); - Set<Integer> already = new HashSet<Integer>(); + Set<Integer> already = new HashSet<>(); for (InputDevice.MotionRange range : device.getMotionRanges()) { boolean isJoystick = range.isFromSource(InputDevice.SOURCE_JOYSTICK); boolean isGamepad = range.isFromSource(InputDevice.SOURCE_GAMEPAD); @@ -360,12 +316,7 @@ public class GodotInputHandler implements InputDeviceListener { } mJoysticksDevices.put(deviceId, joystick); - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.joyconnectionchanged(id, true, joystick.name); - } - }); + queueEvent(() -> GodotLib.joyconnectionchanged(id, true, joystick.name)); } @Override @@ -378,12 +329,7 @@ public class GodotInputHandler implements InputDeviceListener { mJoystickIds.delete(deviceId); mJoysticksDevices.delete(deviceId); - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.joyconnectionchanged(godotJoyId, false, ""); - } - }); + queueEvent(() -> GodotLib.joyconnectionchanged(godotJoyId, false, "")); } @Override @@ -472,12 +418,7 @@ public class GodotInputHandler implements InputDeviceListener { final float x = event.getX(); final float y = event.getY(); final int type = event.getAction(); - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.hover(type, x, y); - } - }); + queueEvent(() -> GodotLib.hover(type, x, y)); return true; } case MotionEvent.ACTION_BUTTON_PRESS: @@ -487,12 +428,7 @@ public class GodotInputHandler implements InputDeviceListener { final float y = event.getY(); final int buttonsMask = event.getButtonState(); final int action = event.getAction(); - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.touch(event.getSource(), action, 0, 1, new float[] { 0, x, y }, buttonsMask); - } - }); + queueEvent(() -> GodotLib.touch(event.getSource(), action, 0, 1, new float[] { 0, x, y }, buttonsMask)); return true; } case MotionEvent.ACTION_SCROLL: { @@ -502,12 +438,7 @@ public class GodotInputHandler implements InputDeviceListener { final int action = event.getAction(); final float verticalFactor = event.getAxisValue(MotionEvent.AXIS_VSCROLL); final float horizontalFactor = event.getAxisValue(MotionEvent.AXIS_HSCROLL); - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.touch(event.getSource(), action, 0, 1, new float[] { 0, x, y }, buttonsMask, verticalFactor, horizontalFactor); - } - }); + queueEvent(() -> GodotLib.touch(event.getSource(), action, 0, 1, new float[] { 0, x, y }, buttonsMask, verticalFactor, horizontalFactor)); } case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_UP: { diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java index 3e0e6a65fd..020870a110 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java +++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java @@ -94,17 +94,14 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene public void beforeTextChanged(final CharSequence pCharSequence, final int start, final int count, final int after) { //Log.d(TAG, "beforeTextChanged(" + pCharSequence + ")start: " + start + ",count: " + count + ",after: " + after); - mRenderView.queueOnRenderThread(new Runnable() { - @Override - public void run() { - for (int i = 0; i < count; ++i) { - GodotLib.key(KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL, 0, true); - GodotLib.key(KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL, 0, false); - - if (mHasSelection) { - mHasSelection = false; - break; - } + mRenderView.queueOnRenderThread(() -> { + for (int i = 0; i < count; ++i) { + GodotLib.key(KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL, 0, true); + GodotLib.key(KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL, 0, false); + + if (mHasSelection) { + mHasSelection = false; + break; } } }); @@ -118,18 +115,15 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene for (int i = start; i < start + count; ++i) { newChars[i - start] = pCharSequence.charAt(i); } - mRenderView.queueOnRenderThread(new Runnable() { - @Override - public void run() { - for (int i = 0; i < count; ++i) { - int key = newChars[i]; - if ((key == '\n') && !mEdit.isMultiline()) { - // Return keys are handled through action events - continue; - } - GodotLib.key(0, 0, key, true); - GodotLib.key(0, 0, key, false); + mRenderView.queueOnRenderThread(() -> { + for (int i = 0; i < count; ++i) { + int key = newChars[i]; + if ((key == '\n') && !mEdit.isMultiline()) { + // Return keys are handled through action events + continue; } + GodotLib.key(0, 0, key, true); + GodotLib.key(0, 0, key, false); } }); } @@ -139,23 +133,21 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene if (mEdit == pTextView && isFullScreenEdit()) { final String characters = pKeyEvent.getCharacters(); - mRenderView.queueOnRenderThread(new Runnable() { - @Override - public void run() { - for (int i = 0; i < characters.length(); i++) { - final int ch = characters.codePointAt(i); - GodotLib.key(0, 0, ch, true); - GodotLib.key(0, 0, ch, false); - } + mRenderView.queueOnRenderThread(() -> { + for (int i = 0; i < characters.length(); i++) { + final int ch = characters.codePointAt(i); + GodotLib.key(0, 0, ch, true); + GodotLib.key(0, 0, ch, false); } }); } if (pActionID == EditorInfo.IME_ACTION_DONE) { // Enter key has been pressed - GodotLib.key(KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_ENTER, 0, true); - GodotLib.key(KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_ENTER, 0, false); - + mRenderView.queueOnRenderThread(() -> { + GodotLib.key(KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_ENTER, 0, true); + GodotLib.key(KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_ENTER, 0, false); + }); mRenderView.getView().requestFocus(); return true; } diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerCompat.java b/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerCompat.java index 62810ad3a4..21fdc658bb 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerCompat.java +++ b/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerCompat.java @@ -28,14 +28,14 @@ public interface InputManagerCompat { * @param id The device id * @return The input device or null if not found */ - public InputDevice getInputDevice(int id); + InputDevice getInputDevice(int id); /** * Gets the ids of all input devices in the system. * * @return The input device ids. */ - public int[] getInputDeviceIds(); + int[] getInputDeviceIds(); /** * Registers an input device listener to receive notifications about when @@ -46,7 +46,7 @@ public interface InputManagerCompat { * null if the listener should be invoked on the calling thread's * looper. */ - public void registerInputDeviceListener(InputManagerCompat.InputDeviceListener listener, + void registerInputDeviceListener(InputManagerCompat.InputDeviceListener listener, Handler handler); /** @@ -54,7 +54,7 @@ public interface InputManagerCompat { * * @param listener The listener to unregister. */ - public void unregisterInputDeviceListener(InputManagerCompat.InputDeviceListener listener); + void unregisterInputDeviceListener(InputManagerCompat.InputDeviceListener listener); /* * The following three calls are to simulate V16 behavior on pre-Jellybean @@ -69,7 +69,7 @@ public interface InputManagerCompat { * * @param event the motion event from the app */ - public void onGenericMotionEvent(MotionEvent event); + void onGenericMotionEvent(MotionEvent event); /** * Tell the V9 input manager that it should stop polling for disconnected @@ -77,7 +77,7 @@ public interface InputManagerCompat { * might want to call it whenever your game is not active (or whenever you * don't care about being notified of new input devices) */ - public void onPause(); + void onPause(); /** * Tell the V9 input manager that it should start polling for disconnected @@ -85,9 +85,9 @@ public interface InputManagerCompat { * might want to call it less often (only when the gameplay is actually * active) */ - public void onResume(); + void onResume(); - public interface InputDeviceListener { + interface InputDeviceListener { /** * Called whenever the input manager detects that a device has been * added. This will only be called in the V9 version when a motion event @@ -119,7 +119,7 @@ public interface InputManagerCompat { /** * Use this to construct a compatible InputManager. */ - public static class Factory { + class Factory { /** * Constructs and returns a compatible InputManger * diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerV16.java b/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerV16.java index 61828dccae..0dbc13c77b 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerV16.java +++ b/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerV16.java @@ -34,7 +34,7 @@ public class InputManagerV16 implements InputManagerCompat { public InputManagerV16(Context context) { mInputManager = (InputManager)context.getSystemService(Context.INPUT_SERVICE); - mListeners = new HashMap<InputManagerCompat.InputDeviceListener, V16InputDeviceListener>(); + mListeners = new HashMap<>(); } @Override diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/Joystick.java b/platform/android/java/lib/src/org/godotengine/godot/input/Joystick.java index 4b7318c718..bff90d7ce9 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/Joystick.java +++ b/platform/android/java/lib/src/org/godotengine/godot/input/Joystick.java @@ -41,12 +41,12 @@ import java.util.List; class Joystick { int device_id; String name; - List<Integer> axes = new ArrayList<Integer>(); + List<Integer> axes = new ArrayList<>(); protected boolean hasAxisHat = false; /* * Keep track of values so we can prevent flooding the engine with useless events. */ - protected final SparseArray axesValues = new SparseArray<Float>(4); + protected final SparseArray<Float> axesValues = new SparseArray<>(4); protected int hatX; protected int hatY; } diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java index 6c8a3d4219..2dc8359615 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java +++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java @@ -136,7 +136,7 @@ public abstract class GodotPlugin { nativeRegisterSingleton(pluginName, pluginObject); Set<Method> filteredMethods = new HashSet<>(); - Class clazz = pluginObject.getClass(); + Class<?> clazz = pluginObject.getClass(); Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { @@ -157,8 +157,8 @@ public abstract class GodotPlugin { for (Method method : filteredMethods) { List<String> ptr = new ArrayList<>(); - Class[] paramTypes = method.getParameterTypes(); - for (Class c : paramTypes) { + Class<?>[] paramTypes = method.getParameterTypes(); + for (Class<?> c : paramTypes) { ptr.add(c.getName()); } diff --git a/platform/android/java/lib/src/org/godotengine/godot/utils/Crypt.java b/platform/android/java/lib/src/org/godotengine/godot/utils/Crypt.java index d6e49bb635..2b6e4ad2be 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/utils/Crypt.java +++ b/platform/android/java/lib/src/org/godotengine/godot/utils/Crypt.java @@ -39,10 +39,10 @@ public class Crypt { // Create MD5 Hash MessageDigest digest = java.security.MessageDigest.getInstance("MD5"); digest.update(input.getBytes()); - byte messageDigest[] = digest.digest(); + byte[] messageDigest = digest.digest(); // Create Hex String - StringBuffer hexString = new StringBuffer(); + StringBuilder hexString = new StringBuilder(); for (int i = 0; i < messageDigest.length; i++) hexString.append(Integer.toHexString(0xFF & messageDigest[i])); return hexString.toString(); diff --git a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt index f0e37d80b8..b01dc2653a 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt @@ -115,7 +115,7 @@ open internal class VkSurfaceView(context: Context) : SurfaceView(context), Surf /** * Tear down the rendering thread. * - * Must not be called before a [VkRenderer] has been set. + * Must not be called before a [VkRenderer] has been set. */ fun onDestroy() { vkThread.blockingExit() diff --git a/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java b/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java index 71610d2d00..c852e8759a 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java +++ b/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java @@ -30,7 +30,6 @@ package org.godotengine.godot.xr.regular; -import org.godotengine.godot.GodotLib; import org.godotengine.godot.utils.GLUtils; import android.opengl.GLSurfaceView; diff --git a/platform/android/java_class_wrapper.cpp b/platform/android/java_class_wrapper.cpp index f49b0e843a..ed6b5c3e14 100644 --- a/platform/android/java_class_wrapper.cpp +++ b/platform/android/java_class_wrapper.cpp @@ -102,7 +102,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method, if (p_args[i]->get_type() != Variant::OBJECT) arg_expected = Variant::OBJECT; else { - Ref<Reference> ref = *p_args[i]; + Ref<RefCounted> ref = *p_args[i]; if (!ref.is_null()) { if (Object::cast_to<JavaObject>(ref.ptr())) { Ref<JavaObject> jo = ref; @@ -488,7 +488,7 @@ Variant JavaClass::call(const StringName &p_method, const Variant **p_args, int return ret; } - return Reference::call(p_method, p_args, p_argcount, r_error); + return RefCounted::call(p_method, p_args, p_argcount, r_error); } JavaClass::JavaClass() { diff --git a/platform/android/java_godot_io_wrapper.cpp b/platform/android/java_godot_io_wrapper.cpp index ec3b6f8ac0..5e99135498 100644 --- a/platform/android/java_godot_io_wrapper.cpp +++ b/platform/android/java_godot_io_wrapper.cpp @@ -49,6 +49,7 @@ GodotIOJavaWrapper::GodotIOJavaWrapper(JNIEnv *p_env, jobject p_godot_io_instanc _open_URI = p_env->GetMethodID(cls, "openURI", "(Ljava/lang/String;)I"); _get_data_dir = p_env->GetMethodID(cls, "getDataDir", "()Ljava/lang/String;"); + _get_external_data_dir = p_env->GetMethodID(cls, "getExternalDataDir", "()Ljava/lang/String;"); _get_locale = p_env->GetMethodID(cls, "getLocale", "()Ljava/lang/String;"); _get_model = p_env->GetMethodID(cls, "getModel", "()Ljava/lang/String;"); _get_screen_DPI = p_env->GetMethodID(cls, "getScreenDPI", "()I"); @@ -92,6 +93,17 @@ String GodotIOJavaWrapper::get_user_data_dir() { } } +String GodotIOJavaWrapper::get_external_data_dir() { + if (_get_external_data_dir) { + JNIEnv *env = get_jni_env(); + ERR_FAIL_COND_V(env == nullptr, String()); + jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_external_data_dir); + return jstring_to_string(s, env); + } else { + return String(); + } +} + String GodotIOJavaWrapper::get_locale() { if (_get_locale) { JNIEnv *env = get_jni_env(); diff --git a/platform/android/java_godot_io_wrapper.h b/platform/android/java_godot_io_wrapper.h index 394e97effa..e4c0a4b2c7 100644 --- a/platform/android/java_godot_io_wrapper.h +++ b/platform/android/java_godot_io_wrapper.h @@ -47,6 +47,7 @@ private: jmethodID _open_URI = 0; jmethodID _get_data_dir = 0; + jmethodID _get_external_data_dir = 0; jmethodID _get_locale = 0; jmethodID _get_model = 0; jmethodID _get_screen_DPI = 0; @@ -66,6 +67,7 @@ public: Error open_uri(const String &p_uri); String get_user_data_dir(); + String get_external_data_dir(); String get_locale(); String get_model(); int get_screen_dpi(); diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp index c7ff6cb2c0..4c66789a83 100644 --- a/platform/android/java_godot_lib_jni.cpp +++ b/platform/android/java_godot_lib_jni.cpp @@ -36,7 +36,6 @@ #include "android/asset_manager_jni.h" #include "api/java_class_wrapper.h" #include "api/jni_singleton.h" -#include "audio_driver_jandroid.h" #include "core/config/engine.h" #include "core/config/project_settings.h" #include "core/input/input.h" @@ -94,7 +93,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en FileAccessAndroid::asset_manager = AAssetManager_fromJava(env, amgr); DirAccessJAndroid::setup(godot_io_java->get_instance()); - AudioDriverAndroid::setup(godot_io_java->get_instance()); NetSocketAndroid::setup(godot_java->get_member_object("netUtils", "Lorg/godotengine/godot/utils/GodotNetUtils;", env)); os_android = new OS_Android(godot_java, godot_io_java, p_use_apk_expansion); @@ -326,15 +324,15 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, j int hat = 0; if (p_hat_x != 0) { if (p_hat_x < 0) - hat |= Input::HAT_MASK_LEFT; + hat |= HatMask::HAT_MASK_LEFT; else - hat |= Input::HAT_MASK_RIGHT; + hat |= HatMask::HAT_MASK_RIGHT; } if (p_hat_y != 0) { if (p_hat_y < 0) - hat |= Input::HAT_MASK_UP; + hat |= HatMask::HAT_MASK_UP; else - hat |= Input::HAT_MASK_DOWN; + hat |= HatMask::HAT_MASK_DOWN; } jevent.hat = hat; @@ -385,11 +383,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusout(JNIEnv *env, os_android->main_loop_focusout(); } -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_audio(JNIEnv *env, jclass clazz) { - setup_android_thread(); - AudioDriverAndroid::thread_func(env); -} - JNIEXPORT jstring JNICALL Java_org_godotengine_godot_GodotLib_getGlobal(JNIEnv *env, jclass clazz, jstring path) { String js = jstring_to_string(path, env); diff --git a/platform/android/java_godot_lib_jni.h b/platform/android/java_godot_lib_jni.h index a3e2933185..63e9e6d8e5 100644 --- a/platform/android/java_godot_lib_jni.h +++ b/platform/android/java_godot_lib_jni.h @@ -56,7 +56,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env, jclass clazz, jint p_device, jint p_axis, jfloat p_value); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, jclass clazz, jint p_device, jint p_hat_x, jint p_hat_y); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged(JNIEnv *env, jclass clazz, jint p_device, jboolean p_connected, jstring p_name); -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_audio(JNIEnv *env, jclass clazz); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_accelerometer(JNIEnv *env, jclass clazz, jfloat x, jfloat y, jfloat z); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_gravity(JNIEnv *env, jclass clazz, jfloat x, jfloat y, jfloat z); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_magnetometer(JNIEnv *env, jclass clazz, jfloat x, jfloat y, jfloat z); diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 422814dd50..222976d948 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -45,6 +45,23 @@ #include "java_godot_io_wrapper.h" #include "java_godot_wrapper.h" +String _remove_symlink(const String &dir) { + // Workaround for Android 6.0+ using a symlink. + // Save the current directory. + char current_dir_name[2048]; + getcwd(current_dir_name, 2048); + // Change directory to the external data directory. + chdir(dir.utf8().get_data()); + // Get the actual directory without the potential symlink. + char dir_name_wihout_symlink[2048]; + getcwd(dir_name_wihout_symlink, 2048); + // Convert back to a String. + String dir_without_symlink(dir_name_wihout_symlink); + // Restore original current directory. + chdir(current_dir_name); + return dir_without_symlink; +} + class AndroidLogger : public Logger { public: virtual void logv(const char *p_format, va_list p_list, bool p_err) { @@ -199,26 +216,18 @@ String OS_Android::get_user_data_dir() const { String data_dir = godot_io_java->get_user_data_dir(); if (data_dir != "") { - //store current dir - char real_current_dir_name[2048]; - getcwd(real_current_dir_name, 2048); - - //go to data dir - chdir(data_dir.utf8().get_data()); - - //get actual data dir, so we resolve potential symlink (Android 6.0+ seems to use symlink) - char data_current_dir_name[2048]; - getcwd(data_current_dir_name, 2048); - - //cache by parsing utf8 - data_dir_cache.parse_utf8(data_current_dir_name); - - //restore original dir so we don't mess things up - chdir(real_current_dir_name); - + data_dir_cache = _remove_symlink(data_dir); return data_dir_cache; } + return "."; +} +String OS_Android::get_external_data_dir() const { + String data_dir = godot_io_java->get_external_data_dir(); + if (data_dir != "") { + data_dir = _remove_symlink(data_dir); + return data_dir; + } return "."; } diff --git a/platform/android/os_android.h b/platform/android/os_android.h index dd14b69cf9..1e89e9211d 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -31,7 +31,6 @@ #ifndef OS_ANDROID_H #define OS_ANDROID_H -#include "audio_driver_jandroid.h" #include "audio_driver_opensl.h" #include "core/os/main_loop.h" #include "drivers/unix/os_unix.h" @@ -59,7 +58,6 @@ private: mutable String data_dir_cache; - //AudioDriverAndroid audio_driver_android; AudioDriverOpenSL audio_driver_android; MainLoop *main_loop; @@ -111,6 +109,7 @@ public: virtual Error shell_open(String p_uri) override; virtual String get_user_data_dir() const override; + virtual String get_external_data_dir() const override; virtual String get_resource_dir() const override; virtual String get_locale() const override; virtual String get_model_name() const override; diff --git a/platform/android/plugin/godot_plugin_config.h b/platform/android/plugin/godot_plugin_config.h index 173ac115a2..6b708548ae 100644 --- a/platform/android/plugin/godot_plugin_config.h +++ b/platform/android/plugin/godot_plugin_config.h @@ -37,8 +37,8 @@ /* The `config` section and fields are required and defined as follow: -- **name**: name of the plugin -- **binary_type**: can be either `local` or `remote`. The type affects the **binary** field +- **name**: name of the plugin. +- **binary_type**: can be either `local` or `remote`. The type affects the **binary** field. - **binary**: - if **binary_type** is `local`, then this should be the filename of the plugin `aar` file in the `res://android/plugins` directory (e.g: `MyPlugin.aar`). - if **binary_type** is `remote`, then this should be a declaration for a remote gradle binary (e.g: "org.godot.example:my-plugin:0.0.0"). @@ -102,7 +102,7 @@ struct PluginConfigAndroid { static inline String resolve_local_dependency_path(String plugin_config_dir, String dependency_path) { String absolute_path; if (!dependency_path.is_empty()) { - if (dependency_path.is_abs_path()) { + if (dependency_path.is_absolute_path()) { absolute_path = ProjectSettings::get_singleton()->globalize_path(dependency_path); } else { absolute_path = plugin_config_dir.plus_file(dependency_path); diff --git a/platform/android/plugin/godot_plugin_jni.cpp b/platform/android/plugin/godot_plugin_jni.cpp index ba3e9fa20f..cf0c02e2bf 100644 --- a/platform/android/plugin/godot_plugin_jni.cpp +++ b/platform/android/plugin/godot_plugin_jni.cpp @@ -43,7 +43,7 @@ extern "C" { JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSingleton(JNIEnv *env, jclass clazz, jstring name, jobject obj) { String singname = jstring_to_string(name, env); - JNISingleton *s = (JNISingleton *)ClassDB::instance("JNISingleton"); + JNISingleton *s = (JNISingleton *)ClassDB::instantiate("JNISingleton"); s->set_instance(env->NewGlobalRef(obj)); jni_singletons[singname] = s; diff --git a/platform/android/vulkan/vulkan_context_android.cpp b/platform/android/vulkan/vulkan_context_android.cpp index 63f2026fae..a031f3beee 100644 --- a/platform/android/vulkan/vulkan_context_android.cpp +++ b/platform/android/vulkan/vulkan_context_android.cpp @@ -36,7 +36,7 @@ const char *VulkanContextAndroid::_get_platform_surface_extension() const { return VK_KHR_ANDROID_SURFACE_EXTENSION_NAME; } -int VulkanContextAndroid::window_create(ANativeWindow *p_window, int p_width, int p_height) { +int VulkanContextAndroid::window_create(ANativeWindow *p_window, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height) { VkAndroidSurfaceCreateInfoKHR createInfo; createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; createInfo.pNext = nullptr; @@ -49,7 +49,7 @@ int VulkanContextAndroid::window_create(ANativeWindow *p_window, int p_width, in ERR_FAIL_V_MSG(-1, "vkCreateAndroidSurfaceKHR failed with error " + itos(err)); } - return _window_create(DisplayServer::MAIN_WINDOW_ID, surface, p_width, p_height); + return _window_create(DisplayServer::MAIN_WINDOW_ID, p_vsync_mode, surface, p_width, p_height); } bool VulkanContextAndroid::_use_validation_layers() { diff --git a/platform/android/vulkan/vulkan_context_android.h b/platform/android/vulkan/vulkan_context_android.h index 5a84eaf8f3..182ce33c97 100644 --- a/platform/android/vulkan/vulkan_context_android.h +++ b/platform/android/vulkan/vulkan_context_android.h @@ -39,7 +39,7 @@ class VulkanContextAndroid : public VulkanContext { virtual const char *_get_platform_surface_extension() const override; public: - int window_create(ANativeWindow *p_window, int p_width, int p_height); + int window_create(ANativeWindow *p_window, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height); VulkanContextAndroid() = default; ~VulkanContextAndroid() override = default; |