summaryrefslogtreecommitdiffstats
path: root/platform
diff options
context:
space:
mode:
Diffstat (limited to 'platform')
-rw-r--r--platform/android/api/api.cpp30
-rw-r--r--platform/android/api/java_class_wrapper.h49
-rw-r--r--platform/android/api/jni_singleton.h5
-rw-r--r--platform/android/display_server_android.cpp8
-rw-r--r--platform/android/export/export_plugin.cpp26
-rw-r--r--platform/android/export/export_plugin.h8
-rw-r--r--platform/android/file_access_android.cpp96
-rw-r--r--platform/android/file_access_android.h9
-rw-r--r--platform/android/file_access_filesystem_jandroid.cpp62
-rw-r--r--platform/android/file_access_filesystem_jandroid.h8
-rw-r--r--platform/android/java/editor/build.gradle2
-rw-r--r--platform/android/java/editor/src/main/java/org/godotengine/editor/EditorMessageDispatcher.kt4
-rw-r--r--platform/android/java/editor/src/main/java/org/godotengine/editor/EditorWindowInfo.kt7
-rw-r--r--platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt45
-rw-r--r--platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.kt2
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/Godot.kt114
-rw-r--r--platform/android/java_class_wrapper.cpp297
-rw-r--r--platform/android/java_godot_lib_jni.cpp11
-rw-r--r--platform/android/java_godot_wrapper.cpp20
-rw-r--r--platform/android/java_godot_wrapper.h5
-rw-r--r--platform/android/jni_utils.cpp22
-rw-r--r--platform/android/jni_utils.h2
-rw-r--r--platform/ios/export/export_plugin.cpp16
-rw-r--r--platform/ios/export/export_plugin.h6
-rw-r--r--platform/linuxbsd/export/export_plugin.cpp9
-rw-r--r--platform/linuxbsd/export/export_plugin.h4
-rw-r--r--platform/linuxbsd/freedesktop_portal_desktop.cpp10
-rw-r--r--platform/linuxbsd/wayland/display_server_wayland.cpp62
-rw-r--r--platform/linuxbsd/x11/display_server_x11.cpp76
-rw-r--r--platform/macos/display_server_macos.mm1
-rw-r--r--platform/macos/export/export_plugin.cpp9
-rw-r--r--platform/macos/export/export_plugin.h4
-rw-r--r--platform/web/api/api.cpp2
-rw-r--r--platform/web/export/export_plugin.cpp9
-rw-r--r--platform/web/export/export_plugin.h6
-rw-r--r--platform/web/javascript_bridge_singleton.cpp2
-rw-r--r--platform/windows/crash_handler_windows_seh.cpp2
-rw-r--r--platform/windows/detect.py93
-rw-r--r--platform/windows/display_server_windows.cpp109
-rw-r--r--platform/windows/display_server_windows.h10
-rw-r--r--platform/windows/export/export_plugin.cpp11
-rw-r--r--platform/windows/export/export_plugin.h6
-rw-r--r--platform/windows/os_windows.cpp11
-rw-r--r--platform/windows/windows_utils.cpp6
44 files changed, 830 insertions, 466 deletions
diff --git a/platform/android/api/api.cpp b/platform/android/api/api.cpp
index 60c369951c..6920f801e5 100644
--- a/platform/android/api/api.cpp
+++ b/platform/android/api/api.cpp
@@ -49,6 +49,7 @@ void register_android_api() {
#endif
GDREGISTER_CLASS(JavaClass);
+ GDREGISTER_CLASS(JavaObject);
GDREGISTER_CLASS(JavaClassWrapper);
Engine::get_singleton()->add_singleton(Engine::Singleton("JavaClassWrapper", JavaClassWrapper::get_singleton()));
}
@@ -59,6 +60,16 @@ void unregister_android_api() {
#endif
}
+void JavaClass::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_java_class_name"), &JavaClass::get_java_class_name);
+ ClassDB::bind_method(D_METHOD("get_java_method_list"), &JavaClass::get_java_method_list);
+ ClassDB::bind_method(D_METHOD("get_java_parent_class"), &JavaClass::get_java_parent_class);
+}
+
+void JavaObject::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_java_class"), &JavaObject::get_java_class);
+}
+
void JavaClassWrapper::_bind_methods() {
ClassDB::bind_method(D_METHOD("wrap", "name"), &JavaClassWrapper::wrap);
}
@@ -69,13 +80,32 @@ Variant JavaClass::callp(const StringName &, const Variant **, int, Callable::Ca
return Variant();
}
+String JavaClass::get_java_class_name() const {
+ return "";
+}
+
+TypedArray<Dictionary> JavaClass::get_java_method_list() const {
+ return TypedArray<Dictionary>();
+}
+
+Ref<JavaClass> JavaClass::get_java_parent_class() const {
+ return Ref<JavaClass>();
+}
+
JavaClass::JavaClass() {
}
+JavaClass::~JavaClass() {
+}
+
Variant JavaObject::callp(const StringName &, const Variant **, int, Callable::CallError &) {
return Variant();
}
+Ref<JavaClass> JavaObject::get_java_class() const {
+ return Ref<JavaClass>();
+}
+
JavaClassWrapper *JavaClassWrapper::singleton = nullptr;
Ref<JavaClass> JavaClassWrapper::wrap(const String &) {
diff --git a/platform/android/api/java_class_wrapper.h b/platform/android/api/java_class_wrapper.h
index e21a331ab9..52df1644be 100644
--- a/platform/android/api/java_class_wrapper.h
+++ b/platform/android/api/java_class_wrapper.h
@@ -32,6 +32,7 @@
#define JAVA_CLASS_WRAPPER_H
#include "core/object/ref_counted.h"
+#include "core/variant/typed_array.h"
#ifdef ANDROID_ENABLED
#include <android/log.h>
@@ -67,6 +68,7 @@ class JavaClass : public RefCounted {
struct MethodInfo {
bool _static = false;
+ bool _constructor = false;
Vector<uint32_t> param_types;
Vector<StringName> param_sigs;
uint32_t return_type = 0;
@@ -174,14 +176,29 @@ class JavaClass : public RefCounted {
bool _call_method(JavaObject *p_instance, const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error, Variant &ret);
friend class JavaClassWrapper;
+ friend class JavaObject;
+ String java_class_name;
+ String java_constructor_name;
HashMap<StringName, List<MethodInfo>> methods;
jclass _class;
#endif
+protected:
+ static void _bind_methods();
+
public:
virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override;
+ String get_java_class_name() const;
+ TypedArray<Dictionary> get_java_method_list() const;
+ Ref<JavaClass> get_java_parent_class() const;
+
+#ifdef ANDROID_ENABLED
+ virtual String to_string() override;
+#endif
+
JavaClass();
+ ~JavaClass();
};
class JavaObject : public RefCounted {
@@ -191,14 +208,24 @@ class JavaObject : public RefCounted {
Ref<JavaClass> base_class;
friend class JavaClass;
- jobject instance;
+ jobject instance = nullptr;
#endif
+protected:
+ static void _bind_methods();
+
public:
virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override;
+ Ref<JavaClass> get_java_class() const;
+
#ifdef ANDROID_ENABLED
- JavaObject(const Ref<JavaClass> &p_base, jobject *p_instance);
+ virtual String to_string() override;
+
+ jobject get_instance() { return instance; }
+
+ JavaObject();
+ JavaObject(const Ref<JavaClass> &p_base, jobject p_instance);
~JavaObject();
#endif
};
@@ -209,13 +236,17 @@ class JavaClassWrapper : public Object {
#ifdef ANDROID_ENABLED
RBMap<String, Ref<JavaClass>> class_cache;
friend class JavaClass;
- jmethodID getDeclaredMethods;
- jmethodID getFields;
- jmethodID getParameterTypes;
- jmethodID getReturnType;
- jmethodID getModifiers;
- jmethodID getName;
+ jmethodID Class_getDeclaredConstructors;
+ jmethodID Class_getDeclaredMethods;
+ jmethodID Class_getFields;
jmethodID Class_getName;
+ jmethodID Class_getSuperclass;
+ jmethodID Constructor_getParameterTypes;
+ jmethodID Constructor_getModifiers;
+ jmethodID Method_getParameterTypes;
+ jmethodID Method_getReturnType;
+ jmethodID Method_getModifiers;
+ jmethodID Method_getName;
jmethodID Field_getName;
jmethodID Field_getModifiers;
jmethodID Field_get;
@@ -242,6 +273,8 @@ public:
Ref<JavaClass> wrap(const String &p_class);
#ifdef ANDROID_ENABLED
+ Ref<JavaClass> wrap_jclass(jclass p_class);
+
JavaClassWrapper(jobject p_activity = nullptr);
#else
JavaClassWrapper();
diff --git a/platform/android/api/jni_singleton.h b/platform/android/api/jni_singleton.h
index 087fd1bace..06afc4eb78 100644
--- a/platform/android/api/jni_singleton.h
+++ b/platform/android/api/jni_singleton.h
@@ -180,6 +180,11 @@ public:
env->DeleteLocalRef(obj);
} break;
+ case Variant::OBJECT: {
+ jobject obj = env->CallObjectMethodA(instance, E->get().method, v);
+ ret = _jobject_to_variant(env, obj);
+ env->DeleteLocalRef(obj);
+ } break;
default: {
env->PopLocalFrame(nullptr);
ERR_FAIL_V(Variant());
diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp
index 8dc0e869d0..5bb520bd73 100644
--- a/platform/android/display_server_android.cpp
+++ b/platform/android/display_server_android.cpp
@@ -455,11 +455,15 @@ Size2i DisplayServerAndroid::window_get_size_with_decorations(DisplayServer::Win
}
void DisplayServerAndroid::window_set_mode(DisplayServer::WindowMode p_mode, DisplayServer::WindowID p_window) {
- // Not supported on Android.
+ OS_Android::get_singleton()->get_godot_java()->enable_immersive_mode(p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN);
}
DisplayServer::WindowMode DisplayServerAndroid::window_get_mode(DisplayServer::WindowID p_window) const {
- return WINDOW_MODE_FULLSCREEN;
+ if (OS_Android::get_singleton()->get_godot_java()->is_in_immersive_mode()) {
+ return WINDOW_MODE_FULLSCREEN;
+ } else {
+ return WINDOW_MODE_MAXIMIZED;
+ }
}
bool DisplayServerAndroid::window_is_maximize_allowed(DisplayServer::WindowID p_window) const {
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index 0fdaca4839..f8ac591a78 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -2002,7 +2002,7 @@ String EditorExportPlatformAndroid::get_device_architecture(int p_index) const {
return devices[p_index].architecture;
}
-Error EditorExportPlatformAndroid::run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) {
+Error EditorExportPlatformAndroid::run(const Ref<EditorExportPreset> &p_preset, int p_device, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) {
ERR_FAIL_INDEX_V(p_device, devices.size(), ERR_INVALID_PARAMETER);
String can_export_error;
@@ -2024,11 +2024,11 @@ Error EditorExportPlatformAndroid::run(const Ref<EditorExportPreset> &p_preset,
}
const bool use_wifi_for_remote_debug = EDITOR_GET("export/android/use_wifi_for_remote_debug");
- const bool use_remote = (p_debug_flags & DEBUG_FLAG_REMOTE_DEBUG) || (p_debug_flags & DEBUG_FLAG_DUMB_CLIENT);
+ const bool use_remote = p_debug_flags.has_flag(DEBUG_FLAG_REMOTE_DEBUG) || p_debug_flags.has_flag(DEBUG_FLAG_DUMB_CLIENT);
const bool use_reverse = devices[p_device].api_level >= 21 && !use_wifi_for_remote_debug;
if (use_reverse) {
- p_debug_flags |= DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST;
+ p_debug_flags.set_flag(DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST);
}
String tmp_export_path = EditorPaths::get_singleton()->get_cache_dir().path_join("tmpexport." + uitos(OS::get_singleton()->get_unix_time()) + ".apk");
@@ -2107,7 +2107,7 @@ Error EditorExportPlatformAndroid::run(const Ref<EditorExportPreset> &p_preset,
OS::get_singleton()->execute(adb, args, &output, &rv, true);
print_verbose(output);
- if (p_debug_flags & DEBUG_FLAG_REMOTE_DEBUG) {
+ if (p_debug_flags.has_flag(DEBUG_FLAG_REMOTE_DEBUG)) {
int dbg_port = EDITOR_GET("network/debug/remote_port");
args.clear();
args.push_back("-s");
@@ -2122,7 +2122,7 @@ Error EditorExportPlatformAndroid::run(const Ref<EditorExportPreset> &p_preset,
print_line("Reverse result: " + itos(rv));
}
- if (p_debug_flags & DEBUG_FLAG_DUMB_CLIENT) {
+ if (p_debug_flags.has_flag(DEBUG_FLAG_DUMB_CLIENT)) {
int fs_port = EDITOR_GET("filesystem/file_server/port");
args.clear();
@@ -2667,7 +2667,7 @@ Error EditorExportPlatformAndroid::save_apk_expansion_file(const Ref<EditorExpor
return err;
}
-void EditorExportPlatformAndroid::get_command_line_flags(const Ref<EditorExportPreset> &p_preset, const String &p_path, int p_flags, Vector<uint8_t> &r_command_line_flags) {
+void EditorExportPlatformAndroid::get_command_line_flags(const Ref<EditorExportPreset> &p_preset, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags, Vector<uint8_t> &r_command_line_flags) {
String cmdline = p_preset->get("command_line/extra_args");
Vector<String> command_line_strings = cmdline.strip_edges().split(" ");
for (int i = 0; i < command_line_strings.size(); i++) {
@@ -2677,7 +2677,7 @@ void EditorExportPlatformAndroid::get_command_line_flags(const Ref<EditorExportP
}
}
- gen_export_flags(command_line_strings, p_flags);
+ command_line_strings.append_array(gen_export_flags(p_flags));
bool apk_expansion = p_preset->get("apk_expansion/enable");
if (apk_expansion) {
@@ -2700,7 +2700,7 @@ void EditorExportPlatformAndroid::get_command_line_flags(const Ref<EditorExportP
bool immersive = p_preset->get("screen/immersive_mode");
if (immersive) {
- command_line_strings.push_back("--use_immersive");
+ command_line_strings.push_back("--fullscreen");
}
bool debug_opengl = p_preset->get("graphics/opengl_debug");
@@ -3000,13 +3000,13 @@ bool EditorExportPlatformAndroid::_is_clean_build_required(const Ref<EditorExpor
return have_plugins_changed || has_build_dir_changed || first_build;
}
-Error EditorExportPlatformAndroid::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+Error EditorExportPlatformAndroid::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags) {
int export_format = int(p_preset->get("gradle_build/export_format"));
bool should_sign = p_preset->get("package/signed");
return export_project_helper(p_preset, p_debug, p_path, export_format, should_sign, p_flags);
}
-Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int export_format, bool should_sign, int p_flags) {
+Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int export_format, bool should_sign, BitField<EditorExportPlatform::DebugFlags> p_flags) {
ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
const String base_dir = p_path.get_base_dir();
@@ -3022,7 +3022,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
bool use_gradle_build = bool(p_preset->get("gradle_build/use_gradle_build"));
String gradle_build_directory = use_gradle_build ? ExportTemplateManager::get_android_build_directory(p_preset) : "";
- bool p_give_internet = p_flags & (DEBUG_FLAG_DUMB_CLIENT | DEBUG_FLAG_REMOTE_DEBUG);
+ bool p_give_internet = p_flags.has_flag(DEBUG_FLAG_DUMB_CLIENT) || p_flags.has_flag(DEBUG_FLAG_REMOTE_DEBUG);
bool apk_expansion = p_preset->get("apk_expansion/enable");
Vector<ABI> enabled_abis = get_enabled_abis(p_preset);
@@ -3127,7 +3127,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
user_data.assets_directory = assets_directory;
user_data.libs_directory = gradle_build_directory.path_join("libs");
user_data.debug = p_debug;
- if (p_flags & DEBUG_FLAG_DUMB_CLIENT) {
+ if (p_flags.has_flag(DEBUG_FLAG_DUMB_CLIENT)) {
err = export_project_files(p_preset, p_debug, ignore_apk_file, &user_data, copy_gradle_so);
} else {
err = export_project_files(p_preset, p_debug, rename_and_store_file_in_gradle_project, &user_data, copy_gradle_so);
@@ -3500,7 +3500,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
}
err = OK;
- if (p_flags & DEBUG_FLAG_DUMB_CLIENT) {
+ if (p_flags.has_flag(DEBUG_FLAG_DUMB_CLIENT)) {
APKExportData ed;
ed.ep = &ep;
ed.apk = unaligned_apk;
diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h
index 97bbd0c7bc..708288fbf4 100644
--- a/platform/android/export/export_plugin.h
+++ b/platform/android/export/export_plugin.h
@@ -214,7 +214,7 @@ public:
virtual String get_device_architecture(int p_index) const override;
- virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) override;
+ virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) override;
virtual Ref<Texture2D> get_run_icon() const override;
@@ -242,7 +242,7 @@ public:
Error save_apk_expansion_file(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path);
- void get_command_line_flags(const Ref<EditorExportPreset> &p_preset, const String &p_path, int p_flags, Vector<uint8_t> &r_command_line_flags);
+ void get_command_line_flags(const Ref<EditorExportPreset> &p_preset, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags, Vector<uint8_t> &r_command_line_flags);
Error sign_apk(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &export_path, EditorProgress &ep);
@@ -253,9 +253,9 @@ public:
static String join_list(const List<String> &p_parts, const String &p_separator);
static String join_abis(const Vector<ABI> &p_parts, const String &p_separator, bool p_use_arch);
- virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override;
+ virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags = 0) override;
- Error export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int export_format, bool should_sign, int p_flags);
+ Error export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int export_format, bool should_sign, BitField<EditorExportPlatform::DebugFlags> p_flags);
virtual void get_platform_features(List<String> *r_features) const override;
diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp
index ae336d6f9d..59b669eabb 100644
--- a/platform/android/file_access_android.cpp
+++ b/platform/android/file_access_android.cpp
@@ -113,87 +113,6 @@ bool FileAccessAndroid::eof_reached() const {
return eof;
}
-uint8_t FileAccessAndroid::get_8() const {
- if (pos >= len) {
- eof = true;
- return 0;
- }
-
- uint8_t byte;
- AAsset_read(asset, &byte, 1);
- pos++;
- return byte;
-}
-
-uint16_t FileAccessAndroid::get_16() const {
- if (pos >= len) {
- eof = true;
- return 0;
- }
-
- uint16_t bytes = 0;
- int r = AAsset_read(asset, &bytes, 2);
-
- if (r >= 0) {
- pos += r;
- if (pos >= len) {
- eof = true;
- }
- }
-
- if (big_endian) {
- bytes = BSWAP16(bytes);
- }
-
- return bytes;
-}
-
-uint32_t FileAccessAndroid::get_32() const {
- if (pos >= len) {
- eof = true;
- return 0;
- }
-
- uint32_t bytes = 0;
- int r = AAsset_read(asset, &bytes, 4);
-
- if (r >= 0) {
- pos += r;
- if (pos >= len) {
- eof = true;
- }
- }
-
- if (big_endian) {
- bytes = BSWAP32(bytes);
- }
-
- return bytes;
-}
-
-uint64_t FileAccessAndroid::get_64() const {
- if (pos >= len) {
- eof = true;
- return 0;
- }
-
- uint64_t bytes = 0;
- int r = AAsset_read(asset, &bytes, 8);
-
- if (r >= 0) {
- pos += r;
- if (pos >= len) {
- eof = true;
- }
- }
-
- if (big_endian) {
- bytes = BSWAP64(bytes);
- }
-
- return bytes;
-}
-
uint64_t FileAccessAndroid::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
@@ -209,6 +128,7 @@ uint64_t FileAccessAndroid::get_buffer(uint8_t *p_dst, uint64_t p_length) const
pos = len;
}
}
+
return r;
}
@@ -220,19 +140,7 @@ void FileAccessAndroid::flush() {
ERR_FAIL();
}
-void FileAccessAndroid::store_8(uint8_t p_dest) {
- ERR_FAIL();
-}
-
-void FileAccessAndroid::store_16(uint16_t p_dest) {
- ERR_FAIL();
-}
-
-void FileAccessAndroid::store_32(uint32_t p_dest) {
- ERR_FAIL();
-}
-
-void FileAccessAndroid::store_64(uint64_t p_dest) {
+void FileAccessAndroid::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL();
}
diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h
index b465a92c78..3224ab50b9 100644
--- a/platform/android/file_access_android.h
+++ b/platform/android/file_access_android.h
@@ -68,19 +68,12 @@ public:
virtual bool eof_reached() const override; // reading passed EOF
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
- virtual uint8_t get_8() const override; // get a byte
- virtual uint16_t get_16() const override;
- virtual uint32_t get_32() const override;
- virtual uint64_t get_64() const override;
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
virtual Error get_error() const override; // get last error
virtual void flush() override;
- virtual void store_8(uint8_t p_dest) override; // store a byte
- virtual void store_16(uint16_t p_dest) override;
- virtual void store_32(uint32_t p_dest) override;
- virtual void store_64(uint64_t p_dest) override;
+ virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual bool file_exists(const String &p_path) override; // return true if a file exists
diff --git a/platform/android/file_access_filesystem_jandroid.cpp b/platform/android/file_access_filesystem_jandroid.cpp
index 9ae48dfb10..8b52a00ed8 100644
--- a/platform/android/file_access_filesystem_jandroid.cpp
+++ b/platform/android/file_access_filesystem_jandroid.cpp
@@ -169,43 +169,6 @@ void FileAccessFilesystemJAndroid::_set_eof(bool eof) {
}
}
-uint8_t FileAccessFilesystemJAndroid::get_8() const {
- ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
- uint8_t byte;
- get_buffer(&byte, 1);
- return byte;
-}
-
-uint16_t FileAccessFilesystemJAndroid::get_16() const {
- ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
- uint16_t bytes = 0;
- get_buffer(reinterpret_cast<uint8_t *>(&bytes), 2);
- if (big_endian) {
- bytes = BSWAP16(bytes);
- }
- return bytes;
-}
-
-uint32_t FileAccessFilesystemJAndroid::get_32() const {
- ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
- uint32_t bytes = 0;
- get_buffer(reinterpret_cast<uint8_t *>(&bytes), 4);
- if (big_endian) {
- bytes = BSWAP32(bytes);
- }
- return bytes;
-}
-
-uint64_t FileAccessFilesystemJAndroid::get_64() const {
- ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
- uint64_t bytes = 0;
- get_buffer(reinterpret_cast<uint8_t *>(&bytes), 8);
- if (big_endian) {
- bytes = BSWAP64(bytes);
- }
- return bytes;
-}
-
String FileAccessFilesystemJAndroid::get_line() const {
ERR_FAIL_COND_V_MSG(!is_open(), String(), "File must be opened before use.");
@@ -271,31 +234,6 @@ uint64_t FileAccessFilesystemJAndroid::get_buffer(uint8_t *p_dst, uint64_t p_len
}
}
-void FileAccessFilesystemJAndroid::store_8(uint8_t p_dest) {
- store_buffer(&p_dest, 1);
-}
-
-void FileAccessFilesystemJAndroid::store_16(uint16_t p_dest) {
- if (big_endian) {
- p_dest = BSWAP16(p_dest);
- }
- store_buffer(reinterpret_cast<uint8_t *>(&p_dest), 2);
-}
-
-void FileAccessFilesystemJAndroid::store_32(uint32_t p_dest) {
- if (big_endian) {
- p_dest = BSWAP32(p_dest);
- }
- store_buffer(reinterpret_cast<uint8_t *>(&p_dest), 4);
-}
-
-void FileAccessFilesystemJAndroid::store_64(uint64_t p_dest) {
- if (big_endian) {
- p_dest = BSWAP64(p_dest);
- }
- store_buffer(reinterpret_cast<uint8_t *>(&p_dest), 8);
-}
-
void FileAccessFilesystemJAndroid::store_buffer(const uint8_t *p_src, uint64_t p_length) {
if (_file_write) {
ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use.");
diff --git a/platform/android/file_access_filesystem_jandroid.h b/platform/android/file_access_filesystem_jandroid.h
index 2795ac02ac..1345b72fa6 100644
--- a/platform/android/file_access_filesystem_jandroid.h
+++ b/platform/android/file_access_filesystem_jandroid.h
@@ -78,20 +78,12 @@ public:
virtual bool eof_reached() const override; ///< reading passed EOF
virtual Error resize(int64_t p_length) override;
- virtual uint8_t get_8() const override; ///< get a byte
- virtual uint16_t get_16() const override;
- virtual uint32_t get_32() const override;
- virtual uint64_t get_64() const override;
virtual String get_line() const override; ///< get a line
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
virtual Error get_error() const override; ///< get last error
virtual void flush() override;
- virtual void store_8(uint8_t p_dest) override; ///< store a byte
- virtual void store_16(uint16_t p_dest) override;
- virtual void store_32(uint32_t p_dest) override;
- virtual void store_64(uint64_t p_dest) override;
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual bool file_exists(const String &p_path) override; ///< return true if a file exists
diff --git a/platform/android/java/editor/build.gradle b/platform/android/java/editor/build.gradle
index f9a3e10680..b8b4233636 100644
--- a/platform/android/java/editor/build.gradle
+++ b/platform/android/java/editor/build.gradle
@@ -37,7 +37,7 @@ ext {
// Return the keystore file used for signing the release build.
getGodotKeystoreFile = { ->
def keyStore = System.getenv("GODOT_ANDROID_SIGN_KEYSTORE")
- if (keyStore == null) {
+ if (keyStore == null || keyStore.isEmpty()) {
return null
}
return file(keyStore)
diff --git a/platform/android/java/editor/src/main/java/org/godotengine/editor/EditorMessageDispatcher.kt b/platform/android/java/editor/src/main/java/org/godotengine/editor/EditorMessageDispatcher.kt
index ba1185d647..b16e62149a 100644
--- a/platform/android/java/editor/src/main/java/org/godotengine/editor/EditorMessageDispatcher.kt
+++ b/platform/android/java/editor/src/main/java/org/godotengine/editor/EditorMessageDispatcher.kt
@@ -176,7 +176,7 @@ internal class EditorMessageDispatcher(private val editor: GodotEditor) {
registerMessenger(senderId, senderMessenger)
// Register ourselves to the sender so that it can communicate with us.
- registerSelfTo(pm, senderMessenger, editor.getEditorId())
+ registerSelfTo(pm, senderMessenger, editor.getEditorWindowInfo().windowId)
}
/**
@@ -185,7 +185,7 @@ internal class EditorMessageDispatcher(private val editor: GodotEditor) {
*/
fun getMessageDispatcherPayload(): Bundle {
return Bundle().apply {
- putInt(KEY_EDITOR_ID, editor.getEditorId())
+ putInt(KEY_EDITOR_ID, editor.getEditorWindowInfo().windowId)
putParcelable(KEY_EDITOR_MESSENGER, Messenger(dispatcherHandler))
}
}
diff --git a/platform/android/java/editor/src/main/java/org/godotengine/editor/EditorWindowInfo.kt b/platform/android/java/editor/src/main/java/org/godotengine/editor/EditorWindowInfo.kt
index d3daa1dbbc..2e1de9a607 100644
--- a/platform/android/java/editor/src/main/java/org/godotengine/editor/EditorWindowInfo.kt
+++ b/platform/android/java/editor/src/main/java/org/godotengine/editor/EditorWindowInfo.kt
@@ -48,7 +48,12 @@ enum class LaunchPolicy {
/**
* Adjacent launches are enabled.
*/
- ADJACENT
+ ADJACENT,
+
+ /**
+ * Launches happen in the same window but start in PiP mode.
+ */
+ SAME_AND_LAUNCH_IN_PIP_MODE
}
/**
diff --git a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt
index 5d6da06f97..405b2fb57f 100644
--- a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt
+++ b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt
@@ -40,6 +40,7 @@ import android.content.pm.PackageManager
import android.os.*
import android.util.Log
import android.view.View
+import android.view.WindowManager
import android.widget.Toast
import androidx.annotation.CallSuper
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
@@ -78,6 +79,8 @@ open class GodotEditor : GodotActivity() {
protected val EXTRA_LAUNCH_IN_PIP = "launch_in_pip_requested"
// Command line arguments
+ private const val FULLSCREEN_ARG = "--fullscreen"
+ private const val FULLSCREEN_ARG_SHORT = "-f"
private const val EDITOR_ARG = "--editor"
private const val EDITOR_ARG_SHORT = "-e"
private const val EDITOR_PROJECT_MANAGER_ARG = "--project-manager"
@@ -98,6 +101,7 @@ open class GodotEditor : GodotActivity() {
private const val ANDROID_WINDOW_AUTO = 0
private const val ANDROID_WINDOW_SAME_AS_EDITOR = 1
private const val ANDROID_WINDOW_SIDE_BY_SIDE_WITH_EDITOR = 2
+ private const val ANDROID_WINDOW_SAME_AS_EDITOR_AND_LAUNCH_IN_PIP_MODE = 3
/**
* Sets of constants to specify the Play window PiP mode.
@@ -116,11 +120,16 @@ open class GodotEditor : GodotActivity() {
override fun getGodotAppLayout() = R.layout.godot_editor_layout
- internal open fun getEditorId() = EDITOR_MAIN_INFO.windowId
+ internal open fun getEditorWindowInfo() = EDITOR_MAIN_INFO
override fun onCreate(savedInstanceState: Bundle?) {
installSplashScreen()
+ // Prevent the editor window from showing in the display cutout
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && getEditorWindowInfo() == EDITOR_MAIN_INFO) {
+ window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
+ }
+
// We exclude certain permissions from the set we request at startup, as they'll be
// requested on demand based on use-cases.
PermissionsUtil.requestManifestPermissions(this, setOf(Manifest.permission.RECORD_AUDIO))
@@ -213,34 +222,53 @@ open class GodotEditor : GodotActivity() {
}
protected fun getNewGodotInstanceIntent(editorWindowInfo: EditorWindowInfo, args: Array<String>): Intent {
+ val updatedArgs = if (editorWindowInfo == EDITOR_MAIN_INFO &&
+ godot?.isInImmersiveMode() == true &&
+ !args.contains(FULLSCREEN_ARG) &&
+ !args.contains(FULLSCREEN_ARG_SHORT)
+ ) {
+ // If we're launching an editor window (project manager or editor) and we're in
+ // fullscreen mode, we want to remain in fullscreen mode.
+ // This doesn't apply to the play / game window since for that window fullscreen is
+ // controlled by the game logic.
+ args + FULLSCREEN_ARG
+ } else {
+ args
+ }
+
val newInstance = Intent()
.setComponent(ComponentName(this, editorWindowInfo.windowClassName))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- .putExtra(EXTRA_COMMAND_LINE_PARAMS, args)
+ .putExtra(EXTRA_COMMAND_LINE_PARAMS, updatedArgs)
val launchPolicy = resolveLaunchPolicyIfNeeded(editorWindowInfo.launchPolicy)
val isPiPAvailable = if (editorWindowInfo.supportsPiPMode && hasPiPSystemFeature()) {
val pipMode = getPlayWindowPiPMode()
pipMode == PLAY_WINDOW_PIP_ENABLED ||
- (pipMode == PLAY_WINDOW_PIP_ENABLED_FOR_SAME_AS_EDITOR && launchPolicy == LaunchPolicy.SAME)
+ (pipMode == PLAY_WINDOW_PIP_ENABLED_FOR_SAME_AS_EDITOR &&
+ (launchPolicy == LaunchPolicy.SAME || launchPolicy == LaunchPolicy.SAME_AND_LAUNCH_IN_PIP_MODE))
} else {
false
}
newInstance.putExtra(EXTRA_PIP_AVAILABLE, isPiPAvailable)
+ var launchInPiP = false
if (launchPolicy == LaunchPolicy.ADJACENT) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Log.v(TAG, "Adding flag for adjacent launch")
newInstance.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT)
}
} else if (launchPolicy == LaunchPolicy.SAME) {
- if (isPiPAvailable &&
- (args.contains(BREAKPOINTS_ARG) || args.contains(BREAKPOINTS_ARG_SHORT))) {
- Log.v(TAG, "Launching in PiP mode because of breakpoints")
- newInstance.putExtra(EXTRA_LAUNCH_IN_PIP, true)
- }
+ launchInPiP = isPiPAvailable &&
+ (updatedArgs.contains(BREAKPOINTS_ARG) || updatedArgs.contains(BREAKPOINTS_ARG_SHORT))
+ } else if (launchPolicy == LaunchPolicy.SAME_AND_LAUNCH_IN_PIP_MODE) {
+ launchInPiP = isPiPAvailable
}
+ if (launchInPiP) {
+ Log.v(TAG, "Launching in PiP mode")
+ newInstance.putExtra(EXTRA_LAUNCH_IN_PIP, launchInPiP)
+ }
return newInstance
}
@@ -381,6 +409,7 @@ open class GodotEditor : GodotActivity() {
when (Integer.parseInt(GodotLib.getEditorSetting("run/window_placement/android_window"))) {
ANDROID_WINDOW_SAME_AS_EDITOR -> LaunchPolicy.SAME
ANDROID_WINDOW_SIDE_BY_SIDE_WITH_EDITOR -> LaunchPolicy.ADJACENT
+ ANDROID_WINDOW_SAME_AS_EDITOR_AND_LAUNCH_IN_PIP_MODE -> LaunchPolicy.SAME_AND_LAUNCH_IN_PIP_MODE
else -> {
// ANDROID_WINDOW_AUTO
defaultLaunchPolicy
diff --git a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.kt b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.kt
index 33fcbf9030..6b4bf255f2 100644
--- a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.kt
+++ b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.kt
@@ -128,7 +128,7 @@ class GodotGame : GodotEditor() {
override fun getGodotAppLayout() = R.layout.godot_game_layout
- override fun getEditorId() = RUN_GAME_INFO.windowId
+ override fun getEditorWindowInfo() = RUN_GAME_INFO
override fun overrideOrientationRequest() = false
diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt
index 49e8ffb008..38bd336e2d 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt
@@ -42,13 +42,16 @@ import android.hardware.Sensor
import android.hardware.SensorManager
import android.os.*
import android.util.Log
+import android.util.TypedValue
import android.view.*
import android.widget.FrameLayout
import androidx.annotation.Keep
import androidx.annotation.StringRes
import androidx.core.view.ViewCompat
+import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsAnimationCompat
import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.WindowInsetsControllerCompat
import com.google.android.vending.expansion.downloader.*
import org.godotengine.godot.error.Error
import org.godotengine.godot.input.GodotEditText
@@ -105,36 +108,26 @@ class Godot(private val context: Context) {
GodotPluginRegistry.getPluginRegistry()
}
- private val accelerometer_enabled = AtomicBoolean(false)
+ private val accelerometerEnabled = AtomicBoolean(false)
private val mAccelerometer: Sensor? by lazy {
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
}
- private val gravity_enabled = AtomicBoolean(false)
+ private val gravityEnabled = AtomicBoolean(false)
private val mGravity: Sensor? by lazy {
mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY)
}
- private val magnetometer_enabled = AtomicBoolean(false)
+ private val magnetometerEnabled = AtomicBoolean(false)
private val mMagnetometer: Sensor? by lazy {
mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)
}
- private val gyroscope_enabled = AtomicBoolean(false)
+ private val gyroscopeEnabled = AtomicBoolean(false)
private val mGyroscope: Sensor? by lazy {
mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)
}
- private val uiChangeListener = View.OnSystemUiVisibilityChangeListener { visibility: Int ->
- if (visibility and View.SYSTEM_UI_FLAG_FULLSCREEN == 0) {
- val decorView = requireActivity().window.decorView
- decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
- View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
- View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
- View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
- }}
-
val tts = GodotTTS(context)
val directoryAccessHandler = DirectoryAccessHandler(context)
val fileAccessHandler = FileAccessHandler(context)
@@ -185,7 +178,7 @@ class Godot(private val context: Context) {
private var xrMode = XRMode.REGULAR
private var expansionPackPath: String = ""
private var useApkExpansion = false
- private var useImmersive = false
+ private val useImmersive = AtomicBoolean(false)
private var useDebugOpengl = false
private var darkMode = false
@@ -254,15 +247,9 @@ class Godot(private val context: Context) {
xrMode = XRMode.OPENXR
} else if (commandLine[i] == "--debug_opengl") {
useDebugOpengl = true
- } else if (commandLine[i] == "--use_immersive") {
- useImmersive = true
- window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
- View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
- View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or // hide nav bar
- View.SYSTEM_UI_FLAG_FULLSCREEN or // hide status bar
- View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
- registerUiChangeListener()
+ } else if (commandLine[i] == "--fullscreen") {
+ useImmersive.set(true)
+ newArgs.add(commandLine[i])
} else if (commandLine[i] == "--use_apk_expansion") {
useApkExpansion = true
} else if (hasExtra && commandLine[i] == "--apk_expansion_md5") {
@@ -336,6 +323,54 @@ class Godot(private val context: Context) {
}
/**
+ * Toggle immersive mode.
+ * Must be called from the UI thread.
+ */
+ private fun enableImmersiveMode(enabled: Boolean, override: Boolean = false) {
+ val activity = getActivity() ?: return
+ val window = activity.window ?: return
+
+ if (!useImmersive.compareAndSet(!enabled, enabled) && !override) {
+ return
+ }
+
+ WindowCompat.setDecorFitsSystemWindows(window, !enabled)
+ val controller = WindowInsetsControllerCompat(window, window.decorView)
+ if (enabled) {
+ controller.hide(WindowInsetsCompat.Type.systemBars())
+ controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
+ } else {
+ val fullScreenThemeValue = TypedValue()
+ val hasStatusBar = if (activity.theme.resolveAttribute(android.R.attr.windowFullscreen, fullScreenThemeValue, true) && fullScreenThemeValue.type == TypedValue.TYPE_INT_BOOLEAN) {
+ fullScreenThemeValue.data == 0
+ } else {
+ // Fallback to checking the editor build
+ !isEditorBuild()
+ }
+
+ val types = if (hasStatusBar) {
+ WindowInsetsCompat.Type.navigationBars() or WindowInsetsCompat.Type.statusBars()
+ } else {
+ WindowInsetsCompat.Type.navigationBars()
+ }
+ controller.show(types)
+ }
+ }
+
+ /**
+ * Invoked from the render thread to toggle the immersive mode.
+ */
+ @Keep
+ private fun nativeEnableImmersiveMode(enabled: Boolean) {
+ runOnUiThread {
+ enableImmersiveMode(enabled)
+ }
+ }
+
+ @Keep
+ fun isInImmersiveMode() = useImmersive.get()
+
+ /**
* Initializes the native layer of the Godot engine.
*
* This must be preceded by [onCreate] and followed by [onInitRenderView] to complete
@@ -552,15 +587,7 @@ class Godot(private val context: Context) {
renderView?.onActivityResumed()
registerSensorsIfNeeded()
- if (useImmersive) {
- val window = requireActivity().window
- window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
- View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
- View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or // hide nav bar
- View.SYSTEM_UI_FLAG_FULLSCREEN or // hide status bar
- View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
- }
+ enableImmersiveMode(useImmersive.get(), true)
for (plugin in pluginRegistry.allPlugins) {
plugin.onMainResume()
}
@@ -571,16 +598,16 @@ class Godot(private val context: Context) {
return
}
- if (accelerometer_enabled.get() && mAccelerometer != null) {
+ if (accelerometerEnabled.get() && mAccelerometer != null) {
mSensorManager.registerListener(godotInputHandler, mAccelerometer, SensorManager.SENSOR_DELAY_GAME)
}
- if (gravity_enabled.get() && mGravity != null) {
+ if (gravityEnabled.get() && mGravity != null) {
mSensorManager.registerListener(godotInputHandler, mGravity, SensorManager.SENSOR_DELAY_GAME)
}
- if (magnetometer_enabled.get() && mMagnetometer != null) {
+ if (magnetometerEnabled.get() && mMagnetometer != null) {
mSensorManager.registerListener(godotInputHandler, mMagnetometer, SensorManager.SENSOR_DELAY_GAME)
}
- if (gyroscope_enabled.get() && mGyroscope != null) {
+ if (gyroscopeEnabled.get() && mGyroscope != null) {
mSensorManager.registerListener(godotInputHandler, mGyroscope, SensorManager.SENSOR_DELAY_GAME)
}
}
@@ -696,10 +723,10 @@ class Godot(private val context: Context) {
Log.v(TAG, "OnGodotMainLoopStarted")
godotMainLoopStarted.set(true)
- accelerometer_enabled.set(java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/sensors/enable_accelerometer")))
- gravity_enabled.set(java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/sensors/enable_gravity")))
- gyroscope_enabled.set(java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/sensors/enable_gyroscope")))
- magnetometer_enabled.set(java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/sensors/enable_magnetometer")))
+ accelerometerEnabled.set(java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/sensors/enable_accelerometer")))
+ gravityEnabled.set(java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/sensors/enable_gravity")))
+ gyroscopeEnabled.set(java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/sensors/enable_gyroscope")))
+ magnetometerEnabled.set(java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/sensors/enable_magnetometer")))
runOnUiThread {
registerSensorsIfNeeded()
@@ -724,11 +751,6 @@ class Godot(private val context: Context) {
primaryHost?.onGodotRestartRequested(this)
}
- private fun registerUiChangeListener() {
- val decorView = requireActivity().window.decorView
- decorView.setOnSystemUiVisibilityChangeListener(uiChangeListener)
- }
-
fun alert(
@StringRes messageResId: Int,
@StringRes titleResId: Int,
diff --git a/platform/android/java_class_wrapper.cpp b/platform/android/java_class_wrapper.cpp
index a309a6ab74..c92717e922 100644
--- a/platform/android/java_class_wrapper.cpp
+++ b/platform/android/java_class_wrapper.cpp
@@ -44,7 +44,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
MethodInfo *method = nullptr;
for (MethodInfo &E : M->value) {
- if (!p_instance && !E._static) {
+ if (!p_instance && !E._static && !E._constructor) {
r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL;
continue;
}
@@ -97,20 +97,24 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
}
} break;
case ARG_TYPE_STRING: {
- if (p_args[i]->get_type() != Variant::STRING) {
+ if (!p_args[i]->is_string()) {
arg_expected = Variant::STRING;
}
} break;
case ARG_TYPE_CLASS: {
- if (p_args[i]->get_type() != Variant::OBJECT) {
+ if (p_args[i]->get_type() != Variant::OBJECT && p_args[i]->get_type() != Variant::NIL) {
arg_expected = Variant::OBJECT;
} else {
Ref<RefCounted> ref = *p_args[i];
- if (!ref.is_null()) {
+ if (ref.is_valid()) {
if (Object::cast_to<JavaObject>(ref.ptr())) {
Ref<JavaObject> jo = ref;
//could be faster
- jclass c = env->FindClass(E.param_sigs[i].operator String().utf8().get_data());
+ String cn = E.param_sigs[i].operator String();
+ if (cn.begins_with("L") && cn.ends_with(";")) {
+ cn = cn.substr(1, cn.length() - 2);
+ }
+ jclass c = env->FindClass(cn.utf8().get_data());
if (!c || !env->IsInstanceOf(jo->instance, c)) {
arg_expected = Variant::OBJECT;
} else {
@@ -458,7 +462,9 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
} break;
default: {
jobject obj;
- if (method->_static) {
+ if (method->_constructor) {
+ obj = env->NewObject(_class, method->method, argv);
+ } else if (method->_static) {
obj = env->CallStaticObjectMethodA(_class, method->method, argv);
} else {
obj = env->CallObjectMethodA(p_instance->instance, method->method, argv);
@@ -487,7 +493,9 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
Variant JavaClass::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
Variant ret;
- bool found = _call_method(nullptr, p_method, p_args, p_argcount, r_error, ret);
+
+ String method = (p_method == java_constructor_name) ? "<init>" : p_method;
+ bool found = _call_method(nullptr, method, p_args, p_argcount, r_error, ret);
if (found) {
return ret;
}
@@ -495,19 +503,156 @@ Variant JavaClass::callp(const StringName &p_method, const Variant **p_args, int
return RefCounted::callp(p_method, p_args, p_argcount, r_error);
}
+String JavaClass::get_java_class_name() const {
+ return java_class_name;
+}
+
+TypedArray<Dictionary> JavaClass::get_java_method_list() const {
+ TypedArray<Dictionary> method_list;
+
+ for (const KeyValue<StringName, List<MethodInfo>> &item : methods) {
+ for (const MethodInfo &mi : item.value) {
+ Dictionary method;
+
+ method["name"] = mi._constructor ? java_constructor_name : String(item.key);
+ method["id"] = (uint64_t)mi.method;
+ method["default_args"] = Array();
+ method["flags"] = METHOD_FLAGS_DEFAULT & (mi._static || mi._constructor ? METHOD_FLAG_STATIC : METHOD_FLAG_NORMAL);
+
+ {
+ Array a;
+
+ for (uint32_t argtype : mi.param_types) {
+ Dictionary d;
+
+ Variant::Type t = Variant::NIL;
+ float likelihood = 0.0;
+ _convert_to_variant_type(argtype, t, likelihood);
+ d["type"] = t;
+ if (t == Variant::OBJECT) {
+ d["hint"] = PROPERTY_HINT_RESOURCE_TYPE;
+ d["hint_string"] = "JavaObject";
+ } else {
+ d["hint"] = 0;
+ d["hint_string"] = "";
+ }
+
+ a.push_back(d);
+ }
+
+ method["args"] = a;
+ }
+
+ {
+ Dictionary d;
+
+ if (mi._constructor) {
+ d["type"] = Variant::OBJECT;
+ d["hint"] = PROPERTY_HINT_RESOURCE_TYPE;
+ d["hint_string"] = "JavaObject";
+ } else {
+ Variant::Type t = Variant::NIL;
+ float likelihood = 0.0;
+ _convert_to_variant_type(mi.return_type, t, likelihood);
+ d["type"] = t;
+ if (t == Variant::OBJECT) {
+ d["hint"] = PROPERTY_HINT_RESOURCE_TYPE;
+ d["hint_string"] = "JavaObject";
+ } else {
+ d["hint"] = 0;
+ d["hint_string"] = "";
+ }
+ }
+
+ method["return_type"] = d;
+ }
+
+ method_list.push_back(method);
+ }
+ }
+
+ return method_list;
+}
+
+Ref<JavaClass> JavaClass::get_java_parent_class() const {
+ ERR_FAIL_NULL_V(_class, Ref<JavaClass>());
+
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_NULL_V(env, Ref<JavaClass>());
+
+ jclass superclass = (jclass)env->CallObjectMethod(_class, JavaClassWrapper::singleton->Class_getSuperclass);
+ if (!superclass) {
+ return Ref<JavaClass>();
+ }
+
+ Ref<JavaClass> ret = JavaClassWrapper::singleton->wrap_jclass(superclass);
+ env->DeleteLocalRef(superclass);
+ return ret;
+}
+
+String JavaClass::to_string() {
+ return "<JavaClass:" + java_class_name + ">";
+}
+
JavaClass::JavaClass() {
}
+JavaClass::~JavaClass() {
+ if (_class) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_NULL(env);
+
+ env->DeleteGlobalRef(_class);
+ }
+}
+
/////////////////////
Variant JavaObject::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
- return Variant();
+ if (instance) {
+ Ref<JavaClass> c = base_class;
+ while (c.is_valid()) {
+ Variant ret;
+ bool found = c->_call_method(this, p_method, p_args, p_argcount, r_error, ret);
+ if (found) {
+ return ret;
+ }
+ c = c->get_java_parent_class();
+ }
+ }
+
+ return RefCounted::callp(p_method, p_args, p_argcount, r_error);
+}
+
+Ref<JavaClass> JavaObject::get_java_class() const {
+ return base_class;
}
-JavaObject::JavaObject(const Ref<JavaClass> &p_base, jobject *p_instance) {
+String JavaObject::to_string() {
+ if (base_class.is_valid() && instance) {
+ return "<JavaObject:" + base_class->java_class_name + " \"" + (String)call("toString") + "\">";
+ }
+ return RefCounted::to_string();
+}
+
+JavaObject::JavaObject() {
+}
+
+JavaObject::JavaObject(const Ref<JavaClass> &p_base, jobject p_instance) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_NULL(env);
+
+ base_class = p_base;
+ instance = env->NewGlobalRef(p_instance);
}
JavaObject::~JavaObject() {
+ if (instance) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_NULL(env);
+
+ env->DeleteGlobalRef(instance);
+ }
}
////////////////////
@@ -649,6 +794,16 @@ bool JavaClass::_convert_object_to_variant(JNIEnv *env, jobject obj, Variant &va
return true;
} break;
case ARG_TYPE_CLASS: {
+ jclass java_class = env->GetObjectClass(obj);
+ Ref<JavaClass> java_class_wrapped = JavaClassWrapper::singleton->wrap_jclass(java_class);
+ env->DeleteLocalRef(java_class);
+
+ if (java_class_wrapped.is_valid()) {
+ Ref<JavaObject> ret = Ref<JavaObject>(memnew(JavaObject(java_class_wrapped, obj)));
+ var = ret;
+ return true;
+ }
+
return false;
} break;
case ARG_ARRAY_BIT | ARG_TYPE_VOID: {
@@ -966,43 +1121,67 @@ bool JavaClass::_convert_object_to_variant(JNIEnv *env, jobject obj, Variant &va
}
Ref<JavaClass> JavaClassWrapper::wrap(const String &p_class) {
- if (class_cache.has(p_class)) {
- return class_cache[p_class];
+ String class_name_dots = p_class.replace("/", ".");
+ if (class_cache.has(class_name_dots)) {
+ return class_cache[class_name_dots];
}
JNIEnv *env = get_jni_env();
ERR_FAIL_NULL_V(env, Ref<JavaClass>());
- jclass bclass = env->FindClass(p_class.utf8().get_data());
+ jclass bclass = env->FindClass(class_name_dots.replace(".", "/").utf8().get_data());
ERR_FAIL_NULL_V(bclass, Ref<JavaClass>());
- jobjectArray methods = (jobjectArray)env->CallObjectMethod(bclass, getDeclaredMethods);
+ jobjectArray constructors = (jobjectArray)env->CallObjectMethod(bclass, Class_getDeclaredConstructors);
+ ERR_FAIL_NULL_V(constructors, Ref<JavaClass>());
+ jobjectArray methods = (jobjectArray)env->CallObjectMethod(bclass, Class_getDeclaredMethods);
ERR_FAIL_NULL_V(methods, Ref<JavaClass>());
Ref<JavaClass> java_class = memnew(JavaClass);
+ java_class->java_class_name = class_name_dots;
+ Vector<String> class_name_parts = class_name_dots.split(".");
+ java_class->java_constructor_name = class_name_parts[class_name_parts.size() - 1];
+ java_class->_class = (jclass)env->NewGlobalRef(bclass);
+ class_cache[class_name_dots] = java_class;
+
+ LocalVector<jobject> methods_and_constructors;
+ int constructor_count = env->GetArrayLength(constructors);
+ int method_count = env->GetArrayLength(methods);
+ methods_and_constructors.resize(method_count + constructor_count);
+ for (int i = 0; i < constructor_count; i++) {
+ methods_and_constructors[i] = env->GetObjectArrayElement(constructors, i);
+ }
+ for (int i = 0; i < method_count; i++) {
+ methods_and_constructors[constructor_count + i] = env->GetObjectArrayElement(methods, i);
+ }
- int count = env->GetArrayLength(methods);
-
- for (int i = 0; i < count; i++) {
- jobject obj = env->GetObjectArrayElement(methods, i);
+ for (int i = 0; i < (int)methods_and_constructors.size(); i++) {
+ jobject obj = methods_and_constructors[i];
ERR_CONTINUE(!obj);
- jstring name = (jstring)env->CallObjectMethod(obj, getName);
- String str_method = jstring_to_string(name, env);
- env->DeleteLocalRef(name);
+ bool is_constructor = i < constructor_count;
+
+ String str_method;
+ if (is_constructor) {
+ str_method = "<init>";
+ } else {
+ jstring name = (jstring)env->CallObjectMethod(obj, Method_getName);
+ str_method = jstring_to_string(name, env);
+ env->DeleteLocalRef(name);
+ }
Vector<String> params;
- jint mods = env->CallIntMethod(obj, getModifiers);
+ jint mods = env->CallIntMethod(obj, is_constructor ? Constructor_getModifiers : Method_getModifiers);
if (!(mods & 0x0001)) {
env->DeleteLocalRef(obj);
continue; //not public bye
}
- jobjectArray param_types = (jobjectArray)env->CallObjectMethod(obj, getParameterTypes);
- int count2 = env->GetArrayLength(param_types);
+ jobjectArray param_types = (jobjectArray)env->CallObjectMethod(obj, is_constructor ? Constructor_getParameterTypes : Method_getParameterTypes);
+ int count = env->GetArrayLength(param_types);
if (!java_class->methods.has(str_method)) {
java_class->methods[str_method] = List<JavaClass::MethodInfo>();
@@ -1010,10 +1189,11 @@ Ref<JavaClass> JavaClassWrapper::wrap(const String &p_class) {
JavaClass::MethodInfo mi;
mi._static = (mods & 0x8) != 0;
+ mi._constructor = is_constructor;
bool valid = true;
String signature = "(";
- for (int j = 0; j < count2; j++) {
+ for (int j = 0; j < count; j++) {
jobject obj2 = env->GetObjectArrayElement(param_types, j);
String strsig;
uint32_t sig = 0;
@@ -1029,7 +1209,7 @@ Ref<JavaClass> JavaClassWrapper::wrap(const String &p_class) {
}
if (!valid) {
- print_line("Method can't be bound (unsupported arguments): " + p_class + "::" + str_method);
+ print_line("Method can't be bound (unsupported arguments): " + class_name_dots + "::" + str_method);
env->DeleteLocalRef(obj);
env->DeleteLocalRef(param_types);
continue;
@@ -1037,21 +1217,28 @@ Ref<JavaClass> JavaClassWrapper::wrap(const String &p_class) {
signature += ")";
- jobject return_type = (jobject)env->CallObjectMethod(obj, getReturnType);
+ if (is_constructor) {
+ signature += "V";
+ mi.return_type = JavaClass::ARG_TYPE_CLASS;
+ } else {
+ jobject return_type = (jobject)env->CallObjectMethod(obj, Method_getReturnType);
+
+ String strsig;
+ uint32_t sig = 0;
+ if (!_get_type_sig(env, return_type, sig, strsig)) {
+ print_line("Method can't be bound (unsupported return type): " + class_name_dots + "::" + str_method);
+ env->DeleteLocalRef(obj);
+ env->DeleteLocalRef(param_types);
+ env->DeleteLocalRef(return_type);
+ continue;
+ }
+
+ signature += strsig;
+ mi.return_type = sig;
- String strsig;
- uint32_t sig = 0;
- if (!_get_type_sig(env, return_type, sig, strsig)) {
- print_line("Method can't be bound (unsupported return type): " + p_class + "::" + str_method);
- env->DeleteLocalRef(obj);
- env->DeleteLocalRef(param_types);
env->DeleteLocalRef(return_type);
- continue;
}
- signature += strsig;
- mi.return_type = sig;
-
bool discard = false;
for (List<JavaClass::MethodInfo>::Element *E = java_class->methods[str_method].front(); E; E = E->next()) {
@@ -1103,14 +1290,14 @@ Ref<JavaClass> JavaClassWrapper::wrap(const String &p_class) {
env->DeleteLocalRef(obj);
env->DeleteLocalRef(param_types);
- env->DeleteLocalRef(return_type);
}
+ env->DeleteLocalRef(constructors);
env->DeleteLocalRef(methods);
- jobjectArray fields = (jobjectArray)env->CallObjectMethod(bclass, getFields);
+ jobjectArray fields = (jobjectArray)env->CallObjectMethod(bclass, Class_getFields);
- count = env->GetArrayLength(fields);
+ int count = env->GetArrayLength(fields);
for (int i = 0; i < count; i++) {
jobject obj = env->GetObjectArrayElement(fields, i);
@@ -1146,7 +1333,18 @@ Ref<JavaClass> JavaClassWrapper::wrap(const String &p_class) {
env->DeleteLocalRef(fields);
- return Ref<JavaClass>();
+ return java_class;
+}
+
+Ref<JavaClass> JavaClassWrapper::wrap_jclass(jclass p_class) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_NULL_V(env, Ref<JavaClass>());
+
+ jstring class_name = (jstring)env->CallObjectMethod(p_class, Class_getName);
+ String class_name_string = jstring_to_string(class_name, env);
+ env->DeleteLocalRef(class_name);
+
+ return wrap(class_name_string);
}
JavaClassWrapper *JavaClassWrapper::singleton = nullptr;
@@ -1158,16 +1356,23 @@ JavaClassWrapper::JavaClassWrapper(jobject p_activity) {
ERR_FAIL_NULL(env);
jclass bclass = env->FindClass("java/lang/Class");
- getDeclaredMethods = env->GetMethodID(bclass, "getDeclaredMethods", "()[Ljava/lang/reflect/Method;");
- getFields = env->GetMethodID(bclass, "getFields", "()[Ljava/lang/reflect/Field;");
+ Class_getDeclaredConstructors = env->GetMethodID(bclass, "getDeclaredConstructors", "()[Ljava/lang/reflect/Constructor;");
+ Class_getDeclaredMethods = env->GetMethodID(bclass, "getDeclaredMethods", "()[Ljava/lang/reflect/Method;");
+ Class_getFields = env->GetMethodID(bclass, "getFields", "()[Ljava/lang/reflect/Field;");
Class_getName = env->GetMethodID(bclass, "getName", "()Ljava/lang/String;");
+ Class_getSuperclass = env->GetMethodID(bclass, "getSuperclass", "()Ljava/lang/Class;");
+ env->DeleteLocalRef(bclass);
+
+ bclass = env->FindClass("java/lang/reflect/Constructor");
+ Constructor_getParameterTypes = env->GetMethodID(bclass, "getParameterTypes", "()[Ljava/lang/Class;");
+ Constructor_getModifiers = env->GetMethodID(bclass, "getModifiers", "()I");
env->DeleteLocalRef(bclass);
bclass = env->FindClass("java/lang/reflect/Method");
- getParameterTypes = env->GetMethodID(bclass, "getParameterTypes", "()[Ljava/lang/Class;");
- getReturnType = env->GetMethodID(bclass, "getReturnType", "()Ljava/lang/Class;");
- getName = env->GetMethodID(bclass, "getName", "()Ljava/lang/String;");
- getModifiers = env->GetMethodID(bclass, "getModifiers", "()I");
+ Method_getParameterTypes = env->GetMethodID(bclass, "getParameterTypes", "()[Ljava/lang/Class;");
+ Method_getReturnType = env->GetMethodID(bclass, "getReturnType", "()Ljava/lang/Class;");
+ Method_getName = env->GetMethodID(bclass, "getName", "()Ljava/lang/String;");
+ Method_getModifiers = env->GetMethodID(bclass, "getModifiers", "()I");
env->DeleteLocalRef(bclass);
bclass = env->FindClass("java/lang/reflect/Field");
diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp
index 1114969de8..390677df22 100644
--- a/platform/android/java_godot_lib_jni.cpp
+++ b/platform/android/java_godot_lib_jni.cpp
@@ -51,7 +51,10 @@
#include "core/config/project_settings.h"
#include "core/input/input.h"
#include "main/main.h"
+
+#ifndef _3D_DISABLED
#include "servers/xr_server.h"
+#endif // _3D_DISABLED
#ifdef TOOLS_ENABLED
#include "editor/editor_settings.h"
@@ -271,14 +274,16 @@ JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env,
}
if (step.get() == STEP_SHOW_LOGO) {
- bool xr_enabled;
+ bool xr_enabled = false;
+#ifndef _3D_DISABLED
+ // Unlike PCVR, there's no additional 2D screen onto which to render the boot logo,
+ // so we skip this step if xr is enabled.
if (XRServer::get_xr_mode() == XRServer::XRMODE_DEFAULT) {
xr_enabled = GLOBAL_GET("xr/shaders/enabled");
} else {
xr_enabled = XRServer::get_xr_mode() == XRServer::XRMODE_ON;
}
- // Unlike PCVR, there's no additional 2D screen onto which to render the boot logo,
- // so we skip this step if xr is enabled.
+#endif // _3D_DISABLED
if (!xr_enabled) {
Main::setup_boot_logo();
}
diff --git a/platform/android/java_godot_wrapper.cpp b/platform/android/java_godot_wrapper.cpp
index f1759af54a..d3b30e4589 100644
--- a/platform/android/java_godot_wrapper.cpp
+++ b/platform/android/java_godot_wrapper.cpp
@@ -86,6 +86,8 @@ GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_
_has_feature = p_env->GetMethodID(godot_class, "hasFeature", "(Ljava/lang/String;)Z");
_sign_apk = p_env->GetMethodID(godot_class, "nativeSignApk", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I");
_verify_apk = p_env->GetMethodID(godot_class, "nativeVerifyApk", "(Ljava/lang/String;)I");
+ _enable_immersive_mode = p_env->GetMethodID(godot_class, "nativeEnableImmersiveMode", "(Z)V");
+ _is_in_immersive_mode = p_env->GetMethodID(godot_class, "isInImmersiveMode", "()Z");
}
GodotJavaWrapper::~GodotJavaWrapper() {
@@ -465,3 +467,21 @@ Error GodotJavaWrapper::verify_apk(const String &p_apk_path) {
return ERR_UNCONFIGURED;
}
}
+
+void GodotJavaWrapper::enable_immersive_mode(bool p_enabled) {
+ if (_enable_immersive_mode) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_NULL(env);
+ env->CallVoidMethod(godot_instance, _enable_immersive_mode, p_enabled);
+ }
+}
+
+bool GodotJavaWrapper::is_in_immersive_mode() {
+ if (_is_in_immersive_mode) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_NULL_V(env, false);
+ return env->CallBooleanMethod(godot_instance, _is_in_immersive_mode);
+ } else {
+ return false;
+ }
+}
diff --git a/platform/android/java_godot_wrapper.h b/platform/android/java_godot_wrapper.h
index 6b66565981..51d7f98541 100644
--- a/platform/android/java_godot_wrapper.h
+++ b/platform/android/java_godot_wrapper.h
@@ -77,6 +77,8 @@ private:
jmethodID _has_feature = nullptr;
jmethodID _sign_apk = nullptr;
jmethodID _verify_apk = nullptr;
+ jmethodID _enable_immersive_mode = nullptr;
+ jmethodID _is_in_immersive_mode = nullptr;
public:
GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_godot_instance);
@@ -122,6 +124,9 @@ public:
// Sign and verify apks
Error sign_apk(const String &p_input_path, const String &p_output_path, const String &p_keystore_path, const String &p_keystore_user, const String &p_keystore_password);
Error verify_apk(const String &p_apk_path);
+
+ void enable_immersive_mode(bool p_enabled);
+ bool is_in_immersive_mode();
};
#endif // JAVA_GODOT_WRAPPER_H
diff --git a/platform/android/jni_utils.cpp b/platform/android/jni_utils.cpp
index fc97d6eca4..4c17d03c60 100644
--- a/platform/android/jni_utils.cpp
+++ b/platform/android/jni_utils.cpp
@@ -30,6 +30,8 @@
#include "jni_utils.h"
+#include "api/java_class_wrapper.h"
+
jvalret _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant *p_arg, bool force_jobject) {
jvalret v;
@@ -185,6 +187,16 @@ jvalret _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant *p_a
v.obj = arr;
} break;
+ case Variant::OBJECT: {
+ Ref<JavaObject> generic_object = *p_arg;
+ if (generic_object.is_valid()) {
+ jobject obj = env->NewLocalRef(generic_object->get_instance());
+ v.val.l = obj;
+ v.obj = obj;
+ } else {
+ v.val.i = 0;
+ }
+ } break;
default: {
v.val.i = 0;
@@ -358,9 +370,11 @@ Variant _jobject_to_variant(JNIEnv *env, jobject obj) {
return ret;
}
+ Ref<JavaObject> generic_object(memnew(JavaObject(JavaClassWrapper::get_singleton()->wrap(name), obj)));
+
env->DeleteLocalRef(c);
- return Variant();
+ return generic_object;
}
Variant::Type get_jni_type(const String &p_type) {
@@ -395,10 +409,10 @@ Variant::Type get_jni_type(const String &p_type) {
idx++;
}
- return Variant::NIL;
+ return Variant::OBJECT;
}
-const char *get_jni_sig(const String &p_type) {
+String get_jni_sig(const String &p_type) {
static struct {
const char *name;
const char *sig;
@@ -430,5 +444,5 @@ const char *get_jni_sig(const String &p_type) {
idx++;
}
- return "Ljava/lang/Object;";
+ return "L" + p_type.replace(".", "/") + ";";
}
diff --git a/platform/android/jni_utils.h b/platform/android/jni_utils.h
index c608f9ebaa..631acd1cef 100644
--- a/platform/android/jni_utils.h
+++ b/platform/android/jni_utils.h
@@ -52,6 +52,6 @@ Variant _jobject_to_variant(JNIEnv *env, jobject obj);
Variant::Type get_jni_type(const String &p_type);
-const char *get_jni_sig(const String &p_type);
+String get_jni_sig(const String &p_type);
#endif // JNI_UTILS_H
diff --git a/platform/ios/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp
index e4b5392c4e..b99e825540 100644
--- a/platform/ios/export/export_plugin.cpp
+++ b/platform/ios/export/export_plugin.cpp
@@ -2017,11 +2017,11 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset>
return OK;
}
-Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags) {
return _export_project_helper(p_preset, p_debug, p_path, p_flags, false, false);
}
-Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags, bool p_simulator, bool p_oneclick) {
+Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags, bool p_simulator, bool p_oneclick) {
ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
const String dest_dir = p_path.get_base_dir() + "/";
@@ -2983,7 +2983,7 @@ void EditorExportPlatformIOS::_update_preset_status() {
}
#endif
-Error EditorExportPlatformIOS::run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) {
+Error EditorExportPlatformIOS::run(const Ref<EditorExportPreset> &p_preset, int p_device, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) {
#ifdef MACOS_ENABLED
ERR_FAIL_INDEX_V(p_device, devices.size(), ERR_INVALID_PARAMETER);
@@ -3029,11 +3029,11 @@ Error EditorExportPlatformIOS::run(const Ref<EditorExportPreset> &p_preset, int
String host = EDITOR_GET("network/debug/remote_host");
int remote_port = (int)EDITOR_GET("network/debug/remote_port");
- if (p_debug_flags & DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST) {
+ if (p_debug_flags.has_flag(DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST)) {
host = "localhost";
}
- if (p_debug_flags & DEBUG_FLAG_DUMB_CLIENT) {
+ if (p_debug_flags.has_flag(DEBUG_FLAG_DUMB_CLIENT)) {
int port = EDITOR_GET("filesystem/file_server/port");
String passwd = EDITOR_GET("filesystem/file_server/password");
cmd_args_list.push_back("--remote-fs");
@@ -3044,7 +3044,7 @@ Error EditorExportPlatformIOS::run(const Ref<EditorExportPreset> &p_preset, int
}
}
- if (p_debug_flags & DEBUG_FLAG_REMOTE_DEBUG) {
+ if (p_debug_flags.has_flag(DEBUG_FLAG_REMOTE_DEBUG)) {
cmd_args_list.push_back("--remote-debug");
cmd_args_list.push_back(get_debug_protocol() + host + ":" + String::num(remote_port));
@@ -3066,11 +3066,11 @@ Error EditorExportPlatformIOS::run(const Ref<EditorExportPreset> &p_preset, int
}
}
- if (p_debug_flags & DEBUG_FLAG_VIEW_COLLISIONS) {
+ if (p_debug_flags.has_flag(DEBUG_FLAG_VIEW_COLLISIONS)) {
cmd_args_list.push_back("--debug-collisions");
}
- if (p_debug_flags & DEBUG_FLAG_VIEW_NAVIGATION) {
+ if (p_debug_flags.has_flag(DEBUG_FLAG_VIEW_NAVIGATION)) {
cmd_args_list.push_back("--debug-navigation");
}
diff --git a/platform/ios/export/export_plugin.h b/platform/ios/export/export_plugin.h
index 1964906c27..db7c0553dd 100644
--- a/platform/ios/export/export_plugin.h
+++ b/platform/ios/export/export_plugin.h
@@ -146,7 +146,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
Error _export_additional_assets(const Ref<EditorExportPreset> &p_preset, const String &p_out_dir, const Vector<SharedObject> &p_libraries, Vector<IOSExportAsset> &r_exported_assets);
Error _export_ios_plugins(const Ref<EditorExportPreset> &p_preset, IOSConfigData &p_config_data, const String &dest_dir, Vector<IOSExportAsset> &r_exported_assets, bool p_debug);
- Error _export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags, bool p_simulator, bool p_oneclick);
+ Error _export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags, bool p_simulator, bool p_oneclick);
bool is_package_name_valid(const String &p_package, String *r_error = nullptr) const;
@@ -169,7 +169,7 @@ public:
virtual Ref<ImageTexture> get_option_icon(int p_index) const override;
virtual String get_option_label(int p_index) const override;
virtual String get_option_tooltip(int p_index) const override;
- virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) override;
+ virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) override;
virtual bool poll_export() override {
bool dc = devices_changed.is_set();
@@ -202,7 +202,7 @@ public:
return list;
}
- virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override;
+ virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags = 0) override;
virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const override;
virtual bool has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const override;
diff --git a/platform/linuxbsd/export/export_plugin.cpp b/platform/linuxbsd/export/export_plugin.cpp
index 0032b898d2..69ba742f72 100644
--- a/platform/linuxbsd/export/export_plugin.cpp
+++ b/platform/linuxbsd/export/export_plugin.cpp
@@ -60,7 +60,7 @@ Error EditorExportPlatformLinuxBSD::_export_debug_script(const Ref<EditorExportP
return OK;
}
-Error EditorExportPlatformLinuxBSD::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+Error EditorExportPlatformLinuxBSD::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags) {
String custom_debug = p_preset->get("custom_template/debug");
String custom_release = p_preset->get("custom_template/release");
String arch = p_preset->get("binary_format/architecture");
@@ -458,7 +458,7 @@ void EditorExportPlatformLinuxBSD::cleanup() {
cleanup_commands.clear();
}
-Error EditorExportPlatformLinuxBSD::run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) {
+Error EditorExportPlatformLinuxBSD::run(const Ref<EditorExportPreset> &p_preset, int p_device, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) {
cleanup();
if (p_device) { // Stop command, cleanup only.
return OK;
@@ -512,8 +512,7 @@ Error EditorExportPlatformLinuxBSD::run(const Ref<EditorExportPreset> &p_preset,
String cmd_args;
{
- Vector<String> cmd_args_list;
- gen_debug_flags(cmd_args_list, p_debug_flags);
+ Vector<String> cmd_args_list = gen_export_flags(p_debug_flags);
for (int i = 0; i < cmd_args_list.size(); i++) {
if (i != 0) {
cmd_args += " ";
@@ -522,7 +521,7 @@ Error EditorExportPlatformLinuxBSD::run(const Ref<EditorExportPreset> &p_preset,
}
}
- const bool use_remote = (p_debug_flags & DEBUG_FLAG_REMOTE_DEBUG) || (p_debug_flags & DEBUG_FLAG_DUMB_CLIENT);
+ const bool use_remote = p_debug_flags.has_flag(DEBUG_FLAG_REMOTE_DEBUG) || p_debug_flags.has_flag(DEBUG_FLAG_DUMB_CLIENT);
int dbg_port = EditorSettings::get_singleton()->get("network/debug/remote_port");
print_line("Creating temporary directory...");
diff --git a/platform/linuxbsd/export/export_plugin.h b/platform/linuxbsd/export/export_plugin.h
index bbc55b82ce..1d9ef01d1a 100644
--- a/platform/linuxbsd/export/export_plugin.h
+++ b/platform/linuxbsd/export/export_plugin.h
@@ -76,7 +76,7 @@ public:
virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override;
virtual bool get_export_option_visibility(const EditorExportPreset *p_preset, const String &p_option) const override;
virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const override;
- virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override;
+ virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags = 0) override;
virtual String get_template_file_name(const String &p_target, const String &p_arch) const override;
virtual Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) override;
virtual bool is_executable(const String &p_path) const override;
@@ -87,7 +87,7 @@ public:
virtual int get_options_count() const override;
virtual String get_option_label(int p_index) const override;
virtual String get_option_tooltip(int p_index) const override;
- virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) override;
+ virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) override;
virtual void cleanup() override;
EditorExportPlatformLinuxBSD();
diff --git a/platform/linuxbsd/freedesktop_portal_desktop.cpp b/platform/linuxbsd/freedesktop_portal_desktop.cpp
index 2b98fda0d5..94a748e414 100644
--- a/platform/linuxbsd/freedesktop_portal_desktop.cpp
+++ b/platform/linuxbsd/freedesktop_portal_desktop.cpp
@@ -210,7 +210,15 @@ void FreeDesktopPortalDesktop::append_dbus_dict_filters(DBusMessageIter *p_iter,
append_dbus_string(&struct_iter, p_filter_names[i]);
dbus_message_iter_open_container(&struct_iter, DBUS_TYPE_ARRAY, "(us)", &array_iter);
- const String &flt = p_filter_exts[i];
+ const String &flt_orig = p_filter_exts[i];
+ String flt;
+ for (int j = 0; j < flt_orig.length(); j++) {
+ if (is_unicode_letter(flt_orig[j])) {
+ flt += vformat("[%c%c]", String::char_lowercase(flt_orig[j]), String::char_uppercase(flt_orig[j]));
+ } else {
+ flt += flt_orig[j];
+ }
+ }
int filter_slice_count = flt.get_slice_count(",");
for (int j = 0; j < filter_slice_count; j++) {
dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, nullptr, &array_struct_iter);
diff --git a/platform/linuxbsd/wayland/display_server_wayland.cpp b/platform/linuxbsd/wayland/display_server_wayland.cpp
index 93096fcdcc..2074d7228d 100644
--- a/platform/linuxbsd/wayland/display_server_wayland.cpp
+++ b/platform/linuxbsd/wayland/display_server_wayland.cpp
@@ -480,7 +480,7 @@ String DisplayServerWayland::clipboard_get_primary() const {
for (String mime : text_mimes) {
if (wayland_thread.primary_has_mime(mime)) {
print_verbose(vformat("Selecting media type \"%s\" from offered types.", mime));
- wayland_thread.primary_get_mime(mime);
+ data = wayland_thread.primary_get_mime(mime);
break;
}
}
@@ -1349,23 +1349,39 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win
rendering_driver = p_rendering_driver;
+ bool driver_found = false;
+ String executable_name = OS::get_singleton()->get_executable_path().get_file();
+
#ifdef RD_ENABLED
#ifdef VULKAN_ENABLED
if (rendering_driver == "vulkan") {
rendering_context = memnew(RenderingContextDriverVulkanWayland);
}
-#endif
+#endif // VULKAN_ENABLED
if (rendering_context) {
if (rendering_context->initialize() != OK) {
- ERR_PRINT(vformat("Could not initialize %s", rendering_driver));
memdelete(rendering_context);
rendering_context = nullptr;
r_error = ERR_CANT_CREATE;
- return;
+
+ if (p_rendering_driver == "vulkan") {
+ OS::get_singleton()->alert(
+ vformat("Your video card drivers seem not to support the required Vulkan version.\n\n"
+ "If possible, consider updating your video card drivers or using the OpenGL 3 driver.\n\n"
+ "You can enable the OpenGL 3 driver by starting the engine from the\n"
+ "command line with the command:\n\n \"%s\" --rendering-driver opengl3\n\n"
+ "If you recently updated your video card drivers, try rebooting.",
+ executable_name),
+ "Unable to initialize Vulkan video driver");
+ }
+
+ ERR_FAIL_MSG(vformat("Could not initialize %s", rendering_driver));
}
+
+ driver_found = true;
}
-#endif
+#endif // RD_ENABLED
#ifdef GLES3_ENABLED
if (rendering_driver == "opengl3" || rendering_driver == "opengl3_es") {
@@ -1429,28 +1445,56 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win
if (fallback) {
WARN_PRINT("Your video card drivers seem not to support the required OpenGL version, switching to OpenGLES.");
rendering_driver = "opengl3_es";
+ OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
} else {
r_error = ERR_UNAVAILABLE;
+
+ OS::get_singleton()->alert(
+ vformat("Your video card drivers seem not to support the required OpenGL 3.3 version.\n\n"
+ "If possible, consider updating your video card drivers or using the Vulkan driver.\n\n"
+ "You can enable the Vulkan driver by starting the engine from the\n"
+ "command line with the command:\n\n \"%s\" --rendering-driver vulkan\n\n"
+ "If you recently updated your video card drivers, try rebooting.",
+ executable_name),
+ "Unable to initialize OpenGL video driver");
+
ERR_FAIL_MSG("Could not initialize OpenGL.");
}
} else {
RasterizerGLES3::make_current(true);
+ driver_found = true;
}
}
if (rendering_driver == "opengl3_es") {
egl_manager = memnew(EGLManagerWaylandGLES);
- if (egl_manager->initialize(wayland_thread.get_wl_display()) != OK) {
+ if (egl_manager->initialize(wayland_thread.get_wl_display()) != OK || egl_manager->open_display(wayland_thread.get_wl_display()) != OK) {
memdelete(egl_manager);
egl_manager = nullptr;
r_error = ERR_CANT_CREATE;
- ERR_FAIL_MSG("Could not initialize GLES3.");
+
+ OS::get_singleton()->alert(
+ vformat("Your video card drivers seem not to support the required OpenGL ES 3.0 version.\n\n"
+ "If possible, consider updating your video card drivers or using the Vulkan driver.\n\n"
+ "You can enable the Vulkan driver by starting the engine from the\n"
+ "command line with the command:\n\n \"%s\" --rendering-driver vulkan\n\n"
+ "If you recently updated your video card drivers, try rebooting.",
+ executable_name),
+ "Unable to initialize OpenGL ES video driver");
+
+ ERR_FAIL_MSG("Could not initialize OpenGL ES.");
}
RasterizerGLES3::make_current(false);
+ driver_found = true;
}
}
+
+ if (!driver_found) {
+ r_error = ERR_UNAVAILABLE;
+ ERR_FAIL_MSG("Video driver not found.");
+ }
#endif // GLES3_ENABLED
cursor_set_shape(CURSOR_BUSY);
@@ -1481,12 +1525,12 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win
RendererCompositorRD::make_current();
}
-#endif
+#endif // RD_ENABLED
#ifdef DBUS_ENABLED
portal_desktop = memnew(FreeDesktopPortalDesktop);
screensaver = memnew(FreeDesktopScreenSaver);
-#endif
+#endif // DBUS_ENABLED
screen_set_keep_on(GLOBAL_GET("display/window/energy_saving/keep_screen_on"));
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index 8a2f83be2d..840cadace3 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -5428,25 +5428,6 @@ Vector<String> DisplayServerX11::get_rendering_drivers_func() {
DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, Error &r_error) {
DisplayServer *ds = memnew(DisplayServerX11(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, p_screen, p_context, r_error));
- if (r_error != OK) {
- if (p_rendering_driver == "vulkan") {
- String executable_name = OS::get_singleton()->get_executable_path().get_file();
- OS::get_singleton()->alert(
- vformat("Your video card drivers seem not to support the required Vulkan version.\n\n"
- "If possible, consider updating your video card drivers or using the OpenGL 3 driver.\n\n"
- "You can enable the OpenGL 3 driver by starting the engine from the\n"
- "command line with the command:\n\n \"%s\" --rendering-driver opengl3\n\n"
- "If you recently updated your video card drivers, try rebooting.",
- executable_name),
- "Unable to initialize Vulkan video driver");
- } else {
- OS::get_singleton()->alert(
- "Your video card drivers seem not to support the required OpenGL 3.3 version.\n\n"
- "If possible, consider updating your video card drivers.\n\n"
- "If you recently updated your video card drivers, try rebooting.",
- "Unable to initialize OpenGL video driver");
- }
- }
return ds;
}
@@ -6160,25 +6141,40 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
rendering_driver = p_rendering_driver;
bool driver_found = false;
+ String executable_name = OS::get_singleton()->get_executable_path().get_file();
+
+ // Initialize context and rendering device.
+
#if defined(RD_ENABLED)
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
rendering_context = memnew(RenderingContextDriverVulkanX11);
}
-#endif
+#endif // VULKAN_ENABLED
if (rendering_context) {
if (rendering_context->initialize() != OK) {
- ERR_PRINT(vformat("Could not initialize %s", rendering_driver));
memdelete(rendering_context);
rendering_context = nullptr;
r_error = ERR_CANT_CREATE;
- return;
+
+ if (p_rendering_driver == "vulkan") {
+ OS::get_singleton()->alert(
+ vformat("Your video card drivers seem not to support the required Vulkan version.\n\n"
+ "If possible, consider updating your video card drivers or using the OpenGL 3 driver.\n\n"
+ "You can enable the OpenGL 3 driver by starting the engine from the\n"
+ "command line with the command:\n\n \"%s\" --rendering-driver opengl3\n\n"
+ "If you recently updated your video card drivers, try rebooting.",
+ executable_name),
+ "Unable to initialize Vulkan video driver");
+ }
+
+ ERR_FAIL_MSG(vformat("Could not initialize %s", rendering_driver));
}
driver_found = true;
}
-#endif
- // Initialize context and rendering device.
+#endif // RD_ENABLED
+
#if defined(GLES3_ENABLED)
if (rendering_driver == "opengl3" || rendering_driver == "opengl3_es") {
if (getenv("DRI_PRIME") == nullptr) {
@@ -6231,8 +6227,19 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
if (fallback) {
WARN_PRINT("Your video card drivers seem not to support the required OpenGL version, switching to OpenGLES.");
rendering_driver = "opengl3_es";
+ OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
} else {
r_error = ERR_UNAVAILABLE;
+
+ OS::get_singleton()->alert(
+ vformat("Your video card drivers seem not to support the required OpenGL 3.3 version.\n\n"
+ "If possible, consider updating your video card drivers or using the Vulkan driver.\n\n"
+ "You can enable the Vulkan driver by starting the engine from the\n"
+ "command line with the command:\n\n \"%s\" --rendering-driver vulkan\n\n"
+ "If you recently updated your video card drivers, try rebooting.",
+ executable_name),
+ "Unable to initialize OpenGL video driver");
+
ERR_FAIL_MSG("Could not initialize OpenGL.");
}
} else {
@@ -6243,20 +6250,28 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
if (rendering_driver == "opengl3_es") {
gl_manager_egl = memnew(GLManagerEGL_X11);
- if (gl_manager_egl->initialize() != OK) {
+ if (gl_manager_egl->initialize() != OK || gl_manager_egl->open_display(x11_display) != OK) {
memdelete(gl_manager_egl);
gl_manager_egl = nullptr;
r_error = ERR_UNAVAILABLE;
- ERR_FAIL_MSG("Could not initialize OpenGLES.");
+
+ OS::get_singleton()->alert(
+ "Your video card drivers seem not to support the required OpenGL ES 3.0 version.\n\n"
+ "If possible, consider updating your video card drivers.\n\n"
+ "If you recently updated your video card drivers, try rebooting.",
+ "Unable to initialize OpenGL ES video driver");
+
+ ERR_FAIL_MSG("Could not initialize OpenGL ES.");
}
driver_found = true;
RasterizerGLES3::make_current(false);
}
-#endif
+#endif // GLES3_ENABLED
+
if (!driver_found) {
r_error = ERR_UNAVAILABLE;
- ERR_FAIL_MSG("Video driver not found");
+ ERR_FAIL_MSG("Video driver not found.");
}
Point2i window_position;
@@ -6297,7 +6312,7 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
RendererCompositorRD::make_current();
}
-#endif
+#endif // RD_ENABLED
{
//set all event master mask
@@ -6450,7 +6465,8 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
screen_set_keep_on(GLOBAL_GET("display/window/energy_saving/keep_screen_on"));
portal_desktop = memnew(FreeDesktopPortalDesktop);
-#endif
+#endif // DBUS_ENABLED
+
XSetErrorHandler(&default_window_error_handler);
r_error = OK;
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index 989a9dcf6c..52dc51bc96 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -3615,6 +3615,7 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM
WARN_PRINT("Your video card drivers seem not to support GLES3 / ANGLE or ANGLE dynamic libraries (libEGL.dylib and libGLESv2.dylib) are missing, switching to native OpenGL.");
#endif
rendering_driver = "opengl3";
+ OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
} else {
r_error = ERR_UNAVAILABLE;
ERR_FAIL_MSG("Could not initialize ANGLE OpenGL.");
diff --git a/platform/macos/export/export_plugin.cpp b/platform/macos/export/export_plugin.cpp
index 290b0082fc..8372600ae9 100644
--- a/platform/macos/export/export_plugin.cpp
+++ b/platform/macos/export/export_plugin.cpp
@@ -1505,7 +1505,7 @@ Error EditorExportPlatformMacOS::_export_debug_script(const Ref<EditorExportPres
return OK;
}
-Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags) {
ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
const String base_dir = p_path.get_base_dir();
@@ -2511,7 +2511,7 @@ void EditorExportPlatformMacOS::cleanup() {
cleanup_commands.clear();
}
-Error EditorExportPlatformMacOS::run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) {
+Error EditorExportPlatformMacOS::run(const Ref<EditorExportPreset> &p_preset, int p_device, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) {
cleanup();
if (p_device) { // Stop command, cleanup only.
return OK;
@@ -2573,8 +2573,7 @@ Error EditorExportPlatformMacOS::run(const Ref<EditorExportPreset> &p_preset, in
String cmd_args;
{
- Vector<String> cmd_args_list;
- gen_debug_flags(cmd_args_list, p_debug_flags);
+ Vector<String> cmd_args_list = gen_export_flags(p_debug_flags);
for (int i = 0; i < cmd_args_list.size(); i++) {
if (i != 0) {
cmd_args += " ";
@@ -2583,7 +2582,7 @@ Error EditorExportPlatformMacOS::run(const Ref<EditorExportPreset> &p_preset, in
}
}
- const bool use_remote = (p_debug_flags & DEBUG_FLAG_REMOTE_DEBUG) || (p_debug_flags & DEBUG_FLAG_DUMB_CLIENT);
+ const bool use_remote = p_debug_flags.has_flag(DEBUG_FLAG_REMOTE_DEBUG) || p_debug_flags.has_flag(DEBUG_FLAG_DUMB_CLIENT);
int dbg_port = EditorSettings::get_singleton()->get("network/debug/remote_port");
print_line("Creating temporary directory...");
diff --git a/platform/macos/export/export_plugin.h b/platform/macos/export/export_plugin.h
index 062a2e5f95..5457c687d3 100644
--- a/platform/macos/export/export_plugin.h
+++ b/platform/macos/export/export_plugin.h
@@ -147,7 +147,7 @@ public:
virtual bool is_executable(const String &p_path) const override;
virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override;
- virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override;
+ virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags = 0) override;
virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const override;
virtual bool has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const override;
@@ -167,7 +167,7 @@ public:
virtual int get_options_count() const override;
virtual String get_option_label(int p_index) const override;
virtual String get_option_tooltip(int p_index) const override;
- virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) override;
+ virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) override;
virtual void cleanup() override;
EditorExportPlatformMacOS();
diff --git a/platform/web/api/api.cpp b/platform/web/api/api.cpp
index a695091a04..9ddbe5d01d 100644
--- a/platform/web/api/api.cpp
+++ b/platform/web/api/api.cpp
@@ -99,7 +99,7 @@ Variant JavaScriptBridge::_create_object_bind(const Variant **p_args, int p_argc
r_error.expected = 1;
return Ref<JavaScriptObject>();
}
- if (p_args[0]->get_type() != Variant::STRING) {
+ if (!p_args[0]->is_string()) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::STRING;
diff --git a/platform/web/export/export_plugin.cpp b/platform/web/export/export_plugin.cpp
index d8c1b6033d..5faab74d7b 100644
--- a/platform/web/export/export_plugin.cpp
+++ b/platform/web/export/export_plugin.cpp
@@ -130,15 +130,14 @@ void EditorExportPlatformWeb::_replace_strings(const HashMap<String, String> &p_
}
}
-void EditorExportPlatformWeb::_fix_html(Vector<uint8_t> &p_html, const Ref<EditorExportPreset> &p_preset, const String &p_name, bool p_debug, int p_flags, const Vector<SharedObject> p_shared_objects, const Dictionary &p_file_sizes) {
+void EditorExportPlatformWeb::_fix_html(Vector<uint8_t> &p_html, const Ref<EditorExportPreset> &p_preset, const String &p_name, bool p_debug, BitField<EditorExportPlatform::DebugFlags> p_flags, const Vector<SharedObject> p_shared_objects, const Dictionary &p_file_sizes) {
// Engine.js config
Dictionary config;
Array libs;
for (int i = 0; i < p_shared_objects.size(); i++) {
libs.push_back(p_shared_objects[i].path.get_file());
}
- Vector<String> flags;
- gen_export_flags(flags, p_flags & (~DEBUG_FLAG_DUMB_CLIENT));
+ Vector<String> flags = gen_export_flags(p_flags & (~DEBUG_FLAG_DUMB_CLIENT));
Array args;
for (int i = 0; i < flags.size(); i++) {
args.push_back(flags[i]);
@@ -450,7 +449,7 @@ List<String> EditorExportPlatformWeb::get_binary_extensions(const Ref<EditorExpo
return list;
}
-Error EditorExportPlatformWeb::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+Error EditorExportPlatformWeb::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags) {
ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
const String custom_debug = p_preset->get("custom_template/debug");
@@ -744,7 +743,7 @@ String EditorExportPlatformWeb::get_option_tooltip(int p_index) const {
return "";
}
-Error EditorExportPlatformWeb::run(const Ref<EditorExportPreset> &p_preset, int p_option, int p_debug_flags) {
+Error EditorExportPlatformWeb::run(const Ref<EditorExportPreset> &p_preset, int p_option, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) {
const uint16_t bind_port = EDITOR_GET("export/web/http_port");
// Resolve host if needed.
const String bind_host = EDITOR_GET("export/web/http_host");
diff --git a/platform/web/export/export_plugin.h b/platform/web/export/export_plugin.h
index 2f67d8107f..3c743e2e74 100644
--- a/platform/web/export/export_plugin.h
+++ b/platform/web/export/export_plugin.h
@@ -98,7 +98,7 @@ class EditorExportPlatformWeb : public EditorExportPlatform {
Error _extract_template(const String &p_template, const String &p_dir, const String &p_name, bool pwa);
void _replace_strings(const HashMap<String, String> &p_replaces, Vector<uint8_t> &r_template);
- void _fix_html(Vector<uint8_t> &p_html, const Ref<EditorExportPreset> &p_preset, const String &p_name, bool p_debug, int p_flags, const Vector<SharedObject> p_shared_objects, const Dictionary &p_file_sizes);
+ void _fix_html(Vector<uint8_t> &p_html, const Ref<EditorExportPreset> &p_preset, const String &p_name, bool p_debug, BitField<EditorExportPlatform::DebugFlags> p_flags, const Vector<SharedObject> p_shared_objects, const Dictionary &p_file_sizes);
Error _add_manifest_icon(const String &p_path, const String &p_icon, int p_size, Array &r_arr);
Error _build_pwa(const Ref<EditorExportPreset> &p_preset, const String p_path, const Vector<SharedObject> &p_shared_objects);
Error _write_or_error(const uint8_t *p_content, int p_len, String p_path);
@@ -120,14 +120,14 @@ public:
virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const override;
virtual bool has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const override;
virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override;
- virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override;
+ virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags = 0) override;
virtual bool poll_export() override;
virtual int get_options_count() const override;
virtual String get_option_label(int p_index) const override;
virtual String get_option_tooltip(int p_index) const override;
virtual Ref<ImageTexture> get_option_icon(int p_index) const override;
- virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_option, int p_debug_flags) override;
+ virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_option, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) override;
virtual Ref<Texture2D> get_run_icon() const override;
virtual void get_platform_features(List<String> *r_features) const override {
diff --git a/platform/web/javascript_bridge_singleton.cpp b/platform/web/javascript_bridge_singleton.cpp
index c4dbb405a3..502e830f82 100644
--- a/platform/web/javascript_bridge_singleton.cpp
+++ b/platform/web/javascript_bridge_singleton.cpp
@@ -304,7 +304,7 @@ Variant JavaScriptBridge::_create_object_bind(const Variant **p_args, int p_argc
r_error.expected = 1;
return Ref<JavaScriptObject>();
}
- if (p_args[0]->get_type() != Variant::STRING) {
+ if (!p_args[0]->is_string()) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::STRING;
diff --git a/platform/windows/crash_handler_windows_seh.cpp b/platform/windows/crash_handler_windows_seh.cpp
index 2abe285d31..a6015092e8 100644
--- a/platform/windows/crash_handler_windows_seh.cpp
+++ b/platform/windows/crash_handler_windows_seh.cpp
@@ -118,7 +118,7 @@ DWORD CrashHandlerException(EXCEPTION_POINTERS *ep) {
HANDLE process = GetCurrentProcess();
HANDLE hThread = GetCurrentThread();
DWORD offset_from_symbol = 0;
- IMAGEHLP_LINE64 line = { 0 };
+ IMAGEHLP_LINE64 line = {};
std::vector<module_data> modules;
DWORD cbNeeded;
std::vector<HMODULE> module_handles(1);
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index 82a98655c0..92ac921cee 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -381,6 +381,15 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
## Compile/link flags
+ if env["use_llvm"]:
+ env["CC"] = "clang-cl"
+ env["CXX"] = "clang-cl"
+ env["LINK"] = "lld-link"
+ env["AR"] = "llvm-lib"
+
+ env.AppendUnique(CPPDEFINES=["R128_STDC_ONLY"])
+ env.extra_suffix = ".llvm" + env.extra_suffix
+
env["MAXLINELENGTH"] = 8192 # Windows Vista and beyond, so always applicable.
if env["silence_msvc"] and not env.GetOption("clean"):
@@ -465,7 +474,6 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
env.AppendUnique(CCFLAGS=["/Gd", "/GR", "/nologo"])
env.AppendUnique(CCFLAGS=["/utf-8"]) # Force to use Unicode encoding.
- env.AppendUnique(CXXFLAGS=["/TP"]) # assume all sources are C++
# Once it was thought that only debug builds would be too large,
# but this has recently stopped being true. See the mingw function
# for notes on why this shouldn't be enabled for gcc
@@ -590,6 +598,9 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
if env["target"] in ["editor", "template_debug"]:
LIBS += ["psapi", "dbghelp"]
+ if env["use_llvm"]:
+ LIBS += [f"clang_rt.builtins-{env['arch']}"]
+
env.Append(LINKFLAGS=[p + env["LIBSUFFIX"] for p in LIBS])
if vcvars_msvc_config:
@@ -605,14 +616,22 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
if env["lto"] != "none":
if env["lto"] == "thin":
- print_error("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.")
- sys.exit(255)
- env.AppendUnique(CCFLAGS=["/GL"])
- env.AppendUnique(ARFLAGS=["/LTCG"])
- if env["progress"]:
- env.AppendUnique(LINKFLAGS=["/LTCG:STATUS"])
+ if not env["use_llvm"]:
+ print("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.")
+ sys.exit(255)
+
+ env.Append(CCFLAGS=["-flto=thin"])
+ env.Append(LINKFLAGS=["-flto=thin"])
+ elif env["use_llvm"]:
+ env.Append(CCFLAGS=["-flto"])
+ env.Append(LINKFLAGS=["-flto"])
else:
- env.AppendUnique(LINKFLAGS=["/LTCG"])
+ env.AppendUnique(CCFLAGS=["/GL"])
+ env.AppendUnique(ARFLAGS=["/LTCG"])
+ if env["progress"]:
+ env.AppendUnique(LINKFLAGS=["/LTCG:STATUS"])
+ else:
+ env.AppendUnique(LINKFLAGS=["/LTCG"])
if vcvars_msvc_config:
env.Prepend(CPPPATH=[p for p in str(os.getenv("INCLUDE")).split(";")])
@@ -630,6 +649,61 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
env.AppendUnique(LINKFLAGS=["/STACK:" + str(STACK_SIZE)])
+def get_ar_version(env):
+ ret = {
+ "major": -1,
+ "minor": -1,
+ "patch": -1,
+ "is_llvm": False,
+ }
+ try:
+ output = (
+ subprocess.check_output([env.subst(env["AR"]), "--version"], shell=(os.name == "nt"))
+ .strip()
+ .decode("utf-8")
+ )
+ except (subprocess.CalledProcessError, OSError):
+ print_warning("Couldn't check version of `ar`.")
+ return ret
+
+ match = re.search(r"GNU ar \(GNU Binutils\) (\d+)\.(\d+)(:?\.(\d+))?", output)
+ if match:
+ ret["major"] = int(match[1])
+ ret["minor"] = int(match[2])
+ if match[3]:
+ ret["patch"] = int(match[3])
+ else:
+ ret["patch"] = 0
+ return ret
+
+ match = re.search(r"LLVM version (\d+)\.(\d+)\.(\d+)", output)
+ if match:
+ ret["major"] = int(match[1])
+ ret["minor"] = int(match[2])
+ ret["patch"] = int(match[3])
+ ret["is_llvm"] = True
+ return ret
+
+ print_warning("Couldn't parse version of `ar`.")
+ return ret
+
+
+def get_is_ar_thin_supported(env):
+ """Check whether `ar --thin` is supported. It is only supported since Binutils 2.38 or LLVM 14."""
+ ar_version = get_ar_version(env)
+ if ar_version["major"] == -1:
+ return False
+
+ if ar_version["is_llvm"]:
+ return ar_version["major"] >= 14
+
+ if ar_version["major"] == 2:
+ return ar_version["minor"] >= 38
+
+ print_warning("Unknown Binutils `ar` version.")
+ return False
+
+
def configure_mingw(env: "SConsEnvironment"):
# Workaround for MinGW. See:
# https://www.scons.org/wiki/LongCmdLinesOnWin32
@@ -762,7 +836,8 @@ def configure_mingw(env: "SConsEnvironment"):
if env["use_llvm"] and os.name == "nt" and methods._colorize:
env.Append(CCFLAGS=["$(-fansi-escape-codes$)", "$(-fcolor-diagnostics$)"])
- env.Append(ARFLAGS=["--thin"])
+ if get_is_ar_thin_supported(env):
+ env.Append(ARFLAGS=["--thin"])
env.Append(CPPDEFINES=["WINDOWS_ENABLED", "WASAPI_ENABLED", "WINMIDI_ENABLED"])
env.Append(
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index 8bcd556c22..50ebe7077f 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -522,7 +522,7 @@ void DisplayServerWindows::_thread_fd_monitor(void *p_ud) {
if (!item.has("name") || !item.has("values") || !item.has("default")) {
continue;
}
- event_handler->add_option(pfdc, item["name"], item["values"], item["default_idx"]);
+ event_handler->add_option(pfdc, item["name"], item["values"], item["default"]);
}
event_handler->set_root(fd->root);
@@ -625,62 +625,41 @@ void DisplayServerWindows::_thread_fd_monitor(void *p_ud) {
}
}
if (fd->callback.is_valid()) {
- if (fd->options_in_cb) {
- Variant v_result = true;
- Variant v_files = file_names;
- Variant v_index = index;
- Variant v_opt = options;
- const Variant *cb_args[4] = { &v_result, &v_files, &v_index, &v_opt };
-
- fd->callback.call_deferredp(cb_args, 4);
- } else {
- Variant v_result = true;
- Variant v_files = file_names;
- Variant v_index = index;
- const Variant *cb_args[3] = { &v_result, &v_files, &v_index };
-
- fd->callback.call_deferredp(cb_args, 3);
- }
+ MutexLock lock(ds->file_dialog_mutex);
+ FileDialogCallback cb;
+ cb.callback = fd->callback;
+ cb.status = true;
+ cb.files = file_names;
+ cb.index = index;
+ cb.options = options;
+ cb.opt_in_cb = fd->options_in_cb;
+ ds->pending_cbs.push_back(cb);
}
} else {
if (fd->callback.is_valid()) {
- if (fd->options_in_cb) {
- Variant v_result = false;
- Variant v_files = Vector<String>();
- Variant v_index = 0;
- Variant v_opt = Dictionary();
- const Variant *cb_args[4] = { &v_result, &v_files, &v_index, &v_opt };
-
- fd->callback.call_deferredp(cb_args, 4);
- } else {
- Variant v_result = false;
- Variant v_files = Vector<String>();
- Variant v_index = 0;
- const Variant *cb_args[3] = { &v_result, &v_files, &v_index };
-
- fd->callback.call_deferredp(cb_args, 3);
- }
+ MutexLock lock(ds->file_dialog_mutex);
+ FileDialogCallback cb;
+ cb.callback = fd->callback;
+ cb.status = false;
+ cb.files = Vector<String>();
+ cb.index = index;
+ cb.options = options;
+ cb.opt_in_cb = fd->options_in_cb;
+ ds->pending_cbs.push_back(cb);
}
}
pfd->Release();
} else {
if (fd->callback.is_valid()) {
- if (fd->options_in_cb) {
- Variant v_result = false;
- Variant v_files = Vector<String>();
- Variant v_index = 0;
- Variant v_opt = Dictionary();
- const Variant *cb_args[4] = { &v_result, &v_files, &v_index, &v_opt };
-
- fd->callback.call_deferredp(cb_args, 4);
- } else {
- Variant v_result = false;
- Variant v_files = Vector<String>();
- Variant v_index = 0;
- const Variant *cb_args[3] = { &v_result, &v_files, &v_index };
-
- fd->callback.call_deferredp(cb_args, 3);
- }
+ MutexLock lock(ds->file_dialog_mutex);
+ FileDialogCallback cb;
+ cb.callback = fd->callback;
+ cb.status = false;
+ cb.files = Vector<String>();
+ cb.index = 0;
+ cb.options = Dictionary();
+ cb.opt_in_cb = fd->options_in_cb;
+ ds->pending_cbs.push_back(cb);
}
}
{
@@ -768,6 +747,34 @@ Error DisplayServerWindows::_file_dialog_with_options_show(const String &p_title
return OK;
}
+void DisplayServerWindows::process_file_dialog_callbacks() {
+ MutexLock lock(file_dialog_mutex);
+ while (!pending_cbs.is_empty()) {
+ FileDialogCallback cb = pending_cbs.front()->get();
+ pending_cbs.pop_front();
+
+ if (cb.opt_in_cb) {
+ Variant ret;
+ Callable::CallError ce;
+ const Variant *args[4] = { &cb.status, &cb.files, &cb.index, &cb.options };
+
+ cb.callback.callp(args, 4, ret, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT(vformat("Failed to execute file dialog callback: %s.", Variant::get_callable_error_text(cb.callback, args, 4, ce)));
+ }
+ } else {
+ Variant ret;
+ Callable::CallError ce;
+ const Variant *args[3] = { &cb.status, &cb.files, &cb.index };
+
+ cb.callback.callp(args, 3, ret, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT(vformat("Failed to execute file dialog callback: %s.", Variant::get_callable_error_text(cb.callback, args, 3, ce)));
+ }
+ }
+ }
+}
+
void DisplayServerWindows::mouse_set_mode(MouseMode p_mode) {
_THREAD_SAFE_METHOD_
@@ -3190,6 +3197,7 @@ void DisplayServerWindows::process_events() {
memdelete(E->get());
E->erase();
}
+ process_file_dialog_callbacks();
}
void DisplayServerWindows::force_process_and_drop_events() {
@@ -6150,6 +6158,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
if (rendering_context->initialize() == OK) {
WARN_PRINT("Your video card drivers seem not to support Direct3D 12, switching to Vulkan.");
rendering_driver = "vulkan";
+ OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
failed = false;
}
}
@@ -6163,6 +6172,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
if (rendering_context->initialize() == OK) {
WARN_PRINT("Your video card drivers seem not to support Vulkan, switching to Direct3D 12.");
rendering_driver = "d3d12";
+ OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
failed = false;
}
}
@@ -6241,6 +6251,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
}
}
rendering_driver = "opengl3_angle";
+ OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
}
}
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index 3deb7ac8b0..54e1c9681d 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -572,6 +572,16 @@ class DisplayServerWindows : public DisplayServer {
Mutex file_dialog_mutex;
List<FileDialogData *> file_dialogs;
HashMap<HWND, FileDialogData *> file_dialog_wnd;
+ struct FileDialogCallback {
+ Callable callback;
+ Variant status;
+ Variant files;
+ Variant index;
+ Variant options;
+ bool opt_in_cb = false;
+ };
+ List<FileDialogCallback> pending_cbs;
+ void process_file_dialog_callbacks();
static void _thread_fd_monitor(void *p_ud);
diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp
index b465bd4ecd..8d3f4bb269 100644
--- a/platform/windows/export/export_plugin.cpp
+++ b/platform/windows/export/export_plugin.cpp
@@ -167,7 +167,7 @@ Error EditorExportPlatformWindows::sign_shared_object(const Ref<EditorExportPres
}
}
-Error EditorExportPlatformWindows::modify_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+Error EditorExportPlatformWindows::modify_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags) {
if (p_preset->get("application/modify_resources")) {
_rcedit_add_data(p_preset, p_path, false);
String wrapper_path = p_path.get_basename() + ".console.exe";
@@ -178,7 +178,7 @@ Error EditorExportPlatformWindows::modify_template(const Ref<EditorExportPreset>
return OK;
}
-Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags) {
String custom_debug = p_preset->get("custom_template/debug");
String custom_release = p_preset->get("custom_template/release");
String arch = p_preset->get("binary_format/architecture");
@@ -996,7 +996,7 @@ void EditorExportPlatformWindows::cleanup() {
cleanup_commands.clear();
}
-Error EditorExportPlatformWindows::run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) {
+Error EditorExportPlatformWindows::run(const Ref<EditorExportPreset> &p_preset, int p_device, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) {
cleanup();
if (p_device) { // Stop command, cleanup only.
return OK;
@@ -1050,8 +1050,7 @@ Error EditorExportPlatformWindows::run(const Ref<EditorExportPreset> &p_preset,
String cmd_args;
{
- Vector<String> cmd_args_list;
- gen_debug_flags(cmd_args_list, p_debug_flags);
+ Vector<String> cmd_args_list = gen_export_flags(p_debug_flags);
for (int i = 0; i < cmd_args_list.size(); i++) {
if (i != 0) {
cmd_args += " ";
@@ -1060,7 +1059,7 @@ Error EditorExportPlatformWindows::run(const Ref<EditorExportPreset> &p_preset,
}
}
- const bool use_remote = (p_debug_flags & DEBUG_FLAG_REMOTE_DEBUG) || (p_debug_flags & DEBUG_FLAG_DUMB_CLIENT);
+ const bool use_remote = p_debug_flags.has_flag(DEBUG_FLAG_REMOTE_DEBUG) || p_debug_flags.has_flag(DEBUG_FLAG_DUMB_CLIENT);
int dbg_port = EditorSettings::get_singleton()->get("network/debug/remote_port");
print_line("Creating temporary directory...");
diff --git a/platform/windows/export/export_plugin.h b/platform/windows/export/export_plugin.h
index 6ccb4a15a7..e86aac83d4 100644
--- a/platform/windows/export/export_plugin.h
+++ b/platform/windows/export/export_plugin.h
@@ -76,8 +76,8 @@ class EditorExportPlatformWindows : public EditorExportPlatformPC {
String _get_exe_arch(const String &p_path) const;
public:
- virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override;
- virtual Error modify_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) override;
+ virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags = 0) override;
+ virtual Error modify_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags) override;
virtual Error sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) override;
virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override;
virtual void get_export_options(List<ExportOption> *r_options) const override;
@@ -95,7 +95,7 @@ public:
virtual int get_options_count() const override;
virtual String get_option_label(int p_index) const override;
virtual String get_option_tooltip(int p_index) const override;
- virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) override;
+ virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) override;
virtual void cleanup() override;
EditorExportPlatformWindows();
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 47836788e1..bcc6a64671 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -1614,16 +1614,7 @@ String OS_Windows::get_executable_path() const {
}
bool OS_Windows::has_environment(const String &p_var) const {
-#ifdef MINGW_ENABLED
- return _wgetenv((LPCWSTR)(p_var.utf16().get_data())) != nullptr;
-#else
- WCHAR *env;
- size_t len;
- _wdupenv_s(&env, &len, (LPCWSTR)(p_var.utf16().get_data()));
- const bool has_env = env != nullptr;
- free(env);
- return has_env;
-#endif
+ return GetEnvironmentVariableW((LPCWSTR)(p_var.utf16().get_data()), nullptr, 0) > 0;
}
String OS_Windows::get_environment(const String &p_var) const {
diff --git a/platform/windows/windows_utils.cpp b/platform/windows/windows_utils.cpp
index 9e0b9eed8a..30743c6900 100644
--- a/platform/windows/windows_utils.cpp
+++ b/platform/windows/windows_utils.cpp
@@ -155,7 +155,11 @@ Error WindowsUtils::copy_and_rename_pdb(const String &p_dll_path) {
} else if (!FileAccess::exists(copy_pdb_path)) {
copy_pdb_path = dll_base_dir.path_join(copy_pdb_path.get_file());
}
- ERR_FAIL_COND_V_MSG(!FileAccess::exists(copy_pdb_path), FAILED, vformat("File '%s' does not exist.", copy_pdb_path));
+ if (!FileAccess::exists(copy_pdb_path)) {
+ // The PDB file may be distributed separately on purpose, so we don't consider this an error.
+ WARN_VERBOSE(vformat("PDB file '%s' for library '%s' was not found, skipping copy/rename.", copy_pdb_path, p_dll_path));
+ return ERR_SKIP;
+ }
String new_pdb_base_name = p_dll_path.get_file().get_basename() + "_";