summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
Diffstat (limited to 'platform')
-rw-r--r--platform/android/export/export.cpp52
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java8
-rw-r--r--platform/android/plugin/godot_plugin_config.h101
-rw-r--r--platform/iphone/export/export.cpp49
-rw-r--r--platform/iphone/plugin/godot_plugin_config.h102
-rw-r--r--platform/javascript/SCsub17
-rw-r--r--platform/javascript/detect.py5
-rw-r--r--platform/javascript/display_server_javascript.cpp80
-rw-r--r--platform/javascript/display_server_javascript.h2
-rw-r--r--platform/javascript/emscripten_helpers.py6
-rw-r--r--platform/javascript/godot_js.h6
-rw-r--r--platform/javascript/http_client_javascript.cpp4
-rw-r--r--platform/javascript/javascript_main.cpp2
-rw-r--r--platform/javascript/js/libs/library_godot_display.js172
-rw-r--r--platform/javascript/os_javascript.cpp8
-rw-r--r--platform/javascript/os_javascript.h3
-rw-r--r--platform/linuxbsd/crash_handler_linuxbsd.cpp2
-rw-r--r--platform/linuxbsd/display_server_x11.cpp2
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp20
-rw-r--r--platform/osx/crash_handler_osx.mm2
-rw-r--r--platform/osx/display_server_osx.mm4
-rw-r--r--platform/osx/export/export.cpp6
-rw-r--r--platform/uwp/export/export.cpp4
-rw-r--r--platform/uwp/os_uwp.cpp8
-rw-r--r--platform/uwp/os_uwp.h3
-rw-r--r--platform/windows/display_server_windows.h2
-rw-r--r--platform/windows/export/export.cpp6
-rw-r--r--platform/windows/os_windows.cpp87
-rw-r--r--platform/windows/os_windows.h3
29 files changed, 478 insertions, 288 deletions
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 08ee410a96..62720e8249 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -261,7 +261,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
EditorProgress *ep = nullptr;
};
- Vector<PluginConfig> plugins;
+ Vector<PluginConfigAndroid> plugins;
String last_plugin_names;
uint64_t last_custom_build_time = 0;
volatile bool plugins_changed;
@@ -280,7 +280,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
{
// Nothing to do if we already know the plugins have changed.
if (!ea->plugins_changed) {
- Vector<PluginConfig> loaded_plugins = get_plugins();
+ Vector<PluginConfigAndroid> loaded_plugins = get_plugins();
MutexLock lock(ea->plugins_lock);
@@ -308,7 +308,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
List<String> args;
args.push_back("devices");
int ec;
- OS::get_singleton()->execute(adb, args, true, nullptr, &devices, &ec);
+ OS::get_singleton()->execute(adb, args, &devices, &ec);
Vector<String> ds = devices.split("\n");
Vector<String> ldevices;
@@ -361,7 +361,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
int ec2;
String dp;
- OS::get_singleton()->execute(adb, args, true, nullptr, &dp, &ec2);
+ OS::get_singleton()->execute(adb, args, &dp, &ec2);
Vector<String> props = dp.split("\n");
String vendor;
@@ -432,7 +432,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
List<String> args;
args.push_back("kill-server");
- OS::get_singleton()->execute(adb, args, true);
+ OS::get_singleton()->execute(adb, args);
};
}
@@ -629,7 +629,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
continue;
}
- if (file.ends_with(PLUGIN_CONFIG_EXT)) {
+ if (file.ends_with(PluginConfigAndroid::PLUGIN_CONFIG_EXT)) {
dir_files.push_back(file);
}
}
@@ -639,8 +639,8 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
return dir_files;
}
- static Vector<PluginConfig> get_plugins() {
- Vector<PluginConfig> loaded_plugins;
+ static Vector<PluginConfigAndroid> get_plugins() {
+ Vector<PluginConfigAndroid> loaded_plugins;
String plugins_dir = ProjectSettings::get_singleton()->get_resource_path().plus_file("android/plugins");
@@ -653,7 +653,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
if (!plugins_filenames.is_empty()) {
Ref<ConfigFile> config_file = memnew(ConfigFile);
for (int i = 0; i < plugins_filenames.size(); i++) {
- PluginConfig config = load_plugin_config(config_file, plugins_dir.plus_file(plugins_filenames[i]));
+ PluginConfigAndroid config = load_plugin_config(config_file, plugins_dir.plus_file(plugins_filenames[i]));
if (config.valid_config) {
loaded_plugins.push_back(config);
} else {
@@ -666,11 +666,11 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
return loaded_plugins;
}
- static Vector<PluginConfig> get_enabled_plugins(const Ref<EditorExportPreset> &p_presets) {
- Vector<PluginConfig> enabled_plugins;
- Vector<PluginConfig> all_plugins = get_plugins();
+ static Vector<PluginConfigAndroid> get_enabled_plugins(const Ref<EditorExportPreset> &p_presets) {
+ Vector<PluginConfigAndroid> enabled_plugins;
+ Vector<PluginConfigAndroid> all_plugins = get_plugins();
for (int i = 0; i < all_plugins.size(); i++) {
- PluginConfig plugin = all_plugins[i];
+ PluginConfigAndroid plugin = all_plugins[i];
bool enabled = p_presets->get("plugins/" + plugin.name);
if (enabled) {
enabled_plugins.push_back(plugin);
@@ -1618,7 +1618,7 @@ public:
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "custom_template/use_custom_build"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "custom_template/export_format", PROPERTY_HINT_ENUM, "Export APK,Export AAB"), EXPORT_FORMAT_APK));
- Vector<PluginConfig> plugins_configs = get_plugins();
+ Vector<PluginConfigAndroid> plugins_configs = get_plugins();
for (int i = 0; i < plugins_configs.size(); i++) {
print_verbose("Found Android plugin " + plugins_configs[i].name);
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "plugins/" + plugins_configs[i].name), false));
@@ -1800,7 +1800,7 @@ public:
args.push_back("uninstall");
args.push_back(get_package_name(package_name));
- err = OS::get_singleton()->execute(adb, args, true, nullptr, nullptr, &rv);
+ err = OS::get_singleton()->execute(adb, args, nullptr, &rv);
}
print_line("Installing to device (please wait...): " + devices[p_device].name);
@@ -1815,7 +1815,7 @@ public:
args.push_back("-r");
args.push_back(tmp_export_path);
- err = OS::get_singleton()->execute(adb, args, true, nullptr, nullptr, &rv);
+ err = OS::get_singleton()->execute(adb, args, nullptr, &rv);
if (err || rv != 0) {
EditorNode::add_io_error("Could not install to device.");
CLEANUP_AND_RETURN(ERR_CANT_CREATE);
@@ -1832,7 +1832,7 @@ public:
args.push_back(devices[p_device].id);
args.push_back("reverse");
args.push_back("--remove-all");
- OS::get_singleton()->execute(adb, args, true, nullptr, nullptr, &rv);
+ OS::get_singleton()->execute(adb, args, nullptr, &rv);
if (p_debug_flags & DEBUG_FLAG_REMOTE_DEBUG) {
int dbg_port = EditorSettings::get_singleton()->get("network/debug/remote_port");
@@ -1843,7 +1843,7 @@ public:
args.push_back("tcp:" + itos(dbg_port));
args.push_back("tcp:" + itos(dbg_port));
- OS::get_singleton()->execute(adb, args, true, nullptr, nullptr, &rv);
+ OS::get_singleton()->execute(adb, args, nullptr, &rv);
print_line("Reverse result: " + itos(rv));
}
@@ -1857,7 +1857,7 @@ public:
args.push_back("tcp:" + itos(fs_port));
args.push_back("tcp:" + itos(fs_port));
- err = OS::get_singleton()->execute(adb, args, true, nullptr, nullptr, &rv);
+ err = OS::get_singleton()->execute(adb, args, nullptr, &rv);
print_line("Reverse result2: " + itos(rv));
}
} else {
@@ -1885,7 +1885,7 @@ public:
args.push_back("-n");
args.push_back(get_package_name(package_name) + "/com.godot.game.GodotApp");
- err = OS::get_singleton()->execute(adb, args, true, nullptr, nullptr, &rv);
+ err = OS::get_singleton()->execute(adb, args, nullptr, &rv);
if (err || rv != 0) {
EditorNode::add_io_error("Could not execute on device.");
CLEANUP_AND_RETURN(ERR_CANT_CREATE);
@@ -2131,7 +2131,7 @@ public:
return list;
}
- inline bool is_clean_build_required(Vector<PluginConfig> enabled_plugins) {
+ inline bool is_clean_build_required(Vector<PluginConfigAndroid> enabled_plugins) {
String plugin_names = get_plugins_names(enabled_plugins);
bool first_build = last_custom_build_time == 0;
bool have_plugins_changed = false;
@@ -2288,7 +2288,7 @@ public:
args.push_back(user);
args.push_back(export_path);
int retval;
- OS::get_singleton()->execute(apksigner, args, true, NULL, NULL, &retval);
+ OS::get_singleton()->execute(apksigner, args, nullptr, &retval);
if (retval) {
EditorNode::add_io_error("'apksigner' returned with error #" + itos(retval));
return ERR_CANT_CREATE;
@@ -2303,7 +2303,7 @@ public:
args.push_back("--verbose");
args.push_back(export_path);
- OS::get_singleton()->execute(apksigner, args, true, NULL, NULL, &retval);
+ OS::get_singleton()->execute(apksigner, args, nullptr, &retval);
if (retval) {
EditorNode::add_io_error("'apksigner' verification of " + export_label + " failed.");
return ERR_CANT_CREATE;
@@ -2438,9 +2438,9 @@ public:
String sign_flag = should_sign ? "true" : "false";
String zipalign_flag = "true";
- Vector<PluginConfig> enabled_plugins = get_enabled_plugins(p_preset);
- String local_plugins_binaries = get_plugins_binaries(BINARY_TYPE_LOCAL, enabled_plugins);
- String remote_plugins_binaries = get_plugins_binaries(BINARY_TYPE_REMOTE, enabled_plugins);
+ Vector<PluginConfigAndroid> enabled_plugins = get_enabled_plugins(p_preset);
+ String local_plugins_binaries = get_plugins_binaries(PluginConfigAndroid::BINARY_TYPE_LOCAL, enabled_plugins);
+ String remote_plugins_binaries = get_plugins_binaries(PluginConfigAndroid::BINARY_TYPE_REMOTE, enabled_plugins);
String custom_maven_repos = get_plugins_custom_maven_repos(enabled_plugins);
bool clean_build_required = is_clean_build_required(enabled_plugins);
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
index b536733201..63c91561ff 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
@@ -188,15 +188,15 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
if (GLUtils.use_32) {
setEGLConfigChooser(translucent ?
- new RegularFallbackConfigChooser(8, 8, 8, 8, 24, stencil,
+ new RegularFallbackConfigChooser(8, 8, 8, 8, 24, stencil,
new RegularConfigChooser(8, 8, 8, 8, 16, stencil)) :
- new RegularFallbackConfigChooser(8, 8, 8, 8, 24, stencil,
+ new RegularFallbackConfigChooser(8, 8, 8, 8, 24, stencil,
new RegularConfigChooser(5, 6, 5, 0, 16, stencil)));
} else {
setEGLConfigChooser(translucent ?
- new RegularConfigChooser(8, 8, 8, 8, 16, stencil) :
- new RegularConfigChooser(5, 6, 5, 0, 16, stencil));
+ new RegularConfigChooser(8, 8, 8, 8, 16, stencil) :
+ new RegularConfigChooser(5, 6, 5, 0, 16, stencil));
}
break;
}
diff --git a/platform/android/plugin/godot_plugin_config.h b/platform/android/plugin/godot_plugin_config.h
index 611053ccba..173ac115a2 100644
--- a/platform/android/plugin/godot_plugin_config.h
+++ b/platform/android/plugin/godot_plugin_config.h
@@ -35,23 +35,6 @@
#include "core/io/config_file.h"
#include "core/string/ustring.h"
-static const char *PLUGIN_CONFIG_EXT = ".gdap";
-
-static const char *CONFIG_SECTION = "config";
-static const char *CONFIG_NAME_KEY = "name";
-static const char *CONFIG_BINARY_TYPE_KEY = "binary_type";
-static const char *CONFIG_BINARY_KEY = "binary";
-
-static const char *DEPENDENCIES_SECTION = "dependencies";
-static const char *DEPENDENCIES_LOCAL_KEY = "local";
-static const char *DEPENDENCIES_REMOTE_KEY = "remote";
-static const char *DEPENDENCIES_CUSTOM_MAVEN_REPOS_KEY = "custom_maven_repos";
-
-static const char *BINARY_TYPE_LOCAL = "local";
-static const char *BINARY_TYPE_REMOTE = "remote";
-
-static const char *PLUGIN_VALUE_SEPARATOR = "|";
-
/*
The `config` section and fields are required and defined as follow:
- **name**: name of the plugin
@@ -67,7 +50,24 @@ The `dependencies` section and fields are optional and defined as follow:
See https://github.com/godotengine/godot/issues/38157#issuecomment-618773871
*/
-struct PluginConfig {
+struct PluginConfigAndroid {
+ inline static const char *PLUGIN_CONFIG_EXT = ".gdap";
+
+ inline static const char *CONFIG_SECTION = "config";
+ inline static const char *CONFIG_NAME_KEY = "name";
+ inline static const char *CONFIG_BINARY_TYPE_KEY = "binary_type";
+ inline static const char *CONFIG_BINARY_KEY = "binary";
+
+ inline static const char *DEPENDENCIES_SECTION = "dependencies";
+ inline static const char *DEPENDENCIES_LOCAL_KEY = "local";
+ inline static const char *DEPENDENCIES_REMOTE_KEY = "remote";
+ inline static const char *DEPENDENCIES_CUSTOM_MAVEN_REPOS_KEY = "custom_maven_repos";
+
+ inline static const char *BINARY_TYPE_LOCAL = "local";
+ inline static const char *BINARY_TYPE_REMOTE = "remote";
+
+ inline static const char *PLUGIN_VALUE_SEPARATOR = "|";
+
// Set to true when the config file is properly loaded.
bool valid_config = false;
// Unix timestamp of last change to this plugin.
@@ -88,7 +88,7 @@ struct PluginConfig {
* Set of prebuilt plugins.
* Currently unused, this is just for future reference:
*/
-// static const PluginConfig MY_PREBUILT_PLUGIN = {
+// static const PluginConfigAndroid MY_PREBUILT_PLUGIN = {
// /*.valid_config =*/true,
// /*.last_updated =*/0,
// /*.name =*/"GodotPayment",
@@ -112,9 +112,9 @@ static inline String resolve_local_dependency_path(String plugin_config_dir, Str
return absolute_path;
}
-static inline PluginConfig resolve_prebuilt_plugin(PluginConfig prebuilt_plugin, String plugin_config_dir) {
- PluginConfig resolved = prebuilt_plugin;
- resolved.binary = resolved.binary_type == BINARY_TYPE_LOCAL ? resolve_local_dependency_path(plugin_config_dir, prebuilt_plugin.binary) : prebuilt_plugin.binary;
+static inline PluginConfigAndroid resolve_prebuilt_plugin(PluginConfigAndroid prebuilt_plugin, String plugin_config_dir) {
+ PluginConfigAndroid resolved = prebuilt_plugin;
+ resolved.binary = resolved.binary_type == PluginConfigAndroid::BINARY_TYPE_LOCAL ? resolve_local_dependency_path(plugin_config_dir, prebuilt_plugin.binary) : prebuilt_plugin.binary;
if (!prebuilt_plugin.local_dependencies.is_empty()) {
resolved.local_dependencies.clear();
for (int i = 0; i < prebuilt_plugin.local_dependencies.size(); i++) {
@@ -124,21 +124,22 @@ static inline PluginConfig resolve_prebuilt_plugin(PluginConfig prebuilt_plugin,
return resolved;
}
-static inline Vector<PluginConfig> get_prebuilt_plugins(String plugins_base_dir) {
- Vector<PluginConfig> prebuilt_plugins;
+static inline Vector<PluginConfigAndroid> get_prebuilt_plugins(String plugins_base_dir) {
+ Vector<PluginConfigAndroid> prebuilt_plugins;
// prebuilt_plugins.push_back(resolve_prebuilt_plugin(MY_PREBUILT_PLUGIN, plugins_base_dir));
return prebuilt_plugins;
}
-static inline bool is_plugin_config_valid(PluginConfig plugin_config) {
+static inline bool is_plugin_config_valid(PluginConfigAndroid plugin_config) {
bool valid_name = !plugin_config.name.is_empty();
- bool valid_binary_type = plugin_config.binary_type == BINARY_TYPE_LOCAL ||
- plugin_config.binary_type == BINARY_TYPE_REMOTE;
+ bool valid_binary_type = plugin_config.binary_type == PluginConfigAndroid::BINARY_TYPE_LOCAL ||
+ plugin_config.binary_type == PluginConfigAndroid::BINARY_TYPE_REMOTE;
bool valid_binary = false;
if (valid_binary_type) {
valid_binary = !plugin_config.binary.is_empty() &&
- (plugin_config.binary_type == BINARY_TYPE_REMOTE ||
+ (plugin_config.binary_type == PluginConfigAndroid::BINARY_TYPE_REMOTE ||
+
FileAccess::exists(plugin_config.binary));
}
@@ -154,7 +155,7 @@ static inline bool is_plugin_config_valid(PluginConfig plugin_config) {
return valid_name && valid_binary && valid_binary_type && valid_local_dependencies;
}
-static inline uint64_t get_plugin_modification_time(const PluginConfig &plugin_config, const String &config_path) {
+static inline uint64_t get_plugin_modification_time(const PluginConfigAndroid &plugin_config, const String &config_path) {
uint64_t last_updated = FileAccess::get_modified_time(config_path);
last_updated = MAX(last_updated, FileAccess::get_modified_time(plugin_config.binary));
@@ -166,30 +167,30 @@ static inline uint64_t get_plugin_modification_time(const PluginConfig &plugin_c
return last_updated;
}
-static inline PluginConfig load_plugin_config(Ref<ConfigFile> config_file, const String &path) {
- PluginConfig plugin_config = {};
+static inline PluginConfigAndroid load_plugin_config(Ref<ConfigFile> config_file, const String &path) {
+ PluginConfigAndroid plugin_config = {};
if (config_file.is_valid()) {
Error err = config_file->load(path);
if (err == OK) {
String config_base_dir = path.get_base_dir();
- plugin_config.name = config_file->get_value(CONFIG_SECTION, CONFIG_NAME_KEY, String());
- plugin_config.binary_type = config_file->get_value(CONFIG_SECTION, CONFIG_BINARY_TYPE_KEY, String());
+ plugin_config.name = config_file->get_value(PluginConfigAndroid::CONFIG_SECTION, PluginConfigAndroid::CONFIG_NAME_KEY, String());
+ plugin_config.binary_type = config_file->get_value(PluginConfigAndroid::CONFIG_SECTION, PluginConfigAndroid::CONFIG_BINARY_TYPE_KEY, String());
- String binary_path = config_file->get_value(CONFIG_SECTION, CONFIG_BINARY_KEY, String());
- plugin_config.binary = plugin_config.binary_type == BINARY_TYPE_LOCAL ? resolve_local_dependency_path(config_base_dir, binary_path) : binary_path;
+ String binary_path = config_file->get_value(PluginConfigAndroid::CONFIG_SECTION, PluginConfigAndroid::CONFIG_BINARY_KEY, String());
+ plugin_config.binary = plugin_config.binary_type == PluginConfigAndroid::BINARY_TYPE_LOCAL ? resolve_local_dependency_path(config_base_dir, binary_path) : binary_path;
- if (config_file->has_section(DEPENDENCIES_SECTION)) {
- Vector<String> local_dependencies_paths = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_LOCAL_KEY, Vector<String>());
+ if (config_file->has_section(PluginConfigAndroid::DEPENDENCIES_SECTION)) {
+ Vector<String> local_dependencies_paths = config_file->get_value(PluginConfigAndroid::DEPENDENCIES_SECTION, PluginConfigAndroid::DEPENDENCIES_LOCAL_KEY, Vector<String>());
if (!local_dependencies_paths.is_empty()) {
for (int i = 0; i < local_dependencies_paths.size(); i++) {
plugin_config.local_dependencies.push_back(resolve_local_dependency_path(config_base_dir, local_dependencies_paths[i]));
}
}
- plugin_config.remote_dependencies = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_REMOTE_KEY, Vector<String>());
- plugin_config.custom_maven_repos = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_CUSTOM_MAVEN_REPOS_KEY, Vector<String>());
+ plugin_config.remote_dependencies = config_file->get_value(PluginConfigAndroid::DEPENDENCIES_SECTION, PluginConfigAndroid::DEPENDENCIES_REMOTE_KEY, Vector<String>());
+ plugin_config.custom_maven_repos = config_file->get_value(PluginConfigAndroid::DEPENDENCIES_SECTION, PluginConfigAndroid::DEPENDENCIES_CUSTOM_MAVEN_REPOS_KEY, Vector<String>());
}
plugin_config.valid_config = is_plugin_config_valid(plugin_config);
@@ -200,12 +201,12 @@ static inline PluginConfig load_plugin_config(Ref<ConfigFile> config_file, const
return plugin_config;
}
-static inline String get_plugins_binaries(String binary_type, Vector<PluginConfig> plugins_configs) {
+static inline String get_plugins_binaries(String binary_type, Vector<PluginConfigAndroid> plugins_configs) {
String plugins_binaries;
if (!plugins_configs.is_empty()) {
Vector<String> binaries;
for (int i = 0; i < plugins_configs.size(); i++) {
- PluginConfig config = plugins_configs[i];
+ PluginConfigAndroid config = plugins_configs[i];
if (!config.valid_config) {
continue;
}
@@ -214,27 +215,27 @@ static inline String get_plugins_binaries(String binary_type, Vector<PluginConfi
binaries.push_back(config.binary);
}
- if (binary_type == BINARY_TYPE_LOCAL) {
+ if (binary_type == PluginConfigAndroid::BINARY_TYPE_LOCAL) {
binaries.append_array(config.local_dependencies);
}
- if (binary_type == BINARY_TYPE_REMOTE) {
+ if (binary_type == PluginConfigAndroid::BINARY_TYPE_REMOTE) {
binaries.append_array(config.remote_dependencies);
}
}
- plugins_binaries = String(PLUGIN_VALUE_SEPARATOR).join(binaries);
+ plugins_binaries = String(PluginConfigAndroid::PLUGIN_VALUE_SEPARATOR).join(binaries);
}
return plugins_binaries;
}
-static inline String get_plugins_custom_maven_repos(Vector<PluginConfig> plugins_configs) {
+static inline String get_plugins_custom_maven_repos(Vector<PluginConfigAndroid> plugins_configs) {
String custom_maven_repos;
if (!plugins_configs.is_empty()) {
Vector<String> repos_urls;
for (int i = 0; i < plugins_configs.size(); i++) {
- PluginConfig config = plugins_configs[i];
+ PluginConfigAndroid config = plugins_configs[i];
if (!config.valid_config) {
continue;
}
@@ -242,24 +243,24 @@ static inline String get_plugins_custom_maven_repos(Vector<PluginConfig> plugins
repos_urls.append_array(config.custom_maven_repos);
}
- custom_maven_repos = String(PLUGIN_VALUE_SEPARATOR).join(repos_urls);
+ custom_maven_repos = String(PluginConfigAndroid::PLUGIN_VALUE_SEPARATOR).join(repos_urls);
}
return custom_maven_repos;
}
-static inline String get_plugins_names(Vector<PluginConfig> plugins_configs) {
+static inline String get_plugins_names(Vector<PluginConfigAndroid> plugins_configs) {
String plugins_names;
if (!plugins_configs.is_empty()) {
Vector<String> names;
for (int i = 0; i < plugins_configs.size(); i++) {
- PluginConfig config = plugins_configs[i];
+ PluginConfigAndroid config = plugins_configs[i];
if (!config.valid_config) {
continue;
}
names.push_back(config.name);
}
- plugins_names = String(PLUGIN_VALUE_SEPARATOR).join(names);
+ plugins_names = String(PluginConfigAndroid::PLUGIN_VALUE_SEPARATOR).join(names);
}
return plugins_names;
diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp
index 3253112bf3..d0c0ef7a4b 100644
--- a/platform/iphone/export/export.cpp
+++ b/platform/iphone/export/export.cpp
@@ -60,7 +60,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
Thread *check_for_changes_thread;
volatile bool quit_request;
Mutex plugins_lock;
- Vector<PluginConfig> plugins;
+ Vector<PluginConfigIOS> plugins;
typedef Error (*FileHandler)(String p_file, void *p_userdata);
static Error _walk_dir_recursive(DirAccess *p_da, FileHandler p_handler, void *p_userdata);
@@ -146,7 +146,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
if (!ea->plugins_changed) {
MutexLock lock(ea->plugins_lock);
- Vector<PluginConfig> loaded_plugins = get_plugins();
+ Vector<PluginConfigIOS> loaded_plugins = get_plugins();
if (ea->plugins.size() != loaded_plugins.size()) {
ea->plugins_changed = true;
@@ -241,7 +241,7 @@ public:
continue;
}
- if (file.ends_with(PLUGIN_CONFIG_EXT)) {
+ if (file.ends_with(PluginConfigIOS::PLUGIN_CONFIG_EXT)) {
dir_files.push_back(file);
}
}
@@ -251,8 +251,8 @@ public:
return dir_files;
}
- static Vector<PluginConfig> get_plugins() {
- Vector<PluginConfig> loaded_plugins;
+ static Vector<PluginConfigIOS> get_plugins() {
+ Vector<PluginConfigIOS> loaded_plugins;
String plugins_dir = ProjectSettings::get_singleton()->get_resource_path().plus_file("ios/plugins");
@@ -262,7 +262,7 @@ public:
if (!plugins_filenames.is_empty()) {
Ref<ConfigFile> config_file = memnew(ConfigFile);
for (int i = 0; i < plugins_filenames.size(); i++) {
- PluginConfig config = load_plugin_config(config_file, plugins_dir.plus_file(plugins_filenames[i]));
+ PluginConfigIOS config = load_plugin_config(config_file, plugins_dir.plus_file(plugins_filenames[i]));
if (config.valid_config) {
loaded_plugins.push_back(config);
} else {
@@ -275,11 +275,11 @@ public:
return loaded_plugins;
}
- static Vector<PluginConfig> get_enabled_plugins(const Ref<EditorExportPreset> &p_presets) {
- Vector<PluginConfig> enabled_plugins;
- Vector<PluginConfig> all_plugins = get_plugins();
+ static Vector<PluginConfigIOS> get_enabled_plugins(const Ref<EditorExportPreset> &p_presets) {
+ Vector<PluginConfigIOS> enabled_plugins;
+ Vector<PluginConfigIOS> all_plugins = get_plugins();
for (int i = 0; i < all_plugins.size(); i++) {
- PluginConfig plugin = all_plugins[i];
+ PluginConfigIOS plugin = all_plugins[i];
bool enabled = p_presets->get("plugins/" + plugin.name);
if (enabled) {
enabled_plugins.push_back(plugin);
@@ -360,7 +360,7 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), ""));
- Vector<PluginConfig> found_plugins = get_plugins();
+ Vector<PluginConfigIOS> found_plugins = get_plugins();
for (int i = 0; i < found_plugins.size(); i++) {
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "plugins/" + found_plugins[i].name), false));
}
@@ -979,7 +979,7 @@ Error EditorExportPlatformIOS::_codesign(String p_file, void *p_userdata) {
codesign_args.push_back("-s");
codesign_args.push_back(data->preset->get(data->debug ? "application/code_sign_identity_debug" : "application/code_sign_identity_release"));
codesign_args.push_back(p_file);
- return OS::get_singleton()->execute("codesign", codesign_args, true);
+ return OS::get_singleton()->execute("codesign", codesign_args);
}
return OK;
}
@@ -1229,7 +1229,7 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String
install_name_args.push_back(String("@rpath").plus_file(framework_name).plus_file(file_name));
install_name_args.push_back(destination);
- OS::get_singleton()->execute("install_name_tool", install_name_args, true);
+ OS::get_singleton()->execute("install_name_tool", install_name_args);
}
// Creating Info.plist
@@ -1345,7 +1345,7 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset>
Vector<String> plugin_embedded_dependencies;
Vector<String> plugin_files;
- Vector<PluginConfig> enabled_plugins = get_enabled_plugins(p_preset);
+ Vector<PluginConfigIOS> enabled_plugins = get_enabled_plugins(p_preset);
Vector<String> added_linked_dependenciy_names;
Vector<String> added_embedded_dependenciy_names;
@@ -1354,19 +1354,14 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset>
Error err;
for (int i = 0; i < enabled_plugins.size(); i++) {
- PluginConfig plugin = enabled_plugins[i];
+ PluginConfigIOS plugin = enabled_plugins[i];
// Export plugin binary.
- if (!plugin.supports_targets) {
- err = _copy_asset(dest_dir, plugin.binary, nullptr, true, true, r_exported_assets);
- } else {
- String plugin_binary_dir = plugin.binary.get_base_dir();
- String plugin_name_prefix = plugin.binary.get_basename().get_file();
- String plugin_file = plugin_name_prefix + "." + (p_debug ? "debug" : "release") + ".a";
- String result_file_name = plugin.binary.get_file();
-
- err = _copy_asset(dest_dir, plugin_binary_dir.plus_file(plugin_file), &result_file_name, true, true, r_exported_assets);
- }
+ String plugin_main_binary = get_plugin_main_binary(plugin, p_debug);
+ String plugin_binary_result_file = plugin.binary.get_file();
+ // We shouldn't embed .xcframework that contains static libraries.
+ // Static libraries are not embedded anyway.
+ err = _copy_asset(dest_dir, plugin_main_binary, &plugin_binary_result_file, true, false, r_exported_assets);
ERR_FAIL_COND_V(err, err);
@@ -1848,7 +1843,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
archive_args.push_back("archive");
archive_args.push_back("-archivePath");
archive_args.push_back(archive_path);
- err = OS::get_singleton()->execute("xcodebuild", archive_args, true);
+ err = OS::get_singleton()->execute("xcodebuild", archive_args);
ERR_FAIL_COND_V(err, err);
if (ep.step("Making .ipa", 4)) {
@@ -1863,7 +1858,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
export_args.push_back("-allowProvisioningUpdates");
export_args.push_back("-exportPath");
export_args.push_back(dest_dir);
- err = OS::get_singleton()->execute("xcodebuild", export_args, true);
+ err = OS::get_singleton()->execute("xcodebuild", export_args);
ERR_FAIL_COND_V(err, err);
#else
print_line(".ipa can only be built on macOS. Leaving Xcode project without building the package.");
diff --git a/platform/iphone/plugin/godot_plugin_config.h b/platform/iphone/plugin/godot_plugin_config.h
index 89f657821e..72fab13600 100644
--- a/platform/iphone/plugin/godot_plugin_config.h
+++ b/platform/iphone/plugin/godot_plugin_config.h
@@ -35,23 +35,6 @@
#include "core/io/config_file.h"
#include "core/string/ustring.h"
-static const char *PLUGIN_CONFIG_EXT = ".gdip";
-
-static const char *CONFIG_SECTION = "config";
-static const char *CONFIG_NAME_KEY = "name";
-static const char *CONFIG_BINARY_KEY = "binary";
-static const char *CONFIG_INITIALIZE_KEY = "initialization";
-static const char *CONFIG_DEINITIALIZE_KEY = "deinitialization";
-
-static const char *DEPENDENCIES_SECTION = "dependencies";
-static const char *DEPENDENCIES_LINKED_KEY = "linked";
-static const char *DEPENDENCIES_EMBEDDED_KEY = "embedded";
-static const char *DEPENDENCIES_SYSTEM_KEY = "system";
-static const char *DEPENDENCIES_CAPABILITIES_KEY = "capabilities";
-static const char *DEPENDENCIES_FILES_KEY = "files";
-
-static const char *PLIST_SECTION = "plist";
-
/*
The `config` section and fields are required and defined as follow:
- **name**: name of the plugin
@@ -68,7 +51,24 @@ The `plist` section are optional.
- **key**: key and value that would be added in Info.plist file.
*/
-struct PluginConfig {
+struct PluginConfigIOS {
+ inline static const char *PLUGIN_CONFIG_EXT = ".gdip";
+
+ inline static const char *CONFIG_SECTION = "config";
+ inline static const char *CONFIG_NAME_KEY = "name";
+ inline static const char *CONFIG_BINARY_KEY = "binary";
+ inline static const char *CONFIG_INITIALIZE_KEY = "initialization";
+ inline static const char *CONFIG_DEINITIALIZE_KEY = "deinitialization";
+
+ inline static const char *DEPENDENCIES_SECTION = "dependencies";
+ inline static const char *DEPENDENCIES_LINKED_KEY = "linked";
+ inline static const char *DEPENDENCIES_EMBEDDED_KEY = "embedded";
+ inline static const char *DEPENDENCIES_SYSTEM_KEY = "system";
+ inline static const char *DEPENDENCIES_CAPABILITIES_KEY = "capabilities";
+ inline static const char *DEPENDENCIES_FILES_KEY = "files";
+
+ inline static const char *PLIST_SECTION = "plist";
+
// Set to true when the config file is properly loaded.
bool valid_config = false;
bool supports_targets = false;
@@ -159,7 +159,7 @@ static inline Vector<String> resolve_system_dependencies(Vector<String> p_paths)
return paths;
}
-static inline bool validate_plugin(PluginConfig &plugin_config) {
+static inline bool validate_plugin(PluginConfigIOS &plugin_config) {
bool valid_name = !plugin_config.name.is_empty();
bool valid_binary_name = !plugin_config.binary.is_empty();
bool valid_initialize = !plugin_config.initialization_method.is_empty();
@@ -167,16 +167,25 @@ static inline bool validate_plugin(PluginConfig &plugin_config) {
bool fields_value = valid_name && valid_binary_name && valid_initialize && valid_deinitialize;
- if (fields_value && FileAccess::exists(plugin_config.binary)) {
+ if (!fields_value) {
+ return false;
+ }
+
+ String plugin_extension = plugin_config.binary.get_extension().to_lower();
+
+ if ((plugin_extension == "a" && FileAccess::exists(plugin_config.binary)) ||
+ (plugin_extension == "xcframework" && DirAccess::exists(plugin_config.binary))) {
plugin_config.valid_config = true;
plugin_config.supports_targets = false;
- } else if (fields_value) {
+ } else {
String file_path = plugin_config.binary.get_base_dir();
String file_name = plugin_config.binary.get_basename().get_file();
- String release_file_name = file_path.plus_file(file_name + ".release.a");
- String debug_file_name = file_path.plus_file(file_name + ".debug.a");
+ String file_extension = plugin_config.binary.get_extension();
+ String release_file_name = file_path.plus_file(file_name + ".release." + file_extension);
+ String debug_file_name = file_path.plus_file(file_name + ".debug." + file_extension);
- if (FileAccess::exists(release_file_name) && FileAccess::exists(debug_file_name)) {
+ if ((plugin_extension == "a" && FileAccess::exists(release_file_name) && FileAccess::exists(debug_file_name)) ||
+ (plugin_extension == "xcframework" && DirAccess::exists(release_file_name) && DirAccess::exists(debug_file_name))) {
plugin_config.valid_config = true;
plugin_config.supports_targets = true;
}
@@ -185,7 +194,20 @@ static inline bool validate_plugin(PluginConfig &plugin_config) {
return plugin_config.valid_config;
}
-static inline uint64_t get_plugin_modification_time(const PluginConfig &plugin_config, const String &config_path) {
+static inline String get_plugin_main_binary(PluginConfigIOS &plugin_config, bool p_debug) {
+ if (!plugin_config.supports_targets) {
+ return plugin_config.binary;
+ }
+
+ String plugin_binary_dir = plugin_config.binary.get_base_dir();
+ String plugin_name_prefix = plugin_config.binary.get_basename().get_file();
+ String plugin_extension = plugin_config.binary.get_extension();
+ String plugin_file = plugin_name_prefix + "." + (p_debug ? "debug" : "release") + "." + plugin_extension;
+
+ return plugin_binary_dir.plus_file(plugin_file);
+}
+
+static inline uint64_t get_plugin_modification_time(const PluginConfigIOS &plugin_config, const String &config_path) {
uint64_t last_updated = FileAccess::get_modified_time(config_path);
if (!plugin_config.supports_targets) {
@@ -203,8 +225,8 @@ static inline uint64_t get_plugin_modification_time(const PluginConfig &plugin_c
return last_updated;
}
-static inline PluginConfig load_plugin_config(Ref<ConfigFile> config_file, const String &path) {
- PluginConfig plugin_config = {};
+static inline PluginConfigIOS load_plugin_config(Ref<ConfigFile> config_file, const String &path) {
+ PluginConfigIOS plugin_config = {};
if (!config_file.is_valid()) {
return plugin_config;
@@ -218,18 +240,18 @@ static inline PluginConfig load_plugin_config(Ref<ConfigFile> config_file, const
String config_base_dir = path.get_base_dir();
- plugin_config.name = config_file->get_value(CONFIG_SECTION, CONFIG_NAME_KEY, String());
- plugin_config.initialization_method = config_file->get_value(CONFIG_SECTION, CONFIG_INITIALIZE_KEY, String());
- plugin_config.deinitialization_method = config_file->get_value(CONFIG_SECTION, CONFIG_DEINITIALIZE_KEY, String());
+ plugin_config.name = config_file->get_value(PluginConfigIOS::CONFIG_SECTION, PluginConfigIOS::CONFIG_NAME_KEY, String());
+ plugin_config.initialization_method = config_file->get_value(PluginConfigIOS::CONFIG_SECTION, PluginConfigIOS::CONFIG_INITIALIZE_KEY, String());
+ plugin_config.deinitialization_method = config_file->get_value(PluginConfigIOS::CONFIG_SECTION, PluginConfigIOS::CONFIG_DEINITIALIZE_KEY, String());
- String binary_path = config_file->get_value(CONFIG_SECTION, CONFIG_BINARY_KEY, String());
+ String binary_path = config_file->get_value(PluginConfigIOS::CONFIG_SECTION, PluginConfigIOS::CONFIG_BINARY_KEY, String());
plugin_config.binary = resolve_local_dependency_path(config_base_dir, binary_path);
- if (config_file->has_section(DEPENDENCIES_SECTION)) {
- Vector<String> linked_dependencies = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_LINKED_KEY, Vector<String>());
- Vector<String> embedded_dependencies = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_EMBEDDED_KEY, Vector<String>());
- Vector<String> system_dependencies = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_SYSTEM_KEY, Vector<String>());
- Vector<String> files = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_FILES_KEY, Vector<String>());
+ if (config_file->has_section(PluginConfigIOS::DEPENDENCIES_SECTION)) {
+ Vector<String> linked_dependencies = config_file->get_value(PluginConfigIOS::DEPENDENCIES_SECTION, PluginConfigIOS::DEPENDENCIES_LINKED_KEY, Vector<String>());
+ Vector<String> embedded_dependencies = config_file->get_value(PluginConfigIOS::DEPENDENCIES_SECTION, PluginConfigIOS::DEPENDENCIES_EMBEDDED_KEY, Vector<String>());
+ Vector<String> system_dependencies = config_file->get_value(PluginConfigIOS::DEPENDENCIES_SECTION, PluginConfigIOS::DEPENDENCIES_SYSTEM_KEY, Vector<String>());
+ Vector<String> files = config_file->get_value(PluginConfigIOS::DEPENDENCIES_SECTION, PluginConfigIOS::DEPENDENCIES_FILES_KEY, Vector<String>());
plugin_config.linked_dependencies = resolve_local_dependencies(config_base_dir, linked_dependencies);
plugin_config.embedded_dependencies = resolve_local_dependencies(config_base_dir, embedded_dependencies);
@@ -237,15 +259,15 @@ static inline PluginConfig load_plugin_config(Ref<ConfigFile> config_file, const
plugin_config.files_to_copy = resolve_local_dependencies(config_base_dir, files);
- plugin_config.capabilities = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_CAPABILITIES_KEY, Vector<String>());
+ plugin_config.capabilities = config_file->get_value(PluginConfigIOS::DEPENDENCIES_SECTION, PluginConfigIOS::DEPENDENCIES_CAPABILITIES_KEY, Vector<String>());
}
- if (config_file->has_section(PLIST_SECTION)) {
+ if (config_file->has_section(PluginConfigIOS::PLIST_SECTION)) {
List<String> keys;
- config_file->get_section_keys(PLIST_SECTION, &keys);
+ config_file->get_section_keys(PluginConfigIOS::PLIST_SECTION, &keys);
for (int i = 0; i < keys.size(); i++) {
- String value = config_file->get_value(PLIST_SECTION, keys[i], String());
+ String value = config_file->get_value(PluginConfigIOS::PLIST_SECTION, keys[i], String());
if (value.is_empty()) {
continue;
diff --git a/platform/javascript/SCsub b/platform/javascript/SCsub
index 1d3f96a6b8..b0302a5f88 100644
--- a/platform/javascript/SCsub
+++ b/platform/javascript/SCsub
@@ -27,8 +27,13 @@ if env["tools"]:
sys_env.AddJSLibraries(["js/libs/library_godot_editor_tools.js"])
if env["javascript_eval"]:
sys_env.AddJSLibraries(["js/libs/library_godot_eval.js"])
+
for lib in sys_env["JS_LIBS"]:
sys_env.Append(LINKFLAGS=["--js-library", lib])
+for js in env["JS_PRE"]:
+ sys_env.Append(LINKFLAGS=["--pre-js", env.File(js).path])
+for ext in env["JS_EXTERNS"]:
+ sys_env["ENV"]["EMCC_CLOSURE_ARGS"] += " --externs " + ext.path
build = []
if env["gdnative_enabled"]:
@@ -66,16 +71,8 @@ else:
build = sys_env.Program(build_targets, javascript_files + ["javascript_runtime.cpp"])
sys_env.Depends(build[0], sys_env["JS_LIBS"])
-
-if "JS_PRE" in env:
- for js in env["JS_PRE"]:
- env.Append(LINKFLAGS=["--pre-js", env.File(js).path])
- env.Depends(build, env["JS_PRE"])
-
-if "JS_EXTERNS" in env:
- for ext in env["JS_EXTERNS"]:
- env["ENV"]["EMCC_CLOSURE_ARGS"] += " --externs " + ext.path
- env.Depends(build, env["JS_EXTERNS"])
+sys_env.Depends(build[0], sys_env["JS_PRE"])
+sys_env.Depends(build[0], sys_env["JS_EXTERNS"])
engine = [
"js/engine/preloader.js",
diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py
index 7d501e94b2..0d57f8aad1 100644
--- a/platform/javascript/detect.py
+++ b/platform/javascript/detect.py
@@ -131,7 +131,10 @@ def configure(env):
jscc = env.Builder(generator=run_closure_compiler, suffix=".cc.js", src_suffix=".js")
env.Append(BUILDERS={"BuildJS": jscc})
- # Add helper method for adding libraries.
+ # Add helper method for adding libraries, externs, pre-js.
+ env["JS_LIBS"] = []
+ env["JS_PRE"] = []
+ env["JS_EXTERNS"] = []
env.AddMethod(add_js_libraries, "AddJSLibraries")
env.AddMethod(add_js_pre, "AddJSPre")
env.AddMethod(add_js_externs, "AddJSExterns")
diff --git a/platform/javascript/display_server_javascript.cpp b/platform/javascript/display_server_javascript.cpp
index f10627b0b6..915e8eeacf 100644
--- a/platform/javascript/display_server_javascript.cpp
+++ b/platform/javascript/display_server_javascript.cpp
@@ -558,57 +558,51 @@ bool DisplayServerJavaScript::screen_is_touchscreen(int p_screen) const {
}
// Gamepad
-
-EM_BOOL DisplayServerJavaScript::gamepad_change_callback(int p_event_type, const EmscriptenGamepadEvent *p_event, void *p_user_data) {
+void DisplayServerJavaScript::gamepad_callback(int p_index, int p_connected, const char *p_id, const char *p_guid) {
Input *input = Input::get_singleton();
- if (p_event_type == EMSCRIPTEN_EVENT_GAMEPADCONNECTED) {
- String guid = "";
- if (String::utf8(p_event->mapping) == "standard")
- guid = "Default HTML5 Gamepad";
- input->joy_connection_changed(p_event->index, true, String::utf8(p_event->id), guid);
+ if (p_connected) {
+ input->joy_connection_changed(p_index, true, String::utf8(p_id), String::utf8(p_guid));
} else {
- input->joy_connection_changed(p_event->index, false, "");
+ input->joy_connection_changed(p_index, false, "");
}
- return true;
}
void DisplayServerJavaScript::process_joypads() {
- int joypad_count = emscripten_get_num_gamepads();
Input *input = Input::get_singleton();
- for (int joypad = 0; joypad < joypad_count; joypad++) {
- EmscriptenGamepadEvent state;
- EMSCRIPTEN_RESULT query_result = emscripten_get_gamepad_status(joypad, &state);
- // Chromium reserves gamepads slots, so NO_DATA is an expected result.
- ERR_CONTINUE(query_result != EMSCRIPTEN_RESULT_SUCCESS &&
- query_result != EMSCRIPTEN_RESULT_NO_DATA);
- if (query_result == EMSCRIPTEN_RESULT_SUCCESS && state.connected) {
- int button_count = MIN(state.numButtons, 18);
- int axis_count = MIN(state.numAxes, 8);
- for (int button = 0; button < button_count; button++) {
- float value = state.analogButton[button];
- input->joy_button(joypad, button, value);
- }
- for (int axis = 0; axis < axis_count; axis++) {
+ int32_t pads = godot_js_display_gamepad_sample_count();
+ int32_t s_btns_num = 0;
+ int32_t s_axes_num = 0;
+ int32_t s_standard = 0;
+ float s_btns[16];
+ float s_axes[10];
+ for (int idx = 0; idx < pads; idx++) {
+ int err = godot_js_display_gamepad_sample_get(idx, s_btns, &s_btns_num, s_axes, &s_axes_num, &s_standard);
+ if (err) {
+ continue;
+ }
+ for (int b = 0; b < s_btns_num; b++) {
+ float value = s_btns[b];
+ // Buttons 6 and 7 in the standard mapping need to be
+ // axis to be handled as JOY_AXIS_TRIGGER by Godot.
+ if (s_standard && (b == 6 || b == 7)) {
Input::JoyAxis joy_axis;
- joy_axis.min = -1;
- joy_axis.value = state.axis[axis];
- input->joy_axis(joypad, axis, joy_axis);
+ joy_axis.min = 0;
+ joy_axis.value = value;
+ int a = b == 6 ? JOY_AXIS_TRIGGER_LEFT : JOY_AXIS_TRIGGER_RIGHT;
+ input->joy_axis(idx, a, joy_axis);
+ } else {
+ input->joy_button(idx, b, value);
}
}
+ for (int a = 0; a < s_axes_num; a++) {
+ Input::JoyAxis joy_axis;
+ joy_axis.min = -1;
+ joy_axis.value = s_axes[a];
+ input->joy_axis(idx, a, joy_axis);
+ }
}
}
-#if 0
-bool DisplayServerJavaScript::is_joy_known(int p_device) {
- return Input::get_singleton()->is_joy_mapped(p_device);
-}
-
-
-String DisplayServerJavaScript::get_joy_guid(int p_device) const {
- return Input::get_singleton()->get_joy_guid_remapped(p_device);
-}
-#endif
-
Vector<String> DisplayServerJavaScript::get_rendering_drivers_func() {
Vector<String> drivers;
drivers.push_back("dummy");
@@ -766,9 +760,6 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive
#define SET_EM_WINDOW_CALLBACK(ev, cb) \
result = emscripten_set_##ev##_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, &cb); \
EM_CHECK(ev)
-#define SET_EM_CALLBACK_NOTARGET(ev, cb) \
- result = emscripten_set_##ev##_callback(nullptr, true, &cb); \
- EM_CHECK(ev)
// These callbacks from Emscripten's html5.h suffice to access most
// JavaScript APIs.
SET_EM_CALLBACK(canvas_id, mousedown, mouse_button_callback)
@@ -783,9 +774,6 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive
SET_EM_CALLBACK(canvas_id, keypress, keypress_callback)
SET_EM_CALLBACK(canvas_id, keyup, keyup_callback)
SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, fullscreenchange, fullscreen_change_callback)
- SET_EM_CALLBACK_NOTARGET(gamepadconnected, gamepad_change_callback)
- SET_EM_CALLBACK_NOTARGET(gamepaddisconnected, gamepad_change_callback)
-#undef SET_EM_CALLBACK_NOTARGET
#undef SET_EM_CALLBACK
#undef EM_CHECK
@@ -798,6 +786,7 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive
WINDOW_EVENT_FOCUS_OUT);
godot_js_display_paste_cb(update_clipboard_callback);
godot_js_display_drop_files_cb(drop_files_js_callback);
+ godot_js_display_gamepad_cb(&DisplayServerJavaScript::gamepad_callback);
Input::get_singleton()->set_event_dispatch_function(_dispatch_input_event);
}
@@ -1026,8 +1015,9 @@ bool DisplayServerJavaScript::can_any_window_draw() const {
}
void DisplayServerJavaScript::process_events() {
- if (emscripten_sample_gamepad_data() == EMSCRIPTEN_RESULT_SUCCESS)
+ if (godot_js_display_gamepad_sample() == OK) {
process_joypads();
+ }
}
int DisplayServerJavaScript::get_current_video_driver() const {
diff --git a/platform/javascript/display_server_javascript.h b/platform/javascript/display_server_javascript.h
index 916be1ae45..e28fbc56f3 100644
--- a/platform/javascript/display_server_javascript.h
+++ b/platform/javascript/display_server_javascript.h
@@ -86,7 +86,7 @@ private:
static EM_BOOL touch_press_callback(int p_event_type, const EmscriptenTouchEvent *p_event, void *p_user_data);
static EM_BOOL touchmove_callback(int p_event_type, const EmscriptenTouchEvent *p_event, void *p_user_data);
- static EM_BOOL gamepad_change_callback(int p_event_type, const EmscriptenGamepadEvent *p_event, void *p_user_data);
+ static void gamepad_callback(int p_index, int p_connected, const char *p_id, const char *p_guid);
void process_joypads();
static Vector<String> get_rendering_drivers_func();
diff --git a/platform/javascript/emscripten_helpers.py b/platform/javascript/emscripten_helpers.py
index 278186e4c0..8b8c492e22 100644
--- a/platform/javascript/emscripten_helpers.py
+++ b/platform/javascript/emscripten_helpers.py
@@ -22,18 +22,12 @@ def create_engine_file(env, target, source, externs):
def add_js_libraries(env, libraries):
- if "JS_LIBS" not in env:
- env["JS_LIBS"] = []
env.Append(JS_LIBS=env.File(libraries))
def add_js_pre(env, js_pre):
- if "JS_PRE" not in env:
- env["JS_PRE"] = []
env.Append(JS_PRE=env.File(js_pre))
def add_js_externs(env, externs):
- if "JS_EXTERNS" not in env:
- env["JS_EXTERNS"] = []
env.Append(JS_EXTERNS=env.File(externs))
diff --git a/platform/javascript/godot_js.h b/platform/javascript/godot_js.h
index 5b98253b08..0006848756 100644
--- a/platform/javascript/godot_js.h
+++ b/platform/javascript/godot_js.h
@@ -76,6 +76,12 @@ extern int godot_js_display_cursor_is_hidden();
extern void godot_js_display_cursor_set_custom_shape(const char *p_shape, const uint8_t *p_ptr, int p_len, int p_hotspot_x, int p_hotspot_y);
extern void godot_js_display_cursor_set_visible(int p_visible);
+// Display gamepad
+extern char *godot_js_display_gamepad_cb(void (*p_on_change)(int p_index, int p_connected, const char *p_id, const char *p_guid));
+extern int godot_js_display_gamepad_sample();
+extern int godot_js_display_gamepad_sample_count();
+extern int godot_js_display_gamepad_sample_get(int p_idx, float r_btns[16], int32_t *r_btns_num, float r_axes[10], int32_t *r_axes_num, int32_t *r_standard);
+
// Display listeners
extern void godot_js_display_notification_cb(void (*p_callback)(int p_notification), int p_enter, int p_exit, int p_in, int p_out);
extern void godot_js_display_paste_cb(void (*p_callback)(const char *p_text));
diff --git a/platform/javascript/http_client_javascript.cpp b/platform/javascript/http_client_javascript.cpp
index 44819c495c..c8c48dd582 100644
--- a/platform/javascript/http_client_javascript.cpp
+++ b/platform/javascript/http_client_javascript.cpp
@@ -220,13 +220,13 @@ Error HTTPClient::poll() {
has_polled = true;
} else {
// forcing synchronous requests is not possible on the web
- if (last_polling_frame == Engine::get_singleton()->get_idle_frames()) {
+ if (last_polling_frame == Engine::get_singleton()->get_process_frames()) {
WARN_PRINT("HTTPClient polled multiple times in one frame, "
"but request cannot progress more than once per "
"frame on the HTML5 platform.");
}
}
- last_polling_frame = Engine::get_singleton()->get_idle_frames();
+ last_polling_frame = Engine::get_singleton()->get_process_frames();
#endif
polled_response_code = godot_xhr_get_status(xhr_id);
diff --git a/platform/javascript/javascript_main.cpp b/platform/javascript/javascript_main.cpp
index 5656ecd7dc..0b8af70b13 100644
--- a/platform/javascript/javascript_main.cpp
+++ b/platform/javascript/javascript_main.cpp
@@ -87,7 +87,7 @@ extern EMSCRIPTEN_KEEPALIVE int godot_js_main(int argc, char *argv[]) {
ResourceLoader::set_abort_on_missing_resources(false);
Main::start();
- os->get_main_loop()->init();
+ os->get_main_loop()->initialize();
emscripten_set_main_loop(main_loop_callback, -1, false);
// Immediately run the first iteration.
// We are inside an animation frame, we want to immediately draw on the newly setup canvas.
diff --git a/platform/javascript/js/libs/library_godot_display.js b/platform/javascript/js/libs/library_godot_display.js
index d1f4d9595b..2977b7c122 100644
--- a/platform/javascript/js/libs/library_godot_display.js
+++ b/platform/javascript/js/libs/library_godot_display.js
@@ -269,13 +269,140 @@ const GodotDisplayCursor = {
};
mergeInto(LibraryManager.library, GodotDisplayCursor);
+/*
+ * Display Gamepad API helper.
+ */
+const GodotDisplayGamepads = {
+ $GodotDisplayGamepads__deps: ['$GodotRuntime', '$GodotDisplayListeners'],
+ $GodotDisplayGamepads: {
+ samples: [],
+
+ get_pads: function () {
+ try {
+ // Will throw in iframe when permission is denied.
+ // Will throw/warn in the future for insecure contexts.
+ // See https://github.com/w3c/gamepad/pull/120
+ const pads = navigator.getGamepads();
+ if (pads) {
+ return pads;
+ }
+ return [];
+ } catch (e) {
+ return [];
+ }
+ },
+
+ get_samples: function () {
+ return GodotDisplayGamepads.samples;
+ },
+
+ get_sample: function (index) {
+ const samples = GodotDisplayGamepads.samples;
+ return index < samples.length ? samples[index] : null;
+ },
+
+ sample: function () {
+ const pads = GodotDisplayGamepads.get_pads();
+ const samples = [];
+ for (let i = 0; i < pads.length; i++) {
+ const pad = pads[i];
+ if (!pad) {
+ samples.push(null);
+ continue;
+ }
+ const s = {
+ standard: pad.mapping === 'standard',
+ buttons: [],
+ axes: [],
+ connected: pad.connected,
+ };
+ for (let b = 0; b < pad.buttons.length; b++) {
+ s.buttons.push(pad.buttons[b].value);
+ }
+ for (let a = 0; a < pad.axes.length; a++) {
+ s.axes.push(pad.axes[a]);
+ }
+ samples.push(s);
+ }
+ GodotDisplayGamepads.samples = samples;
+ },
+
+ init: function (onchange) {
+ GodotDisplayListeners.samples = [];
+ function add(pad) {
+ const guid = GodotDisplayGamepads.get_guid(pad);
+ const c_id = GodotRuntime.allocString(pad.id);
+ const c_guid = GodotRuntime.allocString(guid);
+ onchange(pad.index, 1, c_id, c_guid);
+ GodotRuntime.free(c_id);
+ GodotRuntime.free(c_guid);
+ }
+ const pads = GodotDisplayGamepads.get_pads();
+ for (let i = 0; i < pads.length; i++) {
+ // Might be reserved space.
+ if (pads[i]) {
+ add(pads[i]);
+ }
+ }
+ GodotDisplayListeners.add(window, 'gamepadconnected', function (evt) {
+ add(evt.gamepad);
+ }, false);
+ GodotDisplayListeners.add(window, 'gamepaddisconnected', function (evt) {
+ onchange(evt.gamepad.index, 0);
+ }, false);
+ },
+
+ get_guid: function (pad) {
+ if (pad.mapping) {
+ return pad.mapping;
+ }
+ const ua = navigator.userAgent;
+ let os = 'Unknown';
+ if (ua.indexOf('Android') >= 0) {
+ os = 'Android';
+ } else if (ua.indexOf('Linux') >= 0) {
+ os = 'Linux';
+ } else if (ua.indexOf('iPhone') >= 0) {
+ os = 'iOS';
+ } else if (ua.indexOf('Macintosh') >= 0) {
+ // Updated iPads will fall into this category.
+ os = 'MacOSX';
+ } else if (ua.indexOf('Windows') >= 0) {
+ os = 'Windows';
+ }
+
+ const id = pad.id;
+ // Chrom* style: NAME (Vendor: xxxx Product: xxxx)
+ const exp1 = /vendor: ([0-9a-f]{4}) product: ([0-9a-f]{4})/i;
+ // Firefox/Safari style (safari may remove leading zeores)
+ const exp2 = /^([0-9a-f]+)-([0-9a-f]+)-/i;
+ let vendor = '';
+ let product = '';
+ if (exp1.test(id)) {
+ const match = exp1.exec(id);
+ vendor = match[1].padStart(4, '0');
+ product = match[2].padStart(4, '0');
+ } else if (exp2.test(id)) {
+ const match = exp2.exec(id);
+ vendor = match[1].padStart(4, '0');
+ product = match[2].padStart(4, '0');
+ }
+ if (!vendor || !product) {
+ return `${os}Unknown`;
+ }
+ return os + vendor + product;
+ },
+ },
+};
+mergeInto(LibraryManager.library, GodotDisplayGamepads);
+
/**
* Display server interface.
*
* Exposes all the functions needed by DisplayServer implementation.
*/
const GodotDisplay = {
- $GodotDisplay__deps: ['$GodotConfig', '$GodotRuntime', '$GodotDisplayCursor', '$GodotDisplayListeners', '$GodotDisplayDragDrop'],
+ $GodotDisplay__deps: ['$GodotConfig', '$GodotRuntime', '$GodotDisplayCursor', '$GodotDisplayListeners', '$GodotDisplayDragDrop', '$GodotDisplayGamepads'],
$GodotDisplay: {
window_icon: '',
},
@@ -491,6 +618,49 @@ const GodotDisplay = {
}, false);
GodotDisplayListeners.add(canvas, 'drop', GodotDisplayDragDrop.handler(dropFiles));
},
+
+ /*
+ * Gamepads
+ */
+ godot_js_display_gamepad_cb__sig: 'vi',
+ godot_js_display_gamepad_cb: function (change_cb) {
+ const onchange = GodotRuntime.get_func(change_cb);
+ GodotDisplayGamepads.init(onchange);
+ },
+
+ godot_js_display_gamepad_sample_count__sig: 'i',
+ godot_js_display_gamepad_sample_count: function () {
+ return GodotDisplayGamepads.get_samples().length;
+ },
+
+ godot_js_display_gamepad_sample__sig: 'i',
+ godot_js_display_gamepad_sample: function () {
+ GodotDisplayGamepads.sample();
+ return 0;
+ },
+
+ godot_js_display_gamepad_sample_get__sig: 'iiiiiii',
+ godot_js_display_gamepad_sample_get: function (p_index, r_btns, r_btns_num, r_axes, r_axes_num, r_standard) {
+ const sample = GodotDisplayGamepads.get_sample(p_index);
+ if (!sample || !sample.connected) {
+ return 1;
+ }
+ const btns = sample.buttons;
+ const btns_len = btns.length < 16 ? btns.length : 16;
+ for (let i = 0; i < btns_len; i++) {
+ GodotRuntime.setHeapValue(r_btns + (i << 2), btns[i], 'float');
+ }
+ GodotRuntime.setHeapValue(r_btns_num, btns_len, 'i32');
+ const axes = sample.axes;
+ const axes_len = axes.length < 10 ? axes.length : 10;
+ for (let i = 0; i < axes_len; i++) {
+ GodotRuntime.setHeapValue(r_axes + (i << 2), axes[i], 'float');
+ }
+ GodotRuntime.setHeapValue(r_axes_num, axes_len, 'i32');
+ const is_standard = sample.standard ? 1 : 0;
+ GodotRuntime.setHeapValue(r_standard, is_standard, 'i32');
+ return 0;
+ },
};
autoAddDeps(GodotDisplay, '$GodotDisplay');
diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp
index 3fb5d4ad6a..b922b2ba91 100644
--- a/platform/javascript/os_javascript.cpp
+++ b/platform/javascript/os_javascript.cpp
@@ -106,14 +106,18 @@ void OS_JavaScript::finalize() {
// Miscellaneous
-Error OS_JavaScript::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex) {
+Error OS_JavaScript::execute(const String &p_path, const List<String> &p_arguments, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex) {
+ return create_process(p_path, p_arguments);
+}
+
+Error OS_JavaScript::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id) {
Array args;
for (const List<String>::Element *E = p_arguments.front(); E; E = E->next()) {
args.push_back(E->get());
}
String json_args = JSON::print(args);
int failed = godot_js_os_execute(json_args.utf8().get_data());
- ERR_FAIL_COND_V_MSG(failed, ERR_UNAVAILABLE, "OS::execute() must be implemented in JavaScript via 'engine.setOnExecute' if required.");
+ ERR_FAIL_COND_V_MSG(failed, ERR_UNAVAILABLE, "OS::execute() or create_process() must be implemented in JavaScript via 'engine.setOnExecute' if required.");
return OK;
}
diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h
index 9c8da0c898..8db62d9d1c 100644
--- a/platform/javascript/os_javascript.h
+++ b/platform/javascript/os_javascript.h
@@ -70,7 +70,8 @@ public:
MainLoop *get_main_loop() const override;
bool main_loop_iterate();
- Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking = true, ProcessID *r_child_id = nullptr, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr) override;
+ 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) override;
+ Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr) override;
Error kill(const ProcessID &p_pid) override;
int get_process_id() const override;
diff --git a/platform/linuxbsd/crash_handler_linuxbsd.cpp b/platform/linuxbsd/crash_handler_linuxbsd.cpp
index 90e34f8e77..ea0222cb19 100644
--- a/platform/linuxbsd/crash_handler_linuxbsd.cpp
+++ b/platform/linuxbsd/crash_handler_linuxbsd.cpp
@@ -104,7 +104,7 @@ static void handle_crash(int sig) {
// Try to get the file/line number using addr2line
int ret;
- Error err = OS::get_singleton()->execute(String("addr2line"), args, true, nullptr, &output, &ret);
+ Error err = OS::get_singleton()->execute(String("addr2line"), args, &output, &ret);
if (err == OK) {
output.erase(output.length() - 1, 1);
}
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp
index 1ee5cd3923..00b90923de 100644
--- a/platform/linuxbsd/display_server_x11.cpp
+++ b/platform/linuxbsd/display_server_x11.cpp
@@ -191,7 +191,7 @@ void DisplayServerX11::alert(const String &p_alert, const String &p_title) {
}
if (program.length()) {
- OS::get_singleton()->execute(program, args, true);
+ OS::get_singleton()->execute(program, args);
} else {
print_line(p_alert);
}
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index 68290bb4ec..44b3930d6c 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -128,7 +128,7 @@ Error OS_LinuxBSD::shell_open(String p_uri) {
args.push_back(p_uri);
// Agnostic
- ok = execute("xdg-open", args, true, nullptr, nullptr, &err_code);
+ ok = execute("xdg-open", args, nullptr, &err_code);
if (ok == OK && !err_code) {
return OK;
} else if (err_code == 2) {
@@ -136,25 +136,25 @@ Error OS_LinuxBSD::shell_open(String p_uri) {
}
// GNOME
args.push_front("open"); // The command is `gio open`, so we need to add it to args
- ok = execute("gio", args, true, nullptr, nullptr, &err_code);
+ ok = execute("gio", args, nullptr, &err_code);
if (ok == OK && !err_code) {
return OK;
} else if (err_code == 2) {
return ERR_FILE_NOT_FOUND;
}
args.pop_front();
- ok = execute("gvfs-open", args, true, nullptr, nullptr, &err_code);
+ ok = execute("gvfs-open", args, nullptr, &err_code);
if (ok == OK && !err_code) {
return OK;
} else if (err_code == 2) {
return ERR_FILE_NOT_FOUND;
}
// KDE
- ok = execute("kde-open5", args, true, nullptr, nullptr, &err_code);
+ ok = execute("kde-open5", args, nullptr, &err_code);
if (ok == OK && !err_code) {
return OK;
}
- ok = execute("kde-open", args, true, nullptr, nullptr, &err_code);
+ ok = execute("kde-open", args, nullptr, &err_code);
return !err_code ? ok : FAILED;
}
@@ -232,7 +232,7 @@ String OS_LinuxBSD::get_system_dir(SystemDir p_dir) const {
String pipe;
List<String> arg;
arg.push_back(xdgparam);
- Error err = const_cast<OS_LinuxBSD *>(this)->execute("xdg-user-dir", arg, true, nullptr, &pipe);
+ Error err = const_cast<OS_LinuxBSD *>(this)->execute("xdg-user-dir", arg, &pipe);
if (err != OK) {
return ".";
}
@@ -307,7 +307,7 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
List<String> args;
args.push_back(p_path);
args.push_front("trash"); // The command is `gio trash <file_name>` so we need to add it to args.
- Error result = execute("gio", args, true, nullptr, nullptr, &err_code); // For GNOME based machines.
+ Error result = execute("gio", args, nullptr, &err_code); // For GNOME based machines.
if (result == OK && !err_code) {
return OK;
} else if (err_code == 2) {
@@ -317,7 +317,7 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
args.pop_front();
args.push_front("move");
args.push_back("trash:/"); // The command is `kioclient5 move <file_name> trash:/`.
- result = execute("kioclient5", args, true, nullptr, nullptr, &err_code); // For KDE based machines.
+ result = execute("kioclient5", args, nullptr, &err_code); // For KDE based machines.
if (result == OK && !err_code) {
return OK;
} else if (err_code == 2) {
@@ -326,7 +326,7 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
args.pop_front();
args.pop_back();
- result = execute("gvfs-trash", args, true, nullptr, nullptr, &err_code); // For older Linux machines.
+ result = execute("gvfs-trash", args, nullptr, &err_code); // For older Linux machines.
if (result == OK && !err_code) {
return OK;
} else if (err_code == 2) {
@@ -432,7 +432,7 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
mv_args.push_back(trash_path + "/files");
{
int retval;
- Error err = execute("mv", mv_args, true, nullptr, nullptr, &retval);
+ Error err = execute("mv", mv_args, nullptr, &retval);
// Issue an error if "mv" failed to move the given resource to the trash can.
if (err != OK || retval != 0) {
diff --git a/platform/osx/crash_handler_osx.mm b/platform/osx/crash_handler_osx.mm
index 4d6ed41a73..147ce26779 100644
--- a/platform/osx/crash_handler_osx.mm
+++ b/platform/osx/crash_handler_osx.mm
@@ -135,7 +135,7 @@ static void handle_crash(int sig) {
int ret;
String out = "";
- Error err = OS::get_singleton()->execute(String("atos"), args, true, NULL, &out, &ret);
+ Error err = OS::get_singleton()->execute(String("atos"), args, &out, &ret);
if (err == OK && out.substr(0, 2) != "0x") {
out.erase(out.length() - 1, 1);
output = out;
diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm
index bb3c1d47b7..2d43454501 100644
--- a/platform/osx/display_server_osx.mm
+++ b/platform/osx/display_server_osx.mm
@@ -256,9 +256,7 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
List<String> args;
args.push_back(((OS_OSX *)(OS_OSX::get_singleton()))->open_with_filename);
String exec = OS::get_singleton()->get_executable_path();
-
- OS::ProcessID pid = 0;
- OS::get_singleton()->execute(exec, args, false, &pid);
+ OS::get_singleton()->create_process(exec, args);
}
#endif
return YES;
diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp
index 752b119958..337cfd6808 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/osx/export/export.cpp
@@ -419,7 +419,7 @@ Error EditorExportPlatformOSX::_notarize(const Ref<EditorExportPreset> &p_preset
args.push_back(p_path);
String str;
- Error err = OS::get_singleton()->execute("xcrun", args, true, nullptr, &str, nullptr, true);
+ Error err = OS::get_singleton()->execute("xcrun", args, &str, nullptr, true);
ERR_FAIL_COND_V(err != OK, err);
print_line("altool (" + p_path + "):\n" + str);
@@ -470,7 +470,7 @@ Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_prese
args.push_back(p_path);
String str;
- Error err = OS::get_singleton()->execute("codesign", args, true, nullptr, &str, nullptr, true);
+ Error err = OS::get_singleton()->execute("codesign", args, &str, nullptr, true);
ERR_FAIL_COND_V(err != OK, err);
print_line("codesign (" + p_path + "):\n" + str);
@@ -504,7 +504,7 @@ Error EditorExportPlatformOSX::_create_dmg(const String &p_dmg_path, const Strin
args.push_back(p_app_path_name);
String str;
- Error err = OS::get_singleton()->execute("hdiutil", args, true, nullptr, &str, nullptr, true);
+ Error err = OS::get_singleton()->execute("hdiutil", args, &str, nullptr, true);
ERR_FAIL_COND_V(err != OK, err);
print_line("hdiutil returned: " + str);
diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp
index 860448ceac..1aad2bfa1a 100644
--- a/platform/uwp/export/export.cpp
+++ b/platform/uwp/export/export.cpp
@@ -760,7 +760,7 @@ class EditorExportPlatformUWP : public EditorExportPlatform {
result = result.replace("$version_string$", version);
Platform arch = (Platform)(int)p_preset->get("architecture/target");
- String architecture = arch == ARM ? "arm" : arch == X86 ? "x86" : "x64";
+ String architecture = arch == ARM ? "arm" : (arch == X86 ? "x86" : "x64");
result = result.replace("$architecture$", architecture);
result = result.replace("$display_name$", String(p_preset->get("package/display_name")).is_empty() ? (String)ProjectSettings::get_singleton()->get("application/config/name") : String(p_preset->get("package/display_name")));
@@ -1411,7 +1411,7 @@ public:
args.push_back(cert_pass);
args.push_back(p_path);
- OS::get_singleton()->execute(signtool_path, args, true);
+ OS::get_singleton()->execute(signtool_path, args);
#endif // WINDOWS_ENABLED
return OK;
diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp
index 18d5d7e08d..f43c4ecdaf 100644
--- a/platform/uwp/os_uwp.cpp
+++ b/platform/uwp/os_uwp.cpp
@@ -39,7 +39,6 @@
#include "drivers/windows/dir_access_windows.h"
#include "drivers/windows/file_access_windows.h"
#include "drivers/windows/mutex_windows.h"
-#include "drivers/windows/rw_lock_windows.h"
#include "drivers/windows/semaphore_windows.h"
#include "main/main.h"
#include "platform/windows/windows_terminal_logger.h"
@@ -132,7 +131,6 @@ void OS_UWP::initialize_core() {
//RedirectIOToConsole();
ThreadUWP::make_default();
- RWLockWindows::make_default();
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_RESOURCES);
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_USERDATA);
@@ -638,7 +636,11 @@ void OS_UWP::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, c
// TODO
}
-Error OS_UWP::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex) {
+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) {
+ return FAILED;
+};
+
+Error OS_UWP::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id) {
return FAILED;
};
diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h
index edc197ad08..a4d3d6d52a 100644
--- a/platform/uwp/os_uwp.h
+++ b/platform/uwp/os_uwp.h
@@ -199,7 +199,8 @@ public:
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, bool p_blocking = true, ProcessID *r_child_id = nullptr, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr);
+ 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);
+ virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr);
virtual Error kill(const ProcessID &p_pid);
virtual bool has_environment(const String &p_var) const;
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index 4a3f91eb21..c8c6a75bf5 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -417,7 +417,7 @@ private:
WNDCLASSEXW wc;
HCURSOR cursors[CURSOR_MAX] = { nullptr };
- CursorShape cursor_shape;
+ CursorShape cursor_shape = CursorShape::CURSOR_ARROW;
Map<CursorShape, Vector<Variant>> cursors_cache;
void _drag_event(WindowID p_window, float p_x, float p_y, int idx);
diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp
index 084a5bee1d..222597b3ff 100644
--- a/platform/windows/export/export.cpp
+++ b/platform/windows/export/export.cpp
@@ -173,11 +173,11 @@ void EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset>
}
#ifdef WINDOWS_ENABLED
- OS::get_singleton()->execute(rcedit_path, args, true);
+ OS::get_singleton()->execute(rcedit_path, args);
#else
// On non-Windows we need WINE to run rcedit
args.push_front(rcedit_path);
- OS::get_singleton()->execute(wine_path, args, true);
+ OS::get_singleton()->execute(wine_path, args);
#endif
}
@@ -314,7 +314,7 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p
#endif
String str;
- Error err = OS::get_singleton()->execute(signtool_path, args, true, nullptr, &str, nullptr, true);
+ Error err = OS::get_singleton()->execute(signtool_path, args, &str, nullptr, true);
ERR_FAIL_COND_V(err != OK, err);
print_line("codesign (" + p_path + "): " + str);
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 051b69e8d9..3c38c715c1 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -39,7 +39,6 @@
#include "core/version_generated.gen.h"
#include "drivers/windows/dir_access_windows.h"
#include "drivers/windows/file_access_windows.h"
-#include "drivers/windows/rw_lock_windows.h"
#include "drivers/windows/thread_windows.h"
#include "joypad_windows.h"
#include "lang_table.h"
@@ -178,7 +177,6 @@ void OS_Windows::initialize() {
//RedirectIOToConsole();
ThreadWindows::make_default();
- RWLockWindows::make_default();
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_RESOURCES);
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_USERDATA);
@@ -410,24 +408,23 @@ String OS_Windows::_quote_command_line_argument(const String &p_text) const {
return p_text;
}
-Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex) {
+Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex) {
String path = p_path.replace("/", "\\");
+ String command = _quote_command_line_argument(path);
+ for (const List<String>::Element *E = p_arguments.front(); E; E = E->next()) {
+ command += " " + _quote_command_line_argument(E->get());
+ }
- if (p_blocking && r_pipe) {
- String argss = _quote_command_line_argument(path);
- for (const List<String>::Element *E = p_arguments.front(); E; E = E->next()) {
- argss += " " + _quote_command_line_argument(E->get());
- }
-
+ if (r_pipe) {
if (read_stderr) {
- argss += " 2>&1"; // Read stderr too
+ command += " 2>&1"; // Include stderr
}
- // Note: _wpopen is calling command as "cmd.exe /c argss", instead of executing it directly, add extra quotes around full command, to prevent it from stripping quotes in the command.
- argss = _quote_command_line_argument(argss);
-
- FILE *f = _wpopen((LPCWSTR)(argss.utf16().get_data()), L"r");
- ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);
+ // Add extra quotes around the full command, to prevent it from stripping quotes in the command,
+ // because _wpopen calls command as "cmd.exe /c command", instead of executing it directly
+ command = _quote_command_line_argument(command);
+ FILE *f = _wpopen((LPCWSTR)(command.utf16().get_data()), L"r");
+ ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot create pipe from command: " + command);
char buf[65535];
while (fgets(buf, 65535, f)) {
if (p_pipe_mutex) {
@@ -438,20 +435,40 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
p_pipe_mutex->unlock();
}
}
-
int rv = _pclose(f);
+
if (r_exitcode) {
*r_exitcode = rv;
}
-
return OK;
}
- String cmdline = _quote_command_line_argument(path);
- const List<String>::Element *I = p_arguments.front();
- while (I) {
- cmdline += " " + _quote_command_line_argument(I->get());
- I = I->next();
+ ProcessInfo pi;
+ ZeroMemory(&pi.si, sizeof(pi.si));
+ pi.si.cb = sizeof(pi.si);
+ ZeroMemory(&pi.pi, sizeof(pi.pi));
+ LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si;
+
+ int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, false, NORMAL_PRIORITY_CLASS & CREATE_NO_WINDOW, nullptr, nullptr, si_w, &pi.pi);
+ ERR_FAIL_COND_V_MSG(ret == 0, ERR_CANT_FORK, "Could not create child process: " + command);
+
+ WaitForSingleObject(pi.pi.hProcess, INFINITE);
+ if (r_exitcode) {
+ DWORD ret2;
+ GetExitCodeProcess(pi.pi.hProcess, &ret2);
+ *r_exitcode = ret2;
+ }
+ CloseHandle(pi.pi.hProcess);
+ CloseHandle(pi.pi.hThread);
+
+ return OK;
+};
+
+Error OS_Windows::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id) {
+ String path = p_path.replace("/", "\\");
+ String command = _quote_command_line_argument(path);
+ for (const List<String>::Element *E = p_arguments.front(); E; E = E->next()) {
+ command += " " + _quote_command_line_argument(E->get());
}
ProcessInfo pi;
@@ -460,27 +477,15 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
ZeroMemory(&pi.pi, sizeof(pi.pi));
LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si;
- Char16String modstr = cmdline.utf16(); // Windows wants to change this no idea why.
- int ret = CreateProcessW(nullptr, (LPWSTR)(modstr.ptrw()), nullptr, nullptr, 0, NORMAL_PRIORITY_CLASS & CREATE_NO_WINDOW, nullptr, nullptr, si_w, &pi.pi);
- ERR_FAIL_COND_V(ret == 0, ERR_CANT_FORK);
+ int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, false, NORMAL_PRIORITY_CLASS & CREATE_NO_WINDOW, nullptr, nullptr, si_w, &pi.pi);
+ ERR_FAIL_COND_V_MSG(ret == 0, ERR_CANT_FORK, "Could not create child process: " + command);
- if (p_blocking) {
- WaitForSingleObject(pi.pi.hProcess, INFINITE);
- if (r_exitcode) {
- DWORD ret2;
- GetExitCodeProcess(pi.pi.hProcess, &ret2);
- *r_exitcode = ret2;
- }
-
- CloseHandle(pi.pi.hProcess);
- CloseHandle(pi.pi.hThread);
- } else {
- ProcessID pid = pi.pi.dwProcessId;
- if (r_child_id) {
- *r_child_id = pid;
- }
- process_map->insert(pid, pi);
+ ProcessID pid = pi.pi.dwProcessId;
+ if (r_child_id) {
+ *r_child_id = pid;
}
+ process_map->insert(pid, pi);
+
return OK;
};
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 78258f132b..1a8791196b 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -136,7 +136,8 @@ public:
virtual void delay_usec(uint32_t p_usec) const override;
virtual uint64_t get_ticks_usec() const override;
- virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking = true, ProcessID *r_child_id = nullptr, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr) override;
+ 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) override;
+ virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr) override;
virtual Error kill(const ProcessID &p_pid) override;
virtual int get_process_id() const override;