summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/core_bind.cpp1433
-rw-r--r--core/core_bind.h179
-rw-r--r--core/core_constants.cpp1
-rw-r--r--core/extension/extension_api_dump.cpp2
-rw-r--r--core/extension/gdnative_interface.cpp19
-rw-r--r--core/extension/gdnative_interface.h5
-rw-r--r--core/extension/native_extension.cpp5
-rw-r--r--core/extension/native_extension.h2
-rw-r--r--core/input/input_event.cpp9
-rw-r--r--core/input/input_event.h3
-rw-r--r--core/input/shortcut.cpp76
-rw-r--r--core/input/shortcut.h54
-rw-r--r--core/io/multiplayer_api.cpp252
-rw-r--r--core/io/multiplayer_api.h76
-rw-r--r--core/io/multiplayer_replicator.cpp497
-rw-r--r--core/io/multiplayer_replicator.h99
-rw-r--r--core/io/resource.cpp9
-rw-r--r--core/io/resource_loader.cpp88
-rw-r--r--core/io/resource_loader.h12
-rw-r--r--core/io/resource_saver.cpp35
-rw-r--r--core/io/resource_saver.h6
-rw-r--r--core/math/a_star.cpp28
-rw-r--r--core/math/a_star.h8
-rw-r--r--core/math/convex_hull.cpp11
-rw-r--r--core/object/class_db.cpp29
-rw-r--r--core/object/class_db.h32
-rw-r--r--core/object/make_virtuals.py16
-rw-r--r--core/object/method_bind.h1
-rw-r--r--core/object/object.cpp15
-rw-r--r--core/object/object.h36
-rw-r--r--core/object/ref_counted.h4
-rw-r--r--core/object/undo_redo.cpp4
-rw-r--r--core/object/undo_redo.h4
-rw-r--r--core/os/main_loop.cpp29
-rw-r--r--core/os/main_loop.h6
-rw-r--r--core/os/os.cpp7
-rw-r--r--core/os/os.h3
-rw-r--r--core/register_core_types.cpp85
-rw-r--r--core/string/ustring.cpp119
-rw-r--r--core/variant/type_info.h29
-rw-r--r--core/variant/typed_array.h10
-rw-r--r--core/variant/variant_internal.h26
-rw-r--r--core/variant/variant_parser.cpp2
43 files changed, 2005 insertions, 1361 deletions
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index f3f51e57ee..efb4b84716 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -41,39 +41,41 @@
#include "core/os/keyboard.h"
#include "core/os/os.h"
-////// _ResourceLoader //////
+namespace core_bind {
-_ResourceLoader *_ResourceLoader::singleton = nullptr;
+////// ResourceLoader //////
-Error _ResourceLoader::load_threaded_request(const String &p_path, const String &p_type_hint, bool p_use_sub_threads) {
- return ResourceLoader::load_threaded_request(p_path, p_type_hint, p_use_sub_threads);
+ResourceLoader *ResourceLoader::singleton = nullptr;
+
+Error ResourceLoader::load_threaded_request(const String &p_path, const String &p_type_hint, bool p_use_sub_threads) {
+ return ::ResourceLoader::load_threaded_request(p_path, p_type_hint, p_use_sub_threads);
}
-_ResourceLoader::ThreadLoadStatus _ResourceLoader::load_threaded_get_status(const String &p_path, Array r_progress) {
+ResourceLoader::ThreadLoadStatus ResourceLoader::load_threaded_get_status(const String &p_path, Array r_progress) {
float progress = 0;
- ResourceLoader::ThreadLoadStatus tls = ResourceLoader::load_threaded_get_status(p_path, &progress);
+ ::ResourceLoader::ThreadLoadStatus tls = ::ResourceLoader::load_threaded_get_status(p_path, &progress);
r_progress.resize(1);
r_progress[0] = progress;
return (ThreadLoadStatus)tls;
}
-RES _ResourceLoader::load_threaded_get(const String &p_path) {
+RES ResourceLoader::load_threaded_get(const String &p_path) {
Error error;
- RES res = ResourceLoader::load_threaded_get(p_path, &error);
+ RES res = ::ResourceLoader::load_threaded_get(p_path, &error);
return res;
}
-RES _ResourceLoader::load(const String &p_path, const String &p_type_hint, CacheMode p_cache_mode) {
+RES ResourceLoader::load(const String &p_path, const String &p_type_hint, CacheMode p_cache_mode) {
Error err = OK;
- RES ret = ResourceLoader::load(p_path, p_type_hint, ResourceFormatLoader::CacheMode(p_cache_mode), &err);
+ RES ret = ::ResourceLoader::load(p_path, p_type_hint, ResourceFormatLoader::CacheMode(p_cache_mode), &err);
ERR_FAIL_COND_V_MSG(err != OK, ret, "Error loading resource: '" + p_path + "'.");
return ret;
}
-Vector<String> _ResourceLoader::get_recognized_extensions_for_type(const String &p_type) {
+Vector<String> ResourceLoader::get_recognized_extensions_for_type(const String &p_type) {
List<String> exts;
- ResourceLoader::get_recognized_extensions_for_type(p_type, &exts);
+ ::ResourceLoader::get_recognized_extensions_for_type(p_type, &exts);
Vector<String> ret;
for (const String &E : exts) {
ret.push_back(E);
@@ -82,13 +84,13 @@ Vector<String> _ResourceLoader::get_recognized_extensions_for_type(const String
return ret;
}
-void _ResourceLoader::set_abort_on_missing_resources(bool p_abort) {
- ResourceLoader::set_abort_on_missing_resources(p_abort);
+void ResourceLoader::set_abort_on_missing_resources(bool p_abort) {
+ ::ResourceLoader::set_abort_on_missing_resources(p_abort);
}
-PackedStringArray _ResourceLoader::get_dependencies(const String &p_path) {
+PackedStringArray ResourceLoader::get_dependencies(const String &p_path) {
List<String> deps;
- ResourceLoader::get_dependencies(p_path, &deps);
+ ::ResourceLoader::get_dependencies(p_path, &deps);
PackedStringArray ret;
for (const String &E : deps) {
@@ -98,31 +100,31 @@ PackedStringArray _ResourceLoader::get_dependencies(const String &p_path) {
return ret;
}
-bool _ResourceLoader::has_cached(const String &p_path) {
+bool ResourceLoader::has_cached(const String &p_path) {
String local_path = ProjectSettings::get_singleton()->localize_path(p_path);
return ResourceCache::has(local_path);
}
-bool _ResourceLoader::exists(const String &p_path, const String &p_type_hint) {
- return ResourceLoader::exists(p_path, p_type_hint);
+bool ResourceLoader::exists(const String &p_path, const String &p_type_hint) {
+ return ::ResourceLoader::exists(p_path, p_type_hint);
}
-ResourceUID::ID _ResourceLoader::get_resource_uid(const String &p_path) {
- return ResourceLoader::get_resource_uid(p_path);
+ResourceUID::ID ResourceLoader::get_resource_uid(const String &p_path) {
+ return ::ResourceLoader::get_resource_uid(p_path);
}
-void _ResourceLoader::_bind_methods() {
- ClassDB::bind_method(D_METHOD("load_threaded_request", "path", "type_hint", "use_sub_threads"), &_ResourceLoader::load_threaded_request, DEFVAL(""), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("load_threaded_get_status", "path", "progress"), &_ResourceLoader::load_threaded_get_status, DEFVAL(Array()));
- ClassDB::bind_method(D_METHOD("load_threaded_get", "path"), &_ResourceLoader::load_threaded_get);
+void ResourceLoader::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("load_threaded_request", "path", "type_hint", "use_sub_threads"), &ResourceLoader::load_threaded_request, DEFVAL(""), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("load_threaded_get_status", "path", "progress"), &ResourceLoader::load_threaded_get_status, DEFVAL(Array()));
+ ClassDB::bind_method(D_METHOD("load_threaded_get", "path"), &ResourceLoader::load_threaded_get);
- ClassDB::bind_method(D_METHOD("load", "path", "type_hint", "cache_mode"), &_ResourceLoader::load, DEFVAL(""), DEFVAL(CACHE_MODE_REUSE));
- ClassDB::bind_method(D_METHOD("get_recognized_extensions_for_type", "type"), &_ResourceLoader::get_recognized_extensions_for_type);
- ClassDB::bind_method(D_METHOD("set_abort_on_missing_resources", "abort"), &_ResourceLoader::set_abort_on_missing_resources);
- ClassDB::bind_method(D_METHOD("get_dependencies", "path"), &_ResourceLoader::get_dependencies);
- ClassDB::bind_method(D_METHOD("has_cached", "path"), &_ResourceLoader::has_cached);
- ClassDB::bind_method(D_METHOD("exists", "path", "type_hint"), &_ResourceLoader::exists, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("get_resource_uid", "path"), &_ResourceLoader::get_resource_uid);
+ ClassDB::bind_method(D_METHOD("load", "path", "type_hint", "cache_mode"), &ResourceLoader::load, DEFVAL(""), DEFVAL(CACHE_MODE_REUSE));
+ ClassDB::bind_method(D_METHOD("get_recognized_extensions_for_type", "type"), &ResourceLoader::get_recognized_extensions_for_type);
+ ClassDB::bind_method(D_METHOD("set_abort_on_missing_resources", "abort"), &ResourceLoader::set_abort_on_missing_resources);
+ ClassDB::bind_method(D_METHOD("get_dependencies", "path"), &ResourceLoader::get_dependencies);
+ ClassDB::bind_method(D_METHOD("has_cached", "path"), &ResourceLoader::has_cached);
+ ClassDB::bind_method(D_METHOD("exists", "path", "type_hint"), &ResourceLoader::exists, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_resource_uid", "path"), &ResourceLoader::get_resource_uid);
BIND_ENUM_CONSTANT(THREAD_LOAD_INVALID_RESOURCE);
BIND_ENUM_CONSTANT(THREAD_LOAD_IN_PROGRESS);
@@ -134,17 +136,17 @@ void _ResourceLoader::_bind_methods() {
BIND_ENUM_CONSTANT(CACHE_MODE_REPLACE);
}
-////// _ResourceSaver //////
+////// ResourceSaver //////
-Error _ResourceSaver::save(const String &p_path, const RES &p_resource, SaverFlags p_flags) {
+Error ResourceSaver::save(const String &p_path, const RES &p_resource, SaverFlags p_flags) {
ERR_FAIL_COND_V_MSG(p_resource.is_null(), ERR_INVALID_PARAMETER, "Can't save empty resource to path '" + String(p_path) + "'.");
- return ResourceSaver::save(p_path, p_resource, p_flags);
+ return ::ResourceSaver::save(p_path, p_resource, p_flags);
}
-Vector<String> _ResourceSaver::get_recognized_extensions(const RES &p_resource) {
+Vector<String> ResourceSaver::get_recognized_extensions(const RES &p_resource) {
ERR_FAIL_COND_V_MSG(p_resource.is_null(), Vector<String>(), "It's not a reference to a valid Resource object.");
List<String> exts;
- ResourceSaver::get_recognized_extensions(p_resource, &exts);
+ ::ResourceSaver::get_recognized_extensions(p_resource, &exts);
Vector<String> ret;
for (const String &E : exts) {
ret.push_back(E);
@@ -152,11 +154,11 @@ Vector<String> _ResourceSaver::get_recognized_extensions(const RES &p_resource)
return ret;
}
-_ResourceSaver *_ResourceSaver::singleton = nullptr;
+ResourceSaver *ResourceSaver::singleton = nullptr;
-void _ResourceSaver::_bind_methods() {
- ClassDB::bind_method(D_METHOD("save", "path", "resource", "flags"), &_ResourceSaver::save, DEFVAL(0));
- ClassDB::bind_method(D_METHOD("get_recognized_extensions", "type"), &_ResourceSaver::get_recognized_extensions);
+void ResourceSaver::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("save", "path", "resource", "flags"), &ResourceSaver::save, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_recognized_extensions", "type"), &ResourceSaver::get_recognized_extensions);
BIND_ENUM_CONSTANT(FLAG_RELATIVE_PATHS);
BIND_ENUM_CONSTANT(FLAG_BUNDLE_RESOURCES);
@@ -167,65 +169,65 @@ void _ResourceSaver::_bind_methods() {
BIND_ENUM_CONSTANT(FLAG_REPLACE_SUBRESOURCE_PATHS);
}
-////// _OS //////
+////// OS //////
-PackedStringArray _OS::get_connected_midi_inputs() {
- return OS::get_singleton()->get_connected_midi_inputs();
+PackedStringArray OS::get_connected_midi_inputs() {
+ return ::OS::get_singleton()->get_connected_midi_inputs();
}
-void _OS::open_midi_inputs() {
- OS::get_singleton()->open_midi_inputs();
+void OS::open_midi_inputs() {
+ ::OS::get_singleton()->open_midi_inputs();
}
-void _OS::close_midi_inputs() {
- OS::get_singleton()->close_midi_inputs();
+void OS::close_midi_inputs() {
+ ::OS::get_singleton()->close_midi_inputs();
}
-void _OS::set_use_file_access_save_and_swap(bool p_enable) {
+void OS::set_use_file_access_save_and_swap(bool p_enable) {
FileAccess::set_backup_save(p_enable);
}
-void _OS::set_low_processor_usage_mode(bool p_enabled) {
- OS::get_singleton()->set_low_processor_usage_mode(p_enabled);
+void OS::set_low_processor_usage_mode(bool p_enabled) {
+ ::OS::get_singleton()->set_low_processor_usage_mode(p_enabled);
}
-bool _OS::is_in_low_processor_usage_mode() const {
- return OS::get_singleton()->is_in_low_processor_usage_mode();
+bool OS::is_in_low_processor_usage_mode() const {
+ return ::OS::get_singleton()->is_in_low_processor_usage_mode();
}
-void _OS::set_low_processor_usage_mode_sleep_usec(int p_usec) {
- OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(p_usec);
+void OS::set_low_processor_usage_mode_sleep_usec(int p_usec) {
+ ::OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(p_usec);
}
-int _OS::get_low_processor_usage_mode_sleep_usec() const {
- return OS::get_singleton()->get_low_processor_usage_mode_sleep_usec();
+int OS::get_low_processor_usage_mode_sleep_usec() const {
+ return ::OS::get_singleton()->get_low_processor_usage_mode_sleep_usec();
}
-void _OS::alert(const String &p_alert, const String &p_title) {
- OS::get_singleton()->alert(p_alert, p_title);
+void OS::alert(const String &p_alert, const String &p_title) {
+ ::OS::get_singleton()->alert(p_alert, p_title);
}
-String _OS::get_executable_path() const {
- return OS::get_singleton()->get_executable_path();
+String OS::get_executable_path() const {
+ return ::OS::get_singleton()->get_executable_path();
}
-Error _OS::shell_open(String p_uri) {
+Error OS::shell_open(String p_uri) {
if (p_uri.begins_with("res://")) {
WARN_PRINT("Attempting to open an URL with the \"res://\" protocol. Use `ProjectSettings.globalize_path()` to convert a Godot-specific path to a system path before opening it with `OS.shell_open()`.");
} else if (p_uri.begins_with("user://")) {
WARN_PRINT("Attempting to open an URL with the \"user://\" protocol. Use `ProjectSettings.globalize_path()` to convert a Godot-specific path to a system path before opening it with `OS.shell_open()`.");
}
- return OS::get_singleton()->shell_open(p_uri);
+ return ::OS::get_singleton()->shell_open(p_uri);
}
-int _OS::execute(const String &p_path, const Vector<String> &p_arguments, Array r_output, bool p_read_stderr) {
+int OS::execute(const String &p_path, const Vector<String> &p_arguments, Array r_output, bool p_read_stderr) {
List<String> args;
for (int i = 0; i < p_arguments.size(); i++) {
args.push_back(p_arguments[i]);
}
String pipe;
int exitcode = 0;
- Error err = OS::get_singleton()->execute(p_path, args, &pipe, &exitcode, p_read_stderr);
+ Error err = ::OS::get_singleton()->execute(p_path, args, &pipe, &exitcode, p_read_stderr);
r_output.push_back(pipe);
if (err != OK) {
return -1;
@@ -233,45 +235,45 @@ int _OS::execute(const String &p_path, const Vector<String> &p_arguments, Array
return exitcode;
}
-int _OS::create_process(const String &p_path, const Vector<String> &p_arguments) {
+int OS::create_process(const String &p_path, const Vector<String> &p_arguments) {
List<String> args;
for (int i = 0; i < p_arguments.size(); i++) {
args.push_back(p_arguments[i]);
}
- OS::ProcessID pid = 0;
- Error err = OS::get_singleton()->create_process(p_path, args, &pid);
+ ::OS::ProcessID pid = 0;
+ Error err = ::OS::get_singleton()->create_process(p_path, args, &pid);
if (err != OK) {
return -1;
}
return pid;
}
-Error _OS::kill(int p_pid) {
- return OS::get_singleton()->kill(p_pid);
+Error OS::kill(int p_pid) {
+ return ::OS::get_singleton()->kill(p_pid);
}
-int _OS::get_process_id() const {
- return OS::get_singleton()->get_process_id();
+int OS::get_process_id() const {
+ return ::OS::get_singleton()->get_process_id();
}
-bool _OS::has_environment(const String &p_var) const {
- return OS::get_singleton()->has_environment(p_var);
+bool OS::has_environment(const String &p_var) const {
+ return ::OS::get_singleton()->has_environment(p_var);
}
-String _OS::get_environment(const String &p_var) const {
- return OS::get_singleton()->get_environment(p_var);
+String OS::get_environment(const String &p_var) const {
+ return ::OS::get_singleton()->get_environment(p_var);
}
-bool _OS::set_environment(const String &p_var, const String &p_value) const {
- return OS::get_singleton()->set_environment(p_var, p_value);
+bool OS::set_environment(const String &p_var, const String &p_value) const {
+ return ::OS::get_singleton()->set_environment(p_var, p_value);
}
-String _OS::get_name() const {
- return OS::get_singleton()->get_name();
+String OS::get_name() const {
+ return ::OS::get_singleton()->get_name();
}
-Vector<String> _OS::get_cmdline_args() {
- List<String> cmdline = OS::get_singleton()->get_cmdline_args();
+Vector<String> OS::get_cmdline_args() {
+ List<String> cmdline = ::OS::get_singleton()->get_cmdline_args();
Vector<String> cmdlinev;
for (const String &E : cmdline) {
cmdlinev.push_back(E);
@@ -280,81 +282,81 @@ Vector<String> _OS::get_cmdline_args() {
return cmdlinev;
}
-String _OS::get_locale() const {
- return OS::get_singleton()->get_locale();
+String OS::get_locale() const {
+ return ::OS::get_singleton()->get_locale();
}
-String _OS::get_model_name() const {
- return OS::get_singleton()->get_model_name();
+String OS::get_model_name() const {
+ return ::OS::get_singleton()->get_model_name();
}
-Error _OS::set_thread_name(const String &p_name) {
- return Thread::set_name(p_name);
+Error OS::set_thread_name(const String &p_name) {
+ return ::Thread::set_name(p_name);
}
-Thread::ID _OS::get_thread_caller_id() const {
- return Thread::get_caller_id();
+::Thread::ID OS::get_thread_caller_id() const {
+ return ::Thread::get_caller_id();
};
-bool _OS::has_feature(const String &p_feature) const {
- return OS::get_singleton()->has_feature(p_feature);
+bool OS::has_feature(const String &p_feature) const {
+ return ::OS::get_singleton()->has_feature(p_feature);
}
-uint64_t _OS::get_static_memory_usage() const {
- return OS::get_singleton()->get_static_memory_usage();
+uint64_t OS::get_static_memory_usage() const {
+ return ::OS::get_singleton()->get_static_memory_usage();
}
-uint64_t _OS::get_static_memory_peak_usage() const {
- return OS::get_singleton()->get_static_memory_peak_usage();
+uint64_t OS::get_static_memory_peak_usage() const {
+ return ::OS::get_singleton()->get_static_memory_peak_usage();
}
/** This method uses a signed argument for better error reporting as it's used from the scripting API. */
-void _OS::delay_usec(int p_usec) const {
+void OS::delay_usec(int p_usec) const {
ERR_FAIL_COND_MSG(
p_usec < 0,
vformat("Can't sleep for %d microseconds. The delay provided must be greater than or equal to 0 microseconds.", p_usec));
- OS::get_singleton()->delay_usec(p_usec);
+ ::OS::get_singleton()->delay_usec(p_usec);
}
/** This method uses a signed argument for better error reporting as it's used from the scripting API. */
-void _OS::delay_msec(int p_msec) const {
+void OS::delay_msec(int p_msec) const {
ERR_FAIL_COND_MSG(
p_msec < 0,
vformat("Can't sleep for %d milliseconds. The delay provided must be greater than or equal to 0 milliseconds.", p_msec));
- OS::get_singleton()->delay_usec(int64_t(p_msec) * 1000);
+ ::OS::get_singleton()->delay_usec(int64_t(p_msec) * 1000);
}
-bool _OS::can_use_threads() const {
- return OS::get_singleton()->can_use_threads();
+bool OS::can_use_threads() const {
+ return ::OS::get_singleton()->can_use_threads();
}
-bool _OS::is_userfs_persistent() const {
- return OS::get_singleton()->is_userfs_persistent();
+bool OS::is_userfs_persistent() const {
+ return ::OS::get_singleton()->is_userfs_persistent();
}
-int _OS::get_processor_count() const {
- return OS::get_singleton()->get_processor_count();
+int OS::get_processor_count() const {
+ return ::OS::get_singleton()->get_processor_count();
}
-bool _OS::is_stdout_verbose() const {
- return OS::get_singleton()->is_stdout_verbose();
+bool OS::is_stdout_verbose() const {
+ return ::OS::get_singleton()->is_stdout_verbose();
}
-void _OS::dump_memory_to_file(const String &p_file) {
- OS::get_singleton()->dump_memory_to_file(p_file.utf8().get_data());
+void OS::dump_memory_to_file(const String &p_file) {
+ ::OS::get_singleton()->dump_memory_to_file(p_file.utf8().get_data());
}
-struct _OSCoreBindImg {
+struct OSCoreBindImg {
String path;
Size2 size;
int fmt = 0;
ObjectID id;
int vram = 0;
- bool operator<(const _OSCoreBindImg &p_img) const { return vram == p_img.vram ? id < p_img.id : vram > p_img.vram; }
+ bool operator<(const OSCoreBindImg &p_img) const { return vram == p_img.vram ? id < p_img.id : vram > p_img.vram; }
};
-void _OS::print_all_textures_by_size() {
- List<_OSCoreBindImg> imgs;
+void OS::print_all_textures_by_size() {
+ List<OSCoreBindImg> imgs;
uint64_t total = 0;
{
List<Ref<Resource>> rsrc;
@@ -368,7 +370,7 @@ void _OS::print_all_textures_by_size() {
Size2 size = res->call("get_size");
int fmt = res->call("get_format");
- _OSCoreBindImg img;
+ OSCoreBindImg img;
img.size = size;
img.fmt = fmt;
img.path = res->get_path();
@@ -388,7 +390,7 @@ void _OS::print_all_textures_by_size() {
"Path - VRAM usage (Dimensions)");
}
- for (const _OSCoreBindImg &img : imgs) {
+ for (const OSCoreBindImg &img : imgs) {
print_line(vformat("%s - %s %s",
img.path,
String::humanize_size(img.vram),
@@ -398,7 +400,7 @@ void _OS::print_all_textures_by_size() {
print_line(vformat("Total VRAM usage: %s.", String::humanize_size(total)));
}
-void _OS::print_resources_by_type(const Vector<String> &p_types) {
+void OS::print_resources_by_type(const Vector<String> &p_types) {
ERR_FAIL_COND_MSG(p_types.size() == 0,
"At least one type should be provided to print resources by type.");
@@ -440,42 +442,38 @@ void _OS::print_resources_by_type(const Vector<String> &p_types) {
}
}
-void _OS::print_all_resources(const String &p_to_file) {
- OS::get_singleton()->print_all_resources(p_to_file);
-}
-
-void _OS::print_resources_in_use(bool p_short) {
- OS::get_singleton()->print_resources_in_use(p_short);
+void OS::print_all_resources(const String &p_to_file) {
+ ::OS::get_singleton()->print_all_resources(p_to_file);
}
-void _OS::dump_resources_to_file(const String &p_file) {
- OS::get_singleton()->dump_resources_to_file(p_file.utf8().get_data());
+void OS::print_resources_in_use(bool p_short) {
+ ::OS::get_singleton()->print_resources_in_use(p_short);
}
-String _OS::get_user_data_dir() const {
- return OS::get_singleton()->get_user_data_dir();
+void OS::dump_resources_to_file(const String &p_file) {
+ ::OS::get_singleton()->dump_resources_to_file(p_file.utf8().get_data());
}
-String _OS::get_external_data_dir() const {
- return OS::get_singleton()->get_external_data_dir();
+String OS::get_user_data_dir() const {
+ return ::OS::get_singleton()->get_user_data_dir();
}
-String _OS::get_config_dir() const {
+String OS::get_config_dir() const {
// Exposed as `get_config_dir()` instead of `get_config_path()` for consistency with other exposed OS methods.
- return OS::get_singleton()->get_config_path();
+ return ::OS::get_singleton()->get_config_path();
}
-String _OS::get_data_dir() const {
+String OS::get_data_dir() const {
// Exposed as `get_data_dir()` instead of `get_data_path()` for consistency with other exposed OS methods.
- return OS::get_singleton()->get_data_path();
+ return ::OS::get_singleton()->get_data_path();
}
-String _OS::get_cache_dir() const {
+String OS::get_cache_dir() const {
// Exposed as `get_cache_dir()` instead of `get_cache_path()` for consistency with other exposed OS methods.
- return OS::get_singleton()->get_cache_path();
+ return ::OS::get_singleton()->get_cache_path();
}
-bool _OS::is_debug_build() const {
+bool OS::is_debug_build() const {
#ifdef DEBUG_ENABLED
return true;
#else
@@ -483,114 +481,113 @@ bool _OS::is_debug_build() const {
#endif
}
-String _OS::get_system_dir(SystemDir p_dir) const {
- return OS::get_singleton()->get_system_dir(OS::SystemDir(p_dir));
+String OS::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
+ return ::OS::get_singleton()->get_system_dir(::OS::SystemDir(p_dir), p_shared_storage);
}
-String _OS::get_keycode_string(uint32_t p_code) const {
- return keycode_get_string(p_code);
+String OS::get_keycode_string(uint32_t p_code) const {
+ return ::keycode_get_string(p_code);
}
-bool _OS::is_keycode_unicode(uint32_t p_unicode) const {
- return keycode_has_unicode(p_unicode);
+bool OS::is_keycode_unicode(uint32_t p_unicode) const {
+ return ::keycode_has_unicode(p_unicode);
}
-int _OS::find_keycode_from_string(const String &p_code) const {
+int OS::find_keycode_from_string(const String &p_code) const {
return find_keycode(p_code);
}
-bool _OS::request_permission(const String &p_name) {
- return OS::get_singleton()->request_permission(p_name);
+bool OS::request_permission(const String &p_name) {
+ return ::OS::get_singleton()->request_permission(p_name);
}
-bool _OS::request_permissions() {
- return OS::get_singleton()->request_permissions();
+bool OS::request_permissions() {
+ return ::OS::get_singleton()->request_permissions();
}
-Vector<String> _OS::get_granted_permissions() const {
- return OS::get_singleton()->get_granted_permissions();
+Vector<String> OS::get_granted_permissions() const {
+ return ::OS::get_singleton()->get_granted_permissions();
}
-String _OS::get_unique_id() const {
- return OS::get_singleton()->get_unique_id();
+String OS::get_unique_id() const {
+ return ::OS::get_singleton()->get_unique_id();
}
-_OS *_OS::singleton = nullptr;
+OS *OS::singleton = nullptr;
-void _OS::_bind_methods() {
- ClassDB::bind_method(D_METHOD("get_connected_midi_inputs"), &_OS::get_connected_midi_inputs);
- ClassDB::bind_method(D_METHOD("open_midi_inputs"), &_OS::open_midi_inputs);
- ClassDB::bind_method(D_METHOD("close_midi_inputs"), &_OS::close_midi_inputs);
+void OS::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_connected_midi_inputs"), &OS::get_connected_midi_inputs);
+ ClassDB::bind_method(D_METHOD("open_midi_inputs"), &OS::open_midi_inputs);
+ ClassDB::bind_method(D_METHOD("close_midi_inputs"), &OS::close_midi_inputs);
- ClassDB::bind_method(D_METHOD("alert", "text", "title"), &_OS::alert, DEFVAL("Alert!"));
+ ClassDB::bind_method(D_METHOD("alert", "text", "title"), &OS::alert, DEFVAL("Alert!"));
- ClassDB::bind_method(D_METHOD("set_low_processor_usage_mode", "enable"), &_OS::set_low_processor_usage_mode);
- ClassDB::bind_method(D_METHOD("is_in_low_processor_usage_mode"), &_OS::is_in_low_processor_usage_mode);
+ ClassDB::bind_method(D_METHOD("set_low_processor_usage_mode", "enable"), &OS::set_low_processor_usage_mode);
+ ClassDB::bind_method(D_METHOD("is_in_low_processor_usage_mode"), &OS::is_in_low_processor_usage_mode);
- ClassDB::bind_method(D_METHOD("set_low_processor_usage_mode_sleep_usec", "usec"), &_OS::set_low_processor_usage_mode_sleep_usec);
- ClassDB::bind_method(D_METHOD("get_low_processor_usage_mode_sleep_usec"), &_OS::get_low_processor_usage_mode_sleep_usec);
+ ClassDB::bind_method(D_METHOD("set_low_processor_usage_mode_sleep_usec", "usec"), &OS::set_low_processor_usage_mode_sleep_usec);
+ ClassDB::bind_method(D_METHOD("get_low_processor_usage_mode_sleep_usec"), &OS::get_low_processor_usage_mode_sleep_usec);
- ClassDB::bind_method(D_METHOD("get_processor_count"), &_OS::get_processor_count);
+ ClassDB::bind_method(D_METHOD("get_processor_count"), &OS::get_processor_count);
- ClassDB::bind_method(D_METHOD("get_executable_path"), &_OS::get_executable_path);
- ClassDB::bind_method(D_METHOD("execute", "path", "arguments", "output", "read_stderr"), &_OS::execute, DEFVAL(Array()), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("create_process", "path", "arguments"), &_OS::create_process);
- ClassDB::bind_method(D_METHOD("kill", "pid"), &_OS::kill);
- ClassDB::bind_method(D_METHOD("shell_open", "uri"), &_OS::shell_open);
- ClassDB::bind_method(D_METHOD("get_process_id"), &_OS::get_process_id);
+ ClassDB::bind_method(D_METHOD("get_executable_path"), &OS::get_executable_path);
+ ClassDB::bind_method(D_METHOD("execute", "path", "arguments", "output", "read_stderr"), &OS::execute, DEFVAL(Array()), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("create_process", "path", "arguments"), &OS::create_process);
+ ClassDB::bind_method(D_METHOD("kill", "pid"), &OS::kill);
+ ClassDB::bind_method(D_METHOD("shell_open", "uri"), &OS::shell_open);
+ ClassDB::bind_method(D_METHOD("get_process_id"), &OS::get_process_id);
- ClassDB::bind_method(D_METHOD("get_environment", "variable"), &_OS::get_environment);
- ClassDB::bind_method(D_METHOD("set_environment", "variable", "value"), &_OS::set_environment);
- ClassDB::bind_method(D_METHOD("has_environment", "variable"), &_OS::has_environment);
+ ClassDB::bind_method(D_METHOD("get_environment", "variable"), &OS::get_environment);
+ ClassDB::bind_method(D_METHOD("set_environment", "variable", "value"), &OS::set_environment);
+ ClassDB::bind_method(D_METHOD("has_environment", "variable"), &OS::has_environment);
- ClassDB::bind_method(D_METHOD("get_name"), &_OS::get_name);
- ClassDB::bind_method(D_METHOD("get_cmdline_args"), &_OS::get_cmdline_args);
+ ClassDB::bind_method(D_METHOD("get_name"), &OS::get_name);
+ ClassDB::bind_method(D_METHOD("get_cmdline_args"), &OS::get_cmdline_args);
- ClassDB::bind_method(D_METHOD("delay_usec", "usec"), &_OS::delay_usec);
- ClassDB::bind_method(D_METHOD("delay_msec", "msec"), &_OS::delay_msec);
- ClassDB::bind_method(D_METHOD("get_locale"), &_OS::get_locale);
- ClassDB::bind_method(D_METHOD("get_model_name"), &_OS::get_model_name);
+ ClassDB::bind_method(D_METHOD("delay_usec", "usec"), &OS::delay_usec);
+ ClassDB::bind_method(D_METHOD("delay_msec", "msec"), &OS::delay_msec);
+ ClassDB::bind_method(D_METHOD("get_locale"), &OS::get_locale);
+ ClassDB::bind_method(D_METHOD("get_model_name"), &OS::get_model_name);
- ClassDB::bind_method(D_METHOD("is_userfs_persistent"), &_OS::is_userfs_persistent);
- ClassDB::bind_method(D_METHOD("is_stdout_verbose"), &_OS::is_stdout_verbose);
+ ClassDB::bind_method(D_METHOD("is_userfs_persistent"), &OS::is_userfs_persistent);
+ ClassDB::bind_method(D_METHOD("is_stdout_verbose"), &OS::is_stdout_verbose);
- ClassDB::bind_method(D_METHOD("can_use_threads"), &_OS::can_use_threads);
+ ClassDB::bind_method(D_METHOD("can_use_threads"), &OS::can_use_threads);
- ClassDB::bind_method(D_METHOD("is_debug_build"), &_OS::is_debug_build);
+ ClassDB::bind_method(D_METHOD("is_debug_build"), &OS::is_debug_build);
- ClassDB::bind_method(D_METHOD("dump_memory_to_file", "file"), &_OS::dump_memory_to_file);
- ClassDB::bind_method(D_METHOD("dump_resources_to_file", "file"), &_OS::dump_resources_to_file);
- ClassDB::bind_method(D_METHOD("print_resources_in_use", "short"), &_OS::print_resources_in_use, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("print_all_resources", "tofile"), &_OS::print_all_resources, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("dump_memory_to_file", "file"), &OS::dump_memory_to_file);
+ ClassDB::bind_method(D_METHOD("dump_resources_to_file", "file"), &OS::dump_resources_to_file);
+ ClassDB::bind_method(D_METHOD("print_resources_in_use", "short"), &OS::print_resources_in_use, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("print_all_resources", "tofile"), &OS::print_all_resources, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("get_static_memory_usage"), &_OS::get_static_memory_usage);
- ClassDB::bind_method(D_METHOD("get_static_memory_peak_usage"), &_OS::get_static_memory_peak_usage);
+ ClassDB::bind_method(D_METHOD("get_static_memory_usage"), &OS::get_static_memory_usage);
+ ClassDB::bind_method(D_METHOD("get_static_memory_peak_usage"), &OS::get_static_memory_peak_usage);
- ClassDB::bind_method(D_METHOD("get_user_data_dir"), &_OS::get_user_data_dir);
- ClassDB::bind_method(D_METHOD("get_external_data_dir"), &_OS::get_external_data_dir);
- ClassDB::bind_method(D_METHOD("get_system_dir", "dir"), &_OS::get_system_dir);
- ClassDB::bind_method(D_METHOD("get_config_dir"), &_OS::get_config_dir);
- ClassDB::bind_method(D_METHOD("get_data_dir"), &_OS::get_data_dir);
- ClassDB::bind_method(D_METHOD("get_cache_dir"), &_OS::get_cache_dir);
- ClassDB::bind_method(D_METHOD("get_unique_id"), &_OS::get_unique_id);
+ ClassDB::bind_method(D_METHOD("get_user_data_dir"), &OS::get_user_data_dir);
+ ClassDB::bind_method(D_METHOD("get_system_dir", "dir", "shared_storage"), &OS::get_system_dir, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("get_config_dir"), &OS::get_config_dir);
+ ClassDB::bind_method(D_METHOD("get_data_dir"), &OS::get_data_dir);
+ ClassDB::bind_method(D_METHOD("get_cache_dir"), &OS::get_cache_dir);
+ ClassDB::bind_method(D_METHOD("get_unique_id"), &OS::get_unique_id);
- ClassDB::bind_method(D_METHOD("print_all_textures_by_size"), &_OS::print_all_textures_by_size);
- ClassDB::bind_method(D_METHOD("print_resources_by_type", "types"), &_OS::print_resources_by_type);
+ ClassDB::bind_method(D_METHOD("print_all_textures_by_size"), &OS::print_all_textures_by_size);
+ ClassDB::bind_method(D_METHOD("print_resources_by_type", "types"), &OS::print_resources_by_type);
- ClassDB::bind_method(D_METHOD("get_keycode_string", "code"), &_OS::get_keycode_string);
- ClassDB::bind_method(D_METHOD("is_keycode_unicode", "code"), &_OS::is_keycode_unicode);
- ClassDB::bind_method(D_METHOD("find_keycode_from_string", "string"), &_OS::find_keycode_from_string);
+ ClassDB::bind_method(D_METHOD("get_keycode_string", "code"), &OS::get_keycode_string);
+ ClassDB::bind_method(D_METHOD("is_keycode_unicode", "code"), &OS::is_keycode_unicode);
+ ClassDB::bind_method(D_METHOD("find_keycode_from_string", "string"), &OS::find_keycode_from_string);
- ClassDB::bind_method(D_METHOD("set_use_file_access_save_and_swap", "enabled"), &_OS::set_use_file_access_save_and_swap);
+ ClassDB::bind_method(D_METHOD("set_use_file_access_save_and_swap", "enabled"), &OS::set_use_file_access_save_and_swap);
- ClassDB::bind_method(D_METHOD("set_thread_name", "name"), &_OS::set_thread_name);
- ClassDB::bind_method(D_METHOD("get_thread_caller_id"), &_OS::get_thread_caller_id);
+ ClassDB::bind_method(D_METHOD("set_thread_name", "name"), &OS::set_thread_name);
+ ClassDB::bind_method(D_METHOD("get_thread_caller_id"), &OS::get_thread_caller_id);
- ClassDB::bind_method(D_METHOD("has_feature", "tag_name"), &_OS::has_feature);
+ ClassDB::bind_method(D_METHOD("has_feature", "tag_name"), &OS::has_feature);
- ClassDB::bind_method(D_METHOD("request_permission", "name"), &_OS::request_permission);
- ClassDB::bind_method(D_METHOD("request_permissions"), &_OS::request_permissions);
- ClassDB::bind_method(D_METHOD("get_granted_permissions"), &_OS::get_granted_permissions);
+ ClassDB::bind_method(D_METHOD("request_permission", "name"), &OS::request_permission);
+ ClassDB::bind_method(D_METHOD("request_permissions"), &OS::request_permissions);
+ ClassDB::bind_method(D_METHOD("get_granted_permissions"), &OS::get_granted_permissions);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "low_processor_usage_mode"), "set_low_processor_usage_mode", "is_in_low_processor_usage_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "low_processor_usage_mode_sleep_usec"), "set_low_processor_usage_mode_sleep_usec", "get_low_processor_usage_mode_sleep_usec");
@@ -635,43 +632,43 @@ void _OS::_bind_methods() {
BIND_ENUM_CONSTANT(SYSTEM_DIR_RINGTONES);
}
-////// _Geometry2D //////
+////// Geometry2D //////
-_Geometry2D *_Geometry2D::singleton = nullptr;
+Geometry2D *Geometry2D::singleton = nullptr;
-_Geometry2D *_Geometry2D::get_singleton() {
+Geometry2D *Geometry2D::get_singleton() {
return singleton;
}
-bool _Geometry2D::is_point_in_circle(const Vector2 &p_point, const Vector2 &p_circle_pos, real_t p_circle_radius) {
- return Geometry2D::is_point_in_circle(p_point, p_circle_pos, p_circle_radius);
+bool Geometry2D::is_point_in_circle(const Vector2 &p_point, const Vector2 &p_circle_pos, real_t p_circle_radius) {
+ return ::Geometry2D::is_point_in_circle(p_point, p_circle_pos, p_circle_radius);
}
-real_t _Geometry2D::segment_intersects_circle(const Vector2 &p_from, const Vector2 &p_to, const Vector2 &p_circle_pos, real_t p_circle_radius) {
- return Geometry2D::segment_intersects_circle(p_from, p_to, p_circle_pos, p_circle_radius);
+real_t Geometry2D::segment_intersects_circle(const Vector2 &p_from, const Vector2 &p_to, const Vector2 &p_circle_pos, real_t p_circle_radius) {
+ return ::Geometry2D::segment_intersects_circle(p_from, p_to, p_circle_pos, p_circle_radius);
}
-Variant _Geometry2D::segment_intersects_segment(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b) {
+Variant Geometry2D::segment_intersects_segment(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b) {
Vector2 result;
- if (Geometry2D::segment_intersects_segment(p_from_a, p_to_a, p_from_b, p_to_b, &result)) {
+ if (::Geometry2D::segment_intersects_segment(p_from_a, p_to_a, p_from_b, p_to_b, &result)) {
return result;
} else {
return Variant();
}
}
-Variant _Geometry2D::line_intersects_line(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b) {
+Variant Geometry2D::line_intersects_line(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b) {
Vector2 result;
- if (Geometry2D::line_intersects_line(p_from_a, p_dir_a, p_from_b, p_dir_b, result)) {
+ if (::Geometry2D::line_intersects_line(p_from_a, p_dir_a, p_from_b, p_dir_b, result)) {
return result;
} else {
return Variant();
}
}
-Vector<Vector2> _Geometry2D::get_closest_points_between_segments(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2) {
+Vector<Vector2> Geometry2D::get_closest_points_between_segments(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2) {
Vector2 r1, r2;
- Geometry2D::get_closest_points_between_segments(p1, q1, p2, q2, r1, r2);
+ ::Geometry2D::get_closest_points_between_segments(p1, q1, p2, q2, r1, r2);
Vector<Vector2> r;
r.resize(2);
r.set(0, r1);
@@ -679,42 +676,42 @@ Vector<Vector2> _Geometry2D::get_closest_points_between_segments(const Vector2 &
return r;
}
-Vector2 _Geometry2D::get_closest_point_to_segment(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b) {
+Vector2 Geometry2D::get_closest_point_to_segment(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b) {
Vector2 s[2] = { p_a, p_b };
- return Geometry2D::get_closest_point_to_segment(p_point, s);
+ return ::Geometry2D::get_closest_point_to_segment(p_point, s);
}
-Vector2 _Geometry2D::get_closest_point_to_segment_uncapped(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b) {
+Vector2 Geometry2D::get_closest_point_to_segment_uncapped(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b) {
Vector2 s[2] = { p_a, p_b };
- return Geometry2D::get_closest_point_to_segment_uncapped(p_point, s);
+ return ::Geometry2D::get_closest_point_to_segment_uncapped(p_point, s);
}
-bool _Geometry2D::point_is_inside_triangle(const Vector2 &s, const Vector2 &a, const Vector2 &b, const Vector2 &c) const {
- return Geometry2D::is_point_in_triangle(s, a, b, c);
+bool Geometry2D::point_is_inside_triangle(const Vector2 &s, const Vector2 &a, const Vector2 &b, const Vector2 &c) const {
+ return ::Geometry2D::is_point_in_triangle(s, a, b, c);
}
-bool _Geometry2D::is_polygon_clockwise(const Vector<Vector2> &p_polygon) {
- return Geometry2D::is_polygon_clockwise(p_polygon);
+bool Geometry2D::is_polygon_clockwise(const Vector<Vector2> &p_polygon) {
+ return ::Geometry2D::is_polygon_clockwise(p_polygon);
}
-bool _Geometry2D::is_point_in_polygon(const Point2 &p_point, const Vector<Vector2> &p_polygon) {
- return Geometry2D::is_point_in_polygon(p_point, p_polygon);
+bool Geometry2D::is_point_in_polygon(const Point2 &p_point, const Vector<Vector2> &p_polygon) {
+ return ::Geometry2D::is_point_in_polygon(p_point, p_polygon);
}
-Vector<int> _Geometry2D::triangulate_polygon(const Vector<Vector2> &p_polygon) {
- return Geometry2D::triangulate_polygon(p_polygon);
+Vector<int> Geometry2D::triangulate_polygon(const Vector<Vector2> &p_polygon) {
+ return ::Geometry2D::triangulate_polygon(p_polygon);
}
-Vector<int> _Geometry2D::triangulate_delaunay(const Vector<Vector2> &p_points) {
- return Geometry2D::triangulate_delaunay(p_points);
+Vector<int> Geometry2D::triangulate_delaunay(const Vector<Vector2> &p_points) {
+ return ::Geometry2D::triangulate_delaunay(p_points);
}
-Vector<Point2> _Geometry2D::convex_hull(const Vector<Point2> &p_points) {
- return Geometry2D::convex_hull(p_points);
+Vector<Point2> Geometry2D::convex_hull(const Vector<Point2> &p_points) {
+ return ::Geometry2D::convex_hull(p_points);
}
-Array _Geometry2D::merge_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) {
- Vector<Vector<Point2>> polys = Geometry2D::merge_polygons(p_polygon_a, p_polygon_b);
+Array Geometry2D::merge_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) {
+ Vector<Vector<Point2>> polys = ::Geometry2D::merge_polygons(p_polygon_a, p_polygon_b);
Array ret;
@@ -724,8 +721,8 @@ Array _Geometry2D::merge_polygons(const Vector<Vector2> &p_polygon_a, const Vect
return ret;
}
-Array _Geometry2D::clip_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) {
- Vector<Vector<Point2>> polys = Geometry2D::clip_polygons(p_polygon_a, p_polygon_b);
+Array Geometry2D::clip_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) {
+ Vector<Vector<Point2>> polys = ::Geometry2D::clip_polygons(p_polygon_a, p_polygon_b);
Array ret;
@@ -735,8 +732,8 @@ Array _Geometry2D::clip_polygons(const Vector<Vector2> &p_polygon_a, const Vecto
return ret;
}
-Array _Geometry2D::intersect_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) {
- Vector<Vector<Point2>> polys = Geometry2D::intersect_polygons(p_polygon_a, p_polygon_b);
+Array Geometry2D::intersect_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) {
+ Vector<Vector<Point2>> polys = ::Geometry2D::intersect_polygons(p_polygon_a, p_polygon_b);
Array ret;
@@ -746,8 +743,8 @@ Array _Geometry2D::intersect_polygons(const Vector<Vector2> &p_polygon_a, const
return ret;
}
-Array _Geometry2D::exclude_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) {
- Vector<Vector<Point2>> polys = Geometry2D::exclude_polygons(p_polygon_a, p_polygon_b);
+Array Geometry2D::exclude_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) {
+ Vector<Vector<Point2>> polys = ::Geometry2D::exclude_polygons(p_polygon_a, p_polygon_b);
Array ret;
@@ -757,8 +754,8 @@ Array _Geometry2D::exclude_polygons(const Vector<Vector2> &p_polygon_a, const Ve
return ret;
}
-Array _Geometry2D::clip_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) {
- Vector<Vector<Point2>> polys = Geometry2D::clip_polyline_with_polygon(p_polyline, p_polygon);
+Array Geometry2D::clip_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) {
+ Vector<Vector<Point2>> polys = ::Geometry2D::clip_polyline_with_polygon(p_polyline, p_polygon);
Array ret;
@@ -768,8 +765,8 @@ Array _Geometry2D::clip_polyline_with_polygon(const Vector<Vector2> &p_polyline,
return ret;
}
-Array _Geometry2D::intersect_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) {
- Vector<Vector<Point2>> polys = Geometry2D::intersect_polyline_with_polygon(p_polyline, p_polygon);
+Array Geometry2D::intersect_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) {
+ Vector<Vector<Point2>> polys = ::Geometry2D::intersect_polyline_with_polygon(p_polyline, p_polygon);
Array ret;
@@ -779,8 +776,8 @@ Array _Geometry2D::intersect_polyline_with_polygon(const Vector<Vector2> &p_poly
return ret;
}
-Array _Geometry2D::offset_polygon(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type) {
- Vector<Vector<Point2>> polys = Geometry2D::offset_polygon(p_polygon, p_delta, Geometry2D::PolyJoinType(p_join_type));
+Array Geometry2D::offset_polygon(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type) {
+ Vector<Vector<Point2>> polys = ::Geometry2D::offset_polygon(p_polygon, p_delta, ::Geometry2D::PolyJoinType(p_join_type));
Array ret;
@@ -790,8 +787,8 @@ Array _Geometry2D::offset_polygon(const Vector<Vector2> &p_polygon, real_t p_del
return ret;
}
-Array _Geometry2D::offset_polyline(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) {
- Vector<Vector<Point2>> polys = Geometry2D::offset_polyline(p_polygon, p_delta, Geometry2D::PolyJoinType(p_join_type), Geometry2D::PolyEndType(p_end_type));
+Array Geometry2D::offset_polyline(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) {
+ Vector<Vector<Point2>> polys = ::Geometry2D::offset_polyline(p_polygon, p_delta, ::Geometry2D::PolyJoinType(p_join_type), ::Geometry2D::PolyEndType(p_end_type));
Array ret;
@@ -801,7 +798,7 @@ Array _Geometry2D::offset_polyline(const Vector<Vector2> &p_polygon, real_t p_de
return ret;
}
-Dictionary _Geometry2D::make_atlas(const Vector<Size2> &p_rects) {
+Dictionary Geometry2D::make_atlas(const Vector<Size2> &p_rects) {
Dictionary ret;
Vector<Size2i> rects;
@@ -812,7 +809,7 @@ Dictionary _Geometry2D::make_atlas(const Vector<Size2> &p_rects) {
Vector<Point2i> result;
Size2i size;
- Geometry2D::make_atlas(rects, result, size);
+ ::Geometry2D::make_atlas(rects, result, size);
Size2 r_size = size;
Vector<Point2> r_result;
@@ -826,37 +823,37 @@ Dictionary _Geometry2D::make_atlas(const Vector<Size2> &p_rects) {
return ret;
}
-void _Geometry2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("is_point_in_circle", "point", "circle_position", "circle_radius"), &_Geometry2D::is_point_in_circle);
- ClassDB::bind_method(D_METHOD("segment_intersects_segment", "from_a", "to_a", "from_b", "to_b"), &_Geometry2D::segment_intersects_segment);
- ClassDB::bind_method(D_METHOD("line_intersects_line", "from_a", "dir_a", "from_b", "dir_b"), &_Geometry2D::line_intersects_line);
+void Geometry2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("is_point_in_circle", "point", "circle_position", "circle_radius"), &Geometry2D::is_point_in_circle);
+ ClassDB::bind_method(D_METHOD("segment_intersects_segment", "from_a", "to_a", "from_b", "to_b"), &Geometry2D::segment_intersects_segment);
+ ClassDB::bind_method(D_METHOD("line_intersects_line", "from_a", "dir_a", "from_b", "dir_b"), &Geometry2D::line_intersects_line);
- ClassDB::bind_method(D_METHOD("get_closest_points_between_segments", "p1", "q1", "p2", "q2"), &_Geometry2D::get_closest_points_between_segments);
+ ClassDB::bind_method(D_METHOD("get_closest_points_between_segments", "p1", "q1", "p2", "q2"), &Geometry2D::get_closest_points_between_segments);
- ClassDB::bind_method(D_METHOD("get_closest_point_to_segment", "point", "s1", "s2"), &_Geometry2D::get_closest_point_to_segment);
+ ClassDB::bind_method(D_METHOD("get_closest_point_to_segment", "point", "s1", "s2"), &Geometry2D::get_closest_point_to_segment);
- ClassDB::bind_method(D_METHOD("get_closest_point_to_segment_uncapped", "point", "s1", "s2"), &_Geometry2D::get_closest_point_to_segment_uncapped);
+ ClassDB::bind_method(D_METHOD("get_closest_point_to_segment_uncapped", "point", "s1", "s2"), &Geometry2D::get_closest_point_to_segment_uncapped);
- ClassDB::bind_method(D_METHOD("point_is_inside_triangle", "point", "a", "b", "c"), &_Geometry2D::point_is_inside_triangle);
+ ClassDB::bind_method(D_METHOD("point_is_inside_triangle", "point", "a", "b", "c"), &Geometry2D::point_is_inside_triangle);
- ClassDB::bind_method(D_METHOD("is_polygon_clockwise", "polygon"), &_Geometry2D::is_polygon_clockwise);
- ClassDB::bind_method(D_METHOD("is_point_in_polygon", "point", "polygon"), &_Geometry2D::is_point_in_polygon);
- ClassDB::bind_method(D_METHOD("triangulate_polygon", "polygon"), &_Geometry2D::triangulate_polygon);
- ClassDB::bind_method(D_METHOD("triangulate_delaunay", "points"), &_Geometry2D::triangulate_delaunay);
- ClassDB::bind_method(D_METHOD("convex_hull", "points"), &_Geometry2D::convex_hull);
+ ClassDB::bind_method(D_METHOD("is_polygon_clockwise", "polygon"), &Geometry2D::is_polygon_clockwise);
+ ClassDB::bind_method(D_METHOD("is_point_in_polygon", "point", "polygon"), &Geometry2D::is_point_in_polygon);
+ ClassDB::bind_method(D_METHOD("triangulate_polygon", "polygon"), &Geometry2D::triangulate_polygon);
+ ClassDB::bind_method(D_METHOD("triangulate_delaunay", "points"), &Geometry2D::triangulate_delaunay);
+ ClassDB::bind_method(D_METHOD("convex_hull", "points"), &Geometry2D::convex_hull);
- ClassDB::bind_method(D_METHOD("merge_polygons", "polygon_a", "polygon_b"), &_Geometry2D::merge_polygons);
- ClassDB::bind_method(D_METHOD("clip_polygons", "polygon_a", "polygon_b"), &_Geometry2D::clip_polygons);
- ClassDB::bind_method(D_METHOD("intersect_polygons", "polygon_a", "polygon_b"), &_Geometry2D::intersect_polygons);
- ClassDB::bind_method(D_METHOD("exclude_polygons", "polygon_a", "polygon_b"), &_Geometry2D::exclude_polygons);
+ ClassDB::bind_method(D_METHOD("merge_polygons", "polygon_a", "polygon_b"), &Geometry2D::merge_polygons);
+ ClassDB::bind_method(D_METHOD("clip_polygons", "polygon_a", "polygon_b"), &Geometry2D::clip_polygons);
+ ClassDB::bind_method(D_METHOD("intersect_polygons", "polygon_a", "polygon_b"), &Geometry2D::intersect_polygons);
+ ClassDB::bind_method(D_METHOD("exclude_polygons", "polygon_a", "polygon_b"), &Geometry2D::exclude_polygons);
- ClassDB::bind_method(D_METHOD("clip_polyline_with_polygon", "polyline", "polygon"), &_Geometry2D::clip_polyline_with_polygon);
- ClassDB::bind_method(D_METHOD("intersect_polyline_with_polygon", "polyline", "polygon"), &_Geometry2D::intersect_polyline_with_polygon);
+ ClassDB::bind_method(D_METHOD("clip_polyline_with_polygon", "polyline", "polygon"), &Geometry2D::clip_polyline_with_polygon);
+ ClassDB::bind_method(D_METHOD("intersect_polyline_with_polygon", "polyline", "polygon"), &Geometry2D::intersect_polyline_with_polygon);
- ClassDB::bind_method(D_METHOD("offset_polygon", "polygon", "delta", "join_type"), &_Geometry2D::offset_polygon, DEFVAL(JOIN_SQUARE));
- ClassDB::bind_method(D_METHOD("offset_polyline", "polyline", "delta", "join_type", "end_type"), &_Geometry2D::offset_polyline, DEFVAL(JOIN_SQUARE), DEFVAL(END_SQUARE));
+ ClassDB::bind_method(D_METHOD("offset_polygon", "polygon", "delta", "join_type"), &Geometry2D::offset_polygon, DEFVAL(JOIN_SQUARE));
+ ClassDB::bind_method(D_METHOD("offset_polyline", "polyline", "delta", "join_type", "end_type"), &Geometry2D::offset_polyline, DEFVAL(JOIN_SQUARE), DEFVAL(END_SQUARE));
- ClassDB::bind_method(D_METHOD("make_atlas", "sizes"), &_Geometry2D::make_atlas);
+ ClassDB::bind_method(D_METHOD("make_atlas", "sizes"), &Geometry2D::make_atlas);
BIND_ENUM_CONSTANT(OPERATION_UNION);
BIND_ENUM_CONSTANT(OPERATION_DIFFERENCE);
@@ -874,29 +871,29 @@ void _Geometry2D::_bind_methods() {
BIND_ENUM_CONSTANT(END_ROUND);
}
-////// _Geometry3D //////
+////// Geometry3D //////
-_Geometry3D *_Geometry3D::singleton = nullptr;
+Geometry3D *Geometry3D::singleton = nullptr;
-_Geometry3D *_Geometry3D::get_singleton() {
+Geometry3D *Geometry3D::get_singleton() {
return singleton;
}
-Vector<Plane> _Geometry3D::build_box_planes(const Vector3 &p_extents) {
- return Geometry3D::build_box_planes(p_extents);
+Vector<Plane> Geometry3D::build_box_planes(const Vector3 &p_extents) {
+ return ::Geometry3D::build_box_planes(p_extents);
}
-Vector<Plane> _Geometry3D::build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis) {
- return Geometry3D::build_cylinder_planes(p_radius, p_height, p_sides, p_axis);
+Vector<Plane> Geometry3D::build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis) {
+ return ::Geometry3D::build_cylinder_planes(p_radius, p_height, p_sides, p_axis);
}
-Vector<Plane> _Geometry3D::build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis) {
- return Geometry3D::build_capsule_planes(p_radius, p_height, p_sides, p_lats, p_axis);
+Vector<Plane> Geometry3D::build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis) {
+ return ::Geometry3D::build_capsule_planes(p_radius, p_height, p_sides, p_lats, p_axis);
}
-Vector<Vector3> _Geometry3D::get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2) {
+Vector<Vector3> Geometry3D::get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2) {
Vector3 r1, r2;
- Geometry3D::get_closest_points_between_segments(p1, p2, q1, q2, r1, r2);
+ ::Geometry3D::get_closest_points_between_segments(p1, p2, q1, q2, r1, r2);
Vector<Vector3> r;
r.resize(2);
r.set(0, r1);
@@ -904,38 +901,38 @@ Vector<Vector3> _Geometry3D::get_closest_points_between_segments(const Vector3 &
return r;
}
-Vector3 _Geometry3D::get_closest_point_to_segment(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b) {
+Vector3 Geometry3D::get_closest_point_to_segment(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b) {
Vector3 s[2] = { p_a, p_b };
- return Geometry3D::get_closest_point_to_segment(p_point, s);
+ return ::Geometry3D::get_closest_point_to_segment(p_point, s);
}
-Vector3 _Geometry3D::get_closest_point_to_segment_uncapped(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b) {
+Vector3 Geometry3D::get_closest_point_to_segment_uncapped(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b) {
Vector3 s[2] = { p_a, p_b };
- return Geometry3D::get_closest_point_to_segment_uncapped(p_point, s);
+ return ::Geometry3D::get_closest_point_to_segment_uncapped(p_point, s);
}
-Variant _Geometry3D::ray_intersects_triangle(const Vector3 &p_from, const Vector3 &p_dir, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2) {
+Variant Geometry3D::ray_intersects_triangle(const Vector3 &p_from, const Vector3 &p_dir, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2) {
Vector3 res;
- if (Geometry3D::ray_intersects_triangle(p_from, p_dir, p_v0, p_v1, p_v2, &res)) {
+ if (::Geometry3D::ray_intersects_triangle(p_from, p_dir, p_v0, p_v1, p_v2, &res)) {
return res;
} else {
return Variant();
}
}
-Variant _Geometry3D::segment_intersects_triangle(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2) {
+Variant Geometry3D::segment_intersects_triangle(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2) {
Vector3 res;
- if (Geometry3D::segment_intersects_triangle(p_from, p_to, p_v0, p_v1, p_v2, &res)) {
+ if (::Geometry3D::segment_intersects_triangle(p_from, p_to, p_v0, p_v1, p_v2, &res)) {
return res;
} else {
return Variant();
}
}
-Vector<Vector3> _Geometry3D::segment_intersects_sphere(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_sphere_pos, real_t p_sphere_radius) {
+Vector<Vector3> Geometry3D::segment_intersects_sphere(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_sphere_pos, real_t p_sphere_radius) {
Vector<Vector3> r;
Vector3 res, norm;
- if (!Geometry3D::segment_intersects_sphere(p_from, p_to, p_sphere_pos, p_sphere_radius, &res, &norm)) {
+ if (!::Geometry3D::segment_intersects_sphere(p_from, p_to, p_sphere_pos, p_sphere_radius, &res, &norm)) {
return r;
}
@@ -945,10 +942,10 @@ Vector<Vector3> _Geometry3D::segment_intersects_sphere(const Vector3 &p_from, co
return r;
}
-Vector<Vector3> _Geometry3D::segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, float p_height, float p_radius) {
+Vector<Vector3> Geometry3D::segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, float p_height, float p_radius) {
Vector<Vector3> r;
Vector3 res, norm;
- if (!Geometry3D::segment_intersects_cylinder(p_from, p_to, p_height, p_radius, &res, &norm)) {
+ if (!::Geometry3D::segment_intersects_cylinder(p_from, p_to, p_height, p_radius, &res, &norm)) {
return r;
}
@@ -958,10 +955,10 @@ Vector<Vector3> _Geometry3D::segment_intersects_cylinder(const Vector3 &p_from,
return r;
}
-Vector<Vector3> _Geometry3D::segment_intersects_convex(const Vector3 &p_from, const Vector3 &p_to, const Vector<Plane> &p_planes) {
+Vector<Vector3> Geometry3D::segment_intersects_convex(const Vector3 &p_from, const Vector3 &p_to, const Vector<Plane> &p_planes) {
Vector<Vector3> r;
Vector3 res, norm;
- if (!Geometry3D::segment_intersects_convex(p_from, p_to, p_planes.ptr(), p_planes.size(), &res, &norm)) {
+ if (!::Geometry3D::segment_intersects_convex(p_from, p_to, p_planes.ptr(), p_planes.size(), &res, &norm)) {
return r;
}
@@ -971,33 +968,33 @@ Vector<Vector3> _Geometry3D::segment_intersects_convex(const Vector3 &p_from, co
return r;
}
-Vector<Vector3> _Geometry3D::clip_polygon(const Vector<Vector3> &p_points, const Plane &p_plane) {
- return Geometry3D::clip_polygon(p_points, p_plane);
+Vector<Vector3> Geometry3D::clip_polygon(const Vector<Vector3> &p_points, const Plane &p_plane) {
+ return ::Geometry3D::clip_polygon(p_points, p_plane);
}
-void _Geometry3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("build_box_planes", "extents"), &_Geometry3D::build_box_planes);
- ClassDB::bind_method(D_METHOD("build_cylinder_planes", "radius", "height", "sides", "axis"), &_Geometry3D::build_cylinder_planes, DEFVAL(Vector3::AXIS_Z));
- ClassDB::bind_method(D_METHOD("build_capsule_planes", "radius", "height", "sides", "lats", "axis"), &_Geometry3D::build_capsule_planes, DEFVAL(Vector3::AXIS_Z));
+void Geometry3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("build_box_planes", "extents"), &Geometry3D::build_box_planes);
+ ClassDB::bind_method(D_METHOD("build_cylinder_planes", "radius", "height", "sides", "axis"), &Geometry3D::build_cylinder_planes, DEFVAL(Vector3::AXIS_Z));
+ ClassDB::bind_method(D_METHOD("build_capsule_planes", "radius", "height", "sides", "lats", "axis"), &Geometry3D::build_capsule_planes, DEFVAL(Vector3::AXIS_Z));
- ClassDB::bind_method(D_METHOD("get_closest_points_between_segments", "p1", "p2", "q1", "q2"), &_Geometry3D::get_closest_points_between_segments);
+ ClassDB::bind_method(D_METHOD("get_closest_points_between_segments", "p1", "p2", "q1", "q2"), &Geometry3D::get_closest_points_between_segments);
- ClassDB::bind_method(D_METHOD("get_closest_point_to_segment", "point", "s1", "s2"), &_Geometry3D::get_closest_point_to_segment);
+ ClassDB::bind_method(D_METHOD("get_closest_point_to_segment", "point", "s1", "s2"), &Geometry3D::get_closest_point_to_segment);
- ClassDB::bind_method(D_METHOD("get_closest_point_to_segment_uncapped", "point", "s1", "s2"), &_Geometry3D::get_closest_point_to_segment_uncapped);
+ ClassDB::bind_method(D_METHOD("get_closest_point_to_segment_uncapped", "point", "s1", "s2"), &Geometry3D::get_closest_point_to_segment_uncapped);
- ClassDB::bind_method(D_METHOD("ray_intersects_triangle", "from", "dir", "a", "b", "c"), &_Geometry3D::ray_intersects_triangle);
- ClassDB::bind_method(D_METHOD("segment_intersects_triangle", "from", "to", "a", "b", "c"), &_Geometry3D::segment_intersects_triangle);
- ClassDB::bind_method(D_METHOD("segment_intersects_sphere", "from", "to", "sphere_position", "sphere_radius"), &_Geometry3D::segment_intersects_sphere);
- ClassDB::bind_method(D_METHOD("segment_intersects_cylinder", "from", "to", "height", "radius"), &_Geometry3D::segment_intersects_cylinder);
- ClassDB::bind_method(D_METHOD("segment_intersects_convex", "from", "to", "planes"), &_Geometry3D::segment_intersects_convex);
+ ClassDB::bind_method(D_METHOD("ray_intersects_triangle", "from", "dir", "a", "b", "c"), &Geometry3D::ray_intersects_triangle);
+ ClassDB::bind_method(D_METHOD("segment_intersects_triangle", "from", "to", "a", "b", "c"), &Geometry3D::segment_intersects_triangle);
+ ClassDB::bind_method(D_METHOD("segment_intersects_sphere", "from", "to", "sphere_position", "sphere_radius"), &Geometry3D::segment_intersects_sphere);
+ ClassDB::bind_method(D_METHOD("segment_intersects_cylinder", "from", "to", "height", "radius"), &Geometry3D::segment_intersects_cylinder);
+ ClassDB::bind_method(D_METHOD("segment_intersects_convex", "from", "to", "planes"), &Geometry3D::segment_intersects_convex);
- ClassDB::bind_method(D_METHOD("clip_polygon", "points", "plane"), &_Geometry3D::clip_polygon);
+ ClassDB::bind_method(D_METHOD("clip_polygon", "points", "plane"), &Geometry3D::clip_polygon);
}
-////// _File //////
+////// File //////
-Error _File::open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key) {
+Error File::open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key) {
Error err = open(p_path, p_mode_flags);
if (err) {
return err;
@@ -1014,7 +1011,7 @@ Error _File::open_encrypted(const String &p_path, ModeFlags p_mode_flags, const
return OK;
}
-Error _File::open_encrypted_pass(const String &p_path, ModeFlags p_mode_flags, const String &p_pass) {
+Error File::open_encrypted_pass(const String &p_path, ModeFlags p_mode_flags, const String &p_pass) {
Error err = open(p_path, p_mode_flags);
if (err) {
return err;
@@ -1032,7 +1029,7 @@ Error _File::open_encrypted_pass(const String &p_path, ModeFlags p_mode_flags, c
return OK;
}
-Error _File::open_compressed(const String &p_path, ModeFlags p_mode_flags, CompressionMode p_compress_mode) {
+Error File::open_compressed(const String &p_path, ModeFlags p_mode_flags, CompressionMode p_compress_mode) {
FileAccessCompressed *fac = memnew(FileAccessCompressed);
fac->configure("GCPF", (Compression::Mode)p_compress_mode);
@@ -1048,7 +1045,7 @@ Error _File::open_compressed(const String &p_path, ModeFlags p_mode_flags, Compr
return OK;
}
-Error _File::open(const String &p_path, ModeFlags p_mode_flags) {
+Error File::open(const String &p_path, ModeFlags p_mode_flags) {
close();
Error err;
f = FileAccess::open(p_path, p_mode_flags, &err);
@@ -1058,94 +1055,94 @@ Error _File::open(const String &p_path, ModeFlags p_mode_flags) {
return err;
}
-void _File::flush() {
+void File::flush() {
ERR_FAIL_COND_MSG(!f, "File must be opened before flushing.");
f->flush();
}
-void _File::close() {
+void File::close() {
if (f) {
memdelete(f);
}
f = nullptr;
}
-bool _File::is_open() const {
+bool File::is_open() const {
return f != nullptr;
}
-String _File::get_path() const {
+String File::get_path() const {
ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use.");
return f->get_path();
}
-String _File::get_path_absolute() const {
+String File::get_path_absolute() const {
ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use.");
return f->get_path_absolute();
}
-void _File::seek(int64_t p_position) {
+void File::seek(int64_t p_position) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
ERR_FAIL_COND_MSG(p_position < 0, "Seek position must be a positive integer.");
f->seek(p_position);
}
-void _File::seek_end(int64_t p_position) {
+void File::seek_end(int64_t p_position) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->seek_end(p_position);
}
-uint64_t _File::get_position() const {
+uint64_t File::get_position() const {
ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
return f->get_position();
}
-uint64_t _File::get_length() const {
+uint64_t File::get_length() const {
ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
return f->get_length();
}
-bool _File::eof_reached() const {
+bool File::eof_reached() const {
ERR_FAIL_COND_V_MSG(!f, false, "File must be opened before use.");
return f->eof_reached();
}
-uint8_t _File::get_8() const {
+uint8_t File::get_8() const {
ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
return f->get_8();
}
-uint16_t _File::get_16() const {
+uint16_t File::get_16() const {
ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
return f->get_16();
}
-uint32_t _File::get_32() const {
+uint32_t File::get_32() const {
ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
return f->get_32();
}
-uint64_t _File::get_64() const {
+uint64_t File::get_64() const {
ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
return f->get_64();
}
-float _File::get_float() const {
+float File::get_float() const {
ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
return f->get_float();
}
-double _File::get_double() const {
+double File::get_double() const {
ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
return f->get_double();
}
-real_t _File::get_real() const {
+real_t File::get_real() const {
ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
return f->get_real();
}
-Vector<uint8_t> _File::get_buffer(int64_t p_length) const {
+Vector<uint8_t> File::get_buffer(int64_t p_length) const {
Vector<uint8_t> data;
ERR_FAIL_COND_V_MSG(!f, data, "File must be opened before use.");
@@ -1167,7 +1164,7 @@ Vector<uint8_t> _File::get_buffer(int64_t p_length) const {
return data;
}
-String _File::get_as_text() const {
+String File::get_as_text() const {
ERR_FAIL_COND_V_MSG(!f, String(), "File must be opened before use.");
String text;
@@ -1186,20 +1183,20 @@ String _File::get_as_text() const {
return text;
}
-String _File::get_md5(const String &p_path) const {
+String File::get_md5(const String &p_path) const {
return FileAccess::get_md5(p_path);
}
-String _File::get_sha256(const String &p_path) const {
+String File::get_sha256(const String &p_path) const {
return FileAccess::get_sha256(p_path);
}
-String _File::get_line() const {
+String File::get_line() const {
ERR_FAIL_COND_V_MSG(!f, String(), "File must be opened before use.");
return f->get_line();
}
-Vector<String> _File::get_csv_line(const String &p_delim) const {
+Vector<String> File::get_csv_line(const String &p_delim) const {
ERR_FAIL_COND_V_MSG(!f, Vector<String>(), "File must be opened before use.");
return f->get_csv_line(p_delim);
}
@@ -1209,95 +1206,95 @@ Vector<String> _File::get_csv_line(const String &p_delim) const {
* These flags get reset to false (little endian) on each open
*/
-void _File::set_big_endian(bool p_big_endian) {
+void File::set_big_endian(bool p_big_endian) {
big_endian = p_big_endian;
if (f) {
f->set_big_endian(p_big_endian);
}
}
-bool _File::is_big_endian() {
+bool File::is_big_endian() {
return big_endian;
}
-Error _File::get_error() const {
+Error File::get_error() const {
if (!f) {
return ERR_UNCONFIGURED;
}
return f->get_error();
}
-void _File::store_8(uint8_t p_dest) {
+void File::store_8(uint8_t p_dest) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->store_8(p_dest);
}
-void _File::store_16(uint16_t p_dest) {
+void File::store_16(uint16_t p_dest) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->store_16(p_dest);
}
-void _File::store_32(uint32_t p_dest) {
+void File::store_32(uint32_t p_dest) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->store_32(p_dest);
}
-void _File::store_64(uint64_t p_dest) {
+void File::store_64(uint64_t p_dest) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->store_64(p_dest);
}
-void _File::store_float(float p_dest) {
+void File::store_float(float p_dest) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->store_float(p_dest);
}
-void _File::store_double(double p_dest) {
+void File::store_double(double p_dest) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->store_double(p_dest);
}
-void _File::store_real(real_t p_real) {
+void File::store_real(real_t p_real) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->store_real(p_real);
}
-void _File::store_string(const String &p_string) {
+void File::store_string(const String &p_string) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->store_string(p_string);
}
-void _File::store_pascal_string(const String &p_string) {
+void File::store_pascal_string(const String &p_string) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->store_pascal_string(p_string);
}
-String _File::get_pascal_string() {
+String File::get_pascal_string() {
ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use.");
return f->get_pascal_string();
}
-void _File::store_line(const String &p_string) {
+void File::store_line(const String &p_string) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->store_line(p_string);
}
-void _File::store_csv_line(const Vector<String> &p_values, const String &p_delim) {
+void File::store_csv_line(const Vector<String> &p_values, const String &p_delim) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->store_csv_line(p_values, p_delim);
}
-void _File::store_buffer(const Vector<uint8_t> &p_buffer) {
+void File::store_buffer(const Vector<uint8_t> &p_buffer) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
uint64_t len = p_buffer.size();
@@ -1310,11 +1307,11 @@ void _File::store_buffer(const Vector<uint8_t> &p_buffer) {
f->store_buffer(&r[0], len);
}
-bool _File::file_exists(const String &p_name) const {
+bool File::file_exists(const String &p_name) const {
return FileAccess::exists(p_name);
}
-void _File::store_var(const Variant &p_var, bool p_full_objects) {
+void File::store_var(const Variant &p_var, bool p_full_objects) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
int len;
Error err = encode_variant(p_var, nullptr, len, p_full_objects);
@@ -1331,7 +1328,7 @@ void _File::store_var(const Variant &p_var, bool p_full_objects) {
store_buffer(buff);
}
-Variant _File::get_var(bool p_allow_objects) const {
+Variant File::get_var(bool p_allow_objects) const {
ERR_FAIL_COND_V_MSG(!f, Variant(), "File must be opened before use.");
uint32_t len = get_32();
Vector<uint8_t> buff = get_buffer(len);
@@ -1346,62 +1343,62 @@ Variant _File::get_var(bool p_allow_objects) const {
return v;
}
-uint64_t _File::get_modified_time(const String &p_file) const {
+uint64_t File::get_modified_time(const String &p_file) const {
return FileAccess::get_modified_time(p_file);
}
-void _File::_bind_methods() {
- ClassDB::bind_method(D_METHOD("open_encrypted", "path", "mode_flags", "key"), &_File::open_encrypted);
- ClassDB::bind_method(D_METHOD("open_encrypted_with_pass", "path", "mode_flags", "pass"), &_File::open_encrypted_pass);
- ClassDB::bind_method(D_METHOD("open_compressed", "path", "mode_flags", "compression_mode"), &_File::open_compressed, DEFVAL(0));
-
- ClassDB::bind_method(D_METHOD("open", "path", "flags"), &_File::open);
- ClassDB::bind_method(D_METHOD("flush"), &_File::flush);
- ClassDB::bind_method(D_METHOD("close"), &_File::close);
- ClassDB::bind_method(D_METHOD("get_path"), &_File::get_path);
- ClassDB::bind_method(D_METHOD("get_path_absolute"), &_File::get_path_absolute);
- ClassDB::bind_method(D_METHOD("is_open"), &_File::is_open);
- ClassDB::bind_method(D_METHOD("seek", "position"), &_File::seek);
- ClassDB::bind_method(D_METHOD("seek_end", "position"), &_File::seek_end, DEFVAL(0));
- ClassDB::bind_method(D_METHOD("get_position"), &_File::get_position);
- ClassDB::bind_method(D_METHOD("get_length"), &_File::get_length);
- ClassDB::bind_method(D_METHOD("eof_reached"), &_File::eof_reached);
- ClassDB::bind_method(D_METHOD("get_8"), &_File::get_8);
- ClassDB::bind_method(D_METHOD("get_16"), &_File::get_16);
- ClassDB::bind_method(D_METHOD("get_32"), &_File::get_32);
- ClassDB::bind_method(D_METHOD("get_64"), &_File::get_64);
- ClassDB::bind_method(D_METHOD("get_float"), &_File::get_float);
- ClassDB::bind_method(D_METHOD("get_double"), &_File::get_double);
- ClassDB::bind_method(D_METHOD("get_real"), &_File::get_real);
- ClassDB::bind_method(D_METHOD("get_buffer", "length"), &_File::get_buffer);
- ClassDB::bind_method(D_METHOD("get_line"), &_File::get_line);
- ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &_File::get_csv_line, DEFVAL(","));
- ClassDB::bind_method(D_METHOD("get_as_text"), &_File::get_as_text);
- ClassDB::bind_method(D_METHOD("get_md5", "path"), &_File::get_md5);
- ClassDB::bind_method(D_METHOD("get_sha256", "path"), &_File::get_sha256);
- ClassDB::bind_method(D_METHOD("is_big_endian"), &_File::is_big_endian);
- ClassDB::bind_method(D_METHOD("set_big_endian", "big_endian"), &_File::set_big_endian);
- ClassDB::bind_method(D_METHOD("get_error"), &_File::get_error);
- ClassDB::bind_method(D_METHOD("get_var", "allow_objects"), &_File::get_var, DEFVAL(false));
-
- ClassDB::bind_method(D_METHOD("store_8", "value"), &_File::store_8);
- ClassDB::bind_method(D_METHOD("store_16", "value"), &_File::store_16);
- ClassDB::bind_method(D_METHOD("store_32", "value"), &_File::store_32);
- ClassDB::bind_method(D_METHOD("store_64", "value"), &_File::store_64);
- ClassDB::bind_method(D_METHOD("store_float", "value"), &_File::store_float);
- ClassDB::bind_method(D_METHOD("store_double", "value"), &_File::store_double);
- ClassDB::bind_method(D_METHOD("store_real", "value"), &_File::store_real);
- ClassDB::bind_method(D_METHOD("store_buffer", "buffer"), &_File::store_buffer);
- ClassDB::bind_method(D_METHOD("store_line", "line"), &_File::store_line);
- ClassDB::bind_method(D_METHOD("store_csv_line", "values", "delim"), &_File::store_csv_line, DEFVAL(","));
- ClassDB::bind_method(D_METHOD("store_string", "string"), &_File::store_string);
- ClassDB::bind_method(D_METHOD("store_var", "value", "full_objects"), &_File::store_var, DEFVAL(false));
-
- ClassDB::bind_method(D_METHOD("store_pascal_string", "string"), &_File::store_pascal_string);
- ClassDB::bind_method(D_METHOD("get_pascal_string"), &_File::get_pascal_string);
-
- ClassDB::bind_method(D_METHOD("file_exists", "path"), &_File::file_exists);
- ClassDB::bind_method(D_METHOD("get_modified_time", "file"), &_File::get_modified_time);
+void File::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("open_encrypted", "path", "mode_flags", "key"), &File::open_encrypted);
+ ClassDB::bind_method(D_METHOD("open_encrypted_with_pass", "path", "mode_flags", "pass"), &File::open_encrypted_pass);
+ ClassDB::bind_method(D_METHOD("open_compressed", "path", "mode_flags", "compression_mode"), &File::open_compressed, DEFVAL(0));
+
+ ClassDB::bind_method(D_METHOD("open", "path", "flags"), &File::open);
+ ClassDB::bind_method(D_METHOD("flush"), &File::flush);
+ ClassDB::bind_method(D_METHOD("close"), &File::close);
+ ClassDB::bind_method(D_METHOD("get_path"), &File::get_path);
+ ClassDB::bind_method(D_METHOD("get_path_absolute"), &File::get_path_absolute);
+ ClassDB::bind_method(D_METHOD("is_open"), &File::is_open);
+ ClassDB::bind_method(D_METHOD("seek", "position"), &File::seek);
+ ClassDB::bind_method(D_METHOD("seek_end", "position"), &File::seek_end, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_position"), &File::get_position);
+ ClassDB::bind_method(D_METHOD("get_length"), &File::get_length);
+ ClassDB::bind_method(D_METHOD("eof_reached"), &File::eof_reached);
+ ClassDB::bind_method(D_METHOD("get_8"), &File::get_8);
+ ClassDB::bind_method(D_METHOD("get_16"), &File::get_16);
+ ClassDB::bind_method(D_METHOD("get_32"), &File::get_32);
+ ClassDB::bind_method(D_METHOD("get_64"), &File::get_64);
+ ClassDB::bind_method(D_METHOD("get_float"), &File::get_float);
+ ClassDB::bind_method(D_METHOD("get_double"), &File::get_double);
+ ClassDB::bind_method(D_METHOD("get_real"), &File::get_real);
+ ClassDB::bind_method(D_METHOD("get_buffer", "length"), &File::get_buffer);
+ ClassDB::bind_method(D_METHOD("get_line"), &File::get_line);
+ ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &File::get_csv_line, DEFVAL(","));
+ ClassDB::bind_method(D_METHOD("get_as_text"), &File::get_as_text);
+ ClassDB::bind_method(D_METHOD("get_md5", "path"), &File::get_md5);
+ ClassDB::bind_method(D_METHOD("get_sha256", "path"), &File::get_sha256);
+ ClassDB::bind_method(D_METHOD("is_big_endian"), &File::is_big_endian);
+ ClassDB::bind_method(D_METHOD("set_big_endian", "big_endian"), &File::set_big_endian);
+ ClassDB::bind_method(D_METHOD("get_error"), &File::get_error);
+ ClassDB::bind_method(D_METHOD("get_var", "allow_objects"), &File::get_var, DEFVAL(false));
+
+ ClassDB::bind_method(D_METHOD("store_8", "value"), &File::store_8);
+ ClassDB::bind_method(D_METHOD("store_16", "value"), &File::store_16);
+ ClassDB::bind_method(D_METHOD("store_32", "value"), &File::store_32);
+ ClassDB::bind_method(D_METHOD("store_64", "value"), &File::store_64);
+ ClassDB::bind_method(D_METHOD("store_float", "value"), &File::store_float);
+ ClassDB::bind_method(D_METHOD("store_double", "value"), &File::store_double);
+ ClassDB::bind_method(D_METHOD("store_real", "value"), &File::store_real);
+ ClassDB::bind_method(D_METHOD("store_buffer", "buffer"), &File::store_buffer);
+ ClassDB::bind_method(D_METHOD("store_line", "line"), &File::store_line);
+ ClassDB::bind_method(D_METHOD("store_csv_line", "values", "delim"), &File::store_csv_line, DEFVAL(","));
+ ClassDB::bind_method(D_METHOD("store_string", "string"), &File::store_string);
+ ClassDB::bind_method(D_METHOD("store_var", "value", "full_objects"), &File::store_var, DEFVAL(false));
+
+ ClassDB::bind_method(D_METHOD("store_pascal_string", "string"), &File::store_pascal_string);
+ ClassDB::bind_method(D_METHOD("get_pascal_string"), &File::get_pascal_string);
+
+ ClassDB::bind_method(D_METHOD("file_exists", "path"), &File::file_exists);
+ ClassDB::bind_method(D_METHOD("get_modified_time", "file"), &File::get_modified_time);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "big_endian"), "set_big_endian", "is_big_endian");
@@ -1416,15 +1413,15 @@ void _File::_bind_methods() {
BIND_ENUM_CONSTANT(COMPRESSION_GZIP);
}
-_File::~_File() {
+File::~File() {
if (f) {
memdelete(f);
}
}
-////// _Directory //////
+////// Directory //////
-Error _Directory::open(const String &p_path) {
+Error Directory::open(const String &p_path) {
Error err;
DirAccess *alt = DirAccess::open(p_path, &err);
@@ -1440,11 +1437,11 @@ Error _Directory::open(const String &p_path) {
return OK;
}
-bool _Directory::is_open() const {
+bool Directory::is_open() const {
return d && dir_open;
}
-Error _Directory::list_dir_begin(bool p_show_navigational, bool p_show_hidden) {
+Error Directory::list_dir_begin(bool p_show_navigational, bool p_show_hidden) {
ERR_FAIL_COND_V_MSG(!is_open(), ERR_UNCONFIGURED, "Directory must be opened before use.");
_list_skip_navigational = !p_show_navigational;
@@ -1453,7 +1450,7 @@ Error _Directory::list_dir_begin(bool p_show_navigational, bool p_show_hidden) {
return d->list_dir_begin();
}
-String _Directory::get_next() {
+String Directory::get_next() {
ERR_FAIL_COND_V_MSG(!is_open(), "", "Directory must be opened before use.");
String next = d->get_next();
@@ -1463,32 +1460,32 @@ String _Directory::get_next() {
return next;
}
-bool _Directory::current_is_dir() const {
+bool Directory::current_is_dir() const {
ERR_FAIL_COND_V_MSG(!is_open(), false, "Directory must be opened before use.");
return d->current_is_dir();
}
-void _Directory::list_dir_end() {
+void Directory::list_dir_end() {
ERR_FAIL_COND_MSG(!is_open(), "Directory must be opened before use.");
d->list_dir_end();
}
-int _Directory::get_drive_count() {
+int Directory::get_drive_count() {
ERR_FAIL_COND_V_MSG(!is_open(), 0, "Directory must be opened before use.");
return d->get_drive_count();
}
-String _Directory::get_drive(int p_drive) {
+String Directory::get_drive(int p_drive) {
ERR_FAIL_COND_V_MSG(!is_open(), "", "Directory must be opened before use.");
return d->get_drive(p_drive);
}
-int _Directory::get_current_drive() {
+int Directory::get_current_drive() {
ERR_FAIL_COND_V_MSG(!is_open(), 0, "Directory must be opened before use.");
return d->get_current_drive();
}
-Error _Directory::change_dir(String p_dir) {
+Error Directory::change_dir(String p_dir) {
ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory is not configured properly.");
Error err = d->change_dir(p_dir);
@@ -1500,12 +1497,12 @@ Error _Directory::change_dir(String p_dir) {
return OK;
}
-String _Directory::get_current_dir() {
+String Directory::get_current_dir() {
ERR_FAIL_COND_V_MSG(!is_open(), "", "Directory must be opened before use.");
return d->get_current_dir();
}
-Error _Directory::make_dir(String p_dir) {
+Error Directory::make_dir(String p_dir) {
ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory is not configured properly.");
if (!p_dir.is_rel_path()) {
DirAccess *d = DirAccess::create_for_path(p_dir);
@@ -1516,7 +1513,7 @@ Error _Directory::make_dir(String p_dir) {
return d->make_dir(p_dir);
}
-Error _Directory::make_dir_recursive(String p_dir) {
+Error Directory::make_dir_recursive(String p_dir) {
ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory is not configured properly.");
if (!p_dir.is_rel_path()) {
DirAccess *d = DirAccess::create_for_path(p_dir);
@@ -1527,7 +1524,7 @@ Error _Directory::make_dir_recursive(String p_dir) {
return d->make_dir_recursive(p_dir);
}
-bool _Directory::file_exists(String p_file) {
+bool Directory::file_exists(String p_file) {
ERR_FAIL_COND_V_MSG(!d, false, "Directory is not configured properly.");
if (!p_file.is_rel_path()) {
return FileAccess::exists(p_file);
@@ -1536,7 +1533,7 @@ bool _Directory::file_exists(String p_file) {
return d->file_exists(p_file);
}
-bool _Directory::dir_exists(String p_dir) {
+bool Directory::dir_exists(String p_dir) {
ERR_FAIL_COND_V_MSG(!d, false, "Directory is not configured properly.");
if (!p_dir.is_rel_path()) {
DirAccess *d = DirAccess::create_for_path(p_dir);
@@ -1548,31 +1545,33 @@ bool _Directory::dir_exists(String p_dir) {
return d->dir_exists(p_dir);
}
-uint64_t _Directory::get_space_left() {
+uint64_t Directory::get_space_left() {
ERR_FAIL_COND_V_MSG(!d, 0, "Directory must be opened before use.");
return d->get_space_left() / 1024 * 1024; // Truncate to closest MiB.
}
-Error _Directory::copy(String p_from, String p_to) {
+Error Directory::copy(String p_from, String p_to) {
ERR_FAIL_COND_V_MSG(!is_open(), ERR_UNCONFIGURED, "Directory must be opened before use.");
return d->copy(p_from, p_to);
}
-Error _Directory::rename(String p_from, String p_to) {
+Error Directory::rename(String p_from, String p_to) {
ERR_FAIL_COND_V_MSG(!is_open(), ERR_UNCONFIGURED, "Directory must be opened before use.");
+ ERR_FAIL_COND_V_MSG(p_from.is_empty() || p_from == "." || p_from == "..", ERR_INVALID_PARAMETER, "Invalid path to rename.");
+
if (!p_from.is_rel_path()) {
DirAccess *d = DirAccess::create_for_path(p_from);
- ERR_FAIL_COND_V_MSG(!d->file_exists(p_from), ERR_DOES_NOT_EXIST, "File does not exist.");
+ ERR_FAIL_COND_V_MSG(!d->file_exists(p_from) && !d->dir_exists(p_from), ERR_DOES_NOT_EXIST, "File or directory does not exist.");
Error err = d->rename(p_from, p_to);
memdelete(d);
return err;
}
- ERR_FAIL_COND_V_MSG(!d->file_exists(p_from), ERR_DOES_NOT_EXIST, "File does not exist.");
+ ERR_FAIL_COND_V_MSG(!d->file_exists(p_from) && !d->dir_exists(p_from), ERR_DOES_NOT_EXIST, "File or directory does not exist.");
return d->rename(p_from, p_to);
}
-Error _Directory::remove(String p_name) {
+Error Directory::remove(String p_name) {
ERR_FAIL_COND_V_MSG(!is_open(), ERR_UNCONFIGURED, "Directory must be opened before use.");
if (!p_name.is_rel_path()) {
DirAccess *d = DirAccess::create_for_path(p_name);
@@ -1584,47 +1583,47 @@ Error _Directory::remove(String p_name) {
return d->remove(p_name);
}
-void _Directory::_bind_methods() {
- ClassDB::bind_method(D_METHOD("open", "path"), &_Directory::open);
- ClassDB::bind_method(D_METHOD("list_dir_begin", "show_navigational", "show_hidden"), &_Directory::list_dir_begin, DEFVAL(false), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("get_next"), &_Directory::get_next);
- ClassDB::bind_method(D_METHOD("current_is_dir"), &_Directory::current_is_dir);
- ClassDB::bind_method(D_METHOD("list_dir_end"), &_Directory::list_dir_end);
- ClassDB::bind_method(D_METHOD("get_drive_count"), &_Directory::get_drive_count);
- ClassDB::bind_method(D_METHOD("get_drive", "idx"), &_Directory::get_drive);
- ClassDB::bind_method(D_METHOD("get_current_drive"), &_Directory::get_current_drive);
- ClassDB::bind_method(D_METHOD("change_dir", "todir"), &_Directory::change_dir);
- ClassDB::bind_method(D_METHOD("get_current_dir"), &_Directory::get_current_dir);
- ClassDB::bind_method(D_METHOD("make_dir", "path"), &_Directory::make_dir);
- ClassDB::bind_method(D_METHOD("make_dir_recursive", "path"), &_Directory::make_dir_recursive);
- ClassDB::bind_method(D_METHOD("file_exists", "path"), &_Directory::file_exists);
- ClassDB::bind_method(D_METHOD("dir_exists", "path"), &_Directory::dir_exists);
- //ClassDB::bind_method(D_METHOD("get_modified_time","file"),&_Directory::get_modified_time);
- ClassDB::bind_method(D_METHOD("get_space_left"), &_Directory::get_space_left);
- ClassDB::bind_method(D_METHOD("copy", "from", "to"), &_Directory::copy);
- ClassDB::bind_method(D_METHOD("rename", "from", "to"), &_Directory::rename);
- ClassDB::bind_method(D_METHOD("remove", "path"), &_Directory::remove);
-}
-
-_Directory::_Directory() {
+void Directory::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("open", "path"), &Directory::open);
+ ClassDB::bind_method(D_METHOD("list_dir_begin", "show_navigational", "show_hidden"), &Directory::list_dir_begin, DEFVAL(false), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_next"), &Directory::get_next);
+ ClassDB::bind_method(D_METHOD("current_is_dir"), &Directory::current_is_dir);
+ ClassDB::bind_method(D_METHOD("list_dir_end"), &Directory::list_dir_end);
+ ClassDB::bind_method(D_METHOD("get_drive_count"), &Directory::get_drive_count);
+ ClassDB::bind_method(D_METHOD("get_drive", "idx"), &Directory::get_drive);
+ ClassDB::bind_method(D_METHOD("get_current_drive"), &Directory::get_current_drive);
+ ClassDB::bind_method(D_METHOD("change_dir", "todir"), &Directory::change_dir);
+ ClassDB::bind_method(D_METHOD("get_current_dir"), &Directory::get_current_dir);
+ ClassDB::bind_method(D_METHOD("make_dir", "path"), &Directory::make_dir);
+ ClassDB::bind_method(D_METHOD("make_dir_recursive", "path"), &Directory::make_dir_recursive);
+ ClassDB::bind_method(D_METHOD("file_exists", "path"), &Directory::file_exists);
+ ClassDB::bind_method(D_METHOD("dir_exists", "path"), &Directory::dir_exists);
+ //ClassDB::bind_method(D_METHOD("get_modified_time","file"),&Directory::get_modified_time);
+ ClassDB::bind_method(D_METHOD("get_space_left"), &Directory::get_space_left);
+ ClassDB::bind_method(D_METHOD("copy", "from", "to"), &Directory::copy);
+ ClassDB::bind_method(D_METHOD("rename", "from", "to"), &Directory::rename);
+ ClassDB::bind_method(D_METHOD("remove", "path"), &Directory::remove);
+}
+
+Directory::Directory() {
d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
}
-_Directory::~_Directory() {
+Directory::~Directory() {
if (d) {
memdelete(d);
}
}
-////// _Marshalls //////
+////// Marshalls //////
-_Marshalls *_Marshalls::singleton = nullptr;
+Marshalls *Marshalls::singleton = nullptr;
-_Marshalls *_Marshalls::get_singleton() {
+Marshalls *Marshalls::get_singleton() {
return singleton;
}
-String _Marshalls::variant_to_base64(const Variant &p_var, bool p_full_objects) {
+String Marshalls::variant_to_base64(const Variant &p_var, bool p_full_objects) {
int len;
Error err = encode_variant(p_var, nullptr, len, p_full_objects);
ERR_FAIL_COND_V_MSG(err != OK, "", "Error when trying to encode Variant.");
@@ -1642,7 +1641,7 @@ String _Marshalls::variant_to_base64(const Variant &p_var, bool p_full_objects)
return ret;
}
-Variant _Marshalls::base64_to_variant(const String &p_str, bool p_allow_objects) {
+Variant Marshalls::base64_to_variant(const String &p_str, bool p_allow_objects) {
int strlen = p_str.length();
CharString cstr = p_str.ascii();
@@ -1660,13 +1659,13 @@ Variant _Marshalls::base64_to_variant(const String &p_str, bool p_allow_objects)
return v;
}
-String _Marshalls::raw_to_base64(const Vector<uint8_t> &p_arr) {
+String Marshalls::raw_to_base64(const Vector<uint8_t> &p_arr) {
String ret = CryptoCore::b64_encode_str(p_arr.ptr(), p_arr.size());
ERR_FAIL_COND_V(ret == "", ret);
return ret;
}
-Vector<uint8_t> _Marshalls::base64_to_raw(const String &p_str) {
+Vector<uint8_t> Marshalls::base64_to_raw(const String &p_str) {
int strlen = p_str.length();
CharString cstr = p_str.ascii();
@@ -1683,14 +1682,14 @@ Vector<uint8_t> _Marshalls::base64_to_raw(const String &p_str) {
return buf;
}
-String _Marshalls::utf8_to_base64(const String &p_str) {
+String Marshalls::utf8_to_base64(const String &p_str) {
CharString cstr = p_str.utf8();
String ret = CryptoCore::b64_encode_str((unsigned char *)cstr.get_data(), cstr.length());
ERR_FAIL_COND_V(ret == "", ret);
return ret;
}
-String _Marshalls::base64_to_utf8(const String &p_str) {
+String Marshalls::base64_to_utf8(const String &p_str) {
int strlen = p_str.length();
CharString cstr = p_str.ascii();
@@ -1707,62 +1706,62 @@ String _Marshalls::base64_to_utf8(const String &p_str) {
return ret;
}
-void _Marshalls::_bind_methods() {
- ClassDB::bind_method(D_METHOD("variant_to_base64", "variant", "full_objects"), &_Marshalls::variant_to_base64, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("base64_to_variant", "base64_str", "allow_objects"), &_Marshalls::base64_to_variant, DEFVAL(false));
+void Marshalls::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("variant_to_base64", "variant", "full_objects"), &Marshalls::variant_to_base64, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("base64_to_variant", "base64_str", "allow_objects"), &Marshalls::base64_to_variant, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("raw_to_base64", "array"), &_Marshalls::raw_to_base64);
- ClassDB::bind_method(D_METHOD("base64_to_raw", "base64_str"), &_Marshalls::base64_to_raw);
+ ClassDB::bind_method(D_METHOD("raw_to_base64", "array"), &Marshalls::raw_to_base64);
+ ClassDB::bind_method(D_METHOD("base64_to_raw", "base64_str"), &Marshalls::base64_to_raw);
- ClassDB::bind_method(D_METHOD("utf8_to_base64", "utf8_str"), &_Marshalls::utf8_to_base64);
- ClassDB::bind_method(D_METHOD("base64_to_utf8", "base64_str"), &_Marshalls::base64_to_utf8);
+ ClassDB::bind_method(D_METHOD("utf8_to_base64", "utf8_str"), &Marshalls::utf8_to_base64);
+ ClassDB::bind_method(D_METHOD("base64_to_utf8", "base64_str"), &Marshalls::base64_to_utf8);
}
-////// _Semaphore //////
+////// Semaphore //////
-void _Semaphore::wait() {
+void Semaphore::wait() {
semaphore.wait();
}
-Error _Semaphore::try_wait() {
+Error Semaphore::try_wait() {
return semaphore.try_wait() ? OK : ERR_BUSY;
}
-void _Semaphore::post() {
+void Semaphore::post() {
semaphore.post();
}
-void _Semaphore::_bind_methods() {
- ClassDB::bind_method(D_METHOD("wait"), &_Semaphore::wait);
- ClassDB::bind_method(D_METHOD("try_wait"), &_Semaphore::try_wait);
- ClassDB::bind_method(D_METHOD("post"), &_Semaphore::post);
+void Semaphore::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("wait"), &Semaphore::wait);
+ ClassDB::bind_method(D_METHOD("try_wait"), &Semaphore::try_wait);
+ ClassDB::bind_method(D_METHOD("post"), &Semaphore::post);
}
-////// _Mutex //////
+////// Mutex //////
-void _Mutex::lock() {
+void Mutex::lock() {
mutex.lock();
}
-Error _Mutex::try_lock() {
+Error Mutex::try_lock() {
return mutex.try_lock();
}
-void _Mutex::unlock() {
+void Mutex::unlock() {
mutex.unlock();
}
-void _Mutex::_bind_methods() {
- ClassDB::bind_method(D_METHOD("lock"), &_Mutex::lock);
- ClassDB::bind_method(D_METHOD("try_lock"), &_Mutex::try_lock);
- ClassDB::bind_method(D_METHOD("unlock"), &_Mutex::unlock);
+void Mutex::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("lock"), &Mutex::lock);
+ ClassDB::bind_method(D_METHOD("try_lock"), &Mutex::try_lock);
+ ClassDB::bind_method(D_METHOD("unlock"), &Mutex::unlock);
}
-////// _Thread //////
+////// Thread //////
-void _Thread::_start_func(void *ud) {
- Ref<_Thread> *tud = (Ref<_Thread> *)ud;
- Ref<_Thread> t = *tud;
+void Thread::_start_func(void *ud) {
+ Ref<Thread> *tud = (Ref<Thread> *)ud;
+ Ref<Thread> t = *tud;
memdelete(tud);
Callable::CallError ce;
const Variant *arg[1] = { &t->userdata };
@@ -1797,7 +1796,7 @@ void _Thread::_start_func(void *ud) {
}
}
- Thread::set_name(t->target_method);
+ ::Thread::set_name(t->target_method);
t->ret = t->target_instance->call(t->target_method, arg, argc, ce);
if (ce.error != Callable::CallError::CALL_OK) {
@@ -1823,7 +1822,7 @@ void _Thread::_start_func(void *ud) {
}
}
-Error _Thread::start(Object *p_instance, const StringName &p_method, const Variant &p_userdata, Priority p_priority) {
+Error Thread::start(Object *p_instance, const StringName &p_method, const Variant &p_userdata, Priority p_priority) {
ERR_FAIL_COND_V_MSG(active.is_set(), ERR_ALREADY_IN_USE, "Thread already started.");
ERR_FAIL_COND_V(!p_instance, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(p_method == StringName(), ERR_INVALID_PARAMETER);
@@ -1835,24 +1834,24 @@ Error _Thread::start(Object *p_instance, const StringName &p_method, const Varia
userdata = p_userdata;
active.set();
- Ref<_Thread> *ud = memnew(Ref<_Thread>(this));
+ Ref<Thread> *ud = memnew(Ref<Thread>(this));
- Thread::Settings s;
- s.priority = (Thread::Priority)p_priority;
+ ::Thread::Settings s;
+ s.priority = (::Thread::Priority)p_priority;
thread.start(_start_func, ud, s);
return OK;
}
-String _Thread::get_id() const {
+String Thread::get_id() const {
return itos(thread.get_id());
}
-bool _Thread::is_active() const {
+bool Thread::is_active() const {
return active.is_set();
}
-Variant _Thread::wait_to_finish() {
+Variant Thread::wait_to_finish() {
ERR_FAIL_COND_V_MSG(!active.is_set(), Variant(), "Thread must be active to wait for its completion.");
thread.wait_to_finish();
Variant r = ret;
@@ -1864,22 +1863,24 @@ Variant _Thread::wait_to_finish() {
return r;
}
-void _Thread::_bind_methods() {
- ClassDB::bind_method(D_METHOD("start", "instance", "method", "userdata", "priority"), &_Thread::start, DEFVAL(Variant()), DEFVAL(PRIORITY_NORMAL));
- ClassDB::bind_method(D_METHOD("get_id"), &_Thread::get_id);
- ClassDB::bind_method(D_METHOD("is_active"), &_Thread::is_active);
- ClassDB::bind_method(D_METHOD("wait_to_finish"), &_Thread::wait_to_finish);
+void Thread::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("start", "instance", "method", "userdata", "priority"), &Thread::start, DEFVAL(Variant()), DEFVAL(PRIORITY_NORMAL));
+ ClassDB::bind_method(D_METHOD("get_id"), &Thread::get_id);
+ ClassDB::bind_method(D_METHOD("is_active"), &Thread::is_active);
+ ClassDB::bind_method(D_METHOD("wait_to_finish"), &Thread::wait_to_finish);
BIND_ENUM_CONSTANT(PRIORITY_LOW);
BIND_ENUM_CONSTANT(PRIORITY_NORMAL);
BIND_ENUM_CONSTANT(PRIORITY_HIGH);
}
-////// _ClassDB //////
+namespace special {
+
+////// ClassDB //////
-PackedStringArray _ClassDB::get_class_list() const {
+PackedStringArray ClassDB::get_class_list() const {
List<StringName> classes;
- ClassDB::get_class_list(&classes);
+ ::ClassDB::get_class_list(&classes);
PackedStringArray ret;
ret.resize(classes.size());
@@ -1891,9 +1892,9 @@ PackedStringArray _ClassDB::get_class_list() const {
return ret;
}
-PackedStringArray _ClassDB::get_inheriters_from_class(const StringName &p_class) const {
+PackedStringArray ClassDB::get_inheriters_from_class(const StringName &p_class) const {
List<StringName> classes;
- ClassDB::get_inheriters_from_class(p_class, &classes);
+ ::ClassDB::get_inheriters_from_class(p_class, &classes);
PackedStringArray ret;
ret.resize(classes.size());
@@ -1905,24 +1906,24 @@ PackedStringArray _ClassDB::get_inheriters_from_class(const StringName &p_class)
return ret;
}
-StringName _ClassDB::get_parent_class(const StringName &p_class) const {
- return ClassDB::get_parent_class(p_class);
+StringName ClassDB::get_parent_class(const StringName &p_class) const {
+ return ::ClassDB::get_parent_class(p_class);
}
-bool _ClassDB::class_exists(const StringName &p_class) const {
- return ClassDB::class_exists(p_class);
+bool ClassDB::class_exists(const StringName &p_class) const {
+ return ::ClassDB::class_exists(p_class);
}
-bool _ClassDB::is_parent_class(const StringName &p_class, const StringName &p_inherits) const {
- return ClassDB::is_parent_class(p_class, p_inherits);
+bool ClassDB::is_parent_class(const StringName &p_class, const StringName &p_inherits) const {
+ return ::ClassDB::is_parent_class(p_class, p_inherits);
}
-bool _ClassDB::can_instantiate(const StringName &p_class) const {
- return ClassDB::can_instantiate(p_class);
+bool ClassDB::can_instantiate(const StringName &p_class) const {
+ return ::ClassDB::can_instantiate(p_class);
}
-Variant _ClassDB::instantiate(const StringName &p_class) const {
- Object *obj = ClassDB::instantiate(p_class);
+Variant ClassDB::instantiate(const StringName &p_class) const {
+ Object *obj = ::ClassDB::instantiate(p_class);
if (!obj) {
return Variant();
}
@@ -1935,22 +1936,22 @@ Variant _ClassDB::instantiate(const StringName &p_class) const {
}
}
-bool _ClassDB::has_signal(StringName p_class, StringName p_signal) const {
- return ClassDB::has_signal(p_class, p_signal);
+bool ClassDB::has_signal(StringName p_class, StringName p_signal) const {
+ return ::ClassDB::has_signal(p_class, p_signal);
}
-Dictionary _ClassDB::get_signal(StringName p_class, StringName p_signal) const {
+Dictionary ClassDB::get_signal(StringName p_class, StringName p_signal) const {
MethodInfo signal;
- if (ClassDB::get_signal(p_class, p_signal, &signal)) {
+ if (::ClassDB::get_signal(p_class, p_signal, &signal)) {
return signal.operator Dictionary();
} else {
return Dictionary();
}
}
-Array _ClassDB::get_signal_list(StringName p_class, bool p_no_inheritance) const {
+Array ClassDB::get_signal_list(StringName p_class, bool p_no_inheritance) const {
List<MethodInfo> signals;
- ClassDB::get_signal_list(p_class, &signals, p_no_inheritance);
+ ::ClassDB::get_signal_list(p_class, &signals, p_no_inheritance);
Array ret;
for (const MethodInfo &E : signals) {
@@ -1960,9 +1961,9 @@ Array _ClassDB::get_signal_list(StringName p_class, bool p_no_inheritance) const
return ret;
}
-Array _ClassDB::get_property_list(StringName p_class, bool p_no_inheritance) const {
+Array ClassDB::get_property_list(StringName p_class, bool p_no_inheritance) const {
List<PropertyInfo> plist;
- ClassDB::get_property_list(p_class, &plist, p_no_inheritance);
+ ::ClassDB::get_property_list(p_class, &plist, p_no_inheritance);
Array ret;
for (const PropertyInfo &E : plist) {
ret.push_back(E.operator Dictionary());
@@ -1971,16 +1972,16 @@ Array _ClassDB::get_property_list(StringName p_class, bool p_no_inheritance) con
return ret;
}
-Variant _ClassDB::get_property(Object *p_object, const StringName &p_property) const {
+Variant ClassDB::get_property(Object *p_object, const StringName &p_property) const {
Variant ret;
- ClassDB::get_property(p_object, p_property, ret);
+ ::ClassDB::get_property(p_object, p_property, ret);
return ret;
}
-Error _ClassDB::set_property(Object *p_object, const StringName &p_property, const Variant &p_value) const {
+Error ClassDB::set_property(Object *p_object, const StringName &p_property, const Variant &p_value) const {
Variant ret;
bool valid;
- if (!ClassDB::set_property(p_object, p_property, p_value, &valid)) {
+ if (!::ClassDB::set_property(p_object, p_property, p_value, &valid)) {
return ERR_UNAVAILABLE;
} else if (!valid) {
return ERR_INVALID_DATA;
@@ -1988,13 +1989,13 @@ Error _ClassDB::set_property(Object *p_object, const StringName &p_property, con
return OK;
}
-bool _ClassDB::has_method(StringName p_class, StringName p_method, bool p_no_inheritance) const {
- return ClassDB::has_method(p_class, p_method, p_no_inheritance);
+bool ClassDB::has_method(StringName p_class, StringName p_method, bool p_no_inheritance) const {
+ return ::ClassDB::has_method(p_class, p_method, p_no_inheritance);
}
-Array _ClassDB::get_method_list(StringName p_class, bool p_no_inheritance) const {
+Array ClassDB::get_method_list(StringName p_class, bool p_no_inheritance) const {
List<MethodInfo> methods;
- ClassDB::get_method_list(p_class, &methods, p_no_inheritance);
+ ::ClassDB::get_method_list(p_class, &methods, p_no_inheritance);
Array ret;
for (const MethodInfo &E : methods) {
@@ -2010,9 +2011,9 @@ Array _ClassDB::get_method_list(StringName p_class, bool p_no_inheritance) const
return ret;
}
-PackedStringArray _ClassDB::get_integer_constant_list(const StringName &p_class, bool p_no_inheritance) const {
+PackedStringArray ClassDB::get_integer_constant_list(const StringName &p_class, bool p_no_inheritance) const {
List<String> constants;
- ClassDB::get_integer_constant_list(p_class, &constants, p_no_inheritance);
+ ::ClassDB::get_integer_constant_list(p_class, &constants, p_no_inheritance);
PackedStringArray ret;
ret.resize(constants.size());
@@ -2024,204 +2025,206 @@ PackedStringArray _ClassDB::get_integer_constant_list(const StringName &p_class,
return ret;
}
-bool _ClassDB::has_integer_constant(const StringName &p_class, const StringName &p_name) const {
+bool ClassDB::has_integer_constant(const StringName &p_class, const StringName &p_name) const {
bool success;
- ClassDB::get_integer_constant(p_class, p_name, &success);
+ ::ClassDB::get_integer_constant(p_class, p_name, &success);
return success;
}
-int _ClassDB::get_integer_constant(const StringName &p_class, const StringName &p_name) const {
+int ClassDB::get_integer_constant(const StringName &p_class, const StringName &p_name) const {
bool found;
- int c = ClassDB::get_integer_constant(p_class, p_name, &found);
+ int c = ::ClassDB::get_integer_constant(p_class, p_name, &found);
ERR_FAIL_COND_V(!found, 0);
return c;
}
-StringName _ClassDB::get_category(const StringName &p_node) const {
- return ClassDB::get_category(p_node);
+StringName ClassDB::get_category(const StringName &p_node) const {
+ return ::ClassDB::get_category(p_node);
}
-bool _ClassDB::is_class_enabled(StringName p_class) const {
- return ClassDB::is_class_enabled(p_class);
+bool ClassDB::is_class_enabled(StringName p_class) const {
+ return ::ClassDB::is_class_enabled(p_class);
}
-void _ClassDB::_bind_methods() {
- ClassDB::bind_method(D_METHOD("get_class_list"), &_ClassDB::get_class_list);
- ClassDB::bind_method(D_METHOD("get_inheriters_from_class", "class"), &_ClassDB::get_inheriters_from_class);
- ClassDB::bind_method(D_METHOD("get_parent_class", "class"), &_ClassDB::get_parent_class);
- ClassDB::bind_method(D_METHOD("class_exists", "class"), &_ClassDB::class_exists);
- ClassDB::bind_method(D_METHOD("is_parent_class", "class", "inherits"), &_ClassDB::is_parent_class);
- ClassDB::bind_method(D_METHOD("can_instantiate", "class"), &_ClassDB::can_instantiate);
- ClassDB::bind_method(D_METHOD("instantiate", "class"), &_ClassDB::instantiate);
+void ClassDB::_bind_methods() {
+ ::ClassDB::bind_method(D_METHOD("get_class_list"), &ClassDB::get_class_list);
+ ::ClassDB::bind_method(D_METHOD("get_inheriters_from_class", "class"), &ClassDB::get_inheriters_from_class);
+ ::ClassDB::bind_method(D_METHOD("get_parent_class", "class"), &ClassDB::get_parent_class);
+ ::ClassDB::bind_method(D_METHOD("class_exists", "class"), &ClassDB::class_exists);
+ ::ClassDB::bind_method(D_METHOD("is_parent_class", "class", "inherits"), &ClassDB::is_parent_class);
+ ::ClassDB::bind_method(D_METHOD("can_instantiate", "class"), &ClassDB::can_instantiate);
+ ::ClassDB::bind_method(D_METHOD("instantiate", "class"), &ClassDB::instantiate);
- ClassDB::bind_method(D_METHOD("class_has_signal", "class", "signal"), &_ClassDB::has_signal);
- ClassDB::bind_method(D_METHOD("class_get_signal", "class", "signal"), &_ClassDB::get_signal);
- ClassDB::bind_method(D_METHOD("class_get_signal_list", "class", "no_inheritance"), &_ClassDB::get_signal_list, DEFVAL(false));
+ ::ClassDB::bind_method(D_METHOD("class_has_signal", "class", "signal"), &ClassDB::has_signal);
+ ::ClassDB::bind_method(D_METHOD("class_get_signal", "class", "signal"), &ClassDB::get_signal);
+ ::ClassDB::bind_method(D_METHOD("class_get_signal_list", "class", "no_inheritance"), &ClassDB::get_signal_list, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("class_get_property_list", "class", "no_inheritance"), &_ClassDB::get_property_list, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("class_get_property", "object", "property"), &_ClassDB::get_property);
- ClassDB::bind_method(D_METHOD("class_set_property", "object", "property", "value"), &_ClassDB::set_property);
+ ::ClassDB::bind_method(D_METHOD("class_get_property_list", "class", "no_inheritance"), &ClassDB::get_property_list, DEFVAL(false));
+ ::ClassDB::bind_method(D_METHOD("class_get_property", "object", "property"), &ClassDB::get_property);
+ ::ClassDB::bind_method(D_METHOD("class_set_property", "object", "property", "value"), &ClassDB::set_property);
- ClassDB::bind_method(D_METHOD("class_has_method", "class", "method", "no_inheritance"), &_ClassDB::has_method, DEFVAL(false));
+ ::ClassDB::bind_method(D_METHOD("class_has_method", "class", "method", "no_inheritance"), &ClassDB::has_method, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("class_get_method_list", "class", "no_inheritance"), &_ClassDB::get_method_list, DEFVAL(false));
+ ::ClassDB::bind_method(D_METHOD("class_get_method_list", "class", "no_inheritance"), &ClassDB::get_method_list, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("class_get_integer_constant_list", "class", "no_inheritance"), &_ClassDB::get_integer_constant_list, DEFVAL(false));
+ ::ClassDB::bind_method(D_METHOD("class_get_integer_constant_list", "class", "no_inheritance"), &ClassDB::get_integer_constant_list, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("class_has_integer_constant", "class", "name"), &_ClassDB::has_integer_constant);
- ClassDB::bind_method(D_METHOD("class_get_integer_constant", "class", "name"), &_ClassDB::get_integer_constant);
+ ::ClassDB::bind_method(D_METHOD("class_has_integer_constant", "class", "name"), &ClassDB::has_integer_constant);
+ ::ClassDB::bind_method(D_METHOD("class_get_integer_constant", "class", "name"), &ClassDB::get_integer_constant);
- ClassDB::bind_method(D_METHOD("class_get_category", "class"), &_ClassDB::get_category);
- ClassDB::bind_method(D_METHOD("is_class_enabled", "class"), &_ClassDB::is_class_enabled);
+ ::ClassDB::bind_method(D_METHOD("class_get_category", "class"), &ClassDB::get_category);
+ ::ClassDB::bind_method(D_METHOD("is_class_enabled", "class"), &ClassDB::is_class_enabled);
}
-////// _Engine //////
+} // namespace special
-void _Engine::set_physics_ticks_per_second(int p_ips) {
- Engine::get_singleton()->set_physics_ticks_per_second(p_ips);
+////// Engine //////
+
+void Engine::set_physics_ticks_per_second(int p_ips) {
+ ::Engine::get_singleton()->set_physics_ticks_per_second(p_ips);
}
-int _Engine::get_physics_ticks_per_second() const {
- return Engine::get_singleton()->get_physics_ticks_per_second();
+int Engine::get_physics_ticks_per_second() const {
+ return ::Engine::get_singleton()->get_physics_ticks_per_second();
}
-void _Engine::set_physics_jitter_fix(double p_threshold) {
- Engine::get_singleton()->set_physics_jitter_fix(p_threshold);
+void Engine::set_physics_jitter_fix(double p_threshold) {
+ ::Engine::get_singleton()->set_physics_jitter_fix(p_threshold);
}
-double _Engine::get_physics_jitter_fix() const {
- return Engine::get_singleton()->get_physics_jitter_fix();
+double Engine::get_physics_jitter_fix() const {
+ return ::Engine::get_singleton()->get_physics_jitter_fix();
}
-double _Engine::get_physics_interpolation_fraction() const {
- return Engine::get_singleton()->get_physics_interpolation_fraction();
+double Engine::get_physics_interpolation_fraction() const {
+ return ::Engine::get_singleton()->get_physics_interpolation_fraction();
}
-void _Engine::set_target_fps(int p_fps) {
- Engine::get_singleton()->set_target_fps(p_fps);
+void Engine::set_target_fps(int p_fps) {
+ ::Engine::get_singleton()->set_target_fps(p_fps);
}
-int _Engine::get_target_fps() const {
- return Engine::get_singleton()->get_target_fps();
+int Engine::get_target_fps() const {
+ return ::Engine::get_singleton()->get_target_fps();
}
-double _Engine::get_frames_per_second() const {
- return Engine::get_singleton()->get_frames_per_second();
+double Engine::get_frames_per_second() const {
+ return ::Engine::get_singleton()->get_frames_per_second();
}
-uint64_t _Engine::get_physics_frames() const {
- return Engine::get_singleton()->get_physics_frames();
+uint64_t Engine::get_physics_frames() const {
+ return ::Engine::get_singleton()->get_physics_frames();
}
-uint64_t _Engine::get_process_frames() const {
- return Engine::get_singleton()->get_process_frames();
+uint64_t Engine::get_process_frames() const {
+ return ::Engine::get_singleton()->get_process_frames();
}
-void _Engine::set_time_scale(double p_scale) {
- Engine::get_singleton()->set_time_scale(p_scale);
+void Engine::set_time_scale(double p_scale) {
+ ::Engine::get_singleton()->set_time_scale(p_scale);
}
-double _Engine::get_time_scale() {
- return Engine::get_singleton()->get_time_scale();
+double Engine::get_time_scale() {
+ return ::Engine::get_singleton()->get_time_scale();
}
-int _Engine::get_frames_drawn() {
- return Engine::get_singleton()->get_frames_drawn();
+int Engine::get_frames_drawn() {
+ return ::Engine::get_singleton()->get_frames_drawn();
}
-MainLoop *_Engine::get_main_loop() const {
- //needs to remain in OS, since it's actually OS that interacts with it, but it's better exposed here
- return OS::get_singleton()->get_main_loop();
+MainLoop *Engine::get_main_loop() const {
+ // Needs to remain in OS, since it's actually OS that interacts with it, but it's better exposed here
+ return ::OS::get_singleton()->get_main_loop();
}
-Dictionary _Engine::get_version_info() const {
- return Engine::get_singleton()->get_version_info();
+Dictionary Engine::get_version_info() const {
+ return ::Engine::get_singleton()->get_version_info();
}
-Dictionary _Engine::get_author_info() const {
- return Engine::get_singleton()->get_author_info();
+Dictionary Engine::get_author_info() const {
+ return ::Engine::get_singleton()->get_author_info();
}
-Array _Engine::get_copyright_info() const {
- return Engine::get_singleton()->get_copyright_info();
+Array Engine::get_copyright_info() const {
+ return ::Engine::get_singleton()->get_copyright_info();
}
-Dictionary _Engine::get_donor_info() const {
- return Engine::get_singleton()->get_donor_info();
+Dictionary Engine::get_donor_info() const {
+ return ::Engine::get_singleton()->get_donor_info();
}
-Dictionary _Engine::get_license_info() const {
- return Engine::get_singleton()->get_license_info();
+Dictionary Engine::get_license_info() const {
+ return ::Engine::get_singleton()->get_license_info();
}
-String _Engine::get_license_text() const {
- return Engine::get_singleton()->get_license_text();
+String Engine::get_license_text() const {
+ return ::Engine::get_singleton()->get_license_text();
}
-bool _Engine::is_in_physics_frame() const {
- return Engine::get_singleton()->is_in_physics_frame();
+bool Engine::is_in_physics_frame() const {
+ return ::Engine::get_singleton()->is_in_physics_frame();
}
-bool _Engine::has_singleton(const String &p_name) const {
- return Engine::get_singleton()->has_singleton(p_name);
+bool Engine::has_singleton(const String &p_name) const {
+ return ::Engine::get_singleton()->has_singleton(p_name);
}
-Object *_Engine::get_singleton_object(const String &p_name) const {
- return Engine::get_singleton()->get_singleton_object(p_name);
+Object *Engine::get_singleton_object(const String &p_name) const {
+ return ::Engine::get_singleton()->get_singleton_object(p_name);
}
-void _Engine::set_editor_hint(bool p_enabled) {
- Engine::get_singleton()->set_editor_hint(p_enabled);
+void Engine::set_editor_hint(bool p_enabled) {
+ ::Engine::get_singleton()->set_editor_hint(p_enabled);
}
-bool _Engine::is_editor_hint() const {
- return Engine::get_singleton()->is_editor_hint();
+bool Engine::is_editor_hint() const {
+ return ::Engine::get_singleton()->is_editor_hint();
}
-void _Engine::set_print_error_messages(bool p_enabled) {
- Engine::get_singleton()->set_print_error_messages(p_enabled);
+void Engine::set_print_error_messages(bool p_enabled) {
+ ::Engine::get_singleton()->set_print_error_messages(p_enabled);
}
-bool _Engine::is_printing_error_messages() const {
- return Engine::get_singleton()->is_printing_error_messages();
+bool Engine::is_printing_error_messages() const {
+ return ::Engine::get_singleton()->is_printing_error_messages();
}
-void _Engine::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_physics_ticks_per_second", "physics_ticks_per_second"), &_Engine::set_physics_ticks_per_second);
- ClassDB::bind_method(D_METHOD("get_physics_ticks_per_second"), &_Engine::get_physics_ticks_per_second);
- ClassDB::bind_method(D_METHOD("set_physics_jitter_fix", "physics_jitter_fix"), &_Engine::set_physics_jitter_fix);
- ClassDB::bind_method(D_METHOD("get_physics_jitter_fix"), &_Engine::get_physics_jitter_fix);
- ClassDB::bind_method(D_METHOD("get_physics_interpolation_fraction"), &_Engine::get_physics_interpolation_fraction);
- ClassDB::bind_method(D_METHOD("set_target_fps", "target_fps"), &_Engine::set_target_fps);
- ClassDB::bind_method(D_METHOD("get_target_fps"), &_Engine::get_target_fps);
+void Engine::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_physics_ticks_per_second", "physics_ticks_per_second"), &Engine::set_physics_ticks_per_second);
+ ClassDB::bind_method(D_METHOD("get_physics_ticks_per_second"), &Engine::get_physics_ticks_per_second);
+ ClassDB::bind_method(D_METHOD("set_physics_jitter_fix", "physics_jitter_fix"), &Engine::set_physics_jitter_fix);
+ ClassDB::bind_method(D_METHOD("get_physics_jitter_fix"), &Engine::get_physics_jitter_fix);
+ ClassDB::bind_method(D_METHOD("get_physics_interpolation_fraction"), &Engine::get_physics_interpolation_fraction);
+ ClassDB::bind_method(D_METHOD("set_target_fps", "target_fps"), &Engine::set_target_fps);
+ ClassDB::bind_method(D_METHOD("get_target_fps"), &Engine::get_target_fps);
- ClassDB::bind_method(D_METHOD("set_time_scale", "time_scale"), &_Engine::set_time_scale);
- ClassDB::bind_method(D_METHOD("get_time_scale"), &_Engine::get_time_scale);
+ ClassDB::bind_method(D_METHOD("set_time_scale", "time_scale"), &Engine::set_time_scale);
+ ClassDB::bind_method(D_METHOD("get_time_scale"), &Engine::get_time_scale);
- ClassDB::bind_method(D_METHOD("get_frames_drawn"), &_Engine::get_frames_drawn);
- ClassDB::bind_method(D_METHOD("get_frames_per_second"), &_Engine::get_frames_per_second);
- ClassDB::bind_method(D_METHOD("get_physics_frames"), &_Engine::get_physics_frames);
- ClassDB::bind_method(D_METHOD("get_process_frames"), &_Engine::get_process_frames);
+ ClassDB::bind_method(D_METHOD("get_frames_drawn"), &Engine::get_frames_drawn);
+ ClassDB::bind_method(D_METHOD("get_frames_per_second"), &Engine::get_frames_per_second);
+ ClassDB::bind_method(D_METHOD("get_physics_frames"), &Engine::get_physics_frames);
+ ClassDB::bind_method(D_METHOD("get_process_frames"), &Engine::get_process_frames);
- ClassDB::bind_method(D_METHOD("get_main_loop"), &_Engine::get_main_loop);
+ ClassDB::bind_method(D_METHOD("get_main_loop"), &Engine::get_main_loop);
- ClassDB::bind_method(D_METHOD("get_version_info"), &_Engine::get_version_info);
- ClassDB::bind_method(D_METHOD("get_author_info"), &_Engine::get_author_info);
- ClassDB::bind_method(D_METHOD("get_copyright_info"), &_Engine::get_copyright_info);
- ClassDB::bind_method(D_METHOD("get_donor_info"), &_Engine::get_donor_info);
- ClassDB::bind_method(D_METHOD("get_license_info"), &_Engine::get_license_info);
- ClassDB::bind_method(D_METHOD("get_license_text"), &_Engine::get_license_text);
+ ClassDB::bind_method(D_METHOD("get_version_info"), &Engine::get_version_info);
+ ClassDB::bind_method(D_METHOD("get_author_info"), &Engine::get_author_info);
+ ClassDB::bind_method(D_METHOD("get_copyright_info"), &Engine::get_copyright_info);
+ ClassDB::bind_method(D_METHOD("get_donor_info"), &Engine::get_donor_info);
+ ClassDB::bind_method(D_METHOD("get_license_info"), &Engine::get_license_info);
+ ClassDB::bind_method(D_METHOD("get_license_text"), &Engine::get_license_text);
- ClassDB::bind_method(D_METHOD("is_in_physics_frame"), &_Engine::is_in_physics_frame);
+ ClassDB::bind_method(D_METHOD("is_in_physics_frame"), &Engine::is_in_physics_frame);
- ClassDB::bind_method(D_METHOD("has_singleton", "name"), &_Engine::has_singleton);
- ClassDB::bind_method(D_METHOD("get_singleton", "name"), &_Engine::get_singleton_object);
+ ClassDB::bind_method(D_METHOD("has_singleton", "name"), &Engine::has_singleton);
+ ClassDB::bind_method(D_METHOD("get_singleton", "name"), &Engine::get_singleton_object);
- ClassDB::bind_method(D_METHOD("set_editor_hint", "enabled"), &_Engine::set_editor_hint);
- ClassDB::bind_method(D_METHOD("is_editor_hint"), &_Engine::is_editor_hint);
+ ClassDB::bind_method(D_METHOD("set_editor_hint", "enabled"), &Engine::set_editor_hint);
+ ClassDB::bind_method(D_METHOD("is_editor_hint"), &Engine::is_editor_hint);
- ClassDB::bind_method(D_METHOD("set_print_error_messages", "enabled"), &_Engine::set_print_error_messages);
- ClassDB::bind_method(D_METHOD("is_printing_error_messages"), &_Engine::is_printing_error_messages);
+ ClassDB::bind_method(D_METHOD("set_print_error_messages", "enabled"), &Engine::set_print_error_messages);
+ ClassDB::bind_method(D_METHOD("is_printing_error_messages"), &Engine::is_printing_error_messages);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_hint"), "set_editor_hint", "is_editor_hint");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "print_error_messages"), "set_print_error_messages", "is_printing_error_messages");
@@ -2231,92 +2234,74 @@ void _Engine::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "physics_jitter_fix"), "set_physics_jitter_fix", "get_physics_jitter_fix");
}
-_Engine *_Engine::singleton = nullptr;
-
-////// _EngineDebugger //////
-
-void _EngineDebugger::_bind_methods() {
- ClassDB::bind_method(D_METHOD("is_active"), &_EngineDebugger::is_active);
-
- ClassDB::bind_method(D_METHOD("register_profiler", "name", "toggle", "add", "tick"), &_EngineDebugger::register_profiler);
- ClassDB::bind_method(D_METHOD("unregister_profiler", "name"), &_EngineDebugger::unregister_profiler);
- ClassDB::bind_method(D_METHOD("is_profiling", "name"), &_EngineDebugger::is_profiling);
- ClassDB::bind_method(D_METHOD("has_profiler", "name"), &_EngineDebugger::has_profiler);
-
- ClassDB::bind_method(D_METHOD("profiler_add_frame_data", "name", "data"), &_EngineDebugger::profiler_add_frame_data);
- ClassDB::bind_method(D_METHOD("profiler_enable", "name", "enable", "arguments"), &_EngineDebugger::profiler_enable, DEFVAL(Array()));
+Engine *Engine::singleton = nullptr;
- ClassDB::bind_method(D_METHOD("register_message_capture", "name", "callable"), &_EngineDebugger::register_message_capture);
- ClassDB::bind_method(D_METHOD("unregister_message_capture", "name"), &_EngineDebugger::unregister_message_capture);
- ClassDB::bind_method(D_METHOD("has_capture", "name"), &_EngineDebugger::has_capture);
+////// EngineDebugger //////
- ClassDB::bind_method(D_METHOD("send_message", "message", "data"), &_EngineDebugger::send_message);
+bool EngineDebugger::is_active() {
+ return ::EngineDebugger::is_active();
}
-bool _EngineDebugger::is_active() {
- return EngineDebugger::is_active();
-}
-
-void _EngineDebugger::register_profiler(const StringName &p_name, const Callable &p_toggle, const Callable &p_add, const Callable &p_tick) {
+void EngineDebugger::register_profiler(const StringName &p_name, const Callable &p_toggle, const Callable &p_add, const Callable &p_tick) {
ERR_FAIL_COND_MSG(profilers.has(p_name) || has_profiler(p_name), "Profiler already registered: " + p_name);
profilers.insert(p_name, ProfilerCallable(p_toggle, p_add, p_tick));
ProfilerCallable &p = profilers[p_name];
- EngineDebugger::Profiler profiler(
+ ::EngineDebugger::Profiler profiler(
&p,
- &_EngineDebugger::call_toggle,
- &_EngineDebugger::call_add,
- &_EngineDebugger::call_tick);
- EngineDebugger::register_profiler(p_name, profiler);
+ &EngineDebugger::call_toggle,
+ &EngineDebugger::call_add,
+ &EngineDebugger::call_tick);
+ ::EngineDebugger::register_profiler(p_name, profiler);
}
-void _EngineDebugger::unregister_profiler(const StringName &p_name) {
+void EngineDebugger::unregister_profiler(const StringName &p_name) {
ERR_FAIL_COND_MSG(!profilers.has(p_name), "Profiler not registered: " + p_name);
- EngineDebugger::unregister_profiler(p_name);
+ ::EngineDebugger::unregister_profiler(p_name);
profilers.erase(p_name);
}
-bool _EngineDebugger::_EngineDebugger::is_profiling(const StringName &p_name) {
- return EngineDebugger::is_profiling(p_name);
+bool EngineDebugger::is_profiling(const StringName &p_name) {
+ return ::EngineDebugger::is_profiling(p_name);
}
-bool _EngineDebugger::has_profiler(const StringName &p_name) {
- return EngineDebugger::has_profiler(p_name);
+bool EngineDebugger::has_profiler(const StringName &p_name) {
+ return ::EngineDebugger::has_profiler(p_name);
}
-void _EngineDebugger::profiler_add_frame_data(const StringName &p_name, const Array &p_data) {
- EngineDebugger::profiler_add_frame_data(p_name, p_data);
+void EngineDebugger::profiler_add_frame_data(const StringName &p_name, const Array &p_data) {
+ ::EngineDebugger::profiler_add_frame_data(p_name, p_data);
}
-void _EngineDebugger::profiler_enable(const StringName &p_name, bool p_enabled, const Array &p_opts) {
- if (EngineDebugger::get_singleton()) {
- EngineDebugger::get_singleton()->profiler_enable(p_name, p_enabled, p_opts);
+void EngineDebugger::profiler_enable(const StringName &p_name, bool p_enabled, const Array &p_opts) {
+ if (::EngineDebugger::get_singleton()) {
+ ::EngineDebugger::get_singleton()->profiler_enable(p_name, p_enabled, p_opts);
}
}
-void _EngineDebugger::register_message_capture(const StringName &p_name, const Callable &p_callable) {
+void EngineDebugger::register_message_capture(const StringName &p_name, const Callable &p_callable) {
ERR_FAIL_COND_MSG(captures.has(p_name) || has_capture(p_name), "Capture already registered: " + p_name);
captures.insert(p_name, p_callable);
Callable &c = captures[p_name];
- EngineDebugger::Capture capture(&c, &_EngineDebugger::call_capture);
- EngineDebugger::register_message_capture(p_name, capture);
+ ::EngineDebugger::Capture capture(&c, &EngineDebugger::call_capture);
+ ::EngineDebugger::register_message_capture(p_name, capture);
}
-void _EngineDebugger::unregister_message_capture(const StringName &p_name) {
+void EngineDebugger::unregister_message_capture(const StringName &p_name) {
ERR_FAIL_COND_MSG(!captures.has(p_name), "Capture not registered: " + p_name);
- EngineDebugger::unregister_message_capture(p_name);
+ ::EngineDebugger::unregister_message_capture(p_name);
captures.erase(p_name);
}
-bool _EngineDebugger::has_capture(const StringName &p_name) {
- return EngineDebugger::has_capture(p_name);
+bool EngineDebugger::has_capture(const StringName &p_name) {
+ return ::EngineDebugger::has_capture(p_name);
}
-void _EngineDebugger::send_message(const String &p_msg, const Array &p_data) {
- ERR_FAIL_COND_MSG(!EngineDebugger::is_active(), "Can't send message. No active debugger");
- EngineDebugger::get_singleton()->send_message(p_msg, p_data);
+void EngineDebugger::send_message(const String &p_msg, const Array &p_data) {
+ ERR_FAIL_COND_MSG(!::EngineDebugger::is_active(), "Can't send message. No active debugger");
+ ::EngineDebugger::get_singleton()->send_message(p_msg, p_data);
}
-void _EngineDebugger::call_toggle(void *p_user, bool p_enable, const Array &p_opts) {
+void EngineDebugger::call_toggle(void *p_user, bool p_enable, const Array &p_opts) {
Callable &toggle = ((ProfilerCallable *)p_user)->callable_toggle;
if (toggle.is_null()) {
return;
@@ -2329,7 +2314,7 @@ void _EngineDebugger::call_toggle(void *p_user, bool p_enable, const Array &p_op
ERR_FAIL_COND_MSG(err.error != Callable::CallError::CALL_OK, "Error calling 'toggle' to callable: " + Variant::get_callable_error_text(toggle, args, 2, err));
}
-void _EngineDebugger::call_add(void *p_user, const Array &p_data) {
+void EngineDebugger::call_add(void *p_user, const Array &p_data) {
Callable &add = ((ProfilerCallable *)p_user)->callable_add;
if (add.is_null()) {
return;
@@ -2342,7 +2327,7 @@ void _EngineDebugger::call_add(void *p_user, const Array &p_data) {
ERR_FAIL_COND_MSG(err.error != Callable::CallError::CALL_OK, "Error calling 'add' to callable: " + Variant::get_callable_error_text(add, args, 1, err));
}
-void _EngineDebugger::call_tick(void *p_user, double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
+void EngineDebugger::call_tick(void *p_user, double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
Callable &tick = ((ProfilerCallable *)p_user)->callable_tick;
if (tick.is_null()) {
return;
@@ -2355,7 +2340,7 @@ void _EngineDebugger::call_tick(void *p_user, double p_frame_time, double p_idle
ERR_FAIL_COND_MSG(err.error != Callable::CallError::CALL_OK, "Error calling 'tick' to callable: " + Variant::get_callable_error_text(tick, args, 4, err));
}
-Error _EngineDebugger::call_capture(void *p_user, const String &p_cmd, const Array &p_data, bool &r_captured) {
+Error EngineDebugger::call_capture(void *p_user, const String &p_cmd, const Array &p_data, bool &r_captured) {
Callable &capture = *(Callable *)p_user;
if (capture.is_null()) {
return FAILED;
@@ -2371,15 +2356,35 @@ Error _EngineDebugger::call_capture(void *p_user, const String &p_cmd, const Arr
return OK;
}
-_EngineDebugger::~_EngineDebugger() {
+EngineDebugger::~EngineDebugger() {
for (Map<StringName, Callable>::Element *E = captures.front(); E; E = E->next()) {
- EngineDebugger::unregister_message_capture(E->key());
+ ::EngineDebugger::unregister_message_capture(E->key());
}
captures.clear();
for (Map<StringName, ProfilerCallable>::Element *E = profilers.front(); E; E = E->next()) {
- EngineDebugger::unregister_profiler(E->key());
+ ::EngineDebugger::unregister_profiler(E->key());
}
profilers.clear();
}
-_EngineDebugger *_EngineDebugger::singleton = nullptr;
+EngineDebugger *EngineDebugger::singleton = nullptr;
+
+void EngineDebugger::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("is_active"), &EngineDebugger::is_active);
+
+ ClassDB::bind_method(D_METHOD("register_profiler", "name", "toggle", "add", "tick"), &EngineDebugger::register_profiler);
+ ClassDB::bind_method(D_METHOD("unregister_profiler", "name"), &EngineDebugger::unregister_profiler);
+ ClassDB::bind_method(D_METHOD("is_profiling", "name"), &EngineDebugger::is_profiling);
+ ClassDB::bind_method(D_METHOD("has_profiler", "name"), &EngineDebugger::has_profiler);
+
+ ClassDB::bind_method(D_METHOD("profiler_add_frame_data", "name", "data"), &EngineDebugger::profiler_add_frame_data);
+ ClassDB::bind_method(D_METHOD("profiler_enable", "name", "enable", "arguments"), &EngineDebugger::profiler_enable, DEFVAL(Array()));
+
+ ClassDB::bind_method(D_METHOD("register_message_capture", "name", "callable"), &EngineDebugger::register_message_capture);
+ ClassDB::bind_method(D_METHOD("unregister_message_capture", "name"), &EngineDebugger::unregister_message_capture);
+ ClassDB::bind_method(D_METHOD("has_capture", "name"), &EngineDebugger::has_capture);
+
+ ClassDB::bind_method(D_METHOD("send_message", "message", "data"), &EngineDebugger::send_message);
+}
+
+} // namespace core_bind
diff --git a/core/core_bind.h b/core/core_bind.h
index 9060aff340..1dbe49f418 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -42,12 +42,16 @@
#include "core/os/thread.h"
#include "core/templates/safe_refcount.h"
-class _ResourceLoader : public Object {
- GDCLASS(_ResourceLoader, Object);
+class MainLoop;
+
+namespace core_bind {
+
+class ResourceLoader : public Object {
+ GDCLASS(ResourceLoader, Object);
protected:
static void _bind_methods();
- static _ResourceLoader *singleton;
+ static ResourceLoader *singleton;
public:
enum ThreadLoadStatus {
@@ -63,7 +67,7 @@ public:
CACHE_MODE_REPLACE, // Resource and subresource use path cache, but replace existing loaded resources when available with information from disk.
};
- static _ResourceLoader *get_singleton() { return singleton; }
+ static ResourceLoader *get_singleton() { return singleton; }
Error load_threaded_request(const String &p_path, const String &p_type_hint = "", bool p_use_sub_threads = false);
ThreadLoadStatus load_threaded_get_status(const String &p_path, Array r_progress = Array());
@@ -77,18 +81,15 @@ public:
bool exists(const String &p_path, const String &p_type_hint = "");
ResourceUID::ID get_resource_uid(const String &p_path);
- _ResourceLoader() { singleton = this; }
+ ResourceLoader() { singleton = this; }
};
-VARIANT_ENUM_CAST(_ResourceLoader::ThreadLoadStatus);
-VARIANT_ENUM_CAST(_ResourceLoader::CacheMode);
-
-class _ResourceSaver : public Object {
- GDCLASS(_ResourceSaver, Object);
+class ResourceSaver : public Object {
+ GDCLASS(ResourceSaver, Object);
protected:
static void _bind_methods();
- static _ResourceSaver *singleton;
+ static ResourceSaver *singleton;
public:
enum SaverFlags {
@@ -101,24 +102,20 @@ public:
FLAG_REPLACE_SUBRESOURCE_PATHS = 64,
};
- static _ResourceSaver *get_singleton() { return singleton; }
+ static ResourceSaver *get_singleton() { return singleton; }
Error save(const String &p_path, const RES &p_resource, SaverFlags p_flags);
Vector<String> get_recognized_extensions(const RES &p_resource);
- _ResourceSaver() { singleton = this; }
+ ResourceSaver() { singleton = this; }
};
-VARIANT_ENUM_CAST(_ResourceSaver::SaverFlags);
-
-class MainLoop;
-
-class _OS : public Object {
- GDCLASS(_OS, Object);
+class OS : public Object {
+ GDCLASS(OS, Object);
protected:
static void _bind_methods();
- static _OS *singleton;
+ static OS *singleton;
public:
enum VideoDriver {
@@ -229,10 +226,9 @@ public:
SYSTEM_DIR_RINGTONES,
};
- String get_system_dir(SystemDir p_dir) const;
+ String get_system_dir(SystemDir p_dir, bool p_shared_storage = true) const;
String get_user_data_dir() const;
- String get_external_data_dir() const;
String get_config_dir() const;
String get_data_dir() const;
String get_cache_dir() const;
@@ -246,26 +242,21 @@ public:
bool request_permissions();
Vector<String> get_granted_permissions() const;
- static _OS *get_singleton() { return singleton; }
+ static OS *get_singleton() { return singleton; }
- _OS() { singleton = this; }
+ OS() { singleton = this; }
};
-VARIANT_ENUM_CAST(_OS::VideoDriver);
-VARIANT_ENUM_CAST(_OS::Weekday);
-VARIANT_ENUM_CAST(_OS::Month);
-VARIANT_ENUM_CAST(_OS::SystemDir);
+class Geometry2D : public Object {
+ GDCLASS(Geometry2D, Object);
-class _Geometry2D : public Object {
- GDCLASS(_Geometry2D, Object);
-
- static _Geometry2D *singleton;
+ static Geometry2D *singleton;
protected:
static void _bind_methods();
public:
- static _Geometry2D *get_singleton();
+ static Geometry2D *get_singleton();
Variant segment_intersects_segment(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b);
Variant line_intersects_line(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b);
Vector<Vector2> get_closest_points_between_segments(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2);
@@ -316,23 +307,19 @@ public:
Dictionary make_atlas(const Vector<Size2> &p_rects);
- _Geometry2D() { singleton = this; }
+ Geometry2D() { singleton = this; }
};
-VARIANT_ENUM_CAST(_Geometry2D::PolyBooleanOperation);
-VARIANT_ENUM_CAST(_Geometry2D::PolyJoinType);
-VARIANT_ENUM_CAST(_Geometry2D::PolyEndType);
-
-class _Geometry3D : public Object {
- GDCLASS(_Geometry3D, Object);
+class Geometry3D : public Object {
+ GDCLASS(Geometry3D, Object);
- static _Geometry3D *singleton;
+ static Geometry3D *singleton;
protected:
static void _bind_methods();
public:
- static _Geometry3D *get_singleton();
+ static Geometry3D *get_singleton();
Vector<Plane> build_box_planes(const Vector3 &p_extents);
Vector<Plane> build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis = Vector3::AXIS_Z);
Vector<Plane> build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis = Vector3::AXIS_Z);
@@ -348,11 +335,11 @@ public:
Vector<Vector3> clip_polygon(const Vector<Vector3> &p_points, const Plane &p_plane);
- _Geometry3D() { singleton = this; }
+ Geometry3D() { singleton = this; }
};
-class _File : public RefCounted {
- GDCLASS(_File, RefCounted);
+class File : public RefCounted {
+ GDCLASS(File, RefCounted);
FileAccess *f = nullptr;
bool big_endian = false;
@@ -446,15 +433,12 @@ public:
uint64_t get_modified_time(const String &p_file) const;
- _File() {}
- virtual ~_File();
+ File() {}
+ virtual ~File();
};
-VARIANT_ENUM_CAST(_File::ModeFlags);
-VARIANT_ENUM_CAST(_File::CompressionMode);
-
-class _Directory : public RefCounted {
- GDCLASS(_Directory, RefCounted);
+class Directory : public RefCounted {
+ GDCLASS(Directory, RefCounted);
DirAccess *d;
bool dir_open = false;
@@ -491,24 +475,24 @@ public:
Error rename(String p_from, String p_to);
Error remove(String p_name);
- _Directory();
- virtual ~_Directory();
+ Directory();
+ virtual ~Directory();
private:
bool _list_skip_navigational = false;
bool _list_skip_hidden = false;
};
-class _Marshalls : public Object {
- GDCLASS(_Marshalls, Object);
+class Marshalls : public Object {
+ GDCLASS(Marshalls, Object);
- static _Marshalls *singleton;
+ static Marshalls *singleton;
protected:
static void _bind_methods();
public:
- static _Marshalls *get_singleton();
+ static Marshalls *get_singleton();
String variant_to_base64(const Variant &p_var, bool p_full_objects = false);
Variant base64_to_variant(const String &p_str, bool p_allow_objects = false);
@@ -519,13 +503,13 @@ public:
String utf8_to_base64(const String &p_str);
String base64_to_utf8(const String &p_str);
- _Marshalls() { singleton = this; }
- ~_Marshalls() { singleton = nullptr; }
+ Marshalls() { singleton = this; }
+ ~Marshalls() { singleton = nullptr; }
};
-class _Mutex : public RefCounted {
- GDCLASS(_Mutex, RefCounted);
- Mutex mutex;
+class Mutex : public RefCounted {
+ GDCLASS(Mutex, RefCounted);
+ ::Mutex mutex;
static void _bind_methods();
@@ -535,9 +519,9 @@ public:
void unlock();
};
-class _Semaphore : public RefCounted {
- GDCLASS(_Semaphore, RefCounted);
- Semaphore semaphore;
+class Semaphore : public RefCounted {
+ GDCLASS(Semaphore, RefCounted);
+ ::Semaphore semaphore;
static void _bind_methods();
@@ -547,8 +531,8 @@ public:
void post();
};
-class _Thread : public RefCounted {
- GDCLASS(_Thread, RefCounted);
+class Thread : public RefCounted {
+ GDCLASS(Thread, RefCounted);
protected:
Variant ret;
@@ -556,7 +540,7 @@ protected:
SafeFlag active;
Object *target_instance = nullptr;
StringName target_method;
- Thread thread;
+ ::Thread thread;
static void _bind_methods();
static void _start_func(void *ud);
@@ -574,10 +558,10 @@ public:
Variant wait_to_finish();
};
-VARIANT_ENUM_CAST(_Thread::Priority);
+namespace special {
-class _ClassDB : public Object {
- GDCLASS(_ClassDB, Object);
+class ClassDB : public Object {
+ GDCLASS(ClassDB, Object);
protected:
static void _bind_methods();
@@ -610,19 +594,21 @@ public:
bool is_class_enabled(StringName p_class) const;
- _ClassDB() {}
- ~_ClassDB() {}
+ ClassDB() {}
+ ~ClassDB() {}
};
-class _Engine : public Object {
- GDCLASS(_Engine, Object);
+} // namespace special
+
+class Engine : public Object {
+ GDCLASS(Engine, Object);
protected:
static void _bind_methods();
- static _Engine *singleton;
+ static Engine *singleton;
public:
- static _Engine *get_singleton() { return singleton; }
+ static Engine *get_singleton() { return singleton; }
void set_physics_ticks_per_second(int p_ips);
int get_physics_ticks_per_second() const;
@@ -662,14 +648,14 @@ public:
void set_print_error_messages(bool p_enabled);
bool is_printing_error_messages() const;
- _Engine() { singleton = this; }
+ Engine() { singleton = this; }
};
-class _EngineDebugger : public Object {
- GDCLASS(_EngineDebugger, Object);
+class EngineDebugger : public Object {
+ GDCLASS(EngineDebugger, Object);
class ProfilerCallable {
- friend class _EngineDebugger;
+ friend class EngineDebugger;
Callable callable_toggle;
Callable callable_add;
@@ -690,10 +676,10 @@ class _EngineDebugger : public Object {
protected:
static void _bind_methods();
- static _EngineDebugger *singleton;
+ static EngineDebugger *singleton;
public:
- static _EngineDebugger *get_singleton() { return singleton; }
+ static EngineDebugger *get_singleton() { return singleton; }
bool is_active();
@@ -715,8 +701,29 @@ public:
static void call_tick(void *p_user, double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time);
static Error call_capture(void *p_user, const String &p_cmd, const Array &p_data, bool &r_captured);
- _EngineDebugger() { singleton = this; }
- ~_EngineDebugger();
+ EngineDebugger() { singleton = this; }
+ ~EngineDebugger();
};
+} // namespace core_bind
+
+VARIANT_ENUM_CAST(core_bind::ResourceLoader::ThreadLoadStatus);
+VARIANT_ENUM_CAST(core_bind::ResourceLoader::CacheMode);
+
+VARIANT_ENUM_CAST(core_bind::ResourceSaver::SaverFlags);
+
+VARIANT_ENUM_CAST(core_bind::OS::VideoDriver);
+VARIANT_ENUM_CAST(core_bind::OS::Weekday);
+VARIANT_ENUM_CAST(core_bind::OS::Month);
+VARIANT_ENUM_CAST(core_bind::OS::SystemDir);
+
+VARIANT_ENUM_CAST(core_bind::Geometry2D::PolyBooleanOperation);
+VARIANT_ENUM_CAST(core_bind::Geometry2D::PolyJoinType);
+VARIANT_ENUM_CAST(core_bind::Geometry2D::PolyEndType);
+
+VARIANT_ENUM_CAST(core_bind::File::ModeFlags);
+VARIANT_ENUM_CAST(core_bind::File::CompressionMode);
+
+VARIANT_ENUM_CAST(core_bind::Thread::Priority);
+
#endif // CORE_BIND_H
diff --git a/core/core_constants.cpp b/core/core_constants.cpp
index 5791f79053..ffddcbabc4 100644
--- a/core/core_constants.cpp
+++ b/core/core_constants.cpp
@@ -605,6 +605,7 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_VIRTUAL);
BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_FROM_SCRIPT);
BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_STATIC);
+ BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_OBJECT_CORE);
BIND_CORE_ENUM_CONSTANT(METHOD_FLAGS_DEFAULT);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_NIL", Variant::NIL);
diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp
index 49570cd1c1..46dc5f284b 100644
--- a/core/extension/extension_api_dump.cpp
+++ b/core/extension/extension_api_dump.cpp
@@ -653,7 +653,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
ClassDB::get_method_list(class_name, &method_list, true);
for (const MethodInfo &F : method_list) {
StringName method_name = F.name;
- if (F.flags & METHOD_FLAG_VIRTUAL) {
+ if ((F.flags & METHOD_FLAG_VIRTUAL) && !(F.flags & METHOD_FLAG_OBJECT_CORE)) {
//virtual method
const MethodInfo &mi = F;
Dictionary d2;
diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp
index e0ebd19376..de107b4156 100644
--- a/core/extension/gdnative_interface.cpp
+++ b/core/extension/gdnative_interface.cpp
@@ -663,7 +663,23 @@ static const char32_t *gdnative_string_operator_index_const(const GDNativeString
/* OBJECT API */
-static void gdnative_object_method_bind_ptrcall(GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr p_ret) {
+static void gdnative_object_method_bind_call(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeVariantPtr *p_args, GDNativeInt p_arg_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error) {
+ MethodBind *mb = (MethodBind *)p_method_bind;
+ Object *o = (Object *)p_instance;
+ const Variant **args = (const Variant **)p_args;
+ Callable::CallError error;
+
+ Variant ret = mb->call(o, args, p_arg_count, error);
+ memnew_placement(r_return, Variant(ret));
+
+ if (r_error) {
+ r_error->error = (GDNativeCallErrorType)(error.error);
+ r_error->argument = error.argument;
+ r_error->expected = error.expected;
+ }
+}
+
+static void gdnative_object_method_bind_ptrcall(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr p_ret) {
MethodBind *mb = (MethodBind *)p_method_bind;
Object *o = (Object *)p_instance;
mb->ptrcall(o, (const void **)p_args, p_ret);
@@ -829,6 +845,7 @@ void gdnative_setup_interface(GDNativeInterface *p_interface) {
/* OBJECT */
+ gdni.object_method_bind_call = gdnative_object_method_bind_call;
gdni.object_method_bind_ptrcall = gdnative_object_method_bind_ptrcall;
gdni.object_destroy = gdnative_object_destroy;
gdni.global_get_singleton = gdnative_global_get_singleton;
diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h
index 3432d8fabe..3a5b04429c 100644
--- a/core/extension/gdnative_interface.h
+++ b/core/extension/gdnative_interface.h
@@ -389,7 +389,8 @@ typedef struct {
/* OBJECT */
- void (*object_method_bind_ptrcall)(GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
+ void (*object_method_bind_call)(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeVariantPtr *p_args, GDNativeInt p_arg_count, GDNativeVariantPtr r_ret, GDNativeCallError *r_error);
+ void (*object_method_bind_ptrcall)(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
void (*object_destroy)(GDNativeObjectPtr p_o);
GDNativeObjectPtr (*global_get_singleton)(const char *p_name);
void *(*object_get_instance_binding)(GDNativeObjectPtr p_o, void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks);
@@ -409,7 +410,7 @@ typedef struct {
void (*classdb_register_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs);
void (*classdb_register_extension_class_method)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info);
- void (*classdb_register_extension_class_integer_constant)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_enum_name, const char *p_class_name, const char *p_constant_name, uint32_t p_constant_value);
+ void (*classdb_register_extension_class_integer_constant)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value);
void (*classdb_register_extension_class_property)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter);
void (*classdb_register_extension_class_signal)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count);
void (*classdb_unregister_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name); /* Unregistering a parent class before a class that inherits it will result in failure. Inheritors must be unregistered first. */
diff --git a/core/extension/native_extension.cpp b/core/extension/native_extension.cpp
index 91d304627a..0556c9c84d 100644
--- a/core/extension/native_extension.cpp
+++ b/core/extension/native_extension.cpp
@@ -69,7 +69,7 @@ public:
virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
Variant ret;
GDExtensionClassInstancePtr extension_instance = p_object->_get_extension_instance();
- GDNativeCallError ce;
+ GDNativeCallError ce{ GDNATIVE_CALL_OK, 0, 0 };
call_func(method_userdata, extension_instance, (const GDNativeVariantPtr *)p_args, p_arg_count, (GDNativeVariantPtr)&ret, &ce);
r_error.error = Callable::CallError::Error(ce.error);
r_error.argument = ce.argument;
@@ -154,6 +154,7 @@ void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibr
extension->native_extension.create_instance = p_extension_funcs->create_instance_func;
extension->native_extension.set_object_instance = p_extension_funcs->object_instance_func;
extension->native_extension.free_instance = p_extension_funcs->free_instance_func;
+ extension->native_extension.get_virtual = p_extension_funcs->get_virtual_func;
ClassDB::register_extension_class(&extension->native_extension);
}
@@ -171,7 +172,7 @@ void NativeExtension::_register_extension_class_method(const GDNativeExtensionCl
ClassDB::bind_method_custom(class_name, method);
}
-void NativeExtension::_register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, uint32_t p_constant_value) {
+void NativeExtension::_register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value) {
NativeExtension *self = (NativeExtension *)p_library;
StringName class_name = p_class_name;
diff --git a/core/extension/native_extension.h b/core/extension/native_extension.h
index 8bd95b2867..a961b21cc9 100644
--- a/core/extension/native_extension.h
+++ b/core/extension/native_extension.h
@@ -48,7 +48,7 @@ class NativeExtension : public Resource {
static void _register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs);
static void _register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info);
- static void _register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, uint32_t p_constant_value);
+ static void _register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value);
static void _register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter);
static void _register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count);
static void _unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name);
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index 325cdf2127..50b2099236 100644
--- a/core/input/input_event.cpp
+++ b/core/input/input_event.cpp
@@ -31,8 +31,8 @@
#include "input_event.h"
#include "core/input/input_map.h"
+#include "core/input/shortcut.h"
#include "core/os/keyboard.h"
-#include "scene/gui/shortcut.h"
const int InputEvent::DEVICE_ID_TOUCH_MOUSE = -1;
const int InputEvent::DEVICE_ID_INTERNAL = -2;
@@ -1545,6 +1545,13 @@ Ref<Shortcut> InputEventShortcut::get_shortcut() {
return shortcut;
}
+void InputEventShortcut::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_shortcut", "shortcut"), &InputEventShortcut::set_shortcut);
+ ClassDB::bind_method(D_METHOD("get_shortcut"), &InputEventShortcut::get_shortcut);
+
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut", PROPERTY_HINT_RESOURCE_TYPE, "Shortcut"), "set_shortcut", "get_shortcut");
+}
+
bool InputEventShortcut::is_pressed() const {
return true;
}
diff --git a/core/input/input_event.h b/core/input/input_event.h
index 517d63eb40..3fc8078a09 100644
--- a/core/input/input_event.h
+++ b/core/input/input_event.h
@@ -548,6 +548,9 @@ class InputEventShortcut : public InputEvent {
Ref<Shortcut> shortcut;
+protected:
+ static void _bind_methods();
+
public:
void set_shortcut(Ref<Shortcut> p_shortcut);
Ref<Shortcut> get_shortcut();
diff --git a/core/input/shortcut.cpp b/core/input/shortcut.cpp
new file mode 100644
index 0000000000..d0cb08724e
--- /dev/null
+++ b/core/input/shortcut.cpp
@@ -0,0 +1,76 @@
+/*************************************************************************/
+/* shortcut.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "shortcut.h"
+#include "core/os/keyboard.h"
+
+void Shortcut::set_event(const Ref<InputEvent> &p_event) {
+ ERR_FAIL_COND_MSG(Object::cast_to<InputEventShortcut>(*p_event), "Cannot set a shortcut event to an instance of InputEventShortcut.");
+ event = p_event;
+ emit_changed();
+}
+
+Ref<InputEvent> Shortcut::get_event() const {
+ return event;
+}
+
+bool Shortcut::matches_event(const Ref<InputEvent> &p_event) const {
+ Ref<InputEventShortcut> ies = p_event;
+ if (ies.is_valid()) {
+ if (ies->get_shortcut().ptr() == this) {
+ return true;
+ }
+ }
+ return event.is_valid() && event->is_match(p_event, true);
+}
+
+String Shortcut::get_as_text() const {
+ if (event.is_valid()) {
+ return event->as_text();
+ } else {
+ return "None";
+ }
+}
+
+bool Shortcut::has_valid_event() const {
+ return event.is_valid();
+}
+
+void Shortcut::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_event", "event"), &Shortcut::set_event);
+ ClassDB::bind_method(D_METHOD("get_event"), &Shortcut::get_event);
+
+ ClassDB::bind_method(D_METHOD("has_valid_event"), &Shortcut::has_valid_event);
+
+ ClassDB::bind_method(D_METHOD("matches_event", "event"), &Shortcut::matches_event);
+ ClassDB::bind_method(D_METHOD("get_as_text"), &Shortcut::get_as_text);
+
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), "set_event", "get_event");
+}
diff --git a/core/input/shortcut.h b/core/input/shortcut.h
new file mode 100644
index 0000000000..249dd1971f
--- /dev/null
+++ b/core/input/shortcut.h
@@ -0,0 +1,54 @@
+/*************************************************************************/
+/* shortcut.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef SHORTCUT_H
+#define SHORTCUT_H
+
+#include "core/input/input_event.h"
+#include "core/io/resource.h"
+
+class Shortcut : public Resource {
+ GDCLASS(Shortcut, Resource);
+
+ Ref<InputEvent> event;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_event(const Ref<InputEvent> &p_shortcut);
+ Ref<InputEvent> get_event() const;
+ bool matches_event(const Ref<InputEvent> &p_event) const;
+ bool has_valid_event() const;
+
+ String get_as_text() const;
+};
+
+#endif // SHORTCUT_H
diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp
index f792dc6cb4..0ce9a70921 100644
--- a/core/io/multiplayer_api.cpp
+++ b/core/io/multiplayer_api.cpp
@@ -32,15 +32,11 @@
#include "core/debugger/engine_debugger.h"
#include "core/io/marshalls.h"
+#include "core/io/multiplayer_replicator.h"
#include "scene/main/node.h"
-#include "scene/resources/packed_scene.h"
#include <stdint.h>
-#define NODE_ID_COMPRESSION_SHIFT 3
-#define NAME_ID_COMPRESSION_SHIFT 5
-#define BYTE_ONLY_OR_NO_ARGS_SHIFT 6
-
#ifdef DEBUG_ENABLED
#include "core/os/os.h"
#endif
@@ -147,7 +143,7 @@ void MultiplayerAPI::poll() {
}
void MultiplayerAPI::clear() {
- replicated_nodes.clear();
+ replicator->clear();
connected_peers.clear();
path_get_cache.clear();
path_send_cache.clear();
@@ -325,10 +321,10 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_
_process_raw(p_from, p_packet, p_packet_len);
} break;
case NETWORK_COMMAND_SPAWN: {
- _process_spawn_despawn(p_from, p_packet, p_packet_len, true);
+ replicator->process_spawn_despawn(p_from, p_packet, p_packet_len, true);
} break;
case NETWORK_COMMAND_DESPAWN: {
- _process_spawn_despawn(p_from, p_packet, p_packet_len, false);
+ replicator->process_spawn_despawn(p_from, p_packet, p_packet_len, false);
} break;
}
}
@@ -338,7 +334,6 @@ Node *MultiplayerAPI::_process_get_node(int p_from, const uint8_t *p_packet, uin
if (p_node_target & 0x80000000) {
// Use full path (not cached yet).
-
int ofs = p_node_target & 0x7FFFFFFF;
ERR_FAIL_COND_V_MSG(ofs >= p_packet_len, nullptr, "Invalid packet received. Size smaller than declared.");
@@ -353,25 +348,11 @@ Node *MultiplayerAPI::_process_get_node(int p_from, const uint8_t *p_packet, uin
if (!node) {
ERR_PRINT("Failed to get path from RPC: " + String(np) + ".");
}
+ return node;
} else {
// Use cached path.
- int id = p_node_target;
-
- Map<int, PathGetCache>::Element *E = path_get_cache.find(p_from);
- ERR_FAIL_COND_V_MSG(!E, nullptr, "Invalid packet received. Requests invalid peer cache.");
-
- Map<int, PathGetCache::NodeInfo>::Element *F = E->get().nodes.find(id);
- ERR_FAIL_COND_V_MSG(!F, nullptr, "Invalid packet received. Unabled to find requested cached node.");
-
- PathGetCache::NodeInfo *ni = &F->get();
- // Do proper caching later.
-
- node = root_node->get_node(ni->path);
- if (!node) {
- ERR_PRINT("Failed to get cached path from RPC: " + String(ni->path) + ".");
- }
+ return get_cached_node(p_from, p_node_target);
}
- return node;
}
void MultiplayerAPI::_process_rpc(Node *p_node, const uint16_t p_rpc_method_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) {
@@ -425,7 +406,7 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const uint16_t p_rpc_method_id,
ERR_FAIL_COND_MSG(p_offset >= p_packet_len, "Invalid packet received. Size too small.");
int vlen;
- Error err = _decode_and_decompress_variant(args.write[i], &p_packet[p_offset], p_packet_len - p_offset, &vlen);
+ Error err = decode_and_decompress_variant(args.write[i], &p_packet[p_offset], p_packet_len - p_offset, &vlen);
ERR_FAIL_COND_MSG(err != OK, "Invalid packet received. Unable to decode RPC argument.");
argp.write[i] = &args[i];
@@ -514,64 +495,6 @@ void MultiplayerAPI::_process_confirm_path(int p_from, const uint8_t *p_packet,
E->get() = true;
}
-void MultiplayerAPI::_process_spawn_despawn(int p_from, const uint8_t *p_packet, int p_packet_len, bool p_spawn) {
- ERR_FAIL_COND_MSG(p_packet_len < 18, "Invalid spawn packet received");
- int ofs = 1;
- ResourceUID::ID id = decode_uint64(&p_packet[ofs]);
- ofs += 8;
- ERR_FAIL_COND_MSG(!spawnables.has(id), "Invalid spawn ID received " + itos(id));
-
- uint32_t node_target = decode_uint32(&p_packet[ofs]);
- Node *parent = _process_get_node(p_from, nullptr, node_target, 0);
- ofs += 4;
- ERR_FAIL_COND_MSG(parent == nullptr, "Invalid packet received. Requested node was not found.");
-
- uint32_t name_len = decode_uint32(&p_packet[ofs]);
- ofs += 4;
- ERR_FAIL_COND_MSG(name_len > uint32_t(p_packet_len - ofs), vformat("Invalid spawn packet size: %d, wants: %d", p_packet_len, ofs + name_len));
- ERR_FAIL_COND_MSG(name_len < 1, "Zero spawn name size.");
-
- const String name = String::utf8((const char *)&p_packet[ofs], name_len);
- // We need to make sure no trickery happens here (e.g. despawning a subpath), but we want to allow autogenerated ("@") node names.
- ERR_FAIL_COND_MSG(name.validate_node_name() != name.replace("@", ""), vformat("Invalid node name received: '%s'", name));
- ofs += name_len;
- PackedByteArray data;
- if (p_packet_len > ofs) {
- data.resize(p_packet_len - ofs);
- memcpy(data.ptrw(), &p_packet[ofs], data.size());
- }
-
- SpawnMode mode = spawnables[id];
- if (mode == SPAWN_MODE_SERVER && p_from == 1) {
- String scene_path = ResourceUID::get_singleton()->get_id_path(id);
- if (p_spawn) {
- ERR_FAIL_COND_MSG(parent->has_node(name), vformat("Unable to spawn node. Node already exists: %s/%s", parent->get_path(), name));
- RES res = ResourceLoader::load(scene_path);
- ERR_FAIL_COND_MSG(!res.is_valid(), "Unable to load scene to spawn at path: " + scene_path);
- PackedScene *scene = Object::cast_to<PackedScene>(res.ptr());
- ERR_FAIL_COND(!scene);
- Node *node = scene->instantiate();
- ERR_FAIL_COND(!node);
- replicated_nodes[node->get_instance_id()] = id;
- parent->_add_child_nocheck(node, name);
- emit_signal(SNAME("network_spawn"), p_from, id, node, data);
- } else {
- ERR_FAIL_COND_MSG(!parent->has_node(name), vformat("Path not found: %s/%s", parent->get_path(), name));
- Node *node = parent->get_node(name);
- ERR_FAIL_COND_MSG(!replicated_nodes.has(node->get_instance_id()), vformat("Trying to despawn a Node that was not replicated: %s/%s", parent->get_path(), name));
- emit_signal(SNAME("network_despawn"), p_from, id, node, data);
- replicated_nodes.erase(node->get_instance_id());
- node->queue_delete();
- }
- } else {
- if (p_spawn) {
- emit_signal(SNAME("network_spawn_request"), p_from, id, parent, name, data);
- } else {
- emit_signal(SNAME("network_despawn_request"), p_from, id, parent, name, data);
- }
- }
-}
-
bool MultiplayerAPI::_send_confirm_path(Node *p_node, NodePath p_path, PathSentCache *psc, int p_target) {
bool has_all_peers = true;
List<int> peers_to_add; // If one is missing, take note to add it.
@@ -647,7 +570,7 @@ bool MultiplayerAPI::_send_confirm_path(Node *p_node, NodePath p_path, PathSentC
#define ENCODE_16 1 << 5
#define ENCODE_32 2 << 5
#define ENCODE_64 3 << 5
-Error MultiplayerAPI::_encode_and_compress_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len) {
+Error MultiplayerAPI::encode_and_compress_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len) {
// Unreachable because `VARIANT_MAX` == 27 and `ENCODE_VARIANT_MASK` == 31
CRASH_COND(p_variant.get_type() > VARIANT_META_TYPE_MASK);
@@ -722,7 +645,7 @@ Error MultiplayerAPI::_encode_and_compress_variant(const Variant &p_variant, uin
return OK;
}
-Error MultiplayerAPI::_decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len) {
+Error MultiplayerAPI::decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len) {
const uint8_t *buf = p_buffer;
int len = p_len;
@@ -906,10 +829,10 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const
ofs += 1;
for (int i = 0; i < p_argcount; i++) {
int len(0);
- Error err = _encode_and_compress_variant(*p_arg[i], nullptr, len);
+ Error err = encode_and_compress_variant(*p_arg[i], nullptr, len);
ERR_FAIL_COND_MSG(err != OK, "Unable to encode RPC argument. THIS IS LIKELY A BUG IN THE ENGINE!");
MAKE_ROOM(ofs + len);
- _encode_and_compress_variant(*p_arg[i], &(packet_cache.write[ofs]), len);
+ encode_and_compress_variant(*p_arg[i], &(packet_cache.write[ofs]), len);
ofs += len;
}
}
@@ -976,14 +899,7 @@ void MultiplayerAPI::_add_peer(int p_id) {
connected_peers.insert(p_id);
path_get_cache.insert(p_id, PathGetCache());
if (is_network_server()) {
- for (const KeyValue<ObjectID, ResourceUID::ID> &E : replicated_nodes) {
- // Only server mode adds to replicated_nodes, no need to check it.
- Object *obj = ObjectDB::get_instance(E.key);
- ERR_CONTINUE(!obj);
- Node *node = Object::cast_to<Node>(obj);
- ERR_CONTINUE(!node);
- _send_spawn_despawn(p_id, E.value, node->get_path(), nullptr, 0, true);
- }
+ replicator->spawn_all(p_id);
}
emit_signal(SNAME("network_peer_connected"), p_id);
}
@@ -1000,10 +916,6 @@ void MultiplayerAPI::_del_peer(int p_id) {
PathSentCache *psc = path_send_cache.getptr(E);
psc->confirmed_peers.erase(p_id);
}
- if (p_id == 1) {
- // Erase server replicated nodes, but do not queue them for deletion.
- replicated_nodes.clear();
- }
emit_signal(SNAME("network_peer_disconnected"), p_id);
}
@@ -1109,6 +1021,36 @@ void MultiplayerAPI::_process_raw(int p_from, const uint8_t *p_packet, int p_pac
emit_signal(SNAME("network_peer_packet"), p_from, out);
}
+bool MultiplayerAPI::send_confirm_path(Node *p_node, NodePath p_path, int p_peer_id, int &r_id) {
+ // See if the path is cached.
+ PathSentCache *psc = path_send_cache.getptr(p_path);
+ if (!psc) {
+ // Path is not cached, create.
+ path_send_cache[p_path] = PathSentCache();
+ psc = path_send_cache.getptr(p_path);
+ psc->id = last_send_cache_id++;
+ }
+ r_id = psc->id;
+
+ // See if all peers have cached path (if so, call can be fast).
+ return _send_confirm_path(p_node, p_path, psc, p_peer_id);
+}
+
+Node *MultiplayerAPI::get_cached_node(int p_from, uint32_t p_node_id) {
+ Map<int, PathGetCache>::Element *E = path_get_cache.find(p_from);
+ ERR_FAIL_COND_V_MSG(!E, nullptr, vformat("No cache found for peer %d.", p_from));
+
+ Map<int, PathGetCache::NodeInfo>::Element *F = E->get().nodes.find(p_node_id);
+ ERR_FAIL_COND_V_MSG(!F, nullptr, vformat("ID %d not found in cache of peer %d.", p_node_id, p_from));
+
+ PathGetCache::NodeInfo *ni = &F->get();
+ Node *node = root_node->get_node(ni->path);
+ if (!node) {
+ ERR_PRINT("Failed to get cached path: " + String(ni->path) + ".");
+ }
+ return node;
+}
+
int MultiplayerAPI::get_network_unique_id() const {
ERR_FAIL_COND_V_MSG(!network_peer.is_valid(), 0, "No network peer is assigned. Unable to get unique network ID.");
return network_peer->get_unique_id();
@@ -1147,97 +1089,12 @@ bool MultiplayerAPI::is_object_decoding_allowed() const {
return allow_object_decoding;
}
-Error MultiplayerAPI::spawnable_config(const ResourceUID::ID &p_id, SpawnMode p_mode) {
- ERR_FAIL_COND_V(p_mode < SPAWN_MODE_NONE || p_mode > SPAWN_MODE_CUSTOM, ERR_INVALID_PARAMETER);
- ERR_FAIL_COND_V(!ResourceUID::get_singleton()->has_id(p_id), ERR_INVALID_PARAMETER);
-#ifdef TOOLS_ENABLED
- String path = ResourceUID::get_singleton()->get_id_path(p_id);
- RES res = ResourceLoader::load(path);
- ERR_FAIL_COND_V(!res->is_class("PackedScene"), ERR_INVALID_PARAMETER);
-#endif
- if (p_mode == SPAWN_MODE_NONE) {
- if (spawnables.has(p_id)) {
- spawnables.erase(p_id);
- }
- } else {
- spawnables[p_id] = p_mode;
- }
- return OK;
-}
-
-Error MultiplayerAPI::send_despawn(int p_peer_id, const ResourceUID::ID &p_scene_id, const NodePath &p_path, const PackedByteArray &p_data) {
- return _send_spawn_despawn(p_peer_id, p_scene_id, p_path, p_data.ptr(), p_data.size(), false);
+MultiplayerReplicator *MultiplayerAPI::get_replicator() const {
+ return replicator;
}
-Error MultiplayerAPI::send_spawn(int p_peer_id, const ResourceUID::ID &p_scene_id, const NodePath &p_path, const PackedByteArray &p_data) {
- return _send_spawn_despawn(p_peer_id, p_scene_id, p_path, p_data.ptr(), p_data.size(), true);
-}
-
-Error MultiplayerAPI::_send_spawn_despawn(int p_peer_id, const ResourceUID::ID &p_scene_id, const NodePath &p_path, const uint8_t *p_data, int p_data_len, bool p_spawn) {
- ERR_FAIL_COND_V(!root_node, ERR_UNCONFIGURED);
- ERR_FAIL_COND_V_MSG(!spawnables.has(p_scene_id), ERR_INVALID_PARAMETER, vformat("Spawnable not found: %d", p_scene_id));
-
- NodePath rel_path = (root_node->get_path()).rel_path_to(p_path);
- const Vector<StringName> names = rel_path.get_names();
- ERR_FAIL_COND_V(names.size() < 2, ERR_INVALID_PARAMETER);
-
- NodePath parent = NodePath(names.subarray(0, names.size() - 2), false);
- ERR_FAIL_COND_V_MSG(!root_node->has_node(parent), ERR_INVALID_PARAMETER, "Path not found: " + parent);
-
- // See if the path is cached.
- PathSentCache *psc = path_send_cache.getptr(parent);
- if (!psc) {
- // Path is not cached, create.
- path_send_cache[parent] = PathSentCache();
- psc = path_send_cache.getptr(parent);
- psc->id = last_send_cache_id++;
- }
- _send_confirm_path(root_node->get_node(parent), parent, psc, p_peer_id);
-
- const CharString cname = String(names[names.size() - 1]).utf8();
- int nlen = encode_cstring(cname.get_data(), nullptr);
- MAKE_ROOM(1 + 8 + 4 + 4 + nlen + p_data_len);
- uint8_t *ptr = packet_cache.ptrw();
- ptr[0] = p_spawn ? NETWORK_COMMAND_SPAWN : NETWORK_COMMAND_DESPAWN;
- int ofs = 1;
- ofs += encode_uint64(p_scene_id, &ptr[ofs]);
- ofs += encode_uint32(psc->id, &ptr[ofs]);
- ofs += encode_uint32(nlen, &ptr[ofs]);
- ofs += encode_cstring(cname.get_data(), &ptr[ofs]);
- memcpy(&ptr[ofs], p_data, p_data_len);
- network_peer->set_target_peer(p_peer_id);
- network_peer->set_transfer_channel(0);
- network_peer->set_transfer_mode(MultiplayerPeer::TRANSFER_MODE_RELIABLE);
- return network_peer->put_packet(ptr, ofs + p_data_len);
-}
-
-void MultiplayerAPI::scene_enter_exit_notify(const String &p_scene, const Node *p_node, bool p_enter) {
- if (!has_network_peer()) {
- return;
- }
- ERR_FAIL_COND(!p_node || !p_node->get_parent() || !root_node);
- NodePath path = (root_node->get_path()).rel_path_to(p_node->get_parent()->get_path());
- if (path.is_empty()) {
- return;
- }
- ResourceUID::ID id = ResourceLoader::get_resource_uid(p_scene);
- if (!spawnables.has(id)) {
- return;
- }
- SpawnMode mode = spawnables[id];
- if (p_enter) {
- if (mode == SPAWN_MODE_SERVER && is_network_server()) {
- replicated_nodes[p_node->get_instance_id()] = id;
- _send_spawn_despawn(0, id, p_node->get_path(), nullptr, 0, true);
- }
- emit_signal(SNAME("network_spawnable_added"), id, p_node);
- } else {
- if (mode == SPAWN_MODE_SERVER && is_network_server() && replicated_nodes.has(p_node->get_instance_id())) {
- replicated_nodes.erase(p_node->get_instance_id());
- _send_spawn_despawn(0, id, p_node->get_path(), nullptr, 0, false);
- }
- emit_signal(SNAME("network_spawnable_removed"), id, p_node);
- }
+void MultiplayerAPI::scene_enter_exit_notify(const String &p_scene, Node *p_node, bool p_enter) {
+ replicator->scene_enter_exit_notify(p_scene, p_node, p_enter);
}
void MultiplayerAPI::_bind_methods() {
@@ -1258,15 +1115,14 @@ void MultiplayerAPI::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_refusing_new_network_connections"), &MultiplayerAPI::is_refusing_new_network_connections);
ClassDB::bind_method(D_METHOD("set_allow_object_decoding", "enable"), &MultiplayerAPI::set_allow_object_decoding);
ClassDB::bind_method(D_METHOD("is_object_decoding_allowed"), &MultiplayerAPI::is_object_decoding_allowed);
- ClassDB::bind_method(D_METHOD("spawnable_config", "scene_id", "spawn_mode"), &MultiplayerAPI::spawnable_config);
- ClassDB::bind_method(D_METHOD("send_despawn", "peer_id", "scene_id", "path", "data"), &MultiplayerAPI::send_despawn, DEFVAL(PackedByteArray()));
- ClassDB::bind_method(D_METHOD("send_spawn", "peer_id", "scene_id", "path", "data"), &MultiplayerAPI::send_spawn, DEFVAL(PackedByteArray()));
+ ClassDB::bind_method(D_METHOD("get_replicator"), &MultiplayerAPI::get_replicator);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_object_decoding"), "set_allow_object_decoding", "is_object_decoding_allowed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_network_connections"), "set_refuse_new_network_connections", "is_refusing_new_network_connections");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "network_peer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerPeer", PROPERTY_USAGE_NONE), "set_network_peer", "get_network_peer");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root_node", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_root_node", "get_root_node");
ADD_PROPERTY_DEFAULT("refuse_new_network_connections", false);
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "replicator", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerReplicator", PROPERTY_USAGE_NONE), "", "get_replicator");
ADD_SIGNAL(MethodInfo("network_peer_connected", PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("network_peer_disconnected", PropertyInfo(Variant::INT, "id")));
@@ -1274,27 +1130,19 @@ void MultiplayerAPI::_bind_methods() {
ADD_SIGNAL(MethodInfo("connected_to_server"));
ADD_SIGNAL(MethodInfo("connection_failed"));
ADD_SIGNAL(MethodInfo("server_disconnected"));
- ADD_SIGNAL(MethodInfo("network_despawn", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data")));
- ADD_SIGNAL(MethodInfo("network_spawn", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data")));
- ADD_SIGNAL(MethodInfo("network_despawn_request", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "parent", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data")));
- ADD_SIGNAL(MethodInfo("network_spawn_request", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "parent", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data")));
- ADD_SIGNAL(MethodInfo("network_spawnable_added", PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
- ADD_SIGNAL(MethodInfo("network_spawnable_removed", PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
BIND_ENUM_CONSTANT(RPC_MODE_DISABLED);
BIND_ENUM_CONSTANT(RPC_MODE_REMOTE);
BIND_ENUM_CONSTANT(RPC_MODE_MASTER);
BIND_ENUM_CONSTANT(RPC_MODE_PUPPET);
-
- BIND_ENUM_CONSTANT(SPAWN_MODE_NONE);
- BIND_ENUM_CONSTANT(SPAWN_MODE_SERVER);
- BIND_ENUM_CONSTANT(SPAWN_MODE_CUSTOM);
}
MultiplayerAPI::MultiplayerAPI() {
+ replicator = memnew(MultiplayerReplicator(this));
clear();
}
MultiplayerAPI::~MultiplayerAPI() {
clear();
+ memdelete(replicator);
}
diff --git a/core/io/multiplayer_api.h b/core/io/multiplayer_api.h
index 9552a0bf35..5853541efa 100644
--- a/core/io/multiplayer_api.h
+++ b/core/io/multiplayer_api.h
@@ -35,6 +35,8 @@
#include "core/io/resource_uid.h"
#include "core/object/ref_counted.h"
+class MultiplayerReplicator;
+
class MultiplayerAPI : public RefCounted {
GDCLASS(MultiplayerAPI, RefCounted);
@@ -46,12 +48,6 @@ public:
RPC_MODE_PUPPET, // Using rpc() on it will call method for all puppets
};
- enum SpawnMode {
- SPAWN_MODE_NONE,
- SPAWN_MODE_SERVER,
- SPAWN_MODE_CUSTOM,
- };
-
struct RPCConfig {
StringName name;
RPCMode rpc_mode = RPC_MODE_DISABLED;
@@ -71,6 +67,32 @@ public:
}
};
+ enum NetworkCommands {
+ NETWORK_COMMAND_REMOTE_CALL = 0,
+ NETWORK_COMMAND_SIMPLIFY_PATH,
+ NETWORK_COMMAND_CONFIRM_PATH,
+ NETWORK_COMMAND_RAW,
+ NETWORK_COMMAND_SPAWN,
+ NETWORK_COMMAND_DESPAWN,
+ };
+
+ enum NetworkNodeIdCompression {
+ NETWORK_NODE_ID_COMPRESSION_8 = 0,
+ NETWORK_NODE_ID_COMPRESSION_16,
+ NETWORK_NODE_ID_COMPRESSION_32,
+ };
+
+ enum NetworkNameIdCompression {
+ NETWORK_NAME_ID_COMPRESSION_8 = 0,
+ NETWORK_NAME_ID_COMPRESSION_16,
+ };
+
+ enum {
+ NODE_ID_COMPRESSION_SHIFT = 3,
+ NAME_ID_COMPRESSION_SHIFT = 5,
+ BYTE_ONLY_OR_NO_ARGS_SHIFT = 6,
+ };
+
private:
//path sent caches
struct PathSentCache {
@@ -89,16 +111,15 @@ private:
};
Ref<MultiplayerPeer> network_peer;
- Map<ResourceUID::ID, SpawnMode> spawnables;
int rpc_sender_id = 0;
Set<int> connected_peers;
HashMap<NodePath, PathSentCache> path_send_cache;
Map<int, PathGetCache> path_get_cache;
- Map<ObjectID, ResourceUID::ID> replicated_nodes;
int last_send_cache_id;
Vector<uint8_t> packet_cache;
Node *root_node = nullptr;
bool allow_object_decoding = false;
+ MultiplayerReplicator *replicator = nullptr;
protected:
static void _bind_methods();
@@ -106,7 +127,6 @@ protected:
void _process_packet(int p_from, const uint8_t *p_packet, int p_packet_len);
void _process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len);
void _process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len);
- void _process_spawn_despawn(int p_from, const uint8_t *p_packet, int p_packet_len, bool p_spawn);
Node *_process_get_node(int p_from, const uint8_t *p_packet, uint32_t p_node_target, int p_packet_len);
void _process_rpc(Node *p_node, const uint16_t p_rpc_method_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset);
void _process_raw(int p_from, const uint8_t *p_packet, int p_packet_len);
@@ -114,30 +134,7 @@ protected:
void _send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount);
bool _send_confirm_path(Node *p_node, NodePath p_path, PathSentCache *psc, int p_target);
- Error _encode_and_compress_variant(const Variant &p_variant, uint8_t *p_buffer, int &r_len);
- Error _decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len);
-
public:
- enum NetworkCommands {
- NETWORK_COMMAND_REMOTE_CALL = 0,
- NETWORK_COMMAND_SIMPLIFY_PATH,
- NETWORK_COMMAND_CONFIRM_PATH,
- NETWORK_COMMAND_RAW,
- NETWORK_COMMAND_SPAWN,
- NETWORK_COMMAND_DESPAWN,
- };
-
- enum NetworkNodeIdCompression {
- NETWORK_NODE_ID_COMPRESSION_8 = 0,
- NETWORK_NODE_ID_COMPRESSION_16,
- NETWORK_NODE_ID_COMPRESSION_32,
- };
-
- enum NetworkNameIdCompression {
- NETWORK_NAME_ID_COMPRESSION_8 = 0,
- NETWORK_NAME_ID_COMPRESSION_16,
- };
-
void poll();
void clear();
void set_root_node(Node *p_node);
@@ -146,8 +143,16 @@ public:
Ref<MultiplayerPeer> get_network_peer() const;
Error send_bytes(Vector<uint8_t> p_data, int p_to = MultiplayerPeer::TARGET_PEER_BROADCAST, MultiplayerPeer::TransferMode p_mode = MultiplayerPeer::TRANSFER_MODE_RELIABLE, int p_channel = 0);
+ Error encode_and_compress_variant(const Variant &p_variant, uint8_t *p_buffer, int &r_len);
+ Error decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len);
+
// Called by Node.rpc
void rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_method, const Variant **p_arg, int p_argcount);
+ // Called by Node._notification
+ void scene_enter_exit_notify(const String &p_scene, Node *p_node, bool p_enter);
+ // Called by replicator
+ bool send_confirm_path(Node *p_node, NodePath p_path, int p_target, int &p_id);
+ Node *get_cached_node(int p_from, uint32_t p_node_id);
void _add_peer(int p_id);
void _del_peer(int p_id);
@@ -166,17 +171,12 @@ public:
void set_allow_object_decoding(bool p_enable);
bool is_object_decoding_allowed() const;
- Error spawnable_config(const ResourceUID::ID &p_id, SpawnMode p_mode);
- Error send_despawn(int p_peer_id, const ResourceUID::ID &p_scene_id, const NodePath &p_path, const PackedByteArray &p_data = PackedByteArray());
- Error send_spawn(int p_peer_id, const ResourceUID::ID &p_scene_id, const NodePath &p_path, const PackedByteArray &p_data = PackedByteArray());
- Error _send_spawn_despawn(int p_peer_id, const ResourceUID::ID &p_scene_id, const NodePath &p_path, const uint8_t *p_data, int p_data_len, bool p_spawn);
- void scene_enter_exit_notify(const String &p_scene, const Node *p_node, bool p_enter);
+ MultiplayerReplicator *get_replicator() const;
MultiplayerAPI();
~MultiplayerAPI();
};
VARIANT_ENUM_CAST(MultiplayerAPI::RPCMode);
-VARIANT_ENUM_CAST(MultiplayerAPI::SpawnMode);
#endif // MULTIPLAYER_API_H
diff --git a/core/io/multiplayer_replicator.cpp b/core/io/multiplayer_replicator.cpp
new file mode 100644
index 0000000000..ba0fe32b58
--- /dev/null
+++ b/core/io/multiplayer_replicator.cpp
@@ -0,0 +1,497 @@
+/*************************************************************************/
+/* multiplayer_replicator.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "core/io/multiplayer_replicator.h"
+
+#include "core/io/marshalls.h"
+#include "scene/main/node.h"
+#include "scene/resources/packed_scene.h"
+
+#define MAKE_ROOM(m_amount) \
+ if (packet_cache.size() < m_amount) \
+ packet_cache.resize(m_amount);
+
+Error MultiplayerReplicator::_send_default_spawn_despawn(int p_peer_id, const ResourceUID::ID &p_scene_id, Object *p_obj, const NodePath &p_path, bool p_spawn) {
+ ERR_FAIL_COND_V(p_spawn && !p_obj, ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V(!replications.has(p_scene_id), ERR_INVALID_PARAMETER);
+ Error err;
+ // Prepare state
+ List<Variant> state_variants;
+ int state_len = 0;
+ const SceneConfig &cfg = replications[p_scene_id];
+ if (p_spawn) {
+ if ((err = _get_state(cfg.properties, p_obj, state_variants)) != OK) {
+ return err;
+ }
+ }
+
+ bool is_raw = false;
+ if (state_variants.size() == 1 && state_variants[0].get_type() == Variant::PACKED_BYTE_ARRAY) {
+ is_raw = true;
+ } else if (state_variants.size()) {
+ err = _encode_state(state_variants, nullptr, state_len);
+ ERR_FAIL_COND_V(err, err);
+ } else {
+ is_raw = true;
+ }
+
+ int ofs = 0;
+
+ // Prepare simplified path
+ const Node *root_node = multiplayer->get_root_node();
+ ERR_FAIL_COND_V(!root_node, ERR_UNCONFIGURED);
+ NodePath rel_path = (root_node->get_path()).rel_path_to(p_path);
+ const Vector<StringName> names = rel_path.get_names();
+ ERR_FAIL_COND_V(names.size() < 2, ERR_INVALID_PARAMETER);
+
+ NodePath parent = NodePath(names.subarray(0, names.size() - 2), false);
+ ERR_FAIL_COND_V_MSG(!root_node->has_node(parent), ERR_INVALID_PARAMETER, "Path not found: " + parent);
+
+ int path_id = 0;
+ multiplayer->send_confirm_path(root_node->get_node(parent), parent, p_peer_id, path_id);
+
+ // Encode name and parent ID.
+ CharString cname = String(names[names.size() - 1]).utf8();
+ int nlen = encode_cstring(cname.get_data(), nullptr);
+ MAKE_ROOM(SPAWN_CMD_OFFSET + 4 + 4 + nlen + state_len);
+ uint8_t *ptr = packet_cache.ptrw();
+ ptr[0] = (p_spawn ? MultiplayerAPI::NETWORK_COMMAND_SPAWN : MultiplayerAPI::NETWORK_COMMAND_DESPAWN) + ((is_raw ? 1 : 0) << MultiplayerAPI::BYTE_ONLY_OR_NO_ARGS_SHIFT);
+ ofs = 1;
+ ofs += encode_uint64(p_scene_id, &ptr[ofs]);
+ ofs += encode_uint32(path_id, &ptr[ofs]);
+ ofs += encode_uint32(nlen, &ptr[ofs]);
+ ofs += encode_cstring(cname.get_data(), &ptr[ofs]);
+
+ // Encode state.
+ if (!is_raw) {
+ _encode_state(state_variants, &ptr[ofs], state_len);
+ } else if (state_len) {
+ PackedByteArray pba = state_variants[0];
+ memcpy(&ptr[ofs], pba.ptr(), state_len);
+ }
+
+ Ref<MultiplayerPeer> network_peer = multiplayer->get_network_peer();
+ network_peer->set_target_peer(p_peer_id);
+ network_peer->set_transfer_channel(0);
+ network_peer->set_transfer_mode(MultiplayerPeer::TRANSFER_MODE_RELIABLE);
+ return network_peer->put_packet(ptr, ofs + state_len);
+}
+
+void MultiplayerReplicator::_process_default_spawn_despawn(int p_from, const ResourceUID::ID &p_scene_id, const uint8_t *p_packet, int p_packet_len, bool p_spawn) {
+ ERR_FAIL_COND_MSG(p_packet_len < SPAWN_CMD_OFFSET + 9, "Invalid spawn packet received");
+ int ofs = SPAWN_CMD_OFFSET;
+ uint32_t node_target = decode_uint32(&p_packet[ofs]);
+ Node *parent = multiplayer->get_cached_node(p_from, node_target);
+ ofs += 4;
+ ERR_FAIL_COND_MSG(parent == nullptr, "Invalid packet received. Requested node was not found.");
+
+ uint32_t name_len = decode_uint32(&p_packet[ofs]);
+ ofs += 4;
+ ERR_FAIL_COND_MSG(name_len > uint32_t(p_packet_len - ofs), vformat("Invalid spawn packet size: %d, wants: %d", p_packet_len, ofs + name_len));
+ ERR_FAIL_COND_MSG(name_len < 1, "Zero spawn name size.");
+
+ const String name = String::utf8((const char *)&p_packet[ofs], name_len);
+ // We need to make sure no trickery happens here (e.g. despawning a subpath), but we want to allow autogenerated ("@") node names.
+ ERR_FAIL_COND_MSG(name.validate_node_name() != name.replace("@", ""), vformat("Invalid node name received: '%s'", name));
+ ofs += name_len;
+
+ const SceneConfig &cfg = replications[p_scene_id];
+ if (cfg.mode == REPLICATION_MODE_SERVER && p_from == 1) {
+ String scene_path = ResourceUID::get_singleton()->get_id_path(p_scene_id);
+ if (p_spawn) {
+ const bool is_raw = ((p_packet[0] & 64) >> MultiplayerAPI::BYTE_ONLY_OR_NO_ARGS_SHIFT) == 1;
+
+ ERR_FAIL_COND_MSG(parent->has_node(name), vformat("Unable to spawn node. Node already exists: %s/%s", parent->get_path(), name));
+ RES res = ResourceLoader::load(scene_path);
+ ERR_FAIL_COND_MSG(!res.is_valid(), "Unable to load scene to spawn at path: " + scene_path);
+ PackedScene *scene = Object::cast_to<PackedScene>(res.ptr());
+ ERR_FAIL_COND(!scene);
+ Node *node = scene->instantiate();
+ ERR_FAIL_COND(!node);
+ replicated_nodes[node->get_instance_id()] = p_scene_id;
+ int size;
+ _decode_state(cfg.properties, node, &p_packet[ofs], p_packet_len - ofs, size, is_raw);
+ parent->_add_child_nocheck(node, name);
+ emit_signal(SNAME("spawned"), p_scene_id, node);
+ } else {
+ ERR_FAIL_COND_MSG(!parent->has_node(name), vformat("Path not found: %s/%s", parent->get_path(), name));
+ Node *node = parent->get_node(name);
+ ERR_FAIL_COND_MSG(!replicated_nodes.has(node->get_instance_id()), vformat("Trying to despawn a Node that was not replicated: %s/%s", parent->get_path(), name));
+ emit_signal(SNAME("despawned"), p_scene_id, node);
+ replicated_nodes.erase(node->get_instance_id());
+ node->queue_delete();
+ }
+ } else {
+ PackedByteArray data;
+ if (p_packet_len > ofs) {
+ data.resize(p_packet_len - ofs);
+ memcpy(data.ptrw(), &p_packet[ofs], data.size());
+ }
+ if (p_spawn) {
+ emit_signal(SNAME("spawn_requested"), p_from, p_scene_id, parent, name, data);
+ } else {
+ emit_signal(SNAME("despawn_requested"), p_from, p_scene_id, parent, name, data);
+ }
+ }
+}
+
+void MultiplayerReplicator::process_spawn_despawn(int p_from, const uint8_t *p_packet, int p_packet_len, bool p_spawn) {
+ ERR_FAIL_COND_MSG(p_packet_len < SPAWN_CMD_OFFSET, "Invalid spawn packet received");
+ ResourceUID::ID id = decode_uint64(&p_packet[1]);
+ ERR_FAIL_COND_MSG(!replications.has(id), "Invalid spawn ID received " + itos(id));
+
+ const SceneConfig &cfg = replications[id];
+ if (cfg.on_spawn_despawn_receive.is_valid()) {
+ int ofs = SPAWN_CMD_OFFSET;
+ bool is_raw = ((p_packet[0] & 64) >> MultiplayerAPI::BYTE_ONLY_OR_NO_ARGS_SHIFT) == 1;
+ Variant data;
+ int left = p_packet_len - ofs;
+ if (is_raw && left) {
+ PackedByteArray pba;
+ pba.resize(left);
+ memcpy(pba.ptrw(), &p_packet[ofs], pba.size());
+ data = pba;
+ } else if (left) {
+ ERR_FAIL_COND(decode_variant(data, &p_packet[ofs], left) != OK);
+ }
+
+ Variant args[4];
+ args[0] = p_from;
+ args[1] = id;
+ args[2] = data;
+ args[3] = p_spawn;
+ const Variant *argp[] = { &args[0], &args[1], &args[2], &args[3] };
+ Callable::CallError ce;
+ Variant ret;
+ cfg.on_spawn_despawn_receive.call(argp, 4, ret, ce);
+ ERR_FAIL_COND_MSG(ce.error != Callable::CallError::CALL_OK, "Custom receive function failed");
+ } else {
+ _process_default_spawn_despawn(p_from, id, p_packet, p_packet_len, p_spawn);
+ }
+}
+
+Error MultiplayerReplicator::_get_state(const List<StringName> &p_properties, const Object *p_obj, List<Variant> &r_variant) {
+ ERR_FAIL_COND_V_MSG(!p_obj, ERR_INVALID_PARAMETER, "Cannot encode null object");
+ for (const StringName &prop : p_properties) {
+ bool valid = false;
+ const Variant v = p_obj->get(prop, &valid);
+ ERR_FAIL_COND_V_MSG(!valid, ERR_INVALID_DATA, vformat("Property '%s' not found.", prop));
+ r_variant.push_back(v);
+ }
+ return OK;
+}
+
+Error MultiplayerReplicator::_encode_state(const List<Variant> &p_variants, uint8_t *p_buffer, int &r_len, bool *r_raw) {
+ r_len = 0;
+ int size = 0;
+
+ // Try raw encoding optimization.
+ if (r_raw && p_variants.size() == 1) {
+ *r_raw = false;
+ const Variant v = p_variants[0];
+ if (v.get_type() == Variant::PACKED_BYTE_ARRAY) {
+ *r_raw = true;
+ const PackedByteArray pba = v;
+ if (p_buffer) {
+ memcpy(p_buffer, pba.ptr(), pba.size());
+ }
+ r_len += pba.size();
+ } else {
+ multiplayer->encode_and_compress_variant(v, p_buffer, size);
+ r_len += size;
+ }
+ return OK;
+ }
+
+ // Regular encoding.
+ for (const Variant &v : p_variants) {
+ multiplayer->encode_and_compress_variant(v, p_buffer ? p_buffer + r_len : nullptr, size);
+ r_len += size;
+ }
+ return OK;
+}
+
+Error MultiplayerReplicator::_decode_state(const List<StringName> &p_properties, Object *p_obj, const uint8_t *p_buffer, int p_len, int &r_len, bool p_raw) {
+ r_len = 0;
+ int argc = p_properties.size();
+ if (argc == 0 && p_raw) {
+ ERR_FAIL_COND_V_MSG(p_len != 0, ERR_INVALID_DATA, "Buffer has trailing bytes.");
+ return OK;
+ }
+ ERR_FAIL_COND_V(p_raw && argc != 1, ERR_INVALID_DATA);
+ if (p_raw) {
+ r_len = p_len;
+ PackedByteArray pba;
+ pba.resize(p_len);
+ memcpy(pba.ptrw(), p_buffer, p_len);
+ p_obj->set(p_properties[0], pba);
+ return OK;
+ }
+
+ Vector<Variant> args;
+ Vector<const Variant *> argp;
+ args.resize(argc);
+
+ for (int i = 0; i < argc; i++) {
+ ERR_FAIL_COND_V_MSG(r_len >= p_len, ERR_INVALID_DATA, "Invalid packet received. Size too small.");
+
+ int vlen;
+ Error err = multiplayer->decode_and_decompress_variant(args.write[i], &p_buffer[r_len], p_len - r_len, &vlen);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Invalid packet received. Unable to decode state variable.");
+ r_len += vlen;
+ }
+ ERR_FAIL_COND_V_MSG(p_len - r_len != 0, ERR_INVALID_DATA, "Buffer has trailing bytes.");
+
+ int i = 0;
+ for (const StringName &prop : p_properties) {
+ p_obj->set(prop, args[i]);
+ i += 1;
+ }
+ return OK;
+}
+
+Error MultiplayerReplicator::spawn_config(const ResourceUID::ID &p_id, ReplicationMode p_mode, const TypedArray<StringName> &p_props, const Callable &p_on_send, const Callable &p_on_recv) {
+ ERR_FAIL_COND_V(p_mode < REPLICATION_MODE_NONE || p_mode > REPLICATION_MODE_CUSTOM, ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V(!ResourceUID::get_singleton()->has_id(p_id), ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V_MSG(p_on_send.is_valid() != p_on_recv.is_valid(), ERR_INVALID_PARAMETER, "Send and receive custom callables must be both valid or both empty");
+#ifdef TOOLS_ENABLED
+ if (!p_on_send.is_valid()) {
+ // We allow non scene spawning with custom callables.
+ String path = ResourceUID::get_singleton()->get_id_path(p_id);
+ RES res = ResourceLoader::load(path);
+ ERR_FAIL_COND_V(!res->is_class("PackedScene"), ERR_INVALID_PARAMETER);
+ }
+#endif
+ if (p_mode == REPLICATION_MODE_NONE) {
+ if (replications.has(p_id)) {
+ replications.erase(p_id);
+ }
+ } else {
+ SceneConfig cfg;
+ cfg.mode = p_mode;
+ for (int i = 0; i < p_props.size(); i++) {
+ cfg.properties.push_back(StringName(p_props[i]));
+ }
+ cfg.on_spawn_despawn_send = p_on_send;
+ cfg.on_spawn_despawn_receive = p_on_recv;
+ replications[p_id] = cfg;
+ }
+ return OK;
+}
+
+Error MultiplayerReplicator::_send_spawn_despawn(int p_peer_id, const ResourceUID::ID &p_scene_id, const Variant &p_data, bool p_spawn) {
+ int data_size = 0;
+ int is_raw = false;
+ if (p_data.get_type() == Variant::PACKED_BYTE_ARRAY) {
+ const PackedByteArray pba = p_data;
+ is_raw = true;
+ data_size = p_data.operator PackedByteArray().size();
+ } else if (p_data.get_type() == Variant::NIL) {
+ is_raw = true;
+ } else {
+ Error err = encode_variant(p_data, nullptr, data_size);
+ ERR_FAIL_COND_V(err, err);
+ }
+ MAKE_ROOM(SPAWN_CMD_OFFSET + data_size);
+ uint8_t *ptr = packet_cache.ptrw();
+ ptr[0] = (p_spawn ? MultiplayerAPI::NETWORK_COMMAND_SPAWN : MultiplayerAPI::NETWORK_COMMAND_DESPAWN) + ((is_raw ? 1 : 0) << MultiplayerAPI::BYTE_ONLY_OR_NO_ARGS_SHIFT);
+ encode_uint64(p_scene_id, &ptr[1]);
+ if (p_data.get_type() == Variant::PACKED_BYTE_ARRAY) {
+ const PackedByteArray pba = p_data;
+ memcpy(&ptr[SPAWN_CMD_OFFSET], pba.ptr(), pba.size());
+ } else if (data_size) {
+ encode_variant(p_data, &ptr[SPAWN_CMD_OFFSET], data_size);
+ }
+ Ref<MultiplayerPeer> network_peer = multiplayer->get_network_peer();
+ network_peer->set_target_peer(p_peer_id);
+ network_peer->set_transfer_channel(0);
+ network_peer->set_transfer_mode(MultiplayerPeer::TRANSFER_MODE_RELIABLE);
+ return network_peer->put_packet(ptr, SPAWN_CMD_OFFSET + data_size);
+}
+
+Error MultiplayerReplicator::send_despawn(int p_peer_id, const ResourceUID::ID &p_scene_id, const Variant &p_data, const NodePath &p_path) {
+ ERR_FAIL_COND_V_MSG(!replications.has(p_scene_id), ERR_INVALID_PARAMETER, vformat("Spawnable not found: %d", p_scene_id));
+ const SceneConfig &cfg = replications[p_scene_id];
+ if (cfg.on_spawn_despawn_send.is_valid()) {
+ return _send_spawn_despawn(p_peer_id, p_scene_id, p_data, true);
+ } else {
+ ERR_FAIL_COND_V_MSG(cfg.mode == REPLICATION_MODE_SERVER && multiplayer->is_network_server(), ERR_UNAVAILABLE, "Manual despawn is restricted in default server mode implementation. Use custom mode if you desire control over server spawn requests.");
+ NodePath path = p_path;
+ Object *obj = p_data.get_type() == Variant::OBJECT ? p_data.get_validated_object() : nullptr;
+ if (path.is_empty() && obj) {
+ Node *node = Object::cast_to<Node>(obj);
+ if (node && node->is_inside_tree()) {
+ path = node->get_path();
+ }
+ }
+ ERR_FAIL_COND_V_MSG(path.is_empty(), ERR_INVALID_PARAMETER, "Despawn default implementation requires a despawn path, or the data to be a node inside the SceneTree");
+ return _send_default_spawn_despawn(p_peer_id, p_scene_id, obj, path, false);
+ }
+}
+
+Error MultiplayerReplicator::send_spawn(int p_peer_id, const ResourceUID::ID &p_scene_id, const Variant &p_data, const NodePath &p_path) {
+ ERR_FAIL_COND_V_MSG(!replications.has(p_scene_id), ERR_INVALID_PARAMETER, vformat("Spawnable not found: %d", p_scene_id));
+ const SceneConfig &cfg = replications[p_scene_id];
+ if (cfg.on_spawn_despawn_send.is_valid()) {
+ return _send_spawn_despawn(p_peer_id, p_scene_id, p_data, false);
+ } else {
+ ERR_FAIL_COND_V_MSG(cfg.mode == REPLICATION_MODE_SERVER && multiplayer->is_network_server(), ERR_UNAVAILABLE, "Manual spawn is restricted in default server mode implementation. Use custom mode if you desire control over server spawn requests.");
+ NodePath path = p_path;
+ Object *obj = p_data.get_type() == Variant::OBJECT ? p_data.get_validated_object() : nullptr;
+ ERR_FAIL_COND_V_MSG(!obj, ERR_INVALID_PARAMETER, "Spawn default implementation requires the data to be an object.");
+ if (path.is_empty()) {
+ Node *node = Object::cast_to<Node>(obj);
+ if (node && node->is_inside_tree()) {
+ path = node->get_path();
+ }
+ }
+ ERR_FAIL_COND_V_MSG(path.is_empty(), ERR_INVALID_PARAMETER, "Spawn default implementation requires a spawn path, or the data to be a node inside the SceneTree");
+ return _send_default_spawn_despawn(p_peer_id, p_scene_id, obj, path, true);
+ }
+}
+
+Error MultiplayerReplicator::_spawn_despawn(ResourceUID::ID p_scene_id, Object *p_obj, int p_peer, bool p_spawn) {
+ ERR_FAIL_COND_V_MSG(!replications.has(p_scene_id), ERR_INVALID_PARAMETER, vformat("Spawnable not found: %d", p_scene_id));
+
+ const SceneConfig &cfg = replications[p_scene_id];
+ if (cfg.on_spawn_despawn_send.is_valid()) {
+ Variant args[4];
+ args[0] = p_peer;
+ args[1] = p_scene_id;
+ args[2] = p_obj;
+ args[3] = true;
+ const Variant *argp[] = { &args[0], &args[1], &args[2], &args[3] };
+ Callable::CallError ce;
+ Variant ret;
+ cfg.on_spawn_despawn_send.call(argp, 4, ret, ce);
+ ERR_FAIL_COND_V_MSG(ce.error != Callable::CallError::CALL_OK, FAILED, "Custom send function failed");
+ return OK;
+ } else {
+ Node *node = Object::cast_to<Node>(p_obj);
+ ERR_FAIL_COND_V_MSG(!p_obj, ERR_INVALID_PARAMETER, "Only nodes can be replicated by the default implementation");
+ return _send_default_spawn_despawn(p_peer, p_scene_id, node, node->get_path(), p_spawn);
+ }
+}
+
+Error MultiplayerReplicator::spawn(ResourceUID::ID p_scene_id, Object *p_obj, int p_peer) {
+ return _spawn_despawn(p_scene_id, p_obj, p_peer, true);
+}
+
+Error MultiplayerReplicator::despawn(ResourceUID::ID p_scene_id, Object *p_obj, int p_peer) {
+ return _spawn_despawn(p_scene_id, p_obj, p_peer, false);
+}
+
+PackedByteArray MultiplayerReplicator::encode_state(const ResourceUID::ID &p_scene_id, const Object *p_obj) {
+ PackedByteArray state;
+ ERR_FAIL_COND_V_MSG(!replications.has(p_scene_id), state, vformat("Spawnable not found: %d", p_scene_id));
+ const SceneConfig &cfg = replications[p_scene_id];
+ int len = 0;
+ List<Variant> state_vars;
+ Error err = _get_state(cfg.properties, p_obj, state_vars);
+ ERR_FAIL_COND_V_MSG(err != OK, state, "Unable to retrieve object state.");
+ err = _encode_state(state_vars, nullptr, len);
+ ERR_FAIL_COND_V_MSG(err != OK, state, "Unable to encode object state.");
+ state.resize(len);
+ _encode_state(state_vars, state.ptrw(), len);
+ return state;
+}
+
+Error MultiplayerReplicator::decode_state(const ResourceUID::ID &p_scene_id, Object *p_obj, const PackedByteArray p_data) {
+ ERR_FAIL_COND_V_MSG(!replications.has(p_scene_id), ERR_INVALID_PARAMETER, vformat("Spawnable not found: %d", p_scene_id));
+ const SceneConfig &cfg = replications[p_scene_id];
+ int size;
+ return _decode_state(cfg.properties, p_obj, p_data.ptr(), p_data.size(), size);
+}
+
+void MultiplayerReplicator::scene_enter_exit_notify(const String &p_scene, Node *p_node, bool p_enter) {
+ if (!multiplayer->has_network_peer()) {
+ return;
+ }
+ Node *root_node = multiplayer->get_root_node();
+ ERR_FAIL_COND(!p_node || !p_node->get_parent() || !root_node);
+ NodePath path = (root_node->get_path()).rel_path_to(p_node->get_parent()->get_path());
+ if (path.is_empty()) {
+ return;
+ }
+ ResourceUID::ID id = ResourceLoader::get_resource_uid(p_scene);
+ if (!replications.has(id)) {
+ return;
+ }
+ const SceneConfig &cfg = replications[id];
+ if (p_enter) {
+ if (cfg.mode == REPLICATION_MODE_SERVER && multiplayer->is_network_server()) {
+ replicated_nodes[p_node->get_instance_id()] = id;
+ spawn(id, p_node, 0);
+ }
+ emit_signal(SNAME("replicated_instance_added"), id, p_node);
+ } else {
+ if (cfg.mode == REPLICATION_MODE_SERVER && multiplayer->is_network_server() && replicated_nodes.has(p_node->get_instance_id())) {
+ replicated_nodes.erase(p_node->get_instance_id());
+ despawn(id, p_node, 0);
+ }
+ emit_signal(SNAME("replicated_instance_removed"), id, p_node);
+ }
+}
+
+void MultiplayerReplicator::spawn_all(int p_peer) {
+ for (const KeyValue<ObjectID, ResourceUID::ID> &E : replicated_nodes) {
+ // Only server mode adds to replicated_nodes, no need to check it.
+ Object *obj = ObjectDB::get_instance(E.key);
+ ERR_CONTINUE(!obj);
+ Node *node = Object::cast_to<Node>(obj);
+ ERR_CONTINUE(!node);
+ spawn(E.value, node, p_peer);
+ }
+}
+
+void MultiplayerReplicator::clear() {
+ replicated_nodes.clear();
+}
+
+void MultiplayerReplicator::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("spawn_config", "scene_id", "spawn_mode", "properties", "custom_send", "custom_receive"), &MultiplayerReplicator::spawn_config, DEFVAL(TypedArray<StringName>()), DEFVAL(Callable()), DEFVAL(Callable()));
+ ClassDB::bind_method(D_METHOD("despawn", "scene_id", "object", "peer_id"), &MultiplayerReplicator::despawn, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("spawn", "scene_id", "object", "peer_id"), &MultiplayerReplicator::spawn, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("send_despawn", "peer_id", "scene_id", "data", "path"), &MultiplayerReplicator::send_despawn, DEFVAL(Variant()), DEFVAL(NodePath()));
+ ClassDB::bind_method(D_METHOD("send_spawn", "peer_id", "scene_id", "data", "path"), &MultiplayerReplicator::send_spawn, DEFVAL(Variant()), DEFVAL(NodePath()));
+ ClassDB::bind_method(D_METHOD("encode_state", "scene_id", "object"), &MultiplayerReplicator::encode_state);
+ ClassDB::bind_method(D_METHOD("decode_state", "scene_id", "object", "data"), &MultiplayerReplicator::decode_state);
+
+ ADD_SIGNAL(MethodInfo("despawned", PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
+ ADD_SIGNAL(MethodInfo("spawned", PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
+ ADD_SIGNAL(MethodInfo("despawn_requested", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "parent", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data")));
+ ADD_SIGNAL(MethodInfo("spawn_requested", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "parent", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data")));
+ ADD_SIGNAL(MethodInfo("replicated_instance_added", PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
+ ADD_SIGNAL(MethodInfo("replicated_instance_removed", PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
+
+ BIND_ENUM_CONSTANT(REPLICATION_MODE_NONE);
+ BIND_ENUM_CONSTANT(REPLICATION_MODE_SERVER);
+ BIND_ENUM_CONSTANT(REPLICATION_MODE_CUSTOM);
+}
diff --git a/core/io/multiplayer_replicator.h b/core/io/multiplayer_replicator.h
new file mode 100644
index 0000000000..e19dd80602
--- /dev/null
+++ b/core/io/multiplayer_replicator.h
@@ -0,0 +1,99 @@
+/*************************************************************************/
+/* multiplayer_replicator.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef MULTIPLAYER_REPLICATOR_H
+#define MULTIPLAYER_REPLICATOR_H
+
+#include "core/io/multiplayer_api.h"
+#include "core/variant/typed_array.h"
+
+class MultiplayerReplicator : public Object {
+ GDCLASS(MultiplayerReplicator, Object);
+
+public:
+ enum {
+ SPAWN_CMD_OFFSET = 9,
+ };
+
+ enum ReplicationMode {
+ REPLICATION_MODE_NONE,
+ REPLICATION_MODE_SERVER,
+ REPLICATION_MODE_CUSTOM,
+ };
+
+ struct SceneConfig {
+ ReplicationMode mode;
+ List<StringName> properties;
+ Callable on_spawn_despawn_send;
+ Callable on_spawn_despawn_receive;
+ };
+
+protected:
+ static void _bind_methods();
+
+private:
+ MultiplayerAPI *multiplayer = nullptr;
+ Vector<uint8_t> packet_cache;
+ Map<ResourceUID::ID, SceneConfig> replications;
+ Map<ObjectID, ResourceUID::ID> replicated_nodes;
+
+ Error _encode_state(const List<Variant> &p_variants, uint8_t *p_buffer, int &r_len, bool *r_raw = nullptr);
+ Error _decode_state(const List<StringName> &p_cfg, Object *p_obj, const uint8_t *p_buffer, int p_len, int &r_len, bool p_raw = false);
+ Error _get_state(const List<StringName> &p_properties, const Object *p_obj, List<Variant> &r_variant);
+ Error _spawn_despawn(ResourceUID::ID p_scene_id, Object *p_obj, int p_peer, bool p_spawn);
+ Error _send_spawn_despawn(int p_peer_id, const ResourceUID::ID &p_scene_id, const Variant &p_data, bool p_spawn);
+ void _process_default_spawn_despawn(int p_from, const ResourceUID::ID &p_scene_id, const uint8_t *p_packet, int p_packet_len, bool p_spawn);
+ Error _send_default_spawn_despawn(int p_peer_id, const ResourceUID::ID &p_scene_id, Object *p_obj, const NodePath &p_path, bool p_spawn);
+
+public:
+ void clear();
+
+ Error spawn_config(const ResourceUID::ID &p_id, ReplicationMode p_mode, const TypedArray<StringName> &p_props = TypedArray<StringName>(), const Callable &p_on_send = Callable(), const Callable &p_on_recv = Callable());
+ Error spawn(ResourceUID::ID p_scene_id, Object *p_obj, int p_peer = 0);
+ Error despawn(ResourceUID::ID p_scene_id, Object *p_obj, int p_peer = 0);
+
+ Error send_despawn(int p_peer_id, const ResourceUID::ID &p_scene_id, const Variant &p_data = Variant(), const NodePath &p_path = NodePath());
+ Error send_spawn(int p_peer_id, const ResourceUID::ID &p_scene_id, const Variant &p_data = Variant(), const NodePath &p_path = NodePath());
+ PackedByteArray encode_state(const ResourceUID::ID &p_scene_id, const Object *p_node);
+ Error decode_state(const ResourceUID::ID &p_scene_id, Object *p_node, PackedByteArray p_data);
+
+ // Used by MultiplayerAPI
+ void spawn_all(int p_peer);
+ void process_spawn_despawn(int p_from, const uint8_t *p_packet, int p_packet_len, bool p_spawn);
+ void scene_enter_exit_notify(const String &p_scene, Node *p_node, bool p_enter);
+
+ MultiplayerReplicator(MultiplayerAPI *p_multiplayer) {
+ multiplayer = p_multiplayer;
+ }
+};
+
+VARIANT_ENUM_CAST(MultiplayerReplicator::ReplicationMode);
+
+#endif // MULTIPLAYER_REPLICATOR_H
diff --git a/core/io/resource.cpp b/core/io/resource.cpp
index 0262655927..87b4d7195d 100644
--- a/core/io/resource.cpp
+++ b/core/io/resource.cpp
@@ -352,9 +352,8 @@ Node *Resource::get_local_scene() const {
}
void Resource::setup_local_to_scene() {
- if (get_script_instance()) {
- get_script_instance()->call("_setup_local_to_scene");
- }
+ // Can't use GDVIRTUAL in Resource, so this will have to be done with a signal
+ emit_signal(SNAME("setup_local_to_scene_requested"));
}
Node *(*Resource::_get_local_scene_func)() = nullptr;
@@ -422,12 +421,12 @@ void Resource::_bind_methods() {
ClassDB::bind_method(D_METHOD("duplicate", "subresources"), &Resource::duplicate, DEFVAL(false));
ADD_SIGNAL(MethodInfo("changed"));
+ ADD_SIGNAL(MethodInfo("setup_local_to_scene_requested"));
+
ADD_GROUP("Resource", "resource_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "resource_local_to_scene"), "set_local_to_scene", "is_local_to_scene");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "resource_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_path", "get_path");
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "resource_name"), "set_name", "get_name");
-
- BIND_VMETHOD(MethodInfo("_setup_local_to_scene"));
}
Resource::Resource() :
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index d02d827443..64237f3b15 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -68,25 +68,28 @@ bool ResourceFormatLoader::recognize_path(const String &p_path, const String &p_
}
bool ResourceFormatLoader::handles_type(const String &p_type) const {
- if (get_script_instance() && get_script_instance()->has_method("_handles_type")) {
- // I guess custom loaders for custom resources should use "Resource"
- return get_script_instance()->call("_handles_type", p_type);
+ bool success;
+ if (GDVIRTUAL_CALL(_handles_type, p_type, success)) {
+ return success;
}
return false;
}
String ResourceFormatLoader::get_resource_type(const String &p_path) const {
- if (get_script_instance() && get_script_instance()->has_method("_get_resource_type")) {
- return get_script_instance()->call("_get_resource_type", p_path);
+ String ret;
+
+ if (GDVIRTUAL_CALL(_get_resource_type, p_path, ret)) {
+ return ret;
}
return "";
}
ResourceUID::ID ResourceFormatLoader::get_resource_uid(const String &p_path) const {
- if (get_script_instance() && get_script_instance()->has_method("_get_resource_uid")) {
- return get_script_instance()->call("_get_resource_uid", p_path);
+ int64_t uid;
+ if (GDVIRTUAL_CALL(_get_resource_uid, p_path, uid)) {
+ return uid;
}
return ResourceUID::INVALID_ID;
@@ -105,27 +108,26 @@ void ResourceLoader::get_recognized_extensions_for_type(const String &p_type, Li
}
bool ResourceFormatLoader::exists(const String &p_path) const {
+ bool success;
+ if (GDVIRTUAL_CALL(_exists, p_path, success)) {
+ return success;
+ }
return FileAccess::exists(p_path); //by default just check file
}
void ResourceFormatLoader::get_recognized_extensions(List<String> *p_extensions) const {
- if (get_script_instance() && get_script_instance()->has_method("_get_recognized_extensions")) {
- PackedStringArray exts = get_script_instance()->call("_get_recognized_extensions");
-
- {
- const String *r = exts.ptr();
- for (int i = 0; i < exts.size(); ++i) {
- p_extensions->push_back(r[i]);
- }
+ PackedStringArray exts;
+ if (GDVIRTUAL_CALL(_get_recognized_extensions, exts)) {
+ const String *r = exts.ptr();
+ for (int i = 0; i < exts.size(); ++i) {
+ p_extensions->push_back(r[i]);
}
}
}
RES ResourceFormatLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
- // Check user-defined loader if there's any. Hard fail if it returns an error.
- if (get_script_instance() && get_script_instance()->has_method("_load")) {
- Variant res = get_script_instance()->call("_load", p_path, p_original_path, p_use_sub_threads, p_cache_mode);
-
+ Variant res;
+ if (GDVIRTUAL_CALL(_load, p_path, p_original_path, p_use_sub_threads, p_cache_mode, res)) {
if (res.get_type() == Variant::INT) { // Error code, abort.
if (r_error) {
*r_error = (Error)res.operator int64_t();
@@ -143,48 +145,42 @@ RES ResourceFormatLoader::load(const String &p_path, const String &p_original_pa
}
void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
- if (get_script_instance() && get_script_instance()->has_method("_get_dependencies")) {
- PackedStringArray deps = get_script_instance()->call("_get_dependencies", p_path, p_add_types);
-
- {
- const String *r = deps.ptr();
- for (int i = 0; i < deps.size(); ++i) {
- p_dependencies->push_back(r[i]);
- }
+ PackedStringArray deps;
+ if (GDVIRTUAL_CALL(_get_dependencies, p_path, p_add_types, deps)) {
+ const String *r = deps.ptr();
+ for (int i = 0; i < deps.size(); ++i) {
+ p_dependencies->push_back(r[i]);
}
}
}
Error ResourceFormatLoader::rename_dependencies(const String &p_path, const Map<String, String> &p_map) {
- if (get_script_instance() && get_script_instance()->has_method("_rename_dependencies")) {
- Dictionary deps_dict;
- for (Map<String, String>::Element *E = p_map.front(); E; E = E->next()) {
- deps_dict[E->key()] = E->value();
- }
+ Dictionary deps_dict;
+ for (Map<String, String>::Element *E = p_map.front(); E; E = E->next()) {
+ deps_dict[E->key()] = E->value();
+ }
- int64_t res = get_script_instance()->call("_rename_dependencies", deps_dict);
- return (Error)res;
+ int64_t err;
+ if (GDVIRTUAL_CALL(_rename_dependencies, p_path, deps_dict, err)) {
+ return (Error)err;
}
return OK;
}
void ResourceFormatLoader::_bind_methods() {
- {
- MethodInfo info = MethodInfo(Variant::NIL, "_load", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "original_path"), PropertyInfo(Variant::BOOL, "use_sub_threads"), PropertyInfo(Variant::INT, "cache_mode"));
- info.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
- BIND_VMETHOD(info);
- }
-
- BIND_VMETHOD(MethodInfo(Variant::PACKED_STRING_ARRAY, "_get_recognized_extensions"));
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "_handles_type", PropertyInfo(Variant::STRING_NAME, "typename")));
- BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_resource_type", PropertyInfo(Variant::STRING, "path")));
- BIND_VMETHOD(MethodInfo("_get_dependencies", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "add_types")));
- BIND_VMETHOD(MethodInfo(Variant::INT, "_rename_dependencies", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "renames")));
-
BIND_ENUM_CONSTANT(CACHE_MODE_IGNORE);
BIND_ENUM_CONSTANT(CACHE_MODE_REUSE);
BIND_ENUM_CONSTANT(CACHE_MODE_REPLACE);
+
+ GDVIRTUAL_BIND(_get_recognized_extensions);
+ GDVIRTUAL_BIND(_handles_type, "type");
+ GDVIRTUAL_BIND(_get_resource_type, "path");
+ GDVIRTUAL_BIND(_get_resource_uid, "path");
+ GDVIRTUAL_BIND(_get_dependencies, "path", "add_types");
+ GDVIRTUAL_BIND(_rename_dependencies, "path", "renames");
+ GDVIRTUAL_BIND(_exists, "path");
+ GDVIRTUAL_BIND(_load, "path", "original_path", "use_sub_threads", "cache_mode");
}
///////////////////////////////////
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index e525e80a9d..f1d9815635 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -32,6 +32,8 @@
#define RESOURCE_LOADER_H
#include "core/io/resource.h"
+#include "core/object/gdvirtual.gen.inc"
+#include "core/object/script_language.h"
#include "core/os/semaphore.h"
#include "core/os/thread.h"
@@ -48,6 +50,16 @@ public:
protected:
static void _bind_methods();
+ GDVIRTUAL0RC(Vector<String>, _get_recognized_extensions)
+ GDVIRTUAL1RC(bool, _handles_type, StringName)
+ GDVIRTUAL1RC(String, _get_resource_type, String)
+ GDVIRTUAL1RC(ResourceUID::ID, _get_resource_uid, String)
+ GDVIRTUAL2RC(Vector<String>, _get_dependencies, String, bool)
+ GDVIRTUAL2RC(int64_t, _rename_dependencies, String, Dictionary)
+ GDVIRTUAL1RC(bool, _exists, String)
+
+ GDVIRTUAL4RC(Variant, _load, String, String, bool, int)
+
public:
virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual bool exists(const String &p_path) const;
diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp
index 564de5ee69..823b5f75b1 100644
--- a/core/io/resource_saver.cpp
+++ b/core/io/resource_saver.cpp
@@ -42,44 +42,37 @@ ResourceSavedCallback ResourceSaver::save_callback = nullptr;
ResourceSaverGetResourceIDForPath ResourceSaver::save_get_id_for_path = nullptr;
Error ResourceFormatSaver::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
- if (get_script_instance() && get_script_instance()->has_method("_save")) {
- return (Error)get_script_instance()->call("_save", p_path, p_resource, p_flags).operator int64_t();
+ int64_t res;
+ if (GDVIRTUAL_CALL(_save, p_path, p_resource, p_flags, res)) {
+ return (Error)res;
}
return ERR_METHOD_NOT_FOUND;
}
bool ResourceFormatSaver::recognize(const RES &p_resource) const {
- if (get_script_instance() && get_script_instance()->has_method("_recognize")) {
- return get_script_instance()->call("_recognize", p_resource);
+ bool success;
+ if (GDVIRTUAL_CALL(_recognize, p_resource, success)) {
+ return success;
}
return false;
}
void ResourceFormatSaver::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const {
- if (get_script_instance() && get_script_instance()->has_method("_get_recognized_extensions")) {
- PackedStringArray exts = get_script_instance()->call("_get_recognized_extensions", p_resource);
-
- {
- const String *r = exts.ptr();
- for (int i = 0; i < exts.size(); ++i) {
- p_extensions->push_back(r[i]);
- }
+ PackedStringArray exts;
+ if (GDVIRTUAL_CALL(_get_recognized_extensions, p_resource, exts)) {
+ const String *r = exts.ptr();
+ for (int i = 0; i < exts.size(); ++i) {
+ p_extensions->push_back(r[i]);
}
}
}
void ResourceFormatSaver::_bind_methods() {
- {
- PropertyInfo arg0 = PropertyInfo(Variant::STRING, "path");
- PropertyInfo arg1 = PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource");
- PropertyInfo arg2 = PropertyInfo(Variant::INT, "flags");
- BIND_VMETHOD(MethodInfo(Variant::INT, "_save", arg0, arg1, arg2));
- }
-
- BIND_VMETHOD(MethodInfo(Variant::PACKED_STRING_ARRAY, "_get_recognized_extensions", PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource")));
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "_recognize", PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource")));
+ GDVIRTUAL_BIND(_save, "path", "resource", "flags");
+ GDVIRTUAL_BIND(_recognize, "resource");
+ GDVIRTUAL_BIND(_get_recognized_extensions, "resource");
}
Error ResourceSaver::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
diff --git a/core/io/resource_saver.h b/core/io/resource_saver.h
index 2fc8d32126..fcde835dab 100644
--- a/core/io/resource_saver.h
+++ b/core/io/resource_saver.h
@@ -32,6 +32,8 @@
#define RESOURCE_SAVER_H
#include "core/io/resource.h"
+#include "core/object/gdvirtual.gen.inc"
+#include "core/object/script_language.h"
class ResourceFormatSaver : public RefCounted {
GDCLASS(ResourceFormatSaver, RefCounted);
@@ -39,6 +41,10 @@ class ResourceFormatSaver : public RefCounted {
protected:
static void _bind_methods();
+ GDVIRTUAL3R(int64_t, _save, String, RES, uint32_t)
+ GDVIRTUAL1RC(bool, _recognize, RES)
+ GDVIRTUAL1RC(Vector<String>, _get_recognized_extensions, RES)
+
public:
virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0);
virtual bool recognize(const RES &p_resource) const;
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp
index 322eb7ac61..b380860522 100644
--- a/core/math/a_star.cpp
+++ b/core/math/a_star.cpp
@@ -382,8 +382,9 @@ bool AStar::_solve(Point *begin_point, Point *end_point) {
}
real_t AStar::_estimate_cost(int p_from_id, int p_to_id) {
- if (get_script_instance() && get_script_instance()->has_method(SceneStringNames::get_singleton()->_estimate_cost)) {
- return get_script_instance()->call(SceneStringNames::get_singleton()->_estimate_cost, p_from_id, p_to_id);
+ real_t scost;
+ if (GDVIRTUAL_CALL(_estimate_cost, p_from_id, p_to_id, scost)) {
+ return scost;
}
Point *from_point;
@@ -398,8 +399,9 @@ real_t AStar::_estimate_cost(int p_from_id, int p_to_id) {
}
real_t AStar::_compute_cost(int p_from_id, int p_to_id) {
- if (get_script_instance() && get_script_instance()->has_method(SceneStringNames::get_singleton()->_compute_cost)) {
- return get_script_instance()->call(SceneStringNames::get_singleton()->_compute_cost, p_from_id, p_to_id);
+ real_t scost;
+ if (GDVIRTUAL_CALL(_compute_cost, p_from_id, p_to_id, scost)) {
+ return scost;
}
Point *from_point;
@@ -557,8 +559,8 @@ void AStar::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_point_path", "from_id", "to_id"), &AStar::get_point_path);
ClassDB::bind_method(D_METHOD("get_id_path", "from_id", "to_id"), &AStar::get_id_path);
- BIND_VMETHOD(MethodInfo(Variant::FLOAT, "_estimate_cost", PropertyInfo(Variant::INT, "from_id"), PropertyInfo(Variant::INT, "to_id")));
- BIND_VMETHOD(MethodInfo(Variant::FLOAT, "_compute_cost", PropertyInfo(Variant::INT, "from_id"), PropertyInfo(Variant::INT, "to_id")));
+ GDVIRTUAL_BIND(_estimate_cost, "from_id", "to_id")
+ GDVIRTUAL_BIND(_compute_cost, "from_id", "to_id")
}
AStar::~AStar() {
@@ -654,8 +656,9 @@ Vector2 AStar2D::get_closest_position_in_segment(const Vector2 &p_point) const {
}
real_t AStar2D::_estimate_cost(int p_from_id, int p_to_id) {
- if (get_script_instance() && get_script_instance()->has_method(SceneStringNames::get_singleton()->_estimate_cost)) {
- return get_script_instance()->call(SceneStringNames::get_singleton()->_estimate_cost, p_from_id, p_to_id);
+ real_t scost;
+ if (GDVIRTUAL_CALL(_estimate_cost, p_from_id, p_to_id, scost)) {
+ return scost;
}
AStar::Point *from_point;
@@ -670,8 +673,9 @@ real_t AStar2D::_estimate_cost(int p_from_id, int p_to_id) {
}
real_t AStar2D::_compute_cost(int p_from_id, int p_to_id) {
- if (get_script_instance() && get_script_instance()->has_method(SceneStringNames::get_singleton()->_compute_cost)) {
- return get_script_instance()->call(SceneStringNames::get_singleton()->_compute_cost, p_from_id, p_to_id);
+ real_t scost;
+ if (GDVIRTUAL_CALL(_compute_cost, p_from_id, p_to_id, scost)) {
+ return scost;
}
AStar::Point *from_point;
@@ -875,6 +879,6 @@ void AStar2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_point_path", "from_id", "to_id"), &AStar2D::get_point_path);
ClassDB::bind_method(D_METHOD("get_id_path", "from_id", "to_id"), &AStar2D::get_id_path);
- BIND_VMETHOD(MethodInfo(Variant::FLOAT, "_estimate_cost", PropertyInfo(Variant::INT, "from_id"), PropertyInfo(Variant::INT, "to_id")));
- BIND_VMETHOD(MethodInfo(Variant::FLOAT, "_compute_cost", PropertyInfo(Variant::INT, "from_id"), PropertyInfo(Variant::INT, "to_id")));
+ GDVIRTUAL_BIND(_estimate_cost, "from_id", "to_id")
+ GDVIRTUAL_BIND(_compute_cost, "from_id", "to_id")
}
diff --git a/core/math/a_star.h b/core/math/a_star.h
index 44758cb046..64fa32a325 100644
--- a/core/math/a_star.h
+++ b/core/math/a_star.h
@@ -31,7 +31,9 @@
#ifndef A_STAR_H
#define A_STAR_H
+#include "core/object/gdvirtual.gen.inc"
#include "core/object/ref_counted.h"
+#include "core/object/script_language.h"
#include "core/templates/oa_hash_map.h"
/**
@@ -122,6 +124,9 @@ protected:
virtual real_t _estimate_cost(int p_from_id, int p_to_id);
virtual real_t _compute_cost(int p_from_id, int p_to_id);
+ GDVIRTUAL2RC(real_t, _estimate_cost, int64_t, int64_t)
+ GDVIRTUAL2RC(real_t, _compute_cost, int64_t, int64_t)
+
public:
int get_available_point_id() const;
@@ -169,6 +174,9 @@ protected:
virtual real_t _estimate_cost(int p_from_id, int p_to_id);
virtual real_t _compute_cost(int p_from_id, int p_to_id);
+ GDVIRTUAL2RC(real_t, _estimate_cost, int64_t, int64_t)
+ GDVIRTUAL2RC(real_t, _compute_cost, int64_t, int64_t)
+
public:
int get_available_point_id() const;
diff --git a/core/math/convex_hull.cpp b/core/math/convex_hull.cpp
index 682a7ea39e..21cb0efe20 100644
--- a/core/math/convex_hull.cpp
+++ b/core/math/convex_hull.cpp
@@ -2278,9 +2278,18 @@ Error ConvexHullComputer::convex_hull(const Vector<Vector3> &p_points, Geometry3
e = e->get_next_edge_of_face();
} while (e != e_start);
+ // reverse indices: Godot wants clockwise, but this is counter-clockwise
+ if (face.indices.size() > 2) {
+ // reverse all but the first index.
+ int *indices = face.indices.ptrw();
+ for (int c = 0; c < (face.indices.size() - 1) / 2; c++) {
+ SWAP(indices[c + 1], indices[face.indices.size() - 1 - c]);
+ }
+ }
+
// compute normal
if (face.indices.size() >= 3) {
- face.plane = Plane(r_mesh.vertices[face.indices[0]], r_mesh.vertices[face.indices[2]], r_mesh.vertices[face.indices[1]]);
+ face.plane = Plane(r_mesh.vertices[face.indices[0]], r_mesh.vertices[face.indices[1]], r_mesh.vertices[face.indices[2]]);
} else {
WARN_PRINT("Too few vertices per face.");
}
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index c58fe7bc24..b29b2bd421 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -1068,6 +1068,20 @@ void ClassDB::set_property_default_value(const StringName &p_class, const String
default_values[p_class][p_name] = p_default;
}
+void ClassDB::add_linked_property(const StringName &p_class, const String &p_property, const String &p_linked_property) {
+#ifdef TOOLS_ENABLED
+ OBJTYPE_WLOCK;
+ ClassInfo *type = classes.getptr(p_class);
+ ERR_FAIL_COND(!type);
+
+ ERR_FAIL_COND(!type->property_map.has(p_property));
+ ERR_FAIL_COND(!type->property_map.has(p_linked_property));
+
+ PropertyInfo &pinfo = type->property_map[p_property];
+ pinfo.linked_properties.push_back(p_linked_property);
+#endif
+}
+
void ClassDB::get_property_list(const StringName &p_class, List<PropertyInfo> *p_list, bool p_no_inheritance, const Object *p_validator) {
OBJTYPE_RLOCK;
@@ -1407,7 +1421,7 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const c
return p_bind;
}
-void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_method, bool p_virtual) {
+void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_method, bool p_virtual, const Vector<String> &p_arg_names, bool p_object_core) {
ERR_FAIL_COND_MSG(!classes.has(p_class), "Request for nonexistent class '" + p_class + "'.");
OBJTYPE_WLOCK;
@@ -1417,6 +1431,19 @@ void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_
if (p_virtual) {
mi.flags |= METHOD_FLAG_VIRTUAL;
}
+ if (p_object_core) {
+ mi.flags |= METHOD_FLAG_OBJECT_CORE;
+ }
+ if (p_arg_names.size()) {
+ if (p_arg_names.size() != mi.arguments.size()) {
+ WARN_PRINT("Mismatch argument name count for virtual function: " + String(p_class) + "::" + p_method.name);
+ } else {
+ for (int i = 0; i < p_arg_names.size(); i++) {
+ mi.arguments[i].name = p_arg_names[i];
+ }
+ }
+ }
+
classes[p_class].virtual_methods.push_back(mi);
classes[p_class].virtual_methods_map[p_method.name] = mi;
diff --git a/core/object/class_db.h b/core/object/class_db.h
index bfc9d6f283..45572517be 100644
--- a/core/object/class_db.h
+++ b/core/object/class_db.h
@@ -330,7 +330,7 @@ public:
if (type->method_map.has(p_name)) {
memdelete(bind);
- // overloading not supported
+ // Overloading not supported
ERR_FAIL_V_MSG(nullptr, "Method already bound: " + instance_type + "::" + p_name + ".");
}
type->method_map[p_name] = bind;
@@ -354,6 +354,7 @@ public:
static void add_property_subgroup(const StringName &p_class, const String &p_name, const String &p_prefix = "");
static void add_property(const StringName &p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1);
static void set_property_default_value(const StringName &p_class, const StringName &p_name, const Variant &p_default);
+ static void add_linked_property(const StringName &p_class, const String &p_property, const String &p_linked_property);
static void get_property_list(const StringName &p_class, List<PropertyInfo> *p_list, bool p_no_inheritance = false, const Object *p_validator = nullptr);
static bool get_property_info(const StringName &p_class, const StringName &p_property, PropertyInfo *r_info, bool p_no_inheritance = false, const Object *p_validator = nullptr);
static bool set_property(Object *p_object, const StringName &p_property, const Variant &p_value, bool *r_valid = nullptr);
@@ -371,7 +372,7 @@ public:
static bool get_method_info(const StringName &p_class, const StringName &p_method, MethodInfo *r_info, bool p_no_inheritance = false, bool p_exclude_from_properties = false);
static MethodBind *get_method(const StringName &p_class, const StringName &p_name);
- static void add_virtual_method(const StringName &p_class, const MethodInfo &p_method, bool p_virtual = true);
+ static void add_virtual_method(const StringName &p_class, const MethodInfo &p_method, bool p_virtual = true, const Vector<String> &p_arg_names = Vector<String>(), bool p_object_core = false);
static void get_virtual_methods(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance = false);
static void bind_integer_constant(const StringName &p_class, const StringName &p_enum, const StringName &p_name, int p_constant);
@@ -409,39 +410,28 @@ public:
#ifdef DEBUG_METHODS_ENABLED
#define BIND_CONSTANT(m_constant) \
- ClassDB::bind_integer_constant(get_class_static(), StringName(), #m_constant, m_constant);
+ ::ClassDB::bind_integer_constant(get_class_static(), StringName(), #m_constant, m_constant);
#define BIND_ENUM_CONSTANT(m_constant) \
- ClassDB::bind_integer_constant(get_class_static(), __constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant);
+ ::ClassDB::bind_integer_constant(get_class_static(), __constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant);
#else
#define BIND_CONSTANT(m_constant) \
- ClassDB::bind_integer_constant(get_class_static(), StringName(), #m_constant, m_constant);
+ ::ClassDB::bind_integer_constant(get_class_static(), StringName(), #m_constant, m_constant);
#define BIND_ENUM_CONSTANT(m_constant) \
- ClassDB::bind_integer_constant(get_class_static(), StringName(), #m_constant, m_constant);
-
-#endif
-
-#ifdef TOOLS_ENABLED
-
-#define BIND_VMETHOD(m_method) \
- ClassDB::add_virtual_method(get_class_static(), m_method);
-
-#else
-
-#define BIND_VMETHOD(m_method)
+ ::ClassDB::bind_integer_constant(get_class_static(), StringName(), #m_constant, m_constant);
#endif
#define GDREGISTER_CLASS(m_class) \
if (!GD_IS_DEFINED(ClassDB_Disable_##m_class)) { \
- ClassDB::register_class<m_class>(); \
+ ::ClassDB::register_class<m_class>(); \
}
-#define GDREGISTER_VIRTUAL_CLASS(m_class) \
- if (!GD_IS_DEFINED(ClassDB_Disable_##m_class)) { \
- ClassDB::register_virtual_class<m_class>(); \
+#define GDREGISTER_VIRTUAL_CLASS(m_class) \
+ if (!GD_IS_DEFINED(ClassDB_Disable_##m_class)) { \
+ ::ClassDB::register_virtual_class<m_class>(); \
}
#include "core/disabled_classes.gen.h"
diff --git a/core/object/make_virtuals.py b/core/object/make_virtuals.py
index 2c6b8cddc9..af90593140 100644
--- a/core/object/make_virtuals.py
+++ b/core/object/make_virtuals.py
@@ -1,7 +1,7 @@
proto = """
#define GDVIRTUAL$VER($RET m_name $ARG) \\
-GDNativeExtensionClassCallVirtual _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, #m_name) : (GDNativeExtensionClassCallVirtual) nullptr;\\
StringName _gdvirtual_##m_name##_sn = #m_name;\\
+GDNativeExtensionClassCallVirtual _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, #m_name) : (GDNativeExtensionClassCallVirtual) nullptr;\\
bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
ScriptInstance *script_instance = ((Object*)(this))->get_script_instance();\\
if (script_instance) {\\
@@ -23,6 +23,16 @@ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
\\
return false;\\
}\\
+bool _gdvirtual_##m_name##_overriden() const { \\
+ ScriptInstance *script_instance = ((Object*)(this))->get_script_instance();\\
+ if (script_instance) {\\
+ return script_instance->has_method(_gdvirtual_##m_name##_sn);\\
+ }\\
+ if (_gdvirtual_##m_name) {\\
+ return true;\\
+ }\\
+ return false;\\
+}\\
\\
_FORCE_INLINE_ static MethodInfo _gdvirtual_##m_name##_get_method_info() { \\
MethodInfo method_info;\\
@@ -77,7 +87,7 @@ def generate_version(argcount, const=False, returns=False):
callptrargs += "\t\t"
callptrargsptr += ", "
argtext += "m_type" + str(i + 1)
- callargtext += "const m_type" + str(i + 1) + "& arg" + str(i + 1)
+ callargtext += "m_type" + str(i + 1) + " arg" + str(i + 1)
callsiargs += "Variant(arg" + str(i + 1) + ")"
callsiargptrs += "&vargs[" + str(i) + "]"
callptrargs += (
@@ -103,7 +113,7 @@ def generate_version(argcount, const=False, returns=False):
if returns:
if argcount > 0:
callargtext += ","
- callargtext += " m_ret& r_ret"
+ callargtext += " m_ret& r_ret"
s = s.replace("$CALLSIBEGIN", "Variant ret = ")
s = s.replace("$CALLSIRET", "r_ret = ret;")
s = s.replace("$CALLPTRRETPASS", "&ret")
diff --git a/core/object/method_bind.h b/core/object/method_bind.h
index 92b964772a..b0b379873e 100644
--- a/core/object/method_bind.h
+++ b/core/object/method_bind.h
@@ -43,6 +43,7 @@ enum MethodFlags {
METHOD_FLAG_FROM_SCRIPT = 64,
METHOD_FLAG_VARARG = 128,
METHOD_FLAG_STATIC = 256,
+ METHOD_FLAG_OBJECT_CORE = 512,
METHOD_FLAGS_DEFAULT = METHOD_FLAG_NORMAL,
};
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 2bb4b981b9..3335942fb3 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -1619,22 +1619,25 @@ void Object::_bind_methods() {
ADD_SIGNAL(MethodInfo("script_changed"));
ADD_SIGNAL(MethodInfo("property_list_changed"));
- BIND_VMETHOD(MethodInfo("_notification", PropertyInfo(Variant::INT, "what")));
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "_set", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::NIL, "value")));
+#define BIND_OBJ_CORE_METHOD(m_method) \
+ ::ClassDB::add_virtual_method(get_class_static(), m_method, true, Vector<String>(), true);
+
+ BIND_OBJ_CORE_METHOD(MethodInfo("_notification", PropertyInfo(Variant::INT, "what")));
+ BIND_OBJ_CORE_METHOD(MethodInfo(Variant::BOOL, "_set", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::NIL, "value")));
#ifdef TOOLS_ENABLED
MethodInfo miget("_get", PropertyInfo(Variant::STRING_NAME, "property"));
miget.return_val.name = "Variant";
miget.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
- BIND_VMETHOD(miget);
+ BIND_OBJ_CORE_METHOD(miget);
MethodInfo plget("_get_property_list");
plget.return_val.type = Variant::ARRAY;
- BIND_VMETHOD(plget);
+ BIND_OBJ_CORE_METHOD(plget);
#endif
- BIND_VMETHOD(MethodInfo("_init"));
- BIND_VMETHOD(MethodInfo(Variant::STRING, "_to_string"));
+ BIND_OBJ_CORE_METHOD(MethodInfo("_init"));
+ BIND_OBJ_CORE_METHOD(MethodInfo(Variant::STRING, "_to_string"));
BIND_CONSTANT(NOTIFICATION_POSTINITIALIZE);
BIND_CONSTANT(NOTIFICATION_PREDELETE);
diff --git a/core/object/object.h b/core/object/object.h
index 6523105820..aede48343c 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -137,21 +137,26 @@ enum PropertyUsageFlags {
PROPERTY_USAGE_NOEDITOR = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_NETWORK,
};
-#define ADD_SIGNAL(m_signal) ClassDB::add_signal(get_class_static(), m_signal)
-#define ADD_PROPERTY(m_property, m_setter, m_getter) ClassDB::add_property(get_class_static(), m_property, _scs_create(m_setter), _scs_create(m_getter))
-#define ADD_PROPERTYI(m_property, m_setter, m_getter, m_index) ClassDB::add_property(get_class_static(), m_property, _scs_create(m_setter), _scs_create(m_getter), m_index)
-#define ADD_PROPERTY_DEFAULT(m_property, m_default) ClassDB::set_property_default_value(get_class_static(), m_property, m_default)
-#define ADD_GROUP(m_name, m_prefix) ClassDB::add_property_group(get_class_static(), m_name, m_prefix)
-#define ADD_SUBGROUP(m_name, m_prefix) ClassDB::add_property_subgroup(get_class_static(), m_name, m_prefix)
+#define ADD_SIGNAL(m_signal) ::ClassDB::add_signal(get_class_static(), m_signal)
+#define ADD_PROPERTY(m_property, m_setter, m_getter) ::ClassDB::add_property(get_class_static(), m_property, _scs_create(m_setter), _scs_create(m_getter))
+#define ADD_PROPERTYI(m_property, m_setter, m_getter, m_index) ::ClassDB::add_property(get_class_static(), m_property, _scs_create(m_setter), _scs_create(m_getter), m_index)
+#define ADD_PROPERTY_DEFAULT(m_property, m_default) ::ClassDB::set_property_default_value(get_class_static(), m_property, m_default)
+#define ADD_GROUP(m_name, m_prefix) ::ClassDB::add_property_group(get_class_static(), m_name, m_prefix)
+#define ADD_SUBGROUP(m_name, m_prefix) ::ClassDB::add_property_subgroup(get_class_static(), m_name, m_prefix)
+#define ADD_LINKED_PROPERTY(m_property, m_linked_property) ::ClassDB::add_linked_property(get_class_static(), m_property, m_linked_property)
struct PropertyInfo {
Variant::Type type = Variant::NIL;
String name;
- StringName class_name; //for classes
+ StringName class_name; // For classes
PropertyHint hint = PROPERTY_HINT_NONE;
String hint_string;
uint32_t usage = PROPERTY_USAGE_DEFAULT;
+#ifdef TOOLS_ENABLED
+ Vector<String> linked_properties;
+#endif
+
_FORCE_INLINE_ PropertyInfo added_usage(uint32_t p_fl) const {
PropertyInfo pi = *this;
pi.usage |= p_fl;
@@ -277,7 +282,14 @@ struct ObjectNativeExtension {
};
#define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call(__VA_ARGS__)
-#define GDVIRTUAL_BIND(m_name) ClassDB::add_virtual_method(get_class_static(), _gdvirtual_##m_name##_get_method_info());
+#define GDVIRTUAL_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call(__VA_ARGS__)
+#ifdef DEBUG_METHODS_ENABLED
+#define GDVIRTUAL_BIND(m_name, ...) ::ClassDB::add_virtual_method(get_class_static(), _gdvirtual_##m_name##_get_method_info(), true, sarray(__VA_ARGS__));
+#else
+#define GDVIRTUAL_BIND(m_name, ...)
+#endif
+#define GDVIRTUAL_IS_OVERRIDEN(m_name) _gdvirtual_##m_name##_overriden()
+#define GDVIRTUAL_IS_OVERRIDEN_PTR(m_obj, m_name) m_obj->_gdvirtual_##m_name##_overriden()
/*
the following is an incomprehensible blob of hacks and workarounds to compensate for many of the fallencies in C++. As a plus, this macro pretty much alone defines the object model.
@@ -299,7 +311,7 @@ private:
private: \
void operator=(const m_class &p_rval) {} \
mutable StringName _class_name; \
- friend class ClassDB; \
+ friend class ::ClassDB; \
\
public: \
virtual String get_class() const override { \
@@ -372,7 +384,7 @@ public:
return; \
} \
m_inherits::initialize_class(); \
- ClassDB::_add_class<m_class>(); \
+ ::ClassDB::_add_class<m_class>(); \
if (m_class::_get_bind_methods() != m_inherits::_get_bind_methods()) { \
_bind_methods(); \
} \
@@ -415,13 +427,13 @@ protected:
} \
p_list->push_back(PropertyInfo(Variant::NIL, get_class_static(), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY)); \
if (!_is_gpl_reversed()) { \
- ClassDB::get_property_list(#m_class, p_list, true, this); \
+ ::ClassDB::get_property_list(#m_class, p_list, true, this); \
} \
if (m_class::_get_get_property_list() != m_inherits::_get_get_property_list()) { \
_get_property_list(p_list); \
} \
if (_is_gpl_reversed()) { \
- ClassDB::get_property_list(#m_class, p_list, true, this); \
+ ::ClassDB::get_property_list(#m_class, p_list, true, this); \
} \
if (p_reversed) { \
m_inherits::_get_property_listv(p_list, p_reversed); \
diff --git a/core/object/ref_counted.h b/core/object/ref_counted.h
index e0af2c18bb..f2dd2aa324 100644
--- a/core/object/ref_counted.h
+++ b/core/object/ref_counted.h
@@ -274,8 +274,6 @@ struct PtrToArg<const Ref<T> &> {
}
};
-#ifdef DEBUG_METHODS_ENABLED
-
template <class T>
struct GetTypeInfo<Ref<T>> {
static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
@@ -296,6 +294,4 @@ struct GetTypeInfo<const Ref<T> &> {
}
};
-#endif // DEBUG_METHODS_ENABLED
-
#endif // REF_COUNTED_H
diff --git a/core/object/undo_redo.cpp b/core/object/undo_redo.cpp
index adf068eb2f..b7d2bac96d 100644
--- a/core/object/undo_redo.cpp
+++ b/core/object/undo_redo.cpp
@@ -405,11 +405,11 @@ String UndoRedo::get_current_action_name() const {
return actions[current_action].name;
}
-bool UndoRedo::has_undo() {
+bool UndoRedo::has_undo() const {
return current_action >= 0;
}
-bool UndoRedo::has_redo() {
+bool UndoRedo::has_redo() const {
return (current_action + 1) < actions.size();
}
diff --git a/core/object/undo_redo.h b/core/object/undo_redo.h
index 8f009830e3..d1ce252d86 100644
--- a/core/object/undo_redo.h
+++ b/core/object/undo_redo.h
@@ -121,8 +121,8 @@ public:
String get_action_name(int p_id);
void clear_history(bool p_increase_version = true);
- bool has_undo();
- bool has_redo();
+ bool has_undo() const;
+ bool has_redo() const;
uint64_t get_version() const;
diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp
index 3c0e56f5a8..0ba69a8d47 100644
--- a/core/os/main_loop.cpp
+++ b/core/os/main_loop.cpp
@@ -33,11 +33,6 @@
#include "core/object/script_language.h"
void MainLoop::_bind_methods() {
- BIND_VMETHOD(MethodInfo("_initialize"));
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "_physics_process", PropertyInfo(Variant::FLOAT, "delta")));
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "_process", PropertyInfo(Variant::FLOAT, "delta")));
- BIND_VMETHOD(MethodInfo("_finalize"));
-
BIND_CONSTANT(NOTIFICATION_OS_MEMORY_WARNING);
BIND_CONSTANT(NOTIFICATION_TRANSLATION_CHANGED);
BIND_CONSTANT(NOTIFICATION_WM_ABOUT);
@@ -50,7 +45,12 @@ void MainLoop::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_TEXT_SERVER_CHANGED);
ADD_SIGNAL(MethodInfo("on_request_permissions_result", PropertyInfo(Variant::STRING, "permission"), PropertyInfo(Variant::BOOL, "granted")));
-};
+
+ GDVIRTUAL_BIND(_initialize);
+ GDVIRTUAL_BIND(_physics_process, "delta");
+ GDVIRTUAL_BIND(_process, "delta");
+ GDVIRTUAL_BIND(_finalize);
+}
void MainLoop::set_initialize_script(const Ref<Script> &p_initialize_script) {
initialize_script = p_initialize_script;
@@ -61,30 +61,31 @@ void MainLoop::initialize() {
set_script(initialize_script);
}
- if (get_script_instance()) {
- get_script_instance()->call("_initialize");
- }
+ GDVIRTUAL_CALL(_initialize);
}
bool MainLoop::physics_process(double p_time) {
- if (get_script_instance()) {
- return get_script_instance()->call("_physics_process", p_time);
+ bool quit;
+ if (GDVIRTUAL_CALL(_physics_process, p_time, quit)) {
+ return quit;
}
return false;
}
bool MainLoop::process(double p_time) {
- if (get_script_instance()) {
- return get_script_instance()->call("_process", p_time);
+ bool quit;
+ if (GDVIRTUAL_CALL(_process, p_time, quit)) {
+ return quit;
}
return false;
}
void MainLoop::finalize() {
+ GDVIRTUAL_CALL(_finalize);
+
if (get_script_instance()) {
- get_script_instance()->call("_finalize");
set_script(Variant()); //clear script
}
}
diff --git a/core/os/main_loop.h b/core/os/main_loop.h
index b42e9b18ff..4da01d767e 100644
--- a/core/os/main_loop.h
+++ b/core/os/main_loop.h
@@ -32,6 +32,7 @@
#define MAIN_LOOP_H
#include "core/input/input_event.h"
+#include "core/object/gdvirtual.gen.inc"
#include "core/object/ref_counted.h"
#include "core/object/script_language.h"
@@ -44,6 +45,11 @@ class MainLoop : public Object {
protected:
static void _bind_methods();
+ GDVIRTUAL0(_initialize)
+ GDVIRTUAL1R(bool, _physics_process, double)
+ GDVIRTUAL1R(bool, _process, double)
+ GDVIRTUAL0(_finalize)
+
public:
enum {
//make sure these are replicated in Node
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 76a6da51e1..63390919f4 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -277,18 +277,13 @@ String OS::get_user_data_dir() const {
return ".";
}
-// Android OS path to app's external data storage
-String OS::get_external_data_dir() const {
- return get_user_data_dir();
-};
-
// Absolute path to res://
String OS::get_resource_dir() const {
return ProjectSettings::get_singleton()->get_resource_path();
}
// Access system-specific dirs like Documents, Downloads, etc.
-String OS::get_system_dir(SystemDir p_dir) const {
+String OS::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
return ".";
}
diff --git a/core/os/os.h b/core/os/os.h
index 0466d94acd..55b21266fc 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -250,7 +250,6 @@ public:
virtual String get_bundle_resource_dir() const;
virtual String get_user_data_dir() const;
- virtual String get_external_data_dir() const;
virtual String get_resource_dir() const;
enum SystemDir {
@@ -264,7 +263,7 @@ public:
SYSTEM_DIR_RINGTONES,
};
- virtual String get_system_dir(SystemDir p_dir) const;
+ virtual String get_system_dir(SystemDir p_dir, bool p_shared_storage = true) const;
virtual Error move_to_trash(const String &p_path) { return FAILED; }
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index f801be3db3..35f4532abb 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -41,6 +41,7 @@
#include "core/extension/native_extension_manager.h"
#include "core/input/input.h"
#include "core/input/input_map.h"
+#include "core/input/shortcut.h"
#include "core/io/config_file.h"
#include "core/io/dtls_server.h"
#include "core/io/http_client.h"
@@ -49,6 +50,7 @@
#include "core/io/marshalls.h"
#include "core/io/multiplayer_api.h"
#include "core/io/multiplayer_peer.h"
+#include "core/io/multiplayer_replicator.h"
#include "core/io/packed_data_container.h"
#include "core/io/packet_peer.h"
#include "core/io/packet_peer_dtls.h"
@@ -84,18 +86,18 @@ static Ref<ResourceFormatSaverCrypto> resource_format_saver_crypto;
static Ref<ResourceFormatLoaderCrypto> resource_format_loader_crypto;
static Ref<NativeExtensionResourceLoader> resource_loader_native_extension;
-static _ResourceLoader *_resource_loader = nullptr;
-static _ResourceSaver *_resource_saver = nullptr;
-static _OS *_os = nullptr;
-static _Engine *_engine = nullptr;
-static _ClassDB *_classdb = nullptr;
-static _Marshalls *_marshalls = nullptr;
-static _EngineDebugger *_engine_debugger = nullptr;
+static core_bind::ResourceLoader *_resource_loader = nullptr;
+static core_bind::ResourceSaver *_resource_saver = nullptr;
+static core_bind::OS *_os = nullptr;
+static core_bind::Engine *_engine = nullptr;
+static core_bind::special::ClassDB *_classdb = nullptr;
+static core_bind::Marshalls *_marshalls = nullptr;
+static core_bind::EngineDebugger *_engine_debugger = nullptr;
static IP *ip = nullptr;
-static _Geometry2D *_geometry_2d = nullptr;
-static _Geometry3D *_geometry_3d = nullptr;
+static core_bind::Geometry2D *_geometry_2d = nullptr;
+static core_bind::Geometry3D *_geometry_3d = nullptr;
extern Mutex _global_mutex;
@@ -144,10 +146,12 @@ void register_core_types() {
GDREGISTER_CLASS(Resource);
GDREGISTER_CLASS(Image);
+ GDREGISTER_CLASS(Shortcut);
GDREGISTER_VIRTUAL_CLASS(InputEvent);
GDREGISTER_VIRTUAL_CLASS(InputEventWithModifiers);
GDREGISTER_VIRTUAL_CLASS(InputEventFromWindow);
GDREGISTER_CLASS(InputEventKey);
+ GDREGISTER_CLASS(InputEventShortcut);
GDREGISTER_VIRTUAL_CLASS(InputEventMouse);
GDREGISTER_CLASS(InputEventMouseButton);
GDREGISTER_CLASS(InputEventMouseMotion);
@@ -193,6 +197,7 @@ void register_core_types() {
ResourceLoader::add_resource_format_loader(resource_format_loader_crypto);
GDREGISTER_VIRTUAL_CLASS(MultiplayerPeer);
+ GDREGISTER_VIRTUAL_CLASS(MultiplayerReplicator);
GDREGISTER_CLASS(MultiplayerAPI);
GDREGISTER_CLASS(MainLoop);
GDREGISTER_CLASS(Translation);
@@ -203,11 +208,11 @@ void register_core_types() {
GDREGISTER_CLASS(ResourceFormatLoader);
GDREGISTER_CLASS(ResourceFormatSaver);
- GDREGISTER_CLASS(_File);
- GDREGISTER_CLASS(_Directory);
- GDREGISTER_CLASS(_Thread);
- GDREGISTER_CLASS(_Mutex);
- GDREGISTER_CLASS(_Semaphore);
+ GDREGISTER_CLASS(core_bind::File);
+ GDREGISTER_CLASS(core_bind::Directory);
+ GDREGISTER_CLASS(core_bind::Thread);
+ GDREGISTER_CLASS(core_bind::Mutex);
+ GDREGISTER_CLASS(core_bind::Semaphore);
GDREGISTER_CLASS(XMLParser);
GDREGISTER_CLASS(JSON);
@@ -240,16 +245,16 @@ void register_core_types() {
ip = IP::create();
- _geometry_2d = memnew(_Geometry2D);
- _geometry_3d = memnew(_Geometry3D);
+ _geometry_2d = memnew(core_bind::Geometry2D);
+ _geometry_3d = memnew(core_bind::Geometry3D);
- _resource_loader = memnew(_ResourceLoader);
- _resource_saver = memnew(_ResourceSaver);
- _os = memnew(_OS);
- _engine = memnew(_Engine);
- _classdb = memnew(_ClassDB);
- _marshalls = memnew(_Marshalls);
- _engine_debugger = memnew(_EngineDebugger);
+ _resource_loader = memnew(core_bind::ResourceLoader);
+ _resource_saver = memnew(core_bind::ResourceSaver);
+ _os = memnew(core_bind::OS);
+ _engine = memnew(core_bind::Engine);
+ _classdb = memnew(core_bind::special::ClassDB);
+ _marshalls = memnew(core_bind::Marshalls);
+ _engine_debugger = memnew(core_bind::EngineDebugger);
}
void register_core_settings() {
@@ -266,35 +271,35 @@ void register_core_settings() {
void register_core_singletons() {
GDREGISTER_CLASS(ProjectSettings);
GDREGISTER_VIRTUAL_CLASS(IP);
- GDREGISTER_CLASS(_Geometry2D);
- GDREGISTER_CLASS(_Geometry3D);
- GDREGISTER_CLASS(_ResourceLoader);
- GDREGISTER_CLASS(_ResourceSaver);
- GDREGISTER_CLASS(_OS);
- GDREGISTER_CLASS(_Engine);
- GDREGISTER_CLASS(_ClassDB);
- GDREGISTER_CLASS(_Marshalls);
+ GDREGISTER_CLASS(core_bind::Geometry2D);
+ GDREGISTER_CLASS(core_bind::Geometry3D);
+ GDREGISTER_CLASS(core_bind::ResourceLoader);
+ GDREGISTER_CLASS(core_bind::ResourceSaver);
+ GDREGISTER_CLASS(core_bind::OS);
+ GDREGISTER_CLASS(core_bind::Engine);
+ GDREGISTER_CLASS(core_bind::special::ClassDB);
+ GDREGISTER_CLASS(core_bind::Marshalls);
GDREGISTER_CLASS(TranslationServer);
GDREGISTER_VIRTUAL_CLASS(Input);
GDREGISTER_CLASS(InputMap);
GDREGISTER_CLASS(Expression);
- GDREGISTER_CLASS(_EngineDebugger);
+ GDREGISTER_CLASS(core_bind::EngineDebugger);
GDREGISTER_CLASS(Time);
Engine::get_singleton()->add_singleton(Engine::Singleton("ProjectSettings", ProjectSettings::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("IP", IP::get_singleton(), "IP"));
- Engine::get_singleton()->add_singleton(Engine::Singleton("Geometry2D", _Geometry2D::get_singleton()));
- Engine::get_singleton()->add_singleton(Engine::Singleton("Geometry3D", _Geometry3D::get_singleton()));
- Engine::get_singleton()->add_singleton(Engine::Singleton("ResourceLoader", _ResourceLoader::get_singleton()));
- Engine::get_singleton()->add_singleton(Engine::Singleton("ResourceSaver", _ResourceSaver::get_singleton()));
- Engine::get_singleton()->add_singleton(Engine::Singleton("OS", _OS::get_singleton()));
- Engine::get_singleton()->add_singleton(Engine::Singleton("Engine", _Engine::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("Geometry2D", core_bind::Geometry2D::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("Geometry3D", core_bind::Geometry3D::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("ResourceLoader", core_bind::ResourceLoader::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("ResourceSaver", core_bind::ResourceSaver::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("OS", core_bind::OS::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("Engine", core_bind::Engine::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("ClassDB", _classdb));
- Engine::get_singleton()->add_singleton(Engine::Singleton("Marshalls", _Marshalls::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("Marshalls", core_bind::Marshalls::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("TranslationServer", TranslationServer::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("Input", Input::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("InputMap", InputMap::get_singleton()));
- Engine::get_singleton()->add_singleton(Engine::Singleton("EngineDebugger", _EngineDebugger::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("EngineDebugger", core_bind::EngineDebugger::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("Time", Time::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("NativeExtensionManager", NativeExtensionManager::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("ResourceUID", ResourceUID::get_singleton()));
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index 2fdf6e84e5..a30d6b9102 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -39,12 +39,9 @@
#include "core/string/ucaps.h"
#include "core/variant/variant.h"
-#include <cstdint>
-
-#ifndef NO_USE_STDLIB
#include <stdio.h>
#include <stdlib.h>
-#endif
+#include <cstdint>
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS // to disable build-time warning which suggested to use strcpy_s instead strcpy
@@ -1393,10 +1390,15 @@ String String::num(double p_num, int p_decimals) {
return "inf";
}
}
-#ifndef NO_USE_STDLIB
if (p_decimals < 0) {
- p_decimals = 14 - (int)floor(log10(p_num));
+ p_decimals = 14;
+ const double abs_num = ABS(p_num);
+ if (abs_num > 10) {
+ // We want to align the digits to the above sane default, so we only
+ // need to subtract log10 for numbers with a positive power of ten.
+ p_decimals -= (int)floor(log10(abs_num));
+ }
}
if (p_decimals > MAX_DECIMALS) {
p_decimals = MAX_DECIMALS;
@@ -1460,87 +1462,6 @@ String String::num(double p_num, int p_decimals) {
}
return buf;
-#else
-
- String s;
- String sd;
- /* integer part */
-
- bool neg = p_num < 0;
- p_num = ABS(p_num);
- int intn = (int)p_num;
-
- /* decimal part */
-
- if (p_decimals > 0 || (p_decimals == -1 && (int)p_num != p_num)) {
- double dec = p_num - (double)((int)p_num);
-
- int digit = 0;
- if (p_decimals > MAX_DECIMALS) {
- p_decimals = MAX_DECIMALS;
- }
-
- int dec_int = 0;
- int dec_max = 0;
-
- while (true) {
- dec *= 10.0;
- dec_int = dec_int * 10 + (int)dec % 10;
- dec_max = dec_max * 10 + 9;
- digit++;
-
- if (p_decimals == -1) {
- if (digit == MAX_DECIMALS) { //no point in going to infinite
- break;
- }
-
- if (dec - (double)((int)dec) < 1e-6) {
- break;
- }
- }
-
- if (digit == p_decimals) {
- break;
- }
- }
- dec *= 10;
- int last = (int)dec % 10;
-
- if (last > 5) {
- if (dec_int == dec_max) {
- dec_int = 0;
- intn++;
- } else {
- dec_int++;
- }
- }
-
- String decimal;
- for (int i = 0; i < digit; i++) {
- char num[2] = { 0, 0 };
- num[0] = '0' + dec_int % 10;
- decimal = num + decimal;
- dec_int /= 10;
- }
- sd = '.' + decimal;
- }
-
- if (intn == 0)
-
- s = "0";
- else {
- while (intn) {
- char32_t num = '0' + (intn % 10);
- intn /= 10;
- s = num + s;
- }
- }
-
- s = s + sd;
- if (neg)
- s = "-" + s;
- return s;
-#endif
}
String String::num_int64(int64_t p_num, int base, bool capitalize_hex) {
@@ -1625,24 +1546,31 @@ String String::num_real(double p_num, bool p_trailing) {
String s;
String sd;
- /* integer part */
+
+ // Integer part.
bool neg = p_num < 0;
p_num = ABS(p_num);
int intn = (int)p_num;
- /* decimal part */
+ // Decimal part.
- if ((int)p_num != p_num) {
- double dec = p_num - (double)((int)p_num);
+ if (intn != p_num) {
+ double dec = p_num - (double)(intn);
int digit = 0;
#if REAL_T_IS_DOUBLE
- int decimals = 14 - (int)floor(log10(p_num));
+ int decimals = 14;
#else
- int decimals = 6 - (int)floor(log10(p_num));
+ int decimals = 6;
#endif
+ // We want to align the digits to the above sane default, so we only
+ // need to subtract log10 for numbers with a positive power of ten.
+ if (p_num > 10) {
+ decimals -= (int)floor(log10(p_num));
+ }
+
if (decimals > MAX_DECIMALS) {
decimals = MAX_DECIMALS;
}
@@ -1720,7 +1648,6 @@ String String::num_scientific(double p_num) {
return "inf";
}
}
-#ifndef NO_USE_STDLIB
char buf[256];
@@ -1743,10 +1670,6 @@ String String::num_scientific(double p_num) {
buf[255] = 0;
return buf;
-#else
-
- return String::num(p_num);
-#endif
}
String String::md5(const uint8_t *p_md5) {
diff --git a/core/variant/type_info.h b/core/variant/type_info.h
index 76cb065d10..b70d29bbac 100644
--- a/core/variant/type_info.h
+++ b/core/variant/type_info.h
@@ -241,14 +241,27 @@ struct GetTypeInfo<const T *, typename EnableIf<TypeInherits<Object, T>::value>:
}
};
-#define TEMPL_MAKE_ENUM_TYPE_INFO(m_enum, m_impl) \
- template <> \
- struct GetTypeInfo<m_impl> { \
- static const Variant::Type VARIANT_TYPE = Variant::INT; \
- static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \
- static inline PropertyInfo get_class_info() { \
- return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_ENUM, String(#m_enum).replace("::", ".")); \
- } \
+namespace godot {
+namespace details {
+inline String enum_qualified_name_to_class_info_name(const String &p_qualified_name) {
+ Vector<String> parts = p_qualified_name.split("::", false);
+ if (parts.size() <= 2)
+ return String(".").join(parts);
+ // Contains namespace. We only want the class and enum names.
+ return parts[parts.size() - 2] + "." + parts[parts.size() - 1];
+}
+} // namespace details
+} // namespace godot
+
+#define TEMPL_MAKE_ENUM_TYPE_INFO(m_enum, m_impl) \
+ template <> \
+ struct GetTypeInfo<m_impl> { \
+ static const Variant::Type VARIANT_TYPE = Variant::INT; \
+ static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \
+ static inline PropertyInfo get_class_info() { \
+ return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_ENUM, \
+ godot::details::enum_qualified_name_to_class_info_name(String(#m_enum))); \
+ } \
};
#define MAKE_ENUM_TYPE_INFO(m_enum) \
diff --git a/core/variant/typed_array.h b/core/variant/typed_array.h
index 900dcf7689..2e96f4e445 100644
--- a/core/variant/typed_array.h
+++ b/core/variant/typed_array.h
@@ -125,7 +125,7 @@ struct PtrToArg<TypedArray<T>> {
_FORCE_INLINE_ static TypedArray<T> convert(const void *p_ptr) {
return TypedArray<T>(*reinterpret_cast<const Array *>(p_ptr));
}
-
+ typedef Array EncodeT;
_FORCE_INLINE_ static void encode(TypedArray<T> p_val, void *p_ptr) {
*(Array *)p_ptr = p_val;
}
@@ -133,13 +133,13 @@ struct PtrToArg<TypedArray<T>> {
template <class T>
struct PtrToArg<const TypedArray<T> &> {
- _FORCE_INLINE_ static TypedArray<T> convert(const void *p_ptr) {
+ typedef Array EncodeT;
+ _FORCE_INLINE_ static TypedArray<T>
+ convert(const void *p_ptr) {
return TypedArray<T>(*reinterpret_cast<const Array *>(p_ptr));
}
};
-#ifdef DEBUG_METHODS_ENABLED
-
template <class T>
struct GetTypeInfo<TypedArray<T>> {
static const Variant::Type VARIANT_TYPE = Variant::ARRAY;
@@ -218,6 +218,4 @@ MAKE_TYPED_ARRAY_INFO(Vector<Vector2>, Variant::PACKED_VECTOR2_ARRAY)
MAKE_TYPED_ARRAY_INFO(Vector<Vector3>, Variant::PACKED_VECTOR3_ARRAY)
MAKE_TYPED_ARRAY_INFO(Vector<Color>, Variant::PACKED_COLOR_ARRAY)
-#endif
-
#endif // TYPED_ARRAY_H
diff --git a/core/variant/variant_internal.h b/core/variant/variant_internal.h
index 566b14736e..40c8a1bfde 100644
--- a/core/variant/variant_internal.h
+++ b/core/variant/variant_internal.h
@@ -104,7 +104,7 @@ public:
init_color_array(v);
break;
case Variant::OBJECT:
- object_assign_null(v);
+ init_object(v);
break;
default:
break;
@@ -280,6 +280,10 @@ public:
v->_data.packed_array = Variant::PackedArrayRef<Color>::create(Vector<Color>());
v->type = Variant::PACKED_COLOR_ARRAY;
}
+ _FORCE_INLINE_ static void init_object(Variant *v) {
+ object_assign_null(v);
+ v->type = Variant::OBJECT;
+ }
_FORCE_INLINE_ static void clear(Variant *v) {
v->clear();
@@ -1173,7 +1177,7 @@ struct VariantInitializer<PackedColorArray> {
template <>
struct VariantInitializer<Object *> {
- static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::object_assign_null(v); }
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_object(v); }
};
template <class T>
@@ -1405,4 +1409,22 @@ struct VariantTypeConstructor {
}
};
+template <>
+struct VariantTypeConstructor<Object *> {
+ _FORCE_INLINE_ static void variant_from_type(void *p_variant, void *p_value) {
+ Variant *variant = reinterpret_cast<Variant *>(p_variant);
+ VariantInitializer<Object *>::init(variant);
+ Object *value = *(reinterpret_cast<Object **>(p_value));
+ if (value) {
+ VariantInternalAccessor<Object *>::set(variant, value);
+ VariantInternalAccessor<ObjectID>::set(variant, value->get_instance_id());
+ }
+ }
+
+ _FORCE_INLINE_ static void type_from_variant(void *p_value, void *p_variant) {
+ Object **value = reinterpret_cast<Object **>(p_value);
+ *value = VariantInternalAccessor<Object *>::get(reinterpret_cast<Variant *>(p_variant));
+ }
+};
+
#endif // VARIANT_INTERNAL_H
diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp
index 50c48fd386..a214a238a6 100644
--- a/core/variant/variant_parser.cpp
+++ b/core/variant/variant_parser.cpp
@@ -1423,7 +1423,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
p_store_string_func(p_store_string_ud, itos(p_variant.operator int64_t()));
} break;
case Variant::FLOAT: {
- String s = rtosfix(p_variant.operator real_t());
+ String s = rtosfix(p_variant.operator double());
if (s != "inf" && s != "nan") {
if (s.find(".") == -1 && s.find("e") == -1) {
s += ".0";