summaryrefslogtreecommitdiffstats
path: root/platform
diff options
context:
space:
mode:
Diffstat (limited to 'platform')
-rw-r--r--platform/android/android_input_handler.cpp4
-rw-r--r--platform/android/android_input_handler.h2
-rw-r--r--platform/android/dir_access_jandroid.cpp26
-rw-r--r--platform/android/display_server_android.cpp16
-rw-r--r--platform/android/display_server_android.h3
-rw-r--r--platform/android/doc_classes/EditorExportPlatformAndroid.xml1
-rw-r--r--platform/android/export/export.cpp3
-rw-r--r--platform/android/export/export_plugin.cpp14
-rw-r--r--platform/android/file_access_filesystem_jandroid.cpp26
-rw-r--r--platform/android/java/editor/src/.gitignore1
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/Godot.kt33
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotLib.java2
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java29
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java24
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java131
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java31
-rw-r--r--platform/android/java_class_wrapper.cpp8
-rw-r--r--platform/android/java_godot_lib_jni.cpp4
-rw-r--r--platform/android/java_godot_lib_jni.h2
-rw-r--r--platform/android/java_godot_wrapper.cpp42
-rw-r--r--platform/android/java_godot_wrapper.h8
-rw-r--r--platform/android/os_android.cpp42
-rw-r--r--platform/android/os_android.h6
-rw-r--r--platform/android/platform_gl.h (renamed from platform/uwp/context_egl_uwp.h)61
-rw-r--r--platform/android/plugin/godot_plugin_jni.cpp27
-rw-r--r--platform/android/plugin/godot_plugin_jni.h1
-rw-r--r--platform/android/tts_android.cpp16
-rw-r--r--platform/ios/detect.py10
-rw-r--r--platform/ios/display_server_ios.h3
-rw-r--r--platform/ios/display_server_ios.mm38
-rw-r--r--platform/ios/doc_classes/EditorExportPlatformIOS.xml1
-rw-r--r--platform/ios/export/export_plugin.cpp7
-rw-r--r--platform/ios/export/export_plugin.h10
-rw-r--r--platform/ios/godot_view.mm6
-rw-r--r--platform/ios/os_ios.mm2
-rw-r--r--platform/ios/platform_config.h2
-rw-r--r--platform/ios/platform_gl.h (renamed from platform/uwp/export/export.h)15
-rw-r--r--platform/ios/view_controller.mm4
-rw-r--r--platform/linuxbsd/detect.py4
-rw-r--r--platform/linuxbsd/export/export_plugin.cpp3
-rw-r--r--platform/linuxbsd/godot_linuxbsd.cpp2
-rw-r--r--platform/linuxbsd/platform_config.h2
-rw-r--r--platform/linuxbsd/platform_gl.h41
-rw-r--r--platform/linuxbsd/tts_linux.cpp10
-rw-r--r--platform/linuxbsd/x11/display_server_x11.cpp18
-rw-r--r--platform/linuxbsd/x11/gl_manager_x11.cpp15
-rw-r--r--platform/macos/SCsub1
-rw-r--r--platform/macos/detect.py20
-rw-r--r--platform/macos/display_server_macos.h6
-rw-r--r--platform/macos/display_server_macos.mm195
-rw-r--r--platform/macos/doc_classes/EditorExportPlatformMacOS.xml5
-rw-r--r--platform/macos/export/export_plugin.cpp26
-rw-r--r--platform/macos/gl_manager_macos_angle.h63
-rw-r--r--platform/macos/gl_manager_macos_angle.mm70
-rw-r--r--platform/macos/gl_manager_macos_legacy.h25
-rw-r--r--platform/macos/gl_manager_macos_legacy.mm73
-rw-r--r--platform/macos/godot_content_view.h2
-rw-r--r--platform/macos/godot_content_view.mm15
-rw-r--r--platform/macos/os_macos.mm2
-rw-r--r--platform/macos/platform_config.h1
-rw-r--r--platform/macos/platform_gl.h52
-rw-r--r--platform/uwp/README.md20
-rw-r--r--platform/uwp/SCsub20
-rw-r--r--platform/uwp/app_uwp.cpp560
-rw-r--r--platform/uwp/app_uwp.h115
-rw-r--r--platform/uwp/context_egl_uwp.cpp212
-rw-r--r--platform/uwp/detect.py216
-rw-r--r--platform/uwp/export/app_packager.cpp465
-rw-r--r--platform/uwp/export/app_packager.h149
-rw-r--r--platform/uwp/export/export.cpp56
-rw-r--r--platform/uwp/export/export_plugin.cpp525
-rw-r--r--platform/uwp/export/export_plugin.h450
-rw-r--r--platform/uwp/export/logo.svg1
-rw-r--r--platform/uwp/joypad_uwp.cpp174
-rw-r--r--platform/uwp/joypad_uwp.h81
-rw-r--r--platform/uwp/os_uwp.cpp845
-rw-r--r--platform/uwp/os_uwp.h256
-rw-r--r--platform/web/api/api.cpp2
-rw-r--r--platform/web/audio_driver_web.cpp2
-rw-r--r--platform/web/audio_driver_web.h5
-rw-r--r--platform/web/detect.py13
-rw-r--r--platform/web/display_server_web.cpp2
-rw-r--r--platform/web/display_server_web.h32
-rw-r--r--platform/web/doc_classes/EditorExportPlatformWeb.xml1
-rw-r--r--platform/web/export/export_plugin.cpp3
-rw-r--r--platform/web/export/export_plugin.h3
-rw-r--r--platform/web/godot_js.h2
-rw-r--r--platform/web/javascript_bridge_singleton.cpp12
-rw-r--r--platform/web/js/libs/library_godot_javascript_singleton.js10
-rw-r--r--platform/web/os_web.cpp6
-rw-r--r--platform/web/os_web.h11
-rw-r--r--platform/web/platform_config.h2
-rw-r--r--platform/web/platform_gl.h (renamed from platform/uwp/platform_config.h)13
-rw-r--r--platform/windows/SCsub5
-rw-r--r--platform/windows/crash_handler_windows.h2
-rw-r--r--platform/windows/detect.py32
-rw-r--r--platform/windows/display_server_windows.cpp213
-rw-r--r--platform/windows/display_server_windows.h11
-rw-r--r--platform/windows/doc_classes/EditorExportPlatformWindows.xml3
-rw-r--r--platform/windows/export/export_plugin.cpp35
-rw-r--r--platform/windows/gl_manager_windows_angle.cpp70
-rw-r--r--platform/windows/gl_manager_windows_angle.h61
-rw-r--r--platform/windows/gl_manager_windows_native.cpp (renamed from platform/windows/gl_manager_windows.cpp)130
-rw-r--r--platform/windows/gl_manager_windows_native.h (renamed from platform/windows/gl_manager_windows.h)28
-rw-r--r--platform/windows/os_windows.cpp13
-rw-r--r--platform/windows/platform_config.h2
-rw-r--r--platform/windows/platform_gl.h (renamed from platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginInfoProvider.java)57
-rw-r--r--platform/windows/platform_windows_builders.py16
-rw-r--r--platform/windows/tts_windows.cpp12
-rw-r--r--platform/windows/wgl_detect_version.cpp189
-rw-r--r--platform/windows/wgl_detect_version.h40
-rw-r--r--platform/windows/windows_terminal_logger.cpp4
112 files changed, 1695 insertions, 4804 deletions
diff --git a/platform/android/android_input_handler.cpp b/platform/android/android_input_handler.cpp
index f6a0776017..bd194478d9 100644
--- a/platform/android/android_input_handler.cpp
+++ b/platform/android/android_input_handler.cpp
@@ -292,7 +292,7 @@ void AndroidInputHandler::_release_mouse_event_info(bool p_source_mouse_relative
mouse_event_info.valid = false;
}
-void AndroidInputHandler::process_mouse_event(int p_event_action, int p_event_android_buttons_mask, Point2 p_event_pos, Vector2 p_delta, bool p_double_click, bool p_source_mouse_relative) {
+void AndroidInputHandler::process_mouse_event(int p_event_action, int p_event_android_buttons_mask, Point2 p_event_pos, Vector2 p_delta, bool p_double_click, bool p_source_mouse_relative, float p_pressure, Vector2 p_tilt) {
BitField<MouseButtonMask> event_buttons_mask = _android_button_mask_to_godot_button_mask(p_event_android_buttons_mask);
switch (p_event_action) {
case AMOTION_EVENT_ACTION_HOVER_MOVE: // hover move
@@ -349,6 +349,8 @@ void AndroidInputHandler::process_mouse_event(int p_event_action, int p_event_an
hover_prev_pos = p_event_pos;
}
ev->set_button_mask(event_buttons_mask);
+ ev->set_pressure(p_pressure);
+ ev->set_tilt(p_tilt);
Input::get_singleton()->parse_input_event(ev);
} break;
diff --git a/platform/android/android_input_handler.h b/platform/android/android_input_handler.h
index c74c5020e3..78a484cf05 100644
--- a/platform/android/android_input_handler.h
+++ b/platform/android/android_input_handler.h
@@ -96,7 +96,7 @@ private:
void _cancel_all_touch();
public:
- void process_mouse_event(int p_event_action, int p_event_android_buttons_mask, Point2 p_event_pos, Vector2 p_delta, bool p_double_click, bool p_source_mouse_relative);
+ void process_mouse_event(int p_event_action, int p_event_android_buttons_mask, Point2 p_event_pos, Vector2 p_delta, bool p_double_click, bool p_source_mouse_relative, float p_pressure, Vector2 p_tilt);
void process_touch_event(int p_event, int p_pointer, const Vector<TouchPos> &p_points, bool p_double_tap);
void process_magnify(Point2 p_pos, float p_factor);
void process_pan(Point2 p_pos, Vector2 p_delta);
diff --git a/platform/android/dir_access_jandroid.cpp b/platform/android/dir_access_jandroid.cpp
index 6bd09fe00a..d24d3fa389 100644
--- a/platform/android/dir_access_jandroid.cpp
+++ b/platform/android/dir_access_jandroid.cpp
@@ -67,7 +67,7 @@ String DirAccessJAndroid::get_next() {
ERR_FAIL_COND_V(id == 0, "");
if (_dir_next) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND_V(env == nullptr, "");
+ ERR_FAIL_NULL_V(env, "");
jstring str = (jstring)env->CallObjectMethod(dir_access_handler, _dir_next, get_access_type(), id);
if (!str) {
return "";
@@ -84,7 +84,7 @@ String DirAccessJAndroid::get_next() {
bool DirAccessJAndroid::current_is_dir() const {
if (_dir_is_dir) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND_V(env == nullptr, false);
+ ERR_FAIL_NULL_V(env, false);
return env->CallBooleanMethod(dir_access_handler, _dir_is_dir, get_access_type(), id);
} else {
return false;
@@ -94,7 +94,7 @@ bool DirAccessJAndroid::current_is_dir() const {
bool DirAccessJAndroid::current_is_hidden() const {
if (_current_is_hidden) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND_V(env == nullptr, false);
+ ERR_FAIL_NULL_V(env, false);
return env->CallBooleanMethod(dir_access_handler, _current_is_hidden, get_access_type(), id);
}
return false;
@@ -112,7 +112,7 @@ void DirAccessJAndroid::list_dir_end() {
int DirAccessJAndroid::get_drive_count() {
if (_get_drive_count) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND_V(env == nullptr, 0);
+ ERR_FAIL_NULL_V(env, 0);
return env->CallIntMethod(dir_access_handler, _get_drive_count, get_access_type());
} else {
return 0;
@@ -122,7 +122,7 @@ int DirAccessJAndroid::get_drive_count() {
String DirAccessJAndroid::get_drive(int p_drive) {
if (_get_drive) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND_V(env == nullptr, "");
+ ERR_FAIL_NULL_V(env, "");
jstring j_drive = (jstring)env->CallObjectMethod(dir_access_handler, _get_drive, get_access_type(), p_drive);
if (!j_drive) {
return "";
@@ -191,7 +191,7 @@ String DirAccessJAndroid::get_absolute_path(String p_path) {
bool DirAccessJAndroid::file_exists(String p_file) {
if (_file_exists) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND_V(env == nullptr, false);
+ ERR_FAIL_NULL_V(env, false);
String path = get_absolute_path(p_file);
jstring j_path = env->NewStringUTF(path.utf8().get_data());
@@ -206,7 +206,7 @@ bool DirAccessJAndroid::file_exists(String p_file) {
bool DirAccessJAndroid::dir_exists(String p_dir) {
if (_dir_exists) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND_V(env == nullptr, false);
+ ERR_FAIL_NULL_V(env, false);
String path = get_absolute_path(p_dir);
jstring j_path = env->NewStringUTF(path.utf8().get_data());
@@ -226,7 +226,7 @@ Error DirAccessJAndroid::make_dir_recursive(String p_dir) {
if (_make_dir) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND_V(env == nullptr, ERR_UNCONFIGURED);
+ ERR_FAIL_NULL_V(env, ERR_UNCONFIGURED);
String path = get_absolute_path(p_dir);
jstring j_dir = env->NewStringUTF(path.utf8().get_data());
@@ -249,7 +249,7 @@ Error DirAccessJAndroid::make_dir(String p_dir) {
Error DirAccessJAndroid::rename(String p_from, String p_to) {
if (_rename) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND_V(env == nullptr, ERR_UNCONFIGURED);
+ ERR_FAIL_NULL_V(env, ERR_UNCONFIGURED);
String from_path = get_absolute_path(p_from);
jstring j_from = env->NewStringUTF(from_path.utf8().get_data());
@@ -273,7 +273,7 @@ Error DirAccessJAndroid::rename(String p_from, String p_to) {
Error DirAccessJAndroid::remove(String p_name) {
if (_remove) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND_V(env == nullptr, ERR_UNCONFIGURED);
+ ERR_FAIL_NULL_V(env, ERR_UNCONFIGURED);
String path = get_absolute_path(p_name);
jstring j_name = env->NewStringUTF(path.utf8().get_data());
@@ -292,7 +292,7 @@ Error DirAccessJAndroid::remove(String p_name) {
uint64_t DirAccessJAndroid::get_space_left() {
if (_get_space_left) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND_V(env == nullptr, 0);
+ ERR_FAIL_NULL_V(env, 0);
return env->CallLongMethod(dir_access_handler, _get_space_left, get_access_type());
} else {
return 0;
@@ -331,7 +331,7 @@ DirAccessJAndroid::~DirAccessJAndroid() {
int DirAccessJAndroid::dir_open(String p_path) {
if (_dir_open) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND_V(env == nullptr, 0);
+ ERR_FAIL_NULL_V(env, 0);
String path = get_absolute_path(p_path);
jstring js = env->NewStringUTF(path.utf8().get_data());
@@ -346,7 +346,7 @@ int DirAccessJAndroid::dir_open(String p_path) {
void DirAccessJAndroid::dir_close(int p_id) {
if (_dir_close) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND(env == nullptr);
+ ERR_FAIL_NULL(env);
env->CallVoidMethod(dir_access_handler, _dir_close, get_access_type(), p_id);
}
}
diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp
index f02b292868..11c0945ce0 100644
--- a/platform/android/display_server_android.cpp
+++ b/platform/android/display_server_android.cpp
@@ -111,6 +111,20 @@ void DisplayServerAndroid::tts_stop() {
TTS_Android::stop();
}
+bool DisplayServerAndroid::is_dark_mode_supported() const {
+ GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();
+ ERR_FAIL_NULL_V(godot_java, false);
+
+ return godot_java->is_dark_mode_supported();
+}
+
+bool DisplayServerAndroid::is_dark_mode() const {
+ GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();
+ ERR_FAIL_NULL_V(godot_java, false);
+
+ return godot_java->is_dark_mode();
+}
+
void DisplayServerAndroid::clipboard_set(const String &p_text) {
GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();
ERR_FAIL_NULL(godot_java);
@@ -543,7 +557,7 @@ DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, Dis
#if defined(GLES3_ENABLED)
if (rendering_driver == "opengl3") {
- RasterizerGLES3::make_current();
+ RasterizerGLES3::make_current(false);
}
#endif
diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h
index e0ad2cb916..54912212dc 100644
--- a/platform/android/display_server_android.h
+++ b/platform/android/display_server_android.h
@@ -103,6 +103,9 @@ public:
virtual void tts_resume() override;
virtual void tts_stop() override;
+ virtual bool is_dark_mode_supported() const override;
+ virtual bool is_dark_mode() const override;
+
virtual void clipboard_set(const String &p_text) override;
virtual String clipboard_get() const override;
virtual bool clipboard_has() const override;
diff --git a/platform/android/doc_classes/EditorExportPlatformAndroid.xml b/platform/android/doc_classes/EditorExportPlatformAndroid.xml
index d270980d72..0f1da54376 100644
--- a/platform/android/doc_classes/EditorExportPlatformAndroid.xml
+++ b/platform/android/doc_classes/EditorExportPlatformAndroid.xml
@@ -8,6 +8,7 @@
<tutorials>
<link title="Exporting for Android">$DOCS_URL/tutorials/export/exporting_for_android.html</link>
<link title="Custom builds for Android">$DOCS_URL/tutorials/export/android_custom_build.html</link>
+ <link title="Android plugins documentation index">$DOCS_URL/tutorials/platform/index.html</link>
</tutorials>
<members>
<member name="apk_expansion/SALT" type="String" setter="" getter="">
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 32b46271fd..682603e46b 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -53,6 +53,9 @@ void register_android_exporter() {
EDITOR_DEF("export/android/shutdown_adb_on_exit", true);
EDITOR_DEF("export/android/one_click_deploy_clear_previous_install", false);
+
+ EDITOR_DEF("export/android/use_wifi_for_remote_debug", false);
+ EDITOR_DEF("export/android/wifi_remote_debug_host", "localhost");
#endif
Ref<EditorExportPlatformAndroid> exporter = Ref<EditorExportPlatformAndroid>(memnew(EditorExportPlatformAndroid));
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index 21de46f4fc..aeaa7b9ce7 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -1832,7 +1832,7 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/code", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 1));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "version/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Leave empty to use project version"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/unique_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "ext.domain.name"), "org.godotengine.$genname", false, true));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/unique_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "ext.domain.name"), "com.example.$genname", false, true));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name [default if blank]"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "package/signed"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "package/app_category", PROPERTY_HINT_ENUM, "Accessibility,Audio,Game,Image,Maps,News,Productivity,Social,Video"), APP_CATEGORY_GAME));
@@ -1954,8 +1954,9 @@ Error EditorExportPlatformAndroid::run(const Ref<EditorExportPreset> &p_preset,
return ERR_SKIP;
}
+ 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_reverse = devices[p_device].api_level >= 21;
+ 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;
@@ -2068,7 +2069,10 @@ Error EditorExportPlatformAndroid::run(const Ref<EditorExportPreset> &p_preset,
print_line("Reverse result2: " + itos(rv));
}
} else {
- static const char *const msg = "--- Device API < 21; debugging over Wi-Fi ---";
+ static const char *const api_version_msg = "--- Device API < 21; debugging over Wi-Fi ---";
+ static const char *const manual_override_msg = "--- Wi-Fi remote debug enabled in project settings; debugging over Wi-Fi ---";
+
+ const char *const msg = use_wifi_for_remote_debug ? manual_override_msg : api_version_msg;
EditorNode::get_singleton()->get_log()->add_message(msg, EditorLog::MSG_TYPE_EDITOR);
print_line(String(msg).to_upper());
}
@@ -2631,6 +2635,8 @@ void EditorExportPlatformAndroid::_clear_assets_directory() {
if (da_res->dir_exists(APK_ASSETS_DIRECTORY)) {
print_verbose("Clearing APK assets directory...");
Ref<DirAccess> da_assets = DirAccess::open(APK_ASSETS_DIRECTORY);
+ ERR_FAIL_COND(da_assets.is_null());
+
da_assets->erase_contents_recursive();
da_res->remove(APK_ASSETS_DIRECTORY);
}
@@ -2639,6 +2645,8 @@ void EditorExportPlatformAndroid::_clear_assets_directory() {
if (da_res->dir_exists(AAB_ASSETS_DIRECTORY)) {
print_verbose("Clearing AAB assets directory...");
Ref<DirAccess> da_assets = DirAccess::open(AAB_ASSETS_DIRECTORY);
+ ERR_FAIL_COND(da_assets.is_null());
+
da_assets->erase_contents_recursive();
da_res->remove(AAB_ASSETS_DIRECTORY);
}
diff --git a/platform/android/file_access_filesystem_jandroid.cpp b/platform/android/file_access_filesystem_jandroid.cpp
index a1865fb1d4..beea73fd61 100644
--- a/platform/android/file_access_filesystem_jandroid.cpp
+++ b/platform/android/file_access_filesystem_jandroid.cpp
@@ -69,7 +69,7 @@ Error FileAccessFilesystemJAndroid::open_internal(const String &p_path, int p_mo
if (_file_open) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND_V(env == nullptr, ERR_UNCONFIGURED);
+ ERR_FAIL_NULL_V(env, ERR_UNCONFIGURED);
String path = fix_path(p_path).simplify_path();
jstring js = env->NewStringUTF(path.utf8().get_data());
@@ -103,7 +103,7 @@ void FileAccessFilesystemJAndroid::_close() {
if (_file_close) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND(env == nullptr);
+ ERR_FAIL_NULL(env);
env->CallVoidMethod(file_access_handler, _file_close, id);
}
id = 0;
@@ -116,7 +116,7 @@ bool FileAccessFilesystemJAndroid::is_open() const {
void FileAccessFilesystemJAndroid::seek(uint64_t p_position) {
if (_file_seek) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND(env == nullptr);
+ ERR_FAIL_NULL(env);
ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use.");
env->CallVoidMethod(file_access_handler, _file_seek, id, p_position);
}
@@ -125,7 +125,7 @@ void FileAccessFilesystemJAndroid::seek(uint64_t p_position) {
void FileAccessFilesystemJAndroid::seek_end(int64_t p_position) {
if (_file_seek_end) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND(env == nullptr);
+ ERR_FAIL_NULL(env);
ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use.");
env->CallVoidMethod(file_access_handler, _file_seek_end, id, p_position);
}
@@ -134,7 +134,7 @@ void FileAccessFilesystemJAndroid::seek_end(int64_t p_position) {
uint64_t FileAccessFilesystemJAndroid::get_position() const {
if (_file_tell) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND_V(env == nullptr, 0);
+ ERR_FAIL_NULL_V(env, 0);
ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
return env->CallLongMethod(file_access_handler, _file_tell, id);
} else {
@@ -145,7 +145,7 @@ uint64_t FileAccessFilesystemJAndroid::get_position() const {
uint64_t FileAccessFilesystemJAndroid::get_length() const {
if (_file_get_size) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND_V(env == nullptr, 0);
+ ERR_FAIL_NULL_V(env, 0);
ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
return env->CallLongMethod(file_access_handler, _file_get_size, id);
} else {
@@ -156,7 +156,7 @@ uint64_t FileAccessFilesystemJAndroid::get_length() const {
bool FileAccessFilesystemJAndroid::eof_reached() const {
if (_file_eof) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND_V(env == nullptr, false);
+ ERR_FAIL_NULL_V(env, false);
ERR_FAIL_COND_V_MSG(!is_open(), false, "File must be opened before use.");
return env->CallBooleanMethod(file_access_handler, _file_eof, id);
} else {
@@ -169,7 +169,7 @@ void FileAccessFilesystemJAndroid::_set_eof(bool eof) {
ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use.");
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND(env == nullptr);
+ ERR_FAIL_NULL(env);
env->CallVoidMethod(file_access_handler, _file_set_eof, id, eof);
}
}
@@ -235,7 +235,7 @@ uint64_t FileAccessFilesystemJAndroid::get_buffer(uint8_t *p_dst, uint64_t p_len
}
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND_V(env == nullptr, 0);
+ ERR_FAIL_NULL_V(env, 0);
jobject j_buffer = env->NewDirectByteBuffer(p_dst, p_length);
int length = env->CallIntMethod(file_access_handler, _file_read, id, j_buffer);
@@ -258,7 +258,7 @@ void FileAccessFilesystemJAndroid::store_buffer(const uint8_t *p_src, uint64_t p
}
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND(env == nullptr);
+ ERR_FAIL_NULL(env);
jobject j_buffer = env->NewDirectByteBuffer((void *)p_src, p_length);
env->CallVoidMethod(file_access_handler, _file_write, id, j_buffer);
@@ -276,7 +276,7 @@ Error FileAccessFilesystemJAndroid::get_error() const {
void FileAccessFilesystemJAndroid::flush() {
if (_file_flush) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND(env == nullptr);
+ ERR_FAIL_NULL(env);
ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use.");
env->CallVoidMethod(file_access_handler, _file_flush, id);
}
@@ -285,7 +285,7 @@ void FileAccessFilesystemJAndroid::flush() {
bool FileAccessFilesystemJAndroid::file_exists(const String &p_path) {
if (_file_exists) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND_V(env == nullptr, false);
+ ERR_FAIL_NULL_V(env, false);
String path = fix_path(p_path).simplify_path();
jstring js = env->NewStringUTF(path.utf8().get_data());
@@ -300,7 +300,7 @@ bool FileAccessFilesystemJAndroid::file_exists(const String &p_path) {
uint64_t FileAccessFilesystemJAndroid::_get_modified_time(const String &p_file) {
if (_file_last_modified) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND_V(env == nullptr, false);
+ ERR_FAIL_NULL_V(env, false);
String path = fix_path(p_file).simplify_path();
jstring js = env->NewStringUTF(path.utf8().get_data());
diff --git a/platform/android/java/editor/src/.gitignore b/platform/android/java/editor/src/.gitignore
new file mode 100644
index 0000000000..c081ec3425
--- /dev/null
+++ b/platform/android/java/editor/src/.gitignore
@@ -0,0 +1 @@
+!/debug
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 9c1165bf8a..0e111d5247 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt
@@ -35,6 +35,7 @@ import android.app.Activity
import android.app.AlertDialog
import android.content.*
import android.content.pm.PackageManager
+import android.content.res.Configuration
import android.content.res.Resources
import android.graphics.Rect
import android.hardware.Sensor
@@ -694,6 +695,25 @@ class Godot(private val context: Context) : SensorEventListener {
}
}
+ /**
+ * Returns true if dark mode is supported, false otherwise.
+ */
+ @Keep
+ private fun isDarkModeSupported(): Boolean {
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
+ }
+
+ /**
+ * Returns true if dark mode is supported and enabled, false otherwise.
+ */
+ @Keep
+ private fun isDarkMode(): Boolean {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ return context.resources?.configuration?.uiMode?.and(Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES
+ }
+ return false
+ }
+
fun hasClipboard(): Boolean {
return mClipboard.hasPrimaryClip()
}
@@ -907,6 +927,19 @@ class Godot(private val context: Context) : SensorEventListener {
return PermissionsUtil.getGrantedPermissions(getActivity())
}
+ /**
+ * Get the list of gdextension modules to register.
+ */
+ @Keep
+ private fun getGDExtensionConfigFiles(): Array<String> {
+ val configFiles = mutableSetOf<String>()
+ for (plugin in pluginRegistry.allPlugins) {
+ configFiles.addAll(plugin.pluginGDExtensionLibrariesPaths)
+ }
+
+ return configFiles.toTypedArray()
+ }
+
@Keep
private fun getCACertificates(): String {
return GodotNetUtils.getCACertificates()
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
index b9ecd6971d..fee50e93c2 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
@@ -114,7 +114,7 @@ public class GodotLib {
/**
* Dispatch mouse events
*/
- public static native void dispatchMouseEvent(int event, int buttonMask, float x, float y, float deltaX, float deltaY, boolean doubleClick, boolean sourceMouseRelative);
+ public static native void dispatchMouseEvent(int event, int buttonMask, float x, float y, float deltaX, float deltaY, boolean doubleClick, boolean sourceMouseRelative, float pressure, float tiltX, float tiltY);
public static native void magnify(float x, float y, float factor);
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java
index a7064dfc1d..3070a8a207 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java
@@ -33,6 +33,7 @@ package org.godotengine.godot.input;
import org.godotengine.godot.*;
import android.content.Context;
+import android.content.res.Configuration;
import android.os.Handler;
import android.os.Message;
import android.text.InputFilter;
@@ -209,6 +210,13 @@ public class GodotEditText extends EditText {
mRenderView.getView().requestFocus();
}
+ // When a hardware keyboard is connected, all key events come through so we can route them
+ // directly to the engine.
+ // This is not the case when using a soft keyboard, requiring extra processing from this class.
+ if (hasHardwareKeyboard()) {
+ return mRenderView.getInputHandler().onKeyDown(keyCode, keyEvent);
+ }
+
// pass event to godot in special cases
if (needHandlingInGodot(keyCode, keyEvent) && mRenderView.getInputHandler().onKeyDown(keyCode, keyEvent)) {
return true;
@@ -219,6 +227,13 @@ public class GodotEditText extends EditText {
@Override
public boolean onKeyUp(int keyCode, KeyEvent keyEvent) {
+ // When a hardware keyboard is connected, all key events come through so we can route them
+ // directly to the engine.
+ // This is not the case when using a soft keyboard, requiring extra processing from this class.
+ if (hasHardwareKeyboard()) {
+ return mRenderView.getInputHandler().onKeyUp(keyCode, keyEvent);
+ }
+
if (needHandlingInGodot(keyCode, keyEvent) && mRenderView.getInputHandler().onKeyUp(keyCode, keyEvent)) {
return true;
} else {
@@ -235,10 +250,20 @@ public class GodotEditText extends EditText {
isModifiedKey;
}
+ boolean hasHardwareKeyboard() {
+ Configuration config = getResources().getConfiguration();
+ return config.keyboard != Configuration.KEYBOARD_NOKEYS &&
+ config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO;
+ }
+
// ===========================================================
// Methods
// ===========================================================
public void showKeyboard(String p_existing_text, VirtualKeyboardType p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
+ if (hasHardwareKeyboard()) {
+ return;
+ }
+
int maxInputLength = (p_max_input_length <= 0) ? Integer.MAX_VALUE : p_max_input_length;
if (p_cursor_start == -1) { // cursor position not given
this.mOriginText = p_existing_text;
@@ -262,6 +287,10 @@ public class GodotEditText extends EditText {
}
public void hideKeyboard() {
+ if (hasHardwareKeyboard()) {
+ return;
+ }
+
final Message msg = new Message();
msg.what = HANDLER_CLOSE_IME_KEYBOARD;
msg.obj = this;
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
index 1a25be0460..c8b222254e 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
@@ -433,7 +433,7 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
}
private static boolean isMouseEvent(int eventSource) {
- boolean mouseSource = ((eventSource & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) || ((eventSource & (InputDevice.SOURCE_TOUCHSCREEN | InputDevice.SOURCE_STYLUS)) == InputDevice.SOURCE_STYLUS);
+ boolean mouseSource = ((eventSource & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) || ((eventSource & InputDevice.SOURCE_STYLUS) == InputDevice.SOURCE_STYLUS);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mouseSource = mouseSource || ((eventSource & InputDevice.SOURCE_MOUSE_RELATIVE) == InputDevice.SOURCE_MOUSE_RELATIVE);
}
@@ -470,13 +470,27 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
final float y = event.getY();
final int buttonsMask = event.getButtonState();
+ final float pressure = event.getPressure();
+
+ // Orientation is returned as a radian value between 0 to pi clockwise or 0 to -pi counterclockwise.
+ final float orientation = event.getOrientation();
+
+ // Tilt is zero is perpendicular to the screen and pi/2 is flat on the surface.
+ final float tilt = event.getAxisValue(MotionEvent.AXIS_TILT);
+
+ float tiltMult = (float)Math.sin(tilt);
+
+ // To be consistent with expected tilt.
+ final float tiltX = (float)-Math.sin(orientation) * tiltMult;
+ final float tiltY = (float)Math.cos(orientation) * tiltMult;
+
final float verticalFactor = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
final float horizontalFactor = event.getAxisValue(MotionEvent.AXIS_HSCROLL);
boolean sourceMouseRelative = false;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
sourceMouseRelative = event.isFromSource(InputDevice.SOURCE_MOUSE_RELATIVE);
}
- return handleMouseEvent(eventAction, buttonsMask, x, y, horizontalFactor, verticalFactor, false, sourceMouseRelative);
+ return handleMouseEvent(eventAction, buttonsMask, x, y, horizontalFactor, verticalFactor, false, sourceMouseRelative, pressure, tiltX, tiltY);
}
static boolean handleMouseEvent(int eventAction, int buttonsMask, float x, float y) {
@@ -484,6 +498,10 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
}
static boolean handleMouseEvent(int eventAction, int buttonsMask, float x, float y, float deltaX, float deltaY, boolean doubleClick, boolean sourceMouseRelative) {
+ return handleMouseEvent(eventAction, buttonsMask, x, y, deltaX, deltaY, doubleClick, sourceMouseRelative, 1, 0, 0);
+ }
+
+ static boolean handleMouseEvent(int eventAction, int buttonsMask, float x, float y, float deltaX, float deltaY, boolean doubleClick, boolean sourceMouseRelative, float pressure, float tiltX, float tiltY) {
// Fix the buttonsMask
switch (eventAction) {
case MotionEvent.ACTION_CANCEL:
@@ -511,7 +529,7 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
case MotionEvent.ACTION_HOVER_MOVE:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_SCROLL: {
- GodotLib.dispatchMouseEvent(eventAction, buttonsMask, x, y, deltaX, deltaY, doubleClick, sourceMouseRelative);
+ GodotLib.dispatchMouseEvent(eventAction, buttonsMask, x, y, deltaX, deltaY, doubleClick, sourceMouseRelative, pressure, tiltX, tiltY);
return true;
}
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java
index 48aa231c7a..7f3a3ac7a3 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java
@@ -57,27 +57,28 @@ import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
/**
- * Base class for the Godot Android plugins.
+ * Base class for Godot Android plugins.
* <p>
- * A Godot Android plugin is a regular Android library packaged as an aar archive file with the following caveats:
+ * A Godot Android plugin is an Android library with the following requirements:
* <p>
- * - The library must have a dependency on the Godot Android library (godot-lib.aar).
- * A stable version is available for each release.
+ * - The plugin must have a dependency on the Godot Android library: `implementation "org.godotengine:godot:<godotLibVersion>"`
+ * <p>
+ * - The plugin must include a <meta-data> tag in its Android manifest with the following format:
+ * <meta-data android:name="org.godotengine.plugin.v2.[PluginName]" android:value="[plugin.init.ClassFullName]" />
* <p>
- * - The library must include a <meta-data> tag in its manifest file setup as follow:
- * <meta-data android:name="org.godotengine.plugin.v1.[PluginName]" android:value="[plugin.init.ClassFullName]" />
* Where:
+ * <p>
* - 'PluginName' is the name of the plugin.
- * - 'plugin.init.ClassFullName' is the full name (package + class name) of the plugin class
+ * <p>
+ * - 'plugin.init.ClassFullName' is the full name (package + class name) of the plugin init class
* extending {@link GodotPlugin}.
+ * <p>
+ * A Godot Android plugin can also define and provide c/c++ gdextension libraries, which will be
+ * automatically bundled by the aar build system.
+ * GDExtension ('*.gdextension') config files must be located in the project 'assets' directory and
+ * their paths specified by {@link GodotPlugin#getPluginGDExtensionLibrariesPaths()}.
*
- * A plugin can also define and provide c/c++ gdextension libraries and nativescripts for the target
- * app/game to leverage.
- * The shared library for the gdextension library will be automatically bundled by the aar build
- * system.
- * Godot '*.gdextension' resource files must however be manually defined in the project
- * 'assets' directory. The recommended path for these resources in the 'assets' directory should be:
- * 'godot/plugin/v1/[PluginName]/'
+ * @see <a href="https://docs.godotengine.org/en/stable/tutorials/platform/android/index.html">Android plugins</a>
*/
public abstract class GodotPlugin {
private static final String TAG = GodotPlugin.class.getSimpleName();
@@ -85,6 +86,10 @@ public abstract class GodotPlugin {
private final Godot godot;
private final ConcurrentHashMap<String, SignalInfo> registeredSignals = new ConcurrentHashMap<>();
+ /**
+ * Base constructor passing a {@link Godot} instance through which the plugin can access Godot's
+ * APIs and lifecycle events.
+ */
public GodotPlugin(Godot godot) {
this.godot = godot;
}
@@ -97,7 +102,7 @@ public abstract class GodotPlugin {
}
/**
- * Provides access to the underlying {@link Activity}.
+ * Provides access to the hosting {@link Activity}.
*/
@Nullable
protected Activity getActivity() {
@@ -106,33 +111,16 @@ public abstract class GodotPlugin {
/**
* Register the plugin with Godot native code.
- *
- * This method is invoked on the render thread.
+ * <p>
+ * This method is invoked by the Godot Engine on the render thread.
*/
public final void onRegisterPluginWithGodotNative() {
registeredSignals.putAll(
- registerPluginWithGodotNative(this, getPluginName(), getPluginMethods(), getPluginSignals(),
- getPluginGDExtensionLibrariesPaths()));
- }
-
- /**
- * Register the plugin with Godot native code.
- *
- * This method must be invoked on the render thread.
- */
- public static void registerPluginWithGodotNative(Object pluginObject,
- GodotPluginInfoProvider pluginInfoProvider) {
- registerPluginWithGodotNative(pluginObject, pluginInfoProvider.getPluginName(),
- Collections.emptyList(), pluginInfoProvider.getPluginSignals(),
- pluginInfoProvider.getPluginGDExtensionLibrariesPaths());
-
- // Notify that registration is complete.
- pluginInfoProvider.onPluginRegistered();
+ registerPluginWithGodotNative(this, getPluginName(), getPluginMethods(), getPluginSignals()));
}
private static Map<String, SignalInfo> registerPluginWithGodotNative(Object pluginObject,
- String pluginName, List<String> pluginMethods, Set<SignalInfo> pluginSignals,
- Set<String> pluginGDExtensionLibrariesPaths) {
+ String pluginName, List<String> pluginMethods, Set<SignalInfo> pluginSignals) {
nativeRegisterSingleton(pluginName, pluginObject);
Set<Method> filteredMethods = new HashSet<>();
@@ -176,23 +164,18 @@ public abstract class GodotPlugin {
registeredSignals.put(signalName, signalInfo);
}
- // Get the list of gdextension libraries to register.
- if (!pluginGDExtensionLibrariesPaths.isEmpty()) {
- nativeRegisterGDExtensionLibraries(pluginGDExtensionLibrariesPaths.toArray(new String[0]));
- }
-
return registeredSignals;
}
/**
- * Invoked once during the Godot Android initialization process after creation of the
+ * Invoked once during the initialization process after creation of the
* {@link org.godotengine.godot.GodotRenderView} view.
* <p>
- * The plugin can return a non-null {@link View} layout in order to add it to the Godot view
+ * The plugin can return a non-null {@link View} layout which will be added to the Godot view
* hierarchy.
- *
- * Use shouldBeOnTop() to set whether the plugin's {@link View} should be added on top or behind
- * the main Godot view.
+ * <p>
+ * Use {@link GodotPlugin#shouldBeOnTop()} to specify whether the plugin's {@link View} should
+ * be added on top or behind the main Godot view.
*
* @see Activity#onCreate(Bundle)
* @return the plugin's view to be included; null if no views should be included.
@@ -235,44 +218,52 @@ public abstract class GodotPlugin {
public boolean onMainBackPressed() { return false; }
/**
- * Invoked on the render thread when the Godot setup is complete.
+ * Invoked on the render thread when set up of the Godot engine is complete.
+ * <p>
+ * This is invoked before {@link GodotPlugin#onGodotMainLoopStarted()}.
*/
public void onGodotSetupCompleted() {}
/**
* Invoked on the render thread when the Godot main loop has started.
+ *
+ * This is invoked after {@link GodotPlugin#onGodotSetupCompleted()}.
*/
public void onGodotMainLoopStarted() {}
/**
- * Invoked once per frame on the GL thread after the frame is drawn.
+ * When using the OpenGL renderer, this is invoked once per frame on the GL thread after the
+ * frame is drawn.
*/
public void onGLDrawFrame(GL10 gl) {}
/**
- * Called on the GL thread after the surface is created and whenever the OpenGL ES surface size
- * changes.
+ * When using the OpenGL renderer, this is called on the GL thread after the surface is created
+ * and whenever the OpenGL ES surface size changes.
*/
public void onGLSurfaceChanged(GL10 gl, int width, int height) {}
/**
- * Called on the GL thread when the surface is created or recreated.
+ * When using the OpenGL renderer, this is called on the GL thread when the surface is created
+ * or recreated.
*/
public void onGLSurfaceCreated(GL10 gl, EGLConfig config) {}
/**
- * Invoked once per frame on the Vulkan thread after the frame is drawn.
+ * When using the Vulkan renderer, this is invoked once per frame on the Vulkan thread after
+ * the frame is drawn.
*/
public void onVkDrawFrame() {}
/**
- * Called on the Vulkan thread after the surface is created and whenever the surface size
- * changes.
+ * When using the Vulkan renderer, this is called on the Vulkan thread after the surface is
+ * created and whenever the surface size changes.
*/
public void onVkSurfaceChanged(Surface surface, int width, int height) {}
/**
- * Called on the Vulkan thread when the surface is created or recreated.
+ * When using the Vulkan renderer, this is called on the Vulkan thread when the surface is
+ * created or recreated.
*/
public void onVkSurfaceCreated(Surface surface) {}
@@ -287,7 +278,7 @@ public abstract class GodotPlugin {
/**
* Returns the list of methods to be exposed to Godot.
*
- * @deprecated Used the {@link UsedByGodot} annotation instead.
+ * @deprecated Use the {@link UsedByGodot} annotation instead.
*/
@NonNull
@Deprecated
@@ -304,19 +295,19 @@ public abstract class GodotPlugin {
}
/**
- * Returns the paths for the plugin's gdextension libraries.
- *
- * The paths must be relative to the 'assets' directory and point to a '*.gdextension' file.
+ * Returns the paths for the plugin's gdextension libraries (if any).
+ * <p>
+ * Each returned path must be relative to the 'assets' directory and point to a '*.gdextension' file.
*/
@NonNull
- protected Set<String> getPluginGDExtensionLibrariesPaths() {
+ public Set<String> getPluginGDExtensionLibrariesPaths() {
return Collections.emptySet();
}
/**
- * Returns whether the plugin's {@link View} returned in onMainCreate() should be placed on
- * top of the main Godot view.
- *
+ * Returns whether the plugin's {@link View} returned in
+ * {@link GodotPlugin#onMainCreate(Activity)} should be placed on top of the main Godot view.
+ * <p>
* Returning false causes the plugin's {@link View} to be placed behind, which can be useful
* when used with transparency in order to let the Godot view handle inputs.
*/
@@ -359,7 +350,7 @@ public abstract class GodotPlugin {
}
emitSignal(getGodot(), getPluginName(), signalInfo, signalArgs);
} catch (IllegalArgumentException exception) {
- Log.w(TAG, exception.getMessage());
+ Log.w(TAG, exception);
if (BuildConfig.DEBUG) {
throw exception;
}
@@ -368,7 +359,7 @@ public abstract class GodotPlugin {
/**
* Emit a Godot signal.
- * @param godot
+ * @param godot Godot instance
* @param pluginName Name of the Godot plugin the signal will be emitted from. The plugin must already be registered with the Godot engine.
* @param signalInfo Information about the signal to emit.
* @param signalArgs Arguments used to populate the emitted signal. The arguments will be validated against the given {@link SignalInfo} parameter.
@@ -397,7 +388,7 @@ public abstract class GodotPlugin {
godot.runOnRenderThread(() -> nativeEmitSignal(pluginName, signalInfo.getName(), signalArgs));
} catch (IllegalArgumentException exception) {
- Log.w(TAG, exception.getMessage());
+ Log.w(TAG, exception);
if (BuildConfig.DEBUG) {
throw exception;
}
@@ -420,13 +411,7 @@ public abstract class GodotPlugin {
private static native void nativeRegisterMethod(String p_sname, String p_name, String p_ret, String[] p_params);
/**
- * Used to register gdextension libraries bundled by the plugin.
- * @param gdextensionPaths Paths to the libraries relative to the 'assets' directory.
- */
- private static native void nativeRegisterGDExtensionLibraries(String[] gdextensionPaths);
-
- /**
- * Used to complete registration of the {@link GodotPlugin} instance's methods.
+ * Used to complete registration of the {@link GodotPlugin} instance's signals.
* @param pluginName Name of the plugin
* @param signalName Name of the signal to register
* @param signalParamTypes Signal parameters types
diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java
index c2428de2e1..d338b72441 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java
@@ -52,7 +52,14 @@ import java.util.concurrent.ConcurrentHashMap;
public final class GodotPluginRegistry {
private static final String TAG = GodotPluginRegistry.class.getSimpleName();
+ /**
+ * Prefix used for version 1 of the Godot plugin, mostly compatible with Godot 3.x
+ */
private static final String GODOT_PLUGIN_V1_NAME_PREFIX = "org.godotengine.plugin.v1.";
+ /**
+ * Prefix used for version 2 of the Godot plugin, compatible with Godot 4.2+
+ */
+ private static final String GODOT_PLUGIN_V2_NAME_PREFIX = "org.godotengine.plugin.v2.";
private static GodotPluginRegistry instance;
private final ConcurrentHashMap<String, GodotPlugin> registry;
@@ -123,11 +130,17 @@ public final class GodotPluginRegistry {
return;
}
- int godotPluginV1NamePrefixLength = GODOT_PLUGIN_V1_NAME_PREFIX.length();
for (String metaDataName : metaData.keySet()) {
// Parse the meta-data looking for entry with the Godot plugin name prefix.
- if (metaDataName.startsWith(GODOT_PLUGIN_V1_NAME_PREFIX)) {
- String pluginName = metaDataName.substring(godotPluginV1NamePrefixLength).trim();
+ String pluginName = null;
+ if (metaDataName.startsWith(GODOT_PLUGIN_V2_NAME_PREFIX)) {
+ pluginName = metaDataName.substring(GODOT_PLUGIN_V2_NAME_PREFIX.length()).trim();
+ } else if (metaDataName.startsWith(GODOT_PLUGIN_V1_NAME_PREFIX)) {
+ pluginName = metaDataName.substring(GODOT_PLUGIN_V1_NAME_PREFIX.length()).trim();
+ Log.w(TAG, "Godot v1 plugin are deprecated in Godot 4.2 and higher: " + pluginName);
+ }
+
+ if (!TextUtils.isEmpty(pluginName)) {
Log.i(TAG, "Initializing Godot plugin " + pluginName);
// Retrieve the plugin class full name.
@@ -149,15 +162,7 @@ public final class GodotPluginRegistry {
}
registry.put(pluginName, pluginHandle);
Log.i(TAG, "Completed initialization for Godot plugin " + pluginHandle.getPluginName());
- } catch (ClassNotFoundException e) {
- Log.w(TAG, "Unable to load Godot plugin " + pluginName, e);
- } catch (IllegalAccessException e) {
- Log.w(TAG, "Unable to load Godot plugin " + pluginName, e);
- } catch (InstantiationException e) {
- Log.w(TAG, "Unable to load Godot plugin " + pluginName, e);
- } catch (NoSuchMethodException e) {
- Log.w(TAG, "Unable to load Godot plugin " + pluginName, e);
- } catch (InvocationTargetException e) {
+ } catch (Exception e) {
Log.w(TAG, "Unable to load Godot plugin " + pluginName, e);
}
} else {
@@ -165,7 +170,7 @@ public final class GodotPluginRegistry {
}
}
}
- } catch (PackageManager.NameNotFoundException e) {
+ } catch (Exception e) {
Log.e(TAG, "Unable load Godot Android plugins from the manifest file.", e);
}
}
diff --git a/platform/android/java_class_wrapper.cpp b/platform/android/java_class_wrapper.cpp
index edc934e927..d6455cbf1c 100644
--- a/platform/android/java_class_wrapper.cpp
+++ b/platform/android/java_class_wrapper.cpp
@@ -50,14 +50,14 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
}
int pc = E.param_types.size();
- if (pc > p_argcount) {
+ if (p_argcount < pc) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = pc;
+ r_error.expected = pc;
continue;
}
- if (pc < p_argcount) {
+ if (p_argcount > pc) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
- r_error.argument = pc;
+ r_error.expected = pc;
continue;
}
uint32_t *ptypes = E.param_types.ptrw();
diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp
index 74605e3377..50075ed3f5 100644
--- a/platform/android/java_godot_lib_jni.cpp
+++ b/platform/android/java_godot_lib_jni.cpp
@@ -274,12 +274,12 @@ JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env,
}
// Called on the UI thread
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_dispatchMouseEvent(JNIEnv *env, jclass clazz, jint p_event_type, jint p_button_mask, jfloat p_x, jfloat p_y, jfloat p_delta_x, jfloat p_delta_y, jboolean p_double_click, jboolean p_source_mouse_relative) {
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_dispatchMouseEvent(JNIEnv *env, jclass clazz, jint p_event_type, jint p_button_mask, jfloat p_x, jfloat p_y, jfloat p_delta_x, jfloat p_delta_y, jboolean p_double_click, jboolean p_source_mouse_relative, jfloat p_pressure, jfloat p_tilt_x, jfloat p_tilt_y) {
if (step.get() <= 0) {
return;
}
- input_handler->process_mouse_event(p_event_type, p_button_mask, Point2(p_x, p_y), Vector2(p_delta_x, p_delta_y), p_double_click, p_source_mouse_relative);
+ input_handler->process_mouse_event(p_event_type, p_button_mask, Point2(p_x, p_y), Vector2(p_delta_x, p_delta_y), p_double_click, p_source_mouse_relative, p_pressure, Vector2(p_tilt_x, p_tilt_y));
}
// Called on the UI thread
diff --git a/platform/android/java_godot_lib_jni.h b/platform/android/java_godot_lib_jni.h
index ee6a19034c..1ddda6c1c8 100644
--- a/platform/android/java_godot_lib_jni.h
+++ b/platform/android/java_godot_lib_jni.h
@@ -45,7 +45,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *en
JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jclass clazz);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ttsCallback(JNIEnv *env, jclass clazz, jint event, jint id, jint pos);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, jclass clazz);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_dispatchMouseEvent(JNIEnv *env, jclass clazz, jint p_event_type, jint p_button_mask, jfloat p_x, jfloat p_y, jfloat p_delta_x, jfloat p_delta_y, jboolean p_double_click, jboolean p_source_mouse_relative);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_dispatchMouseEvent(JNIEnv *env, jclass clazz, jint p_event_type, jint p_button_mask, jfloat p_x, jfloat p_y, jfloat p_delta_x, jfloat p_delta_y, jboolean p_double_click, jboolean p_source_mouse_relative, jfloat p_pressure, jfloat p_tilt_x, jfloat p_tilt_y);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_dispatchTouchEvent(JNIEnv *env, jclass clazz, jint ev, jint pointer, jint pointer_count, jfloatArray positions, jboolean p_double_tap);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_magnify(JNIEnv *env, jclass clazz, jfloat p_x, jfloat p_y, jfloat p_factor);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_pan(JNIEnv *env, jclass clazz, jfloat p_x, jfloat p_y, jfloat p_delta_x, jfloat p_delta_y);
diff --git a/platform/android/java_godot_wrapper.cpp b/platform/android/java_godot_wrapper.cpp
index 79ba2528ba..1703179b8e 100644
--- a/platform/android/java_godot_wrapper.cpp
+++ b/platform/android/java_godot_wrapper.cpp
@@ -62,6 +62,8 @@ GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_
_finish = p_env->GetMethodID(godot_class, "forceQuit", "(I)Z");
_set_keep_screen_on = p_env->GetMethodID(godot_class, "setKeepScreenOn", "(Z)V");
_alert = p_env->GetMethodID(godot_class, "alert", "(Ljava/lang/String;Ljava/lang/String;)V");
+ _is_dark_mode_supported = p_env->GetMethodID(godot_class, "isDarkModeSupported", "()Z");
+ _is_dark_mode = p_env->GetMethodID(godot_class, "isDarkMode", "()Z");
_get_clipboard = p_env->GetMethodID(godot_class, "getClipboard", "()Ljava/lang/String;");
_set_clipboard = p_env->GetMethodID(godot_class, "setClipboard", "(Ljava/lang/String;)V");
_has_clipboard = p_env->GetMethodID(godot_class, "hasClipboard", "()Z");
@@ -79,6 +81,7 @@ GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_
_begin_benchmark_measure = p_env->GetMethodID(godot_class, "nativeBeginBenchmarkMeasure", "(Ljava/lang/String;)V");
_end_benchmark_measure = p_env->GetMethodID(godot_class, "nativeEndBenchmarkMeasure", "(Ljava/lang/String;)V");
_dump_benchmark = p_env->GetMethodID(godot_class, "nativeDumpBenchmark", "(Ljava/lang/String;)V");
+ _get_gdextension_list_config_file = p_env->GetMethodID(godot_class, "getGDExtensionConfigFiles", "()[Ljava/lang/String;");
}
GodotJavaWrapper::~GodotJavaWrapper() {
@@ -171,6 +174,26 @@ void GodotJavaWrapper::alert(const String &p_message, const String &p_title) {
}
}
+bool GodotJavaWrapper::is_dark_mode_supported() {
+ if (_is_dark_mode_supported) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_NULL_V(env, false);
+ return env->CallBooleanMethod(godot_instance, _is_dark_mode_supported);
+ } else {
+ return false;
+ }
+}
+
+bool GodotJavaWrapper::is_dark_mode() {
+ if (_is_dark_mode) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_NULL_V(env, false);
+ return env->CallBooleanMethod(godot_instance, _is_dark_mode);
+ } else {
+ return false;
+ }
+}
+
bool GodotJavaWrapper::has_get_clipboard() {
return _get_clipboard != nullptr;
}
@@ -264,6 +287,25 @@ Vector<String> GodotJavaWrapper::get_granted_permissions() const {
return permissions_list;
}
+Vector<String> GodotJavaWrapper::get_gdextension_list_config_file() const {
+ Vector<String> config_file_list;
+ if (_get_gdextension_list_config_file) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_NULL_V(env, config_file_list);
+ jobject config_file_list_object = env->CallObjectMethod(godot_instance, _get_gdextension_list_config_file);
+ jobjectArray *arr = reinterpret_cast<jobjectArray *>(&config_file_list_object);
+
+ jsize len = env->GetArrayLength(*arr);
+ for (int i = 0; i < len; i++) {
+ jstring j_config_file = (jstring)env->GetObjectArrayElement(*arr, i);
+ String config_file = jstring_to_string(j_config_file, env);
+ config_file_list.push_back(config_file);
+ env->DeleteLocalRef(j_config_file);
+ }
+ }
+ return config_file_list;
+}
+
String GodotJavaWrapper::get_ca_certificates() const {
if (_get_ca_certificates) {
JNIEnv *env = get_jni_env();
diff --git a/platform/android/java_godot_wrapper.h b/platform/android/java_godot_wrapper.h
index ba42d5dccd..f427a2937c 100644
--- a/platform/android/java_godot_wrapper.h
+++ b/platform/android/java_godot_wrapper.h
@@ -53,12 +53,15 @@ private:
jmethodID _finish = nullptr;
jmethodID _set_keep_screen_on = nullptr;
jmethodID _alert = nullptr;
+ jmethodID _is_dark_mode_supported = nullptr;
+ jmethodID _is_dark_mode = nullptr;
jmethodID _get_clipboard = nullptr;
jmethodID _set_clipboard = nullptr;
jmethodID _has_clipboard = nullptr;
jmethodID _request_permission = nullptr;
jmethodID _request_permissions = nullptr;
jmethodID _get_granted_permissions = nullptr;
+ jmethodID _get_gdextension_list_config_file = nullptr;
jmethodID _get_ca_certificates = nullptr;
jmethodID _init_input_devices = nullptr;
jmethodID _vibrate = nullptr;
@@ -85,6 +88,8 @@ public:
bool force_quit(JNIEnv *p_env = nullptr, int p_instance_id = 0);
void set_keep_screen_on(bool p_enabled);
void alert(const String &p_message, const String &p_title);
+ bool is_dark_mode_supported();
+ bool is_dark_mode();
bool has_get_clipboard();
String get_clipboard();
bool has_set_clipboard();
@@ -102,6 +107,9 @@ public:
void begin_benchmark_measure(const String &p_label);
void end_benchmark_measure(const String &p_label);
void dump_benchmark(const String &benchmark_file);
+
+ // Return the list of gdextensions config file.
+ Vector<String> get_gdextension_list_config_file() const;
};
#endif // JAVA_GODOT_WRAPPER_H
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index c040d8c4c6..8f80516a9f 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -39,6 +39,8 @@
#include "net_socket_android.h"
#include "core/config/project_settings.h"
+#include "core/extension/gdextension_manager.h"
+#include "core/io/xml_parser.h"
#include "drivers/unix/dir_access_unix.h"
#include "drivers/unix/file_access_unix.h"
#include "main/main.h"
@@ -162,11 +164,39 @@ Vector<String> OS_Android::get_granted_permissions() const {
Error OS_Android::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) {
String path = p_path;
+ bool so_file_exists = true;
if (!FileAccess::exists(path)) {
path = p_path.get_file();
+ so_file_exists = false;
}
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
+ if (!p_library_handle && so_file_exists) {
+ // The library may be on the sdcard and thus inaccessible. Try to copy it to the internal
+ // directory.
+ uint64_t so_modified_time = FileAccess::get_modified_time(p_path);
+ String dynamic_library_path = get_dynamic_libraries_path().path_join(String::num_uint64(so_modified_time));
+ String internal_path = dynamic_library_path.path_join(p_path.get_file());
+
+ bool internal_so_file_exists = FileAccess::exists(internal_path);
+ if (!internal_so_file_exists) {
+ Ref<DirAccess> da_ref = DirAccess::create_for_path(p_path);
+ if (da_ref.is_valid()) {
+ Error create_dir_result = da_ref->make_dir_recursive(dynamic_library_path);
+ if (create_dir_result == OK || create_dir_result == ERR_ALREADY_EXISTS) {
+ internal_so_file_exists = da_ref->copy(path, internal_path) == OK;
+ }
+ }
+ }
+
+ if (internal_so_file_exists) {
+ p_library_handle = dlopen(internal_path.utf8().get_data(), RTLD_NOW);
+ if (p_library_handle) {
+ path = internal_path;
+ }
+ }
+ }
+
ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror()));
if (r_resolved_path != nullptr) {
@@ -584,6 +614,10 @@ String OS_Android::get_user_data_dir() const {
return ".";
}
+String OS_Android::get_dynamic_libraries_path() const {
+ return get_cache_path().path_join("dynamic_libraries");
+}
+
String OS_Android::get_cache_path() const {
if (!cache_dir_cache.is_empty()) {
return cache_dir_cache;
@@ -791,5 +825,13 @@ Error OS_Android::setup_remote_filesystem(const String &p_server_host, int p_por
return err;
}
+void OS_Android::load_platform_gdextensions() const {
+ Vector<String> extension_list_config_file = godot_java->get_gdextension_list_config_file();
+ for (String config_file_path : extension_list_config_file) {
+ GDExtensionManager::LoadStatus err = GDExtensionManager::get_singleton()->load_extension(config_file_path);
+ ERR_CONTINUE_MSG(err == GDExtensionManager::LOAD_STATUS_FAILED, "Error loading platform extension: " + config_file_path);
+ }
+}
+
OS_Android::~OS_Android() {
}
diff --git a/platform/android/os_android.h b/platform/android/os_android.h
index abcc412588..f88f3e0518 100644
--- a/platform/android/os_android.h
+++ b/platform/android/os_android.h
@@ -169,9 +169,15 @@ public:
virtual void benchmark_end_measure(const String &p_what) override;
virtual void benchmark_dump() override;
+ virtual void load_platform_gdextensions() const override;
+
virtual bool _check_internal_feature_support(const String &p_feature) override;
OS_Android(GodotJavaWrapper *p_godot_java, GodotIOJavaWrapper *p_godot_io_java, bool p_use_apk_expansion);
~OS_Android();
+
+private:
+ // Location where we relocate external dynamic libraries to make them accessible.
+ String get_dynamic_libraries_path() const;
};
#endif // OS_ANDROID_H
diff --git a/platform/uwp/context_egl_uwp.h b/platform/android/platform_gl.h
index 810c3dcbc1..af6edb103d 100644
--- a/platform/uwp/context_egl_uwp.h
+++ b/platform/android/platform_gl.h
@@ -1,5 +1,5 @@
/**************************************************************************/
-/* context_egl_uwp.h */
+/* platform_gl.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,57 +28,16 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
-#ifndef CONTEXT_EGL_UWP_H
-#define CONTEXT_EGL_UWP_H
+#ifndef PLATFORM_GL_H
+#define PLATFORM_GL_H
-#include "core/error/error_list.h"
-#include "core/os/os.h"
+#ifndef GLES_API_ENABLED
+#define GLES_API_ENABLED // Allow using GLES.
+#endif
#include <EGL/egl.h>
-#include <wrl.h>
+#include <EGL/eglext.h>
+#include <GLES3/gl3.h>
+#include <GLES3/gl3ext.h>
-using namespace Windows::UI::Core;
-
-class ContextEGL_UWP {
-public:
- enum Driver {
- GLES_2_0,
- VULKAN, // FIXME: Add Vulkan support.
- };
-
-private:
- CoreWindow ^ window;
-
- EGLDisplay mEglDisplay;
- EGLContext mEglContext;
- EGLSurface mEglSurface;
-
- EGLint width;
- EGLint height;
-
- bool vsync;
-
- Driver driver;
-
-public:
- void release_current();
-
- void make_current();
-
- int get_window_width();
- int get_window_height();
- void swap_buffers();
-
- void set_use_vsync(bool use) { vsync = use; }
- bool is_using_vsync() const { return vsync; }
-
- Error initialize();
- void reset();
-
- void cleanup();
-
- ContextEGL_UWP(CoreWindow ^ p_window, Driver p_driver);
- ~ContextEGL_UWP();
-};
-
-#endif // CONTEXT_EGL_UWP_H
+#endif // PLATFORM_GL_H
diff --git a/platform/android/plugin/godot_plugin_jni.cpp b/platform/android/plugin/godot_plugin_jni.cpp
index 5d48c4e248..fd60ba4ae7 100644
--- a/platform/android/plugin/godot_plugin_jni.cpp
+++ b/platform/android/plugin/godot_plugin_jni.cpp
@@ -129,31 +129,4 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitS
singleton->emit_signalp(StringName(signal_name), args, count);
}
-
-JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterGDExtensionLibraries(JNIEnv *env, jclass clazz, jobjectArray gdextension_paths) {
- int gdextension_count = env->GetArrayLength(gdextension_paths);
- if (gdextension_count == 0) {
- return;
- }
-
- // Retrieve the current list of gdextension libraries.
- Array singletons;
- if (ProjectSettings::get_singleton()->has_setting("gdextension/singletons")) {
- singletons = GLOBAL_GET("gdextension/singletons");
- }
-
- // Insert the libraries provided by the plugin
- for (int i = 0; i < gdextension_count; i++) {
- jstring relative_path = (jstring)env->GetObjectArrayElement(gdextension_paths, i);
-
- String path = "res://" + jstring_to_string(relative_path, env);
- if (!singletons.has(path)) {
- singletons.push_back(path);
- }
- env->DeleteLocalRef(relative_path);
- }
-
- // Insert the updated list back into project settings.
- ProjectSettings::get_singleton()->set("gdextension/singletons", singletons);
-}
}
diff --git a/platform/android/plugin/godot_plugin_jni.h b/platform/android/plugin/godot_plugin_jni.h
index 36a992246d..baa29a79ea 100644
--- a/platform/android/plugin/godot_plugin_jni.h
+++ b/platform/android/plugin/godot_plugin_jni.h
@@ -39,7 +39,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegis
JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterMethod(JNIEnv *env, jclass clazz, jstring sname, jstring name, jstring ret, jobjectArray args);
JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSignal(JNIEnv *env, jclass clazz, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_param_types);
JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitSignal(JNIEnv *env, jclass clazz, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_params);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterGDExtensionLibraries(JNIEnv *env, jclass clazz, jobjectArray gdextension_paths);
}
#endif // GODOT_PLUGIN_JNI_H
diff --git a/platform/android/tts_android.cpp b/platform/android/tts_android.cpp
index aef59c2584..93517d8045 100644
--- a/platform/android/tts_android.cpp
+++ b/platform/android/tts_android.cpp
@@ -54,7 +54,7 @@ void TTS_Android::setup(jobject p_tts) {
bool tts_enabled = GLOBAL_GET("audio/general/text_to_speech");
if (tts_enabled) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND(env == nullptr);
+ ERR_FAIL_NULL(env);
tts = env->NewGlobalRef(p_tts);
@@ -103,7 +103,7 @@ bool TTS_Android::is_speaking() {
if (_is_speaking) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND_V(env == nullptr, false);
+ ERR_FAIL_NULL_V(env, false);
return env->CallBooleanMethod(tts, _is_speaking);
} else {
return false;
@@ -115,7 +115,7 @@ bool TTS_Android::is_paused() {
if (_is_paused) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND_V(env == nullptr, false);
+ ERR_FAIL_NULL_V(env, false);
return env->CallBooleanMethod(tts, _is_paused);
} else {
return false;
@@ -127,7 +127,7 @@ Array TTS_Android::get_voices() {
Array list;
if (_get_voices) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND_V(env == nullptr, list);
+ ERR_FAIL_NULL_V(env, list);
jobject voices_object = env->CallObjectMethod(tts, _get_voices);
jobjectArray *arr = reinterpret_cast<jobjectArray *>(&voices_object);
@@ -165,7 +165,7 @@ void TTS_Android::speak(const String &p_text, const String &p_voice, int p_volum
if (_speak) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND(env == nullptr);
+ ERR_FAIL_NULL(env);
jstring jStrT = env->NewStringUTF(p_text.utf8().get_data());
jstring jStrV = env->NewStringUTF(p_voice.utf8().get_data());
@@ -178,7 +178,7 @@ void TTS_Android::pause() {
if (_pause_speaking) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND(env == nullptr);
+ ERR_FAIL_NULL(env);
env->CallVoidMethod(tts, _pause_speaking);
}
}
@@ -188,7 +188,7 @@ void TTS_Android::resume() {
if (_resume_speaking) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND(env == nullptr);
+ ERR_FAIL_NULL(env);
env->CallVoidMethod(tts, _resume_speaking);
}
}
@@ -203,7 +203,7 @@ void TTS_Android::stop() {
if (_stop_speaking) {
JNIEnv *env = get_jni_env();
- ERR_FAIL_COND(env == nullptr);
+ ERR_FAIL_NULL(env);
env->CallVoidMethod(tts, _stop_speaking);
}
}
diff --git a/platform/ios/detect.py b/platform/ios/detect.py
index e11c0b7d91..40eb61abc8 100644
--- a/platform/ios/detect.py
+++ b/platform/ios/detect.py
@@ -103,13 +103,13 @@ def configure(env: "Environment"):
if env["ios_simulator"]:
detect_darwin_sdk_path("iossimulator", env)
- env.Append(ASFLAGS=["-mios-simulator-version-min=11.0"])
- env.Append(CCFLAGS=["-mios-simulator-version-min=11.0"])
+ env.Append(ASFLAGS=["-mios-simulator-version-min=12.0"])
+ env.Append(CCFLAGS=["-mios-simulator-version-min=12.0"])
env.extra_suffix = ".simulator" + env.extra_suffix
else:
detect_darwin_sdk_path("ios", env)
- env.Append(ASFLAGS=["-miphoneos-version-min=11.0"])
- env.Append(CCFLAGS=["-miphoneos-version-min=11.0"])
+ env.Append(ASFLAGS=["-miphoneos-version-min=12.0"])
+ env.Append(CCFLAGS=["-miphoneos-version-min=12.0"])
if env["arch"] == "x86_64":
if not env["ios_simulator"]:
@@ -154,7 +154,7 @@ def configure(env: "Environment"):
env.Append(CPPDEFINES=["VULKAN_ENABLED"])
if env["opengl3"]:
- env.Append(CPPDEFINES=["GLES3_ENABLED"])
+ env.Append(CPPDEFINES=["GLES3_ENABLED", "GLES_SILENCE_DEPRECATION"])
env.Prepend(
CPPPATH=[
"$IOS_SDK_PATH/System/Library/Frameworks/OpenGLES.framework/Headers",
diff --git a/platform/ios/display_server_ios.h b/platform/ios/display_server_ios.h
index da16449c61..be4ea1e6ab 100644
--- a/platform/ios/display_server_ios.h
+++ b/platform/ios/display_server_ios.h
@@ -141,6 +141,9 @@ public:
virtual void tts_resume() override;
virtual void tts_stop() override;
+ virtual bool is_dark_mode_supported() const override;
+ virtual bool is_dark_mode() const override;
+
virtual Rect2i get_display_safe_area() const override;
virtual int get_screen_count() const override;
diff --git a/platform/ios/display_server_ios.mm b/platform/ios/display_server_ios.mm
index 7d91274a0c..489894a135 100644
--- a/platform/ios/display_server_ios.mm
+++ b/platform/ios/display_server_ios.mm
@@ -103,7 +103,7 @@ DisplayServerIOS::DisplayServerIOS(const String &p_rendering_driver, WindowMode
ERR_FAIL_MSG("Failed to create iOS OpenGLES rendering layer.");
}
- RasterizerGLES3::make_current();
+ RasterizerGLES3::make_current(false);
}
#endif
@@ -354,20 +354,32 @@ void DisplayServerIOS::tts_stop() {
[tts stopSpeaking];
}
-Rect2i DisplayServerIOS::get_display_safe_area() const {
- if (@available(iOS 11, *)) {
- UIEdgeInsets insets = UIEdgeInsetsZero;
- UIView *view = AppDelegate.viewController.godotView;
- if ([view respondsToSelector:@selector(safeAreaInsets)]) {
- insets = [view safeAreaInsets];
- }
- float scale = screen_get_scale();
- Size2i insets_position = Size2i(insets.left, insets.top) * scale;
- Size2i insets_size = Size2i(insets.left + insets.right, insets.top + insets.bottom) * scale;
- return Rect2i(screen_get_position() + insets_position, screen_get_size() - insets_size);
+bool DisplayServerIOS::is_dark_mode_supported() const {
+ if (@available(iOS 13.0, *)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool DisplayServerIOS::is_dark_mode() const {
+ if (@available(iOS 13.0, *)) {
+ return [UITraitCollection currentTraitCollection].userInterfaceStyle == UIUserInterfaceStyleDark;
} else {
- return Rect2i(screen_get_position(), screen_get_size());
+ return false;
+ }
+}
+
+Rect2i DisplayServerIOS::get_display_safe_area() const {
+ UIEdgeInsets insets = UIEdgeInsetsZero;
+ UIView *view = AppDelegate.viewController.godotView;
+ if ([view respondsToSelector:@selector(safeAreaInsets)]) {
+ insets = [view safeAreaInsets];
}
+ float scale = screen_get_scale();
+ Size2i insets_position = Size2i(insets.left, insets.top) * scale;
+ Size2i insets_size = Size2i(insets.left + insets.right, insets.top + insets.bottom) * scale;
+ return Rect2i(screen_get_position() + insets_position, screen_get_size() - insets_size);
}
int DisplayServerIOS::get_screen_count() const {
diff --git a/platform/ios/doc_classes/EditorExportPlatformIOS.xml b/platform/ios/doc_classes/EditorExportPlatformIOS.xml
index 563c057266..ecae6d721e 100644
--- a/platform/ios/doc_classes/EditorExportPlatformIOS.xml
+++ b/platform/ios/doc_classes/EditorExportPlatformIOS.xml
@@ -7,6 +7,7 @@
</description>
<tutorials>
<link title="Exporting for iOS">$DOCS_URL/tutorials/export/exporting_for_ios.html</link>
+ <link title="iOS plugins documentation index">$DOCS_URL/tutorials/platform/ios/index.html</link>
</tutorials>
<members>
<member name="application/app_store_team_id" type="String" setter="" getter="">
diff --git a/platform/ios/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp
index b6320fb22b..a8596c30a6 100644
--- a/platform/ios/export/export_plugin.cpp
+++ b/platform/ios/export/export_plugin.cpp
@@ -38,6 +38,7 @@
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
#include "editor/editor_scale.h"
+#include "editor/editor_string_names.h"
#include "editor/export/editor_export.h"
#include "editor/import/resource_importer_texture_settings.h"
#include "editor/plugins/script_editor_plugin.h"
@@ -2013,11 +2014,11 @@ Ref<ImageTexture> EditorExportPlatformIOS::get_option_icon(int p_index) const {
Ref<Theme> theme = EditorNode::get_singleton()->get_editor_theme();
if (theme.is_valid()) {
if (devices[p_index].simulator) {
- icon = theme->get_icon("IOSSimulator", "EditorIcons");
+ icon = theme->get_icon("IOSSimulator", EditorStringName(EditorIcons));
} else if (devices[p_index].wifi) {
- icon = theme->get_icon("IOSDeviceWireless", "EditorIcons");
+ icon = theme->get_icon("IOSDeviceWireless", EditorStringName(EditorIcons));
} else {
- icon = theme->get_icon("IOSDeviceWired", "EditorIcons");
+ icon = theme->get_icon("IOSDeviceWired", EditorStringName(EditorIcons));
}
}
}
diff --git a/platform/ios/export/export_plugin.h b/platform/ios/export/export_plugin.h
index 7de4c0b69d..27a4d73fcd 100644
--- a/platform/ios/export/export_plugin.h
+++ b/platform/ios/export/export_plugin.h
@@ -181,9 +181,17 @@ public:
virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override {
List<String> list;
- list.push_back("ipa");
+ if (p_preset.is_valid()) {
+ bool project_only = p_preset->get("application/export_project_only");
+ if (project_only) {
+ list.push_back("xcodeproj");
+ } else {
+ list.push_back("ipa");
+ }
+ }
return list;
}
+
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int 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;
diff --git a/platform/ios/godot_view.mm b/platform/ios/godot_view.mm
index 4c9a75fdc0..ff8a4f8921 100644
--- a/platform/ios/godot_view.mm
+++ b/platform/ios/godot_view.mm
@@ -82,10 +82,10 @@ static const float earth_gravity = 9.80665;
layer = [GodotMetalLayer layer];
#endif
} else if ([driverName isEqualToString:@"opengl3"]) {
- if (@available(iOS 13, *)) {
- NSLog(@"OpenGL ES is deprecated on iOS 13");
- }
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations" // OpenGL is deprecated in iOS 12.0
layer = [GodotOpenGLLayer layer];
+#pragma clang diagnostic pop
} else {
return nil;
}
diff --git a/platform/ios/os_ios.mm b/platform/ios/os_ios.mm
index 50102e02cc..68e6d4c934 100644
--- a/platform/ios/os_ios.mm
+++ b/platform/ios/os_ios.mm
@@ -257,7 +257,7 @@ Error OS_IOS::open_dynamic_library(const String p_path, void *&p_library_handle,
}
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
- ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror()));
+ ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror()));
if (r_resolved_path != nullptr) {
*r_resolved_path = path;
diff --git a/platform/ios/platform_config.h b/platform/ios/platform_config.h
index fc0e165d6b..01b0a12b5d 100644
--- a/platform/ios/platform_config.h
+++ b/platform/ios/platform_config.h
@@ -30,8 +30,6 @@
#include <alloca.h>
-#define OPENGL_INCLUDE_H <ES3/gl.h>
-
#define PTHREAD_RENAME_SELF
#define _weakify(var) __weak typeof(var) GDWeak_##var = var;
diff --git a/platform/uwp/export/export.h b/platform/ios/platform_gl.h
index d2053e02b1..974ea9d2c2 100644
--- a/platform/uwp/export/export.h
+++ b/platform/ios/platform_gl.h
@@ -1,5 +1,5 @@
/**************************************************************************/
-/* export.h */
+/* platform_gl.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,10 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
-#ifndef UWP_EXPORT_H
-#define UWP_EXPORT_H
+#ifndef PLATFORM_GL_H
+#define PLATFORM_GL_H
-void register_uwp_exporter_types();
-void register_uwp_exporter();
+#ifndef GLES_API_ENABLED
+#define GLES_API_ENABLED // Allow using GLES.
+#endif
-#endif // UWP_EXPORT_H
+#include <ES3/gl.h>
+
+#endif // PLATFORM_GL_H
diff --git a/platform/ios/view_controller.mm b/platform/ios/view_controller.mm
index 0ef61da646..1f55670b68 100644
--- a/platform/ios/view_controller.mm
+++ b/platform/ios/view_controller.mm
@@ -161,9 +161,7 @@
[self observeKeyboard];
[self displayLoadingOverlay];
- if (@available(iOS 11.0, *)) {
- [self setNeedsUpdateOfScreenEdgesDeferringSystemGestures];
- }
+ [self setNeedsUpdateOfScreenEdgesDeferringSystemGestures];
}
- (void)observeKeyboard {
diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py
index a723bb5d58..72bffceb1f 100644
--- a/platform/linuxbsd/detect.py
+++ b/platform/linuxbsd/detect.py
@@ -106,7 +106,7 @@ def configure(env: "Environment"):
print("Using linker program: " + env["linker"])
if env["linker"] == "mold" and using_gcc(env): # GCC < 12.1 doesn't support -fuse-ld=mold.
cc_version = get_compiler_version(env)
- cc_semver = (int(cc_version["major"]), int(cc_version["minor"]))
+ cc_semver = (cc_version["major"], cc_version["minor"])
if cc_semver < (12, 1):
found_wrapper = False
for path in ["/usr/libexec", "/usr/local/libexec", "/usr/lib", "/usr/local/lib"]:
@@ -455,7 +455,7 @@ def configure(env: "Environment"):
linker_version_str = subprocess.check_output(
[env.subst(env["LINK"]), "-Wl,--version"] + env.subst(env["LINKFLAGS"])
).decode("utf-8")
- gnu_ld_version = re.search("^GNU ld [^$]*(\d+\.\d+)$", linker_version_str, re.MULTILINE)
+ gnu_ld_version = re.search(r"^GNU ld [^$]*(\d+\.\d+)$", linker_version_str, re.MULTILINE)
if not gnu_ld_version:
print(
"Warning: Creating export template binaries enabled for PCK embedding is currently only supported with GNU ld, not gold, LLD or mold."
diff --git a/platform/linuxbsd/export/export_plugin.cpp b/platform/linuxbsd/export/export_plugin.cpp
index 40151b1a02..9d1e058b76 100644
--- a/platform/linuxbsd/export/export_plugin.cpp
+++ b/platform/linuxbsd/export/export_plugin.cpp
@@ -37,6 +37,7 @@
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
#include "editor/editor_scale.h"
+#include "editor/editor_string_names.h"
#include "editor/export/editor_export.h"
#include "modules/modules_enabled.gen.h" // For svg.
@@ -530,7 +531,7 @@ EditorExportPlatformLinuxBSD::EditorExportPlatformLinuxBSD() {
Ref<Theme> theme = EditorNode::get_singleton()->get_editor_theme();
if (theme.is_valid()) {
- stop_icon = theme->get_icon(SNAME("Stop"), SNAME("EditorIcons"));
+ stop_icon = theme->get_icon(SNAME("Stop"), EditorStringName(EditorIcons));
} else {
stop_icon.instantiate();
}
diff --git a/platform/linuxbsd/godot_linuxbsd.cpp b/platform/linuxbsd/godot_linuxbsd.cpp
index d059d60b72..efad9c8594 100644
--- a/platform/linuxbsd/godot_linuxbsd.cpp
+++ b/platform/linuxbsd/godot_linuxbsd.cpp
@@ -56,7 +56,7 @@ int main(int argc, char *argv[]) {
TEST_MAIN_OVERRIDE
char *cwd = (char *)malloc(PATH_MAX);
- ERR_FAIL_COND_V(!cwd, ERR_OUT_OF_MEMORY);
+ ERR_FAIL_NULL_V(cwd, ERR_OUT_OF_MEMORY);
char *ret = getcwd(cwd, PATH_MAX);
Error err = Main::setup(argv[0], argc - 1, &argv[1]);
diff --git a/platform/linuxbsd/platform_config.h b/platform/linuxbsd/platform_config.h
index 82c9c54879..c372ef28f6 100644
--- a/platform/linuxbsd/platform_config.h
+++ b/platform/linuxbsd/platform_config.h
@@ -43,5 +43,3 @@
#define PTHREAD_BSD_SET_NAME
#endif
#endif
-
-#define OPENGL_INCLUDE_H "thirdparty/glad/glad/gl.h"
diff --git a/platform/linuxbsd/platform_gl.h b/platform/linuxbsd/platform_gl.h
new file mode 100644
index 0000000000..1c19c4518a
--- /dev/null
+++ b/platform/linuxbsd/platform_gl.h
@@ -0,0 +1,41 @@
+/**************************************************************************/
+/* platform_gl.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef PLATFORM_GL_H
+#define PLATFORM_GL_H
+
+#ifndef GL_API_ENABLED
+#define GL_API_ENABLED // Allow using desktop GL.
+#endif
+
+#include "thirdparty/glad/glad/egl.h"
+#include "thirdparty/glad/glad/gl.h"
+
+#endif // PLATFORM_GL_H
diff --git a/platform/linuxbsd/tts_linux.cpp b/platform/linuxbsd/tts_linux.cpp
index 8bc83f5b9c..96745ab8ae 100644
--- a/platform/linuxbsd/tts_linux.cpp
+++ b/platform/linuxbsd/tts_linux.cpp
@@ -186,7 +186,7 @@ bool TTS_Linux::is_paused() const {
Array TTS_Linux::get_voices() const {
_THREAD_SAFE_METHOD_
- ERR_FAIL_COND_V(!synth, Array());
+ ERR_FAIL_NULL_V(synth, Array());
const_cast<TTS_Linux *>(this)->_load_voices();
Array list;
@@ -204,7 +204,7 @@ Array TTS_Linux::get_voices() const {
void TTS_Linux::speak(const String &p_text, const String &p_voice, int p_volume, float p_pitch, float p_rate, int p_utterance_id, bool p_interrupt) {
_THREAD_SAFE_METHOD_
- ERR_FAIL_COND(!synth);
+ ERR_FAIL_NULL(synth);
if (p_interrupt) {
stop();
}
@@ -233,7 +233,7 @@ void TTS_Linux::speak(const String &p_text, const String &p_voice, int p_volume,
void TTS_Linux::pause() {
_THREAD_SAFE_METHOD_
- ERR_FAIL_COND(!synth);
+ ERR_FAIL_NULL(synth);
if (spd_pause(synth) == 0) {
paused = true;
}
@@ -242,7 +242,7 @@ void TTS_Linux::pause() {
void TTS_Linux::resume() {
_THREAD_SAFE_METHOD_
- ERR_FAIL_COND(!synth);
+ ERR_FAIL_NULL(synth);
spd_resume(synth);
paused = false;
}
@@ -250,7 +250,7 @@ void TTS_Linux::resume() {
void TTS_Linux::stop() {
_THREAD_SAFE_METHOD_
- ERR_FAIL_COND(!synth);
+ ERR_FAIL_NULL(synth);
for (DisplayServer::TTSUtterance &message : queue) {
DisplayServer::get_singleton()->tts_post_utterance_event(DisplayServer::TTS_UTTERANCE_CANCELED, message.id);
}
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index f38a9dd278..897a6438d2 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -307,37 +307,37 @@ void DisplayServerX11::_flush_mouse_motion() {
#ifdef SPEECHD_ENABLED
bool DisplayServerX11::tts_is_speaking() const {
- ERR_FAIL_COND_V_MSG(!tts, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
+ ERR_FAIL_NULL_V_MSG(tts, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
return tts->is_speaking();
}
bool DisplayServerX11::tts_is_paused() const {
- ERR_FAIL_COND_V_MSG(!tts, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
+ ERR_FAIL_NULL_V_MSG(tts, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
return tts->is_paused();
}
TypedArray<Dictionary> DisplayServerX11::tts_get_voices() const {
- ERR_FAIL_COND_V_MSG(!tts, TypedArray<Dictionary>(), "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
+ ERR_FAIL_NULL_V_MSG(tts, TypedArray<Dictionary>(), "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
return tts->get_voices();
}
void DisplayServerX11::tts_speak(const String &p_text, const String &p_voice, int p_volume, float p_pitch, float p_rate, int p_utterance_id, bool p_interrupt) {
- ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
+ ERR_FAIL_NULL_MSG(tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
tts->speak(p_text, p_voice, p_volume, p_pitch, p_rate, p_utterance_id, p_interrupt);
}
void DisplayServerX11::tts_pause() {
- ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
+ ERR_FAIL_NULL_MSG(tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
tts->pause();
}
void DisplayServerX11::tts_resume() {
- ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
+ ERR_FAIL_NULL_MSG(tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
tts->resume();
}
void DisplayServerX11::tts_stop() {
- ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
+ ERR_FAIL_NULL_MSG(tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
tts->stop();
}
@@ -5100,7 +5100,7 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
XVisualInfo vInfoTemplate = {};
vInfoTemplate.screen = DefaultScreen(x11_display);
XVisualInfo *vi_list = XGetVisualInfo(x11_display, visualMask, &vInfoTemplate, &numberOfVisuals);
- ERR_FAIL_COND_V(!vi_list, INVALID_WINDOW_ID);
+ ERR_FAIL_NULL_V(vi_list, INVALID_WINDOW_ID);
visualInfo = vi_list[0];
if (OS::get_singleton()->is_layered_allowed()) {
@@ -5821,7 +5821,7 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
driver_found = true;
if (true) {
- RasterizerGLES3::make_current();
+ RasterizerGLES3::make_current(true);
} else {
memdelete(gl_manager);
gl_manager = nullptr;
diff --git a/platform/linuxbsd/x11/gl_manager_x11.cpp b/platform/linuxbsd/x11/gl_manager_x11.cpp
index f24bac5e19..95947301cf 100644
--- a/platform/linuxbsd/x11/gl_manager_x11.cpp
+++ b/platform/linuxbsd/x11/gl_manager_x11.cpp
@@ -103,7 +103,7 @@ Error GLManager_X11::_create_context(GLDisplay &gl_display) {
GLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (GLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((const GLubyte *)"glXCreateContextAttribsARB");
- ERR_FAIL_COND_V(!glXCreateContextAttribsARB, ERR_UNCONFIGURED);
+ ERR_FAIL_NULL_V(glXCreateContextAttribsARB, ERR_UNCONFIGURED);
static int visual_attribs[] = {
GLX_RENDER_TYPE, GLX_RGBA_BIT,
@@ -134,7 +134,7 @@ Error GLManager_X11::_create_context(GLDisplay &gl_display) {
if (OS::get_singleton()->is_layered_allowed()) {
GLXFBConfig *fbc = glXChooseFBConfig(x11_display, DefaultScreen(x11_display), visual_attribs_layered, &fbcount);
- ERR_FAIL_COND_V(!fbc, ERR_UNCONFIGURED);
+ ERR_FAIL_NULL_V(fbc, ERR_UNCONFIGURED);
for (int i = 0; i < fbcount; i++) {
vi = (XVisualInfo *)glXGetVisualFromFBConfig(x11_display, fbc[i]);
@@ -156,10 +156,10 @@ Error GLManager_X11::_create_context(GLDisplay &gl_display) {
}
XFree(fbc);
- ERR_FAIL_COND_V(!fbconfig, ERR_UNCONFIGURED);
+ ERR_FAIL_NULL_V(fbconfig, ERR_UNCONFIGURED);
} else {
GLXFBConfig *fbc = glXChooseFBConfig(x11_display, DefaultScreen(x11_display), visual_attribs, &fbcount);
- ERR_FAIL_COND_V(!fbc, ERR_UNCONFIGURED);
+ ERR_FAIL_NULL_V(fbc, ERR_UNCONFIGURED);
vi = glXGetVisualFromFBConfig(x11_display, fbc[0]);
@@ -347,12 +347,6 @@ Error GLManager_X11::initialize(Display *p_display) {
}
void GLManager_X11::set_use_vsync(bool p_use) {
- // force vsync in the editor for now, as a safety measure
- bool is_editor = Engine::get_singleton()->is_editor_hint();
- if (is_editor) {
- p_use = true;
- }
-
// we need an active window to get a display to set the vsync
if (!_current_window) {
return;
@@ -368,6 +362,7 @@ void GLManager_X11::set_use_vsync(bool p_use) {
GLXDrawable drawable = glXGetCurrentDrawable();
glXSwapIntervalEXT(disp.x11_display, drawable, val);
} else {
+ WARN_PRINT("Could not set V-Sync mode. V-Sync is not supported.");
return;
}
use_vsync = p_use;
diff --git a/platform/macos/SCsub b/platform/macos/SCsub
index 7ffb80f70b..30202e5de7 100644
--- a/platform/macos/SCsub
+++ b/platform/macos/SCsub
@@ -24,6 +24,7 @@ files = [
"tts_macos.mm",
"joypad_macos.cpp",
"vulkan_context_macos.mm",
+ "gl_manager_macos_angle.mm",
"gl_manager_macos_legacy.mm",
]
diff --git a/platform/macos/detect.py b/platform/macos/detect.py
index 21e824b2d3..b41d2141fb 100644
--- a/platform/macos/detect.py
+++ b/platform/macos/detect.py
@@ -1,6 +1,6 @@
import os
import sys
-from methods import detect_darwin_sdk_path
+from methods import detect_darwin_sdk_path, get_compiler_version, is_vanilla_clang
from platform_methods import detect_arch
from typing import TYPE_CHECKING
@@ -32,6 +32,7 @@ def get_opts():
BoolVariable("use_asan", "Use LLVM/GCC compiler address sanitizer (ASAN)", False),
BoolVariable("use_tsan", "Use LLVM/GCC compiler thread sanitizer (TSAN)", False),
BoolVariable("use_coverage", "Use instrumentation codes in the binary (e.g. for code coverage)", False),
+ ("angle_libs", "Path to the ANGLE static libraries", ""),
]
@@ -119,6 +120,15 @@ def configure(env: "Environment"):
env.Append(CCFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.13"])
env.Append(LINKFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.13"])
+ cc_version = get_compiler_version(env)
+ cc_version_major = cc_version["major"]
+ cc_version_minor = cc_version["minor"]
+ vanilla = is_vanilla_clang(env)
+
+ # Workaround for Xcode 15 linker bug.
+ if not vanilla and cc_version_major == 15 and cc_version_minor == 0:
+ env.Prepend(LINKFLAGS=["-ld_classic"])
+
env.Append(CCFLAGS=["-fobjc-arc"])
if not "osxcross" in env: # regular native build
@@ -239,7 +249,13 @@ def configure(env: "Environment"):
if env["opengl3"]:
env.Append(CPPDEFINES=["GLES3_ENABLED"])
- env.Append(LINKFLAGS=["-framework", "OpenGL"])
+ if env["angle_libs"] != "":
+ env.AppendUnique(CPPDEFINES=["EGL_STATIC"])
+ env.Append(LINKFLAGS=["-L" + env["angle_libs"]])
+ env.Append(LINKFLAGS=["-lANGLE.macos." + env["arch"]])
+ env.Append(LINKFLAGS=["-lEGL.macos." + env["arch"]])
+ env.Append(LINKFLAGS=["-lGLES.macos." + env["arch"]])
+ env.Prepend(CPPPATH=["#thirdparty/angle/include"])
env.Append(LINKFLAGS=["-rpath", "@executable_path/../Frameworks", "-rpath", "@executable_path"])
diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h
index 69f6008043..d89511927e 100644
--- a/platform/macos/display_server_macos.h
+++ b/platform/macos/display_server_macos.h
@@ -35,6 +35,7 @@
#include "servers/display_server.h"
#if defined(GLES3_ENABLED)
+#include "gl_manager_macos_angle.h"
#include "gl_manager_macos_legacy.h"
#endif // GLES3_ENABLED
@@ -127,7 +128,8 @@ public:
private:
#if defined(GLES3_ENABLED)
- GLManager_MacOS *gl_manager = nullptr;
+ GLManagerLegacy_MacOS *gl_manager_legacy = nullptr;
+ GLManagerANGLE_MacOS *gl_manager_angle = nullptr;
#endif
#if defined(VULKAN_ENABLED)
VulkanContextMacOS *context_vulkan = nullptr;
@@ -244,7 +246,6 @@ public:
void mouse_enter_window(WindowID p_window);
void mouse_exit_window(WindowID p_window);
- void window_update(WindowID p_window);
void window_destroy(WindowID p_window);
void window_resize(WindowID p_window, int p_width, int p_height);
void window_set_custom_window_buttons(WindowData &p_wd, bool p_enabled);
@@ -367,6 +368,7 @@ public:
virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Size2i window_get_title_size(const String &p_title, WindowID p_window) const override;
virtual void window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window = MAIN_WINDOW_ID) override;
virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const override;
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index e79d6acc3f..4e1ceac8bf 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -139,7 +139,7 @@ DisplayServerMacOS::WindowID DisplayServerMacOS::_create_window(WindowMode p_mod
// initWithContentRect uses bottom-left corner of the window’s frame as origin.
wd.window_object = [[GodotWindow alloc]
- initWithContentRect:NSMakeRect(100, 100, p_rect.size.width / scale, p_rect.size.height / scale)
+ initWithContentRect:NSMakeRect(100, 100, MAX(1, p_rect.size.width / scale), MAX(1, p_rect.size.height / scale))
styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable
backing:NSBackingStoreBuffered
defer:NO];
@@ -185,9 +185,13 @@ DisplayServerMacOS::WindowID DisplayServerMacOS::_create_window(WindowMode p_mod
}
#endif
#if defined(GLES3_ENABLED)
- if (gl_manager) {
- Error err = gl_manager->window_create(window_id_counter, wd.window_view, p_rect.size.width, p_rect.size.height);
- ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create an OpenGL context");
+ if (gl_manager_legacy) {
+ Error err = gl_manager_legacy->window_create(window_id_counter, wd.window_view, p_rect.size.width, p_rect.size.height);
+ ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create an OpenGL context.");
+ }
+ if (gl_manager_angle) {
+ Error err = gl_manager_angle->window_create(window_id_counter, nullptr, (__bridge void *)[wd.window_view layer], p_rect.size.width, p_rect.size.height);
+ ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create an OpenGL context.");
}
window_set_vsync_mode(p_vsync_mode, window_id_counter);
#endif
@@ -219,8 +223,11 @@ DisplayServerMacOS::WindowID DisplayServerMacOS::_create_window(WindowMode p_mod
}
#if defined(GLES3_ENABLED)
- if (gl_manager) {
- gl_manager->window_resize(id, wd.size.width, wd.size.height);
+ if (gl_manager_legacy) {
+ gl_manager_legacy->window_resize(id, wd.size.width, wd.size.height);
+ }
+ if (gl_manager_angle) {
+ gl_manager_angle->window_resize(id, wd.size.width, wd.size.height);
}
#endif
#if defined(VULKAN_ENABLED)
@@ -279,8 +286,8 @@ void DisplayServerMacOS::_set_window_per_pixel_transparency_enabled(bool p_enabl
[layer setOpaque:NO];
}
#if defined(GLES3_ENABLED)
- if (gl_manager) {
- gl_manager->window_set_per_pixel_transparency_enabled(p_window, true);
+ if (gl_manager_legacy) {
+ gl_manager_legacy->window_set_per_pixel_transparency_enabled(p_window, true);
}
#endif
wd.layered_window = true;
@@ -299,8 +306,8 @@ void DisplayServerMacOS::_set_window_per_pixel_transparency_enabled(bool p_enabl
[layer setOpaque:YES];
}
#if defined(GLES3_ENABLED)
- if (gl_manager) {
- gl_manager->window_set_per_pixel_transparency_enabled(p_window, false);
+ if (gl_manager_legacy) {
+ gl_manager_legacy->window_set_per_pixel_transparency_enabled(p_window, false);
}
#endif
wd.layered_window = false;
@@ -730,18 +737,10 @@ bool DisplayServerMacOS::get_is_resizing() const {
return is_resizing;
}
-void DisplayServerMacOS::window_update(WindowID p_window) {
-#if defined(GLES3_ENABLED)
- if (gl_manager) {
- gl_manager->window_update(p_window);
- }
-#endif
-}
-
void DisplayServerMacOS::window_destroy(WindowID p_window) {
#if defined(GLES3_ENABLED)
- if (gl_manager) {
- gl_manager->window_destroy(p_window);
+ if (gl_manager_legacy) {
+ gl_manager_legacy->window_destroy(p_window);
}
#endif
#ifdef VULKAN_ENABLED
@@ -754,8 +753,11 @@ void DisplayServerMacOS::window_destroy(WindowID p_window) {
void DisplayServerMacOS::window_resize(WindowID p_window, int p_width, int p_height) {
#if defined(GLES3_ENABLED)
- if (gl_manager) {
- gl_manager->window_resize(p_window, p_width, p_height);
+ if (gl_manager_legacy) {
+ gl_manager_legacy->window_resize(p_window, p_width, p_height);
+ }
+ if (gl_manager_angle) {
+ gl_manager_angle->window_resize(p_window, p_width, p_height);
}
#endif
#if defined(VULKAN_ENABLED)
@@ -1451,7 +1453,7 @@ void DisplayServerMacOS::global_menu_set_item_checkable(const String &p_menu_roo
NSMenuItem *menu_item = [menu itemAtIndex:p_idx];
if (menu_item) {
GodotMenuItem *obj = [menu_item representedObject];
- ERR_FAIL_COND(!obj);
+ ERR_FAIL_NULL(obj);
obj->checkable_type = (p_checkable) ? CHECKABLE_TYPE_CHECK_BOX : CHECKABLE_TYPE_NONE;
}
}
@@ -1470,7 +1472,7 @@ void DisplayServerMacOS::global_menu_set_item_radio_checkable(const String &p_me
NSMenuItem *menu_item = [menu itemAtIndex:p_idx];
if (menu_item) {
GodotMenuItem *obj = [menu_item representedObject];
- ERR_FAIL_COND(!obj);
+ ERR_FAIL_NULL(obj);
obj->checkable_type = (p_checkable) ? CHECKABLE_TYPE_RADIO_BUTTON : CHECKABLE_TYPE_NONE;
}
}
@@ -1489,7 +1491,7 @@ void DisplayServerMacOS::global_menu_set_item_callback(const String &p_menu_root
NSMenuItem *menu_item = [menu itemAtIndex:p_idx];
if (menu_item) {
GodotMenuItem *obj = [menu_item representedObject];
- ERR_FAIL_COND(!obj);
+ ERR_FAIL_NULL(obj);
obj->callback = p_callback;
}
}
@@ -1508,7 +1510,7 @@ void DisplayServerMacOS::global_menu_set_item_key_callback(const String &p_menu_
NSMenuItem *menu_item = [menu itemAtIndex:p_idx];
if (menu_item) {
GodotMenuItem *obj = [menu_item representedObject];
- ERR_FAIL_COND(!obj);
+ ERR_FAIL_NULL(obj);
obj->key_callback = p_key_callback;
}
}
@@ -1527,7 +1529,7 @@ void DisplayServerMacOS::global_menu_set_item_tag(const String &p_menu_root, int
NSMenuItem *menu_item = [menu itemAtIndex:p_idx];
if (menu_item) {
GodotMenuItem *obj = [menu_item representedObject];
- ERR_FAIL_COND(!obj);
+ ERR_FAIL_NULL(obj);
obj->meta = p_tag;
}
}
@@ -1642,7 +1644,7 @@ void DisplayServerMacOS::global_menu_set_item_state(const String &p_menu_root, i
NSMenuItem *menu_item = [menu itemAtIndex:p_idx];
if (menu_item) {
GodotMenuItem *obj = [menu_item representedObject];
- ERR_FAIL_COND(!obj);
+ ERR_FAIL_NULL(obj);
obj->state = p_state;
}
}
@@ -1661,7 +1663,7 @@ void DisplayServerMacOS::global_menu_set_item_max_states(const String &p_menu_ro
NSMenuItem *menu_item = [menu itemAtIndex:p_idx];
if (menu_item) {
GodotMenuItem *obj = [menu_item representedObject];
- ERR_FAIL_COND(!obj);
+ ERR_FAIL_NULL(obj);
obj->max_states = p_max_states;
}
}
@@ -1680,7 +1682,7 @@ void DisplayServerMacOS::global_menu_set_item_icon(const String &p_menu_root, in
NSMenuItem *menu_item = [menu itemAtIndex:p_idx];
if (menu_item) {
GodotMenuItem *obj = [menu_item representedObject];
- ERR_FAIL_COND(!obj);
+ ERR_FAIL_NULL(obj);
if (p_icon.is_valid()) {
obj->img = p_icon->get_image();
obj->img = obj->img->duplicate();
@@ -1761,37 +1763,37 @@ void DisplayServerMacOS::global_menu_clear(const String &p_menu_root) {
}
bool DisplayServerMacOS::tts_is_speaking() const {
- ERR_FAIL_COND_V_MSG(!tts, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
+ ERR_FAIL_NULL_V_MSG(tts, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
return [tts isSpeaking];
}
bool DisplayServerMacOS::tts_is_paused() const {
- ERR_FAIL_COND_V_MSG(!tts, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
+ ERR_FAIL_NULL_V_MSG(tts, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
return [tts isPaused];
}
TypedArray<Dictionary> DisplayServerMacOS::tts_get_voices() const {
- ERR_FAIL_COND_V_MSG(!tts, Array(), "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
+ ERR_FAIL_NULL_V_MSG(tts, Array(), "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
return [tts getVoices];
}
void DisplayServerMacOS::tts_speak(const String &p_text, const String &p_voice, int p_volume, float p_pitch, float p_rate, int p_utterance_id, bool p_interrupt) {
- ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
+ ERR_FAIL_NULL_MSG(tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
[tts speak:p_text voice:p_voice volume:p_volume pitch:p_pitch rate:p_rate utterance_id:p_utterance_id interrupt:p_interrupt];
}
void DisplayServerMacOS::tts_pause() {
- ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
+ ERR_FAIL_NULL_MSG(tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
[tts pauseSpeaking];
}
void DisplayServerMacOS::tts_resume() {
- ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
+ ERR_FAIL_NULL_MSG(tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
[tts resumeSpeaking];
}
void DisplayServerMacOS::tts_stop() {
- ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
+ ERR_FAIL_NULL_MSG(tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
[tts stopSpeaking];
}
@@ -2624,6 +2626,47 @@ void DisplayServerMacOS::window_set_title(const String &p_title, WindowID p_wind
[wd.window_object setTitle:[NSString stringWithUTF8String:p_title.utf8().get_data()]];
}
+Size2i DisplayServerMacOS::window_get_title_size(const String &p_title, WindowID p_window) const {
+ _THREAD_SAFE_METHOD_
+
+ Size2i size;
+ ERR_FAIL_COND_V(!windows.has(p_window), size);
+
+ const WindowData &wd = windows[p_window];
+ if (wd.fullscreen || wd.borderless) {
+ return size;
+ }
+ if ([wd.window_object respondsToSelector:@selector(isMiniaturized)]) {
+ if ([wd.window_object isMiniaturized]) {
+ return size;
+ }
+ }
+
+ float scale = screen_get_max_scale();
+
+ if (wd.window_button_view) {
+ size.x = ([wd.window_button_view getOffset].x + [wd.window_button_view frame].size.width);
+ size.y = ([wd.window_button_view getOffset].y + [wd.window_button_view frame].size.height);
+ } else {
+ NSButton *cb = [wd.window_object standardWindowButton:NSWindowCloseButton];
+ NSButton *mb = [wd.window_object standardWindowButton:NSWindowMiniaturizeButton];
+ float cb_frame = NSMinX([cb frame]);
+ float mb_frame = NSMinX([mb frame]);
+ bool is_rtl = ([wd.window_object windowTitlebarLayoutDirection] == NSUserInterfaceLayoutDirectionRightToLeft);
+
+ float window_buttons_spacing = (is_rtl) ? (cb_frame - mb_frame) : (mb_frame - cb_frame);
+ size.x = window_buttons_spacing * 4;
+ size.y = [cb frame].origin.y + [cb frame].size.height;
+ }
+
+ NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:[NSFont titleBarFontOfSize:0], NSFontAttributeName, nil];
+ NSSize text_size = [[[NSAttributedString alloc] initWithString:[NSString stringWithUTF8String:p_title.utf8().get_data()] attributes:attributes] size];
+ size.x += text_size.width;
+ size.y = MAX(size.y, text_size.height);
+
+ return size * scale;
+}
+
void DisplayServerMacOS::window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window) {
_THREAD_SAFE_METHOD_
@@ -2912,7 +2955,7 @@ void DisplayServerMacOS::window_set_size(const Size2i p_size, WindowID p_window)
top_left.x = old_frame.origin.x;
top_left.y = NSMaxY(old_frame);
- NSRect new_frame = NSMakeRect(0, 0, size.x, size.y);
+ NSRect new_frame = NSMakeRect(0, 0, MAX(1, size.x), MAX(1, size.y));
new_frame = [wd.window_object frameRectForContentRect:new_frame];
new_frame.origin.x = top_left.x;
@@ -3370,8 +3413,11 @@ int64_t DisplayServerMacOS::window_get_native_handle(HandleType p_handle_type, W
}
#ifdef GLES3_ENABLED
case OPENGL_CONTEXT: {
- if (gl_manager) {
- return (int64_t)gl_manager->get_context(p_window);
+ if (gl_manager_legacy) {
+ return (int64_t)gl_manager_legacy->get_context(p_window);
+ }
+ if (gl_manager_angle) {
+ return (int64_t)gl_manager_angle->get_context(p_window);
}
return 0;
}
@@ -3398,8 +3444,11 @@ ObjectID DisplayServerMacOS::window_get_attached_instance_id(WindowID p_window)
void DisplayServerMacOS::gl_window_make_current(DisplayServer::WindowID p_window_id) {
#if defined(GLES3_ENABLED)
- if (gl_manager) {
- gl_manager->window_make_current(p_window_id);
+ if (gl_manager_legacy) {
+ gl_manager_legacy->window_make_current(p_window_id);
+ }
+ if (gl_manager_angle) {
+ gl_manager_angle->window_make_current(p_window_id);
}
#endif
}
@@ -3407,8 +3456,11 @@ void DisplayServerMacOS::gl_window_make_current(DisplayServer::WindowID p_window
void DisplayServerMacOS::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
_THREAD_SAFE_METHOD_
#if defined(GLES3_ENABLED)
- if (gl_manager) {
- gl_manager->set_use_vsync(p_vsync_mode != DisplayServer::VSYNC_DISABLED);
+ if (gl_manager_angle) {
+ gl_manager_angle->set_use_vsync(p_vsync_mode != DisplayServer::VSYNC_DISABLED);
+ }
+ if (gl_manager_legacy) {
+ gl_manager_legacy->set_use_vsync(p_vsync_mode != DisplayServer::VSYNC_DISABLED);
}
#endif
#if defined(VULKAN_ENABLED)
@@ -3421,8 +3473,11 @@ void DisplayServerMacOS::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_
DisplayServer::VSyncMode DisplayServerMacOS::window_get_vsync_mode(WindowID p_window) const {
_THREAD_SAFE_METHOD_
#if defined(GLES3_ENABLED)
- if (gl_manager) {
- return (gl_manager->is_using_vsync() ? DisplayServer::VSyncMode::VSYNC_ENABLED : DisplayServer::VSyncMode::VSYNC_DISABLED);
+ if (gl_manager_angle) {
+ return (gl_manager_angle->is_using_vsync() ? DisplayServer::VSyncMode::VSYNC_ENABLED : DisplayServer::VSyncMode::VSYNC_DISABLED);
+ }
+ if (gl_manager_legacy) {
+ return (gl_manager_legacy->is_using_vsync() ? DisplayServer::VSyncMode::VSYNC_ENABLED : DisplayServer::VSyncMode::VSYNC_DISABLED);
}
#endif
#if defined(VULKAN_ENABLED)
@@ -3805,8 +3860,11 @@ void DisplayServerMacOS::make_rendering_thread() {
void DisplayServerMacOS::swap_buffers() {
#if defined(GLES3_ENABLED)
- if (gl_manager) {
- gl_manager->swap_buffers();
+ if (gl_manager_angle) {
+ gl_manager_angle->swap_buffers();
+ }
+ if (gl_manager_legacy) {
+ gl_manager_legacy->swap_buffers();
}
#endif
}
@@ -3826,10 +3884,10 @@ void DisplayServerMacOS::set_native_icon(const String &p_filename) {
@try {
NSData *icon_data = [[NSData alloc] initWithBytes:&data.write[0] length:len];
- ERR_FAIL_COND_MSG(!icon_data, "Error reading icon data.");
+ ERR_FAIL_NULL_MSG(icon_data, "Error reading icon data.");
NSImage *icon = [[NSImage alloc] initWithData:icon_data];
- ERR_FAIL_COND_MSG(!icon, "Error loading icon.");
+ ERR_FAIL_NULL_MSG(icon, "Error loading icon.");
[NSApp setApplicationIconImage:icon];
} @catch (NSException *exception) {
@@ -3917,6 +3975,7 @@ Vector<String> DisplayServerMacOS::get_rendering_drivers_func() {
#endif
#if defined(GLES3_ENABLED)
drivers.push_back("opengl3");
+ drivers.push_back("opengl3_angle");
#endif
return drivers;
@@ -4155,13 +4214,22 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM
#if defined(GLES3_ENABLED)
if (rendering_driver == "opengl3") {
- GLManager_MacOS::ContextType opengl_api_type = GLManager_MacOS::GLES_3_0_COMPATIBLE;
- gl_manager = memnew(GLManager_MacOS(opengl_api_type));
- if (gl_manager->initialize() != OK) {
- memdelete(gl_manager);
- gl_manager = nullptr;
+ gl_manager_legacy = memnew(GLManagerLegacy_MacOS);
+ if (gl_manager_legacy->initialize() != OK) {
+ memdelete(gl_manager_legacy);
+ gl_manager_legacy = nullptr;
+ r_error = ERR_UNAVAILABLE;
+ ERR_FAIL_MSG("Could not initialize OpenGL.");
+ return;
+ }
+ }
+ if (rendering_driver == "opengl3_angle") {
+ gl_manager_angle = memnew(GLManagerANGLE_MacOS);
+ if (gl_manager_angle->initialize() != OK) {
+ memdelete(gl_manager_angle);
+ gl_manager_angle = nullptr;
r_error = ERR_UNAVAILABLE;
- ERR_FAIL_MSG("Could not initialize OpenGL");
+ ERR_FAIL_MSG("Could not initialize OpenGL.");
}
}
#endif
@@ -4199,7 +4267,10 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM
#if defined(GLES3_ENABLED)
if (rendering_driver == "opengl3") {
- RasterizerGLES3::make_current();
+ RasterizerGLES3::make_current(true);
+ }
+ if (rendering_driver == "opengl3_angle") {
+ RasterizerGLES3::make_current(false);
}
#endif
#if defined(VULKAN_ENABLED)
@@ -4230,9 +4301,13 @@ DisplayServerMacOS::~DisplayServerMacOS() {
// Destroy drivers.
#if defined(GLES3_ENABLED)
- if (gl_manager) {
- memdelete(gl_manager);
- gl_manager = nullptr;
+ if (gl_manager_legacy) {
+ memdelete(gl_manager_legacy);
+ gl_manager_legacy = nullptr;
+ }
+ if (gl_manager_angle) {
+ memdelete(gl_manager_angle);
+ gl_manager_angle = nullptr;
}
#endif
#if defined(VULKAN_ENABLED)
diff --git a/platform/macos/doc_classes/EditorExportPlatformMacOS.xml b/platform/macos/doc_classes/EditorExportPlatformMacOS.xml
index c24ff4cb73..99187fe60e 100644
--- a/platform/macos/doc_classes/EditorExportPlatformMacOS.xml
+++ b/platform/macos/doc_classes/EditorExportPlatformMacOS.xml
@@ -22,6 +22,9 @@
<member name="application/copyright_localized" type="Dictionary" setter="" getter="">
Copyright notice for the bundle visible to the user (localized).
</member>
+ <member name="application/export_angle" type="int" setter="" getter="">
+ If set to [code]1[/code], ANGLE libraries are exported with the exported application. If set to [code]0[/code], ANGLE libraries are exported only if [member ProjectSettings.rendering/gl_compatibility/driver] is set to [code]"opengl3_angle"[/code].
+ </member>
<member name="application/icon" type="String" setter="" getter="">
Application icon file. If left empty, it will fallback to [member ProjectSettings.application/config/macos_native_icon], and then to [member ProjectSettings.application/config/icon].
</member>
@@ -155,7 +158,7 @@
If enabled, a wrapper that can be used to run the application with console output is created alongside the exported application.
</member>
<member name="display/high_res" type="bool" setter="" getter="">
- If [code]true[/code], the application is rendered at native display resolution, otherwise it is always rendered at loHPI resolution and upscaled by OS when required.
+ If [code]true[/code], the application is rendered at native display resolution, otherwise it is always rendered at loDPI resolution and upscaled by OS when required.
</member>
<member name="export/distribution_type" type="int" setter="" getter="">
Application distribution target.
diff --git a/platform/macos/export/export_plugin.cpp b/platform/macos/export/export_plugin.cpp
index 6586fe7f82..639a7699ee 100644
--- a/platform/macos/export/export_plugin.cpp
+++ b/platform/macos/export/export_plugin.cpp
@@ -41,6 +41,7 @@
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
#include "editor/editor_scale.h"
+#include "editor/editor_string_names.h"
#include "editor/import/resource_importer_texture_settings.h"
#include "scene/resources/image_texture.h"
@@ -383,6 +384,7 @@ void EditorExportPlatformMacOS::get_export_options(List<ExportOption> *r_options
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "application/copyright_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/min_macos_version"), "10.12"));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/export_angle", PROPERTY_HINT_ENUM, "Auto,Yes,No"), 0, true));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "display/high_res"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "xcode/platform_build"), "14C18"));
@@ -1617,6 +1619,14 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
// Now process our template.
bool found_binary = false;
+ int export_angle = p_preset->get("application/export_angle");
+ bool include_angle_libs = false;
+ if (export_angle == 0) {
+ include_angle_libs = String(GLOBAL_GET("rendering/gl_compatibility/driver.macos")) == "opengl3_angle";
+ } else if (export_angle == 1) {
+ include_angle_libs = true;
+ }
+
while (ret == UNZ_OK && err == OK) {
// Get filename.
unz_file_info info;
@@ -1664,6 +1674,20 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
continue; // next
}
+ if (file == "Contents/Frameworks/libEGL.dylib") {
+ if (!include_angle_libs) {
+ ret = unzGoToNextFile(src_pkg_zip);
+ continue; // skip
+ }
+ }
+
+ if (file == "Contents/Frameworks/libGLESv2.dylib") {
+ if (!include_angle_libs) {
+ ret = unzGoToNextFile(src_pkg_zip);
+ continue; // skip
+ }
+ }
+
if (file == "Contents/Info.plist") {
_fix_plist(p_preset, data, pkg_name);
}
@@ -2460,7 +2484,7 @@ EditorExportPlatformMacOS::EditorExportPlatformMacOS() {
Ref<Theme> theme = EditorNode::get_singleton()->get_editor_theme();
if (theme.is_valid()) {
- stop_icon = theme->get_icon(SNAME("Stop"), SNAME("EditorIcons"));
+ stop_icon = theme->get_icon(SNAME("Stop"), EditorStringName(EditorIcons));
} else {
stop_icon.instantiate();
}
diff --git a/platform/macos/gl_manager_macos_angle.h b/platform/macos/gl_manager_macos_angle.h
new file mode 100644
index 0000000000..919b8ec9c8
--- /dev/null
+++ b/platform/macos/gl_manager_macos_angle.h
@@ -0,0 +1,63 @@
+/**************************************************************************/
+/* gl_manager_macos_angle.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef GL_MANAGER_MACOS_ANGLE_H
+#define GL_MANAGER_MACOS_ANGLE_H
+
+#if defined(MACOS_ENABLED) && defined(GLES3_ENABLED)
+
+#include "core/error/error_list.h"
+#include "core/os/os.h"
+#include "core/templates/local_vector.h"
+#include "drivers/egl/egl_manager.h"
+#include "servers/display_server.h"
+
+#include <AppKit/AppKit.h>
+#include <ApplicationServices/ApplicationServices.h>
+#include <CoreVideo/CoreVideo.h>
+
+class GLManagerANGLE_MacOS : public EGLManager {
+private:
+ virtual const char *_get_platform_extension_name() const override;
+ virtual EGLenum _get_platform_extension_enum() const override;
+ virtual EGLenum _get_platform_api_enum() const override;
+ virtual Vector<EGLAttrib> _get_platform_display_attributes() const override;
+ virtual Vector<EGLint> _get_platform_context_attribs() const override;
+
+public:
+ void window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height) {}
+
+ GLManagerANGLE_MacOS() {}
+ ~GLManagerANGLE_MacOS() {}
+};
+
+#endif // MACOS_ENABLED && GLES3_ENABLED
+
+#endif // GL_MANAGER_MACOS_ANGLE_H
diff --git a/platform/macos/gl_manager_macos_angle.mm b/platform/macos/gl_manager_macos_angle.mm
new file mode 100644
index 0000000000..ec0ca3e1f3
--- /dev/null
+++ b/platform/macos/gl_manager_macos_angle.mm
@@ -0,0 +1,70 @@
+/**************************************************************************/
+/* gl_manager_macos_angle.mm */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "gl_manager_macos_angle.h"
+
+#if defined(MACOS_ENABLED) && defined(GLES3_ENABLED)
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <EGL/eglext_angle.h>
+
+const char *GLManagerANGLE_MacOS::_get_platform_extension_name() const {
+ return "EGL_ANGLE_platform_angle";
+}
+
+EGLenum GLManagerANGLE_MacOS::_get_platform_extension_enum() const {
+ return EGL_PLATFORM_ANGLE_ANGLE;
+}
+
+Vector<EGLAttrib> GLManagerANGLE_MacOS::_get_platform_display_attributes() const {
+ Vector<EGLAttrib> ret;
+ ret.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
+ ret.push_back(EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE);
+ ret.push_back(EGL_NONE);
+
+ return ret;
+}
+
+EGLenum GLManagerANGLE_MacOS::_get_platform_api_enum() const {
+ return EGL_OPENGL_ES_API;
+}
+
+Vector<EGLint> GLManagerANGLE_MacOS::_get_platform_context_attribs() const {
+ Vector<EGLint> ret;
+ ret.push_back(EGL_CONTEXT_CLIENT_VERSION);
+ ret.push_back(3);
+ ret.push_back(EGL_NONE);
+
+ return ret;
+}
+
+#endif // MACOS_ENABLED && GLES3_ENABLED
diff --git a/platform/macos/gl_manager_macos_legacy.h b/platform/macos/gl_manager_macos_legacy.h
index 94d966f4ed..bafe825efb 100644
--- a/platform/macos/gl_manager_macos_legacy.h
+++ b/platform/macos/gl_manager_macos_legacy.h
@@ -45,17 +45,12 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations" // OpenGL is deprecated in macOS 10.14
-class GLManager_MacOS {
-public:
- enum ContextType {
- GLES_3_0_COMPATIBLE,
- };
+typedef CGLError (*CGLEnablePtr)(CGLContextObj ctx, CGLContextEnable pname);
+typedef CGLError (*CGLSetParameterPtr)(CGLContextObj ctx, CGLContextParameter pname, const GLint *params);
+typedef CGLContextObj (*CGLGetCurrentContextPtr)(void);
-private:
+class GLManagerLegacy_MacOS {
struct GLWindow {
- int width = 0;
- int height = 0;
-
id window_view = nullptr;
NSOpenGLContext *context = nullptr;
};
@@ -68,23 +63,21 @@ private:
Error create_context(GLWindow &win);
bool use_vsync = false;
- ContextType context_type;
+ CGLEnablePtr CGLEnable = nullptr;
+ CGLSetParameterPtr CGLSetParameter = nullptr;
+ CGLGetCurrentContextPtr CGLGetCurrentContext = nullptr;
public:
Error window_create(DisplayServer::WindowID p_window_id, id p_view, int p_width, int p_height);
void window_destroy(DisplayServer::WindowID p_window_id);
void window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height);
- int window_get_width(DisplayServer::WindowID p_window_id = 0);
- int window_get_height(DisplayServer::WindowID p_window_id = 0);
-
void release_current();
void make_current();
void swap_buffers();
void window_make_current(DisplayServer::WindowID p_window_id);
- void window_update(DisplayServer::WindowID p_window_id);
void window_set_per_pixel_transparency_enabled(DisplayServer::WindowID p_window_id, bool p_enabled);
Error initialize();
@@ -94,8 +87,8 @@ public:
NSOpenGLContext *get_context(DisplayServer::WindowID p_window_id);
- GLManager_MacOS(ContextType p_context_type);
- ~GLManager_MacOS();
+ GLManagerLegacy_MacOS();
+ ~GLManagerLegacy_MacOS();
};
#pragma clang diagnostic push
diff --git a/platform/macos/gl_manager_macos_legacy.mm b/platform/macos/gl_manager_macos_legacy.mm
index 550e2d5c59..3e5a96bffd 100644
--- a/platform/macos/gl_manager_macos_legacy.mm
+++ b/platform/macos/gl_manager_macos_legacy.mm
@@ -38,7 +38,7 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations" // OpenGL is deprecated in macOS 10.14
-Error GLManager_MacOS::create_context(GLWindow &win) {
+Error GLManagerLegacy_MacOS::create_context(GLWindow &win) {
NSOpenGLPixelFormatAttribute attributes[] = {
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAClosestPolicy,
@@ -64,10 +64,8 @@ Error GLManager_MacOS::create_context(GLWindow &win) {
return OK;
}
-Error GLManager_MacOS::window_create(DisplayServer::WindowID p_window_id, id p_view, int p_width, int p_height) {
+Error GLManagerLegacy_MacOS::window_create(DisplayServer::WindowID p_window_id, id p_view, int p_width, int p_height) {
GLWindow win;
- win.width = p_width;
- win.height = p_height;
win.window_view = p_view;
if (create_context(win) != OK) {
@@ -80,16 +78,13 @@ Error GLManager_MacOS::window_create(DisplayServer::WindowID p_window_id, id p_v
return OK;
}
-void GLManager_MacOS::window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height) {
+void GLManagerLegacy_MacOS::window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height) {
if (!windows.has(p_window_id)) {
return;
}
GLWindow &win = windows[p_window_id];
- win.width = p_width;
- win.height = p_height;
-
GLint dim[2];
dim[0] = p_width;
dim[1] = p_height;
@@ -104,25 +99,7 @@ void GLManager_MacOS::window_resize(DisplayServer::WindowID p_window_id, int p_w
[win.context update];
}
-int GLManager_MacOS::window_get_width(DisplayServer::WindowID p_window_id) {
- if (!windows.has(p_window_id)) {
- return 0;
- }
-
- GLWindow &win = windows[p_window_id];
- return win.width;
-}
-
-int GLManager_MacOS::window_get_height(DisplayServer::WindowID p_window_id) {
- if (!windows.has(p_window_id)) {
- return 0;
- }
-
- GLWindow &win = windows[p_window_id];
- return win.height;
-}
-
-void GLManager_MacOS::window_destroy(DisplayServer::WindowID p_window_id) {
+void GLManagerLegacy_MacOS::window_destroy(DisplayServer::WindowID p_window_id) {
if (!windows.has(p_window_id)) {
return;
}
@@ -134,7 +111,7 @@ void GLManager_MacOS::window_destroy(DisplayServer::WindowID p_window_id) {
windows.erase(p_window_id);
}
-void GLManager_MacOS::release_current() {
+void GLManagerLegacy_MacOS::release_current() {
if (current_window == DisplayServer::INVALID_WINDOW_ID) {
return;
}
@@ -142,7 +119,7 @@ void GLManager_MacOS::release_current() {
[NSOpenGLContext clearCurrentContext];
}
-void GLManager_MacOS::window_make_current(DisplayServer::WindowID p_window_id) {
+void GLManagerLegacy_MacOS::window_make_current(DisplayServer::WindowID p_window_id) {
if (current_window == p_window_id) {
return;
}
@@ -156,7 +133,7 @@ void GLManager_MacOS::window_make_current(DisplayServer::WindowID p_window_id) {
current_window = p_window_id;
}
-void GLManager_MacOS::make_current() {
+void GLManagerLegacy_MacOS::make_current() {
if (current_window == DisplayServer::INVALID_WINDOW_ID) {
return;
}
@@ -168,21 +145,12 @@ void GLManager_MacOS::make_current() {
[win.context makeCurrentContext];
}
-void GLManager_MacOS::swap_buffers() {
+void GLManagerLegacy_MacOS::swap_buffers() {
GLWindow &win = windows[current_window];
[win.context flushBuffer];
}
-void GLManager_MacOS::window_update(DisplayServer::WindowID p_window_id) {
- if (!windows.has(p_window_id)) {
- return;
- }
-
- GLWindow &win = windows[p_window_id];
- [win.context update];
-}
-
-void GLManager_MacOS::window_set_per_pixel_transparency_enabled(DisplayServer::WindowID p_window_id, bool p_enabled) {
+void GLManagerLegacy_MacOS::window_set_per_pixel_transparency_enabled(DisplayServer::WindowID p_window_id, bool p_enabled) {
if (!windows.has(p_window_id)) {
return;
}
@@ -198,26 +166,28 @@ void GLManager_MacOS::window_set_per_pixel_transparency_enabled(DisplayServer::W
[win.context update];
}
-Error GLManager_MacOS::initialize() {
+Error GLManagerLegacy_MacOS::initialize() {
return OK;
}
-void GLManager_MacOS::set_use_vsync(bool p_use) {
+void GLManagerLegacy_MacOS::set_use_vsync(bool p_use) {
use_vsync = p_use;
CGLContextObj ctx = CGLGetCurrentContext();
if (ctx) {
GLint swapInterval = p_use ? 1 : 0;
- CGLSetParameter(ctx, kCGLCPSwapInterval, &swapInterval);
+ if (CGLSetParameter(ctx, kCGLCPSwapInterval, &swapInterval) != kCGLNoError) {
+ WARN_PRINT("Could not set V-Sync mode.");
+ }
use_vsync = p_use;
}
}
-bool GLManager_MacOS::is_using_vsync() const {
+bool GLManagerLegacy_MacOS::is_using_vsync() const {
return use_vsync;
}
-NSOpenGLContext *GLManager_MacOS::get_context(DisplayServer::WindowID p_window_id) {
+NSOpenGLContext *GLManagerLegacy_MacOS::get_context(DisplayServer::WindowID p_window_id) {
if (!windows.has(p_window_id)) {
return nullptr;
}
@@ -226,11 +196,16 @@ NSOpenGLContext *GLManager_MacOS::get_context(DisplayServer::WindowID p_window_i
return win.context;
}
-GLManager_MacOS::GLManager_MacOS(ContextType p_context_type) {
- context_type = p_context_type;
+GLManagerLegacy_MacOS::GLManagerLegacy_MacOS() {
+ CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
+ CFBundleLoadExecutable(framework);
+
+ CGLEnable = (CGLEnablePtr)CFBundleGetFunctionPointerForName(framework, CFSTR("CGLEnable"));
+ CGLSetParameter = (CGLSetParameterPtr)CFBundleGetFunctionPointerForName(framework, CFSTR("CGLSetParameter"));
+ CGLGetCurrentContext = (CGLGetCurrentContextPtr)CFBundleGetFunctionPointerForName(framework, CFSTR("CGLGetCurrentContext"));
}
-GLManager_MacOS::~GLManager_MacOS() {
+GLManagerLegacy_MacOS::~GLManagerLegacy_MacOS() {
release_current();
}
diff --git a/platform/macos/godot_content_view.h b/platform/macos/godot_content_view.h
index 0d18ac742a..c6060c96c6 100644
--- a/platform/macos/godot_content_view.h
+++ b/platform/macos/godot_content_view.h
@@ -47,9 +47,11 @@
@interface GodotContentLayerDelegate : NSObject <CALayerDelegate> {
DisplayServer::WindowID window_id;
+ bool need_redraw;
}
- (void)setWindowID:(DisplayServer::WindowID)wid;
+- (void)setNeedRedraw:(bool)redraw;
@end
diff --git a/platform/macos/godot_content_view.mm b/platform/macos/godot_content_view.mm
index 231be83a03..22a9aa14c0 100644
--- a/platform/macos/godot_content_view.mm
+++ b/platform/macos/godot_content_view.mm
@@ -40,6 +40,7 @@
- (id)init {
self = [super init];
window_id = DisplayServer::INVALID_WINDOW_ID;
+ need_redraw = false;
return self;
}
@@ -47,13 +48,18 @@
window_id = wid;
}
+- (void)setNeedRedraw:(bool)redraw {
+ need_redraw = redraw;
+}
+
- (void)displayLayer:(CALayer *)layer {
DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
- if (OS::get_singleton()->get_main_loop() && ds->get_is_resizing()) {
+ if (OS::get_singleton()->get_main_loop() && ds->get_is_resizing() && need_redraw) {
Main::force_redraw();
if (!Main::is_iterating()) { // Avoid cyclic loop.
Main::iteration();
}
+ need_redraw = false;
}
}
@@ -93,6 +99,7 @@
}
[super setFrameSize:newSize];
+ [layer_delegate setNeedRedraw:true];
[self.layer setNeedsDisplay]; // Force "drawRect" call.
}
@@ -132,12 +139,6 @@
return [[CAMetalLayer class] layer];
}
-- (void)updateLayer {
- DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
- ds->window_update(window_id);
- [super updateLayer];
-}
-
- (BOOL)wantsUpdateLayer {
return YES;
}
diff --git a/platform/macos/os_macos.mm b/platform/macos/os_macos.mm
index c17ea95f4f..1b8ca0134d 100644
--- a/platform/macos/os_macos.mm
+++ b/platform/macos/os_macos.mm
@@ -231,7 +231,7 @@ Error OS_MacOS::open_dynamic_library(const String p_path, void *&p_library_handl
}
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
- ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror()));
+ ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror()));
if (r_resolved_path != nullptr) {
*r_resolved_path = path;
diff --git a/platform/macos/platform_config.h b/platform/macos/platform_config.h
index 65a898dcc1..1a571b689a 100644
--- a/platform/macos/platform_config.h
+++ b/platform/macos/platform_config.h
@@ -30,5 +30,4 @@
#include <alloca.h>
-#define OPENGL_INCLUDE_H "thirdparty/glad/glad/gl.h"
#define PTHREAD_RENAME_SELF
diff --git a/platform/macos/platform_gl.h b/platform/macos/platform_gl.h
new file mode 100644
index 0000000000..3bad9d5a5f
--- /dev/null
+++ b/platform/macos/platform_gl.h
@@ -0,0 +1,52 @@
+/**************************************************************************/
+/* platform_gl.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef PLATFORM_GL_H
+#define PLATFORM_GL_H
+
+#ifndef GL_API_ENABLED
+#define GL_API_ENABLED // Allow using desktop GL.
+#endif
+
+#ifndef GLES_API_ENABLED
+#define GLES_API_ENABLED // Allow using GLES (ANGLE).
+#endif
+
+#ifdef EGL_STATIC
+#define KHRONOS_STATIC 1
+#include "thirdparty/angle/include/EGL/egl.h"
+#include "thirdparty/angle/include/EGL/eglext.h"
+#undef KHRONOS_STATIC
+#else
+#include "thirdparty/glad/glad/egl.h"
+#endif
+#include "thirdparty/glad/glad/gl.h"
+
+#endif // PLATFORM_GL_H
diff --git a/platform/uwp/README.md b/platform/uwp/README.md
deleted file mode 100644
index d69a8a8850..0000000000
--- a/platform/uwp/README.md
+++ /dev/null
@@ -1,20 +0,0 @@
-# UWP platform port
-
-> **Warning**
->
-> The UWP platform port is not currently in a working state for the `master`
-> branch, and may be dropped in the future.
-
-This folder contains the C++ code for the Universal Windows Platform (UWP)
-platform port. **This is not to be confused with the "standard" Win32 port**,
-which is available in [`platform/windows`](/platform/windows).
-
-See also [`misc/dist/uwp_template`](/misc/dist/uwp_template) folder for the UWP
-project template used for packaging the UWP export templates.
-
-## Documentation
-
-- [Compiling for Universal Windows Platform](https://docs.godotengine.org/en/latest/contributing/development/compiling/compiling_for_uwp.html)
- - Instructions on building this platform port from source.
-- [Exporting for Universal Windows Platform](https://docs.godotengine.org/en/latest/tutorials/export/exporting_for_uwp.html)
- - Instructions on using the compiled export templates to export a project.
diff --git a/platform/uwp/SCsub b/platform/uwp/SCsub
deleted file mode 100644
index 8726d32d61..0000000000
--- a/platform/uwp/SCsub
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/env python
-
-Import("env")
-
-files = [
- "#platform/windows/key_mapping_windows.cpp",
- "#platform/windows/windows_terminal_logger.cpp",
- "joypad_uwp.cpp",
- "context_egl_uwp.cpp",
- "app_uwp.cpp",
- "os_uwp.cpp",
-]
-
-if "build_angle" in env and env["build_angle"]:
- cmd = env.AlwaysBuild(env.ANGLE("libANGLE.lib", None))
-
-prog = env.add_program("#bin/godot", files)
-
-if "build_angle" in env and env["build_angle"]:
- env.Depends(prog, [cmd])
diff --git a/platform/uwp/app_uwp.cpp b/platform/uwp/app_uwp.cpp
deleted file mode 100644
index 789adb5e5b..0000000000
--- a/platform/uwp/app_uwp.cpp
+++ /dev/null
@@ -1,560 +0,0 @@
-/**************************************************************************/
-/* app_uwp.cpp */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#include "app_uwp.h"
-
-#include "core/io/dir_access.h"
-#include "core/io/file_access.h"
-#include "core/os/keyboard.h"
-#include "main/main.h"
-#include "platform/windows/key_mapping_windows.h"
-
-#include <collection.h>
-
-using namespace Windows::ApplicationModel::Core;
-using namespace Windows::ApplicationModel::Activation;
-using namespace Windows::UI::Core;
-using namespace Windows::UI::Input;
-using namespace Windows::Devices::Input;
-using namespace Windows::UI::Xaml::Input;
-using namespace Windows::Foundation;
-using namespace Windows::Graphics::Display;
-using namespace Windows::System;
-using namespace Windows::System::Threading::Core;
-using namespace Microsoft::WRL;
-
-using namespace GodotUWP;
-
-// Helper to convert a length in device-independent pixels (DIPs) to a length in physical pixels.
-inline float ConvertDipsToPixels(float dips, float dpi) {
- static const float dipsPerInch = 96.0f;
- return floor(dips * dpi / dipsPerInch + 0.5f); // Round to nearest integer.
-}
-
-// Implementation of the IFrameworkViewSource interface, necessary to run our app.
-ref class GodotUWPViewSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource {
-public:
- virtual Windows::ApplicationModel::Core::IFrameworkView ^ CreateView() {
- return ref new App();
- }
-};
-
-// The main function creates an IFrameworkViewSource for our app, and runs the app.
-[Platform::MTAThread] int main(Platform::Array<Platform::String ^> ^) {
- auto godotApplicationSource = ref new GodotUWPViewSource();
- CoreApplication::Run(godotApplicationSource);
- return 0;
-}
-
-// The first method called when the IFrameworkView is being created.
-void App::Initialize(CoreApplicationView ^ applicationView) {
- // Register event handlers for app lifecycle. This example includes Activated, so that we
- // can make the CoreWindow active and start rendering on the window.
- applicationView->Activated +=
- ref new TypedEventHandler<CoreApplicationView ^, IActivatedEventArgs ^>(this, &App::OnActivated);
-
- // Logic for other event handlers could go here.
- // Information about the Suspending and Resuming event handlers can be found here:
- // http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh994930.aspx
-
- os = new OS_UWP;
-}
-
-// Called when the CoreWindow object is created (or re-created).
-void App::SetWindow(CoreWindow ^ p_window) {
- window = p_window;
- window->VisibilityChanged +=
- ref new TypedEventHandler<CoreWindow ^, VisibilityChangedEventArgs ^>(this, &App::OnVisibilityChanged);
-
- window->Closed +=
- ref new TypedEventHandler<CoreWindow ^, CoreWindowEventArgs ^>(this, &App::OnWindowClosed);
-
- window->SizeChanged +=
- ref new TypedEventHandler<CoreWindow ^, WindowSizeChangedEventArgs ^>(this, &App::OnWindowSizeChanged);
-
-#if !(WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
- // Disable all pointer visual feedback for better performance when touching.
- // This is not supported on Windows Phone applications.
- auto pointerVisualizationSettings = PointerVisualizationSettings::GetForCurrentView();
- pointerVisualizationSettings->IsContactFeedbackEnabled = false;
- pointerVisualizationSettings->IsBarrelButtonFeedbackEnabled = false;
-#endif
-
- window->PointerPressed +=
- ref new TypedEventHandler<CoreWindow ^, PointerEventArgs ^>(this, &App::OnPointerPressed);
- window->PointerMoved +=
- ref new TypedEventHandler<CoreWindow ^, PointerEventArgs ^>(this, &App::OnPointerMoved);
- window->PointerReleased +=
- ref new TypedEventHandler<CoreWindow ^, PointerEventArgs ^>(this, &App::OnPointerReleased);
- window->PointerWheelChanged +=
- ref new TypedEventHandler<CoreWindow ^, PointerEventArgs ^>(this, &App::OnPointerWheelChanged);
-
- mouseChangedNotifier = SignalNotifier::AttachToEvent(L"os_mouse_mode_changed", ref new SignalHandler(this, &App::OnMouseModeChanged));
-
- mouseChangedNotifier->Enable();
-
- window->CharacterReceived +=
- ref new TypedEventHandler<CoreWindow ^, CharacterReceivedEventArgs ^>(this, &App::OnCharacterReceived);
- window->KeyDown +=
- ref new TypedEventHandler<CoreWindow ^, KeyEventArgs ^>(this, &App::OnKeyDown);
- window->KeyUp +=
- ref new TypedEventHandler<CoreWindow ^, KeyEventArgs ^>(this, &App::OnKeyUp);
-
- os->set_window(window);
-
- unsigned int argc;
- char **argv = get_command_line(&argc);
-
- Main::setup("uwp", argc, argv, false);
-
- UpdateWindowSize(Size(window->Bounds.Width, window->Bounds.Height));
-
- Main::setup2();
-}
-
-static MouseButton _get_button(Windows::UI::Input::PointerPoint ^ pt) {
- using namespace Windows::UI::Input;
-
-#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
- return MOUSE_BUTTON_LEFT;
-#else
- switch (pt->Properties->PointerUpdateKind) {
- case PointerUpdateKind::LeftButtonPressed:
- case PointerUpdateKind::LeftButtonReleased:
- return MOUSE_BUTTON_LEFT;
-
- case PointerUpdateKind::RightButtonPressed:
- case PointerUpdateKind::RightButtonReleased:
- return MOUSE_BUTTON_RIGHT;
-
- case PointerUpdateKind::MiddleButtonPressed:
- case PointerUpdateKind::MiddleButtonReleased:
- return MOUSE_BUTTON_MIDDLE;
-
- case PointerUpdateKind::XButton1Pressed:
- case PointerUpdateKind::XButton1Released:
- return MOUSE_BUTTON_WHEEL_UP;
-
- case PointerUpdateKind::XButton2Pressed:
- case PointerUpdateKind::XButton2Released:
- return MOUSE_BUTTON_WHEEL_DOWN;
-
- default:
- break;
- }
-#endif
-
- return MOUSE_BUTTON_NONE;
-}
-
-static bool _is_touch(Windows::UI::Input::PointerPoint ^ pointerPoint) {
-#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
- return true;
-#else
- using namespace Windows::Devices::Input;
- switch (pointerPoint->PointerDevice->PointerDeviceType) {
- case PointerDeviceType::Touch:
- case PointerDeviceType::Pen:
- return true;
- default:
- return false;
- }
-#endif
-}
-
-static Windows::Foundation::Point _get_pixel_position(CoreWindow ^ window, Windows::Foundation::Point rawPosition, OS *os) {
- Windows::Foundation::Point outputPosition;
-
-// Compute coordinates normalized from 0..1.
-// If the coordinates need to be sized to the SDL window,
-// we'll do that after.
-#if 1 || WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
- outputPosition.X = rawPosition.X / window->Bounds.Width;
- outputPosition.Y = rawPosition.Y / window->Bounds.Height;
-#else
- switch (DisplayProperties::CurrentOrientation) {
- case DisplayOrientations::Portrait:
- outputPosition.X = rawPosition.X / window->Bounds.Width;
- outputPosition.Y = rawPosition.Y / window->Bounds.Height;
- break;
- case DisplayOrientations::PortraitFlipped:
- outputPosition.X = 1.0f - (rawPosition.X / window->Bounds.Width);
- outputPosition.Y = 1.0f - (rawPosition.Y / window->Bounds.Height);
- break;
- case DisplayOrientations::Landscape:
- outputPosition.X = rawPosition.Y / window->Bounds.Height;
- outputPosition.Y = 1.0f - (rawPosition.X / window->Bounds.Width);
- break;
- case DisplayOrientations::LandscapeFlipped:
- outputPosition.X = 1.0f - (rawPosition.Y / window->Bounds.Height);
- outputPosition.Y = rawPosition.X / window->Bounds.Width;
- break;
- default:
- break;
- }
-#endif
-
- OS::VideoMode vm = os->get_video_mode();
- outputPosition.X *= vm.width;
- outputPosition.Y *= vm.height;
-
- return outputPosition;
-}
-
-static int _get_finger(uint32_t p_touch_id) {
- return p_touch_id % 31; // for now
-}
-
-void App::pointer_event(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::PointerEventArgs ^ args, bool p_pressed, bool p_is_wheel) {
- Windows::UI::Input::PointerPoint ^ point = args->CurrentPoint;
- Windows::Foundation::Point pos = _get_pixel_position(window, point->Position, os);
- MouseButton but = _get_button(point);
- if (_is_touch(point)) {
- Ref<InputEventScreenTouch> screen_touch;
- screen_touch.instantiate();
- screen_touch->set_device(0);
- screen_touch->set_pressed(p_pressed);
- screen_touch->set_position(Vector2(pos.X, pos.Y));
- screen_touch->set_index(_get_finger(point->PointerId));
-
- last_touch_x[screen_touch->get_index()] = pos.X;
- last_touch_y[screen_touch->get_index()] = pos.Y;
-
- os->input_event(screen_touch);
- } else {
- Ref<InputEventMouseButton> mouse_button;
- mouse_button.instantiate();
- mouse_button->set_device(0);
- mouse_button->set_pressed(p_pressed);
- mouse_button->set_button_index(but);
- mouse_button->set_position(Vector2(pos.X, pos.Y));
- mouse_button->set_global_position(Vector2(pos.X, pos.Y));
-
- if (p_is_wheel) {
- if (point->Properties->MouseWheelDelta > 0) {
- mouse_button->set_button_index(point->Properties->IsHorizontalMouseWheel ? MOUSE_BUTTON_WHEEL_RIGHT : MOUSE_BUTTON_WHEEL_UP);
- } else if (point->Properties->MouseWheelDelta < 0) {
- mouse_button->set_button_index(point->Properties->IsHorizontalMouseWheel ? MOUSE_BUTTON_WHEEL_LEFT : MOUSE_BUTTON_WHEEL_DOWN);
- }
- }
-
- last_touch_x[31] = pos.X;
- last_touch_y[31] = pos.Y;
-
- os->input_event(mouse_button);
-
- if (p_is_wheel) {
- // Send release for mouse wheel
- mouse_button->set_pressed(false);
- os->input_event(mouse_button);
- }
- }
-}
-
-void App::OnPointerPressed(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::PointerEventArgs ^ args) {
- pointer_event(sender, args, true);
-}
-
-void App::OnPointerReleased(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::PointerEventArgs ^ args) {
- pointer_event(sender, args, false);
-}
-
-void App::OnPointerWheelChanged(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::PointerEventArgs ^ args) {
- pointer_event(sender, args, true, true);
-}
-
-void App::OnMouseModeChanged(Windows::System::Threading::Core::SignalNotifier ^ signalNotifier, bool timedOut) {
- OS::MouseMode mode = os->get_mouse_mode();
- SignalNotifier ^ notifier = mouseChangedNotifier;
-
- window->Dispatcher->RunAsync(
- CoreDispatcherPriority::High,
- ref new DispatchedHandler(
- [mode, notifier, this]() {
- if (mode == OS::MOUSE_MODE_CAPTURED) {
- this->MouseMovedToken = MouseDevice::GetForCurrentView()->MouseMoved +=
- ref new TypedEventHandler<MouseDevice ^, MouseEventArgs ^>(this, &App::OnMouseMoved);
-
- } else {
- MouseDevice::GetForCurrentView()->MouseMoved -= MouseMovedToken;
- }
-
- notifier->Enable();
- }));
-
- ResetEvent(os->mouse_mode_changed);
-}
-
-void App::OnPointerMoved(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::PointerEventArgs ^ args) {
- Windows::UI::Input::PointerPoint ^ point = args->CurrentPoint;
- Windows::Foundation::Point pos = _get_pixel_position(window, point->Position, os);
-
- if (_is_touch(point)) {
- Ref<InputEventScreenDrag> screen_drag;
- screen_drag.instantiate();
- screen_drag->set_device(0);
- screen_drag->set_position(Vector2(pos.X, pos.Y));
- screen_drag->set_index(_get_finger(point->PointerId));
- screen_drag->set_relative(Vector2(screen_drag->get_position().x - last_touch_x[screen_drag->get_index()], screen_drag->get_position().y - last_touch_y[screen_drag->get_index()]));
-
- os->input_event(screen_drag);
- } else {
- // In case the mouse grabbed, MouseMoved will handle this
- if (os->get_mouse_mode() == OS::MouseMode::MOUSE_MODE_CAPTURED) {
- return;
- }
-
- Ref<InputEventMouseMotion> mouse_motion;
- mouse_motion.instantiate();
- mouse_motion->set_device(0);
- mouse_motion->set_position(Vector2(pos.X, pos.Y));
- mouse_motion->set_global_position(Vector2(pos.X, pos.Y));
- mouse_motion->set_relative(Vector2(pos.X - last_touch_x[31], pos.Y - last_touch_y[31]));
-
- last_mouse_pos = pos;
-
- os->input_event(mouse_motion);
- }
-}
-
-void App::OnMouseMoved(MouseDevice ^ mouse_device, MouseEventArgs ^ args) {
- // In case the mouse isn't grabbed, PointerMoved will handle this
- if (os->get_mouse_mode() != OS::MouseMode::MOUSE_MODE_CAPTURED) {
- return;
- }
-
- Windows::Foundation::Point pos;
- pos.X = last_mouse_pos.X + args->MouseDelta.X;
- pos.Y = last_mouse_pos.Y + args->MouseDelta.Y;
-
- Ref<InputEventMouseMotion> mouse_motion;
- mouse_motion.instantiate();
- mouse_motion->set_device(0);
- mouse_motion->set_position(Vector2(pos.X, pos.Y));
- mouse_motion->set_global_position(Vector2(pos.X, pos.Y));
- mouse_motion->set_relative(Vector2(args->MouseDelta.X, args->MouseDelta.Y));
-
- last_mouse_pos = pos;
-
- os->input_event(mouse_motion);
-}
-
-void App::key_event(Windows::UI::Core::CoreWindow ^ sender, bool p_pressed, Windows::UI::Core::KeyEventArgs ^ key_args, Windows::UI::Core::CharacterReceivedEventArgs ^ char_args) {
- OS_UWP::KeyEvent ke;
-
- ke.control = sender->GetAsyncKeyState(VirtualKey::Control) == CoreVirtualKeyStates::Down;
- ke.alt = sender->GetAsyncKeyState(VirtualKey::Menu) == CoreVirtualKeyStates::Down;
- ke.shift = sender->GetAsyncKeyState(VirtualKey::Shift) == CoreVirtualKeyStates::Down;
-
- ke.pressed = p_pressed;
-
- if (key_args != nullptr) {
- ke.type = OS_UWP::KeyEvent::MessageType::KEY_EVENT_MESSAGE;
- ke.unicode = 0;
- ke.keycode = KeyMappingWindows::get_keysym((unsigned int)key_args->VirtualKey);
- ke.physical_keycode = KeyMappingWindows::get_scansym((unsigned int)key_args->KeyStatus.ScanCode, key_args->KeyStatus.IsExtendedKey);
- ke.echo = (!p_pressed && !key_args->KeyStatus.IsKeyReleased) || (p_pressed && key_args->KeyStatus.WasKeyDown);
-
- } else {
- ke.type = OS_UWP::KeyEvent::MessageType::CHAR_EVENT_MESSAGE;
- ke.unicode = char_args->KeyCode;
- ke.keycode = 0;
- ke.physical_keycode = 0;
- ke.echo = (!p_pressed && !char_args->KeyStatus.IsKeyReleased) || (p_pressed && char_args->KeyStatus.WasKeyDown);
- }
-
- os->queue_key_event(ke);
-}
-
-void App::OnKeyDown(CoreWindow ^ sender, KeyEventArgs ^ args) {
- key_event(sender, true, args);
-}
-
-void App::OnKeyUp(CoreWindow ^ sender, KeyEventArgs ^ args) {
- key_event(sender, false, args);
-}
-
-void App::OnCharacterReceived(CoreWindow ^ sender, CharacterReceivedEventArgs ^ args) {
- key_event(sender, true, nullptr, args);
-}
-
-// Initializes scene resources
-void App::Load(Platform::String ^ entryPoint) {
-}
-
-// This method is called after the window becomes active.
-void App::Run() {
- if (Main::start()) {
- os->run();
- }
-}
-
-// Terminate events do not cause Uninitialize to be called. It will be called if your IFrameworkView
-// class is torn down while the app is in the foreground.
-void App::Uninitialize() {
- Main::cleanup();
- delete os;
-}
-
-// Application lifecycle event handler.
-void App::OnActivated(CoreApplicationView ^ applicationView, IActivatedEventArgs ^ args) {
- // Run() won't start until the CoreWindow is activated.
- CoreWindow::GetForCurrentThread()->Activate();
-}
-
-// Window event handlers.
-void App::OnVisibilityChanged(CoreWindow ^ sender, VisibilityChangedEventArgs ^ args) {
- mWindowVisible = args->Visible;
-}
-
-void App::OnWindowClosed(CoreWindow ^ sender, CoreWindowEventArgs ^ args) {
- mWindowClosed = true;
-}
-
-void App::OnWindowSizeChanged(CoreWindow ^ sender, WindowSizeChangedEventArgs ^ args) {
-#if (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP)
- // On Windows 8.1, apps are resized when they are snapped alongside other apps, or when the device is rotated.
- // The default framebuffer will be automatically resized when either of these occur.
- // In particular, on a 90 degree rotation, the default framebuffer's width and height will switch.
- UpdateWindowSize(args->Size);
-#else if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
- // On Windows Phone 8.1, the window size changes when the device is rotated.
- // The default framebuffer will not be automatically resized when this occurs.
- // It is therefore up to the app to handle rotation-specific logic in its rendering code.
- //os->screen_size_changed();
- UpdateWindowSize(args->Size);
-#endif
-}
-
-void App::UpdateWindowSize(Size size) {
- float dpi;
-#if (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP)
- DisplayInformation ^ currentDisplayInformation = DisplayInformation::GetForCurrentView();
- dpi = currentDisplayInformation->LogicalDpi;
-#else if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
- dpi = DisplayProperties::LogicalDpi;
-#endif
- Size pixelSize(ConvertDipsToPixels(size.Width, dpi), ConvertDipsToPixels(size.Height, dpi));
-
- mWindowWidth = static_cast<GLsizei>(pixelSize.Width);
- mWindowHeight = static_cast<GLsizei>(pixelSize.Height);
-
- OS::VideoMode vm;
- vm.width = mWindowWidth;
- vm.height = mWindowHeight;
- vm.fullscreen = true;
- vm.resizable = false;
- os->set_video_mode(vm);
-}
-
-char **App::get_command_line(unsigned int *out_argc) {
- static char *fail_cl[] = { "--path", "game", nullptr };
- *out_argc = 2;
-
- FILE *f = _wfopen(L"__cl__.cl", L"rb");
-
- if (f == nullptr) {
- wprintf(L"Couldn't open command line file.\n");
- return fail_cl;
- }
-
-#define READ_LE_4(v) ((int)(##v[3] & 0xFF) << 24) | ((int)(##v[2] & 0xFF) << 16) | ((int)(##v[1] & 0xFF) << 8) | ((int)(##v[0] & 0xFF))
-#define CMD_MAX_LEN 65535
-
- uint8_t len[4];
- int r = fread(len, sizeof(uint8_t), 4, f);
-
- Platform::Collections::Vector<Platform::String ^> cl;
-
- if (r < 4) {
- fclose(f);
- wprintf(L"Wrong cmdline length.\n");
- return (fail_cl);
- }
-
- int argc = READ_LE_4(len);
-
- for (int i = 0; i < argc; i++) {
- r = fread(len, sizeof(uint8_t), 4, f);
-
- if (r < 4) {
- fclose(f);
- wprintf(L"Wrong cmdline param length.\n");
- return (fail_cl);
- }
-
- int strlen = READ_LE_4(len);
-
- if (strlen > CMD_MAX_LEN) {
- fclose(f);
- wprintf(L"Wrong command length.\n");
- return (fail_cl);
- }
-
- char *arg = new char[strlen + 1];
- r = fread(arg, sizeof(char), strlen, f);
- arg[strlen] = '\0';
-
- if (r == strlen) {
- int warg_size = MultiByteToWideChar(CP_UTF8, 0, arg, -1, nullptr, 0);
- wchar_t *warg = new wchar_t[warg_size];
-
- MultiByteToWideChar(CP_UTF8, 0, arg, -1, warg, warg_size);
-
- cl.Append(ref new Platform::String(warg, warg_size));
-
- } else {
- delete[] arg;
- fclose(f);
- wprintf(L"Error reading command.\n");
- return (fail_cl);
- }
- }
-
-#undef READ_LE_4
-#undef CMD_MAX_LEN
-
- fclose(f);
-
- char **ret = new char *[cl.Size + 1];
-
- for (int i = 0; i < cl.Size; i++) {
- int arg_size = WideCharToMultiByte(CP_UTF8, 0, cl.GetAt(i)->Data(), -1, nullptr, 0, nullptr, nullptr);
- char *arg = new char[arg_size];
-
- WideCharToMultiByte(CP_UTF8, 0, cl.GetAt(i)->Data(), -1, arg, arg_size, nullptr, nullptr);
-
- ret[i] = arg;
- }
- ret[cl.Size] = nullptr;
- *out_argc = cl.Size;
-
- return ret;
-}
diff --git a/platform/uwp/app_uwp.h b/platform/uwp/app_uwp.h
deleted file mode 100644
index 87c66bd679..0000000000
--- a/platform/uwp/app_uwp.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/**************************************************************************/
-/* app_uwp.h */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#ifndef APP_UWP_H
-#define APP_UWP_H
-
-#include "os_uwp.h"
-
-#include <GLES2/gl2.h>
-#include <wrl.h>
-#include <string>
-
-/** clang-format does not play nice with this C++/CX hybrid, needs investigation. */
-/* clang-format off */
-
-namespace GodotUWP
-{
- ref class App sealed : public Windows::ApplicationModel::Core::IFrameworkView
- {
- public:
- App() {}
-
- // IFrameworkView Methods.
- virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView);
- virtual void SetWindow(Windows::UI::Core::CoreWindow^ window);
- virtual void Load(Platform::String^ entryPoint);
- virtual void Run();
- virtual void Uninitialize();
-
- property Windows::Foundation::EventRegistrationToken MouseMovedToken {
- Windows::Foundation::EventRegistrationToken get() { return this->mouseMovedToken; }
- void set(Windows::Foundation::EventRegistrationToken p_token) { this->mouseMovedToken = p_token; }
- }
-
- private:
- void RecreateRenderer();
-
- // Application lifecycle event handlers.
- void OnActivated(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args);
-
- // Window event handlers.
- void OnWindowSizeChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ args);
- void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args);
- void OnWindowClosed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CoreWindowEventArgs^ args);
-
- void pointer_event(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args, bool p_pressed, bool p_is_wheel = false);
- void OnPointerPressed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
- void OnPointerReleased(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
- void OnPointerMoved(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
- void OnMouseMoved(Windows::Devices::Input::MouseDevice^ mouse_device, Windows::Devices::Input::MouseEventArgs^ args);
- void OnPointerWheelChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
-
- Windows::System::Threading::Core::SignalNotifier^ mouseChangedNotifier;
- Windows::Foundation::EventRegistrationToken mouseMovedToken;
- void OnMouseModeChanged(Windows::System::Threading::Core::SignalNotifier^ signalNotifier, bool timedOut);
-
- void key_event(Windows::UI::Core::CoreWindow^ sender, bool p_pressed, Windows::UI::Core::KeyEventArgs^ key_args = nullptr, Windows::UI::Core::CharacterReceivedEventArgs^ char_args = nullptr);
- void OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
- void OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
- void OnCharacterReceived(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CharacterReceivedEventArgs^ args);
-
- void UpdateWindowSize(Windows::Foundation::Size size);
- void InitializeEGL(Windows::UI::Core::CoreWindow^ window);
- void CleanupEGL();
-
- char** get_command_line(unsigned int* out_argc);
-
- bool mWindowClosed = false;
- bool mWindowVisible = true;
- GLsizei mWindowWidth = 0;
- GLsizei mWindowHeight = 0;
-
- EGLDisplay mEglDisplay = EGL_NO_DISPLAY;
- EGLContext mEglContext = EGL_NO_CONTEXT;
- EGLSurface mEglSurface = EGL_NO_SURFACE;
-
- CoreWindow^ window;
- OS_UWP* os;
-
- int last_touch_x[32]; // 20 fingers, index 31 reserved for the mouse
- int last_touch_y[32];
- Windows::Foundation::Point last_mouse_pos;
- };
-}
-
-/* clang-format on */
-
-#endif // APP_UWP_H
diff --git a/platform/uwp/context_egl_uwp.cpp b/platform/uwp/context_egl_uwp.cpp
deleted file mode 100644
index aa8cfb4d49..0000000000
--- a/platform/uwp/context_egl_uwp.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-/**************************************************************************/
-/* context_egl_uwp.cpp */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#include "context_egl_uwp.h"
-
-#include <EGL/eglext.h>
-
-using Platform::Exception;
-
-void ContextEGL_UWP::release_current() {
- eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, mEglContext);
-}
-
-void ContextEGL_UWP::make_current() {
- eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
-}
-
-int ContextEGL_UWP::get_window_width() {
- return width;
-}
-
-int ContextEGL_UWP::get_window_height() {
- return height;
-}
-
-void ContextEGL_UWP::reset() {
- cleanup();
-
- window = CoreWindow::GetForCurrentThread();
- initialize();
-}
-
-void ContextEGL_UWP::swap_buffers() {
- if (eglSwapBuffers(mEglDisplay, mEglSurface) != EGL_TRUE) {
- cleanup();
-
- window = CoreWindow::GetForCurrentThread();
- initialize();
-
- // tell rasterizer to reload textures and stuff?
- }
-}
-
-Error ContextEGL_UWP::initialize() {
- EGLint configAttribList[] = {
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, 8,
- EGL_DEPTH_SIZE, 8,
- EGL_STENCIL_SIZE, 8,
- EGL_SAMPLE_BUFFERS, 0,
- EGL_NONE
- };
-
- EGLint surfaceAttribList[] = {
- EGL_NONE, EGL_NONE
- };
-
- EGLint numConfigs = 0;
- EGLint majorVersion = 1;
- EGLint minorVersion;
- if (driver == GLES_2_0) {
- minorVersion = 0;
- } else {
- minorVersion = 5;
- }
- EGLDisplay display = EGL_NO_DISPLAY;
- EGLContext context = EGL_NO_CONTEXT;
- EGLSurface surface = EGL_NO_SURFACE;
- EGLConfig config = nullptr;
- EGLint contextAttribs[3];
- if (driver == GLES_2_0) {
- contextAttribs[0] = EGL_CONTEXT_CLIENT_VERSION;
- contextAttribs[1] = 2;
- contextAttribs[2] = EGL_NONE;
- } else {
- contextAttribs[0] = EGL_CONTEXT_CLIENT_VERSION;
- contextAttribs[1] = 3;
- contextAttribs[2] = EGL_NONE;
- }
-
- try {
- const EGLint displayAttributes[] = {
- /*EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
- EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, 9,
- EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, 3,
- EGL_NONE,*/
- // These are the default display attributes, used to request ANGLE's D3D11 renderer.
- // eglInitialize will only succeed with these attributes if the hardware supports D3D11 Feature Level 10_0+.
- EGL_PLATFORM_ANGLE_TYPE_ANGLE,
- EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
-
- // EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER is an optimization that can have large performance benefits on mobile devices.
- // Its syntax is subject to change, though. Please update your Visual Studio templates if you experience compilation issues with it.
- EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER,
- EGL_TRUE,
-
- // EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE is an option that enables ANGLE to automatically call
- // the IDXGIDevice3::Trim method on behalf of the application when it gets suspended.
- // Calling IDXGIDevice3::Trim when an application is suspended is a Windows Store application certification requirement.
- EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
- EGL_TRUE,
- EGL_NONE,
- };
-
- PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(eglGetProcAddress("eglGetPlatformDisplayEXT"));
-
- if (!eglGetPlatformDisplayEXT) {
- throw Exception::CreateException(E_FAIL, L"Failed to get function eglGetPlatformDisplayEXT");
- }
-
- display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, displayAttributes);
-
- if (display == EGL_NO_DISPLAY) {
- throw Exception::CreateException(E_FAIL, L"Failed to get default EGL display");
- }
-
- if (eglInitialize(display, &majorVersion, &minorVersion) == EGL_FALSE) {
- throw Exception::CreateException(E_FAIL, L"Failed to initialize EGL");
- }
-
- if (eglGetConfigs(display, nullptr, 0, &numConfigs) == EGL_FALSE) {
- throw Exception::CreateException(E_FAIL, L"Failed to get EGLConfig count");
- }
-
- if (eglChooseConfig(display, configAttribList, &config, 1, &numConfigs) == EGL_FALSE) {
- throw Exception::CreateException(E_FAIL, L"Failed to choose first EGLConfig count");
- }
-
- surface = eglCreateWindowSurface(display, config, reinterpret_cast<IInspectable *>(window), surfaceAttribList);
- if (surface == EGL_NO_SURFACE) {
- throw Exception::CreateException(E_FAIL, L"Failed to create EGL fullscreen surface");
- }
-
- context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
- if (context == EGL_NO_CONTEXT) {
- throw Exception::CreateException(E_FAIL, L"Failed to create EGL context");
- }
-
- if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
- throw Exception::CreateException(E_FAIL, L"Failed to make fullscreen EGLSurface current");
- }
- } catch (...) {
- return FAILED;
- }
-
- mEglDisplay = display;
- mEglSurface = surface;
- mEglContext = context;
-
- eglQuerySurface(display, surface, EGL_WIDTH, &width);
- eglQuerySurface(display, surface, EGL_HEIGHT, &height);
-
- return OK;
-}
-
-void ContextEGL_UWP::cleanup() {
- if (mEglDisplay != EGL_NO_DISPLAY && mEglSurface != EGL_NO_SURFACE) {
- eglDestroySurface(mEglDisplay, mEglSurface);
- mEglSurface = EGL_NO_SURFACE;
- }
-
- if (mEglDisplay != EGL_NO_DISPLAY && mEglContext != EGL_NO_CONTEXT) {
- eglDestroyContext(mEglDisplay, mEglContext);
- mEglContext = EGL_NO_CONTEXT;
- }
-
- if (mEglDisplay != EGL_NO_DISPLAY) {
- eglTerminate(mEglDisplay);
- mEglDisplay = EGL_NO_DISPLAY;
- }
-}
-
-ContextEGL_UWP::ContextEGL_UWP(CoreWindow ^ p_window, Driver p_driver) :
- mEglDisplay(EGL_NO_DISPLAY),
- mEglContext(EGL_NO_CONTEXT),
- mEglSurface(EGL_NO_SURFACE),
- driver(p_driver),
- window(p_window),
- vsync(false) {}
-
-ContextEGL_UWP::~ContextEGL_UWP() {
- cleanup();
-}
diff --git a/platform/uwp/detect.py b/platform/uwp/detect.py
deleted file mode 100644
index 604f5e48e3..0000000000
--- a/platform/uwp/detect.py
+++ /dev/null
@@ -1,216 +0,0 @@
-import methods
-import os
-import sys
-from platform_methods import detect_arch
-
-from typing import TYPE_CHECKING
-
-if TYPE_CHECKING:
- from SCons import Environment
-
-
-def get_name():
- return "UWP"
-
-
-def can_build():
- if os.name == "nt":
- # building natively on windows!
- if os.getenv("VSINSTALLDIR"):
- if os.getenv("ANGLE_SRC_PATH") is None:
- return False
-
- return True
- return False
-
-
-def get_opts():
- return [
- ("msvc_version", "MSVC version to use (ignored if the VCINSTALLDIR environment variable is set)", None),
- ]
-
-
-def get_flags():
- return [
- ("arch", detect_arch()),
- ("tools", False),
- ("xaudio2", True),
- ("builtin_pcre2_with_jit", False),
- ]
-
-
-def configure(env: "Environment"):
- # Validate arch.
- supported_arches = ["x86_32", "x86_64", "arm32"]
- if env["arch"] not in supported_arches:
- print(
- 'Unsupported CPU architecture "%s" for UWP. Supported architectures are: %s.'
- % (env["arch"], ", ".join(supported_arches))
- )
- sys.exit()
-
- env.msvc = True
-
- ## Build type
-
- if env["target"] == "release":
- env.Append(CCFLAGS=["/MD"])
- env.Append(LINKFLAGS=["/SUBSYSTEM:WINDOWS"])
- if env["optimize"] != "none":
- env.Append(CCFLAGS=["/O2", "/GL"])
- env.Append(LINKFLAGS=["/LTCG"])
-
- elif env["target"] == "release_debug":
- env.Append(CCFLAGS=["/MD"])
- env.Append(LINKFLAGS=["/SUBSYSTEM:CONSOLE"])
- env.AppendUnique(CPPDEFINES=["WINDOWS_SUBSYSTEM_CONSOLE"])
- if env["optimize"] != "none":
- env.Append(CCFLAGS=["/O2", "/Zi"])
-
- elif env["target"] == "debug":
- env.Append(CCFLAGS=["/Zi"])
- env.Append(CCFLAGS=["/MDd"])
- env.Append(LINKFLAGS=["/SUBSYSTEM:CONSOLE"])
- env.AppendUnique(CPPDEFINES=["WINDOWS_SUBSYSTEM_CONSOLE"])
- env.Append(LINKFLAGS=["/DEBUG"])
-
- ## Compiler configuration
-
- env["ENV"] = os.environ
- vc_base_path = os.environ["VCTOOLSINSTALLDIR"] if "VCTOOLSINSTALLDIR" in os.environ else os.environ["VCINSTALLDIR"]
-
- # Force to use Unicode encoding
- env.AppendUnique(CCFLAGS=["/utf-8"])
-
- # ANGLE
- angle_root = os.environ["ANGLE_SRC_PATH"]
- env.Prepend(CPPPATH=[angle_root + "/include"])
- jobs = str(env.GetOption("num_jobs"))
- angle_build_cmd = (
- "msbuild.exe "
- + angle_root
- + "/winrt/10/src/angle.sln /nologo /v:m /m:"
- + jobs
- + " /p:Configuration=Release /p:Platform="
- )
-
- if os.path.isfile(f"{angle_root}/winrt/10/src/angle.sln"):
- env["build_angle"] = True
-
- ## Architecture
-
- arch = ""
- if str(os.getenv("Platform")).lower() == "arm":
- print("Compiled program architecture will be an ARM executable (forcing arch=arm32).")
-
- arch = "arm"
- env["arch"] = "arm32"
- env.Append(LINKFLAGS=["/MACHINE:ARM"])
- env.Append(LIBPATH=[vc_base_path + "lib/store/arm"])
-
- angle_build_cmd += "ARM"
-
- env.Append(LIBPATH=[angle_root + "/winrt/10/src/Release_ARM/lib"])
-
- else:
- compiler_version_str = methods.detect_visual_c_compiler_version(env["ENV"])
-
- if compiler_version_str == "amd64" or compiler_version_str == "x86_amd64":
- env["arch"] = "x86_64"
- print("Compiled program architecture will be a x64 executable (forcing arch=x86_64).")
- elif compiler_version_str == "x86" or compiler_version_str == "amd64_x86":
- env["arch"] = "x86_32"
- print("Compiled program architecture will be a x86 executable (forcing arch=x86_32).")
- else:
- print(
- "Failed to detect MSVC compiler architecture version... Defaulting to x86 32-bit executable settings"
- " (forcing arch=x86_32). Compilation attempt will continue, but SCons can not detect for what architecture"
- " this build is compiled for. You should check your settings/compilation setup."
- )
- env["arch"] = "x86_32"
-
- if env["arch"] == "x86_32":
- arch = "x86"
-
- angle_build_cmd += "Win32"
-
- env.Append(LINKFLAGS=["/MACHINE:X86"])
- env.Append(LIBPATH=[vc_base_path + "lib/store"])
- env.Append(LIBPATH=[angle_root + "/winrt/10/src/Release_Win32/lib"])
-
- else:
- arch = "x64"
-
- angle_build_cmd += "x64"
-
- env.Append(LINKFLAGS=["/MACHINE:X64"])
- env.Append(LIBPATH=[os.environ["VCINSTALLDIR"] + "lib/store/amd64"])
- env.Append(LIBPATH=[angle_root + "/winrt/10/src/Release_x64/lib"])
-
- env["PROGSUFFIX"] = "." + arch + env["PROGSUFFIX"]
- env["OBJSUFFIX"] = "." + arch + env["OBJSUFFIX"]
- env["LIBSUFFIX"] = "." + arch + env["LIBSUFFIX"]
-
- ## Compile flags
-
- env.Prepend(CPPPATH=["#platform/uwp", "#drivers/windows"])
- env.Append(CPPDEFINES=["UWP_ENABLED", "WINDOWS_ENABLED", "TYPED_METHOD_BIND"])
- env.Append(CPPDEFINES=["GLES_ENABLED", "GL_GLEXT_PROTOTYPES", "EGL_EGLEXT_PROTOTYPES", "ANGLE_ENABLED"])
- winver = "0x0602" # Windows 8 is the minimum target for UWP build
- env.Append(CPPDEFINES=[("WINVER", winver), ("_WIN32_WINNT", winver), "WIN32"])
-
- env.Append(CPPDEFINES=["__WRL_NO_DEFAULT_LIB__", ("PNG_ABORT", "abort")])
-
- env.Append(CPPFLAGS=["/AI", vc_base_path + "lib/store/references"])
- env.Append(CPPFLAGS=["/AI", vc_base_path + "lib/x86/store/references"])
-
- env.Append(
- CCFLAGS=(
- '/FS /MP /GS /wd"4453" /wd"28204" /wd"4291" /Zc:wchar_t /Gm- /fp:precise /errorReport:prompt /WX-'
- " /Zc:forScope /Gd /EHsc /nologo".split()
- )
- )
- env.Append(CPPDEFINES=["_UNICODE", "UNICODE", ("WINAPI_FAMILY", "WINAPI_FAMILY_APP")])
- env.Append(CXXFLAGS=["/ZW"])
- env.Append(
- CCFLAGS=[
- "/AI",
- vc_base_path + "\\vcpackages",
- "/AI",
- os.environ["WINDOWSSDKDIR"] + "\\References\\CommonConfiguration\\Neutral",
- ]
- )
-
- ## Link flags
-
- env.Append(
- LINKFLAGS=[
- "/MANIFEST:NO",
- "/NXCOMPAT",
- "/DYNAMICBASE",
- "/WINMD",
- "/APPCONTAINER",
- "/ERRORREPORT:PROMPT",
- "/NOLOGO",
- "/TLBID:1",
- '/NODEFAULTLIB:"kernel32.lib"',
- '/NODEFAULTLIB:"ole32.lib"',
- ]
- )
-
- LIBS = [
- "WindowsApp",
- "mincore",
- "ws2_32",
- "libANGLE",
- "libEGL",
- "libGLESv2",
- "bcrypt",
- ]
- env.Append(LINKFLAGS=[p + ".lib" for p in LIBS])
-
- # Incremental linking fix
- env["BUILDERS"]["ProgramOriginal"] = env["BUILDERS"]["Program"]
- env["BUILDERS"]["Program"] = methods.precious_program
-
- env.Append(BUILDERS={"ANGLE": env.Builder(action=angle_build_cmd)})
diff --git a/platform/uwp/export/app_packager.cpp b/platform/uwp/export/app_packager.cpp
deleted file mode 100644
index ffb5e31851..0000000000
--- a/platform/uwp/export/app_packager.cpp
+++ /dev/null
@@ -1,465 +0,0 @@
-/**************************************************************************/
-/* app_packager.cpp */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#include "app_packager.h"
-
-#include "editor/editor_node.h"
-#include "editor/editor_paths.h"
-
-String AppxPackager::hash_block(const uint8_t *p_block_data, size_t p_block_len) {
- unsigned char hash[32];
- char base64[45];
-
- CryptoCore::sha256(p_block_data, p_block_len, hash);
- size_t len = 0;
- CryptoCore::b64_encode((unsigned char *)base64, 45, &len, (unsigned char *)hash, 32);
- base64[44] = '\0';
-
- return String(base64);
-}
-
-void AppxPackager::make_block_map(const String &p_path) {
- Ref<FileAccess> tmp_file = FileAccess::open(p_path, FileAccess::WRITE);
-
- tmp_file->store_string("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>");
- tmp_file->store_string("<BlockMap xmlns=\"http://schemas.microsoft.com/appx/2010/blockmap\" HashMethod=\"http://www.w3.org/2001/04/xmlenc#sha256\">");
-
- for (int i = 0; i < file_metadata.size(); i++) {
- FileMeta file = file_metadata[i];
-
- tmp_file->store_string(
- "<File Name=\"" + file.name.replace("/", "\\") + "\" Size=\"" + itos(file.uncompressed_size) + "\" LfhSize=\"" + itos(file.lfh_size) + "\">");
-
- for (int j = 0; j < file.hashes.size(); j++) {
- tmp_file->store_string("<Block Hash=\"" + file.hashes[j].base64_hash + "\" ");
- if (file.compressed) {
- tmp_file->store_string("Size=\"" + itos(file.hashes[j].compressed_size) + "\" ");
- }
- tmp_file->store_string("/>");
- }
-
- tmp_file->store_string("</File>");
- }
-
- tmp_file->store_string("</BlockMap>");
-}
-
-String AppxPackager::content_type(String p_extension) {
- if (p_extension == "png") {
- return "image/png";
- } else if (p_extension == "jpg") {
- return "image/jpg";
- } else if (p_extension == "xml") {
- return "application/xml";
- } else if (p_extension == "exe" || p_extension == "dll") {
- return "application/x-msdownload";
- } else {
- return "application/octet-stream";
- }
-}
-
-void AppxPackager::make_content_types(const String &p_path) {
- Ref<FileAccess> tmp_file = FileAccess::open(p_path, FileAccess::WRITE);
-
- tmp_file->store_string("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
- tmp_file->store_string("<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">");
-
- HashMap<String, String> types;
-
- for (int i = 0; i < file_metadata.size(); i++) {
- String ext = file_metadata[i].name.get_extension().to_lower();
-
- if (types.has(ext)) {
- continue;
- }
-
- types[ext] = content_type(ext);
-
- tmp_file->store_string("<Default Extension=\"" + ext + "\" ContentType=\"" + types[ext] + "\" />");
- }
-
- // Appx signature file
- tmp_file->store_string("<Default Extension=\"p7x\" ContentType=\"application/octet-stream\" />");
-
- // Override for package files
- tmp_file->store_string("<Override PartName=\"/AppxManifest.xml\" ContentType=\"application/vnd.ms-appx.manifest+xml\" />");
- tmp_file->store_string("<Override PartName=\"/AppxBlockMap.xml\" ContentType=\"application/vnd.ms-appx.blockmap+xml\" />");
- tmp_file->store_string("<Override PartName=\"/AppxSignature.p7x\" ContentType=\"application/vnd.ms-appx.signature\" />");
- tmp_file->store_string("<Override PartName=\"/AppxMetadata/CodeIntegrity.cat\" ContentType=\"application/vnd.ms-pkiseccat\" />");
-
- tmp_file->store_string("</Types>");
-}
-
-Vector<uint8_t> AppxPackager::make_file_header(FileMeta p_file_meta) {
- Vector<uint8_t> buf;
- buf.resize(BASE_FILE_HEADER_SIZE + p_file_meta.name.length());
-
- int offs = 0;
- // Write magic
- offs += buf_put_int32(FILE_HEADER_MAGIC, &buf.write[offs]);
-
- // Version
- offs += buf_put_int16(ZIP_VERSION, &buf.write[offs]);
-
- // Special flag
- offs += buf_put_int16(GENERAL_PURPOSE, &buf.write[offs]);
-
- // Compression
- offs += buf_put_int16(p_file_meta.compressed ? Z_DEFLATED : 0, &buf.write[offs]);
-
- // File date and time
- offs += buf_put_int32(0, &buf.write[offs]);
-
- // CRC-32
- offs += buf_put_int32(p_file_meta.file_crc32, &buf.write[offs]);
-
- // Compressed size
- offs += buf_put_int32(p_file_meta.compressed_size, &buf.write[offs]);
-
- // Uncompressed size
- offs += buf_put_int32(p_file_meta.uncompressed_size, &buf.write[offs]);
-
- // File name length
- offs += buf_put_int16(p_file_meta.name.length(), &buf.write[offs]);
-
- // Extra data length
- offs += buf_put_int16(0, &buf.write[offs]);
-
- // File name
- offs += buf_put_string(p_file_meta.name, &buf.write[offs]);
-
- // Done!
- return buf;
-}
-
-void AppxPackager::store_central_dir_header(const FileMeta &p_file, bool p_do_hash) {
- Vector<uint8_t> &buf = central_dir_data;
- int offs = buf.size();
- buf.resize(buf.size() + BASE_CENTRAL_DIR_SIZE + p_file.name.length());
-
- // Write magic
- offs += buf_put_int32(CENTRAL_DIR_MAGIC, &buf.write[offs]);
-
- // ZIP versions
- offs += buf_put_int16(ZIP_ARCHIVE_VERSION, &buf.write[offs]);
- offs += buf_put_int16(ZIP_VERSION, &buf.write[offs]);
-
- // General purpose flag
- offs += buf_put_int16(GENERAL_PURPOSE, &buf.write[offs]);
-
- // Compression
- offs += buf_put_int16(p_file.compressed ? Z_DEFLATED : 0, &buf.write[offs]);
-
- // Modification date/time
- offs += buf_put_int32(0, &buf.write[offs]);
-
- // Crc-32
- offs += buf_put_int32(p_file.file_crc32, &buf.write[offs]);
-
- // File sizes
- offs += buf_put_int32(p_file.compressed_size, &buf.write[offs]);
- offs += buf_put_int32(p_file.uncompressed_size, &buf.write[offs]);
-
- // File name length
- offs += buf_put_int16(p_file.name.length(), &buf.write[offs]);
-
- // Extra field length
- offs += buf_put_int16(0, &buf.write[offs]);
-
- // Comment length
- offs += buf_put_int16(0, &buf.write[offs]);
-
- // Disk number start, internal/external file attributes
- for (int i = 0; i < 8; i++) {
- buf.write[offs++] = 0;
- }
-
- // Relative offset
- offs += buf_put_int32(p_file.zip_offset, &buf.write[offs]);
-
- // File name
- offs += buf_put_string(p_file.name, &buf.write[offs]);
-
- // Done!
-}
-
-Vector<uint8_t> AppxPackager::make_end_of_central_record() {
- Vector<uint8_t> buf;
- buf.resize(ZIP64_END_OF_CENTRAL_DIR_SIZE + 12 + END_OF_CENTRAL_DIR_SIZE); // Size plus magic
-
- int offs = 0;
-
- // Write magic
- offs += buf_put_int32(ZIP64_END_OF_CENTRAL_DIR_MAGIC, &buf.write[offs]);
-
- // Size of this record
- offs += buf_put_int64(ZIP64_END_OF_CENTRAL_DIR_SIZE, &buf.write[offs]);
-
- // Version (yes, twice)
- offs += buf_put_int16(ZIP_ARCHIVE_VERSION, &buf.write[offs]);
- offs += buf_put_int16(ZIP_ARCHIVE_VERSION, &buf.write[offs]);
-
- // Disk number
- for (int i = 0; i < 8; i++) {
- buf.write[offs++] = 0;
- }
-
- // Number of entries (total and per disk)
- offs += buf_put_int64(file_metadata.size(), &buf.write[offs]);
- offs += buf_put_int64(file_metadata.size(), &buf.write[offs]);
-
- // Size of central dir
- offs += buf_put_int64(central_dir_data.size(), &buf.write[offs]);
-
- // Central dir offset
- offs += buf_put_int64(central_dir_offset, &buf.write[offs]);
-
- ////// ZIP64 locator
-
- // Write magic for zip64 central dir locator
- offs += buf_put_int32(ZIP64_END_DIR_LOCATOR_MAGIC, &buf.write[offs]);
-
- // Disk number
- for (int i = 0; i < 4; i++) {
- buf.write[offs++] = 0;
- }
-
- // Relative offset
- offs += buf_put_int64(end_of_central_dir_offset, &buf.write[offs]);
-
- // Number of disks
- offs += buf_put_int32(1, &buf.write[offs]);
-
- /////// End of zip directory
-
- // Write magic for end central dir
- offs += buf_put_int32(END_OF_CENTRAL_DIR_MAGIC, &buf.write[offs]);
-
- // Dummy stuff for Zip64
- for (int i = 0; i < 4; i++) {
- buf.write[offs++] = 0x0;
- }
- for (int i = 0; i < 12; i++) {
- buf.write[offs++] = 0xFF;
- }
-
- // Size of comments
- for (int i = 0; i < 2; i++) {
- buf.write[offs++] = 0;
- }
-
- // Done!
- return buf;
-}
-
-void AppxPackager::init(Ref<FileAccess> p_fa) {
- package = p_fa;
- central_dir_offset = 0;
- end_of_central_dir_offset = 0;
-}
-
-Error AppxPackager::add_file(String p_file_name, const uint8_t *p_buffer, size_t p_len, int p_file_no, int p_total_files, bool p_compress) {
- if (p_file_no >= 1 && p_total_files >= 1) {
- if (EditorNode::progress_task_step(progress_task, "File: " + p_file_name, (p_file_no * 100) / p_total_files)) {
- return ERR_SKIP;
- }
- }
-
- FileMeta meta;
- meta.name = p_file_name;
- meta.uncompressed_size = p_len;
- meta.compressed = p_compress;
- meta.zip_offset = package->get_position();
-
- Vector<uint8_t> file_buffer;
-
- // Data for compression
- z_stream strm{};
- Vector<uint8_t> strm_in;
- strm_in.resize(BLOCK_SIZE);
- Vector<uint8_t> strm_out;
-
- if (p_compress) {
- strm.zalloc = zipio_alloc;
- strm.zfree = zipio_free;
- strm.opaque = Z_NULL;
-
- strm_out.resize(BLOCK_SIZE + 8);
-
- deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
- }
-
- int step = 0;
-
- while (p_len - step > 0) {
- size_t block_size = (p_len - step) > BLOCK_SIZE ? (size_t)BLOCK_SIZE : (p_len - step);
-
- for (uint64_t i = 0; i < block_size; i++) {
- strm_in.write[i] = p_buffer[step + i];
- }
-
- BlockHash bh;
- bh.base64_hash = hash_block(strm_in.ptr(), block_size);
-
- if (p_compress) {
- strm.avail_in = block_size;
- strm.avail_out = strm_out.size();
- strm.next_in = (uint8_t *)strm_in.ptr();
- strm.next_out = strm_out.ptrw();
-
- int total_out_before = strm.total_out;
-
- int err = deflate(&strm, Z_FULL_FLUSH);
- ERR_FAIL_COND_V(err < 0, ERR_BUG); // Negative means bug
-
- bh.compressed_size = strm.total_out - total_out_before;
-
- //package->store_buffer(strm_out.ptr(), strm.total_out - total_out_before);
- int start = file_buffer.size();
- file_buffer.resize(file_buffer.size() + bh.compressed_size);
- for (uint64_t i = 0; i < bh.compressed_size; i++) {
- file_buffer.write[start + i] = strm_out[i];
- }
- } else {
- bh.compressed_size = block_size;
- //package->store_buffer(strm_in.ptr(), block_size);
- int start = file_buffer.size();
- file_buffer.resize(file_buffer.size() + block_size);
- for (uint64_t i = 0; i < bh.compressed_size; i++) {
- file_buffer.write[start + i] = strm_in[i];
- }
- }
-
- meta.hashes.push_back(bh);
-
- step += block_size;
- }
-
- if (p_compress) {
- strm.avail_in = 0;
- strm.avail_out = strm_out.size();
- strm.next_in = (uint8_t *)strm_in.ptr();
- strm.next_out = strm_out.ptrw();
-
- int total_out_before = strm.total_out;
-
- deflate(&strm, Z_FINISH);
-
- //package->store_buffer(strm_out.ptr(), strm.total_out - total_out_before);
- int start = file_buffer.size();
- file_buffer.resize(file_buffer.size() + (strm.total_out - total_out_before));
- for (uint64_t i = 0; i < (strm.total_out - total_out_before); i++) {
- file_buffer.write[start + i] = strm_out[i];
- }
-
- deflateEnd(&strm);
- meta.compressed_size = strm.total_out;
-
- } else {
- meta.compressed_size = p_len;
- }
-
- // Calculate file CRC-32
- uLong crc = crc32(0L, Z_NULL, 0);
- crc = crc32(crc, p_buffer, p_len);
- meta.file_crc32 = crc;
-
- // Create file header
- Vector<uint8_t> file_header = make_file_header(meta);
- meta.lfh_size = file_header.size();
-
- // Store the header and file;
- package->store_buffer(file_header.ptr(), file_header.size());
- package->store_buffer(file_buffer.ptr(), file_buffer.size());
-
- file_metadata.push_back(meta);
-
- return OK;
-}
-
-void AppxPackager::finish() {
- // Create and add block map file
- EditorNode::progress_task_step("export", "Creating block map...", 4);
-
- const String &tmp_blockmap_file_path = EditorPaths::get_singleton()->get_cache_dir().path_join("tmpblockmap.xml");
- make_block_map(tmp_blockmap_file_path);
-
- {
- Ref<FileAccess> blockmap_file = FileAccess::open(tmp_blockmap_file_path, FileAccess::READ);
- Vector<uint8_t> blockmap_buffer;
- blockmap_buffer.resize(blockmap_file->get_length());
-
- blockmap_file->get_buffer(blockmap_buffer.ptrw(), blockmap_buffer.size());
-
- add_file("AppxBlockMap.xml", blockmap_buffer.ptr(), blockmap_buffer.size(), -1, -1, true);
- }
-
- // Add content types
-
- EditorNode::progress_task_step("export", "Setting content types...", 5);
-
- const String &tmp_content_types_file_path = EditorPaths::get_singleton()->get_cache_dir().path_join("tmpcontenttypes.xml");
- make_content_types(tmp_content_types_file_path);
-
- {
- Ref<FileAccess> types_file = FileAccess::open(tmp_content_types_file_path, FileAccess::READ);
- Vector<uint8_t> types_buffer;
- types_buffer.resize(types_file->get_length());
-
- types_file->get_buffer(types_buffer.ptrw(), types_buffer.size());
-
- add_file("[Content_Types].xml", types_buffer.ptr(), types_buffer.size(), -1, -1, true);
- }
-
- // Cleanup generated files.
- DirAccess::remove_file_or_error(tmp_blockmap_file_path);
- DirAccess::remove_file_or_error(tmp_content_types_file_path);
-
- // Pre-process central directory before signing
- for (int i = 0; i < file_metadata.size(); i++) {
- store_central_dir_header(file_metadata[i]);
- }
-
- // Write central directory
- EditorNode::progress_task_step("export", "Finishing package...", 6);
- central_dir_offset = package->get_position();
- package->store_buffer(central_dir_data.ptr(), central_dir_data.size());
-
- // End record
- end_of_central_dir_offset = package->get_position();
- Vector<uint8_t> end_record = make_end_of_central_record();
- package->store_buffer(end_record.ptr(), end_record.size());
-
- package.unref();
-}
-
-AppxPackager::AppxPackager() {}
-
-AppxPackager::~AppxPackager() {}
diff --git a/platform/uwp/export/app_packager.h b/platform/uwp/export/app_packager.h
deleted file mode 100644
index e989ba9b90..0000000000
--- a/platform/uwp/export/app_packager.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/**************************************************************************/
-/* app_packager.h */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#ifndef UWP_APP_PACKAGER_H
-#define UWP_APP_PACKAGER_H
-
-#include "core/config/project_settings.h"
-#include "core/core_bind.h"
-#include "core/crypto/crypto_core.h"
-#include "core/io/dir_access.h"
-#include "core/io/file_access.h"
-#include "core/io/marshalls.h"
-#include "core/io/zip_io.h"
-#include "core/object/class_db.h"
-#include "core/version.h"
-#include "editor/export/editor_export_platform.h"
-
-#include "thirdparty/minizip/unzip.h"
-#include "thirdparty/minizip/zip.h"
-
-#include <zlib.h>
-
-class AppxPackager {
- enum {
- FILE_HEADER_MAGIC = 0x04034b50,
- DATA_DESCRIPTOR_MAGIC = 0x08074b50,
- CENTRAL_DIR_MAGIC = 0x02014b50,
- END_OF_CENTRAL_DIR_MAGIC = 0x06054b50,
- ZIP64_END_OF_CENTRAL_DIR_MAGIC = 0x06064b50,
- ZIP64_END_DIR_LOCATOR_MAGIC = 0x07064b50,
- P7X_SIGNATURE = 0x58434b50,
- ZIP64_HEADER_ID = 0x0001,
- ZIP_VERSION = 20,
- ZIP_ARCHIVE_VERSION = 45,
- GENERAL_PURPOSE = 0x00,
- BASE_FILE_HEADER_SIZE = 30,
- DATA_DESCRIPTOR_SIZE = 24,
- BASE_CENTRAL_DIR_SIZE = 46,
- EXTRA_FIELD_LENGTH = 28,
- ZIP64_HEADER_SIZE = 24,
- ZIP64_END_OF_CENTRAL_DIR_SIZE = (56 - 12),
- END_OF_CENTRAL_DIR_SIZE = 42,
- BLOCK_SIZE = 65536,
- };
-
- struct BlockHash {
- String base64_hash;
- size_t compressed_size = 0;
- };
-
- struct FileMeta {
- String name;
- int lfh_size = 0;
- bool compressed = false;
- size_t compressed_size = 0;
- size_t uncompressed_size = 0;
- Vector<BlockHash> hashes;
- uLong file_crc32 = 0;
- ZPOS64_T zip_offset = 0;
- };
-
- String progress_task;
- Ref<FileAccess> package;
-
- HashSet<String> mime_types;
-
- Vector<FileMeta> file_metadata;
-
- ZPOS64_T central_dir_offset = 0;
- ZPOS64_T end_of_central_dir_offset = 0;
- Vector<uint8_t> central_dir_data;
-
- String hash_block(const uint8_t *p_block_data, size_t p_block_len);
-
- void make_block_map(const String &p_path);
- void make_content_types(const String &p_path);
-
- _FORCE_INLINE_ unsigned int buf_put_int16(uint16_t p_val, uint8_t *p_buf) {
- for (int i = 0; i < 2; i++) {
- *p_buf++ = (p_val >> (i * 8)) & 0xFF;
- }
- return 2;
- }
-
- _FORCE_INLINE_ unsigned int buf_put_int32(uint32_t p_val, uint8_t *p_buf) {
- for (int i = 0; i < 4; i++) {
- *p_buf++ = (p_val >> (i * 8)) & 0xFF;
- }
- return 4;
- }
-
- _FORCE_INLINE_ unsigned int buf_put_int64(uint64_t p_val, uint8_t *p_buf) {
- for (int i = 0; i < 8; i++) {
- *p_buf++ = (p_val >> (i * 8)) & 0xFF;
- }
- return 8;
- }
-
- _FORCE_INLINE_ unsigned int buf_put_string(String p_val, uint8_t *p_buf) {
- for (int i = 0; i < p_val.length(); i++) {
- *p_buf++ = p_val.utf8().get(i);
- }
- return p_val.length();
- }
-
- Vector<uint8_t> make_file_header(FileMeta p_file_meta);
- void store_central_dir_header(const FileMeta &p_file, bool p_do_hash = true);
- Vector<uint8_t> make_end_of_central_record();
-
- String content_type(String p_extension);
-
-public:
- void set_progress_task(String p_task) { progress_task = p_task; }
- void init(Ref<FileAccess> p_fa);
- Error add_file(String p_file_name, const uint8_t *p_buffer, size_t p_len, int p_file_no, int p_total_files, bool p_compress = false);
- void finish();
-
- AppxPackager();
- ~AppxPackager();
-};
-
-#endif // UWP_APP_PACKAGER_H
diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp
deleted file mode 100644
index 3e229c7419..0000000000
--- a/platform/uwp/export/export.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/**************************************************************************/
-/* export.cpp */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#include "export.h"
-
-#include "export_plugin.h"
-
-#include "editor/editor_settings.h"
-#include "editor/export/editor_export.h"
-
-void register_uwp_exporter_types() {
- // GDREGISTER_VIRTUAL_CLASS(EditorExportPlatformUWP);
-}
-
-void register_uwp_exporter() {
-#ifdef WINDOWS_ENABLED
- EDITOR_DEF("export/uwp/signtool", "");
- EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/uwp/signtool", PROPERTY_HINT_GLOBAL_FILE, "*.exe"));
- EDITOR_DEF("export/uwp/debug_certificate", "");
- EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/uwp/debug_certificate", PROPERTY_HINT_GLOBAL_FILE, "*.pfx"));
- EDITOR_DEF("export/uwp/debug_password", "");
- EDITOR_DEF("export/uwp/debug_algorithm", 2); // SHA256 is the default
- EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "export/uwp/debug_algorithm", PROPERTY_HINT_ENUM, "MD5,SHA1,SHA256"));
-#endif // WINDOWS_ENABLED
-
- Ref<EditorExportPlatformUWP> exporter;
- exporter.instantiate();
- EditorExport::get_singleton()->add_export_platform(exporter);
-}
diff --git a/platform/uwp/export/export_plugin.cpp b/platform/uwp/export/export_plugin.cpp
deleted file mode 100644
index c92520b755..0000000000
--- a/platform/uwp/export/export_plugin.cpp
+++ /dev/null
@@ -1,525 +0,0 @@
-/**************************************************************************/
-/* export_plugin.cpp */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#include "export_plugin.h"
-
-#include "logo_svg.gen.h"
-
-#include "editor/editor_scale.h"
-#include "editor/editor_settings.h"
-#include "scene/resources/image_texture.h"
-
-#include "modules/modules_enabled.gen.h" // For svg and regex.
-#ifdef MODULE_SVG_ENABLED
-#include "modules/svg/image_loader_svg.h"
-#endif
-
-String EditorExportPlatformUWP::get_name() const {
- return "UWP";
-}
-String EditorExportPlatformUWP::get_os_name() const {
- return "UWP";
-}
-
-List<String> EditorExportPlatformUWP::get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const {
- List<String> list;
- list.push_back("appx");
- return list;
-}
-
-Ref<Texture2D> EditorExportPlatformUWP::get_logo() const {
- return logo;
-}
-
-void EditorExportPlatformUWP::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const {
- r_features->push_back("s3tc");
- r_features->push_back("etc");
- r_features->push_back(p_preset->get("binary_format/architecture"));
-}
-
-void EditorExportPlatformUWP::get_export_options(List<ExportOption> *r_options) const {
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
-
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "binary_format/architecture", PROPERTY_HINT_ENUM, "x86_64,x86_32,arm32"), "x86_64"));
-
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "command_line/extra_args"), ""));
-
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/display_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/short_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/unique_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game.Name"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/description"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/publisher", PROPERTY_HINT_PLACEHOLDER_TEXT, "CN=CompanyName"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/publisher_display_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Company Name"), ""));
-
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "identity/product_guid", PROPERTY_HINT_PLACEHOLDER_TEXT, "00000000-0000-0000-0000-000000000000"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "identity/publisher_guid", PROPERTY_HINT_PLACEHOLDER_TEXT, "00000000-0000-0000-0000-000000000000"), ""));
-
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "signing/certificate", PROPERTY_HINT_GLOBAL_FILE, "*.pfx", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "signing/password", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "signing/algorithm", PROPERTY_HINT_ENUM, "MD5,SHA1,SHA256"), 2));
-
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/major"), 1));
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/minor"), 0));
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/build"), 0));
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/revision"), 0));
-
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "orientation/landscape"), true));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "orientation/portrait"), true));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "orientation/landscape_flipped"), true));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "orientation/portrait_flipped"), true));
-
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "images/background_color"), "transparent"));
- r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/store_logo", PROPERTY_HINT_RESOURCE_TYPE, "CompressedTexture2D"), Variant()));
- r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/square44x44_logo", PROPERTY_HINT_RESOURCE_TYPE, "CompressedTexture2D"), Variant()));
- r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/square71x71_logo", PROPERTY_HINT_RESOURCE_TYPE, "CompressedTexture2D"), Variant()));
- r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/square150x150_logo", PROPERTY_HINT_RESOURCE_TYPE, "CompressedTexture2D"), Variant()));
- r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/square310x310_logo", PROPERTY_HINT_RESOURCE_TYPE, "CompressedTexture2D"), Variant()));
- r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/wide310x150_logo", PROPERTY_HINT_RESOURCE_TYPE, "CompressedTexture2D"), Variant()));
- r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/splash_screen", PROPERTY_HINT_RESOURCE_TYPE, "CompressedTexture2D"), Variant()));
-
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "tiles/show_name_on_square150x150"), false));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "tiles/show_name_on_wide310x150"), false));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "tiles/show_name_on_square310x310"), false));
-
- // Capabilities
- const char **basic = uwp_capabilities;
- while (*basic) {
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/" + String(*basic)), false));
- basic++;
- }
-
- const char **uap = uwp_uap_capabilities;
- while (*uap) {
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/" + String(*uap)), false));
- uap++;
- }
-
- const char **device = uwp_device_capabilities;
- while (*device) {
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/" + String(*device)), false));
- device++;
- }
-}
-
-bool EditorExportPlatformUWP::has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug) const {
-#ifndef DEV_ENABLED
- // We don't provide export templates for the UWP platform currently as it
- // has not been ported for Godot 4. This is skipped in DEV_ENABLED so that
- // contributors can still test the pipeline if/when we can build it again.
- r_error = "The UWP platform is currently not supported in Godot 4.\n";
- return false;
-#else
-
- String err;
- bool valid = false;
-
- // Look for export templates (first official, and if defined custom templates).
- String arch = p_preset->get("binary_format/architecture");
- String arch_infix;
- if (arch == "arm32") {
- arch_infix = "arm";
- } else if (arch == "x86_32") {
- arch_infix = "x86";
- } else if (arch == "x86_64") {
- arch_infix = "x64";
- }
-
- bool dvalid = exists_export_template("uwp_" + arch_infix + "_debug.zip", &err);
- bool rvalid = exists_export_template("uwp_" + arch_infix + "_release.zip", &err);
-
- if (p_preset->get("custom_template/debug") != "") {
- dvalid = FileAccess::exists(p_preset->get("custom_template/debug"));
- if (!dvalid) {
- err += TTR("Custom debug template not found.") + "\n";
- }
- }
- if (p_preset->get("custom_template/release") != "") {
- rvalid = FileAccess::exists(p_preset->get("custom_template/release"));
- if (!rvalid) {
- err += TTR("Custom release template not found.") + "\n";
- }
- }
-
- valid = dvalid || rvalid;
- r_missing_templates = !valid;
-
- if (!err.is_empty()) {
- r_error = err;
- }
-
- return valid;
-#endif // DEV_ENABLED
-}
-
-bool EditorExportPlatformUWP::has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const {
-#ifndef DEV_ENABLED
- // We don't provide export templates for the UWP platform currently as it
- // has not been ported for Godot 4. This is skipped in DEV_ENABLED so that
- // contributors can still test the pipeline if/when we can build it again.
- r_error = "The UWP platform is currently not supported in Godot 4.\n";
- return false;
-#else
-
- String err;
- bool valid = true;
-
- // Validate the project configuration.
-
- if (!_valid_resource_name(p_preset->get("package/short_name"))) {
- valid = false;
- err += TTR("Invalid package short name.") + "\n";
- }
-
- if (!_valid_resource_name(p_preset->get("package/unique_name"))) {
- valid = false;
- err += TTR("Invalid package unique name.") + "\n";
- }
-
- if (!_valid_resource_name(p_preset->get("package/publisher_display_name"))) {
- valid = false;
- err += TTR("Invalid package publisher display name.") + "\n";
- }
-
- if (!_valid_guid(p_preset->get("identity/product_guid"))) {
- valid = false;
- err += TTR("Invalid product GUID.") + "\n";
- }
-
- if (!_valid_guid(p_preset->get("identity/publisher_guid"))) {
- valid = false;
- err += TTR("Invalid publisher GUID.") + "\n";
- }
-
- if (!_valid_bgcolor(p_preset->get("images/background_color"))) {
- valid = false;
- err += TTR("Invalid background color.") + "\n";
- }
-
- if (!p_preset->get("images/store_logo").is_zero() && !_valid_image((Object::cast_to<CompressedTexture2D>((Object *)p_preset->get("images/store_logo"))), 50, 50)) {
- valid = false;
- err += TTR("Invalid Store Logo image dimensions (should be 50x50).") + "\n";
- }
-
- if (!p_preset->get("images/square44x44_logo").is_zero() && !_valid_image((Object::cast_to<CompressedTexture2D>((Object *)p_preset->get("images/square44x44_logo"))), 44, 44)) {
- valid = false;
- err += TTR("Invalid square 44x44 logo image dimensions (should be 44x44).") + "\n";
- }
-
- if (!p_preset->get("images/square71x71_logo").is_zero() && !_valid_image((Object::cast_to<CompressedTexture2D>((Object *)p_preset->get("images/square71x71_logo"))), 71, 71)) {
- valid = false;
- err += TTR("Invalid square 71x71 logo image dimensions (should be 71x71).") + "\n";
- }
-
- if (!p_preset->get("images/square150x150_logo").is_zero() && !_valid_image((Object::cast_to<CompressedTexture2D>((Object *)p_preset->get("images/square150x150_logo"))), 150, 150)) {
- valid = false;
- err += TTR("Invalid square 150x150 logo image dimensions (should be 150x150).") + "\n";
- }
-
- if (!p_preset->get("images/square310x310_logo").is_zero() && !_valid_image((Object::cast_to<CompressedTexture2D>((Object *)p_preset->get("images/square310x310_logo"))), 310, 310)) {
- valid = false;
- err += TTR("Invalid square 310x310 logo image dimensions (should be 310x310).") + "\n";
- }
-
- if (!p_preset->get("images/wide310x150_logo").is_zero() && !_valid_image((Object::cast_to<CompressedTexture2D>((Object *)p_preset->get("images/wide310x150_logo"))), 310, 150)) {
- valid = false;
- err += TTR("Invalid wide 310x150 logo image dimensions (should be 310x150).") + "\n";
- }
-
- if (!p_preset->get("images/splash_screen").is_zero() && !_valid_image((Object::cast_to<CompressedTexture2D>((Object *)p_preset->get("images/splash_screen"))), 620, 300)) {
- valid = false;
- err += TTR("Invalid splash screen image dimensions (should be 620x300).") + "\n";
- }
-
- r_error = err;
- return valid;
-#endif // DEV_ENABLED
-}
-
-Error EditorExportPlatformUWP::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
- ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
-
- String src_appx;
-
- EditorProgress ep("export", TTR("Exporting for UWP"), 7, true);
-
- if (p_debug) {
- src_appx = p_preset->get("custom_template/debug");
- } else {
- src_appx = p_preset->get("custom_template/release");
- }
-
- src_appx = src_appx.strip_edges();
-
- String arch = p_preset->get("binary_format/architecture");
-
- if (src_appx.is_empty()) {
- String err, arch_infix;
- if (arch == "arm32") {
- arch_infix = "arm";
- } else if (arch == "x86_32") {
- arch_infix = "x86";
- } else if (arch == "x86_64") {
- arch_infix = "x64";
- }
- if (p_debug) {
- src_appx = find_export_template("uwp_" + arch_infix + "_debug.zip", &err);
- } else {
- src_appx = find_export_template("uwp_" + arch_infix + "_release.zip", &err);
- }
- if (src_appx.is_empty()) {
- EditorNode::add_io_error(err);
- return ERR_FILE_NOT_FOUND;
- }
- }
-
- if (!DirAccess::exists(p_path.get_base_dir())) {
- return ERR_FILE_BAD_PATH;
- }
-
- Error err = OK;
-
- Ref<FileAccess> fa_pack = FileAccess::open(p_path, FileAccess::WRITE, &err);
- ERR_FAIL_COND_V_MSG(err != OK, ERR_CANT_CREATE, "Cannot create file '" + p_path + "'.");
-
- AppxPackager packager;
- packager.init(fa_pack);
-
- Ref<FileAccess> io_fa;
- zlib_filefunc_def io = zipio_create_io(&io_fa);
-
- if (ep.step("Creating package...", 0)) {
- return ERR_SKIP;
- }
-
- unzFile pkg = unzOpen2(src_appx.utf8().get_data(), &io);
-
- if (!pkg) {
- EditorNode::add_io_error("Could not find template appx to export:\n" + src_appx);
- return ERR_FILE_NOT_FOUND;
- }
-
- int ret = unzGoToFirstFile(pkg);
-
- if (ep.step("Copying template files...", 1)) {
- return ERR_SKIP;
- }
-
- EditorNode::progress_add_task("template_files", "Template files", 100);
- packager.set_progress_task("template_files");
-
- int template_files_amount = 9;
- int template_file_no = 1;
-
- while (ret == UNZ_OK) {
- // get file name
- unz_file_info info;
- char fname[16834];
- ret = unzGetCurrentFileInfo(pkg, &info, fname, 16834, nullptr, 0, nullptr, 0);
- if (ret != UNZ_OK) {
- break;
- }
-
- String path = String::utf8(fname);
-
- if (path.ends_with("/")) {
- // Ignore directories
- ret = unzGoToNextFile(pkg);
- continue;
- }
-
- Vector<uint8_t> data;
- bool do_read = true;
-
- if (path.begins_with("Assets/")) {
- path = path.replace(".scale-100", "");
-
- data = _get_image_data(p_preset, path);
- if (data.size() > 0) {
- do_read = false;
- }
- }
-
- //read
- if (do_read) {
- data.resize(info.uncompressed_size);
- unzOpenCurrentFile(pkg);
- unzReadCurrentFile(pkg, data.ptrw(), data.size());
- unzCloseCurrentFile(pkg);
- }
-
- if (path == "AppxManifest.xml") {
- data = _fix_manifest(p_preset, data, p_flags & (DEBUG_FLAG_DUMB_CLIENT | DEBUG_FLAG_REMOTE_DEBUG));
- }
-
- print_line("ADDING: " + path);
-
- err = packager.add_file(path, data.ptr(), data.size(), template_file_no++, template_files_amount, _should_compress_asset(path, data));
- if (err != OK) {
- return err;
- }
-
- ret = unzGoToNextFile(pkg);
- }
-
- EditorNode::progress_end_task("template_files");
-
- if (ep.step("Creating command line...", 2)) {
- return ERR_SKIP;
- }
-
- Vector<String> cl = ((String)p_preset->get("command_line/extra_args")).strip_edges().split(" ");
- for (int i = 0; i < cl.size(); i++) {
- if (cl[i].strip_edges().length() == 0) {
- cl.remove_at(i);
- i--;
- }
- }
-
- if (!(p_flags & DEBUG_FLAG_DUMB_CLIENT)) {
- cl.push_back("--path");
- cl.push_back("game");
- }
-
- gen_export_flags(cl, p_flags);
-
- // Command line file
- Vector<uint8_t> clf;
-
- // Argc
- clf.resize(4);
- encode_uint32(cl.size(), clf.ptrw());
-
- for (int i = 0; i < cl.size(); i++) {
- CharString txt = cl[i].utf8();
- int base = clf.size();
- clf.resize(base + 4 + txt.length());
- encode_uint32(txt.length(), &clf.write[base]);
- memcpy(&clf.write[base + 4], txt.ptr(), txt.length());
- print_line(itos(i) + " param: " + cl[i]);
- }
-
- err = packager.add_file("__cl__.cl", clf.ptr(), clf.size(), -1, -1, false);
- if (err != OK) {
- return err;
- }
-
- if (ep.step("Adding project files...", 3)) {
- return ERR_SKIP;
- }
-
- EditorNode::progress_add_task("project_files", "Project Files", 100);
- packager.set_progress_task("project_files");
-
- err = export_project_files(p_preset, p_debug, save_appx_file, &packager);
-
- EditorNode::progress_end_task("project_files");
-
- if (ep.step("Closing package...", 7)) {
- return ERR_SKIP;
- }
-
- unzClose(pkg);
-
- packager.finish();
-
-#ifdef WINDOWS_ENABLED
- // Sign with signtool
- String signtool_path = EDITOR_GET("export/uwp/signtool");
- if (signtool_path.is_empty()) {
- return OK;
- }
-
- if (!FileAccess::exists(signtool_path)) {
- ERR_PRINT("Could not find signtool executable at " + signtool_path + ", aborting.");
- return ERR_FILE_NOT_FOUND;
- }
-
- static String algs[] = { "MD5", "SHA1", "SHA256" };
-
- String cert_path = EDITOR_GET("export/uwp/debug_certificate");
- String cert_pass = EDITOR_GET("export/uwp/debug_password");
- int cert_alg = EDITOR_GET("export/uwp/debug_algorithm");
-
- if (!p_debug) {
- cert_path = p_preset->get_or_env("signing/certificate", ENV_UWP_SIGNING_CERT);
- cert_pass = p_preset->get_or_env("signing/password", ENV_UWP_SIGNING_PASS);
- cert_alg = p_preset->get("signing/algorithm");
- }
-
- if (cert_path.is_empty()) {
- return OK; // Certificate missing, don't try to sign
- }
-
- if (!FileAccess::exists(cert_path)) {
- ERR_PRINT("Could not find certificate file at " + cert_path + ", aborting.");
- return ERR_FILE_NOT_FOUND;
- }
-
- if (cert_alg < 0 || cert_alg > 2) {
- ERR_PRINT("Invalid certificate algorithm " + itos(cert_alg) + ", aborting.");
- return ERR_INVALID_DATA;
- }
-
- List<String> args;
- args.push_back("sign");
- args.push_back("/fd");
- args.push_back(algs[cert_alg]);
- args.push_back("/a");
- args.push_back("/f");
- args.push_back(cert_path);
- args.push_back("/p");
- args.push_back(cert_pass);
- args.push_back(p_path);
-
- OS::get_singleton()->execute(signtool_path, args);
-#endif // WINDOWS_ENABLED
-
- return OK;
-}
-
-void EditorExportPlatformUWP::get_platform_features(List<String> *r_features) const {
- r_features->push_back("pc");
- r_features->push_back("uwp");
-}
-
-void EditorExportPlatformUWP::resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) {
-}
-
-EditorExportPlatformUWP::EditorExportPlatformUWP() {
-#ifdef MODULE_SVG_ENABLED
- Ref<Image> img = memnew(Image);
- const bool upsample = !Math::is_equal_approx(Math::round(EDSCALE), EDSCALE);
-
- ImageLoaderSVG::create_image_from_string(img, _uwp_logo_svg, EDSCALE, upsample, false);
-
- logo = ImageTexture::create_from_image(img);
-#endif
-}
diff --git a/platform/uwp/export/export_plugin.h b/platform/uwp/export/export_plugin.h
deleted file mode 100644
index 147279e5c5..0000000000
--- a/platform/uwp/export/export_plugin.h
+++ /dev/null
@@ -1,450 +0,0 @@
-/**************************************************************************/
-/* export_plugin.h */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#ifndef UWP_EXPORT_PLUGIN_H
-#define UWP_EXPORT_PLUGIN_H
-
-#include "app_packager.h"
-
-#include "core/config/project_settings.h"
-#include "core/crypto/crypto_core.h"
-#include "core/io/dir_access.h"
-#include "core/io/file_access.h"
-#include "core/io/marshalls.h"
-#include "core/io/zip_io.h"
-#include "core/object/class_db.h"
-#include "core/version.h"
-#include "editor/editor_node.h"
-#include "editor/editor_paths.h"
-#include "editor/export/editor_export_platform.h"
-#include "scene/resources/compressed_texture.h"
-
-#include "thirdparty/minizip/unzip.h"
-#include "thirdparty/minizip/zip.h"
-
-#include <zlib.h>
-
-// Capabilities
-static const char *uwp_capabilities[] = {
- "allJoyn",
- "codeGeneration",
- "internetClient",
- "internetClientServer",
- "privateNetworkClientServer",
- nullptr
-};
-static const char *uwp_uap_capabilities[] = {
- "appointments",
- "blockedChatMessages",
- "chat",
- "contacts",
- "enterpriseAuthentication",
- "musicLibrary",
- "objects3D",
- "picturesLibrary",
- "phoneCall",
- "removableStorage",
- "sharedUserCertificates",
- "userAccountInformation",
- "videosLibrary",
- "voipCall",
- nullptr
-};
-static const char *uwp_device_capabilities[] = {
- "bluetooth",
- "location",
- "microphone",
- "proximity",
- "webcam",
- nullptr
-};
-
-// Optional environment variables for defining confidential information. If any
-// of these is set, they will override the values set in the credentials file.
-const String ENV_UWP_SIGNING_CERT = "GODOT_UWP_SIGNING_CERTIFICATE";
-const String ENV_UWP_SIGNING_PASS = "GODOT_UWP_SIGNING_PASSWORD";
-
-class EditorExportPlatformUWP : public EditorExportPlatform {
- GDCLASS(EditorExportPlatformUWP, EditorExportPlatform);
-
- Ref<ImageTexture> logo;
-
- bool _valid_resource_name(const String &p_name) const {
- if (p_name.is_empty()) {
- return false;
- }
- if (p_name.ends_with(".")) {
- return false;
- }
-
- static const char *invalid_names[] = {
- "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7",
- "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
- nullptr
- };
-
- const char **t = invalid_names;
- while (*t) {
- if (p_name == *t) {
- return false;
- }
- t++;
- }
-
- return true;
- }
-
- bool _valid_guid(const String &p_guid) const {
- Vector<String> parts = p_guid.split("-");
-
- if (parts.size() != 5) {
- return false;
- }
- if (parts[0].length() != 8) {
- return false;
- }
- for (int i = 1; i < 4; i++) {
- if (parts[i].length() != 4) {
- return false;
- }
- }
- if (parts[4].length() != 12) {
- return false;
- }
-
- return true;
- }
-
- bool _valid_bgcolor(const String &p_color) const {
- if (p_color.is_empty()) {
- return true;
- }
- if (p_color.begins_with("#") && p_color.is_valid_html_color()) {
- return true;
- }
-
- // Colors from https://msdn.microsoft.com/en-us/library/windows/apps/dn934817.aspx
- static const char *valid_colors[] = {
- "aliceBlue", "antiqueWhite", "aqua", "aquamarine", "azure", "beige",
- "bisque", "black", "blanchedAlmond", "blue", "blueViolet", "brown",
- "burlyWood", "cadetBlue", "chartreuse", "chocolate", "coral", "cornflowerBlue",
- "cornsilk", "crimson", "cyan", "darkBlue", "darkCyan", "darkGoldenrod",
- "darkGray", "darkGreen", "darkKhaki", "darkMagenta", "darkOliveGreen", "darkOrange",
- "darkOrchid", "darkRed", "darkSalmon", "darkSeaGreen", "darkSlateBlue", "darkSlateGray",
- "darkTurquoise", "darkViolet", "deepPink", "deepSkyBlue", "dimGray", "dodgerBlue",
- "firebrick", "floralWhite", "forestGreen", "fuchsia", "gainsboro", "ghostWhite",
- "gold", "goldenrod", "gray", "green", "greenYellow", "honeydew",
- "hotPink", "indianRed", "indigo", "ivory", "khaki", "lavender",
- "lavenderBlush", "lawnGreen", "lemonChiffon", "lightBlue", "lightCoral", "lightCyan",
- "lightGoldenrodYellow", "lightGreen", "lightGray", "lightPink", "lightSalmon", "lightSeaGreen",
- "lightSkyBlue", "lightSlateGray", "lightSteelBlue", "lightYellow", "lime", "limeGreen",
- "linen", "magenta", "maroon", "mediumAquamarine", "mediumBlue", "mediumOrchid",
- "mediumPurple", "mediumSeaGreen", "mediumSlateBlue", "mediumSpringGreen", "mediumTurquoise", "mediumVioletRed",
- "midnightBlue", "mintCream", "mistyRose", "moccasin", "navajoWhite", "navy",
- "oldLace", "olive", "oliveDrab", "orange", "orangeRed", "orchid",
- "paleGoldenrod", "paleGreen", "paleTurquoise", "paleVioletRed", "papayaWhip", "peachPuff",
- "peru", "pink", "plum", "powderBlue", "purple", "red",
- "rosyBrown", "royalBlue", "saddleBrown", "salmon", "sandyBrown", "seaGreen",
- "seaShell", "sienna", "silver", "skyBlue", "slateBlue", "slateGray",
- "snow", "springGreen", "steelBlue", "tan", "teal", "thistle",
- "tomato", "transparent", "turquoise", "violet", "wheat", "white",
- "whiteSmoke", "yellow", "yellowGreen",
- nullptr
- };
-
- const char **color = valid_colors;
-
- while (*color) {
- if (p_color == *color) {
- return true;
- }
- color++;
- }
-
- return false;
- }
-
- bool _valid_image(const CompressedTexture2D *p_image, int p_width, int p_height) const {
- if (!p_image) {
- return false;
- }
-
- // TODO: Add resource creation or image rescaling to enable other scales:
- // 1.25, 1.5, 2.0
- return p_width == p_image->get_width() && p_height == p_image->get_height();
- }
-
- Vector<uint8_t> _fix_manifest(const Ref<EditorExportPreset> &p_preset, const Vector<uint8_t> &p_template, bool p_give_internet) const {
- String result = String::utf8((const char *)p_template.ptr(), p_template.size());
-
- result = result.replace("$godot_version$", VERSION_FULL_NAME);
-
- result = result.replace("$identity_name$", p_preset->get("package/unique_name"));
- result = result.replace("$publisher$", p_preset->get("package/publisher"));
-
- result = result.replace("$product_guid$", p_preset->get("identity/product_guid"));
- result = result.replace("$publisher_guid$", p_preset->get("identity/publisher_guid"));
-
- String version = itos(p_preset->get("version/major")) + "." + itos(p_preset->get("version/minor")) + "." + itos(p_preset->get("version/build")) + "." + itos(p_preset->get("version/revision"));
- result = result.replace("$version_string$", version);
-
- String arch = p_preset->get("binary_format/architecture");
- String architecture = arch == "arm32" ? "arm" : (arch == "x86_32" ? "x86" : "x64");
- result = result.replace("$architecture$", architecture);
-
- result = result.replace("$display_name$", String(p_preset->get("package/display_name")).is_empty() ? (String)GLOBAL_GET("application/config/name") : String(p_preset->get("package/display_name")));
-
- result = result.replace("$publisher_display_name$", p_preset->get("package/publisher_display_name"));
- result = result.replace("$app_description$", p_preset->get("package/description"));
- result = result.replace("$bg_color$", p_preset->get("images/background_color"));
- result = result.replace("$short_name$", p_preset->get("package/short_name"));
-
- String name_on_tiles = "";
- if ((bool)p_preset->get("tiles/show_name_on_square150x150")) {
- name_on_tiles += " <uap:ShowOn Tile=\"square150x150Logo\" />\n";
- }
- if ((bool)p_preset->get("tiles/show_name_on_wide310x150")) {
- name_on_tiles += " <uap:ShowOn Tile=\"wide310x150Logo\" />\n";
- }
- if ((bool)p_preset->get("tiles/show_name_on_square310x310")) {
- name_on_tiles += " <uap:ShowOn Tile=\"square310x310Logo\" />\n";
- }
-
- String show_name_on_tiles = "";
- if (!name_on_tiles.is_empty()) {
- show_name_on_tiles = "<uap:ShowNameOnTiles>\n" + name_on_tiles + " </uap:ShowNameOnTiles>";
- }
-
- result = result.replace("$name_on_tiles$", name_on_tiles);
-
- String rotations = "";
- if ((bool)p_preset->get("orientation/landscape")) {
- rotations += " <uap:Rotation Preference=\"landscape\" />\n";
- }
- if ((bool)p_preset->get("orientation/portrait")) {
- rotations += " <uap:Rotation Preference=\"portrait\" />\n";
- }
- if ((bool)p_preset->get("orientation/landscape_flipped")) {
- rotations += " <uap:Rotation Preference=\"landscapeFlipped\" />\n";
- }
- if ((bool)p_preset->get("orientation/portrait_flipped")) {
- rotations += " <uap:Rotation Preference=\"portraitFlipped\" />\n";
- }
-
- String rotation_preference = "";
- if (!rotations.is_empty()) {
- rotation_preference = "<uap:InitialRotationPreference>\n" + rotations + " </uap:InitialRotationPreference>";
- }
-
- result = result.replace("$rotation_preference$", rotation_preference);
-
- String capabilities_elements = "";
- const char **basic = uwp_capabilities;
- while (*basic) {
- if ((bool)p_preset->get("capabilities/" + String(*basic))) {
- capabilities_elements += " <Capability Name=\"" + String(*basic) + "\" />\n";
- }
- basic++;
- }
- const char **uap = uwp_uap_capabilities;
- while (*uap) {
- if ((bool)p_preset->get("capabilities/" + String(*uap))) {
- capabilities_elements += " <uap:Capability Name=\"" + String(*uap) + "\" />\n";
- }
- uap++;
- }
- const char **device = uwp_device_capabilities;
- while (*device) {
- if ((bool)p_preset->get("capabilities/" + String(*device))) {
- capabilities_elements += " <DeviceCapability Name=\"" + String(*device) + "\" />\n";
- }
- device++;
- }
-
- if (!((bool)p_preset->get("capabilities/internetClient")) && p_give_internet) {
- capabilities_elements += " <Capability Name=\"internetClient\" />\n";
- }
-
- String capabilities_string = "<Capabilities />";
- if (!capabilities_elements.is_empty()) {
- capabilities_string = "<Capabilities>\n" + capabilities_elements + " </Capabilities>";
- }
-
- result = result.replace("$capabilities_place$", capabilities_string);
-
- Vector<uint8_t> r_ret;
- r_ret.resize(result.length());
-
- for (int i = 0; i < result.length(); i++) {
- r_ret.write[i] = result.utf8().get(i);
- }
-
- return r_ret;
- }
-
- Vector<uint8_t> _get_image_data(const Ref<EditorExportPreset> &p_preset, const String &p_path) {
- Vector<uint8_t> data;
- CompressedTexture2D *texture = nullptr;
-
- if (p_path.find("StoreLogo") != -1) {
- texture = p_preset->get("images/store_logo").is_zero() ? nullptr : Object::cast_to<CompressedTexture2D>(((Object *)p_preset->get("images/store_logo")));
- } else if (p_path.find("Square44x44Logo") != -1) {
- texture = p_preset->get("images/square44x44_logo").is_zero() ? nullptr : Object::cast_to<CompressedTexture2D>(((Object *)p_preset->get("images/square44x44_logo")));
- } else if (p_path.find("Square71x71Logo") != -1) {
- texture = p_preset->get("images/square71x71_logo").is_zero() ? nullptr : Object::cast_to<CompressedTexture2D>(((Object *)p_preset->get("images/square71x71_logo")));
- } else if (p_path.find("Square150x150Logo") != -1) {
- texture = p_preset->get("images/square150x150_logo").is_zero() ? nullptr : Object::cast_to<CompressedTexture2D>(((Object *)p_preset->get("images/square150x150_logo")));
- } else if (p_path.find("Square310x310Logo") != -1) {
- texture = p_preset->get("images/square310x310_logo").is_zero() ? nullptr : Object::cast_to<CompressedTexture2D>(((Object *)p_preset->get("images/square310x310_logo")));
- } else if (p_path.find("Wide310x150Logo") != -1) {
- texture = p_preset->get("images/wide310x150_logo").is_zero() ? nullptr : Object::cast_to<CompressedTexture2D>(((Object *)p_preset->get("images/wide310x150_logo")));
- } else if (p_path.find("SplashScreen") != -1) {
- texture = p_preset->get("images/splash_screen").is_zero() ? nullptr : Object::cast_to<CompressedTexture2D>(((Object *)p_preset->get("images/splash_screen")));
- } else {
- ERR_PRINT("Unable to load logo");
- }
-
- if (!texture) {
- return data;
- }
-
- String tmp_path = EditorPaths::get_singleton()->get_cache_dir().path_join("uwp_tmp_logo.png");
-
- Error err = texture->get_image()->save_png(tmp_path);
-
- if (err != OK) {
- String err_string = "Couldn't save temp logo file.";
-
- EditorNode::add_io_error(err_string);
- ERR_FAIL_V_MSG(data, err_string);
- }
-
- {
- Ref<FileAccess> f = FileAccess::open(tmp_path, FileAccess::READ, &err);
-
- if (err != OK) {
- String err_string = "Couldn't open temp logo file.";
- // Cleanup generated file.
- DirAccess::remove_file_or_error(tmp_path);
- EditorNode::add_io_error(err_string);
- ERR_FAIL_V_MSG(data, err_string);
- }
-
- data.resize(f->get_length());
- f->get_buffer(data.ptrw(), data.size());
- }
-
- DirAccess::remove_file_or_error(tmp_path);
-
- return data;
- }
-
- static bool _should_compress_asset(const String &p_path, const Vector<uint8_t> &p_data) {
- /* TODO: This was copied verbatim from Android export. It should be
- * refactored to the parent class and also be used for .zip export.
- */
-
- /*
- * By not compressing files with little or not benefit in doing so,
- * a performance gain is expected at runtime. Moreover, if the APK is
- * zip-aligned, assets stored as they are can be efficiently read by
- * Android by memory-mapping them.
- */
-
- // -- Unconditional uncompress to mimic AAPT plus some other
-
- static const char *unconditional_compress_ext[] = {
- // From https://github.com/android/platform_frameworks_base/blob/master/tools/aapt/Package.cpp
- // These formats are already compressed, or don't compress well:
- ".jpg", ".jpeg", ".png", ".gif",
- ".wav", ".mp2", ".mp3", ".ogg", ".aac",
- ".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet",
- ".rtttl", ".imy", ".xmf", ".mp4", ".m4a",
- ".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2",
- ".amr", ".awb", ".wma", ".wmv",
- // Godot-specific:
- ".webp", // Same reasoning as .png
- ".cfb", // Don't let small config files slow-down startup
- ".scn", // Binary scenes are usually already compressed
- ".ctex", // Streamable textures are usually already compressed
- // Trailer for easier processing
- nullptr
- };
-
- for (const char **ext = unconditional_compress_ext; *ext; ++ext) {
- if (p_path.to_lower().ends_with(String(*ext))) {
- return false;
- }
- }
-
- // -- Compressed resource?
-
- if (p_data.size() >= 4 && p_data[0] == 'R' && p_data[1] == 'S' && p_data[2] == 'C' && p_data[3] == 'C') {
- // Already compressed
- return false;
- }
-
- // --- TODO: Decide on texture resources according to their image compression setting
-
- return true;
- }
-
- static Error save_appx_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) {
- AppxPackager *packager = static_cast<AppxPackager *>(p_userdata);
- String dst_path = p_path.replace_first("res://", "game/");
-
- return packager->add_file(dst_path, p_data.ptr(), p_data.size(), p_file, p_total, _should_compress_asset(p_path, p_data));
- }
-
-public:
- virtual String get_name() const override;
- virtual String get_os_name() const override;
-
- virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override;
-
- virtual Ref<Texture2D> get_logo() const override;
-
- virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const override;
-
- virtual void get_export_options(List<ExportOption> *r_options) 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 bool has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const override;
-
- virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override;
-
- virtual void get_platform_features(List<String> *r_features) const override;
-
- virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) override;
-
- EditorExportPlatformUWP();
-};
-
-#endif // UWP_EXPORT_PLUGIN_H
diff --git a/platform/uwp/export/logo.svg b/platform/uwp/export/logo.svg
deleted file mode 100644
index 5bcbdcfcd4..0000000000
--- a/platform/uwp/export/logo.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg height="32" width="32" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><g transform="translate(8.981 1.816)"><circle style="fill:#2f75bb;fill-opacity:1;stroke:none;stroke-width:.815427" cx="7.019" cy="14.184" r="13.825"/><path d="m-1.192 8.234 6.73-.927v6.503h-6.73Zm0 11.899 6.73.927v-6.422h-6.73Zm7.47 1.026 8.952 1.236v-7.757H6.278Zm0-13.951v6.602h8.952V5.973Z" fill="#00abed" style="fill:#fff;fill-opacity:1"/></g></svg>
diff --git a/platform/uwp/joypad_uwp.cpp b/platform/uwp/joypad_uwp.cpp
deleted file mode 100644
index e6a923c0c5..0000000000
--- a/platform/uwp/joypad_uwp.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-/**************************************************************************/
-/* joypad_uwp.cpp */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#include "joypad_uwp.h"
-
-#include "core/os/os.h"
-
-using namespace Windows::Gaming::Input;
-using namespace Windows::Foundation;
-
-void JoypadUWP::register_events() {
- Gamepad::GamepadAdded +=
- ref new EventHandler<Gamepad ^>(this, &JoypadUWP::OnGamepadAdded);
- Gamepad::GamepadRemoved +=
- ref new EventHandler<Gamepad ^>(this, &JoypadUWP::OnGamepadRemoved);
-}
-
-void JoypadUWP::process_controllers() {
- for (int i = 0; i < MAX_CONTROLLERS; i++) {
- ControllerDevice &joy = controllers[i];
-
- if (!joy.connected) {
- break;
- }
-
- switch (joy.type) {
- case ControllerType::GAMEPAD_CONTROLLER: {
- GamepadReading reading = ((Gamepad ^) joy.controller_reference)->GetCurrentReading();
-
- int button_mask = (int)GamepadButtons::Menu;
- for (int j = 0; j < 14; j++) {
- input->joy_button(joy.id, j, (int)reading.Buttons & button_mask);
- button_mask *= 2;
- }
-
- input->joy_axis(joy.id, JoyAxis::LEFT_X, axis_correct(reading.LeftThumbstickX));
- input->joy_axis(joy.id, JoyAxis::LEFT_Y, axis_correct(reading.LeftThumbstickY, true));
- input->joy_axis(joy.id, JoyAxis::RIGHT_X, axis_correct(reading.RightThumbstickX));
- input->joy_axis(joy.id, JoyAxis::RIGHT_Y, axis_correct(reading.RightThumbstickY, true));
- input->joy_axis(joy.id, JoyAxis::TRIGGER_LEFT, axis_correct(reading.LeftTrigger, false, true));
- input->joy_axis(joy.id, JoyAxis::TRIGGER_RIGHT, axis_correct(reading.RightTrigger, false, true));
-
- uint64_t timestamp = input->get_joy_vibration_timestamp(joy.id);
- if (timestamp > joy.ff_timestamp) {
- Vector2 strength = input->get_joy_vibration_strength(joy.id);
- float duration = input->get_joy_vibration_duration(joy.id);
- if (strength.x == 0 && strength.y == 0) {
- joypad_vibration_stop(i, timestamp);
- } else {
- joypad_vibration_start(i, strength.x, strength.y, duration, timestamp);
- }
- } else if (joy.vibrating && joy.ff_end_timestamp != 0) {
- uint64_t current_time = OS::get_singleton()->get_ticks_usec();
- if (current_time >= joy.ff_end_timestamp) {
- joypad_vibration_stop(i, current_time);
- }
- }
-
- break;
- }
- }
- }
-}
-
-JoypadUWP::JoypadUWP() {
- for (int i = 0; i < MAX_CONTROLLERS; i++) {
- controllers[i].id = i;
- }
-}
-
-JoypadUWP::JoypadUWP(InputDefault *p_input) {
- input = p_input;
-
- JoypadUWP();
-}
-
-void JoypadUWP::OnGamepadAdded(Platform::Object ^ sender, Windows::Gaming::Input::Gamepad ^ value) {
- short idx = -1;
-
- for (int i = 0; i < MAX_CONTROLLERS; i++) {
- if (!controllers[i].connected) {
- idx = i;
- break;
- }
- }
-
- ERR_FAIL_COND(idx == -1);
-
- controllers[idx].connected = true;
- controllers[idx].controller_reference = value;
- controllers[idx].id = idx;
- controllers[idx].type = ControllerType::GAMEPAD_CONTROLLER;
-
- input->joy_connection_changed(controllers[idx].id, true, "Xbox Controller", "__UWP_GAMEPAD__");
-}
-
-void JoypadUWP::OnGamepadRemoved(Platform::Object ^ sender, Windows::Gaming::Input::Gamepad ^ value) {
- short idx = -1;
-
- for (int i = 0; i < MAX_CONTROLLERS; i++) {
- if (controllers[i].controller_reference == value) {
- idx = i;
- break;
- }
- }
-
- ERR_FAIL_COND(idx == -1);
-
- controllers[idx] = ControllerDevice();
-
- input->joy_connection_changed(idx, false, "Xbox Controller");
-}
-
-float JoypadUWP::axis_correct(double p_val, bool p_negate, bool p_trigger) const {
- if (p_trigger) {
- // Convert to a value between -1.0f and 1.0f.
- return 2.0f * p_val - 1.0f;
- }
- return (float)(p_negate ? -p_val : p_val);
-}
-
-void JoypadUWP::joypad_vibration_start(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp) {
- ControllerDevice &joy = controllers[p_device];
- if (joy.connected) {
- GamepadVibration vibration;
- vibration.LeftMotor = p_strong_magnitude;
- vibration.RightMotor = p_weak_magnitude;
- ((Gamepad ^) joy.controller_reference)->Vibration = vibration;
-
- joy.ff_timestamp = p_timestamp;
- joy.ff_end_timestamp = p_duration == 0 ? 0 : p_timestamp + (uint64_t)(p_duration * 1000000.0);
- joy.vibrating = true;
- }
-}
-
-void JoypadUWP::joypad_vibration_stop(int p_device, uint64_t p_timestamp) {
- ControllerDevice &joy = controllers[p_device];
- if (joy.connected) {
- GamepadVibration vibration;
- vibration.LeftMotor = 0.0;
- vibration.RightMotor = 0.0;
- ((Gamepad ^) joy.controller_reference)->Vibration = vibration;
-
- joy.ff_timestamp = p_timestamp;
- joy.vibrating = false;
- }
-}
diff --git a/platform/uwp/joypad_uwp.h b/platform/uwp/joypad_uwp.h
deleted file mode 100644
index e9be647dd4..0000000000
--- a/platform/uwp/joypad_uwp.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/**************************************************************************/
-/* joypad_uwp.h */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#ifndef JOYPAD_UWP_H
-#define JOYPAD_UWP_H
-
-#include "core/input/input.h"
-
-ref class JoypadUWP sealed {
- /** clang-format breaks this, it does not understand this token. */
- /* clang-format off */
-internal:
- void register_events();
- void process_controllers();
- /* clang-format on */
-
- JoypadUWP();
- JoypadUWP(InputDefault *p_input);
-
-private:
- enum {
- MAX_CONTROLLERS = 4,
- };
-
- enum ControllerType {
- GAMEPAD_CONTROLLER,
- ARCADE_STICK_CONTROLLER,
- RACING_WHEEL_CONTROLLER,
- };
-
- struct ControllerDevice {
- Windows::Gaming::Input::IGameController ^ controller_reference;
-
- int id = -1;
- bool connected = false;
- ControllerType type = ControllerType::GAMEPAD_CONTROLLER;
- float ff_timestamp = 0;
- float ff_end_timestamp = 0;
- bool vibrating = false;
- };
-
- ControllerDevice controllers[MAX_CONTROLLERS];
-
- InputDefault *input = nullptr;
-
- void OnGamepadAdded(Platform::Object ^ sender, Windows::Gaming::Input::Gamepad ^ value);
- void OnGamepadRemoved(Platform::Object ^ sender, Windows::Gaming::Input::Gamepad ^ value);
-
- float axis_correct(double p_val, bool p_negate = false, bool p_trigger = false) const;
- void joypad_vibration_start(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp);
- void joypad_vibration_stop(int p_device, uint64_t p_timestamp);
-};
-
-#endif // JOYPAD_UWP_H
diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp
deleted file mode 100644
index b9cd9d0baa..0000000000
--- a/platform/uwp/os_uwp.cpp
+++ /dev/null
@@ -1,845 +0,0 @@
-/**************************************************************************/
-/* os_uwp.cpp */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#include "os_uwp.h"
-
-#include "core/config/project_settings.h"
-#include "core/io/marshalls.h"
-#include "drivers/unix/ip_unix.h"
-#include "drivers/unix/net_socket_posix.h"
-#include "drivers/windows/dir_access_windows.h"
-#include "drivers/windows/file_access_windows.h"
-#include "drivers/windows/mutex_windows.h"
-#include "drivers/windows/semaphore_windows.h"
-#include "main/main.h"
-#include "platform/windows/windows_terminal_logger.h"
-#include "servers/audio_server.h"
-#include "servers/rendering/rendering_server_default.h"
-
-#include <ppltasks.h>
-#include <wrl.h>
-
-using namespace Windows::ApplicationModel::Core;
-using namespace Windows::ApplicationModel::Activation;
-using namespace Windows::UI::Core;
-using namespace Windows::UI::Input;
-using namespace Windows::UI::Popups;
-using namespace Windows::Foundation;
-using namespace Windows::Graphics::Display;
-using namespace Microsoft::WRL;
-using namespace Windows::UI::ViewManagement;
-using namespace Windows::Devices::Input;
-using namespace Windows::Devices::Sensors;
-using namespace Windows::ApplicationModel::DataTransfer;
-using namespace concurrency;
-
-static const float earth_gravity = 9.80665;
-
-int OS_UWP::get_video_driver_count() const {
- return 2;
-}
-
-Size2 OS_UWP::get_window_size() const {
- Size2 size;
- size.width = video_mode.width;
- size.height = video_mode.height;
- return size;
-}
-
-int OS_UWP::get_current_video_driver() const {
- return video_driver_index;
-}
-
-void OS_UWP::set_window_size(const Size2 p_size) {
- Windows::Foundation::Size new_size;
- new_size.Width = p_size.width;
- new_size.Height = p_size.height;
-
- ApplicationView ^ view = ApplicationView::GetForCurrentView();
-
- if (view->TryResizeView(new_size)) {
- video_mode.width = p_size.width;
- video_mode.height = p_size.height;
- }
-}
-
-void OS_UWP::set_window_fullscreen(bool p_enabled) {
- ApplicationView ^ view = ApplicationView::GetForCurrentView();
-
- video_mode.fullscreen = view->IsFullScreenMode;
-
- if (video_mode.fullscreen == p_enabled) {
- return;
- }
-
- if (p_enabled) {
- video_mode.fullscreen = view->TryEnterFullScreenMode();
- } else {
- view->ExitFullScreenMode();
- video_mode.fullscreen = false;
- }
-}
-
-bool OS_UWP::is_window_fullscreen() const {
- return ApplicationView::GetForCurrentView()->IsFullScreenMode;
-}
-
-void OS_UWP::set_keep_screen_on(bool p_enabled) {
- if (is_keep_screen_on() == p_enabled) {
- return;
- }
-
- if (p_enabled) {
- display_request->RequestActive();
- } else {
- display_request->RequestRelease();
- }
-
- OS::set_keep_screen_on(p_enabled);
-}
-
-void OS_UWP::initialize_core() {
- //RedirectIOToConsole();
-
- FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_RESOURCES);
- FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_USERDATA);
- FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_FILESYSTEM);
- DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_RESOURCES);
- DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_USERDATA);
- DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_FILESYSTEM);
-
- NetSocketPosix::make_default();
-
- // We need to know how often the clock is updated
- QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second);
- QueryPerformanceCounter((LARGE_INTEGER *)&ticks_start);
-
- IPUnix::make_default();
-
- cursor_shape = CURSOR_ARROW;
-}
-
-void OS_UWP::set_window(Windows::UI::Core::CoreWindow ^ p_window) {
- window = p_window;
-}
-
-void OS_UWP::screen_size_changed() {
- gl_context->reset();
-}
-
-Error OS_UWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) {
- main_loop = nullptr;
- outside = true;
-
- // FIXME: Hardcoded for now, add Vulkan support.
- p_video_driver = RENDERING_DRIVER_OPENGL3;
- ContextEGL_UWP::Driver opengl_api_type = ContextEGL_UWP::GLES_2_0;
-
- bool gl_initialization_error = false;
-
- gl_context = memnew(ContextEGL_UWP(window, opengl_api_type));
-
- if (gl_context->initialize() != OK) {
- memdelete(gl_context);
- gl_context = nullptr;
- gl_initialization_error = true;
- }
-
- if (opengl_api_type == ContextEGL_UWP::GLES_2_0) {
- if (RasterizerGLES3::is_viable() == OK) {
- RasterizerGLES3::register_config();
- RasterizerGLES3::make_current();
- } else {
- gl_initialization_error = true;
- }
- }
-
- if (gl_initialization_error) {
- OS::get_singleton()->alert("Your video card driver does not support any of the supported OpenGL versions.\n"
- "Please update your drivers or if you have a very old or integrated GPU upgrade it.",
- "Unable to initialize video driver");
- return ERR_UNAVAILABLE;
- }
-
- video_driver_index = p_video_driver;
- gl_context->make_current();
- gl_context->set_use_vsync(video_mode.use_vsync);
-
- VideoMode vm;
- vm.width = gl_context->get_window_width();
- vm.height = gl_context->get_window_height();
- vm.resizable = false;
-
- ApplicationView ^ view = ApplicationView::GetForCurrentView();
- vm.fullscreen = view->IsFullScreenMode;
-
- view->SetDesiredBoundsMode(ApplicationViewBoundsMode::UseVisible);
- view->PreferredLaunchWindowingMode = ApplicationViewWindowingMode::PreferredLaunchViewSize;
-
- if (p_desired.fullscreen != view->IsFullScreenMode) {
- if (p_desired.fullscreen) {
- vm.fullscreen = view->TryEnterFullScreenMode();
-
- } else {
- view->ExitFullScreenMode();
- vm.fullscreen = false;
- }
- }
-
- Windows::Foundation::Size desired;
- desired.Width = p_desired.width;
- desired.Height = p_desired.height;
-
- view->PreferredLaunchViewSize = desired;
-
- if (view->TryResizeView(desired)) {
- vm.width = view->VisibleBounds.Width;
- vm.height = view->VisibleBounds.Height;
- }
-
- set_video_mode(vm);
-
- rendering_server = memnew(RenderingServerDefault);
- // FIXME: Reimplement threaded rendering
- if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) {
- rendering_server = memnew(RenderingServerWrapMT(rendering_server, false));
- }
-
- rendering_server->init();
-
- input = memnew(InputDefault);
-
- joypad = ref new JoypadUWP(input);
- joypad->register_events();
-
- AudioDriverManager::initialize(p_audio_driver);
-
- managed_object->update_clipboard();
-
- Clipboard::ContentChanged += ref new EventHandler<Platform::Object ^>(managed_object, &ManagedType::on_clipboard_changed);
-
- accelerometer = Accelerometer::GetDefault();
- if (accelerometer != nullptr) {
- // 60 FPS
- accelerometer->ReportInterval = (1.0f / 60.0f) * 1000;
- accelerometer->ReadingChanged +=
- ref new TypedEventHandler<Accelerometer ^, AccelerometerReadingChangedEventArgs ^>(managed_object, &ManagedType::on_accelerometer_reading_changed);
- }
-
- magnetometer = Magnetometer::GetDefault();
- if (magnetometer != nullptr) {
- // 60 FPS
- magnetometer->ReportInterval = (1.0f / 60.0f) * 1000;
- magnetometer->ReadingChanged +=
- ref new TypedEventHandler<Magnetometer ^, MagnetometerReadingChangedEventArgs ^>(managed_object, &ManagedType::on_magnetometer_reading_changed);
- }
-
- gyrometer = Gyrometer::GetDefault();
- if (gyrometer != nullptr) {
- // 60 FPS
- gyrometer->ReportInterval = (1.0f / 60.0f) * 1000;
- gyrometer->ReadingChanged +=
- ref new TypedEventHandler<Gyrometer ^, GyrometerReadingChangedEventArgs ^>(managed_object, &ManagedType::on_gyroscope_reading_changed);
- }
-
- _ensure_user_data_dir();
-
- if (is_keep_screen_on()) {
- display_request->RequestActive();
- }
-
- set_keep_screen_on(GLOBAL_GET("display/window/energy_saving/keep_screen_on"));
-
- return OK;
-}
-
-void OS_UWP::set_clipboard(const String &p_text) {
- DataPackage ^ clip = ref new DataPackage();
- clip->RequestedOperation = DataPackageOperation::Copy;
- clip->SetText(ref new Platform::String((LPCWSTR)(p_text.utf16().get_data())));
-
- Clipboard::SetContent(clip);
-}
-
-String OS_UWP::get_clipboard() const {
- if (managed_object->clipboard != nullptr) {
- return managed_object->clipboard->Data();
- } else {
- return "";
- }
-}
-
-void OS_UWP::input_event(const Ref<InputEvent> &p_event) {
- input->parse_input_event(p_event);
-}
-
-void OS_UWP::delete_main_loop() {
- if (main_loop) {
- memdelete(main_loop);
- }
- main_loop = nullptr;
-}
-
-void OS_UWP::set_main_loop(MainLoop *p_main_loop) {
- input->set_main_loop(p_main_loop);
- main_loop = p_main_loop;
-}
-
-void OS_UWP::finalize() {
- if (main_loop) {
- memdelete(main_loop);
- }
-
- main_loop = nullptr;
-
- rendering_server->finish();
- memdelete(rendering_server);
-#ifdef GLES3_ENABLED
- if (gl_context) {
- memdelete(gl_context);
- }
-#endif
-
- memdelete(input);
-
- joypad = nullptr;
-}
-
-void OS_UWP::finalize_core() {
- NetSocketPosix::cleanup();
-}
-
-void OS_UWP::alert(const String &p_alert, const String &p_title) {
- Platform::String ^ alert = ref new Platform::String((LPCWSTR)(p_alert.utf16().get_data()));
- Platform::String ^ title = ref new Platform::String((LPCWSTR)(p_title.utf16().get_data()));
-
- MessageDialog ^ msg = ref new MessageDialog(alert, title);
-
- UICommand ^ close = ref new UICommand("Close", ref new UICommandInvokedHandler(managed_object, &OS_UWP::ManagedType::alert_close));
- msg->Commands->Append(close);
- msg->DefaultCommandIndex = 0;
-
- managed_object->alert_close_handle = true;
-
- msg->ShowAsync();
-}
-
-void OS_UWP::ManagedType::alert_close(IUICommand ^ command) {
- alert_close_handle = false;
-}
-
-void OS_UWP::ManagedType::on_clipboard_changed(Platform::Object ^ sender, Platform::Object ^ ev) {
- update_clipboard();
-}
-
-void OS_UWP::ManagedType::update_clipboard() {
- DataPackageView ^ data = Clipboard::GetContent();
-
- if (data->Contains(StandardDataFormats::Text)) {
- create_task(data->GetTextAsync()).then([this](Platform::String ^ clipboard_content) {
- this->clipboard = clipboard_content;
- });
- }
-}
-
-void OS_UWP::ManagedType::on_accelerometer_reading_changed(Accelerometer ^ sender, AccelerometerReadingChangedEventArgs ^ args) {
- AccelerometerReading ^ reading = args->Reading;
-
- os->input->set_accelerometer(Vector3(
- reading->AccelerationX * earth_gravity,
- reading->AccelerationY * earth_gravity,
- reading->AccelerationZ * earth_gravity));
-}
-
-void OS_UWP::ManagedType::on_magnetometer_reading_changed(Magnetometer ^ sender, MagnetometerReadingChangedEventArgs ^ args) {
- MagnetometerReading ^ reading = args->Reading;
-
- os->input->set_magnetometer(Vector3(
- reading->MagneticFieldX,
- reading->MagneticFieldY,
- reading->MagneticFieldZ));
-}
-
-void OS_UWP::ManagedType::on_gyroscope_reading_changed(Gyrometer ^ sender, GyrometerReadingChangedEventArgs ^ args) {
- GyrometerReading ^ reading = args->Reading;
-
- os->input->set_magnetometer(Vector3(
- reading->AngularVelocityX,
- reading->AngularVelocityY,
- reading->AngularVelocityZ));
-}
-
-void OS_UWP::set_mouse_mode(MouseMode p_mode) {
- if (p_mode == MouseMode::MOUSE_MODE_CAPTURED) {
- CoreWindow::GetForCurrentThread()->SetPointerCapture();
- } else {
- CoreWindow::GetForCurrentThread()->ReleasePointerCapture();
- }
-
- if (p_mode == MouseMode::MOUSE_MODE_HIDDEN || p_mode == MouseMode::MOUSE_MODE_CAPTURED || p_mode == MouseMode::MOUSE_MODE_CONFINED_HIDDEN) {
- CoreWindow::GetForCurrentThread()->PointerCursor = nullptr;
- } else {
- CoreWindow::GetForCurrentThread()->PointerCursor = ref new CoreCursor(CoreCursorType::Arrow, 0);
- }
-
- mouse_mode = p_mode;
-
- SetEvent(mouse_mode_changed);
-}
-
-OS_UWP::MouseMode OS_UWP::get_mouse_mode() const {
- return mouse_mode;
-}
-
-Point2 OS_UWP::get_mouse_position() const {
- return Point2(old_x, old_y);
-}
-
-MouseButton OS_UWP::get_mouse_button_state() const {
- return last_button_state;
-}
-
-void OS_UWP::set_window_title(const String &p_title) {
-}
-
-void OS_UWP::set_video_mode(const VideoMode &p_video_mode, int p_screen) {
- video_mode = p_video_mode;
-}
-
-OS::VideoMode OS_UWP::get_video_mode(int p_screen) const {
- return video_mode;
-}
-
-void OS_UWP::get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen) const {
-}
-
-String OS_UWP::get_name() const {
- return "UWP";
-}
-
-String OS_UWP::get_distribution_name() const {
- return get_name();
-}
-
-String OS_UWP::get_version() const {
- winrt::hstring df_version = VersionInfo().DeviceFamilyVersion();
- return String(winrt::to_string(df_version).c_str());
-}
-
-OS::DateTime OS_UWP::get_datetime(bool p_utc) const {
- SYSTEMTIME systemtime;
- if (p_utc) {
- GetSystemTime(&systemtime);
- } else {
- GetLocalTime(&systemtime);
- }
-
- //Get DST information from Windows, but only if p_utc is false.
- TIME_ZONE_INFORMATION info;
- bool daylight = false;
- if (!p_utc && GetTimeZoneInformation(&info) == TIME_ZONE_ID_DAYLIGHT) {
- daylight = true;
- }
-
- DateTime dt;
- dt.year = systemtime.wYear;
- dt.month = Month(systemtime.wMonth);
- dt.day = systemtime.wDay;
- dt.weekday = Weekday(systemtime.wDayOfWeek);
- dt.hour = systemtime.wHour;
- dt.minute = systemtime.wMinute;
- dt.second = systemtime.wSecond;
- dt.dst = daylight;
- return dt;
-}
-
-OS::TimeZoneInfo OS_UWP::get_time_zone_info() const {
- TIME_ZONE_INFORMATION info;
- bool daylight = false;
- if (GetTimeZoneInformation(&info) == TIME_ZONE_ID_DAYLIGHT) {
- daylight = true;
- }
-
- TimeZoneInfo ret;
- if (daylight) {
- ret.name = info.DaylightName;
- } else {
- ret.name = info.StandardName;
- }
-
- // Bias value returned by GetTimeZoneInformation is inverted of what we expect
- // For example on GMT-3 GetTimeZoneInformation return a Bias of 180, so invert the value to get -180
- ret.bias = -info.Bias;
- return ret;
-}
-
-uint64_t OS_UWP::get_unix_time() const {
- FILETIME ft;
- SYSTEMTIME st;
- GetSystemTime(&st);
- SystemTimeToFileTime(&st, &ft);
-
- SYSTEMTIME ep;
- ep.wYear = 1970;
- ep.wMonth = 1;
- ep.wDayOfWeek = 4;
- ep.wDay = 1;
- ep.wHour = 0;
- ep.wMinute = 0;
- ep.wSecond = 0;
- ep.wMilliseconds = 0;
- FILETIME fep;
- SystemTimeToFileTime(&ep, &fep);
-
- return (*(uint64_t *)&ft - *(uint64_t *)&fep) / 10000000;
-}
-
-void OS_UWP::delay_usec(uint32_t p_usec) const {
- int msec = p_usec < 1000 ? 1 : p_usec / 1000;
-
- // no Sleep()
- WaitForSingleObjectEx(GetCurrentThread(), msec, false);
-}
-
-uint64_t OS_UWP::get_ticks_usec() const {
- uint64_t ticks;
-
- // This is the number of clock ticks since start
- QueryPerformanceCounter((LARGE_INTEGER *)&ticks);
- // Subtract the ticks at game start to get
- // the ticks since the game started
- ticks -= ticks_start;
-
- // Divide by frequency to get the time in seconds
- // original calculation shown below is subject to overflow
- // with high ticks_per_second and a number of days since the last reboot.
- // time = ticks * 1000000L / ticks_per_second;
-
- // we can prevent this by either using 128 bit math
- // or separating into a calculation for seconds, and the fraction
- uint64_t seconds = ticks / ticks_per_second;
-
- // compiler will optimize these two into one divide
- uint64_t leftover = ticks % ticks_per_second;
-
- // remainder
- uint64_t time = (leftover * 1000000L) / ticks_per_second;
-
- // seconds
- time += seconds * 1000000L;
-
- return time;
-}
-
-void OS_UWP::process_events() {
- joypad->process_controllers();
- process_key_events();
- input->flush_buffered_events();
-}
-
-void OS_UWP::process_key_events() {
- for (int i = 0; i < key_event_pos; i++) {
- KeyEvent &kev = key_event_buffer[i];
-
- Ref<InputEventKey> key_event;
- key_event.instantiate();
- key_event->set_alt_pressed(kev.alt);
- key_event->set_shift_pressed(kev.shift);
- key_event->set_ctrl_pressed(kev.control);
- key_event->set_echo(kev.echo);
- key_event->set_keycode(kev.keycode);
- key_event->set_physical_keycode((Key)kev.physical_keycode);
- key_event->set_unicode(kev.unicode);
- key_event->set_pressed(kev.pressed);
-
- input_event(key_event);
- }
- key_event_pos = 0;
-}
-
-void OS_UWP::queue_key_event(KeyEvent &p_event) {
- // This merges Char events with the previous Key event, so
- // the unicode can be retrieved without sending duplicate events.
- if (p_event.type == KeyEvent::MessageType::CHAR_EVENT_MESSAGE && key_event_pos > 0) {
- KeyEvent &old = key_event_buffer[key_event_pos - 1];
- ERR_FAIL_COND(old.type != KeyEvent::MessageType::KEY_EVENT_MESSAGE);
-
- key_event_buffer[key_event_pos - 1].unicode = p_event.unicode;
- return;
- }
-
- ERR_FAIL_COND(key_event_pos >= KEY_EVENT_BUFFER_SIZE);
-
- key_event_buffer[key_event_pos++] = p_event;
-}
-
-void OS_UWP::set_cursor_shape(CursorShape p_shape) {
- ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
-
- if (cursor_shape == p_shape) {
- return;
- }
-
- static const CoreCursorType uwp_cursors[CURSOR_MAX] = {
- CoreCursorType::Arrow,
- CoreCursorType::IBeam,
- CoreCursorType::Hand,
- CoreCursorType::Cross,
- CoreCursorType::Wait,
- CoreCursorType::Wait,
- CoreCursorType::Arrow,
- CoreCursorType::Arrow,
- CoreCursorType::UniversalNo,
- CoreCursorType::SizeNorthSouth,
- CoreCursorType::SizeWestEast,
- CoreCursorType::SizeNortheastSouthwest,
- CoreCursorType::SizeNorthwestSoutheast,
- CoreCursorType::SizeAll,
- CoreCursorType::SizeNorthSouth,
- CoreCursorType::SizeWestEast,
- CoreCursorType::Help
- };
-
- CoreWindow::GetForCurrentThread()->PointerCursor = ref new CoreCursor(uwp_cursors[p_shape], 0);
-
- cursor_shape = p_shape;
-}
-
-OS::CursorShape OS_UWP::get_cursor_shape() const {
- return cursor_shape;
-}
-
-void OS_UWP::set_custom_mouse_cursor(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
- // TODO
-}
-
-Error OS_UWP::execute(const String &p_path, const List<String> &p_arguments, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex, bool p_open_console) {
- return FAILED;
-}
-
-Error OS_UWP::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id, bool p_open_console) {
- return FAILED;
-}
-
-Error OS_UWP::kill(const ProcessID &p_pid) {
- return FAILED;
-}
-
-bool OS_UWP::is_process_running(const ProcessID &p_pid) const {
- return false;
-}
-
-Error OS_UWP::set_cwd(const String &p_cwd) {
- return FAILED;
-}
-
-String OS_UWP::get_executable_path() const {
- return "";
-}
-
-void OS_UWP::set_icon(const Ref<Image> &p_icon) {
-}
-
-bool OS_UWP::has_environment(const String &p_var) const {
- return false;
-}
-
-String OS_UWP::get_environment(const String &p_var) const {
- return "";
-}
-
-bool OS_UWP::set_environment(const String &p_var, const String &p_value) const {
- return false;
-}
-
-String OS_UWP::get_stdin_string() {
- return String();
-}
-
-void OS_UWP::move_window_to_foreground() {
-}
-
-Error OS_UWP::shell_open(String p_uri) {
- return FAILED;
-}
-
-String OS_UWP::get_locale() const {
-#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP // this should work on phone 8.1, but it doesn't
- return "en";
-#else
- Platform::String ^ language = Windows::Globalization::Language::CurrentInputMethodLanguageTag;
- return String(language->Data()).replace("-", "_");
-#endif
-}
-
-void OS_UWP::release_rendering_thread() {
- gl_context->release_current();
-}
-
-void OS_UWP::make_rendering_thread() {
- gl_context->make_current();
-}
-
-void OS_UWP::swap_buffers() {
- gl_context->swap_buffers();
-}
-
-bool OS_UWP::has_touchscreen_ui_hint() const {
- TouchCapabilities ^ tc = ref new TouchCapabilities();
- return tc->TouchPresent != 0 || UIViewSettings::GetForCurrentView()->UserInteractionMode == UserInteractionMode::Touch;
-}
-
-bool OS_UWP::has_virtual_keyboard() const {
- return UIViewSettings::GetForCurrentView()->UserInteractionMode == UserInteractionMode::Touch;
-}
-
-void OS_UWP::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
- InputPane ^ pane = InputPane::GetForCurrentView();
- pane->TryShow();
-}
-
-void OS_UWP::hide_virtual_keyboard() {
- InputPane ^ pane = InputPane::GetForCurrentView();
- pane->TryHide();
-}
-
-static String format_error_message(DWORD id) {
- LPWSTR messageBuffer = nullptr;
- size_t size = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
- nullptr, id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&messageBuffer, 0, nullptr);
-
- String msg = "Error " + itos(id) + ": " + String(messageBuffer, size);
-
- LocalFree(messageBuffer);
-
- return msg;
-}
-
-Error OS_UWP::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) {
- String full_path = "game/" + p_path;
- p_library_handle = (void *)LoadPackagedLibrary((LPCWSTR)(full_path.utf16().get_data()), 0);
- ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", full_path, format_error_message(GetLastError())));
-
- if (r_resolved_path != nullptr) {
- *r_resolved_path = full_path;
- }
-
- return OK;
-}
-
-Error OS_UWP::close_dynamic_library(void *p_library_handle) {
- if (!FreeLibrary((HMODULE)p_library_handle)) {
- return FAILED;
- }
- return OK;
-}
-
-Error OS_UWP::get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional) {
- p_symbol_handle = (void *)GetProcAddress((HMODULE)p_library_handle, p_name.utf8().get_data());
- if (!p_symbol_handle) {
- if (!p_optional) {
- ERR_FAIL_V_MSG(ERR_CANT_RESOLVE, "Can't resolve symbol " + p_name + ", error: " + String::num(GetLastError()) + ".");
- } else {
- return ERR_CANT_RESOLVE;
- }
- }
- return OK;
-}
-
-void OS_UWP::run() {
- if (!main_loop) {
- return;
- }
-
- main_loop->init();
-
- uint64_t last_ticks = get_ticks_usec();
-
- int frames = 0;
- uint64_t frame = 0;
-
- while (true) {
- CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
- if (managed_object->alert_close_handle) {
- continue;
- }
- process_events(); // get rid of pending events
- if (Main::iteration()) {
- break;
- }
- }
-
- main_loop->finish();
-}
-
-MainLoop *OS_UWP::get_main_loop() const {
- return main_loop;
-}
-
-String OS_UWP::get_user_data_dir() const {
- Windows::Storage::StorageFolder ^ data_folder = Windows::Storage::ApplicationData::Current->LocalFolder;
-
- return String(data_folder->Path->Data()).replace("\\", "/");
-}
-
-bool OS_UWP::_check_internal_feature_support(const String &p_feature) {
- return p_feature == "pc";
-}
-
-OS_UWP::OS_UWP() {
- key_event_pos = 0;
- alt_mem = false;
- gr_mem = false;
- shift_mem = false;
- control_mem = false;
- meta_mem = false;
- minimized = false;
-
- pressrc = 0;
- old_invalid = true;
- mouse_mode = MOUSE_MODE_VISIBLE;
- gl_context = nullptr;
-
- display_request = ref new Windows::System::Display::DisplayRequest();
-
- managed_object = ref new ManagedType;
- managed_object->os = this;
-
- mouse_mode_changed = CreateEvent(nullptr, TRUE, FALSE, L"os_mouse_mode_changed");
-
- AudioDriverManager::add_driver(&audio_driver);
-
- Vector<Logger *> loggers;
- loggers.push_back(memnew(WindowsTerminalLogger));
- _set_logger(memnew(CompositeLogger(loggers)));
-}
-
-OS_UWP::~OS_UWP() {
-}
diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h
deleted file mode 100644
index 7f2195e4fd..0000000000
--- a/platform/uwp/os_uwp.h
+++ /dev/null
@@ -1,256 +0,0 @@
-/**************************************************************************/
-/* os_uwp.h */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#ifndef OS_UWP_H
-#define OS_UWP_H
-
-#include "context_egl_uwp.h"
-#include "joypad_uwp.h"
-
-#include "core/input/input.h"
-#include "core/math/transform_2d.h"
-#include "core/os/os.h"
-#include "core/string/ustring.h"
-#include "drivers/xaudio2/audio_driver_xaudio2.h"
-#include "servers/audio_server.h"
-#include "servers/rendering/renderer_compositor.h"
-#include "servers/rendering_server.h"
-
-#include <io.h>
-#include <stdio.h>
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
-class OS_UWP : public OS {
-public:
- struct KeyEvent {
- enum MessageType {
- KEY_EVENT_MESSAGE,
- CHAR_EVENT_MESSAGE
- };
-
- bool alt = false, shift = false, control = false;
- MessageType type = KEY_EVENT_MESSAGE;
- bool pressed = false;
- Key keycode = Key::NONE;
- unsigned int physical_keycode = 0;
- unsigned int unicode = 0;
- bool echo = false;
- CorePhysicalKeyStatus status;
- };
-
-private:
- enum {
- JOYPADS_MAX = 8,
- JOY_AXIS_COUNT = 6,
- MAX_JOY_AXIS = 32768, // I've no idea
- KEY_EVENT_BUFFER_SIZE = 512
- };
-
- FILE *stdo = nullptr;
-
- KeyEvent key_event_buffer[KEY_EVENT_BUFFER_SIZE];
- int key_event_pos;
-
- uint64_t ticks_start;
- uint64_t ticks_per_second;
-
- bool minimized;
- bool old_invalid;
- bool outside;
- int old_x, old_y;
- Point2i center;
- RenderingServer *rendering_server = nullptr;
- int pressrc;
-
- ContextEGL_UWP *gl_context = nullptr;
- Windows::UI::Core::CoreWindow ^ window;
-
- VideoMode video_mode;
- int video_driver_index;
-
- MainLoop *main_loop = nullptr;
-
- AudioDriverXAudio2 audio_driver;
-
- MouseMode mouse_mode;
- bool alt_mem;
- bool gr_mem;
- bool shift_mem;
- bool control_mem;
- bool meta_mem;
- MouseButton last_button_state = MouseButton::NONE;
-
- CursorShape cursor_shape;
-
- InputDefault *input = nullptr;
-
- JoypadUWP ^ joypad;
-
- Windows::System::Display::DisplayRequest ^ display_request;
-
- ref class ManagedType {
- public:
- property bool alert_close_handle;
- property Platform::String ^ clipboard;
- void alert_close(Windows::UI::Popups::IUICommand ^ command);
- void on_clipboard_changed(Platform::Object ^ sender, Platform::Object ^ ev);
- void update_clipboard();
- void on_accelerometer_reading_changed(Windows::Devices::Sensors::Accelerometer ^ sender, Windows::Devices::Sensors::AccelerometerReadingChangedEventArgs ^ args);
- void on_magnetometer_reading_changed(Windows::Devices::Sensors::Magnetometer ^ sender, Windows::Devices::Sensors::MagnetometerReadingChangedEventArgs ^ args);
- void on_gyroscope_reading_changed(Windows::Devices::Sensors::Gyrometer ^ sender, Windows::Devices::Sensors::GyrometerReadingChangedEventArgs ^ args);
-
- /** clang-format breaks this, it does not understand this token. */
- /* clang-format off */
- internal:
- ManagedType() { alert_close_handle = false; }
- property OS_UWP* os;
- /* clang-format on */
- };
- ManagedType ^ managed_object;
- Windows::Devices::Sensors::Accelerometer ^ accelerometer;
- Windows::Devices::Sensors::Magnetometer ^ magnetometer;
- Windows::Devices::Sensors::Gyrometer ^ gyrometer;
-
- // functions used by main to initialize/deinitialize the OS
-protected:
- virtual int get_video_driver_count() const;
- virtual int get_current_video_driver() const;
-
- virtual void initialize_core();
- virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
-
- virtual void set_main_loop(MainLoop *p_main_loop);
- virtual void delete_main_loop();
-
- virtual void finalize();
- virtual void finalize_core();
-
- void process_events();
-
- void process_key_events();
-
-public:
- // Event to send to the app wrapper
- HANDLE mouse_mode_changed;
-
- virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
- String get_stdin_string();
-
- void set_mouse_mode(MouseMode p_mode);
- MouseMode get_mouse_mode() const;
-
- virtual Point2 get_mouse_position() const;
- virtual MouseButton get_mouse_button_state() const;
- virtual void set_window_title(const String &p_title);
-
- virtual void set_video_mode(const VideoMode &p_video_mode, int p_screen = 0);
- virtual VideoMode get_video_mode(int p_screen = 0) const;
- virtual void get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen = 0) const;
- virtual Size2 get_window_size() const;
- virtual void set_window_size(const Size2 p_size);
- virtual void set_window_fullscreen(bool p_enabled);
- virtual bool is_window_fullscreen() const;
- virtual void set_keep_screen_on(bool p_enabled);
-
- virtual MainLoop *get_main_loop() const;
-
- virtual String get_name() const;
- virtual String get_distribution_name() const;
- virtual String get_version() const;
-
- virtual DateTime get_datetime(bool p_utc) const;
- virtual TimeZoneInfo get_time_zone_info() const;
- virtual uint64_t get_unix_time() const;
-
- virtual Error set_cwd(const String &p_cwd);
-
- virtual void delay_usec(uint32_t p_usec) const;
- virtual uint64_t get_ticks_usec() const;
-
- virtual Error execute(const String &p_path, const List<String> &p_arguments, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr, bool p_open_console = false);
- virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr, bool p_open_console = false);
- virtual Error kill(const ProcessID &p_pid);
- virtual bool is_process_running(const ProcessID &p_pid) const;
-
- virtual bool has_environment(const String &p_var) const;
- virtual String get_environment(const String &p_var) const;
- virtual bool set_environment(const String &p_var, const String &p_value) const;
-
- virtual void set_clipboard(const String &p_text);
- virtual String get_clipboard() const;
-
- void set_cursor_shape(CursorShape p_shape);
- CursorShape get_cursor_shape() const;
- virtual void set_custom_mouse_cursor(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
- void set_icon(const Ref<Image> &p_icon);
-
- virtual String get_executable_path() const;
-
- virtual String get_locale() const;
-
- virtual void move_window_to_foreground();
- virtual String get_user_data_dir() const;
-
- virtual bool _check_internal_feature_support(const String &p_feature);
-
- void set_window(Windows::UI::Core::CoreWindow ^ p_window);
- void screen_size_changed();
-
- virtual void release_rendering_thread();
- virtual void make_rendering_thread();
- virtual void swap_buffers();
-
- virtual bool has_touchscreen_ui_hint() const;
-
- virtual bool has_virtual_keyboard() const;
- virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), VirtualKeyboardType p_type = KEYBOARD_TYPE_DEFAULT, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1);
- virtual void hide_virtual_keyboard();
-
- virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr);
- virtual Error close_dynamic_library(void *p_library_handle);
- virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false);
-
- virtual Error shell_open(String p_uri);
-
- void run();
-
- virtual bool get_swap_cancel_ok() { return true; }
-
- void input_event(const Ref<InputEvent> &p_event);
-
- void queue_key_event(KeyEvent &p_event);
-
- OS_UWP();
- ~OS_UWP();
-};
-
-#endif // OS_UWP_H
diff --git a/platform/web/api/api.cpp b/platform/web/api/api.cpp
index ab7154b0fb..a695091a04 100644
--- a/platform/web/api/api.cpp
+++ b/platform/web/api/api.cpp
@@ -96,7 +96,7 @@ Ref<JavaScriptObject> JavaScriptBridge::create_callback(const Callable &p_callab
Variant JavaScriptBridge::_create_object_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
if (p_argcount < 1) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = 0;
+ r_error.expected = 1;
return Ref<JavaScriptObject>();
}
if (p_args[0]->get_type() != Variant::STRING) {
diff --git a/platform/web/audio_driver_web.cpp b/platform/web/audio_driver_web.cpp
index c6c67db3de..1298d28ebf 100644
--- a/platform/web/audio_driver_web.cpp
+++ b/platform/web/audio_driver_web.cpp
@@ -101,7 +101,7 @@ void AudioDriverWeb::_audio_driver_capture(int p_from, int p_samples) {
}
Error AudioDriverWeb::init() {
- int latency = GLOBAL_GET("audio/driver/output_latency");
+ int latency = Engine::get_singleton()->get_audio_output_latency();
if (!audio_context.inited) {
audio_context.mix_rate = _get_configured_mix_rate();
audio_context.channel_count = godot_audio_init(&audio_context.mix_rate, latency, &_state_change_callback, &_latency_update_callback);
diff --git a/platform/web/audio_driver_web.h b/platform/web/audio_driver_web.h
index 7bfed834e1..12a61746c3 100644
--- a/platform/web/audio_driver_web.h
+++ b/platform/web/audio_driver_web.h
@@ -32,6 +32,7 @@
#define AUDIO_DRIVER_WEB_H
#include "godot_audio.h"
+#include "godot_js.h"
#include "core/os/mutex.h"
#include "core/os/thread.h"
@@ -55,8 +56,8 @@ private:
int mix_rate = 0;
int channel_count = 0;
- static void _state_change_callback(int p_state);
- static void _latency_update_callback(float p_latency);
+ WASM_EXPORT static void _state_change_callback(int p_state);
+ WASM_EXPORT static void _latency_update_callback(float p_latency);
static AudioDriverWeb *singleton;
diff --git a/platform/web/detect.py b/platform/web/detect.py
index 4015c8ff16..043ddca65d 100644
--- a/platform/web/detect.py
+++ b/platform/web/detect.py
@@ -60,6 +60,8 @@ def get_flags():
("target", "template_debug"),
("builtin_pcre2_with_jit", False),
("vulkan", False),
+ # Embree is heavy and requires too much memory (GH-70621).
+ ("module_raycast_enabled", False),
# Use -Os to prioritize optimizing for reduced file size. This is
# particularly valuable for the web platform because it directly
# decreases download time.
@@ -199,9 +201,16 @@ def configure(env: "Environment"):
env.Append(LINKFLAGS=["-s", "PTHREAD_POOL_SIZE=8"])
env.Append(LINKFLAGS=["-s", "WASM_MEM_MAX=2048MB"])
+ # Get version info for checks below.
+ cc_version = get_compiler_version(env)
+ cc_semver = (cc_version["major"], cc_version["minor"], cc_version["patch"])
+
+ if env["lto"] != "none":
+ # Workaround https://github.com/emscripten-core/emscripten/issues/19781.
+ if cc_semver >= (3, 1, 42) and cc_semver < (3, 1, 46):
+ env.Append(LINKFLAGS=["-Wl,-u,scalbnf"])
+
if env["dlink_enabled"]:
- cc_version = get_compiler_version(env)
- cc_semver = (int(cc_version["major"]), int(cc_version["minor"]), int(cc_version["patch"]))
if cc_semver < (3, 1, 14):
print("GDExtension support requires emscripten >= 3.1.14, detected: %s.%s.%s" % cc_semver)
sys.exit(255)
diff --git a/platform/web/display_server_web.cpp b/platform/web/display_server_web.cpp
index 93b0496d74..aac1401f23 100644
--- a/platform/web/display_server_web.cpp
+++ b/platform/web/display_server_web.cpp
@@ -817,7 +817,7 @@ DisplayServerWeb::DisplayServerWeb(const String &p_rendering_driver, WindowMode
if (!emscripten_webgl_enable_extension(webgl_ctx, "OVR_multiview2")) {
print_verbose("Failed to enable WebXR extension.");
}
- RasterizerGLES3::make_current();
+ RasterizerGLES3::make_current(false);
} else {
OS::get_singleton()->alert(
diff --git a/platform/web/display_server_web.h b/platform/web/display_server_web.h
index a4fd75f33b..1653deff80 100644
--- a/platform/web/display_server_web.h
+++ b/platform/web/display_server_web.h
@@ -33,6 +33,8 @@
#include "servers/display_server.h"
+#include "godot_js.h"
+
#include <emscripten.h>
#include <emscripten/html5.h>
@@ -88,28 +90,28 @@ private:
static const char *godot2dom_cursor(DisplayServer::CursorShape p_shape);
// events
- static void fullscreen_change_callback(int p_fullscreen);
- static int mouse_button_callback(int p_pressed, int p_button, double p_x, double p_y, int p_modifiers);
- static void mouse_move_callback(double p_x, double p_y, double p_rel_x, double p_rel_y, int p_modifiers);
- static int mouse_wheel_callback(double p_delta_x, double p_delta_y);
- static void touch_callback(int p_type, int p_count);
- static void key_callback(int p_pressed, int p_repeat, int p_modifiers);
- static void vk_input_text_callback(const char *p_text, int p_cursor);
- static void gamepad_callback(int p_index, int p_connected, const char *p_id, const char *p_guid);
+ WASM_EXPORT static void fullscreen_change_callback(int p_fullscreen);
+ WASM_EXPORT static int mouse_button_callback(int p_pressed, int p_button, double p_x, double p_y, int p_modifiers);
+ WASM_EXPORT static void mouse_move_callback(double p_x, double p_y, double p_rel_x, double p_rel_y, int p_modifiers);
+ WASM_EXPORT static int mouse_wheel_callback(double p_delta_x, double p_delta_y);
+ WASM_EXPORT static void touch_callback(int p_type, int p_count);
+ WASM_EXPORT static void key_callback(int p_pressed, int p_repeat, int p_modifiers);
+ WASM_EXPORT static void vk_input_text_callback(const char *p_text, int p_cursor);
+ WASM_EXPORT static void gamepad_callback(int p_index, int p_connected, const char *p_id, const char *p_guid);
void process_joypads();
- static void _js_utterance_callback(int p_event, int p_id, int p_pos);
+ WASM_EXPORT static void _js_utterance_callback(int p_event, int p_id, int p_pos);
static Vector<String> get_rendering_drivers_func();
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_window_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error);
static void _dispatch_input_event(const Ref<InputEvent> &p_event);
- static void request_quit_callback();
- static void window_blur_callback();
- static void update_voices_callback(int p_size, const char **p_voice);
- static void update_clipboard_callback(const char *p_text);
- static void send_window_event_callback(int p_notification);
- static void drop_files_js_callback(char **p_filev, int p_filec);
+ WASM_EXPORT static void request_quit_callback();
+ WASM_EXPORT static void window_blur_callback();
+ WASM_EXPORT static void update_voices_callback(int p_size, const char **p_voice);
+ WASM_EXPORT static void update_clipboard_callback(const char *p_text);
+ WASM_EXPORT static void send_window_event_callback(int p_notification);
+ WASM_EXPORT static void drop_files_js_callback(char **p_filev, int p_filec);
protected:
int get_current_video_driver() const;
diff --git a/platform/web/doc_classes/EditorExportPlatformWeb.xml b/platform/web/doc_classes/EditorExportPlatformWeb.xml
index 607fdd0533..c4c4fd870b 100644
--- a/platform/web/doc_classes/EditorExportPlatformWeb.xml
+++ b/platform/web/doc_classes/EditorExportPlatformWeb.xml
@@ -7,6 +7,7 @@
</description>
<tutorials>
<link title="Exporting for the Web">$DOCS_URL/tutorials/export/exporting_for_web.html</link>
+ <link title="Web documentation index">$DOCS_URL/tutorials/platform/web/index.html</link>
</tutorials>
<members>
<member name="custom_template/debug" type="String" setter="" getter="">
diff --git a/platform/web/export/export_plugin.cpp b/platform/web/export/export_plugin.cpp
index 993abd2cee..a62ccdc2aa 100644
--- a/platform/web/export/export_plugin.cpp
+++ b/platform/web/export/export_plugin.cpp
@@ -36,6 +36,7 @@
#include "core/config/project_settings.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/editor_string_names.h"
#include "editor/export/editor_export.h"
#include "editor/import/resource_importer_texture_settings.h"
#include "scene/resources/image_texture.h"
@@ -683,7 +684,7 @@ EditorExportPlatformWeb::EditorExportPlatformWeb() {
Ref<Theme> theme = EditorNode::get_singleton()->get_editor_theme();
if (theme.is_valid()) {
- stop_icon = theme->get_icon(SNAME("Stop"), SNAME("EditorIcons"));
+ stop_icon = theme->get_icon(SNAME("Stop"), EditorStringName(EditorIcons));
} else {
stop_icon.instantiate();
}
diff --git a/platform/web/export/export_plugin.h b/platform/web/export/export_plugin.h
index 2de4a4c153..887000ac45 100644
--- a/platform/web/export/export_plugin.h
+++ b/platform/web/export/export_plugin.h
@@ -39,6 +39,7 @@
#include "core/io/tcp_server.h"
#include "core/io/zip_io.h"
#include "editor/editor_node.h"
+#include "editor/editor_string_names.h"
#include "editor/export/editor_export_platform.h"
#include "main/splash.gen.h"
@@ -73,7 +74,7 @@ class EditorExportPlatformWeb : public EditorExportPlatform {
icon.instantiate();
const String icon_path = String(GLOBAL_GET("application/config/icon")).strip_edges();
if (icon_path.is_empty() || ImageLoader::load_image(icon_path, icon) != OK) {
- return EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("DefaultProjectIcon"), SNAME("EditorIcons"))->get_image();
+ return EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("DefaultProjectIcon"), EditorStringName(EditorIcons))->get_image();
}
return icon;
}
diff --git a/platform/web/godot_js.h b/platform/web/godot_js.h
index 3341cf8a67..f172148bf9 100644
--- a/platform/web/godot_js.h
+++ b/platform/web/godot_js.h
@@ -31,6 +31,8 @@
#ifndef GODOT_JS_H
#define GODOT_JS_H
+#define WASM_EXPORT __attribute__((visibility("default")))
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/platform/web/javascript_bridge_singleton.cpp b/platform/web/javascript_bridge_singleton.cpp
index 45bce1b480..41206f14a5 100644
--- a/platform/web/javascript_bridge_singleton.cpp
+++ b/platform/web/javascript_bridge_singleton.cpp
@@ -68,11 +68,11 @@ private:
int _js_id = 0;
Callable _callable;
- static int _variant2js(const void **p_args, int p_pos, godot_js_wrapper_ex *r_val, void **p_lock);
- static void _free_lock(void **p_lock, int p_type);
- static Variant _js2variant(int p_type, godot_js_wrapper_ex *p_val);
- static void *_alloc_variants(int p_size);
- static void _callback(void *p_ref, int p_arg_id, int p_argc);
+ WASM_EXPORT static int _variant2js(const void **p_args, int p_pos, godot_js_wrapper_ex *r_val, void **p_lock);
+ WASM_EXPORT static void _free_lock(void **p_lock, int p_type);
+ WASM_EXPORT static Variant _js2variant(int p_type, godot_js_wrapper_ex *p_val);
+ WASM_EXPORT static void *_alloc_variants(int p_size);
+ WASM_EXPORT static void _callback(void *p_ref, int p_arg_id, int p_argc);
protected:
bool _set(const StringName &p_name, const Variant &p_value) override;
@@ -289,7 +289,7 @@ Ref<JavaScriptObject> JavaScriptBridge::get_interface(const String &p_interface)
Variant JavaScriptBridge::_create_object_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
if (p_argcount < 1) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = 0;
+ r_error.expected = 1;
return Ref<JavaScriptObject>();
}
if (p_args[0]->get_type() != Variant::STRING) {
diff --git a/platform/web/js/libs/library_godot_javascript_singleton.js b/platform/web/js/libs/library_godot_javascript_singleton.js
index dafc01a1fd..cbe59230ee 100644
--- a/platform/web/js/libs/library_godot_javascript_singleton.js
+++ b/platform/web/js/libs/library_godot_javascript_singleton.js
@@ -109,7 +109,7 @@ const GodotJSWrapper = {
return 2; // INT
}
GodotRuntime.setHeapValue(p_exchange, p_val, 'double');
- return 3; // REAL
+ return 3; // FLOAT
} else if (type === 'string') {
const c_str = GodotRuntime.allocString(p_val);
GodotRuntime.setHeapValue(p_exchange, c_str, '*');
@@ -210,7 +210,9 @@ const GodotJSWrapper = {
// This is safe! JavaScript is single threaded (and using it in threads is not a good idea anyway).
GodotJSWrapper.cb_ret = null;
const args = Array.from(arguments);
- func(p_ref, GodotJSWrapper.get_proxied(args), args.length);
+ const argsProxy = GodotJSWrapper.MyProxy(args);
+ func(p_ref, argsProxy.get_id(), args.length);
+ argsProxy.unref();
const ret = GodotJSWrapper.cb_ret;
GodotJSWrapper.cb_ret = null;
return ret;
@@ -313,7 +315,7 @@ const GodotEval = {
case 'number':
GodotRuntime.setHeapValue(p_union_ptr, eval_ret, 'double');
- return 3; // REAL
+ return 3; // FLOAT
case 'string':
GodotRuntime.setHeapValue(p_union_ptr, GodotRuntime.allocString(eval_ret), '*');
@@ -333,7 +335,7 @@ const GodotEval = {
const func = GodotRuntime.get_func(p_callback);
const bytes_ptr = func(p_byte_arr, p_byte_arr_write, eval_ret.length);
HEAPU8.set(eval_ret, bytes_ptr);
- return 20; // POOL_BYTE_ARRAY
+ return 29; // PACKED_BYTE_ARRAY
}
break;
diff --git a/platform/web/os_web.cpp b/platform/web/os_web.cpp
index 9ee8f90e89..186e4abf92 100644
--- a/platform/web/os_web.cpp
+++ b/platform/web/os_web.cpp
@@ -132,6 +132,10 @@ int OS_Web::get_processor_count() const {
return godot_js_os_hw_concurrency_get();
}
+String OS_Web::get_unique_id() const {
+ ERR_FAIL_V_MSG("", "OS::get_unique_id() is not available on the Web platform.");
+}
+
bool OS_Web::_check_internal_feature_support(const String &p_feature) {
if (p_feature == "web") {
return true;
@@ -232,7 +236,7 @@ bool OS_Web::is_userfs_persistent() const {
Error OS_Web::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) {
String path = p_path.get_file();
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
- ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror()));
+ ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror()));
if (r_resolved_path != nullptr) {
*r_resolved_path = path;
diff --git a/platform/web/os_web.h b/platform/web/os_web.h
index b9570f9ca1..f262337f00 100644
--- a/platform/web/os_web.h
+++ b/platform/web/os_web.h
@@ -33,6 +33,8 @@
#include "audio_driver_web.h"
+#include "godot_js.h"
+
#include "core/input/input.h"
#include "drivers/unix/os_unix.h"
#include "servers/audio_server.h"
@@ -48,11 +50,11 @@ class OS_Web : public OS_Unix {
bool idb_needs_sync = false;
bool pwa_is_waiting = false;
- static void main_loop_callback();
+ WASM_EXPORT static void main_loop_callback();
- static void file_access_close_callback(const String &p_file, int p_flags);
- static void fs_sync_callback();
- static void update_pwa_state_callback();
+ WASM_EXPORT static void file_access_close_callback(const String &p_file, int p_flags);
+ WASM_EXPORT static void fs_sync_callback();
+ WASM_EXPORT static void update_pwa_state_callback();
protected:
void initialize() override;
@@ -83,6 +85,7 @@ public:
int get_process_id() const override;
bool is_process_running(const ProcessID &p_pid) const override;
int get_processor_count() const override;
+ String get_unique_id() const override;
int get_default_thread_pool_size() const override { return 1; }
String get_executable_path() const override;
diff --git a/platform/web/platform_config.h b/platform/web/platform_config.h
index 78deaadcfd..c3189bccfb 100644
--- a/platform/web/platform_config.h
+++ b/platform/web/platform_config.h
@@ -29,5 +29,3 @@
/**************************************************************************/
#include <alloca.h>
-
-#define OPENGL_INCLUDE_H "platform/web/godot_webgl2.h"
diff --git a/platform/uwp/platform_config.h b/platform/web/platform_gl.h
index 964e341ce4..be6e1462a7 100644
--- a/platform/uwp/platform_config.h
+++ b/platform/web/platform_gl.h
@@ -1,5 +1,5 @@
/**************************************************************************/
-/* platform_config.h */
+/* platform_gl.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,4 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
-#include <malloc.h>
+#ifndef PLATFORM_GL_H
+#define PLATFORM_GL_H
+
+#ifndef GLES_API_ENABLED
+#define GLES_API_ENABLED // Allow using GLES.
+#endif
+
+#include "platform/web/godot_webgl2.h"
+
+#endif // PLATFORM_GL_H
diff --git a/platform/windows/SCsub b/platform/windows/SCsub
index efbb47d965..1b6908d2bb 100644
--- a/platform/windows/SCsub
+++ b/platform/windows/SCsub
@@ -16,7 +16,9 @@ common_win = [
"tts_windows.cpp",
"windows_terminal_logger.cpp",
"vulkan_context_win.cpp",
- "gl_manager_windows.cpp",
+ "gl_manager_windows_native.cpp",
+ "gl_manager_windows_angle.cpp",
+ "wgl_detect_version.cpp",
]
common_win_wrap = [
@@ -44,6 +46,7 @@ if env["windows_subsystem"] == "gui":
env_wrap.Append(LIBS=["version"])
prog_wrap = env_wrap.add_program("#bin/godot", common_win_wrap + res_wrap_obj, PROGSUFFIX=env["PROGSUFFIX_WRAP"])
+ env_wrap.Depends(prog_wrap, prog)
# Microsoft Visual Studio Project Generation
if env["vsproj"]:
diff --git a/platform/windows/crash_handler_windows.h b/platform/windows/crash_handler_windows.h
index ef5831f10c..3871210977 100644
--- a/platform/windows/crash_handler_windows.h
+++ b/platform/windows/crash_handler_windows.h
@@ -35,7 +35,7 @@
#include <windows.h>
// Crash handler exception only enabled with MSVC
-#if defined(DEBUG_ENABLED) && defined(MSVC)
+#if defined(DEBUG_ENABLED) && defined(_MSC_VER)
#define CRASH_HANDLER_EXCEPTION 1
extern DWORD CrashHandlerException(EXCEPTION_POINTERS *ep);
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index 9548939695..7caa0153d7 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -185,6 +185,8 @@ def get_opts():
BoolVariable("use_static_cpp", "Link MinGW/MSVC C++ runtime libraries statically", True),
BoolVariable("use_asan", "Use address sanitizer (ASAN)", False),
BoolVariable("debug_crt", "Compile with MSVC's debug CRT (/MDd)", False),
+ BoolVariable("incremental_link", "Use MSVC incremental linking. May increase or decrease build times.", False),
+ ("angle_libs", "Path to the ANGLE static libraries", ""),
]
@@ -355,8 +357,9 @@ def configure_msvc(env, vcvars_msvc_config):
else:
env.AppendUnique(CCFLAGS=["/MD"])
- # MSVC incremental linking is broken and _increases_ link time (GH-77968).
- env.Append(LINKFLAGS=["/INCREMENTAL:NO"])
+ # MSVC incremental linking is broken and may _increase_ link time (GH-77968).
+ if not env["incremental_link"]:
+ env.Append(LINKFLAGS=["/INCREMENTAL:NO"])
if env["arch"] == "x86_32":
env["x86_libtheora_opt_vc"] = True
@@ -382,7 +385,6 @@ def configure_msvc(env, vcvars_msvc_config):
"WINMIDI_ENABLED",
"TYPED_METHOD_BIND",
"WIN32",
- "MSVC",
"WINVER=%s" % env["target_win_version"],
"_WIN32_WINNT=%s" % env["target_win_version"],
]
@@ -429,7 +431,16 @@ def configure_msvc(env, vcvars_msvc_config):
if env["opengl3"]:
env.AppendUnique(CPPDEFINES=["GLES3_ENABLED"])
- LIBS += ["opengl32"]
+ if env["angle_libs"] != "":
+ env.AppendUnique(CPPDEFINES=["EGL_STATIC"])
+ env.Append(LIBPATH=[env["angle_libs"]])
+ LIBS += [
+ "libANGLE.windows." + env["arch"],
+ "libEGL.windows." + env["arch"],
+ "libGLES.windows." + env["arch"],
+ ]
+ LIBS += ["dxgi", "d3d9", "d3d11"]
+ env.Prepend(CPPPATH=["#thirdparty/angle/include"])
env.Append(LINKFLAGS=[p + env["LIBSUFFIX"] for p in LIBS])
@@ -612,7 +623,18 @@ def configure_mingw(env):
if env["opengl3"]:
env.Append(CPPDEFINES=["GLES3_ENABLED"])
- env.Append(LIBS=["opengl32"])
+ if env["angle_libs"] != "":
+ env.AppendUnique(CPPDEFINES=["EGL_STATIC"])
+ env.Append(LIBPATH=[env["angle_libs"]])
+ env.Append(
+ LIBS=[
+ "EGL.windows." + env["arch"],
+ "GLES.windows." + env["arch"],
+ "ANGLE.windows." + env["arch"],
+ ]
+ )
+ env.Append(LIBS=["dxgi", "d3d9", "d3d11"])
+ env.Prepend(CPPPATH=["#thirdparty/angle/include"])
env.Append(CPPDEFINES=["MINGW_ENABLED", ("MINGW_HAS_SECURE_API", 1)])
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index 5863a75324..70c6fe6549 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -31,6 +31,7 @@
#include "display_server_windows.h"
#include "os_windows.h"
+#include "wgl_detect_version.h"
#include "core/config/project_settings.h"
#include "core/io/marshalls.h"
@@ -184,37 +185,37 @@ void DisplayServerWindows::_register_raw_input_devices(WindowID p_target_window)
}
bool DisplayServerWindows::tts_is_speaking() const {
- ERR_FAIL_COND_V_MSG(!tts, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
+ ERR_FAIL_NULL_V_MSG(tts, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
return tts->is_speaking();
}
bool DisplayServerWindows::tts_is_paused() const {
- ERR_FAIL_COND_V_MSG(!tts, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
+ ERR_FAIL_NULL_V_MSG(tts, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
return tts->is_paused();
}
TypedArray<Dictionary> DisplayServerWindows::tts_get_voices() const {
- ERR_FAIL_COND_V_MSG(!tts, TypedArray<Dictionary>(), "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
+ ERR_FAIL_NULL_V_MSG(tts, TypedArray<Dictionary>(), "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
return tts->get_voices();
}
void DisplayServerWindows::tts_speak(const String &p_text, const String &p_voice, int p_volume, float p_pitch, float p_rate, int p_utterance_id, bool p_interrupt) {
- ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
+ ERR_FAIL_NULL_MSG(tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
tts->speak(p_text, p_voice, p_volume, p_pitch, p_rate, p_utterance_id, p_interrupt);
}
void DisplayServerWindows::tts_pause() {
- ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
+ ERR_FAIL_NULL_MSG(tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
tts->pause();
}
void DisplayServerWindows::tts_resume() {
- ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
+ ERR_FAIL_NULL_MSG(tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
tts->resume();
}
void DisplayServerWindows::tts_stop() {
- ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
+ ERR_FAIL_NULL_MSG(tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
tts->stop();
}
@@ -413,7 +414,7 @@ void DisplayServerWindows::clipboard_set(const String &p_text) {
Char16String utf16 = text.utf16();
HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE, (utf16.length() + 1) * sizeof(WCHAR));
- ERR_FAIL_COND_MSG(mem == nullptr, "Unable to allocate memory for clipboard contents.");
+ ERR_FAIL_NULL_MSG(mem, "Unable to allocate memory for clipboard contents.");
LPWSTR lptstrCopy = (LPWSTR)GlobalLock(mem);
memcpy(lptstrCopy, utf16.get_data(), (utf16.length() + 1) * sizeof(WCHAR));
@@ -424,7 +425,7 @@ void DisplayServerWindows::clipboard_set(const String &p_text) {
// Set the CF_TEXT version (not needed?).
CharString utf8 = text.utf8();
mem = GlobalAlloc(GMEM_MOVEABLE, utf8.length() + 1);
- ERR_FAIL_COND_MSG(mem == nullptr, "Unable to allocate memory for clipboard contents.");
+ ERR_FAIL_NULL_MSG(mem, "Unable to allocate memory for clipboard contents.");
LPTSTR ptr = (LPTSTR)GlobalLock(mem);
memcpy(ptr, utf8.get_data(), utf8.length());
@@ -1070,8 +1071,11 @@ void DisplayServerWindows::delete_sub_window(WindowID p_window) {
}
#endif
#ifdef GLES3_ENABLED
- if (gl_manager) {
- gl_manager->window_destroy(p_window);
+ if (gl_manager_angle) {
+ gl_manager_angle->window_destroy(p_window);
+ }
+ if (gl_manager_native) {
+ gl_manager_native->window_destroy(p_window);
}
#endif
@@ -1089,8 +1093,11 @@ void DisplayServerWindows::delete_sub_window(WindowID p_window) {
void DisplayServerWindows::gl_window_make_current(DisplayServer::WindowID p_window_id) {
#if defined(GLES3_ENABLED)
- if (gl_manager) {
- gl_manager->window_make_current(p_window_id);
+ if (gl_manager_angle) {
+ gl_manager_angle->window_make_current(p_window_id);
+ }
+ if (gl_manager_native) {
+ gl_manager_native->window_make_current(p_window_id);
}
#endif
}
@@ -1106,14 +1113,18 @@ int64_t DisplayServerWindows::window_get_native_handle(HandleType p_handle_type,
}
#if defined(GLES3_ENABLED)
case WINDOW_VIEW: {
- if (gl_manager) {
- return (int64_t)gl_manager->get_hdc(p_window);
+ if (gl_manager_native) {
+ return (int64_t)gl_manager_native->get_hdc(p_window);
+ } else {
+ return (int64_t)GetDC(windows[p_window].hWnd);
}
- return 0;
}
case OPENGL_CONTEXT: {
- if (gl_manager) {
- return (int64_t)gl_manager->get_hglrc(p_window);
+ if (gl_manager_native) {
+ return (int64_t)gl_manager_native->get_hglrc(p_window);
+ }
+ if (gl_manager_angle) {
+ return (int64_t)gl_manager_angle->get_context(p_window);
}
return 0;
}
@@ -1180,6 +1191,51 @@ void DisplayServerWindows::window_set_title(const String &p_title, WindowID p_wi
SetWindowTextW(windows[p_window].hWnd, (LPCWSTR)(p_title.utf16().get_data()));
}
+Size2i DisplayServerWindows::window_get_title_size(const String &p_title, WindowID p_window) const {
+ _THREAD_SAFE_METHOD_
+
+ Size2i size;
+ ERR_FAIL_COND_V(!windows.has(p_window), size);
+
+ const WindowData &wd = windows[p_window];
+ if (wd.fullscreen || wd.minimized || wd.borderless) {
+ return size;
+ }
+
+ HDC hdc = GetDCEx(wd.hWnd, NULL, DCX_WINDOW);
+ if (hdc) {
+ Char16String s = p_title.utf16();
+ SIZE text_size;
+ if (GetTextExtentPoint32W(hdc, (LPCWSTR)(s.get_data()), s.length(), &text_size)) {
+ size.x = text_size.cx;
+ size.y = text_size.cy;
+ }
+
+ ReleaseDC(wd.hWnd, hdc);
+ }
+ RECT rect;
+ if (DwmGetWindowAttribute(wd.hWnd, DWMWA_CAPTION_BUTTON_BOUNDS, &rect, sizeof(RECT)) == S_OK) {
+ if (rect.right - rect.left > 0) {
+ ClientToScreen(wd.hWnd, (POINT *)&rect.left);
+ ClientToScreen(wd.hWnd, (POINT *)&rect.right);
+
+ if (win81p_PhysicalToLogicalPointForPerMonitorDPI) {
+ win81p_PhysicalToLogicalPointForPerMonitorDPI(0, (POINT *)&rect.left);
+ win81p_PhysicalToLogicalPointForPerMonitorDPI(0, (POINT *)&rect.right);
+ }
+
+ size.x += (rect.right - rect.left);
+ size.y = MAX(size.y, rect.bottom - rect.top);
+ }
+ }
+ if (icon.is_valid()) {
+ size.x += 32;
+ } else {
+ size.x += 16;
+ }
+ return size;
+}
+
void DisplayServerWindows::window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window) {
_THREAD_SAFE_METHOD_
@@ -1447,8 +1503,11 @@ void DisplayServerWindows::window_set_size(const Size2i p_size, WindowID p_windo
}
#endif
#if defined(GLES3_ENABLED)
- if (gl_manager) {
- gl_manager->window_resize(p_window, w, h);
+ if (gl_manager_native) {
+ gl_manager_native->window_resize(p_window, w, h);
+ }
+ if (gl_manager_angle) {
+ gl_manager_angle->window_resize(p_window, w, h);
}
#endif
@@ -1511,7 +1570,7 @@ void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_fullscre
if (p_fullscreen || p_borderless) {
r_style |= WS_POPUP; // p_borderless was WS_EX_TOOLWINDOW in the past.
- if (p_fullscreen && p_multiwindow_fs) {
+ if ((p_fullscreen && p_multiwindow_fs) || p_maximized) {
r_style |= WS_BORDER; // Allows child windows to be displayed on top of full screen.
}
} else {
@@ -2318,8 +2377,11 @@ void DisplayServerWindows::make_rendering_thread() {
void DisplayServerWindows::swap_buffers() {
#if defined(GLES3_ENABLED)
- if (gl_manager) {
- gl_manager->swap_buffers();
+ if (gl_manager_angle) {
+ gl_manager_angle->swap_buffers();
+ }
+ if (gl_manager_native) {
+ gl_manager_native->swap_buffers();
}
#endif
}
@@ -2390,7 +2452,7 @@ void DisplayServerWindows::set_native_icon(const String &p_filename) {
f->seek(pos);
f->get_buffer((uint8_t *)&data_big.write[0], bytecount_big);
HICON icon_big = CreateIconFromResource((PBYTE)&data_big.write[0], bytecount_big, TRUE, 0x00030000);
- ERR_FAIL_COND_MSG(!icon_big, "Could not create " + itos(big_icon_width) + "x" + itos(big_icon_width) + " @" + itos(big_icon_cc) + " icon, error: " + format_error_message(GetLastError()) + ".");
+ ERR_FAIL_NULL_MSG(icon_big, "Could not create " + itos(big_icon_width) + "x" + itos(big_icon_width) + " @" + itos(big_icon_cc) + " icon, error: " + format_error_message(GetLastError()) + ".");
// Read the small icon.
DWORD bytecount_small = icon_dir->idEntries[small_icon_index].dwBytesInRes;
@@ -2400,7 +2462,7 @@ void DisplayServerWindows::set_native_icon(const String &p_filename) {
f->seek(pos);
f->get_buffer((uint8_t *)&data_small.write[0], bytecount_small);
HICON icon_small = CreateIconFromResource((PBYTE)&data_small.write[0], bytecount_small, TRUE, 0x00030000);
- ERR_FAIL_COND_MSG(!icon_small, "Could not create 16x16 @" + itos(small_icon_cc) + " icon, error: " + format_error_message(GetLastError()) + ".");
+ ERR_FAIL_NULL_MSG(icon_small, "Could not create 16x16 @" + itos(small_icon_cc) + " icon, error: " + format_error_message(GetLastError()) + ".");
// Online tradition says to be sure last error is cleared and set the small icon first.
int err = 0;
@@ -2465,7 +2527,7 @@ void DisplayServerWindows::set_icon(const Ref<Image> &p_icon) {
}
HICON hicon = CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000);
- ERR_FAIL_COND(!hicon);
+ ERR_FAIL_NULL(hicon);
icon = img;
@@ -2490,8 +2552,11 @@ void DisplayServerWindows::window_set_vsync_mode(DisplayServer::VSyncMode p_vsyn
#endif
#if defined(GLES3_ENABLED)
- if (gl_manager) {
- gl_manager->set_use_vsync(p_window, p_vsync_mode != DisplayServer::VSYNC_DISABLED);
+ if (gl_manager_native) {
+ gl_manager_native->set_use_vsync(p_window, p_vsync_mode != DisplayServer::VSYNC_DISABLED);
+ }
+ if (gl_manager_angle) {
+ gl_manager_angle->set_use_vsync(p_vsync_mode != DisplayServer::VSYNC_DISABLED);
}
#endif
}
@@ -2505,8 +2570,11 @@ DisplayServer::VSyncMode DisplayServerWindows::window_get_vsync_mode(WindowID p_
#endif
#if defined(GLES3_ENABLED)
- if (gl_manager) {
- return gl_manager->is_using_vsync(p_window) ? DisplayServer::VSYNC_ENABLED : DisplayServer::VSYNC_DISABLED;
+ if (gl_manager_native) {
+ return gl_manager_native->is_using_vsync(p_window) ? DisplayServer::VSYNC_ENABLED : DisplayServer::VSYNC_DISABLED;
+ }
+ if (gl_manager_angle) {
+ return gl_manager_angle->is_using_vsync() ? DisplayServer::VSYNC_ENABLED : DisplayServer::VSYNC_DISABLED;
}
#endif
@@ -2829,6 +2897,30 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
// Process window messages.
switch (uMsg) {
+ case WM_NCPAINT: {
+ if (RenderingServer::get_singleton() && (windows[window_id].borderless || (windows[window_id].fullscreen && windows[window_id].multiwindow_fs))) {
+ Color color = RenderingServer::get_singleton()->get_default_clear_color();
+ HDC hdc = GetWindowDC(hWnd);
+ if (hdc) {
+ HPEN pen = CreatePen(PS_SOLID, 1, RGB(color.r * 255.f, color.g * 255.f, color.b * 255.f));
+ if (pen) {
+ HGDIOBJ prev_pen = SelectObject(hdc, pen);
+ HGDIOBJ prev_brush = SelectObject(hdc, GetStockObject(NULL_BRUSH));
+
+ RECT rc;
+ GetWindowRect(hWnd, &rc);
+ OffsetRect(&rc, -rc.left, -rc.top);
+ Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
+
+ SelectObject(hdc, prev_pen);
+ SelectObject(hdc, prev_brush);
+ DeleteObject(pen);
+ }
+ ReleaseDC(hWnd, hdc);
+ }
+ return 0;
+ }
+ } break;
case WM_NCHITTEST: {
if (windows[window_id].mpass) {
return HTTRANSPARENT;
@@ -4224,10 +4316,20 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
#endif
#ifdef GLES3_ENABLED
- if (gl_manager) {
- if (gl_manager->window_create(id, wd.hWnd, hInstance, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top) != OK) {
- memdelete(gl_manager);
- gl_manager = nullptr;
+ if (gl_manager_native) {
+ if (gl_manager_native->window_create(id, wd.hWnd, hInstance, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top) != OK) {
+ memdelete(gl_manager_native);
+ gl_manager_native = nullptr;
+ windows.erase(id);
+ ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Failed to create an OpenGL window.");
+ }
+ window_set_vsync_mode(p_vsync_mode, id);
+ }
+
+ if (gl_manager_angle) {
+ if (gl_manager_angle->window_create(id, nullptr, wd.hWnd, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top) != OK) {
+ memdelete(gl_manager_angle);
+ gl_manager_angle = nullptr;
windows.erase(id);
ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Failed to create an OpenGL window.");
}
@@ -4328,6 +4430,7 @@ bool DisplayServerWindows::winink_available = false;
GetPointerTypePtr DisplayServerWindows::win8p_GetPointerType = nullptr;
GetPointerPenInfoPtr DisplayServerWindows::win8p_GetPointerPenInfo = nullptr;
LogicalToPhysicalPointForPerMonitorDPIPtr DisplayServerWindows::win81p_LogicalToPhysicalPointForPerMonitorDPI = nullptr;
+PhysicalToLogicalPointForPerMonitorDPIPtr DisplayServerWindows::win81p_PhysicalToLogicalPointForPerMonitorDPI = nullptr;
typedef enum _SHC_PROCESS_DPI_AWARENESS {
SHC_PROCESS_DPI_UNAWARE = 0,
@@ -4465,6 +4568,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
win8p_GetPointerType = (GetPointerTypePtr)GetProcAddress(user32_lib, "GetPointerType");
win8p_GetPointerPenInfo = (GetPointerPenInfoPtr)GetProcAddress(user32_lib, "GetPointerPenInfo");
win81p_LogicalToPhysicalPointForPerMonitorDPI = (LogicalToPhysicalPointForPerMonitorDPIPtr)GetProcAddress(user32_lib, "LogicalToPhysicalPointForPerMonitorDPI");
+ win81p_PhysicalToLogicalPointForPerMonitorDPI = (PhysicalToLogicalPointForPerMonitorDPIPtr)GetProcAddress(user32_lib, "PhysicalToLogicalPointForPerMonitorDPI");
winink_available = win8p_GetPointerType && win8p_GetPointerPenInfo;
}
@@ -4523,18 +4627,36 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
#if defined(GLES3_ENABLED)
if (rendering_driver == "opengl3") {
- GLManager_Windows::ContextType opengl_api_type = GLManager_Windows::GLES_3_0_COMPATIBLE;
+ int gl_version = detect_wgl_version();
+ if (gl_version < 30003) {
+ WARN_PRINT("Your video card drivers seem not to support the required OpenGL 3.3 version, switching to ANGLE.");
+ rendering_driver = "opengl3_angle";
+ }
+ }
+
+ if (rendering_driver == "opengl3") {
+ gl_manager_native = memnew(GLManagerNative_Windows);
- gl_manager = memnew(GLManager_Windows(opengl_api_type));
+ if (gl_manager_native->initialize() != OK) {
+ memdelete(gl_manager_native);
+ gl_manager_native = nullptr;
+ r_error = ERR_UNAVAILABLE;
+ return;
+ }
- if (gl_manager->initialize() != OK) {
- memdelete(gl_manager);
- gl_manager = nullptr;
+ RasterizerGLES3::make_current(true);
+ }
+ if (rendering_driver == "opengl3_angle") {
+ gl_manager_angle = memnew(GLManagerANGLE_Windows);
+
+ if (gl_manager_angle->initialize() != OK) {
+ memdelete(gl_manager_angle);
+ gl_manager_angle = nullptr;
r_error = ERR_UNAVAILABLE;
return;
}
- RasterizerGLES3::make_current();
+ RasterizerGLES3::make_current(false);
}
#endif
@@ -4608,6 +4730,7 @@ Vector<String> DisplayServerWindows::get_rendering_drivers_func() {
#endif
#ifdef GLES3_ENABLED
drivers.push_back("opengl3");
+ drivers.push_back("opengl3_angle");
#endif
return drivers;
@@ -4693,9 +4816,13 @@ DisplayServerWindows::~DisplayServerWindows() {
SystemParametersInfoA(SPI_SETMOUSETRAILS, restore_mouse_trails, 0, 0);
}
#ifdef GLES3_ENABLED
- if (gl_manager) {
- memdelete(gl_manager);
- gl_manager = nullptr;
+ if (gl_manager_angle) {
+ memdelete(gl_manager_angle);
+ gl_manager_angle = nullptr;
+ }
+ if (gl_manager_native) {
+ memdelete(gl_manager_native);
+ gl_manager_native = nullptr;
}
#endif
if (tts) {
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index 59c4442604..48c8c20280 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -59,8 +59,9 @@
#endif
#if defined(GLES3_ENABLED)
-#include "gl_manager_windows.h"
-#endif
+#include "gl_manager_windows_angle.h"
+#include "gl_manager_windows_native.h"
+#endif // GLES3_ENABLED
#include <io.h>
#include <stdio.h>
@@ -261,6 +262,7 @@ typedef struct tagPOINTER_PEN_INFO {
typedef BOOL(WINAPI *GetPointerTypePtr)(uint32_t p_id, POINTER_INPUT_TYPE *p_type);
typedef BOOL(WINAPI *GetPointerPenInfoPtr)(uint32_t p_id, POINTER_PEN_INFO *p_pen_info);
typedef BOOL(WINAPI *LogicalToPhysicalPointForPerMonitorDPIPtr)(HWND hwnd, LPPOINT lpPoint);
+typedef BOOL(WINAPI *PhysicalToLogicalPointForPerMonitorDPIPtr)(HWND hwnd, LPPOINT lpPoint);
typedef struct {
BYTE bWidth; // Width, in pixels, of the image
@@ -308,6 +310,7 @@ class DisplayServerWindows : public DisplayServer {
// DPI conversion API
static LogicalToPhysicalPointForPerMonitorDPIPtr win81p_LogicalToPhysicalPointForPerMonitorDPI;
+ static PhysicalToLogicalPointForPerMonitorDPIPtr win81p_PhysicalToLogicalPointForPerMonitorDPI;
void _update_tablet_ctx(const String &p_old_driver, const String &p_new_driver);
String tablet_driver;
@@ -335,7 +338,8 @@ class DisplayServerWindows : public DisplayServer {
Point2i center;
#if defined(GLES3_ENABLED)
- GLManager_Windows *gl_manager = nullptr;
+ GLManagerANGLE_Windows *gl_manager_angle = nullptr;
+ GLManagerNative_Windows *gl_manager_native = nullptr;
#endif
#if defined(VULKAN_ENABLED)
@@ -567,6 +571,7 @@ public:
virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Size2i window_get_title_size(const String &p_title, WindowID p_window = MAIN_WINDOW_ID) const override;
virtual void window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window = MAIN_WINDOW_ID) override;
virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const override;
diff --git a/platform/windows/doc_classes/EditorExportPlatformWindows.xml b/platform/windows/doc_classes/EditorExportPlatformWindows.xml
index fc068efc75..2a286de100 100644
--- a/platform/windows/doc_classes/EditorExportPlatformWindows.xml
+++ b/platform/windows/doc_classes/EditorExportPlatformWindows.xml
@@ -18,6 +18,9 @@
<member name="application/copyright" type="String" setter="" getter="">
Copyright notice for the bundle visible to the user. Optional. See [url=https://learn.microsoft.com/en-us/windows/win32/menurc/stringfileinfo-block]StringFileInfo[/url].
</member>
+ <member name="application/export_angle" type="int" setter="" getter="">
+ If set to [code]1[/code], ANGLE libraries are exported with the exported application. If set to [code]0[/code], ANGLE libraries are exported only if [member ProjectSettings.rendering/gl_compatibility/driver] is set to [code]"opengl3_angle"[/code].
+ </member>
<member name="application/file_description" type="String" setter="" getter="">
File description to be presented to users. Required. See [url=https://learn.microsoft.com/en-us/windows/win32/menurc/stringfileinfo-block]StringFileInfo[/url].
</member>
diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp
index c4be1821bd..4185c36d77 100644
--- a/platform/windows/export/export_plugin.cpp
+++ b/platform/windows/export/export_plugin.cpp
@@ -38,6 +38,7 @@
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
#include "editor/editor_scale.h"
+#include "editor/editor_string_names.h"
#include "editor/export/editor_export.h"
#include "modules/modules_enabled.gen.h" // For svg.
@@ -178,6 +179,35 @@ Error EditorExportPlatformWindows::modify_template(const Ref<EditorExportPreset>
}
Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+ int export_angle = p_preset->get("application/export_angle");
+ bool include_angle_libs = false;
+ if (export_angle == 0) {
+ include_angle_libs = String(GLOBAL_GET("rendering/gl_compatibility/driver.windows")) == "opengl3_angle";
+ } else if (export_angle == 1) {
+ include_angle_libs = true;
+ }
+
+ if (include_angle_libs) {
+ 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");
+
+ String template_path = p_debug ? custom_debug : custom_release;
+
+ template_path = template_path.strip_edges();
+
+ if (template_path.is_empty()) {
+ template_path = find_export_template(get_template_file_name(p_debug ? "debug" : "release", arch));
+ }
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ if (da->file_exists(template_path.get_base_dir().path_join("libEGL." + arch + ".dll"))) {
+ da->copy(template_path.get_base_dir().path_join("libEGL." + arch + ".dll"), p_path.get_base_dir().path_join("libEGL.dll"), get_chmod_flags());
+ }
+ if (da->file_exists(template_path.get_base_dir().path_join("libGLESv2." + arch + ".dll"))) {
+ da->copy(template_path.get_base_dir().path_join("libGLESv2." + arch + ".dll"), p_path.get_base_dir().path_join("libGLESv2.dll"), get_chmod_flags());
+ }
+ }
+
bool export_as_zip = p_path.ends_with("zip");
bool embedded = p_preset->get("binary_format/embed_pck");
@@ -310,7 +340,7 @@ bool EditorExportPlatformWindows::get_export_option_visibility(const EditorExpor
// Hide resources.
bool mod_res = p_preset->get("application/modify_resources");
- if (!mod_res && p_option != "application/modify_resources" && p_option.begins_with("application/")) {
+ if (!mod_res && p_option != "application/modify_resources" && p_option != "application/export_angle" && p_option.begins_with("application/")) {
return false;
}
@@ -349,6 +379,7 @@ void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_optio
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_description"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/trademarks"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/export_angle", PROPERTY_HINT_ENUM, "Auto,Yes,No"), 0, true));
String run_script = "Expand-Archive -LiteralPath '{temp_dir}\\{archive_name}' -DestinationPath '{temp_dir}'\n"
"$action = New-ScheduledTaskAction -Execute '{temp_dir}\\{exe_name}' -Argument '{cmd_args}'\n"
@@ -1020,7 +1051,7 @@ EditorExportPlatformWindows::EditorExportPlatformWindows() {
Ref<Theme> theme = EditorNode::get_singleton()->get_editor_theme();
if (theme.is_valid()) {
- stop_icon = theme->get_icon(SNAME("Stop"), SNAME("EditorIcons"));
+ stop_icon = theme->get_icon(SNAME("Stop"), EditorStringName(EditorIcons));
} else {
stop_icon.instantiate();
}
diff --git a/platform/windows/gl_manager_windows_angle.cpp b/platform/windows/gl_manager_windows_angle.cpp
new file mode 100644
index 0000000000..3086edc7f2
--- /dev/null
+++ b/platform/windows/gl_manager_windows_angle.cpp
@@ -0,0 +1,70 @@
+/**************************************************************************/
+/* gl_manager_windows_angle.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "gl_manager_windows_angle.h"
+
+#if defined(WINDOWS_ENABLED) && defined(GLES3_ENABLED)
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <EGL/eglext_angle.h>
+
+const char *GLManagerANGLE_Windows::_get_platform_extension_name() const {
+ return "EGL_ANGLE_platform_angle";
+}
+
+EGLenum GLManagerANGLE_Windows::_get_platform_extension_enum() const {
+ return EGL_PLATFORM_ANGLE_ANGLE;
+}
+
+Vector<EGLAttrib> GLManagerANGLE_Windows::_get_platform_display_attributes() const {
+ Vector<EGLAttrib> ret;
+ ret.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
+ ret.push_back(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE);
+ ret.push_back(EGL_NONE);
+
+ return ret;
+}
+
+EGLenum GLManagerANGLE_Windows::_get_platform_api_enum() const {
+ return EGL_OPENGL_ES_API;
+}
+
+Vector<EGLint> GLManagerANGLE_Windows::_get_platform_context_attribs() const {
+ Vector<EGLint> ret;
+ ret.push_back(EGL_CONTEXT_CLIENT_VERSION);
+ ret.push_back(3);
+ ret.push_back(EGL_NONE);
+
+ return ret;
+}
+
+#endif // WINDOWS_ENABLED && GLES3_ENABLED
diff --git a/platform/windows/gl_manager_windows_angle.h b/platform/windows/gl_manager_windows_angle.h
new file mode 100644
index 0000000000..d8dc651cfd
--- /dev/null
+++ b/platform/windows/gl_manager_windows_angle.h
@@ -0,0 +1,61 @@
+/**************************************************************************/
+/* gl_manager_windows_angle.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef GL_MANAGER_WINDOWS_ANGLE_H
+#define GL_MANAGER_WINDOWS_ANGLE_H
+
+#if defined(WINDOWS_ENABLED) && defined(GLES3_ENABLED)
+
+#include "core/error/error_list.h"
+#include "core/os/os.h"
+#include "core/templates/local_vector.h"
+#include "drivers/egl/egl_manager.h"
+#include "servers/display_server.h"
+
+#include <windows.h>
+
+class GLManagerANGLE_Windows : public EGLManager {
+private:
+ virtual const char *_get_platform_extension_name() const override;
+ virtual EGLenum _get_platform_extension_enum() const override;
+ virtual EGLenum _get_platform_api_enum() const override;
+ virtual Vector<EGLAttrib> _get_platform_display_attributes() const override;
+ virtual Vector<EGLint> _get_platform_context_attribs() const override;
+
+public:
+ void window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height) {}
+
+ GLManagerANGLE_Windows(){};
+ ~GLManagerANGLE_Windows(){};
+};
+
+#endif // WINDOWS_ENABLED && GLES3_ENABLED
+
+#endif // GL_MANAGER_WINDOWS_ANGLE_H
diff --git a/platform/windows/gl_manager_windows.cpp b/platform/windows/gl_manager_windows_native.cpp
index d3972c7bbc..b350786d11 100644
--- a/platform/windows/gl_manager_windows.cpp
+++ b/platform/windows/gl_manager_windows_native.cpp
@@ -1,5 +1,5 @@
/**************************************************************************/
-/* gl_manager_windows.cpp */
+/* gl_manager_windows_native.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
-#include "gl_manager_windows.h"
+#include "gl_manager_windows_native.h"
#if defined(WINDOWS_ENABLED) && defined(GLES3_ENABLED)
@@ -52,11 +52,14 @@
#if defined(__GNUC__)
// Workaround GCC warning from -Wcast-function-type.
-#define wglGetProcAddress (void *)wglGetProcAddress
#define GetProcAddress (void *)GetProcAddress
#endif
+typedef HGLRC(APIENTRY *PFNWGLCREATECONTEXT)(HDC);
+typedef BOOL(APIENTRY *PFNWGLDELETECONTEXT)(HGLRC);
+typedef BOOL(APIENTRY *PFNWGLMAKECURRENT)(HDC, HGLRC);
typedef HGLRC(APIENTRY *PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC, HGLRC, const int *);
+typedef void *(APIENTRY *PFNWGLGETPROCADDRESS)(LPCSTR);
static String format_error_message(DWORD id) {
LPWSTR messageBuffer = nullptr;
@@ -85,6 +88,7 @@ typedef int(__cdecl *NvAPI_DRS_CreateApplication_t)(NvDRSSessionHandle, NvDRSPro
typedef int(__cdecl *NvAPI_DRS_SaveSettings_t)(NvDRSSessionHandle);
typedef int(__cdecl *NvAPI_DRS_SetSetting_t)(NvDRSSessionHandle, NvDRSProfileHandle, NVDRS_SETTING *);
typedef int(__cdecl *NvAPI_DRS_FindProfileByName_t)(NvDRSSessionHandle, NvAPI_UnicodeString, NvDRSProfileHandle *);
+typedef int(__cdecl *NvAPI_DRS_FindApplicationByName_t)(NvDRSSessionHandle, NvAPI_UnicodeString, NvDRSProfileHandle *, NVDRS_APPLICATION *);
NvAPI_GetErrorMessage_t NvAPI_GetErrorMessage__;
static bool nvapi_err_check(const char *msg, int status) {
@@ -102,7 +106,7 @@ static bool nvapi_err_check(const char *msg, int status) {
// On windows we have to disable threaded optimization when using NVIDIA graphics cards
// to avoid stuttering, see https://github.com/microsoft/vscode-cpptools/issues/6592
// also see https://github.com/Ryujinx/Ryujinx/blob/master/Ryujinx.Common/GraphicsDriver/NVThreadedOptimization.cs
-void GLManager_Windows::_nvapi_disable_threaded_optimization() {
+void GLManagerNative_Windows::_nvapi_disable_threaded_optimization() {
HMODULE nvapi = 0;
#ifdef _WIN64
nvapi = LoadLibraryA("nvapi64.dll");
@@ -116,7 +120,7 @@ void GLManager_Windows::_nvapi_disable_threaded_optimization() {
void *(__cdecl * NvAPI_QueryInterface)(unsigned int interface_id) = 0;
- NvAPI_QueryInterface = (void *(__cdecl *)(unsigned int))GetProcAddress(nvapi, "nvapi_QueryInterface");
+ NvAPI_QueryInterface = (void *(__cdecl *)(unsigned int))(void *)GetProcAddress(nvapi, "nvapi_QueryInterface");
if (NvAPI_QueryInterface == NULL) {
print_verbose("Error getting NVAPI NvAPI_QueryInterface");
@@ -135,6 +139,7 @@ void GLManager_Windows::_nvapi_disable_threaded_optimization() {
NvAPI_DRS_SaveSettings_t NvAPI_DRS_SaveSettings = (NvAPI_DRS_SaveSettings_t)NvAPI_QueryInterface(0xFCBC7E14);
NvAPI_DRS_SetSetting_t NvAPI_DRS_SetSetting = (NvAPI_DRS_SetSetting_t)NvAPI_QueryInterface(0x577DD202);
NvAPI_DRS_FindProfileByName_t NvAPI_DRS_FindProfileByName = (NvAPI_DRS_FindProfileByName_t)NvAPI_QueryInterface(0x7E4A9A0B);
+ NvAPI_DRS_FindApplicationByName_t NvAPI_DRS_FindApplicationByName = (NvAPI_DRS_FindApplicationByName_t)NvAPI_QueryInterface(0xEEE566B2);
if (!nvapi_err_check("NVAPI: Init failed", NvAPI_Initialize())) {
return;
@@ -169,9 +174,9 @@ void GLManager_Windows::_nvapi_disable_threaded_optimization() {
NvDRSProfileHandle profile_handle = 0;
- int status = NvAPI_DRS_FindProfileByName(session_handle, (NvU16 *)(app_profile_name_u16.ptrw()), &profile_handle);
+ int profile_status = NvAPI_DRS_FindProfileByName(session_handle, (NvU16 *)(app_profile_name_u16.ptrw()), &profile_handle);
- if (status != 0) {
+ if (profile_status != 0) {
print_verbose("NVAPI: Profile not found, creating....");
NVDRS_PROFILE profile_info;
@@ -184,9 +189,17 @@ void GLManager_Windows::_nvapi_disable_threaded_optimization() {
NvAPI_Unload();
return;
}
+ }
+
+ NvDRSProfileHandle app_profile_handle = 0;
+ NVDRS_APPLICATION_V4 app;
+ app.version = NVDRS_APPLICATION_VER_V4;
+
+ int app_status = NvAPI_DRS_FindApplicationByName(session_handle, (NvU16 *)(app_executable_name_u16.ptrw()), &app_profile_handle, &app);
+
+ if (app_status != 0) {
+ print_verbose("NVAPI: Application not found, adding to profile...");
- NVDRS_APPLICATION_V4 app;
- app.version = NVDRS_APPLICATION_VER_V4;
app.isPredefined = 0;
app.isMetro = 1;
app.isCommandLine = 1;
@@ -235,7 +248,7 @@ void GLManager_Windows::_nvapi_disable_threaded_optimization() {
NvAPI_DRS_DestroySession(session_handle);
}
-int GLManager_Windows::_find_or_create_display(GLWindow &win) {
+int GLManagerNative_Windows::_find_or_create_display(GLWindow &win) {
// find display NYI, only 1 supported so far
if (_displays.size()) {
return 0;
@@ -297,19 +310,36 @@ static Error _configure_pixel_format(HDC hDC) {
return OK;
}
-Error GLManager_Windows::_create_context(GLWindow &win, GLDisplay &gl_display) {
+PFNWGLCREATECONTEXT gd_wglCreateContext;
+PFNWGLMAKECURRENT gd_wglMakeCurrent;
+PFNWGLDELETECONTEXT gd_wglDeleteContext;
+PFNWGLGETPROCADDRESS gd_wglGetProcAddress;
+
+Error GLManagerNative_Windows::_create_context(GLWindow &win, GLDisplay &gl_display) {
Error err = _configure_pixel_format(win.hDC);
if (err != OK) {
return err;
}
- gl_display.hRC = wglCreateContext(win.hDC);
+ HMODULE module = LoadLibraryW(L"opengl32.dll");
+ if (!module) {
+ return ERR_CANT_CREATE;
+ }
+ gd_wglCreateContext = (PFNWGLCREATECONTEXT)GetProcAddress(module, "wglCreateContext");
+ gd_wglMakeCurrent = (PFNWGLMAKECURRENT)GetProcAddress(module, "wglMakeCurrent");
+ gd_wglDeleteContext = (PFNWGLDELETECONTEXT)GetProcAddress(module, "wglDeleteContext");
+ gd_wglGetProcAddress = (PFNWGLGETPROCADDRESS)GetProcAddress(module, "wglGetProcAddress");
+ if (!gd_wglCreateContext || !gd_wglMakeCurrent || !gd_wglDeleteContext || !gd_wglGetProcAddress) {
+ return ERR_CANT_CREATE;
+ }
+
+ gl_display.hRC = gd_wglCreateContext(win.hDC);
if (!gl_display.hRC) // Are We Able To Get A Rendering Context?
{
return ERR_CANT_CREATE; // Return FALSE
}
- if (!wglMakeCurrent(win.hDC, gl_display.hRC)) {
+ if (!gd_wglMakeCurrent(win.hDC, gl_display.hRC)) {
ERR_PRINT("Could not attach OpenGL context to newly created window: " + format_error_message(GetLastError()));
}
@@ -323,45 +353,45 @@ Error GLManager_Windows::_create_context(GLWindow &win, GLDisplay &gl_display) {
}; //zero indicates the end of the array
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = nullptr; //pointer to the method
- wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
+ wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)gd_wglGetProcAddress("wglCreateContextAttribsARB");
if (wglCreateContextAttribsARB == nullptr) //OpenGL 3.0 is not supported
{
- wglDeleteContext(gl_display.hRC);
+ gd_wglDeleteContext(gl_display.hRC);
gl_display.hRC = 0;
return ERR_CANT_CREATE;
}
HGLRC new_hRC = wglCreateContextAttribsARB(win.hDC, 0, attribs);
if (!new_hRC) {
- wglDeleteContext(gl_display.hRC);
+ gd_wglDeleteContext(gl_display.hRC);
gl_display.hRC = 0;
return ERR_CANT_CREATE;
}
- if (!wglMakeCurrent(win.hDC, nullptr)) {
+ if (!gd_wglMakeCurrent(win.hDC, nullptr)) {
ERR_PRINT("Could not detach OpenGL context from newly created window: " + format_error_message(GetLastError()));
}
- wglDeleteContext(gl_display.hRC);
+ gd_wglDeleteContext(gl_display.hRC);
gl_display.hRC = new_hRC;
- if (!wglMakeCurrent(win.hDC, gl_display.hRC)) // Try To Activate The Rendering Context
+ if (!gd_wglMakeCurrent(win.hDC, gl_display.hRC)) // Try to activate the rendering context.
{
ERR_PRINT("Could not attach OpenGL context to newly created window with replaced OpenGL context: " + format_error_message(GetLastError()));
- wglDeleteContext(gl_display.hRC);
+ gd_wglDeleteContext(gl_display.hRC);
gl_display.hRC = 0;
return ERR_CANT_CREATE;
}
if (!wglSwapIntervalEXT) {
- wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
+ wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)gd_wglGetProcAddress("wglSwapIntervalEXT");
}
return OK;
}
-Error GLManager_Windows::window_create(DisplayServer::WindowID p_window_id, HWND p_hwnd, HINSTANCE p_hinstance, int p_width, int p_height) {
+Error GLManagerNative_Windows::window_create(DisplayServer::WindowID p_window_id, HWND p_hwnd, HINSTANCE p_hinstance, int p_width, int p_height) {
HDC hDC = GetDC(p_hwnd);
if (!hDC) {
return ERR_CANT_CREATE;
@@ -374,8 +404,6 @@ Error GLManager_Windows::window_create(DisplayServer::WindowID p_window_id, HWND
}
GLWindow win;
- win.width = p_width;
- win.height = p_height;
win.hwnd = p_hwnd;
win.hDC = hDC;
@@ -395,24 +423,11 @@ Error GLManager_Windows::window_create(DisplayServer::WindowID p_window_id, HWND
return OK;
}
-void GLManager_Windows::_internal_set_current_window(GLWindow *p_win) {
+void GLManagerNative_Windows::_internal_set_current_window(GLWindow *p_win) {
_current_window = p_win;
}
-void GLManager_Windows::window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height) {
- get_window(p_window_id).width = p_width;
- get_window(p_window_id).height = p_height;
-}
-
-int GLManager_Windows::window_get_width(DisplayServer::WindowID p_window_id) {
- return get_window(p_window_id).width;
-}
-
-int GLManager_Windows::window_get_height(DisplayServer::WindowID p_window_id) {
- return get_window(p_window_id).height;
-}
-
-void GLManager_Windows::window_destroy(DisplayServer::WindowID p_window_id) {
+void GLManagerNative_Windows::window_destroy(DisplayServer::WindowID p_window_id) {
GLWindow &win = get_window(p_window_id);
if (_current_window == &win) {
_current_window = nullptr;
@@ -420,17 +435,17 @@ void GLManager_Windows::window_destroy(DisplayServer::WindowID p_window_id) {
_windows.erase(p_window_id);
}
-void GLManager_Windows::release_current() {
+void GLManagerNative_Windows::release_current() {
if (!_current_window) {
return;
}
- if (!wglMakeCurrent(_current_window->hDC, nullptr)) {
+ if (!gd_wglMakeCurrent(_current_window->hDC, nullptr)) {
ERR_PRINT("Could not detach OpenGL context from window marked current: " + format_error_message(GetLastError()));
}
}
-void GLManager_Windows::window_make_current(DisplayServer::WindowID p_window_id) {
+void GLManagerNative_Windows::window_make_current(DisplayServer::WindowID p_window_id) {
if (p_window_id == -1) {
return;
}
@@ -444,33 +459,33 @@ void GLManager_Windows::window_make_current(DisplayServer::WindowID p_window_id)
}
const GLDisplay &disp = get_display(win.gldisplay_id);
- if (!wglMakeCurrent(win.hDC, disp.hRC)) {
+ if (!gd_wglMakeCurrent(win.hDC, disp.hRC)) {
ERR_PRINT("Could not switch OpenGL context to other window: " + format_error_message(GetLastError()));
}
_internal_set_current_window(&win);
}
-void GLManager_Windows::make_current() {
+void GLManagerNative_Windows::make_current() {
if (!_current_window) {
return;
}
const GLDisplay &disp = get_current_display();
- if (!wglMakeCurrent(_current_window->hDC, disp.hRC)) {
+ if (!gd_wglMakeCurrent(_current_window->hDC, disp.hRC)) {
ERR_PRINT("Could not switch OpenGL context to window marked current: " + format_error_message(GetLastError()));
}
}
-void GLManager_Windows::swap_buffers() {
+void GLManagerNative_Windows::swap_buffers() {
SwapBuffers(_current_window->hDC);
}
-Error GLManager_Windows::initialize() {
+Error GLManagerNative_Windows::initialize() {
_nvapi_disable_threaded_optimization();
return OK;
}
-void GLManager_Windows::set_use_vsync(DisplayServer::WindowID p_window_id, bool p_use) {
+void GLManagerNative_Windows::set_use_vsync(DisplayServer::WindowID p_window_id, bool p_use) {
GLWindow &win = get_window(p_window_id);
GLWindow *current = _current_window;
@@ -480,7 +495,12 @@ void GLManager_Windows::set_use_vsync(DisplayServer::WindowID p_window_id, bool
if (wglSwapIntervalEXT) {
win.use_vsync = p_use;
- wglSwapIntervalEXT(p_use ? 1 : 0);
+
+ if (!wglSwapIntervalEXT(p_use ? 1 : 0)) {
+ WARN_PRINT("Could not set V-Sync mode.");
+ }
+ } else {
+ WARN_PRINT("Could not set V-Sync mode. V-Sync is not supported.");
}
if (current != _current_window) {
@@ -489,29 +509,27 @@ void GLManager_Windows::set_use_vsync(DisplayServer::WindowID p_window_id, bool
}
}
-bool GLManager_Windows::is_using_vsync(DisplayServer::WindowID p_window_id) const {
+bool GLManagerNative_Windows::is_using_vsync(DisplayServer::WindowID p_window_id) const {
return get_window(p_window_id).use_vsync;
}
-HDC GLManager_Windows::get_hdc(DisplayServer::WindowID p_window_id) {
+HDC GLManagerNative_Windows::get_hdc(DisplayServer::WindowID p_window_id) {
return get_window(p_window_id).hDC;
}
-HGLRC GLManager_Windows::get_hglrc(DisplayServer::WindowID p_window_id) {
+HGLRC GLManagerNative_Windows::get_hglrc(DisplayServer::WindowID p_window_id) {
const GLWindow &win = get_window(p_window_id);
const GLDisplay &disp = get_display(win.gldisplay_id);
return disp.hRC;
}
-GLManager_Windows::GLManager_Windows(ContextType p_context_type) {
- context_type = p_context_type;
-
+GLManagerNative_Windows::GLManagerNative_Windows() {
direct_render = false;
glx_minor = glx_major = 0;
_current_window = nullptr;
}
-GLManager_Windows::~GLManager_Windows() {
+GLManagerNative_Windows::~GLManagerNative_Windows() {
release_current();
}
diff --git a/platform/windows/gl_manager_windows.h b/platform/windows/gl_manager_windows_native.h
index 482b00a1ba..829c53b3d2 100644
--- a/platform/windows/gl_manager_windows.h
+++ b/platform/windows/gl_manager_windows_native.h
@@ -1,5 +1,5 @@
/**************************************************************************/
-/* gl_manager_windows.h */
+/* gl_manager_windows_native.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
-#ifndef GL_MANAGER_WINDOWS_H
-#define GL_MANAGER_WINDOWS_H
+#ifndef GL_MANAGER_WINDOWS_NATIVE_H
+#define GL_MANAGER_WINDOWS_NATIVE_H
#if defined(WINDOWS_ENABLED) && defined(GLES3_ENABLED)
@@ -43,17 +43,10 @@
typedef bool(APIENTRY *PFNWGLSWAPINTERVALEXTPROC)(int interval);
typedef int(APIENTRY *PFNWGLGETSWAPINTERVALEXTPROC)(void);
-class GLManager_Windows {
-public:
- enum ContextType {
- GLES_3_0_COMPATIBLE,
- };
-
+class GLManagerNative_Windows {
private:
// any data specific to the window
struct GLWindow {
- int width = 0;
- int height = 0;
bool use_vsync = false;
// windows specific
@@ -86,7 +79,6 @@ private:
bool direct_render;
int glx_minor, glx_major;
- ContextType context_type;
private:
void _nvapi_disable_threaded_optimization();
@@ -96,11 +88,7 @@ private:
public:
Error window_create(DisplayServer::WindowID p_window_id, HWND p_hwnd, HINSTANCE p_hinstance, int p_width, int p_height);
void window_destroy(DisplayServer::WindowID p_window_id);
- void window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height);
-
- // get directly from the cached GLWindow
- int window_get_width(DisplayServer::WindowID p_window_id = 0);
- int window_get_height(DisplayServer::WindowID p_window_id = 0);
+ void window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height) {}
void release_current();
void make_current();
@@ -116,10 +104,10 @@ public:
HDC get_hdc(DisplayServer::WindowID p_window_id);
HGLRC get_hglrc(DisplayServer::WindowID p_window_id);
- GLManager_Windows(ContextType p_context_type);
- ~GLManager_Windows();
+ GLManagerNative_Windows();
+ ~GLManagerNative_Windows();
};
#endif // WINDOWS_ENABLED && GLES3_ENABLED
-#endif // GL_MANAGER_WINDOWS_H
+#endif // GL_MANAGER_WINDOWS_NATIVE_H
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 7c94e38e14..1d3b80e21e 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -395,7 +395,7 @@ Error OS_Windows::open_dynamic_library(const String p_path, void *&p_library_han
}
}
#else
- ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, format_error_message(GetLastError())));
+ ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, format_error_message(GetLastError())));
#endif
if (cookie) {
@@ -1356,18 +1356,13 @@ Error OS_Windows::shell_open(String p_uri) {
}
Error OS_Windows::shell_show_in_file_manager(String p_path, bool p_open_folder) {
- p_path = p_path.trim_suffix("file://");
-
bool open_folder = false;
if (DirAccess::dir_exists_absolute(p_path) && p_open_folder) {
open_folder = true;
}
- if (p_path.begins_with("\"")) {
- p_path = String("\"") + p_path;
- }
- if (p_path.ends_with("\"")) {
- p_path = p_path + String("\"");
+ if (!p_path.is_quoted()) {
+ p_path = p_path.quote();
}
p_path = p_path.replace("/", "\\");
@@ -1683,7 +1678,7 @@ Error OS_Windows::move_to_trash(const String &p_path) {
String OS_Windows::get_system_ca_certificates() {
HCERTSTORE cert_store = CertOpenSystemStoreA(0, "ROOT");
- ERR_FAIL_COND_V_MSG(!cert_store, "", "Failed to read the root certificate store.");
+ ERR_FAIL_NULL_V_MSG(cert_store, "", "Failed to read the root certificate store.");
FILETIME curr_time;
GetSystemTimeAsFileTime(&curr_time);
diff --git a/platform/windows/platform_config.h b/platform/windows/platform_config.h
index ae4e51e3fb..964e341ce4 100644
--- a/platform/windows/platform_config.h
+++ b/platform/windows/platform_config.h
@@ -29,5 +29,3 @@
/**************************************************************************/
#include <malloc.h>
-
-#define OPENGL_INCLUDE_H "thirdparty/glad/glad/gl.h"
diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginInfoProvider.java b/platform/windows/platform_gl.h
index 63999a8321..e4af8b0ccd 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginInfoProvider.java
+++ b/platform/windows/platform_gl.h
@@ -1,5 +1,5 @@
/**************************************************************************/
-/* GodotPluginInfoProvider.java */
+/* platform_gl.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,45 +28,26 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
-package org.godotengine.godot.plugin;
+#ifndef PLATFORM_GL_H
+#define PLATFORM_GL_H
-import androidx.annotation.NonNull;
+#ifndef GL_API_ENABLED
+#define GL_API_ENABLED // Allow using desktop GL.
+#endif
-import java.util.Collections;
-import java.util.Set;
+#ifndef GLES_API_ENABLED
+#define GLES_API_ENABLED // Allow using GLES (ANGLE).
+#endif
-/**
- * Provides the set of information expected from a Godot plugin.
- */
-public interface GodotPluginInfoProvider {
- /**
- * Returns the name of the plugin.
- */
- @NonNull
- String getPluginName();
+#ifdef EGL_STATIC
+#define KHRONOS_STATIC 1
+#include "thirdparty/angle/include/EGL/egl.h"
+#include "thirdparty/angle/include/EGL/eglext.h"
+#undef KHRONOS_STATIC
+#else
+#include "thirdparty/glad/glad/egl.h"
+#endif
- /**
- * Returns the list of signals to be exposed to Godot.
- */
- @NonNull
- default Set<SignalInfo> getPluginSignals() {
- return Collections.emptySet();
- }
+#include "thirdparty/glad/glad/gl.h"
- /**
- * Returns the paths for the plugin's gdextension libraries (if any).
- *
- * The paths must be relative to the 'assets' directory and point to a '*.gdextension' file.
- */
- @NonNull
- default Set<String> getPluginGDExtensionLibrariesPaths() {
- return Collections.emptySet();
- }
-
- /**
- * This is invoked on the render thread when the plugin described by this instance has been
- * registered.
- */
- default void onPluginRegistered() {
- }
-}
+#endif // PLATFORM_GL_H
diff --git a/platform/windows/platform_windows_builders.py b/platform/windows/platform_windows_builders.py
index b522a75a9c..51652fa814 100644
--- a/platform/windows/platform_windows_builders.py
+++ b/platform/windows/platform_windows_builders.py
@@ -5,14 +5,24 @@ All such functions are invoked in a subprocess on Windows to prevent build flaki
"""
import os
from detect import get_mingw_bin_prefix
+from detect import try_cmd
from platform_methods import subprocess_main
def make_debug_mingw(target, source, env):
mingw_bin_prefix = get_mingw_bin_prefix(env["mingw_prefix"], env["arch"])
- os.system(mingw_bin_prefix + "objcopy --only-keep-debug {0} {0}.debugsymbols".format(target[0]))
- os.system(mingw_bin_prefix + "strip --strip-debug --strip-unneeded {0}".format(target[0]))
- os.system(mingw_bin_prefix + "objcopy --add-gnu-debuglink={0}.debugsymbols {0}".format(target[0]))
+ if try_cmd("objcopy --version", env["mingw_prefix"], env["arch"]):
+ os.system(mingw_bin_prefix + "objcopy --only-keep-debug {0} {0}.debugsymbols".format(target[0]))
+ else:
+ os.system("objcopy --only-keep-debug {0} {0}.debugsymbols".format(target[0]))
+ if try_cmd("strip --version", env["mingw_prefix"], env["arch"]):
+ os.system(mingw_bin_prefix + "strip --strip-debug --strip-unneeded {0}".format(target[0]))
+ else:
+ os.system("strip --strip-debug --strip-unneeded {0}".format(target[0]))
+ if try_cmd("objcopy --version", env["mingw_prefix"], env["arch"]):
+ os.system(mingw_bin_prefix + "objcopy --add-gnu-debuglink={0}.debugsymbols {0}".format(target[0]))
+ else:
+ os.system("objcopy --add-gnu-debuglink={0}.debugsymbols {0}".format(target[0]))
if __name__ == "__main__":
diff --git a/platform/windows/tts_windows.cpp b/platform/windows/tts_windows.cpp
index 907096d890..11d63d85ee 100644
--- a/platform/windows/tts_windows.cpp
+++ b/platform/windows/tts_windows.cpp
@@ -114,7 +114,7 @@ void TTS_Windows::_update_tts() {
}
bool TTS_Windows::is_speaking() const {
- ERR_FAIL_COND_V(!synth, false);
+ ERR_FAIL_NULL_V(synth, false);
SPVOICESTATUS status;
synth->GetStatus(&status, nullptr);
@@ -122,7 +122,7 @@ bool TTS_Windows::is_speaking() const {
}
bool TTS_Windows::is_paused() const {
- ERR_FAIL_COND_V(!synth, false);
+ ERR_FAIL_NULL_V(synth, false);
return paused;
}
@@ -185,7 +185,7 @@ Array TTS_Windows::get_voices() const {
}
void TTS_Windows::speak(const String &p_text, const String &p_voice, int p_volume, float p_pitch, float p_rate, int p_utterance_id, bool p_interrupt) {
- ERR_FAIL_COND(!synth);
+ ERR_FAIL_NULL(synth);
if (p_interrupt) {
stop();
}
@@ -212,7 +212,7 @@ void TTS_Windows::speak(const String &p_text, const String &p_voice, int p_volum
}
void TTS_Windows::pause() {
- ERR_FAIL_COND(!synth);
+ ERR_FAIL_NULL(synth);
if (!paused) {
if (synth->Pause() == S_OK) {
paused = true;
@@ -221,13 +221,13 @@ void TTS_Windows::pause() {
}
void TTS_Windows::resume() {
- ERR_FAIL_COND(!synth);
+ ERR_FAIL_NULL(synth);
synth->Resume();
paused = false;
}
void TTS_Windows::stop() {
- ERR_FAIL_COND(!synth);
+ ERR_FAIL_NULL(synth);
SPVOICESTATUS status;
synth->GetStatus(&status, nullptr);
diff --git a/platform/windows/wgl_detect_version.cpp b/platform/windows/wgl_detect_version.cpp
new file mode 100644
index 0000000000..264cd525c5
--- /dev/null
+++ b/platform/windows/wgl_detect_version.cpp
@@ -0,0 +1,189 @@
+/**************************************************************************/
+/* wgl_detect_version.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#if defined(WINDOWS_ENABLED) && defined(GLES3_ENABLED)
+
+#include "wgl_detect_version.h"
+#include "os_windows.h"
+
+#include "core/string/print_string.h"
+#include "core/string/ustring.h"
+
+#include <windows.h>
+
+#include <dwmapi.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define WGL_CONTEXT_FLAGS_ARB 0x2094
+#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
+#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
+#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define WGL_VENDOR 0x1F00
+#define WGL_RENDERER 0x1F01
+#define WGL_VERSION 0x1F02
+
+#if defined(__GNUC__)
+// Workaround GCC warning from -Wcast-function-type.
+#define GetProcAddress (void *)GetProcAddress
+#endif
+
+typedef HGLRC(APIENTRY *PFNWGLCREATECONTEXT)(HDC);
+typedef BOOL(APIENTRY *PFNWGLDELETECONTEXT)(HGLRC);
+typedef BOOL(APIENTRY *PFNWGLMAKECURRENT)(HDC, HGLRC);
+typedef HGLRC(APIENTRY *PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC, HGLRC, const int *);
+typedef void *(APIENTRY *PFNWGLGETPROCADDRESS)(LPCSTR);
+typedef const char *(APIENTRY *PFNWGLGETSTRINGPROC)(unsigned int);
+
+int detect_wgl_version() {
+ int major = 0;
+ int minor = 0;
+
+ PFNWGLCREATECONTEXT gd_wglCreateContext;
+ PFNWGLMAKECURRENT gd_wglMakeCurrent;
+ PFNWGLDELETECONTEXT gd_wglDeleteContext;
+ PFNWGLGETPROCADDRESS gd_wglGetProcAddress;
+
+ HMODULE module = LoadLibraryW(L"opengl32.dll");
+ if (!module) {
+ return 0;
+ }
+ gd_wglCreateContext = (PFNWGLCREATECONTEXT)GetProcAddress(module, "wglCreateContext");
+ gd_wglMakeCurrent = (PFNWGLMAKECURRENT)GetProcAddress(module, "wglMakeCurrent");
+ gd_wglDeleteContext = (PFNWGLDELETECONTEXT)GetProcAddress(module, "wglDeleteContext");
+ gd_wglGetProcAddress = (PFNWGLGETPROCADDRESS)GetProcAddress(module, "wglGetProcAddress");
+ if (!gd_wglCreateContext || !gd_wglMakeCurrent || !gd_wglDeleteContext || !gd_wglGetProcAddress) {
+ return 0;
+ }
+
+ LPCWSTR class_name = L"EngineWGLDetect";
+ HINSTANCE hInstance = static_cast<OS_Windows *>(OS::get_singleton())->get_hinstance();
+ WNDCLASSW wc = {};
+
+ wc.lpfnWndProc = DefWindowProcW;
+ wc.hInstance = hInstance;
+ wc.lpszClassName = class_name;
+
+ RegisterClassW(&wc);
+
+ HWND hWnd = CreateWindowExW(WS_EX_APPWINDOW, class_name, L"", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, hInstance, nullptr);
+ if (hWnd) {
+ HDC hDC = GetDC(hWnd);
+ if (hDC) {
+ static PIXELFORMATDESCRIPTOR pfd = {
+ sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
+ 1,
+ PFD_DRAW_TO_WINDOW | // Format Must Support Window
+ PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
+ PFD_DOUBLEBUFFER,
+ (BYTE)PFD_TYPE_RGBA,
+ (BYTE)(OS::get_singleton()->is_layered_allowed() ? 32 : 24),
+ (BYTE)0, (BYTE)0, (BYTE)0, (BYTE)0, (BYTE)0, (BYTE)0, // Color Bits Ignored
+ (BYTE)(OS::get_singleton()->is_layered_allowed() ? 8 : 0), // Alpha Buffer
+ (BYTE)0, // Shift Bit Ignored
+ (BYTE)0, // No Accumulation Buffer
+ (BYTE)0, (BYTE)0, (BYTE)0, (BYTE)0, // Accumulation Bits Ignored
+ (BYTE)24, // 24Bit Z-Buffer (Depth Buffer)
+ (BYTE)0, // No Stencil Buffer
+ (BYTE)0, // No Auxiliary Buffer
+ (BYTE)PFD_MAIN_PLANE, // Main Drawing Layer
+ (BYTE)0, // Reserved
+ 0, 0, 0 // Layer Masks Ignored
+ };
+
+ int pixel_format = ChoosePixelFormat(hDC, &pfd);
+ SetPixelFormat(hDC, pixel_format, &pfd);
+
+ HGLRC hRC = gd_wglCreateContext(hDC);
+ if (hRC) {
+ if (gd_wglMakeCurrent(hDC, hRC)) {
+ int attribs[] = {
+ WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
+ WGL_CONTEXT_MINOR_VERSION_ARB, 3,
+ WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
+ WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
+ 0
+ };
+
+ PFNWGLCREATECONTEXTATTRIBSARBPROC gd_wglCreateContextAttribsARB = nullptr;
+ gd_wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)gd_wglGetProcAddress("wglCreateContextAttribsARB");
+ if (gd_wglCreateContextAttribsARB) {
+ HGLRC new_hRC = gd_wglCreateContextAttribsARB(hDC, 0, attribs);
+ if (new_hRC) {
+ if (gd_wglMakeCurrent(hDC, new_hRC)) {
+ PFNWGLGETSTRINGPROC gd_wglGetString = (PFNWGLGETSTRINGPROC)GetProcAddress(module, "glGetString");
+ if (gd_wglGetString) {
+ const char *prefixes[] = {
+ "OpenGL ES-CM ",
+ "OpenGL ES-CL ",
+ "OpenGL ES ",
+ "OpenGL SC ",
+ nullptr
+ };
+ const char *version = (const char *)gd_wglGetString(WGL_VERSION);
+ if (version) {
+ const String device_vendor = String::utf8((const char *)gd_wglGetString(WGL_VENDOR)).strip_edges();
+ const String device_name = String::utf8((const char *)gd_wglGetString(WGL_RENDERER)).strip_edges();
+ for (int i = 0; prefixes[i]; i++) {
+ size_t length = strlen(prefixes[i]);
+ if (strncmp(version, prefixes[i], length) == 0) {
+ version += length;
+ break;
+ }
+ }
+#ifdef _MSC_VER
+ sscanf_s(version, "%d.%d", &major, &minor);
+#else
+ sscanf(version, "%d.%d", &major, &minor);
+#endif
+ print_verbose(vformat("Native OpenGL API detected: %d.%d: %s - %s", major, minor, device_vendor, device_name));
+ }
+ }
+ }
+ gd_wglMakeCurrent(nullptr, nullptr);
+ gd_wglDeleteContext(new_hRC);
+ }
+ }
+ }
+ gd_wglMakeCurrent(nullptr, nullptr);
+ gd_wglDeleteContext(hRC);
+ }
+ ReleaseDC(hWnd, hDC);
+ }
+ DestroyWindow(hWnd);
+ }
+ UnregisterClassW(class_name, hInstance);
+
+ return major * 10000 + minor;
+}
+
+#endif // WINDOWS_ENABLED && GLES3_ENABLED
diff --git a/platform/windows/wgl_detect_version.h b/platform/windows/wgl_detect_version.h
new file mode 100644
index 0000000000..0be2923ba3
--- /dev/null
+++ b/platform/windows/wgl_detect_version.h
@@ -0,0 +1,40 @@
+/**************************************************************************/
+/* wgl_detect_version.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef WGL_DETECT_VERSION_H
+#define WGL_DETECT_VERSION_H
+
+#if defined(WINDOWS_ENABLED) && defined(GLES3_ENABLED)
+
+int detect_wgl_version();
+
+#endif // WINDOWS_ENABLED && GLES3_ENABLED
+
+#endif // WGL_DETECT_VERSION_H
diff --git a/platform/windows/windows_terminal_logger.cpp b/platform/windows/windows_terminal_logger.cpp
index bb223628a8..6881a75596 100644
--- a/platform/windows/windows_terminal_logger.cpp
+++ b/platform/windows/windows_terminal_logger.cpp
@@ -81,12 +81,9 @@ void WindowsTerminalLogger::log_error(const char *p_function, const char *p_file
return;
}
-#ifndef UWP_ENABLED
HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
if (!hCon || hCon == INVALID_HANDLE_VALUE) {
-#endif
StdLogger::log_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
-#ifndef UWP_ENABLED
} else {
CONSOLE_SCREEN_BUFFER_INFO sbi; //original
GetConsoleScreenBufferInfo(hCon, &sbi);
@@ -159,7 +156,6 @@ void WindowsTerminalLogger::log_error(const char *p_function, const char *p_file
SetConsoleTextAttribute(hCon, sbi.wAttributes);
}
-#endif
}
WindowsTerminalLogger::~WindowsTerminalLogger() {}