summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
Diffstat (limited to 'platform')
-rw-r--r--platform/android/export/export_plugin.cpp8
-rw-r--r--platform/android/java/editor/src/main/AndroidManifest.xml8
-rw-r--r--platform/android/java/editor/src/main/res/values/themes.xml5
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java2
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java30
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginInfoProvider.java6
-rw-r--r--platform/android/plugin/godot_plugin_jni.cpp18
-rw-r--r--platform/android/plugin/godot_plugin_jni.h2
-rw-r--r--platform/ios/display_server_ios.h2
-rw-r--r--platform/ios/display_server_ios.mm50
-rw-r--r--platform/ios/export/export_plugin.cpp2
-rw-r--r--platform/ios/keyboard_input_view.mm36
-rw-r--r--platform/ios/os_ios.h2
-rw-r--r--platform/ios/os_ios.mm45
-rw-r--r--platform/linuxbsd/tts_linux.cpp11
-rw-r--r--platform/linuxbsd/x11/display_server_x11.cpp36
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c2
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h2
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c4
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h4
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c2
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h2
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c2
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h2
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c2
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h2
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c2
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h2
-rw-r--r--platform/macos/export/plist.cpp290
-rw-r--r--platform/macos/export/plist.h25
-rw-r--r--platform/macos/os_macos.mm56
-rw-r--r--platform/web/export/export_plugin.cpp2
-rw-r--r--platform/web/js/engine/config.js4
-rw-r--r--platform/web/js/engine/engine.js4
-rw-r--r--platform/windows/export/export_plugin.cpp2
-rw-r--r--platform/windows/os_windows.cpp37
-rw-r--r--platform/windows/platform_windows_builders.py13
37 files changed, 531 insertions, 193 deletions
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index 795a542ed5..3cea8e5c0c 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -205,7 +205,7 @@ static const char *LEGACY_BUILD_SPLASH_IMAGE_EXPORT_PATH = "res/drawable-nodpi-v
static const char *SPLASH_BG_COLOR_PATH = "res/drawable-nodpi/splash_bg_color.png";
static const char *LEGACY_BUILD_SPLASH_BG_COLOR_PATH = "res/drawable-nodpi-v4/splash_bg_color.png";
static const char *SPLASH_CONFIG_PATH = "res://android/build/res/drawable/splash_drawable.xml";
-static const char *GDNATIVE_LIBS_PATH = "res://android/build/libs/gdnativelibs.json";
+static const char *GDEXTENSION_LIBS_PATH = "res://android/build/libs/gdextensionlibs.json";
static const int icon_densities_count = 6;
static const char *launcher_icon_option = PNAME("launcher_icons/main_192x192");
@@ -2509,7 +2509,7 @@ void EditorExportPlatformAndroid::_clear_assets_directory() {
void EditorExportPlatformAndroid::_remove_copied_libs() {
print_verbose("Removing previously installed libraries...");
Error error;
- String libs_json = FileAccess::get_file_as_string(GDNATIVE_LIBS_PATH, &error);
+ String libs_json = FileAccess::get_file_as_string(GDEXTENSION_LIBS_PATH, &error);
if (error || libs_json.is_empty()) {
print_verbose("No previously installed libraries found");
return;
@@ -2525,7 +2525,7 @@ void EditorExportPlatformAndroid::_remove_copied_libs() {
print_verbose("Removing previously installed library " + libs[i]);
da->remove(libs[i]);
}
- da->remove(GDNATIVE_LIBS_PATH);
+ da->remove(GDEXTENSION_LIBS_PATH);
}
String EditorExportPlatformAndroid::join_list(const List<String> &p_parts, const String &p_separator) {
@@ -2661,7 +2661,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
return err;
}
if (user_data.libs.size() > 0) {
- Ref<FileAccess> fa = FileAccess::open(GDNATIVE_LIBS_PATH, FileAccess::WRITE);
+ Ref<FileAccess> fa = FileAccess::open(GDEXTENSION_LIBS_PATH, FileAccess::WRITE);
fa->store_string(JSON::stringify(user_data.libs, "\t"));
}
} else {
diff --git a/platform/android/java/editor/src/main/AndroidManifest.xml b/platform/android/java/editor/src/main/AndroidManifest.xml
index f3ddaafd0e..80ef10b6a4 100644
--- a/platform/android/java/editor/src/main/AndroidManifest.xml
+++ b/platform/android/java/editor/src/main/AndroidManifest.xml
@@ -27,6 +27,7 @@
android:icon="@mipmap/icon"
android:label="@string/godot_editor_name_string"
tools:ignore="GoogleAppIndexingWarning"
+ android:theme="@style/GodotEditorTheme"
android:requestLegacyExternalStorage="true">
<activity
@@ -35,7 +36,6 @@
android:launchMode="singleTask"
android:screenOrientation="userLandscape"
android:exported="true"
- android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
android:process=":GodotProjectManager">
<layout android:defaultHeight="@dimen/editor_default_window_height"
@@ -53,8 +53,7 @@
android:process=":GodotEditor"
android:launchMode="singleTask"
android:screenOrientation="userLandscape"
- android:exported="false"
- android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
+ android:exported="false">
<layout android:defaultHeight="@dimen/editor_default_window_height"
android:defaultWidth="@dimen/editor_default_window_width" />
</activity>
@@ -66,8 +65,7 @@
android:process=":GodotGame"
android:launchMode="singleTask"
android:exported="false"
- android:screenOrientation="userLandscape"
- android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
+ android:screenOrientation="userLandscape">
<layout android:defaultHeight="@dimen/editor_default_window_height"
android:defaultWidth="@dimen/editor_default_window_width" />
</activity>
diff --git a/platform/android/java/editor/src/main/res/values/themes.xml b/platform/android/java/editor/src/main/res/values/themes.xml
new file mode 100644
index 0000000000..fda04d6dc7
--- /dev/null
+++ b/platform/android/java/editor/src/main/res/values/themes.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <style name="GodotEditorTheme" parent="@android:style/Theme.Black.NoTitleBar.Fullscreen">
+ </style>
+</resources>
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 2f26497cc8..0ba86e4316 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
@@ -422,7 +422,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_STYLUS) == InputDevice.SOURCE_STYLUS);
+ boolean mouseSource = ((eventSource & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) || ((eventSource & (InputDevice.SOURCE_TOUCHSCREEN | 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);
}
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 bb5042fa09..8ca5bcaa6e 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
@@ -71,11 +71,11 @@ import javax.microedition.khronos.opengles.GL10;
* - 'plugin.init.ClassFullName' is the full name (package + class name) of the plugin class
* extending {@link GodotPlugin}.
*
- * A plugin can also define and provide c/c++ gdnative libraries and nativescripts for the target
+ * 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 gdnative library will be automatically bundled by the aar build
+ * The shared library for the gdextension library will be automatically bundled by the aar build
* system.
- * Godot '*.gdnlib' and '*.gdns' resource files must however be manually defined in the project
+ * 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]/'
*/
@@ -112,7 +112,7 @@ public abstract class GodotPlugin {
public final void onRegisterPluginWithGodotNative() {
registeredSignals.putAll(
registerPluginWithGodotNative(this, getPluginName(), getPluginMethods(), getPluginSignals(),
- getPluginGDNativeLibrariesPaths()));
+ getPluginGDExtensionLibrariesPaths()));
}
/**
@@ -124,7 +124,7 @@ public abstract class GodotPlugin {
GodotPluginInfoProvider pluginInfoProvider) {
registerPluginWithGodotNative(pluginObject, pluginInfoProvider.getPluginName(),
Collections.emptyList(), pluginInfoProvider.getPluginSignals(),
- pluginInfoProvider.getPluginGDNativeLibrariesPaths());
+ pluginInfoProvider.getPluginGDExtensionLibrariesPaths());
// Notify that registration is complete.
pluginInfoProvider.onPluginRegistered();
@@ -132,7 +132,7 @@ public abstract class GodotPlugin {
private static Map<String, SignalInfo> registerPluginWithGodotNative(Object pluginObject,
String pluginName, List<String> pluginMethods, Set<SignalInfo> pluginSignals,
- Set<String> pluginGDNativeLibrariesPaths) {
+ Set<String> pluginGDExtensionLibrariesPaths) {
nativeRegisterSingleton(pluginName, pluginObject);
Set<Method> filteredMethods = new HashSet<>();
@@ -176,9 +176,9 @@ public abstract class GodotPlugin {
registeredSignals.put(signalName, signalInfo);
}
- // Get the list of gdnative libraries to register.
- if (!pluginGDNativeLibrariesPaths.isEmpty()) {
- nativeRegisterGDNativeLibraries(pluginGDNativeLibrariesPaths.toArray(new String[0]));
+ // Get the list of gdextension libraries to register.
+ if (!pluginGDExtensionLibrariesPaths.isEmpty()) {
+ nativeRegisterGDExtensionLibraries(pluginGDExtensionLibrariesPaths.toArray(new String[0]));
}
return registeredSignals;
@@ -304,12 +304,12 @@ public abstract class GodotPlugin {
}
/**
- * Returns the paths for the plugin's gdnative libraries.
+ * Returns the paths for the plugin's gdextension libraries.
*
- * The paths must be relative to the 'assets' directory and point to a '*.gdnlib' file.
+ * The paths must be relative to the 'assets' directory and point to a '*.gdextension' file.
*/
@NonNull
- protected Set<String> getPluginGDNativeLibrariesPaths() {
+ protected Set<String> getPluginGDExtensionLibrariesPaths() {
return Collections.emptySet();
}
@@ -420,10 +420,10 @@ public abstract class GodotPlugin {
private static native void nativeRegisterMethod(String p_sname, String p_name, String p_ret, String[] p_params);
/**
- * Used to register gdnative libraries bundled by the plugin.
- * @param gdnlibPaths Paths to the libraries relative to the 'assets' directory.
+ * Used to register gdextension libraries bundled by the plugin.
+ * @param gdextensionPaths Paths to the libraries relative to the 'assets' directory.
*/
- private static native void nativeRegisterGDNativeLibraries(String[] gdnlibPaths);
+ private static native void nativeRegisterGDExtensionLibraries(String[] gdextensionPaths);
/**
* Used to complete registration of the {@link GodotPlugin} instance's methods.
diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginInfoProvider.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginInfoProvider.java
index cfb84c3931..53b78aebfb 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginInfoProvider.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginInfoProvider.java
@@ -54,12 +54,12 @@ public interface GodotPluginInfoProvider {
}
/**
- * Returns the paths for the plugin's gdnative libraries (if any).
+ * Returns the paths for the plugin's gdextension libraries (if any).
*
- * The paths must be relative to the 'assets' directory and point to a '*.gdnlib' file.
+ * The paths must be relative to the 'assets' directory and point to a '*.gdextension' file.
*/
@NonNull
- default Set<String> getPluginGDNativeLibrariesPaths() {
+ default Set<String> getPluginGDExtensionLibrariesPaths() {
return Collections.emptySet();
}
diff --git a/platform/android/plugin/godot_plugin_jni.cpp b/platform/android/plugin/godot_plugin_jni.cpp
index 5a7123b833..fe35babba6 100644
--- a/platform/android/plugin/godot_plugin_jni.cpp
+++ b/platform/android/plugin/godot_plugin_jni.cpp
@@ -128,21 +128,21 @@ 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_nativeRegisterGDNativeLibraries(JNIEnv *env, jclass clazz, jobjectArray gdnlib_paths) {
- int gdnlib_count = env->GetArrayLength(gdnlib_paths);
- if (gdnlib_count == 0) {
+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 gdnative libraries.
+ // Retrieve the current list of gdextension libraries.
Array singletons;
- if (ProjectSettings::get_singleton()->has_setting("gdnative/singletons")) {
- singletons = GLOBAL_GET("gdnative/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 < gdnlib_count; i++) {
- jstring relative_path = (jstring)env->GetObjectArrayElement(gdnlib_paths, i);
+ 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)) {
@@ -152,6 +152,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegis
}
// Insert the updated list back into project settings.
- ProjectSettings::get_singleton()->set("gdnative/singletons", singletons);
+ 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 35f9d5b513..e36cc8b0e3 100644
--- a/platform/android/plugin/godot_plugin_jni.h
+++ b/platform/android/plugin/godot_plugin_jni.h
@@ -39,7 +39,7 @@ 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_nativeRegisterGDNativeLibraries(JNIEnv *env, jclass clazz, jobjectArray gdnlib_paths);
+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/ios/display_server_ios.h b/platform/ios/display_server_ios.h
index 4901eeefaf..0ca0d3d1fe 100644
--- a/platform/ios/display_server_ios.h
+++ b/platform/ios/display_server_ios.h
@@ -113,7 +113,7 @@ public:
// MARK: Keyboard
- void key(Key p_key, bool p_pressed);
+ void key(Key p_key, char32_t p_char, bool p_pressed);
// MARK: Motion
diff --git a/platform/ios/display_server_ios.mm b/platform/ios/display_server_ios.mm
index ed1bc499ed..3f4a406116 100644
--- a/platform/ios/display_server_ios.mm
+++ b/platform/ios/display_server_ios.mm
@@ -227,27 +227,23 @@ void DisplayServerIOS::_window_callback(const Callable &p_callable, const Varian
// MARK: Touches
void DisplayServerIOS::touch_press(int p_idx, int p_x, int p_y, bool p_pressed, bool p_double_click) {
- if (!GLOBAL_GET("debug/disable_touch")) {
- Ref<InputEventScreenTouch> ev;
- ev.instantiate();
-
- ev->set_index(p_idx);
- ev->set_pressed(p_pressed);
- ev->set_position(Vector2(p_x, p_y));
- ev->set_double_tap(p_double_click);
- perform_event(ev);
- }
+ Ref<InputEventScreenTouch> ev;
+ ev.instantiate();
+
+ ev->set_index(p_idx);
+ ev->set_pressed(p_pressed);
+ ev->set_position(Vector2(p_x, p_y));
+ ev->set_double_tap(p_double_click);
+ perform_event(ev);
}
void DisplayServerIOS::touch_drag(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y) {
- if (!GLOBAL_GET("debug/disable_touch")) {
- Ref<InputEventScreenDrag> ev;
- ev.instantiate();
- ev->set_index(p_idx);
- ev->set_position(Vector2(p_x, p_y));
- ev->set_relative(Vector2(p_x - p_prev_x, p_y - p_prev_y));
- perform_event(ev);
- }
+ Ref<InputEventScreenDrag> ev;
+ ev.instantiate();
+ ev->set_index(p_idx);
+ ev->set_position(Vector2(p_x, p_y));
+ ev->set_relative(Vector2(p_x - p_prev_x, p_y - p_prev_y));
+ perform_event(ev);
}
void DisplayServerIOS::perform_event(const Ref<InputEvent> &p_event) {
@@ -260,14 +256,14 @@ void DisplayServerIOS::touches_cancelled(int p_idx) {
// MARK: Keyboard
-void DisplayServerIOS::key(Key p_key, bool p_pressed) {
+void DisplayServerIOS::key(Key p_key, char32_t p_char, bool p_pressed) {
Ref<InputEventKey> ev;
ev.instantiate();
ev->set_echo(false);
ev->set_pressed(p_pressed);
ev->set_keycode(p_key);
ev->set_physical_keycode(p_key);
- ev->set_unicode((char32_t)p_key);
+ ev->set_unicode(p_char);
perform_event(ev);
}
@@ -589,6 +585,16 @@ bool DisplayServerIOS::is_touchscreen_available() const {
return true;
}
+_FORCE_INLINE_ int _convert_utf32_offset_to_utf16(const String &p_existing_text, int p_pos) {
+ int limit = p_pos;
+ for (int i = 0; i < MIN(p_existing_text.length(), p_pos); i++) {
+ if (p_existing_text[i] > 0xffff) {
+ limit++;
+ }
+ }
+ return limit;
+}
+
void DisplayServerIOS::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_length, int p_cursor_start, int p_cursor_end) {
NSString *existingString = [[NSString alloc] initWithUTF8String:p_existing_text.utf8().get_data()];
@@ -627,8 +633,8 @@ void DisplayServerIOS::virtual_keyboard_show(const String &p_existing_text, cons
[AppDelegate.viewController.keyboardView
becomeFirstResponderWithString:existingString
- cursorStart:p_cursor_start
- cursorEnd:p_cursor_end];
+ cursorStart:_convert_utf32_offset_to_utf16(p_existing_text, p_cursor_start)
+ cursorEnd:_convert_utf32_offset_to_utf16(p_existing_text, p_cursor_end)];
}
void DisplayServerIOS::virtual_keyboard_hide() {
diff --git a/platform/ios/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp
index 33f1071077..ea37278309 100644
--- a/platform/ios/export/export_plugin.cpp
+++ b/platform/ios/export/export_plugin.cpp
@@ -1134,7 +1134,7 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String
"<key>CFBundleShortVersionString</key>\n"
"<string>1.0</string>\n"
"<key>CFBundleIdentifier</key>\n"
- "<string>com.gdnative.framework.$name</string>\n"
+ "<string>com.gdextension.framework.$name</string>\n"
"<key>CFBundleName</key>\n"
"<string>$name</string>\n"
"<key>CFBundleExecutable</key>\n"
diff --git a/platform/ios/keyboard_input_view.mm b/platform/ios/keyboard_input_view.mm
index f031a1de22..8fb5656c24 100644
--- a/platform/ios/keyboard_input_view.mm
+++ b/platform/ios/keyboard_input_view.mm
@@ -115,8 +115,8 @@
- (void)deleteText:(NSInteger)charactersToDelete {
for (int i = 0; i < charactersToDelete; i++) {
- DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, true);
- DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, false);
+ DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, 0, true);
+ DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, 0, false);
}
}
@@ -126,20 +126,28 @@
for (int i = 0; i < characters.size(); i++) {
int character = characters[i];
-
- switch (character) {
- case 10:
- character = (int)Key::ENTER;
- break;
- case 8198:
- character = (int)Key::SPACE;
- break;
- default:
- break;
+ Key key = Key::NONE;
+
+ if (character == '\t') { // 0x09
+ key = Key::TAB;
+ } else if (character == '\n') { // 0x0A
+ key = Key::ENTER;
+ } else if (character == 0x2006) {
+ key = Key::SPACE;
+ } else if (character == U'¥') {
+ key = Key::YEN;
+ } else if (character == U'§') {
+ key = Key::SECTION;
+ } else if (character >= 0x20 && character <= 0x7E) { // ASCII.
+ if (character > 0x60 && character < 0x7B) { // Lowercase ASCII.
+ key = (Key)(character - 32);
+ } else {
+ key = (Key)character;
+ }
}
- DisplayServerIOS::get_singleton()->key((Key)character, true);
- DisplayServerIOS::get_singleton()->key((Key)character, false);
+ DisplayServerIOS::get_singleton()->key(key, character, true);
+ DisplayServerIOS::get_singleton()->key(key, character, false);
}
}
diff --git a/platform/ios/os_ios.h b/platform/ios/os_ios.h
index 186efd14a8..3589dd17c9 100644
--- a/platform/ios/os_ios.h
+++ b/platform/ios/os_ios.h
@@ -77,6 +77,8 @@ private:
CGFloat _stretch_to_ct(int p_stretch) const;
String _get_default_fontname(const String &p_font_name) const;
+ static _FORCE_INLINE_ String get_framework_executable(const String &p_path);
+
void deinitialize_modules();
public:
diff --git a/platform/ios/os_ios.mm b/platform/ios/os_ios.mm
index 9617627b6f..d0c367cc45 100644
--- a/platform/ios/os_ios.mm
+++ b/platform/ios/os_ios.mm
@@ -198,8 +198,31 @@ void OS_IOS::finalize() {
// MARK: Dynamic Libraries
+_FORCE_INLINE_ String OS_IOS::get_framework_executable(const String &p_path) {
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+
+ // Read framework bundle to get executable name.
+ NSURL *url = [NSURL fileURLWithPath:@(p_path.utf8().get_data())];
+ NSBundle *bundle = [NSBundle bundleWithURL:url];
+ if (bundle) {
+ String exe_path = String::utf8([[bundle executablePath] UTF8String]);
+ if (da->file_exists(exe_path)) {
+ return exe_path;
+ }
+ }
+
+ // Try default executable name (invalid framework).
+ if (da->dir_exists(p_path) && da->file_exists(p_path.path_join(p_path.get_file().get_basename()))) {
+ return p_path.path_join(p_path.get_file().get_basename());
+ }
+
+ // Not a framework, try loading as .dylib.
+ return p_path;
+}
+
Error OS_IOS::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) {
if (p_path.length() == 0) {
+ // Static xcframework.
p_library_handle = RTLD_SELF;
if (r_resolved_path != nullptr) {
@@ -208,7 +231,27 @@ Error OS_IOS::open_dynamic_library(const String p_path, void *&p_library_handle,
return OK;
}
- return OS_Unix::open_dynamic_library(p_path, p_library_handle, p_also_set_library_path, r_resolved_path);
+
+ String path = get_framework_executable(p_path);
+
+ if (!FileAccess::exists(path)) {
+ // Load .dylib or framework from within the executable path.
+ path = get_framework_executable(get_executable_path().get_base_dir().path_join(p_path.get_file()));
+ }
+
+ if (!FileAccess::exists(path)) {
+ // Load .dylib or framework from a standard iOS location.
+ path = get_framework_executable(get_executable_path().get_base_dir().path_join("Frameworks").path_join(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, "Can't open dynamic library: " + p_path + ", error: " + dlerror() + ".");
+
+ if (r_resolved_path != nullptr) {
+ *r_resolved_path = path;
+ }
+
+ return OK;
}
Error OS_IOS::close_dynamic_library(void *p_library_handle) {
diff --git a/platform/linuxbsd/tts_linux.cpp b/platform/linuxbsd/tts_linux.cpp
index aea1183d3d..8fa708aad6 100644
--- a/platform/linuxbsd/tts_linux.cpp
+++ b/platform/linuxbsd/tts_linux.cpp
@@ -117,13 +117,12 @@ void TTS_Linux::speech_event_callback(size_t p_msg_id, size_t p_client_id, SPDNo
free_spd_voices(voices);
}
PackedInt32Array breaks = TS->string_get_word_breaks(message.text, language);
- int prev = 0;
- for (int i = 0; i < breaks.size(); i++) {
- text += message.text.substr(prev, breaks[i] - prev);
- text += "<mark name=\"" + String::num_int64(breaks[i], 10) + "\"/>";
- prev = breaks[i];
+ for (int i = 0; i < breaks.size(); i += 2) {
+ const int start = breaks[i];
+ const int end = breaks[i + 1];
+ text += message.text.substr(start, end - start + 1);
+ text += "<mark name=\"" + String::num_int64(end, 10) + "\"/>";
}
- text += message.text.substr(prev, -1);
spd_set_synthesis_voice(tts->synth, message.voice.utf8().get_data());
spd_set_volume(tts->synth, message.volume * 2 - 100);
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index 1c5c8b2d19..57f125a754 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -3985,29 +3985,41 @@ void DisplayServerX11::process_events() {
} else {
DEBUG_LOG_X11("[%u] ButtonRelease window=%lu (%u), button_index=%u \n", frame, event.xbutton.window, window_id, mb->get_button_index());
- if (!wd.focused) {
+ WindowID window_id_other = INVALID_WINDOW_ID;
+ Window wd_other_x11_window;
+ if (wd.focused) {
+ // Handle cases where an unfocused popup is open that needs to receive button-up events.
+ WindowID popup_id = _get_focused_window_or_popup();
+ if (popup_id != INVALID_WINDOW_ID && popup_id != window_id) {
+ window_id_other = popup_id;
+ wd_other_x11_window = windows[popup_id].x11_window;
+ }
+ } else {
// Propagate the event to the focused window,
// because it's received only on the topmost window.
// Note: This is needed for drag & drop to work between windows,
// because the engine expects events to keep being processed
// on the same window dragging started.
for (const KeyValue<WindowID, WindowData> &E : windows) {
- const WindowData &wd_other = E.value;
- WindowID window_id_other = E.key;
- if (wd_other.focused) {
- if (window_id_other != window_id) {
- int x, y;
- Window child;
- XTranslateCoordinates(x11_display, wd.x11_window, wd_other.x11_window, event.xbutton.x, event.xbutton.y, &x, &y, &child);
-
- mb->set_window_id(window_id_other);
- mb->set_position(Vector2(x, y));
- mb->set_global_position(mb->get_position());
+ if (E.value.focused) {
+ if (E.key != window_id) {
+ window_id_other = E.key;
+ wd_other_x11_window = E.value.x11_window;
}
break;
}
}
}
+
+ if (window_id_other != INVALID_WINDOW_ID) {
+ int x, y;
+ Window child;
+ XTranslateCoordinates(x11_display, wd.x11_window, wd_other_x11_window, event.xbutton.x, event.xbutton.y, &x, &y, &child);
+
+ mb->set_window_id(window_id_other);
+ mb->set_position(Vector2(x, y));
+ mb->set_global_position(mb->get_position());
+ }
}
Input::get_singleton()->parse_input_event(mb);
diff --git a/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c
index d689ff1aa8..7042a60d47 100644
--- a/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c
+++ b/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c
@@ -5,7 +5,7 @@
//
// NOTE: Generated from Xcursor 1.2.0.
// This has been handpatched to workaround some issues with the generator that
-// will be eventually fixed. In this case, non-existant symbols inherited from
+// will be eventually fixed. In this case, non-existent symbols inherited from
// libX11, but absent in libXcursor.so.1, were removed.
#include <stdint.h>
diff --git a/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h
index 43bbcf62c5..d00fccffda 100644
--- a/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h
+++ b/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h
@@ -7,7 +7,7 @@
//
// NOTE: Generated from Xcursor 1.2.0.
// This has been handpatched to workaround some issues with the generator that
-// will be eventually fixed. In this case, non-existant symbols inherited from
+// will be eventually fixed. In this case, non-existent symbols inherited from
// libX11, but absent in libXcursor.so.1, were removed.
#include <stdint.h>
diff --git a/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c
index 711dd3fa5e..c8e87a6b85 100644
--- a/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c
+++ b/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c
@@ -5,10 +5,10 @@
//
// NOTE: Generated from Xext 1.3.5.
// This has been handpatched to workaround some issues with the generator that
-// will be eventually fixed. In this case, non-existant symbols inherited from
+// will be eventually fixed. In this case, non-existent symbols inherited from
// libX11, but absent in libXext.so.6, were removed and an include needed for
// proper parsing was added (this had also to be temporarily added to the
-// original header, as dynload-wrapper would complain otherwsise)
+// original header, as dynload-wrapper would complain otherwise)
#include <stdint.h>
// HANDPATCH: Needed for a successful compilation.
diff --git a/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h
index 991d07b405..aee92b593e 100644
--- a/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h
+++ b/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h
@@ -7,10 +7,10 @@
//
// NOTE: Generated from Xext 1.3.5.
// This has been handpatched to workaround some issues with the generator that
-// will be eventually fixed. In this case, non-existant symbols inherited from
+// will be eventually fixed. In this case, non-existent symbols inherited from
// libX11, but absent in libXext.so.6, were removed and an include needed for
// proper parsing was added (this had also to be temporarily added to the
-// original header, as dynload-wrapper would complain otherwsise)
+// original header, as dynload-wrapper would complain otherwise)
#include <stdint.h>
// HANDPATCH: Needed for a successful compilation.
diff --git a/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c
index 42af983345..85ac80e3f2 100644
--- a/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c
+++ b/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c
@@ -5,7 +5,7 @@
//
// NOTE: Generated from Xinerama 1.1.4.
// This has been handpatched to workaround some issues with the generator that
-// will be eventually fixed. In this case, non-existant symbols inherited from
+// will be eventually fixed. In this case, non-existent symbols inherited from
// libX11, but absent in libXinerama.so.1, were removed.
#include <stdint.h>
diff --git a/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h
index 891d9f21fd..9139421cd6 100644
--- a/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h
+++ b/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h
@@ -7,7 +7,7 @@
//
// NOTE: Generated from Xinerama 1.1.4.
// This has been handpatched to workaround some issues with the generator that
-// will be eventually fixed. In this case, non-existant symbols inherited from
+// will be eventually fixed. In this case, non-existent symbols inherited from
// libX11, but absent in libXinerama.so.1, were removed.
#include <stdint.h>
diff --git a/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c
index 5e1f0999fc..5f16bc6111 100644
--- a/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c
+++ b/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c
@@ -5,7 +5,7 @@
//
// NOTE: Generated from Xi 1.7.10.
// This has been handpatched to workaround some issues with the generator that
-// will be eventually fixed. In this case, non-existant symbols inherited from
+// will be eventually fixed. In this case, non-existent symbols inherited from
// libX11, liXext and libXfixes, but absent in libXi.so.6, were removed.
#include <stdint.h>
diff --git a/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h
index 95740cee58..ecb7aa5048 100644
--- a/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h
+++ b/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h
@@ -7,7 +7,7 @@
//
// NOTE: Generated from Xi 1.7.10.
// This has been handpatched to workaround some issues with the generator that
-// will be eventually fixed. In this case, non-existant symbols inherited from
+// will be eventually fixed. In this case, non-existent symbols inherited from
// libX11, liXext and libXfixes, but absent in libXi.so.6, were removed.
#include <stdint.h>
diff --git a/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c
index eb0f9abf15..f37f3a9db0 100644
--- a/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c
+++ b/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c
@@ -5,7 +5,7 @@
//
// NOTE: Generated from Xrandr 1.5.2.
// This has been handpatched to workaround some issues with the generator that
-// will be eventually fixed. In this case, non-existant symbols inherited from
+// will be eventually fixed. In this case, non-existent symbols inherited from
// libX11 and libXrender, but absent in libXrandr.so.2, were removed.
#include <stdint.h>
diff --git a/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h
index f1ca9f94a5..046d4c7de3 100644
--- a/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h
+++ b/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h
@@ -7,7 +7,7 @@
//
// NOTE: Generated from Xrandr 1.5.2.
// This has been handpatched to workaround some issues with the generator that
-// will be eventually fixed. In this case, non-existant symbols inherited from
+// will be eventually fixed. In this case, non-existent symbols inherited from
// libX11 and libXrender, but absent in libXrandr.so.2, were removed.
#include <stdint.h>
diff --git a/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c
index b63a1eca8d..2d3847e584 100644
--- a/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c
+++ b/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c
@@ -5,7 +5,7 @@
//
// NOTE: Generated from Xrender 0.9.10.
// This has been handpatched to workaround some issues with the generator that
-// will be eventually fixed. In this case, non-existant symbols inherited from
+// will be eventually fixed. In this case, non-existent symbols inherited from
// libX11, but absent in libXrender.so.1, were removed.
#include <stdint.h>
diff --git a/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h
index d3862ed459..e873448ec5 100644
--- a/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h
+++ b/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h
@@ -7,7 +7,7 @@
//
// NOTE: Generated from Xrender 0.9.10.
// This has been handpatched to workaround some issues with the generator that
-// will be eventually fixed. In this case, non-existant symbols inherited from
+// will be eventually fixed. In this case, non-existent symbols inherited from
// libX11, but absent in libXrender.so.1, were removed.
#include <stdint.h>
diff --git a/platform/macos/export/plist.cpp b/platform/macos/export/plist.cpp
index 82ecd41d9c..c88b6e1077 100644
--- a/platform/macos/export/plist.cpp
+++ b/platform/macos/export/plist.cpp
@@ -30,6 +30,119 @@
#include "plist.h"
+PList::PLNodeType PListNode::get_type() const {
+ return data_type;
+}
+
+Variant PListNode::get_value() const {
+ switch (data_type) {
+ case PList::PL_NODE_TYPE_NIL: {
+ return Variant();
+ } break;
+ case PList::PL_NODE_TYPE_STRING: {
+ return String::utf8(data_string.get_data());
+ } break;
+ case PList::PL_NODE_TYPE_ARRAY: {
+ Array arr;
+ for (const Ref<PListNode> &E : data_array) {
+ arr.push_back(E);
+ }
+ return arr;
+ } break;
+ case PList::PL_NODE_TYPE_DICT: {
+ Dictionary dict;
+ for (const KeyValue<String, Ref<PListNode>> &E : data_dict) {
+ dict[E.key] = E.value;
+ }
+ return dict;
+ } break;
+ case PList::PL_NODE_TYPE_BOOLEAN: {
+ return data_bool;
+ } break;
+ case PList::PL_NODE_TYPE_INTEGER: {
+ return data_int;
+ } break;
+ case PList::PL_NODE_TYPE_REAL: {
+ return data_real;
+ } break;
+ case PList::PL_NODE_TYPE_DATA: {
+ int strlen = data_string.length();
+
+ size_t arr_len = 0;
+ Vector<uint8_t> buf;
+ {
+ buf.resize(strlen / 4 * 3 + 1);
+ uint8_t *w = buf.ptrw();
+
+ ERR_FAIL_COND_V(CryptoCore::b64_decode(&w[0], buf.size(), &arr_len, (unsigned char *)data_string.get_data(), strlen) != OK, Vector<uint8_t>());
+ }
+ buf.resize(arr_len);
+ return buf;
+ } break;
+ case PList::PL_NODE_TYPE_DATE: {
+ return String(data_string.get_data());
+ } break;
+ }
+ return Variant();
+}
+
+Ref<PListNode> PListNode::new_node(const Variant &p_value) {
+ Ref<PListNode> node;
+ node.instantiate();
+
+ switch (p_value.get_type()) {
+ case Variant::NIL: {
+ node->data_type = PList::PL_NODE_TYPE_NIL;
+ } break;
+ case Variant::BOOL: {
+ node->data_type = PList::PL_NODE_TYPE_BOOLEAN;
+ node->data_bool = p_value;
+ } break;
+ case Variant::INT: {
+ node->data_type = PList::PL_NODE_TYPE_INTEGER;
+ node->data_int = p_value;
+ } break;
+ case Variant::FLOAT: {
+ node->data_type = PList::PL_NODE_TYPE_REAL;
+ node->data_real = p_value;
+ } break;
+ case Variant::STRING_NAME:
+ case Variant::STRING: {
+ node->data_type = PList::PL_NODE_TYPE_STRING;
+ node->data_string = p_value.operator String().utf8();
+ } break;
+ case Variant::DICTIONARY: {
+ node->data_type = PList::PL_NODE_TYPE_DICT;
+ Dictionary dict = p_value;
+ const Variant *next = dict.next(nullptr);
+ while (next) {
+ Ref<PListNode> sub_node = dict[*next];
+ ERR_FAIL_COND_V_MSG(sub_node.is_null(), Ref<PListNode>(), "Invalid dictionary element, should be PListNode.");
+ node->data_dict[*next] = sub_node;
+ next = dict.next(next);
+ }
+ } break;
+ case Variant::ARRAY: {
+ node->data_type = PList::PL_NODE_TYPE_ARRAY;
+ Array ar = p_value;
+ for (int i = 0; i < ar.size(); i++) {
+ Ref<PListNode> sub_node = ar[i];
+ ERR_FAIL_COND_V_MSG(sub_node.is_null(), Ref<PListNode>(), "Invalid array element, should be PListNode.");
+ node->data_array.push_back(sub_node);
+ }
+ } break;
+ case Variant::PACKED_BYTE_ARRAY: {
+ node->data_type = PList::PL_NODE_TYPE_DATA;
+ PackedByteArray buf = p_value;
+ node->data_string = CryptoCore::b64_encode_str(buf.ptr(), buf.size()).utf8();
+ } break;
+ default: {
+ ERR_FAIL_V_MSG(Ref<PListNode>(), "Unsupported data type.");
+ } break;
+ }
+ return node;
+}
+
Ref<PListNode> PListNode::new_array() {
Ref<PListNode> node = memnew(PListNode());
ERR_FAIL_COND_V(node.is_null(), Ref<PListNode>());
@@ -65,6 +178,7 @@ Ref<PListNode> PListNode::new_date(const String &p_string) {
ERR_FAIL_COND_V(node.is_null(), Ref<PListNode>());
node->data_type = PList::PLNodeType::PL_NODE_TYPE_DATE;
node->data_string = p_string.utf8();
+ node->data_real = (double)Time::get_singleton()->get_unix_time_from_datetime_string(p_string) - 978307200.0;
return node;
}
@@ -76,7 +190,7 @@ Ref<PListNode> PListNode::new_bool(bool p_bool) {
return node;
}
-Ref<PListNode> PListNode::new_int(int32_t p_int) {
+Ref<PListNode> PListNode::new_int(int64_t p_int) {
Ref<PListNode> node = memnew(PListNode());
ERR_FAIL_COND_V(node.is_null(), Ref<PListNode>());
node->data_type = PList::PLNodeType::PL_NODE_TYPE_INTEGER;
@@ -84,7 +198,7 @@ Ref<PListNode> PListNode::new_int(int32_t p_int) {
return node;
}
-Ref<PListNode> PListNode::new_real(float p_real) {
+Ref<PListNode> PListNode::new_real(double p_real) {
Ref<PListNode> node = memnew(PListNode());
ERR_FAIL_COND_V(node.is_null(), Ref<PListNode>());
node->data_type = PList::PLNodeType::PL_NODE_TYPE_REAL;
@@ -337,6 +451,168 @@ PList::PList(const String &p_string) {
load_string(p_string);
}
+uint64_t PList::read_bplist_var_size_int(Ref<FileAccess> p_file, uint8_t p_size) {
+ uint64_t pos = p_file->get_position();
+ uint64_t ret = 0;
+ switch (p_size) {
+ case 1: {
+ ret = p_file->get_8();
+ } break;
+ case 2: {
+ ret = BSWAP16(p_file->get_16());
+ } break;
+ case 3: {
+ ret = BSWAP32(p_file->get_32() & 0x00FFFFFF);
+ } break;
+ case 4: {
+ ret = BSWAP32(p_file->get_32());
+ } break;
+ case 5: {
+ ret = BSWAP64(p_file->get_64() & 0x000000FFFFFFFFFF);
+ } break;
+ case 6: {
+ ret = BSWAP64(p_file->get_64() & 0x0000FFFFFFFFFFFF);
+ } break;
+ case 7: {
+ ret = BSWAP64(p_file->get_64() & 0x00FFFFFFFFFFFFFF);
+ } break;
+ case 8: {
+ ret = BSWAP64(p_file->get_64());
+ } break;
+ default: {
+ ret = 0;
+ }
+ }
+ p_file->seek(pos + p_size);
+
+ return ret;
+}
+
+Ref<PListNode> PList::read_bplist_obj(Ref<FileAccess> p_file, uint64_t p_offset_idx) {
+ Ref<PListNode> node;
+ node.instantiate();
+
+ uint64_t ot_off = trailer.offset_table_start + p_offset_idx * trailer.offset_size;
+ p_file->seek(ot_off);
+ uint64_t marker_off = read_bplist_var_size_int(p_file, trailer.offset_size);
+ ERR_FAIL_COND_V_MSG(marker_off == 0, Ref<PListNode>(), "Invalid marker size.");
+
+ p_file->seek(marker_off);
+ uint8_t marker = p_file->get_8();
+ uint8_t marker_type = marker & 0xF0;
+ uint64_t marker_size = marker & 0x0F;
+
+ switch (marker_type) {
+ case 0x00: {
+ if (marker_size == 0x00) {
+ node->data_type = PL_NODE_TYPE_NIL;
+ } else if (marker_size == 0x08) {
+ node->data_type = PL_NODE_TYPE_BOOLEAN;
+ node->data_bool = false;
+ } else if (marker_size == 0x09) {
+ node->data_type = PL_NODE_TYPE_BOOLEAN;
+ node->data_bool = true;
+ } else {
+ ERR_FAIL_V_MSG(Ref<PListNode>(), "Invalid nil/bool marker value.");
+ }
+ } break;
+ case 0x10: {
+ node->data_type = PL_NODE_TYPE_INTEGER;
+ node->data_int = static_cast<int64_t>(read_bplist_var_size_int(p_file, pow(2, marker_size)));
+ } break;
+ case 0x20: {
+ node->data_type = PL_NODE_TYPE_REAL;
+ node->data_int = static_cast<int64_t>(read_bplist_var_size_int(p_file, pow(2, marker_size)));
+ } break;
+ case 0x30: {
+ node->data_type = PL_NODE_TYPE_DATE;
+ node->data_int = BSWAP64(p_file->get_64());
+ node->data_string = Time::get_singleton()->get_datetime_string_from_unix_time(node->data_real + 978307200.0).utf8();
+ } break;
+ case 0x40: {
+ if (marker_size == 0x0F) {
+ uint8_t ext = p_file->get_8() & 0xF;
+ marker_size = read_bplist_var_size_int(p_file, pow(2, ext));
+ }
+ node->data_type = PL_NODE_TYPE_DATA;
+ PackedByteArray buf;
+ buf.resize(marker_size + 1);
+ p_file->get_buffer(reinterpret_cast<uint8_t *>(buf.ptrw()), marker_size);
+ node->data_string = CryptoCore::b64_encode_str(buf.ptr(), buf.size()).utf8();
+ } break;
+ case 0x50: {
+ if (marker_size == 0x0F) {
+ uint8_t ext = p_file->get_8() & 0xF;
+ marker_size = read_bplist_var_size_int(p_file, pow(2, ext));
+ }
+ node->data_type = PL_NODE_TYPE_STRING;
+ node->data_string.resize(marker_size + 1);
+ p_file->get_buffer(reinterpret_cast<uint8_t *>(node->data_string.ptrw()), marker_size);
+ } break;
+ case 0x60: {
+ if (marker_size == 0x0F) {
+ uint8_t ext = p_file->get_8() & 0xF;
+ marker_size = read_bplist_var_size_int(p_file, pow(2, ext));
+ }
+ Char16String cs16;
+ cs16.resize(marker_size + 1);
+ for (uint64_t i = 0; i < marker_size; i++) {
+ cs16[i] = BSWAP16(p_file->get_16());
+ }
+ node->data_type = PL_NODE_TYPE_STRING;
+ node->data_string = String::utf16(cs16.ptr(), cs16.length()).utf8();
+ } break;
+ case 0x80: {
+ node->data_type = PL_NODE_TYPE_INTEGER;
+ node->data_int = static_cast<int64_t>(read_bplist_var_size_int(p_file, marker_size + 1));
+ } break;
+ case 0xA0:
+ case 0xC0: {
+ if (marker_size == 0x0F) {
+ uint8_t ext = p_file->get_8() & 0xF;
+ marker_size = read_bplist_var_size_int(p_file, pow(2, ext));
+ }
+ uint64_t pos = p_file->get_position();
+
+ node->data_type = PL_NODE_TYPE_ARRAY;
+ for (uint64_t i = 0; i < marker_size; i++) {
+ p_file->seek(pos + trailer.ref_size * i);
+ uint64_t ref = read_bplist_var_size_int(p_file, trailer.ref_size);
+
+ Ref<PListNode> element = read_bplist_obj(p_file, ref);
+ ERR_FAIL_COND_V(element.is_null(), Ref<PListNode>());
+ node->data_array.push_back(element);
+ }
+ } break;
+ case 0xD0: {
+ if (marker_size == 0x0F) {
+ uint8_t ext = p_file->get_8() & 0xF;
+ marker_size = read_bplist_var_size_int(p_file, pow(2, ext));
+ }
+ uint64_t pos = p_file->get_position();
+
+ node->data_type = PL_NODE_TYPE_DICT;
+ for (uint64_t i = 0; i < marker_size; i++) {
+ p_file->seek(pos + trailer.ref_size * i);
+ uint64_t key_ref = read_bplist_var_size_int(p_file, trailer.ref_size);
+
+ p_file->seek(pos + trailer.ref_size * (i + marker_size));
+ uint64_t obj_ref = read_bplist_var_size_int(p_file, trailer.ref_size);
+
+ Ref<PListNode> element_key = read_bplist_obj(p_file, key_ref);
+ ERR_FAIL_COND_V(element_key.is_null() || element_key->data_type != PL_NODE_TYPE_STRING, Ref<PListNode>());
+ Ref<PListNode> element = read_bplist_obj(p_file, obj_ref);
+ ERR_FAIL_COND_V(element.is_null(), Ref<PListNode>());
+ node->data_dict[String::utf8(element_key->data_string.ptr(), element_key->data_string.length())] = element;
+ }
+ } break;
+ default: {
+ ERR_FAIL_V_MSG(Ref<PListNode>(), "Invalid marker type.");
+ }
+ }
+ return node;
+}
+
bool PList::load_file(const String &p_filename) {
root = Ref<PListNode>();
@@ -349,7 +625,15 @@ bool PList::load_file(const String &p_filename) {
fb->get_buffer(magic, 8);
if (String((const char *)magic, 8) == "bplist00") {
- ERR_FAIL_V_MSG(false, "PList: Binary property lists are not supported.");
+ fb->seek_end(-26);
+ trailer.offset_size = fb->get_8();
+ trailer.ref_size = fb->get_8();
+ trailer.object_num = BSWAP64(fb->get_64());
+ trailer.root_offset_idx = BSWAP64(fb->get_64());
+ trailer.offset_table_start = BSWAP64(fb->get_64());
+ root = read_bplist_obj(fb, trailer.root_offset_idx);
+
+ return root.is_valid();
} else {
// Load text plist.
Error err;
diff --git a/platform/macos/export/plist.h b/platform/macos/export/plist.h
index 97331a3629..d53e88832f 100644
--- a/platform/macos/export/plist.h
+++ b/platform/macos/export/plist.h
@@ -35,6 +35,7 @@
#include "core/crypto/crypto_core.h"
#include "core/io/file_access.h"
+#include "core/os/time.h"
class PListNode;
@@ -55,8 +56,20 @@ public:
};
private:
+ struct PListTrailer {
+ uint8_t offset_size;
+ uint8_t ref_size;
+ uint64_t object_num;
+ uint64_t root_offset_idx;
+ uint64_t offset_table_start;
+ };
+
+ PListTrailer trailer;
Ref<PListNode> root;
+ uint64_t read_bplist_var_size_int(Ref<FileAccess> p_file, uint8_t p_size);
+ Ref<PListNode> read_bplist_obj(Ref<FileAccess> p_file, uint64_t p_offset_idx);
+
public:
PList();
PList(const String &p_string);
@@ -82,19 +95,23 @@ public:
Vector<Ref<PListNode>> data_array;
HashMap<String, Ref<PListNode>> data_dict;
union {
- int32_t data_int;
+ int64_t data_int;
bool data_bool;
- float data_real;
+ double data_real;
};
+ PList::PLNodeType get_type() const;
+ Variant get_value() const;
+
+ static Ref<PListNode> new_node(const Variant &p_value);
static Ref<PListNode> new_array();
static Ref<PListNode> new_dict();
static Ref<PListNode> new_string(const String &p_string);
static Ref<PListNode> new_data(const String &p_string);
static Ref<PListNode> new_date(const String &p_string);
static Ref<PListNode> new_bool(bool p_bool);
- static Ref<PListNode> new_int(int32_t p_int);
- static Ref<PListNode> new_real(float p_real);
+ static Ref<PListNode> new_int(int64_t p_int);
+ static Ref<PListNode> new_real(double p_real);
bool push_subnode(const Ref<PListNode> &p_node, const String &p_key = "");
diff --git a/platform/macos/os_macos.mm b/platform/macos/os_macos.mm
index ebba96ceb1..fd8ba38808 100644
--- a/platform/macos/os_macos.mm
+++ b/platform/macos/os_macos.mm
@@ -45,16 +45,6 @@
#include <os/log.h>
#include <sys/sysctl.h>
-_FORCE_INLINE_ String OS_MacOS::get_framework_executable(const String &p_path) {
- // Append framework executable name, or return as is if p_path is not a framework.
- Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- if (da->dir_exists(p_path) && da->file_exists(p_path.path_join(p_path.get_file().get_basename()))) {
- return p_path.path_join(p_path.get_file().get_basename());
- } else {
- return p_path;
- }
-}
-
void OS_MacOS::pre_wait_observer_cb(CFRunLoopObserverRef p_observer, CFRunLoopActivity p_activiy, void *p_context) {
// Prevent main loop from sleeping and redraw window during modal popup display.
// Do not redraw when rendering is done from the separate thread, it will conflict with the OpenGL context updates.
@@ -162,6 +152,28 @@ void OS_MacOS::alert(const String &p_alert, const String &p_title) {
}
}
+_FORCE_INLINE_ String OS_MacOS::get_framework_executable(const String &p_path) {
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+
+ // Read framework bundle to get executable name.
+ NSURL *url = [NSURL fileURLWithPath:@(p_path.utf8().get_data())];
+ NSBundle *bundle = [NSBundle bundleWithURL:url];
+ if (bundle) {
+ String exe_path = String::utf8([[bundle executablePath] UTF8String]);
+ if (da->file_exists(exe_path)) {
+ return exe_path;
+ }
+ }
+
+ // Try default executable name (invalid framework).
+ if (da->dir_exists(p_path) && da->file_exists(p_path.path_join(p_path.get_file().get_basename()))) {
+ return p_path.path_join(p_path.get_file().get_basename());
+ }
+
+ // Not a framework, try loading as .dylib.
+ return p_path;
+}
+
Error OS_MacOS::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) {
String path = get_framework_executable(p_path);
@@ -190,14 +202,6 @@ MainLoop *OS_MacOS::get_main_loop() const {
}
String OS_MacOS::get_config_path() const {
- // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on macOS as well.
- if (has_environment("XDG_CONFIG_HOME")) {
- if (get_environment("XDG_CONFIG_HOME").is_absolute_path()) {
- return get_environment("XDG_CONFIG_HOME");
- } else {
- WARN_PRINT_ONCE("`XDG_CONFIG_HOME` is a relative path. Ignoring its value and falling back to `$HOME/Library/Application Support` or `.` per the XDG Base Directory specification.");
- }
- }
if (has_environment("HOME")) {
return get_environment("HOME").path_join("Library/Application Support");
}
@@ -205,26 +209,10 @@ String OS_MacOS::get_config_path() const {
}
String OS_MacOS::get_data_path() const {
- // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on macOS as well.
- if (has_environment("XDG_DATA_HOME")) {
- if (get_environment("XDG_DATA_HOME").is_absolute_path()) {
- return get_environment("XDG_DATA_HOME");
- } else {
- WARN_PRINT_ONCE("`XDG_DATA_HOME` is a relative path. Ignoring its value and falling back to `get_config_path()` per the XDG Base Directory specification.");
- }
- }
return get_config_path();
}
String OS_MacOS::get_cache_path() const {
- // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on macOS as well.
- if (has_environment("XDG_CACHE_HOME")) {
- if (get_environment("XDG_CACHE_HOME").is_absolute_path()) {
- return get_environment("XDG_CACHE_HOME");
- } else {
- WARN_PRINT_ONCE("`XDG_CACHE_HOME` is a relative path. Ignoring its value and falling back to `$HOME/Library/Caches` or `get_config_path()` per the XDG Base Directory specification.");
- }
- }
if (has_environment("HOME")) {
return get_environment("HOME").path_join("Library/Caches");
}
diff --git a/platform/web/export/export_plugin.cpp b/platform/web/export/export_plugin.cpp
index f59ac54f20..3087b12c40 100644
--- a/platform/web/export/export_plugin.cpp
+++ b/platform/web/export/export_plugin.cpp
@@ -133,7 +133,7 @@ void EditorExportPlatformWeb::_fix_html(Vector<uint8_t> &p_html, const Ref<Edito
config["canvasResizePolicy"] = p_preset->get("html/canvas_resize_policy");
config["experimentalVK"] = p_preset->get("html/experimental_virtual_keyboard");
config["focusCanvas"] = p_preset->get("html/focus_canvas_on_start");
- config["gdnativeLibs"] = libs;
+ config["gdextensionLibs"] = libs;
config["executable"] = p_name;
config["args"] = args;
config["fileSizes"] = p_file_sizes;
diff --git a/platform/web/js/engine/config.js b/platform/web/js/engine/config.js
index 4560f12b49..6a30c253fb 100644
--- a/platform/web/js/engine/config.js
+++ b/platform/web/js/engine/config.js
@@ -127,7 +127,7 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused-
* @ignore
* @type {Array.<string>}
*/
- gdnativeLibs: [],
+ gdextensionLibs: [],
/**
* @ignore
* @type {Array.<string>}
@@ -257,7 +257,7 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused-
this.experimentalVK = parse('experimentalVK', this.experimentalVK);
this.focusCanvas = parse('focusCanvas', this.focusCanvas);
this.serviceWorker = parse('serviceWorker', this.serviceWorker);
- this.gdnativeLibs = parse('gdnativeLibs', this.gdnativeLibs);
+ this.gdextensionLibs = parse('gdextensionLibs', this.gdextensionLibs);
this.fileSizes = parse('fileSizes', this.fileSizes);
this.args = parse('args', this.args);
this.onExecute = parse('onExecute', this.onExecute);
diff --git a/platform/web/js/engine/engine.js b/platform/web/js/engine/engine.js
index 9227aa1f05..fb80bd55e1 100644
--- a/platform/web/js/engine/engine.js
+++ b/platform/web/js/engine/engine.js
@@ -162,9 +162,9 @@ const Engine = (function () {
// Godot configuration.
me.rtenv['initConfig'](config);
- // Preload GDNative libraries.
+ // Preload GDExtension libraries.
const libs = [];
- me.config.gdnativeLibs.forEach(function (lib) {
+ me.config.gdextensionLibs.forEach(function (lib) {
libs.push(me.rtenv['loadDynamicLibrary'](lib, { 'loadAsync': true }));
});
return Promise.all(libs).then(function () {
diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp
index f04177d79a..89f56ffd93 100644
--- a/platform/windows/export/export_plugin.cpp
+++ b/platform/windows/export/export_plugin.cpp
@@ -226,7 +226,7 @@ void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_optio
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "application/modify_resources"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.ico,*.png,*.webp,*.svg"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/console_wrapper_icon", PROPERTY_HINT_FILE, "*.ico.*.png,*.webp,*.svg"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/console_wrapper_icon", PROPERTY_HINT_FILE, "*.ico,*.png,*.webp,*.svg"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/icon_interpolation", PROPERTY_HINT_ENUM, "Nearest neighbor,Bilinear,Cubic,Trilinear,Lanczos"), 4));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0.0"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0.0"), ""));
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index e957a25e87..f8633d29ac 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -272,7 +272,7 @@ Error OS_Windows::open_dynamic_library(const String p_path, void *&p_library_han
String path = p_path.replace("/", "\\");
if (!FileAccess::exists(path)) {
- //this code exists so gdnative can load .dll files from within the executable path
+ //this code exists so gdextension can load .dll files from within the executable path
path = get_executable_path().get_base_dir().path_join(p_path.get_file());
}
@@ -1059,7 +1059,7 @@ String OS_Windows::get_system_font_path(const String &p_font_name, int p_weight,
UINT32 index = 0;
BOOL exists = false;
HRESULT hr = font_collection->FindFamilyName((const WCHAR *)font_name.utf16().get_data(), &index, &exists);
- if (FAILED(hr)) {
+ if (FAILED(hr) || !exists) {
return String();
}
@@ -1164,8 +1164,11 @@ bool OS_Windows::set_environment(const String &p_var, const String &p_value) con
String OS_Windows::get_stdin_string(bool p_block) {
if (p_block) {
- char buff[1024];
- return fgets(buff, 1024, stdin);
+ WCHAR buff[1024];
+ DWORD count = 0;
+ if (ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE), buff, 1024, &count, nullptr)) {
+ return String::utf16((const char16_t *)buff, count);
+ }
}
return String();
@@ -1336,14 +1339,6 @@ uint64_t OS_Windows::get_embedded_pck_offset() const {
}
String OS_Windows::get_config_path() const {
- // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well.
- if (has_environment("XDG_CONFIG_HOME")) {
- if (get_environment("XDG_CONFIG_HOME").is_absolute_path()) {
- return get_environment("XDG_CONFIG_HOME").replace("\\", "/");
- } else {
- WARN_PRINT_ONCE("`XDG_CONFIG_HOME` is a relative path. Ignoring its value and falling back to `%APPDATA%` or `.` per the XDG Base Directory specification.");
- }
- }
if (has_environment("APPDATA")) {
return get_environment("APPDATA").replace("\\", "/");
}
@@ -1351,29 +1346,13 @@ String OS_Windows::get_config_path() const {
}
String OS_Windows::get_data_path() const {
- // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well.
- if (has_environment("XDG_DATA_HOME")) {
- if (get_environment("XDG_DATA_HOME").is_absolute_path()) {
- return get_environment("XDG_DATA_HOME").replace("\\", "/");
- } else {
- WARN_PRINT_ONCE("`XDG_DATA_HOME` is a relative path. Ignoring its value and falling back to `get_config_path()` per the XDG Base Directory specification.");
- }
- }
return get_config_path();
}
String OS_Windows::get_cache_path() const {
static String cache_path_cache;
if (cache_path_cache.is_empty()) {
- // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well.
- if (has_environment("XDG_CACHE_HOME")) {
- if (get_environment("XDG_CACHE_HOME").is_absolute_path()) {
- cache_path_cache = get_environment("XDG_CACHE_HOME").replace("\\", "/");
- } else {
- WARN_PRINT_ONCE("`XDG_CACHE_HOME` is a relative path. Ignoring its value and falling back to `%LOCALAPPDATA%\\cache`, `%TEMP%` or `get_config_path()` per the XDG Base Directory specification.");
- }
- }
- if (cache_path_cache.is_empty() && has_environment("LOCALAPPDATA")) {
+ if (has_environment("LOCALAPPDATA")) {
cache_path_cache = get_environment("LOCALAPPDATA").replace("\\", "/");
}
if (cache_path_cache.is_empty() && has_environment("TEMP")) {
diff --git a/platform/windows/platform_windows_builders.py b/platform/windows/platform_windows_builders.py
index 33ca2e8ffa..b522a75a9c 100644
--- a/platform/windows/platform_windows_builders.py
+++ b/platform/windows/platform_windows_builders.py
@@ -4,18 +4,15 @@ All such functions are invoked in a subprocess on Windows to prevent build flaki
"""
import os
+from detect import get_mingw_bin_prefix
from platform_methods import subprocess_main
def make_debug_mingw(target, source, env):
- mingw_prefix = ""
- if env["arch"] == "x86_32":
- mingw_prefix = env["mingw_prefix_32"]
- else:
- mingw_prefix = env["mingw_prefix_64"]
- os.system(mingw_prefix + "objcopy --only-keep-debug {0} {0}.debugsymbols".format(target[0]))
- os.system(mingw_prefix + "strip --strip-debug --strip-unneeded {0}".format(target[0]))
- os.system(mingw_prefix + "objcopy --add-gnu-debuglink={0}.debugsymbols {0}".format(target[0]))
+ 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 __name__ == "__main__":