summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/config/project_settings.cpp102
-rw-r--r--core/config/project_settings.h13
-rw-r--r--core/core_bind.cpp17
-rw-r--r--core/core_bind.h5
-rw-r--r--core/core_constants.cpp153
-rw-r--r--core/core_constants.h1
-rw-r--r--core/debugger/script_debugger.cpp4
-rw-r--r--core/debugger/script_debugger.h1
-rw-r--r--core/doc_data.h5
-rw-r--r--core/error/error_macros.h14
-rw-r--r--core/extension/extension_api_dump.cpp5
-rw-r--r--core/extension/gdextension_interface.cpp75
-rw-r--r--core/extension/gdextension_interface.h20
-rw-r--r--core/input/input.cpp25
-rw-r--r--core/input/input.h6
-rw-r--r--core/input/input_builders.py2
-rw-r--r--core/input/input_enums.h59
-rw-r--r--core/input/input_event.cpp67
-rw-r--r--core/input/input_event.h8
-rw-r--r--core/io/config_file.cpp4
-rw-r--r--core/io/file_access.cpp12
-rw-r--r--core/io/file_access.h4
-rw-r--r--core/io/file_access_compressed.cpp16
-rw-r--r--core/io/file_access_compressed.h3
-rw-r--r--core/io/image_loader.cpp4
-rw-r--r--core/io/image_loader.h2
-rw-r--r--core/io/resource.cpp7
-rw-r--r--core/io/resource.h2
-rw-r--r--core/io/resource_format_binary.cpp126
-rw-r--r--core/io/resource_format_binary.h3
-rw-r--r--core/io/resource_importer.cpp16
-rw-r--r--core/io/resource_importer.h8
-rw-r--r--core/io/resource_loader.cpp7
-rw-r--r--core/io/resource_loader.h1
-rw-r--r--core/io/resource_saver.cpp31
-rw-r--r--core/io/resource_saver.h5
-rw-r--r--core/io/xml_parser.cpp10
-rw-r--r--core/io/xml_parser.h4
-rw-r--r--core/math/a_star_grid_2d.cpp2
-rw-r--r--core/math/basis.cpp25
-rw-r--r--core/math/basis.h4
-rw-r--r--core/math/face3.cpp40
-rw-r--r--core/math/face3.h5
-rw-r--r--core/math/geometry_2d.cpp35
-rw-r--r--core/math/geometry_2d.h1
-rw-r--r--core/math/geometry_3d.cpp145
-rw-r--r--core/math/geometry_3d.h2
-rw-r--r--core/math/plane.h2
-rw-r--r--core/math/transform_2d.cpp6
-rw-r--r--core/math/transform_2d.h1
-rw-r--r--core/math/triangle_mesh.cpp196
-rw-r--r--core/math/triangle_mesh.h2
-rw-r--r--core/object/method_bind.h2
-rw-r--r--core/object/object.cpp19
-rw-r--r--core/object/object.h21
-rw-r--r--core/object/script_language.cpp51
-rw-r--r--core/object/script_language.h1
-rw-r--r--core/object/script_language_extension.h3
-rw-r--r--core/os/keyboard.cpp3
-rw-r--r--core/os/keyboard.h5
-rw-r--r--core/os/os.h5
-rw-r--r--core/register_core_types.cpp7
-rw-r--r--core/templates/safe_refcount.h20
-rw-r--r--core/variant/array.cpp10
-rw-r--r--core/variant/binder_common.h39
-rw-r--r--core/variant/callable.cpp53
-rw-r--r--core/variant/callable.h6
-rw-r--r--core/variant/callable_bind.cpp60
-rw-r--r--core/variant/callable_bind.h5
-rw-r--r--core/variant/dictionary.cpp10
-rw-r--r--core/variant/type_info.h9
-rw-r--r--core/variant/variant.cpp92
-rw-r--r--core/variant/variant.h1
-rw-r--r--core/variant/variant_call.cpp5
-rw-r--r--core/variant/variant_parser.cpp21
-rw-r--r--core/variant/variant_setget.cpp21
76 files changed, 895 insertions, 887 deletions
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index 2ce3ce2678..ed89bc15d3 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -33,6 +33,7 @@
#include "core/core_bind.h" // For Compression enum.
#include "core/core_string_names.h"
#include "core/input/input_map.h"
+#include "core/io/config_file.h"
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
#include "core/io/file_access_network.h"
@@ -291,31 +292,26 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
return true;
}
- if (!disable_feature_overrides) {
+ { // Feature overrides.
int dot = p_name.operator String().find(".");
if (dot != -1) {
Vector<String> s = p_name.operator String().split(".");
- bool override_valid = false;
for (int i = 1; i < s.size(); i++) {
String feature = s[i].strip_edges();
- if (OS::get_singleton()->has_feature(feature) || custom_features.has(feature)) {
- override_valid = true;
- break;
+ Pair<StringName, StringName> fo(feature, p_name);
+
+ if (!feature_overrides.has(s[0])) {
+ feature_overrides[s[0]] = LocalVector<Pair<StringName, StringName>>();
}
- }
- if (override_valid) {
- feature_overrides[s[0]] = p_name;
+ feature_overrides[s[0]].push_back(fo);
}
}
}
if (props.has(p_name)) {
- if (!props[p_name].overridden) {
- props[p_name].variant = p_value;
- }
-
+ props[p_name].variant = p_value;
} else {
props[p_name] = VariantContainer(p_value, last_order++);
}
@@ -340,16 +336,35 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
bool ProjectSettings::_get(const StringName &p_name, Variant &r_ret) const {
_THREAD_SAFE_METHOD_
+ if (!props.has(p_name)) {
+ WARN_PRINT("Property not found: " + String(p_name));
+ return false;
+ }
+ r_ret = props[p_name].variant;
+ return true;
+}
+
+Variant ProjectSettings::get_setting_with_override(const StringName &p_name) const {
+ _THREAD_SAFE_METHOD_
+
StringName name = p_name;
- if (!disable_feature_overrides && feature_overrides.has(name)) {
- name = feature_overrides[name];
+ if (feature_overrides.has(name)) {
+ const LocalVector<Pair<StringName, StringName>> &overrides = feature_overrides[name];
+ for (uint32_t i = 0; i < overrides.size(); i++) {
+ if (OS::get_singleton()->has_feature(overrides[i].first)) { // Custom features are checked in OS.has_feature() already. No need to check twice.
+ if (props.has(overrides[i].second)) {
+ name = overrides[i].second;
+ break;
+ }
+ }
+ }
}
+
if (!props.has(name)) {
WARN_PRINT("Property not found: " + String(name));
- return false;
+ return Variant();
}
- r_ret = props[name].variant;
- return true;
+ return props[name].variant;
}
struct _VCSort {
@@ -1054,23 +1069,6 @@ Variant _GLOBAL_DEF(const PropertyInfo &p_info, const Variant &p_default, bool p
return ret;
}
-Vector<String> ProjectSettings::get_optimizer_presets() const {
- List<PropertyInfo> pi;
- ProjectSettings::get_singleton()->get_property_list(&pi);
- Vector<String> names;
-
- for (const PropertyInfo &E : pi) {
- if (!E.name.begins_with("optimizer_presets/")) {
- continue;
- }
- names.push_back(E.name.get_slicec('/', 1));
- }
-
- names.sort();
-
- return names;
-}
-
void ProjectSettings::_add_property_info_bind(const Dictionary &p_info) {
ERR_FAIL_COND(!p_info.has("name"));
ERR_FAIL_COND(!p_info.has("type"));
@@ -1101,10 +1099,6 @@ const HashMap<StringName, PropertyInfo> &ProjectSettings::get_custom_property_in
return custom_prop_info;
}
-void ProjectSettings::set_disable_feature_overrides(bool p_disable) {
- disable_feature_overrides = p_disable;
-}
-
bool ProjectSettings::is_using_datapack() const {
return using_datapack;
}
@@ -1138,6 +1132,29 @@ Variant ProjectSettings::get_setting(const String &p_setting, const Variant &p_d
}
}
+Array ProjectSettings::get_global_class_list() {
+ Array script_classes;
+
+ Ref<ConfigFile> cf;
+ cf.instantiate();
+ if (cf->load(get_project_data_path().path_join("global_script_class_cache.cfg")) == OK) {
+ script_classes = cf->get_value("", "list");
+ } else {
+#ifndef TOOLS_ENABLED
+ // Script classes can't be recreated in exported project, so print an error.
+ ERR_PRINT("Could not load global script cache.");
+#endif
+ }
+ return script_classes;
+}
+
+void ProjectSettings::store_global_class_list(const Array &p_classes) {
+ Ref<ConfigFile> cf;
+ cf.instantiate();
+ cf->set_value("", "list", p_classes);
+ cf->save(get_project_data_path().path_join("global_script_class_cache.cfg"));
+}
+
bool ProjectSettings::has_custom_feature(const String &p_feature) const {
return custom_features.has(p_feature);
}
@@ -1169,6 +1186,7 @@ void ProjectSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_setting", "name"), &ProjectSettings::has_setting);
ClassDB::bind_method(D_METHOD("set_setting", "name", "value"), &ProjectSettings::set_setting);
ClassDB::bind_method(D_METHOD("get_setting", "name", "default_value"), &ProjectSettings::get_setting, DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("get_setting_with_override", "name"), &ProjectSettings::get_setting_with_override);
ClassDB::bind_method(D_METHOD("set_order", "name", "position"), &ProjectSettings::set_order);
ClassDB::bind_method(D_METHOD("get_order", "name"), &ProjectSettings::get_order);
ClassDB::bind_method(D_METHOD("set_initial_value", "name", "value"), &ProjectSettings::set_initial_value);
@@ -1240,6 +1258,14 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF_BASIC("display/window/size/mode", 0);
custom_prop_info["display/window/size/mode"] = PropertyInfo(Variant::INT, "display/window/size/mode", PROPERTY_HINT_ENUM, "Windowed,Minimized,Maximized,Fullscreen,Exclusive Fullscreen");
+ // Keep the enum values in sync with the `DisplayServer::SCREEN_` enum.
+ GLOBAL_DEF_BASIC("display/window/size/initial_screen", -2);
+ String screen_hints = "Primary Monitor:-2"; // Note: Main Window Monitor:-1 is not used for the main window, skip it.
+ for (int i = 0; i < 64; i++) {
+ screen_hints += ",Monitor " + itos(i + 1) + ":" + itos(i);
+ }
+ custom_prop_info["display/window/size/initial_screen"] = PropertyInfo(Variant::INT, "display/window/size/initial_screen", PROPERTY_HINT_ENUM, screen_hints);
+
GLOBAL_DEF_BASIC("display/window/size/resizable", true);
GLOBAL_DEF_BASIC("display/window/size/borderless", false);
GLOBAL_DEF("display/window/size/always_on_top", false);
diff --git a/core/config/project_settings.h b/core/config/project_settings.h
index 2aca1e7691..d1704a7c31 100644
--- a/core/config/project_settings.h
+++ b/core/config/project_settings.h
@@ -34,6 +34,7 @@
#include "core/object/class_db.h"
#include "core/os/thread_safe.h"
#include "core/templates/hash_map.h"
+#include "core/templates/local_vector.h"
#include "core/templates/rb_set.h"
class ProjectSettings : public Object {
@@ -69,7 +70,6 @@ protected:
Variant variant;
Variant initial;
bool hide_from_editor = false;
- bool overridden = false;
bool restart_if_changed = false;
#ifdef DEBUG_METHODS_ENABLED
bool ignore_value_in_docs = false;
@@ -91,12 +91,11 @@ protected:
RBMap<StringName, VariantContainer> props; // NOTE: Key order is used e.g. in the save_custom method.
String resource_path;
HashMap<StringName, PropertyInfo> custom_prop_info;
- bool disable_feature_overrides = false;
bool using_datapack = false;
List<String> input_presets;
HashSet<String> custom_features;
- HashMap<StringName, StringName> feature_overrides;
+ HashMap<StringName, LocalVector<Pair<StringName, StringName>>> feature_overrides;
HashMap<StringName, AutoloadInfo> autoloads;
@@ -142,6 +141,8 @@ public:
void set_setting(const String &p_setting, const Variant &p_value);
Variant get_setting(const String &p_setting, const Variant &p_default_value = Variant()) const;
+ Array get_global_class_list();
+ void store_global_class_list(const Array &p_classes);
bool has_setting(String p_var) const;
String localize_path(const String &p_path) const;
@@ -177,11 +178,9 @@ public:
const HashMap<StringName, PropertyInfo> &get_custom_property_info() const;
uint64_t get_last_saved_time() { return last_save_time; }
- Vector<String> get_optimizer_presets() const;
-
List<String> get_input_presets() const { return input_presets; }
- void set_disable_feature_overrides(bool p_disable);
+ Variant get_setting_with_override(const StringName &p_name) const;
bool is_using_datapack() const;
@@ -205,7 +204,7 @@ Variant _GLOBAL_DEF(const PropertyInfo &p_info, const Variant &p_default, bool p
#define GLOBAL_DEF_RST(m_var, m_value) _GLOBAL_DEF(m_var, m_value, true)
#define GLOBAL_DEF_NOVAL(m_var, m_value) _GLOBAL_DEF(m_var, m_value, false, true)
#define GLOBAL_DEF_RST_NOVAL(m_var, m_value) _GLOBAL_DEF(m_var, m_value, true, true)
-#define GLOBAL_GET(m_var) ProjectSettings::get_singleton()->get(m_var)
+#define GLOBAL_GET(m_var) ProjectSettings::get_singleton()->get_setting_with_override(m_var)
#define GLOBAL_DEF_BASIC(m_var, m_value) _GLOBAL_DEF(m_var, m_value, false, false, true)
#define GLOBAL_DEF_RST_BASIC(m_var, m_value) _GLOBAL_DEF(m_var, m_value, true, false, true)
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index 0ed05a20a2..96e1da9dde 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -257,8 +257,8 @@ Error OS::shell_open(String p_uri) {
return ::OS::get_singleton()->shell_open(p_uri);
}
-String OS::read_string_from_stdin(bool p_block) {
- return ::OS::get_singleton()->get_stdin_string(true);
+String OS::read_string_from_stdin() {
+ return ::OS::get_singleton()->get_stdin_string();
}
int OS::execute(const String &p_path, const Vector<String> &p_arguments, Array r_output, bool p_read_stderr, bool p_open_console) {
@@ -322,8 +322,12 @@ 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);
+void OS::set_environment(const String &p_var, const String &p_value) const {
+ ::OS::get_singleton()->set_environment(p_var, p_value);
+}
+
+void OS::unset_environment(const String &p_var) const {
+ ::OS::get_singleton()->unset_environment(p_var);
}
String OS::get_name() const {
@@ -539,7 +543,7 @@ void OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_system_font_path", "font_name", "weight", "stretch", "italic"), &OS::get_system_font_path, DEFVAL(400), DEFVAL(100), DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_system_font_path_for_text", "font_name", "text", "locale", "script", "weight", "stretch", "italic"), &OS::get_system_font_path_for_text, DEFVAL(String()), DEFVAL(String()), DEFVAL(400), DEFVAL(100), DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_executable_path"), &OS::get_executable_path);
- ClassDB::bind_method(D_METHOD("read_string_from_stdin", "block"), &OS::read_string_from_stdin, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("read_string_from_stdin"), &OS::read_string_from_stdin);
ClassDB::bind_method(D_METHOD("execute", "path", "arguments", "output", "read_stderr", "open_console"), &OS::execute, DEFVAL(Array()), DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("create_process", "path", "arguments", "open_console"), &OS::create_process, DEFVAL(false));
ClassDB::bind_method(D_METHOD("create_instance", "arguments"), &OS::create_instance);
@@ -548,9 +552,10 @@ void OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_process_running", "pid"), &OS::is_process_running);
ClassDB::bind_method(D_METHOD("get_process_id"), &OS::get_process_id);
+ 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("unset_environment", "variable"), &OS::unset_environment);
ClassDB::bind_method(D_METHOD("get_name"), &OS::get_name);
ClassDB::bind_method(D_METHOD("get_distribution_name"), &OS::get_distribution_name);
diff --git a/core/core_bind.h b/core/core_bind.h
index e8c59866e3..c0c87fd009 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -146,7 +146,7 @@ public:
String get_system_font_path(const String &p_font_name, int p_weight = 400, int p_stretch = 100, bool p_italic = false) const;
Vector<String> get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale = String(), const String &p_script = String(), int p_weight = 400, int p_stretch = 100, bool p_italic = false) const;
String get_executable_path() const;
- String read_string_from_stdin(bool p_block = true);
+ String read_string_from_stdin();
int execute(const String &p_path, const Vector<String> &p_arguments, Array r_output = Array(), bool p_read_stderr = false, bool p_open_console = false);
int create_process(const String &p_path, const Vector<String> &p_arguments, bool p_open_console = false);
int create_instance(const Vector<String> &p_arguments);
@@ -162,7 +162,8 @@ public:
bool has_environment(const String &p_var) const;
String get_environment(const String &p_var) const;
- bool set_environment(const String &p_var, const String &p_value) const;
+ void set_environment(const String &p_var, const String &p_value) const;
+ void unset_environment(const String &p_var) const;
String get_name() const;
String get_distribution_name() const;
diff --git a/core/core_constants.cpp b/core/core_constants.cpp
index 500a554a24..edb72f73cb 100644
--- a/core/core_constants.cpp
+++ b/core/core_constants.cpp
@@ -39,6 +39,7 @@ struct _CoreConstant {
#ifdef DEBUG_METHODS_ENABLED
StringName enum_name;
bool ignore_value_in_docs = false;
+ bool is_bitfield = false;
#endif
const char *name = nullptr;
int64_t value = 0;
@@ -46,9 +47,10 @@ struct _CoreConstant {
_CoreConstant() {}
#ifdef DEBUG_METHODS_ENABLED
- _CoreConstant(const StringName &p_enum_name, const char *p_name, int64_t p_value, bool p_ignore_value_in_docs = false) :
+ _CoreConstant(const StringName &p_enum_name, const char *p_name, int64_t p_value, bool p_ignore_value_in_docs = false, bool p_is_bitfield = false) :
enum_name(p_enum_name),
ignore_value_in_docs(p_ignore_value_in_docs),
+ is_bitfield(p_is_bitfield),
name(p_name),
value(p_value) {
}
@@ -70,13 +72,22 @@ static Vector<_CoreConstant> _global_constants;
#define BIND_CORE_ENUM_CONSTANT(m_constant) \
_global_constants.push_back(_CoreConstant(__constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant));
+#define BIND_CORE_BITFIELD_FLAG(m_constant) \
+ _global_constants.push_back(_CoreConstant(__constant_get_bitfield_name(m_constant, #m_constant), #m_constant, m_constant, false, true));
+
// This just binds enum classes as if they were regular enum constants.
#define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \
_global_constants.push_back(_CoreConstant(__constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member), #m_prefix "_" #m_member, (int64_t)m_enum::m_member));
+#define BIND_CORE_BITFIELD_CLASS_FLAG(m_enum, m_prefix, m_member) \
+ _global_constants.push_back(_CoreConstant(__constant_get_bitfield_name(m_enum::m_member, #m_prefix "_" #m_member), #m_prefix "_" #m_member, (int64_t)m_enum::m_member, false, true));
+
#define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \
_global_constants.push_back(_CoreConstant(__constant_get_enum_name(m_enum::m_member, #m_name), #m_name, (int64_t)m_enum::m_member));
+#define BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(m_enum, m_name, m_member) \
+ _global_constants.push_back(_CoreConstant(__constant_get_bitfield_name(m_enum::m_member, #m_name), #m_name, (int64_t)m_enum::m_member, false, true));
+
#define BIND_CORE_ENUM_CLASS_CONSTANT_NO_VAL(m_enum, m_prefix, m_member) \
_global_constants.push_back(_CoreConstant(__constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member), #m_prefix "_" #m_member, (int64_t)m_enum::m_member, true));
@@ -100,13 +111,22 @@ static Vector<_CoreConstant> _global_constants;
#define BIND_CORE_ENUM_CONSTANT(m_constant) \
_global_constants.push_back(_CoreConstant(#m_constant, m_constant));
+#define BIND_CORE_BITFIELD_FLAG(m_constant) \
+ _global_constants.push_back(_CoreConstant(#m_constant, m_constant));
+
// This just binds enum classes as if they were regular enum constants.
#define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \
_global_constants.push_back(_CoreConstant(#m_prefix "_" #m_member, (int64_t)m_enum::m_member));
+#define BIND_CORE_BITFIELD_CLASS_FLAG(m_enum, m_prefix, m_member) \
+ _global_constants.push_back(_CoreConstant(#m_prefix "_" #m_member, (int64_t)m_enum::m_member));
+
#define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \
_global_constants.push_back(_CoreConstant(#m_name, (int64_t)m_enum::m_member));
+#define BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(m_enum, m_name, m_member) \
+ _global_constants.push_back(_CoreConstant(#m_name, (int64_t)m_enum::m_member));
+
#define BIND_CORE_ENUM_CLASS_CONSTANT_NO_VAL(m_enum, m_prefix, m_member) \
_global_constants.push_back(_CoreConstant(#m_prefix "_" #m_member, (int64_t)m_enum::m_member));
@@ -439,15 +459,15 @@ void register_global_constants() {
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, DIVISION);
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, YDIAERESIS);
- BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(KeyModifierMask, KEY_CODE_MASK, CODE_MASK);
- BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(KeyModifierMask, KEY_MODIFIER_MASK, MODIFIER_MASK);
- BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, CMD_OR_CTRL);
- BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, SHIFT);
- BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, ALT);
- BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, META);
- BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, CTRL);
- BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, KPAD);
- BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, GROUP_SWITCH);
+ BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(KeyModifierMask, KEY_CODE_MASK, CODE_MASK);
+ BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(KeyModifierMask, KEY_MODIFIER_MASK, MODIFIER_MASK);
+ BIND_CORE_BITFIELD_CLASS_FLAG(KeyModifierMask, KEY_MASK, CMD_OR_CTRL);
+ BIND_CORE_BITFIELD_CLASS_FLAG(KeyModifierMask, KEY_MASK, SHIFT);
+ BIND_CORE_BITFIELD_CLASS_FLAG(KeyModifierMask, KEY_MASK, ALT);
+ BIND_CORE_BITFIELD_CLASS_FLAG(KeyModifierMask, KEY_MASK, META);
+ BIND_CORE_BITFIELD_CLASS_FLAG(KeyModifierMask, KEY_MASK, CTRL);
+ BIND_CORE_BITFIELD_CLASS_FLAG(KeyModifierMask, KEY_MASK, KPAD);
+ BIND_CORE_BITFIELD_CLASS_FLAG(KeyModifierMask, KEY_MASK, GROUP_SWITCH);
BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, NONE);
BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, LEFT);
@@ -459,11 +479,12 @@ void register_global_constants() {
BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, WHEEL_RIGHT);
BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(MouseButton, MOUSE_BUTTON_XBUTTON1, MB_XBUTTON1);
BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(MouseButton, MOUSE_BUTTON_XBUTTON2, MB_XBUTTON2);
- BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MASK_LEFT);
- BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MASK_RIGHT);
- BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MASK_MIDDLE);
- BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MASK_XBUTTON1);
- BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MASK_XBUTTON2);
+
+ BIND_CORE_BITFIELD_CLASS_FLAG(MouseButtonMask, MOUSE_BUTTON_MASK, LEFT);
+ BIND_CORE_BITFIELD_CLASS_FLAG(MouseButtonMask, MOUSE_BUTTON_MASK, RIGHT);
+ BIND_CORE_BITFIELD_CLASS_FLAG(MouseButtonMask, MOUSE_BUTTON_MASK, MIDDLE);
+ BIND_CORE_BITFIELD_CLASS_FLAG(MouseButtonMask, MOUSE_BUTTON_MASK, MB_XBUTTON1);
+ BIND_CORE_BITFIELD_CLASS_FLAG(MouseButtonMask, MOUSE_BUTTON_MASK, MB_XBUTTON2);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, INVALID);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, A);
@@ -600,14 +621,6 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_TYPE_STRING);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_METHOD_OF_VARIANT_TYPE);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_METHOD_OF_BASE_TYPE);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_METHOD_OF_INSTANCE);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_METHOD_OF_SCRIPT);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_PROPERTY_OF_BASE_TYPE);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_PROPERTY_OF_INSTANCE);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_PROPERTY_OF_SCRIPT);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_OBJECT_TOO_BIG);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_NODE_PATH_VALID_TYPES);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_SAVE_FILE);
@@ -622,50 +635,48 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_PASSWORD);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_MAX);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NONE);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_STORAGE);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_EDITOR);
-
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CHECKABLE);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CHECKED);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_INTERNATIONALIZED);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_GROUP);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CATEGORY);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_SUBGROUP);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CLASS_IS_BITFIELD);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NO_INSTANCE_STATE);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_RESTART_IF_CHANGED);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_SCRIPT_VARIABLE);
-
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_STORE_IF_NULL);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CLASS_IS_ENUM);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NIL_IS_VARIANT);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_INTERNAL);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_HIGH_END_GFX);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_KEYING_INCREMENTS);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_DEFERRED_SET_RESOURCE);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_EDITOR_BASIC_SETTING);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_READ_ONLY);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_ARRAY);
-
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_DEFAULT);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_DEFAULT_INTL);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NO_EDITOR);
-
- BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_NORMAL);
- BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_EDITOR);
- BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_CONST);
- BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_VIRTUAL);
- BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_VARARG);
- BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_STATIC);
- BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_OBJECT_CORE);
- BIND_CORE_ENUM_CONSTANT(METHOD_FLAGS_DEFAULT);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NONE);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_STORAGE);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_EDITOR);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_INTERNAL);
+
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_CHECKABLE);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_CHECKED);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_GROUP);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_CATEGORY);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_SUBGROUP);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_CLASS_IS_BITFIELD);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NO_INSTANCE_STATE);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_RESTART_IF_CHANGED);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_SCRIPT_VARIABLE);
+
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_STORE_IF_NULL);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_CLASS_IS_ENUM);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NIL_IS_VARIANT);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_ARRAY);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_HIGH_END_GFX);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_KEYING_INCREMENTS);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_DEFERRED_SET_RESOURCE);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_EDITOR_BASIC_SETTING);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_READ_ONLY);
+
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_DEFAULT);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NO_EDITOR);
+
+ BIND_CORE_BITFIELD_FLAG(METHOD_FLAG_NORMAL);
+ BIND_CORE_BITFIELD_FLAG(METHOD_FLAG_EDITOR);
+ BIND_CORE_BITFIELD_FLAG(METHOD_FLAG_CONST);
+ BIND_CORE_BITFIELD_FLAG(METHOD_FLAG_VIRTUAL);
+ BIND_CORE_BITFIELD_FLAG(METHOD_FLAG_VARARG);
+ BIND_CORE_BITFIELD_FLAG(METHOD_FLAG_STATIC);
+ BIND_CORE_BITFIELD_FLAG(METHOD_FLAG_OBJECT_CORE);
+ BIND_CORE_BITFIELD_FLAG(METHOD_FLAGS_DEFAULT);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_NIL", Variant::NIL);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_BOOL", Variant::BOOL);
@@ -753,6 +764,10 @@ StringName CoreConstants::get_global_constant_enum(int p_idx) {
return _global_constants[p_idx].enum_name;
}
+bool CoreConstants::is_global_constant_bitfield(int p_idx) {
+ return _global_constants[p_idx].is_bitfield;
+}
+
bool CoreConstants::get_ignore_value_in_docs(int p_idx) {
return _global_constants[p_idx].ignore_value_in_docs;
}
@@ -761,6 +776,10 @@ StringName CoreConstants::get_global_constant_enum(int p_idx) {
return StringName();
}
+bool CoreConstants::is_global_constant_bitfield(int p_idx) {
+ return false;
+}
+
bool CoreConstants::get_ignore_value_in_docs(int p_idx) {
return false;
}
diff --git a/core/core_constants.h b/core/core_constants.h
index 6bd725de88..5a5cd4394c 100644
--- a/core/core_constants.h
+++ b/core/core_constants.h
@@ -37,6 +37,7 @@ class CoreConstants {
public:
static int get_global_constant_count();
static StringName get_global_constant_enum(int p_idx);
+ static bool is_global_constant_bitfield(int p_idx);
static bool get_ignore_value_in_docs(int p_idx);
static const char *get_global_constant_name(int p_idx);
static int64_t get_global_constant_value(int p_idx);
diff --git a/core/debugger/script_debugger.cpp b/core/debugger/script_debugger.cpp
index 8af1573bff..32725b76c1 100644
--- a/core/debugger/script_debugger.cpp
+++ b/core/debugger/script_debugger.cpp
@@ -73,10 +73,6 @@ bool ScriptDebugger::is_breakpoint(int p_line, const StringName &p_source) const
return breakpoints[p_line].has(p_source);
}
-bool ScriptDebugger::is_breakpoint_line(int p_line) const {
- return breakpoints.has(p_line);
-}
-
String ScriptDebugger::breakpoint_find_source(const String &p_source) const {
return p_source;
}
diff --git a/core/debugger/script_debugger.h b/core/debugger/script_debugger.h
index c7aa90027b..edce089179 100644
--- a/core/debugger/script_debugger.h
+++ b/core/debugger/script_debugger.h
@@ -64,7 +64,6 @@ public:
void insert_breakpoint(int p_line, const StringName &p_source);
void remove_breakpoint(int p_line, const StringName &p_source);
bool is_breakpoint(int p_line, const StringName &p_source) const;
- bool is_breakpoint_line(int p_line) const;
void clear_breakpoints();
const HashMap<int, HashSet<StringName>> &get_breakpoints() const { return breakpoints; }
diff --git a/core/doc_data.h b/core/doc_data.h
index c547138619..1cf4e4f206 100644
--- a/core/doc_data.h
+++ b/core/doc_data.h
@@ -378,7 +378,6 @@ public:
struct ClassDoc {
String name;
String inherits;
- String category; // FIXME: Wrongly used by VisualScriptPropertySelector, should be removed.
String brief_description;
String description;
Vector<TutorialDoc> tutorials;
@@ -409,10 +408,6 @@ public:
doc.inherits = p_dict["inherits"];
}
- if (p_dict.has("category")) {
- doc.category = p_dict["category"];
- }
-
if (p_dict.has("brief_description")) {
doc.brief_description = p_dict["brief_description"];
}
diff --git a/core/error/error_macros.h b/core/error/error_macros.h
index f651ef57a3..63a2d22416 100644
--- a/core/error/error_macros.h
+++ b/core/error/error_macros.h
@@ -33,7 +33,7 @@
#include "core/typedefs.h"
-#include "core/templates/safe_refcount.h"
+#include <atomic> // We'd normally use safe_refcount.h, but that would cause circular includes.
class String;
@@ -737,10 +737,10 @@ void _err_flush_stdout();
*/
#define WARN_DEPRECATED \
if (true) { \
- static SafeFlag warning_shown; \
- if (!warning_shown.is_set()) { \
+ static std::atomic<bool> warning_shown; \
+ if (!warning_shown.load()) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", false, ERR_HANDLER_WARNING); \
- warning_shown.set(); \
+ warning_shown.store(true); \
} \
} else \
((void)0)
@@ -750,10 +750,10 @@ void _err_flush_stdout();
*/
#define WARN_DEPRECATED_MSG(m_msg) \
if (true) { \
- static SafeFlag warning_shown; \
- if (!warning_shown.is_set()) { \
+ static std::atomic<bool> warning_shown; \
+ if (!warning_shown.load()) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", m_msg, false, ERR_HANDLER_WARNING); \
- warning_shown.set(); \
+ warning_shown.store(true); \
} \
} else \
((void)0)
diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp
index 1957ad987a..7be14b741d 100644
--- a/core/extension/extension_api_dump.cpp
+++ b/core/extension/extension_api_dump.cpp
@@ -458,17 +458,21 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
// Global enums and constants.
Array constants;
HashMap<String, List<Pair<String, int64_t>>> enum_list;
+ HashMap<String, bool> enum_is_bitfield;
for (int i = 0; i < CoreConstants::get_global_constant_count(); i++) {
int64_t value = CoreConstants::get_global_constant_value(i);
String enum_name = CoreConstants::get_global_constant_enum(i);
String name = CoreConstants::get_global_constant_name(i);
+ bool bitfield = CoreConstants::is_global_constant_bitfield(i);
if (!enum_name.is_empty()) {
enum_list[enum_name].push_back(Pair<String, int64_t>(name, value));
+ enum_is_bitfield[enum_name] = bitfield;
} else {
Dictionary d;
d["name"] = name;
d["value"] = value;
+ d["is_bitfield"] = bitfield;
constants.push_back(d);
}
}
@@ -479,6 +483,7 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
for (const KeyValue<String, List<Pair<String, int64_t>>> &E : enum_list) {
Dictionary d1;
d1["name"] = E.key;
+ d1["is_bitfield"] = enum_is_bitfield[E.key];
Array values;
for (const Pair<String, int64_t> &F : E.value) {
Dictionary d2;
diff --git a/core/extension/gdextension_interface.cpp b/core/extension/gdextension_interface.cpp
index bd4fa61bd5..a9063c8b27 100644
--- a/core/extension/gdextension_interface.cpp
+++ b/core/extension/gdextension_interface.cpp
@@ -31,8 +31,11 @@
#include "gdextension_interface.h"
#include "core/config/engine.h"
+#include "core/io/file_access.h"
+#include "core/io/xml_parser.h"
#include "core/object/class_db.h"
#include "core/object/script_language_extension.h"
+#include "core/object/worker_thread_pool.h"
#include "core/os/memory.h"
#include "core/variant/variant.h"
#include "core/version.h"
@@ -678,6 +681,59 @@ static const char32_t *gdextension_string_operator_index_const(GDExtensionConstS
return &self->ptr()[p_index];
}
+static void gdextension_string_operator_plus_eq_string(GDExtensionStringPtr p_self, GDExtensionConstStringPtr p_b) {
+ String *self = (String *)p_self;
+ const String *b = (const String *)p_b;
+ *self += *b;
+}
+
+static void gdextension_string_operator_plus_eq_char(GDExtensionStringPtr p_self, char32_t p_b) {
+ String *self = (String *)p_self;
+ *self += p_b;
+}
+
+static void gdextension_string_operator_plus_eq_cstr(GDExtensionStringPtr p_self, const char *p_b) {
+ String *self = (String *)p_self;
+ *self += p_b;
+}
+
+static void gdextension_string_operator_plus_eq_wcstr(GDExtensionStringPtr p_self, const wchar_t *p_b) {
+ String *self = (String *)p_self;
+ *self += p_b;
+}
+
+static void gdextension_string_operator_plus_eq_c32str(GDExtensionStringPtr p_self, const char32_t *p_b) {
+ String *self = (String *)p_self;
+ *self += p_b;
+}
+
+static GDExtensionInt gdextension_xml_parser_open_buffer(GDExtensionObjectPtr p_instance, const uint8_t *p_buffer, size_t p_size) {
+ XMLParser *xml = (XMLParser *)p_instance;
+ return (GDExtensionInt)xml->_open_buffer(p_buffer, p_size);
+}
+
+static void gdextension_file_access_store_buffer(GDExtensionObjectPtr p_instance, const uint8_t *p_src, uint64_t p_length) {
+ FileAccess *fa = (FileAccess *)p_instance;
+ fa->store_buffer(p_src, p_length);
+}
+
+static uint64_t gdextension_file_access_get_buffer(GDExtensionConstObjectPtr p_instance, uint8_t *p_dst, uint64_t p_length) {
+ const FileAccess *fa = (FileAccess *)p_instance;
+ return fa->get_buffer(p_dst, p_length);
+}
+
+static int64_t gdextension_worker_thread_pool_add_native_group_task(GDExtensionObjectPtr p_instance, void (*p_func)(void *, uint32_t), void *p_userdata, int p_elements, int p_tasks, GDExtensionBool p_high_priority, GDExtensionConstStringPtr p_description) {
+ WorkerThreadPool *p = (WorkerThreadPool *)p_instance;
+ const String *description = (const String *)p_description;
+ return (int64_t)p->add_native_group_task(p_func, p_userdata, p_elements, p_tasks, static_cast<bool>(p_high_priority), *description);
+}
+
+static int64_t gdextension_worker_thread_pool_add_native_task(GDExtensionObjectPtr p_instance, void (*p_func)(void *), void *p_userdata, GDExtensionBool p_high_priority, GDExtensionConstStringPtr p_description) {
+ WorkerThreadPool *p = (WorkerThreadPool *)p_instance;
+ const String *description = (const String *)p_description;
+ return (int64_t)p->add_native_task(p_func, p_userdata, static_cast<bool>(p_high_priority), *description);
+}
+
/* Packed array functions */
static uint8_t *gdextension_packed_byte_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) {
@@ -1025,6 +1081,25 @@ void gdextension_setup_interface(GDExtensionInterface *p_interface) {
gde_interface.string_to_wide_chars = gdextension_string_to_wide_chars;
gde_interface.string_operator_index = gdextension_string_operator_index;
gde_interface.string_operator_index_const = gdextension_string_operator_index_const;
+ gde_interface.string_operator_plus_eq_string = gdextension_string_operator_plus_eq_string;
+ gde_interface.string_operator_plus_eq_char = gdextension_string_operator_plus_eq_char;
+ gde_interface.string_operator_plus_eq_cstr = gdextension_string_operator_plus_eq_cstr;
+ gde_interface.string_operator_plus_eq_wcstr = gdextension_string_operator_plus_eq_wcstr;
+ gde_interface.string_operator_plus_eq_c32str = gdextension_string_operator_plus_eq_c32str;
+
+ /* XMLParser extra utilities */
+
+ gde_interface.xml_parser_open_buffer = gdextension_xml_parser_open_buffer;
+
+ /* FileAccess extra utilities */
+
+ gde_interface.file_access_store_buffer = gdextension_file_access_store_buffer;
+ gde_interface.file_access_get_buffer = gdextension_file_access_get_buffer;
+
+ /* WorkerThreadPool extra utilities */
+
+ gde_interface.worker_thread_pool_add_native_group_task = gdextension_worker_thread_pool_add_native_group_task;
+ gde_interface.worker_thread_pool_add_native_task = gdextension_worker_thread_pool_add_native_task;
/* Packed array functions */
diff --git a/core/extension/gdextension_interface.h b/core/extension/gdextension_interface.h
index 190298ee8a..6e5dee8265 100644
--- a/core/extension/gdextension_interface.h
+++ b/core/extension/gdextension_interface.h
@@ -503,6 +503,26 @@ typedef struct {
char32_t *(*string_operator_index)(GDExtensionStringPtr p_self, GDExtensionInt p_index);
const char32_t *(*string_operator_index_const)(GDExtensionConstStringPtr p_self, GDExtensionInt p_index);
+ void (*string_operator_plus_eq_string)(GDExtensionStringPtr p_self, GDExtensionConstStringPtr p_b);
+ void (*string_operator_plus_eq_char)(GDExtensionStringPtr p_self, char32_t p_b);
+ void (*string_operator_plus_eq_cstr)(GDExtensionStringPtr p_self, const char *p_b);
+ void (*string_operator_plus_eq_wcstr)(GDExtensionStringPtr p_self, const wchar_t *p_b);
+ void (*string_operator_plus_eq_c32str)(GDExtensionStringPtr p_self, const char32_t *p_b);
+
+ /* XMLParser extra utilities */
+
+ GDExtensionInt (*xml_parser_open_buffer)(GDExtensionObjectPtr p_instance, const uint8_t *p_buffer, size_t p_size);
+
+ /* FileAccess extra utilities */
+
+ void (*file_access_store_buffer)(GDExtensionObjectPtr p_instance, const uint8_t *p_src, uint64_t p_length);
+ uint64_t (*file_access_get_buffer)(GDExtensionConstObjectPtr p_instance, uint8_t *p_dst, uint64_t p_length);
+
+ /* WorkerThreadPool extra utilities */
+
+ int64_t (*worker_thread_pool_add_native_group_task)(GDExtensionObjectPtr p_instance, void (*p_func)(void *, uint32_t), void *p_userdata, int p_elements, int p_tasks, GDExtensionBool p_high_priority, GDExtensionConstStringPtr p_description);
+ int64_t (*worker_thread_pool_add_native_task)(GDExtensionObjectPtr p_instance, void (*p_func)(void *), void *p_userdata, GDExtensionBool p_high_priority, GDExtensionConstStringPtr p_description);
+
/* Packed array functions */
uint8_t *(*packed_byte_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedByteArray
diff --git a/core/input/input.cpp b/core/input/input.cpp
index a1944c0920..0afa004515 100644
--- a/core/input/input.cpp
+++ b/core/input/input.cpp
@@ -237,7 +237,7 @@ bool Input::is_anything_pressed() const {
}
return !keys_pressed.is_empty() ||
!joy_buttons_pressed.is_empty() ||
- mouse_button_mask > MouseButton::NONE;
+ !mouse_button_mask.is_empty();
}
bool Input::is_key_pressed(Key p_keycode) const {
@@ -252,7 +252,7 @@ bool Input::is_physical_key_pressed(Key p_keycode) const {
bool Input::is_mouse_button_pressed(MouseButton p_button) const {
_THREAD_SAFE_METHOD_
- return (mouse_button_mask & mouse_button_to_mask(p_button)) != MouseButton::NONE;
+ return mouse_button_mask.has_flag(mouse_button_to_mask(p_button));
}
static JoyAxis _combine_device(JoyAxis p_value, int p_device) {
@@ -504,9 +504,9 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
if (mb.is_valid()) {
if (mb->is_pressed()) {
- mouse_button_mask |= mouse_button_to_mask(mb->get_button_index());
+ mouse_button_mask.set_flag(mouse_button_to_mask(mb->get_button_index()));
} else {
- mouse_button_mask &= ~mouse_button_to_mask(mb->get_button_index());
+ mouse_button_mask.clear_flag(mouse_button_to_mask(mb->get_button_index()));
}
Point2 pos = mb->get_global_position();
@@ -534,7 +534,7 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
Vector2 relative = mm->get_relative();
mouse_velocity_track.update(relative);
- if (event_dispatch_function && emulate_touch_from_mouse && !p_is_emulated && (mm->get_button_mask() & MouseButton::LEFT) != MouseButton::NONE) {
+ if (event_dispatch_function && emulate_touch_from_mouse && !p_is_emulated && mm->get_button_mask().has_flag(MouseButtonMask::LEFT)) {
Ref<InputEventScreenDrag> drag_event;
drag_event.instantiate();
@@ -585,11 +585,14 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
button_event->set_pressed(st->is_pressed());
button_event->set_button_index(MouseButton::LEFT);
button_event->set_double_click(st->is_double_tap());
+
+ BitField<MouseButtonMask> ev_bm = mouse_button_mask;
if (st->is_pressed()) {
- button_event->set_button_mask(MouseButton(mouse_button_mask | MouseButton::MASK_LEFT));
+ ev_bm.set_flag(MouseButtonMask::LEFT);
} else {
- button_event->set_button_mask(MouseButton(mouse_button_mask & ~MouseButton::MASK_LEFT));
+ ev_bm.clear_flag(MouseButtonMask::LEFT);
}
+ button_event->set_button_mask(ev_bm);
_parse_input_event_impl(button_event, true);
}
@@ -740,7 +743,7 @@ Point2 Input::get_last_mouse_velocity() {
return mouse_velocity_track.velocity;
}
-MouseButton Input::get_mouse_button_mask() const {
+BitField<MouseButtonMask> Input::get_mouse_button_mask() const {
return mouse_button_mask; // do not trust OS implementation, should remove it - OS::get_singleton()->get_mouse_button_state();
}
@@ -821,7 +824,9 @@ void Input::ensure_touch_mouse_raised() {
button_event->set_global_position(mouse_pos);
button_event->set_pressed(false);
button_event->set_button_index(MouseButton::LEFT);
- button_event->set_button_mask(MouseButton(mouse_button_mask & ~MouseButton::MASK_LEFT));
+ BitField<MouseButtonMask> ev_bm = mouse_button_mask;
+ ev_bm.clear_flag(MouseButtonMask::LEFT);
+ button_event->set_button_mask(ev_bm);
_parse_input_event_impl(button_event, true);
}
@@ -1022,7 +1027,7 @@ void Input::joy_axis(int p_device, JoyAxis p_axis, float p_value) {
}
}
-void Input::joy_hat(int p_device, HatMask p_val) {
+void Input::joy_hat(int p_device, BitField<HatMask> p_val) {
_THREAD_SAFE_METHOD_;
const Joypad &joy = joy_names[p_device];
diff --git a/core/input/input.h b/core/input/input.h
index 5ef163e530..0915588700 100644
--- a/core/input/input.h
+++ b/core/input/input.h
@@ -82,7 +82,7 @@ public:
typedef void (*EventDispatchFunc)(const Ref<InputEvent> &p_event);
private:
- MouseButton mouse_button_mask = MouseButton::NONE;
+ BitField<MouseButtonMask> mouse_button_mask;
RBSet<Key> physical_keys_pressed;
RBSet<Key> keys_pressed;
@@ -273,7 +273,7 @@ public:
Point2 get_mouse_position() const;
Vector2 get_last_mouse_velocity();
- MouseButton get_mouse_button_mask() const;
+ BitField<MouseButtonMask> get_mouse_button_mask() const;
void warp_mouse(const Vector2 &p_position);
Point2i warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect);
@@ -310,7 +310,7 @@ public:
void parse_mapping(String p_mapping);
void joy_button(int p_device, JoyButton p_button, bool p_pressed);
void joy_axis(int p_device, JoyAxis p_axis, float p_value);
- void joy_hat(int p_device, HatMask p_val);
+ void joy_hat(int p_device, BitField<HatMask> p_val);
void add_joy_mapping(String p_mapping, bool p_update_existing = false);
void remove_joy_mapping(String p_guid);
diff --git a/core/input/input_builders.py b/core/input/input_builders.py
index a7729c9af2..76e199e0ff 100644
--- a/core/input/input_builders.py
+++ b/core/input/input_builders.py
@@ -45,7 +45,7 @@ def make_default_controller_mappings(target, source, env):
platform_mappings[current_platform][guid] = line
platform_variables = {
- "Linux": "#if X11_ENABLED",
+ "Linux": "#if LINUXBSD_ENABLED",
"Windows": "#ifdef WINDOWS_ENABLED",
"Mac OS X": "#ifdef MACOS_ENABLED",
"Android": "#if defined(__ANDROID__)",
diff --git a/core/input/input_enums.h b/core/input/input_enums.h
index c30516676f..02efde2d30 100644
--- a/core/input/input_enums.h
+++ b/core/input/input_enums.h
@@ -119,59 +119,18 @@ enum class MouseButton {
WHEEL_RIGHT = 7,
MB_XBUTTON1 = 8, // "XBUTTON1" is a reserved word on Windows.
MB_XBUTTON2 = 9, // "XBUTTON2" is a reserved word on Windows.
- MASK_LEFT = (1 << (LEFT - 1)),
- MASK_RIGHT = (1 << (RIGHT - 1)),
- MASK_MIDDLE = (1 << (MIDDLE - 1)),
- MASK_XBUTTON1 = (1 << (MB_XBUTTON1 - 1)),
- MASK_XBUTTON2 = (1 << (MB_XBUTTON2 - 1)),
};
-inline MouseButton mouse_button_to_mask(MouseButton button) {
- return MouseButton(1 << ((int)button - 1));
-}
-
-inline MouseButton operator&(MouseButton a, MouseButton b) {
- return (MouseButton)((int)a & (int)b);
-}
-
-inline MouseButton operator|(MouseButton a, MouseButton b) {
- return (MouseButton)((int)a | (int)b);
-}
-
-inline MouseButton operator^(MouseButton a, MouseButton b) {
- return (MouseButton)((int)a ^ (int)b);
-}
-
-inline MouseButton &operator|=(MouseButton &a, MouseButton b) {
- return (MouseButton &)((int &)a |= (int)b);
-}
-
-inline MouseButton &operator&=(MouseButton &a, MouseButton b) {
- return (MouseButton &)((int &)a &= (int)b);
-}
-
-inline MouseButton operator~(MouseButton a) {
- return (MouseButton)(~(int)a);
-}
-
-inline HatMask operator|(HatMask a, HatMask b) {
- return (HatMask)((int)a | (int)b);
-}
-
-inline HatMask operator&(HatMask a, HatMask b) {
- return (HatMask)((int)a & (int)b);
-}
-
-inline HatMask &operator&=(HatMask &a, HatMask b) {
- return (HatMask &)((int &)a &= (int)b);
-}
-
-inline HatMask &operator|=(HatMask &a, HatMask b) {
- return (HatMask &)((int &)a |= (int)b);
-}
+enum class MouseButtonMask {
+ LEFT = (1 << (int(MouseButton::LEFT) - 1)),
+ RIGHT = (1 << (int(MouseButton::RIGHT) - 1)),
+ MIDDLE = (1 << (int(MouseButton::MIDDLE) - 1)),
+ MB_XBUTTON1 = (1 << (int(MouseButton::MB_XBUTTON1) - 1)),
+ MB_XBUTTON2 = (1 << (int(MouseButton::MB_XBUTTON2) - 1)),
+};
-inline HatMask operator~(HatMask a) {
- return (HatMask)(~(int)a);
+inline MouseButtonMask mouse_button_to_mask(MouseButton button) {
+ return MouseButtonMask(1 << ((int)button - 1));
}
#endif // INPUT_ENUMS_H
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index f421ecb22d..0dd7fdc19b 100644
--- a/core/input/input_event.cpp
+++ b/core/input/input_event.cpp
@@ -216,25 +216,25 @@ void InputEventWithModifiers::set_modifiers_from_event(const InputEventWithModif
set_meta_pressed(event->is_meta_pressed());
}
-Key InputEventWithModifiers::get_modifiers_mask() const {
- Key mask = Key::NONE;
+BitField<KeyModifierMask> InputEventWithModifiers::get_modifiers_mask() const {
+ BitField<KeyModifierMask> mask;
if (is_ctrl_pressed()) {
- mask |= KeyModifierMask::CTRL;
+ mask.set_flag(KeyModifierMask::CTRL);
}
if (is_shift_pressed()) {
- mask |= KeyModifierMask::SHIFT;
+ mask.set_flag(KeyModifierMask::SHIFT);
}
if (is_alt_pressed()) {
- mask |= KeyModifierMask::ALT;
+ mask.set_flag(KeyModifierMask::ALT);
}
if (is_meta_pressed()) {
- mask |= KeyModifierMask::META;
+ mask.set_flag(KeyModifierMask::META);
}
if (is_command_or_control_autoremap()) {
#ifdef MACOS_ENABLED
- mask |= KeyModifierMask::META;
+ mask.set_flag(KeyModifierMask::META);
#else
- mask |= KeyModifierMask::CTRL;
+ mask.set_flag(KeyModifierMask::CTRL);
#endif
}
return mask;
@@ -356,11 +356,11 @@ bool InputEventKey::is_echo() const {
}
Key InputEventKey::get_keycode_with_modifiers() const {
- return keycode | get_modifiers_mask();
+ return keycode | (int64_t)get_modifiers_mask();
}
Key InputEventKey::get_physical_keycode_with_modifiers() const {
- return physical_keycode | get_modifiers_mask();
+ return physical_keycode | (int64_t)get_modifiers_mask();
}
String InputEventKey::as_text() const {
@@ -440,8 +440,8 @@ bool InputEventKey::action_match(const Ref<InputEvent> &p_event, bool p_exact_ma
} else {
match = get_physical_keycode() == key->get_physical_keycode();
}
- Key action_mask = get_modifiers_mask();
- Key key_mask = key->get_modifiers_mask();
+ Key action_mask = (Key)(int64_t)get_modifiers_mask();
+ Key key_mask = (Key)(int64_t)key->get_modifiers_mask();
if (key->is_pressed()) {
match &= (action_mask & key_mask) == action_mask;
}
@@ -505,12 +505,12 @@ void InputEventKey::_bind_methods() {
///////////////////////////////////
-void InputEventMouse::set_button_mask(MouseButton p_mask) {
+void InputEventMouse::set_button_mask(BitField<MouseButtonMask> p_mask) {
button_mask = p_mask;
emit_changed();
}
-MouseButton InputEventMouse::get_button_mask() const {
+BitField<MouseButtonMask> InputEventMouse::get_button_mask() const {
return button_mask;
}
@@ -610,8 +610,8 @@ bool InputEventMouseButton::action_match(const Ref<InputEvent> &p_event, bool p_
}
bool match = button_index == mb->button_index;
- Key action_modifiers_mask = get_modifiers_mask();
- Key button_modifiers_mask = mb->get_modifiers_mask();
+ Key action_modifiers_mask = (Key)(int64_t)get_modifiers_mask();
+ Key button_modifiers_mask = (Key)(int64_t)mb->get_modifiers_mask();
if (mb->is_pressed()) {
match &= (action_modifiers_mask & button_modifiers_mask) == action_modifiers_mask;
}
@@ -808,26 +808,23 @@ String InputEventMouseMotion::as_text() const {
}
String InputEventMouseMotion::to_string() {
- MouseButton mouse_button_mask = get_button_mask();
+ BitField<MouseButtonMask> mouse_button_mask = get_button_mask();
String button_mask_string = itos((int64_t)mouse_button_mask);
- switch (mouse_button_mask) {
- case MouseButton::MASK_LEFT:
- button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::LEFT - 1]));
- break;
- case MouseButton::MASK_MIDDLE:
- button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::MIDDLE - 1]));
- break;
- case MouseButton::MASK_RIGHT:
- button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::RIGHT - 1]));
- break;
- case MouseButton::MASK_XBUTTON1:
- button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::MB_XBUTTON1 - 1]));
- break;
- case MouseButton::MASK_XBUTTON2:
- button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::MB_XBUTTON2 - 1]));
- break;
- default:
- break;
+
+ if (mouse_button_mask.has_flag(MouseButtonMask::LEFT)) {
+ button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::LEFT - 1]));
+ }
+ if (mouse_button_mask.has_flag(MouseButtonMask::MIDDLE)) {
+ button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::MIDDLE - 1]));
+ }
+ if (mouse_button_mask.has_flag(MouseButtonMask::RIGHT)) {
+ button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::RIGHT - 1]));
+ }
+ if (mouse_button_mask.has_flag(MouseButtonMask::MB_XBUTTON1)) {
+ button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::MB_XBUTTON1 - 1]));
+ }
+ if (mouse_button_mask.has_flag(MouseButtonMask::MB_XBUTTON2)) {
+ button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::MB_XBUTTON2 - 1]));
}
// Work around the fact vformat can only take 5 substitutions but 7 need to be passed.
diff --git a/core/input/input_event.h b/core/input/input_event.h
index e90f38b489..2d7a72e327 100644
--- a/core/input/input_event.h
+++ b/core/input/input_event.h
@@ -138,7 +138,7 @@ public:
void set_modifiers_from_event(const InputEventWithModifiers *event);
- Key get_modifiers_mask() const;
+ BitField<KeyModifierMask> get_modifiers_mask() const;
virtual String as_text() const override;
virtual String to_string() override;
@@ -195,7 +195,7 @@ public:
class InputEventMouse : public InputEventWithModifiers {
GDCLASS(InputEventMouse, InputEventWithModifiers);
- MouseButton button_mask = MouseButton::NONE;
+ BitField<MouseButtonMask> button_mask;
Vector2 pos;
Vector2 global_pos;
@@ -204,8 +204,8 @@ protected:
static void _bind_methods();
public:
- void set_button_mask(MouseButton p_mask);
- MouseButton get_button_mask() const;
+ void set_button_mask(BitField<MouseButtonMask> p_mask);
+ BitField<MouseButtonMask> get_button_mask() const;
void set_position(const Vector2 &p_pos);
Vector2 get_position() const;
diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp
index f2cd3ba4d9..98f8c3de41 100644
--- a/core/io/config_file.cpp
+++ b/core/io/config_file.cpp
@@ -208,7 +208,7 @@ Error ConfigFile::_internal_save(Ref<FileAccess> file) {
file->store_string("\n");
}
if (!E.key.is_empty()) {
- file->store_string("[" + E.key + "]\n\n");
+ file->store_string("[" + E.key.replace("]", "\\]") + "]\n\n");
}
for (const KeyValue<String, Variant> &F : E.value) {
@@ -308,7 +308,7 @@ Error ConfigFile::_parse(const String &p_path, VariantParser::Stream *p_stream)
if (!assign.is_empty()) {
set_value(section, assign, value);
} else if (!next_tag.name.is_empty()) {
- section = next_tag.name;
+ section = next_tag.name.replace("\\]", "]");
}
}
diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp
index 77d1bdcc5c..cacbcb28a4 100644
--- a/core/io/file_access.cpp
+++ b/core/io/file_access.cpp
@@ -292,7 +292,7 @@ real_t FileAccess::get_real() const {
Variant FileAccess::get_var(bool p_allow_objects) const {
uint32_t len = get_32();
- Vector<uint8_t> buff = _get_buffer(len);
+ Vector<uint8_t> buff = get_buffer(len);
ERR_FAIL_COND_V((uint32_t)buff.size() != len, Variant());
const uint8_t *r = buff.ptr();
@@ -469,7 +469,7 @@ uint64_t FileAccess::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
return i;
}
-Vector<uint8_t> FileAccess::_get_buffer(int64_t p_length) const {
+Vector<uint8_t> FileAccess::get_buffer(int64_t p_length) const {
Vector<uint8_t> data;
ERR_FAIL_COND_V_MSG(p_length < 0, data, "Length of buffer cannot be smaller than 0.");
@@ -663,7 +663,7 @@ void FileAccess::store_buffer(const uint8_t *p_src, uint64_t p_length) {
}
}
-void FileAccess::_store_buffer(const Vector<uint8_t> &p_buffer) {
+void FileAccess::store_buffer(const Vector<uint8_t> &p_buffer) {
uint64_t len = p_buffer.size();
if (len == 0) {
return;
@@ -687,7 +687,7 @@ void FileAccess::store_var(const Variant &p_var, bool p_full_objects) {
ERR_FAIL_COND_MSG(err != OK, "Error when trying to encode Variant.");
store_32(len);
- _store_buffer(buff);
+ store_buffer(buff);
}
Vector<uint8_t> FileAccess::get_file_as_bytes(const String &p_path, Error *r_error) {
@@ -829,7 +829,7 @@ void FileAccess::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_float"), &FileAccess::get_float);
ClassDB::bind_method(D_METHOD("get_double"), &FileAccess::get_double);
ClassDB::bind_method(D_METHOD("get_real"), &FileAccess::get_real);
- ClassDB::bind_method(D_METHOD("get_buffer", "length"), &FileAccess::_get_buffer);
+ ClassDB::bind_method(D_METHOD("get_buffer", "length"), (Vector<uint8_t>(FileAccess::*)(int64_t) const) & FileAccess::get_buffer);
ClassDB::bind_method(D_METHOD("get_line"), &FileAccess::get_line);
ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &FileAccess::get_csv_line, DEFVAL(","));
ClassDB::bind_method(D_METHOD("get_as_text", "skip_cr"), &FileAccess::get_as_text, DEFVAL(false));
@@ -847,7 +847,7 @@ void FileAccess::_bind_methods() {
ClassDB::bind_method(D_METHOD("store_float", "value"), &FileAccess::store_float);
ClassDB::bind_method(D_METHOD("store_double", "value"), &FileAccess::store_double);
ClassDB::bind_method(D_METHOD("store_real", "value"), &FileAccess::store_real);
- ClassDB::bind_method(D_METHOD("store_buffer", "buffer"), &FileAccess::_store_buffer);
+ ClassDB::bind_method(D_METHOD("store_buffer", "buffer"), (void(FileAccess::*)(const Vector<uint8_t> &)) & FileAccess::store_buffer);
ClassDB::bind_method(D_METHOD("store_line", "line"), &FileAccess::store_line);
ClassDB::bind_method(D_METHOD("store_csv_line", "values", "delim"), &FileAccess::store_csv_line, DEFVAL(","));
ClassDB::bind_method(D_METHOD("store_string", "string"), &FileAccess::store_string);
diff --git a/core/io/file_access.h b/core/io/file_access.h
index 3116ed521f..3e51ba11ed 100644
--- a/core/io/file_access.h
+++ b/core/io/file_access.h
@@ -127,7 +127,7 @@ public:
Variant get_var(bool p_allow_objects = false) const;
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; ///< get an array of bytes
- Vector<uint8_t> _get_buffer(int64_t p_length) const;
+ Vector<uint8_t> get_buffer(int64_t p_length) const;
virtual String get_line() const;
virtual String get_token() const;
virtual Vector<String> get_csv_line(const String &p_delim = ",") const;
@@ -162,7 +162,7 @@ public:
virtual String get_pascal_string();
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes
- void _store_buffer(const Vector<uint8_t> &p_buffer);
+ void store_buffer(const Vector<uint8_t> &p_buffer);
void store_var(const Variant &p_var, bool p_full_objects = false);
diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp
index c9e0c2c638..c256668af0 100644
--- a/core/io/file_access_compressed.cpp
+++ b/core/io/file_access_compressed.cpp
@@ -184,6 +184,22 @@ bool FileAccessCompressed::is_open() const {
return f.is_valid();
}
+String FileAccessCompressed::get_path() const {
+ if (f.is_valid()) {
+ return f->get_path();
+ } else {
+ return "";
+ }
+}
+
+String FileAccessCompressed::get_path_absolute() const {
+ if (f.is_valid()) {
+ return f->get_path_absolute();
+ } else {
+ return "";
+ }
+}
+
void FileAccessCompressed::seek(uint64_t p_position) {
ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use.");
diff --git a/core/io/file_access_compressed.h b/core/io/file_access_compressed.h
index 53b4887b90..136fcede06 100644
--- a/core/io/file_access_compressed.h
+++ b/core/io/file_access_compressed.h
@@ -73,6 +73,9 @@ public:
virtual Error open_internal(const String &p_path, int p_mode_flags) override; ///< open a file
virtual bool is_open() const override; ///< true when file is open
+ virtual String get_path() const override; /// returns the path for the current open file
+ virtual String get_path_absolute() const override; /// returns the absolute path for the current open file
+
virtual void seek(uint64_t p_position) override; ///< seek to a given position
virtual void seek_end(int64_t p_position = 0) override; ///< seek from the end of file
virtual uint64_t get_position() const override; ///< get position in the file
diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp
index 17fb199811..c6452f1033 100644
--- a/core/io/image_loader.cpp
+++ b/core/io/image_loader.cpp
@@ -135,10 +135,6 @@ void ImageLoader::remove_image_format_loader(Ref<ImageFormatLoader> p_loader) {
loader.erase(p_loader);
}
-const Vector<Ref<ImageFormatLoader>> &ImageLoader::get_image_format_loaders() {
- return loader;
-}
-
void ImageLoader::cleanup() {
while (loader.size()) {
remove_image_format_loader(loader[0]);
diff --git a/core/io/image_loader.h b/core/io/image_loader.h
index 1473f24186..ac51f13376 100644
--- a/core/io/image_loader.h
+++ b/core/io/image_loader.h
@@ -98,8 +98,6 @@ public:
static void add_image_format_loader(Ref<ImageFormatLoader> p_loader);
static void remove_image_format_loader(Ref<ImageFormatLoader> p_loader);
- static const Vector<Ref<ImageFormatLoader>> &get_image_format_loaders();
-
static void cleanup();
};
diff --git a/core/io/resource.cpp b/core/io/resource.cpp
index 2d6f09725f..6d3575b9fa 100644
--- a/core/io/resource.cpp
+++ b/core/io/resource.cpp
@@ -385,10 +385,6 @@ void Resource::set_as_translation_remapped(bool p_remapped) {
ResourceCache::lock.unlock();
}
-bool Resource::is_translation_remapped() const {
- return remapped_list.in_list();
-}
-
#ifdef TOOLS_ENABLED
//helps keep IDs same number when loading/saving scenes. -1 clears ID and it Returns -1 when no id stored
void Resource::set_id_for_path(const String &p_path, const String &p_id) {
@@ -481,9 +477,6 @@ void ResourceCache::clear() {
resources.clear();
}
-void ResourceCache::reload_externals() {
-}
-
bool ResourceCache::has(const String &p_path) {
lock.lock();
diff --git a/core/io/resource.h b/core/io/resource.h
index 22ce5cef43..5135664f36 100644
--- a/core/io/resource.h
+++ b/core/io/resource.h
@@ -136,7 +136,6 @@ public:
#endif
void set_as_translation_remapped(bool p_remapped);
- bool is_translation_remapped() const;
virtual RID get_rid() const; // some resources may offer conversion to RID
@@ -164,7 +163,6 @@ class ResourceCache {
friend void register_core_types();
public:
- static void reload_externals();
static bool has(const String &p_path);
static Ref<Resource> get_ref(const String &p_path);
static void get_cached_resources(List<Ref<Resource>> *p_resources);
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index ba6ad16ca8..03beb25b03 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -661,10 +661,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
return OK; //never reach anyway
}
-void ResourceLoaderBinary::set_local_path(const String &p_local_path) {
- res_path = p_local_path;
-}
-
Ref<Resource> ResourceLoaderBinary::get_resource() {
return resource;
}
@@ -1045,10 +1041,10 @@ void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p
#ifdef TOOLS_ENABLED
// Silence a warning that can happen during the initial filesystem scan due to cache being regenerated.
if (ResourceLoader::get_resource_uid(res_path) != er.uid) {
- WARN_PRINT(String(res_path + ": In external resource #" + itos(i) + ", invalid UUID: " + ResourceUID::get_singleton()->id_to_text(er.uid) + " - using text path instead: " + er.path).utf8().get_data());
+ WARN_PRINT(String(res_path + ": In external resource #" + itos(i) + ", invalid UID: " + ResourceUID::get_singleton()->id_to_text(er.uid) + " - using text path instead: " + er.path).utf8().get_data());
}
#else
- WARN_PRINT(String(res_path + ": In external resource #" + itos(i) + ", invalid UUID: " + ResourceUID::get_singleton()->id_to_text(er.uid) + " - using text path instead: " + er.path).utf8().get_data());
+ WARN_PRINT(String(res_path + ": In external resource #" + itos(i) + ", invalid UID: " + ResourceUID::get_singleton()->id_to_text(er.uid) + " - using text path instead: " + er.path).utf8().get_data());
#endif
}
}
@@ -2209,12 +2205,130 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Re
return OK;
}
+Error ResourceFormatSaverBinaryInstance::set_uid(const String &p_path, ResourceUID::ID p_uid) {
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, "Cannot open file '" + p_path + "'.");
+
+ Ref<FileAccess> fw;
+
+ local_path = p_path.get_base_dir();
+
+ uint8_t header[4];
+ f->get_buffer(header, 4);
+ if (header[0] == 'R' && header[1] == 'S' && header[2] == 'C' && header[3] == 'C') {
+ // Compressed.
+ Ref<FileAccessCompressed> fac;
+ fac.instantiate();
+ Error err = fac->open_after_magic(f);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot open file '" + p_path + "'.");
+ f = fac;
+
+ Ref<FileAccessCompressed> facw;
+ facw.instantiate();
+ facw->configure("RSCC");
+ err = facw->open_internal(p_path + ".uidren", FileAccess::WRITE);
+ ERR_FAIL_COND_V_MSG(err, ERR_FILE_CORRUPT, "Cannot create file '" + p_path + ".uidren'.");
+
+ fw = facw;
+
+ } else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') {
+ // Not a binary resource.
+ return ERR_FILE_UNRECOGNIZED;
+ } else {
+ fw = FileAccess::open(p_path + ".uidren", FileAccess::WRITE);
+ ERR_FAIL_COND_V_MSG(fw.is_null(), ERR_CANT_CREATE, "Cannot create file '" + p_path + ".uidren'.");
+
+ uint8_t magich[4] = { 'R', 'S', 'R', 'C' };
+ fw->store_buffer(magich, 4);
+ }
+
+ big_endian = f->get_32();
+ bool use_real64 = f->get_32();
+ f->set_big_endian(big_endian != 0); //read big endian if saved as big endian
+#ifdef BIG_ENDIAN_ENABLED
+ fw->store_32(!big_endian);
+#else
+ fw->store_32(big_endian);
+#endif
+ fw->set_big_endian(big_endian != 0);
+ fw->store_32(use_real64); //use real64
+
+ uint32_t ver_major = f->get_32();
+ uint32_t ver_minor = f->get_32();
+ uint32_t ver_format = f->get_32();
+
+ if (ver_format < FORMAT_VERSION_CAN_RENAME_DEPS) {
+ fw.unref();
+
+ {
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ da->remove(p_path + ".uidren");
+ }
+
+ // Use the old approach.
+
+ WARN_PRINT("This file is old, so it does not support UIDs, opening and resaving '" + p_path + "'.");
+ return ERR_UNAVAILABLE;
+ }
+
+ if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) {
+ ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED,
+ vformat("File '%s' can't be loaded, as it uses a format version (%d) or engine version (%d.%d) which are not supported by your engine version (%s).",
+ local_path, ver_format, ver_major, ver_minor, VERSION_BRANCH));
+ }
+
+ // Since we're not actually converting the file contents, leave the version
+ // numbers in the file untouched.
+ fw->store_32(ver_major);
+ fw->store_32(ver_minor);
+ fw->store_32(ver_format);
+
+ save_ustring(fw, get_ustring(f)); //type
+
+ fw->store_64(f->get_64()); //metadata offset
+
+ uint32_t flags = f->get_32();
+ flags |= ResourceFormatSaverBinaryInstance::FORMAT_FLAG_UIDS;
+ f->get_64(); // Skip previous UID
+
+ fw->store_32(flags);
+ fw->store_64(p_uid);
+
+ //rest of file
+ uint8_t b = f->get_8();
+ while (!f->eof_reached()) {
+ fw->store_8(b);
+ b = f->get_8();
+ }
+
+ f.unref();
+
+ bool all_ok = fw->get_error() == OK;
+
+ if (!all_ok) {
+ return ERR_CANT_CREATE;
+ }
+
+ fw.unref();
+
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ da->remove(p_path);
+ da->rename(p_path + ".uidren", p_path);
+ return OK;
+}
+
Error ResourceFormatSaverBinary::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) {
String local_path = ProjectSettings::get_singleton()->localize_path(p_path);
ResourceFormatSaverBinaryInstance saver;
return saver.save(local_path, p_resource, p_flags);
}
+Error ResourceFormatSaverBinary::set_uid(const String &p_path, ResourceUID::ID p_uid) {
+ String local_path = ProjectSettings::get_singleton()->localize_path(p_path);
+ ResourceFormatSaverBinaryInstance saver;
+ return saver.set_uid(local_path, p_uid);
+}
+
bool ResourceFormatSaverBinary::recognize(const Ref<Resource> &p_resource) const {
return true; //all recognized
}
diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h
index 36613dbd58..9dd208e3cd 100644
--- a/core/io/resource_format_binary.h
+++ b/core/io/resource_format_binary.h
@@ -92,7 +92,6 @@ class ResourceLoaderBinary {
HashMap<String, Ref<Resource>> dependency_cache;
public:
- void set_local_path(const String &p_local_path);
Ref<Resource> get_resource();
Error load();
void set_translation_remapped(bool p_remapped);
@@ -170,6 +169,7 @@ public:
RESERVED_FIELDS = 11
};
Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0);
+ Error set_uid(const String &p_path, ResourceUID::ID p_uid);
static void write_variant(Ref<FileAccess> f, const Variant &p_property, HashMap<Ref<Resource>, int> &resource_map, HashMap<Ref<Resource>, int> &external_resources, HashMap<StringName, int> &string_map, const PropertyInfo &p_hint = PropertyInfo());
};
@@ -177,6 +177,7 @@ class ResourceFormatSaverBinary : public ResourceFormatSaver {
public:
static ResourceFormatSaverBinary *singleton;
virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0);
+ virtual Error set_uid(const String &p_path, ResourceUID::ID p_uid);
virtual bool recognize(const Ref<Resource> &p_resource) const;
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const;
diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp
index a4f4d705ee..dc1de6b9ce 100644
--- a/core/io/resource_importer.cpp
+++ b/core/io/resource_importer.cpp
@@ -31,6 +31,7 @@
#include "resource_importer.h"
#include "core/config/project_settings.h"
+#include "core/io/config_file.h"
#include "core/os/os.h"
#include "core/variant/variant_parser.h"
@@ -484,3 +485,18 @@ void ResourceFormatImporter::add_importer(const Ref<ResourceImporter> &p_importe
importers.push_back(p_importer);
}
}
+
+/////
+
+Error ResourceFormatImporterSaver::set_uid(const String &p_path, ResourceUID::ID p_uid) {
+ Ref<ConfigFile> cf;
+ cf.instantiate();
+ Error err = cf->load(p_path + ".import");
+ if (err != OK) {
+ return err;
+ }
+ cf->set_value("remap", "uid", ResourceUID::get_singleton()->id_to_text(p_uid));
+ cf->save(p_path + ".import");
+
+ return OK;
+}
diff --git a/core/io/resource_importer.h b/core/io/resource_importer.h
index b104a9dffe..0089544caa 100644
--- a/core/io/resource_importer.h
+++ b/core/io/resource_importer.h
@@ -32,6 +32,7 @@
#define RESOURCE_IMPORTER_H
#include "core/io/resource_loader.h"
+#include "core/io/resource_saver.h"
class ResourceImporter;
@@ -149,4 +150,11 @@ public:
VARIANT_ENUM_CAST(ResourceImporter::ImportOrder);
+class ResourceFormatImporterSaver : public ResourceFormatSaver {
+ GDCLASS(ResourceFormatImporterSaver, ResourceFormatSaver)
+
+public:
+ virtual Error set_uid(const String &p_path, ResourceUID::ID p_uid) override;
+};
+
#endif // RESOURCE_IMPORTER_H
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 946c31cf0d..68b9f8b6f7 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -1011,13 +1011,6 @@ bool ResourceLoader::add_custom_resource_format_loader(String script_path) {
return true;
}
-void ResourceLoader::remove_custom_resource_format_loader(String script_path) {
- Ref<ResourceFormatLoader> custom_loader = _find_custom_resource_format_loader(script_path);
- if (custom_loader.is_valid()) {
- remove_resource_format_loader(custom_loader);
- }
-}
-
void ResourceLoader::set_create_missing_resources_if_class_unavailable(bool p_enable) {
create_missing_resources_if_class_unavailable = p_enable;
}
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index 41ba0dc6e6..e427a2f5fc 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -225,7 +225,6 @@ public:
static ResourceLoaderImport import;
static bool add_custom_resource_format_loader(String script_path);
- static void remove_custom_resource_format_loader(String script_path);
static void add_custom_loaders();
static void remove_custom_loaders();
diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp
index de450a8420..b8201cc6b9 100644
--- a/core/io/resource_saver.cpp
+++ b/core/io/resource_saver.cpp
@@ -47,6 +47,12 @@ Error ResourceFormatSaver::save(const Ref<Resource> &p_resource, const String &p
return (Error)res;
}
+Error ResourceFormatSaver::set_uid(const String &p_path, ResourceUID::ID p_uid) {
+ Error err = ERR_FILE_UNRECOGNIZED;
+ GDVIRTUAL_CALL(_set_uid, p_path, p_uid, err);
+ return err;
+}
+
bool ResourceFormatSaver::recognize(const Ref<Resource> &p_resource) const {
bool success = false;
GDVIRTUAL_CALL(_recognize, p_resource, success);
@@ -85,6 +91,7 @@ bool ResourceFormatSaver::recognize_path(const Ref<Resource> &p_resource, const
void ResourceFormatSaver::_bind_methods() {
GDVIRTUAL_BIND(_save, "resource", "path", "flags");
+ GDVIRTUAL_BIND(_set_uid, "path", "uid");
GDVIRTUAL_BIND(_recognize, "resource");
GDVIRTUAL_BIND(_get_recognized_extensions, "resource");
GDVIRTUAL_BIND(_recognize_path, "resource", "path");
@@ -146,6 +153,23 @@ Error ResourceSaver::save(const Ref<Resource> &p_resource, const String &p_path,
return err;
}
+Error ResourceSaver::set_uid(const String &p_path, ResourceUID::ID p_uid) {
+ String path = p_path;
+
+ ERR_FAIL_COND_V_MSG(path.is_empty(), ERR_INVALID_PARAMETER, "Can't update UID to empty path. Provide non-empty path.");
+
+ Error err = ERR_FILE_UNRECOGNIZED;
+
+ for (int i = 0; i < saver_count; i++) {
+ err = saver[i]->set_uid(path, p_uid);
+ if (err == OK) {
+ break;
+ }
+ }
+
+ return err;
+}
+
void ResourceSaver::set_save_callback(ResourceSavedCallback p_callback) {
save_callback = p_callback;
}
@@ -226,13 +250,6 @@ bool ResourceSaver::add_custom_resource_format_saver(String script_path) {
return true;
}
-void ResourceSaver::remove_custom_resource_format_saver(String script_path) {
- Ref<ResourceFormatSaver> custom_saver = _find_custom_resource_format_saver(script_path);
- if (custom_saver.is_valid()) {
- remove_resource_format_saver(custom_saver);
- }
-}
-
void ResourceSaver::add_custom_savers() {
// Custom resource savers exploits global class names
diff --git a/core/io/resource_saver.h b/core/io/resource_saver.h
index f25463d71f..9e88b2086b 100644
--- a/core/io/resource_saver.h
+++ b/core/io/resource_saver.h
@@ -42,12 +42,14 @@ protected:
static void _bind_methods();
GDVIRTUAL3R(int64_t, _save, Ref<Resource>, String, uint32_t)
+ GDVIRTUAL2R(Error, _set_uid, String, ResourceUID::ID)
GDVIRTUAL1RC(bool, _recognize, Ref<Resource>)
GDVIRTUAL1RC(Vector<String>, _get_recognized_extensions, Ref<Resource>)
GDVIRTUAL2RC(bool, _recognize_path, Ref<Resource>, String)
public:
virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0);
+ virtual Error set_uid(const String &p_path, ResourceUID::ID p_uid);
virtual bool recognize(const Ref<Resource> &p_resource) const;
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const;
virtual bool recognize_path(const Ref<Resource> &p_resource, const String &p_path) const;
@@ -88,6 +90,8 @@ public:
static void add_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver, bool p_at_front = false);
static void remove_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver);
+ static Error set_uid(const String &p_path, ResourceUID::ID p_uid);
+
static void set_timestamp_on_save(bool p_timestamp) { timestamp_on_save = p_timestamp; }
static bool get_timestamp_on_save() { return timestamp_on_save; }
@@ -97,7 +101,6 @@ public:
static void set_get_resource_id_for_path(ResourceSaverGetResourceIDForPath p_callback);
static bool add_custom_resource_format_saver(String script_path);
- static void remove_custom_resource_format_saver(String script_path);
static void add_custom_savers();
static void remove_custom_savers();
};
diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp
index 09836419be..5c0a017bfc 100644
--- a/core/io/xml_parser.cpp
+++ b/core/io/xml_parser.cpp
@@ -354,10 +354,10 @@ void XMLParser::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_node_offset"), &XMLParser::get_node_offset);
ClassDB::bind_method(D_METHOD("get_attribute_count"), &XMLParser::get_attribute_count);
ClassDB::bind_method(D_METHOD("get_attribute_name", "idx"), &XMLParser::get_attribute_name);
- ClassDB::bind_method(D_METHOD("get_attribute_value", "idx"), (String(XMLParser::*)(int) const) & XMLParser::get_attribute_value);
+ ClassDB::bind_method(D_METHOD("get_attribute_value", "idx"), &XMLParser::get_attribute_value);
ClassDB::bind_method(D_METHOD("has_attribute", "name"), &XMLParser::has_attribute);
- ClassDB::bind_method(D_METHOD("get_named_attribute_value", "name"), (String(XMLParser::*)(const String &) const) & XMLParser::get_attribute_value);
- ClassDB::bind_method(D_METHOD("get_named_attribute_value_safe", "name"), &XMLParser::get_attribute_value_safe);
+ ClassDB::bind_method(D_METHOD("get_named_attribute_value", "name"), &XMLParser::get_named_attribute_value);
+ ClassDB::bind_method(D_METHOD("get_named_attribute_value_safe", "name"), &XMLParser::get_named_attribute_value_safe);
ClassDB::bind_method(D_METHOD("is_empty"), &XMLParser::is_empty);
ClassDB::bind_method(D_METHOD("get_current_line"), &XMLParser::get_current_line);
ClassDB::bind_method(D_METHOD("skip_section"), &XMLParser::skip_section);
@@ -422,7 +422,7 @@ bool XMLParser::has_attribute(const String &p_name) const {
return false;
}
-String XMLParser::get_attribute_value(const String &p_name) const {
+String XMLParser::get_named_attribute_value(const String &p_name) const {
int idx = -1;
for (int i = 0; i < attributes.size(); i++) {
if (attributes[i].name == p_name) {
@@ -436,7 +436,7 @@ String XMLParser::get_attribute_value(const String &p_name) const {
return attributes[idx].value;
}
-String XMLParser::get_attribute_value_safe(const String &p_name) const {
+String XMLParser::get_named_attribute_value_safe(const String &p_name) const {
int idx = -1;
for (int i = 0; i < attributes.size(); i++) {
if (attributes[i].name == p_name) {
diff --git a/core/io/xml_parser.h b/core/io/xml_parser.h
index b4ae5c93b6..b96478c7a5 100644
--- a/core/io/xml_parser.h
+++ b/core/io/xml_parser.h
@@ -109,8 +109,8 @@ public:
String get_attribute_name(int p_idx) const;
String get_attribute_value(int p_idx) const;
bool has_attribute(const String &p_name) const;
- String get_attribute_value(const String &p_name) const;
- String get_attribute_value_safe(const String &p_name) const; // do not print error if doesn't exist
+ String get_named_attribute_value(const String &p_name) const;
+ String get_named_attribute_value_safe(const String &p_name) const; // do not print error if doesn't exist
bool is_empty() const;
int get_current_line() const;
diff --git a/core/math/a_star_grid_2d.cpp b/core/math/a_star_grid_2d.cpp
index cacdde6da5..30d50073d7 100644
--- a/core/math/a_star_grid_2d.cpp
+++ b/core/math/a_star_grid_2d.cpp
@@ -528,7 +528,7 @@ TypedArray<Vector2i> AStarGrid2D::get_id_path(const Vector2i &p_from_id, const V
if (a == b) {
TypedArray<Vector2i> ret;
- ret.push_back(a);
+ ret.push_back(a->id);
return ret;
}
diff --git a/core/math/basis.cpp b/core/math/basis.cpp
index 39e383fb49..234a4ddb79 100644
--- a/core/math/basis.cpp
+++ b/core/math/basis.cpp
@@ -36,23 +36,6 @@
#define cofac(row1, col1, row2, col2) \
(rows[row1][col1] * rows[row2][col2] - rows[row1][col2] * rows[row2][col1])
-void Basis::from_z(const Vector3 &p_z) {
- if (Math::abs(p_z.z) > (real_t)Math_SQRT12) {
- // choose p in y-z plane
- real_t a = p_z[1] * p_z[1] + p_z[2] * p_z[2];
- real_t k = 1.0f / Math::sqrt(a);
- rows[0] = Vector3(0, -p_z[2] * k, p_z[1] * k);
- rows[1] = Vector3(a * k, -p_z[0] * rows[0][2], p_z[0] * rows[0][1]);
- } else {
- // choose p in x-y plane
- real_t a = p_z.x * p_z.x + p_z.y * p_z.y;
- real_t k = 1.0f / Math::sqrt(a);
- rows[0] = Vector3(-p_z.y * k, p_z.x * k, 0);
- rows[1] = Vector3(-p_z.z * rows[0].y, p_z.z * rows[0].x, a * k);
- }
- rows[2] = p_z;
-}
-
void Basis::invert() {
real_t co[3] = {
cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1)
@@ -271,14 +254,6 @@ float Basis::get_uniform_scale() const {
return (rows[0].length() + rows[1].length() + rows[2].length()) / 3.0f;
}
-void Basis::make_scale_uniform() {
- float l = (rows[0].length() + rows[1].length() + rows[2].length()) / 3.0f;
- for (int i = 0; i < 3; i++) {
- rows[i].normalize();
- rows[i] *= l;
- }
-}
-
Basis Basis::scaled_local(const Vector3 &p_scale) const {
return (*this) * Basis::from_scale(p_scale);
}
diff --git a/core/math/basis.h b/core/math/basis.h
index b3197dbc84..bbc1d40469 100644
--- a/core/math/basis.h
+++ b/core/math/basis.h
@@ -56,8 +56,6 @@ struct _NO_DISCARD_ Basis {
_FORCE_INLINE_ real_t determinant() const;
- void from_z(const Vector3 &p_z);
-
void rotate(const Vector3 &p_axis, real_t p_angle);
Basis rotated(const Vector3 &p_axis, real_t p_angle) const;
@@ -101,8 +99,6 @@ struct _NO_DISCARD_ Basis {
void scale_orthogonal(const Vector3 &p_scale);
Basis scaled_orthogonal(const Vector3 &p_scale) const;
-
- void make_scale_uniform();
float get_uniform_scale() const;
Vector3 get_scale() const;
diff --git a/core/math/face3.cpp b/core/math/face3.cpp
index e53bbf872b..1dff0ee4a6 100644
--- a/core/math/face3.cpp
+++ b/core/math/face3.cpp
@@ -120,36 +120,6 @@ bool Face3::is_degenerate() const {
return (normal.length_squared() < (real_t)CMP_EPSILON2);
}
-Face3::Side Face3::get_side_of(const Face3 &p_face, ClockDirection p_clock_dir) const {
- int over = 0, under = 0;
-
- Plane plane = get_plane(p_clock_dir);
-
- for (int i = 0; i < 3; i++) {
- const Vector3 &v = p_face.vertex[i];
-
- if (plane.has_point(v)) { //coplanar, don't bother
- continue;
- }
-
- if (plane.is_point_over(v)) {
- over++;
- } else {
- under++;
- }
- }
-
- if (over > 0 && under == 0) {
- return SIDE_OVER;
- } else if (under > 0 && over == 0) {
- return SIDE_UNDER;
- } else if (under == 0 && over == 0) {
- return SIDE_COPLANAR;
- } else {
- return SIDE_SPANNING;
- }
-}
-
Vector3 Face3::get_random_point_inside() const {
real_t a = Math::random(0.0, 1.0);
real_t b = Math::random(0.0, 1.0);
@@ -164,20 +134,10 @@ Plane Face3::get_plane(ClockDirection p_dir) const {
return Plane(vertex[0], vertex[1], vertex[2], p_dir);
}
-Vector3 Face3::get_median_point() const {
- return (vertex[0] + vertex[1] + vertex[2]) / 3.0f;
-}
-
real_t Face3::get_area() const {
return vec3_cross(vertex[0] - vertex[1], vertex[0] - vertex[2]).length() * 0.5f;
}
-ClockDirection Face3::get_clock_dir() const {
- Vector3 normal = vec3_cross(vertex[0] - vertex[1], vertex[0] - vertex[2]);
- //printf("normal is %g,%g,%g x %g,%g,%g- wtfu is %g\n",tofloat(normal.x),tofloat(normal.y),tofloat(normal.z),tofloat(vertex[0].x),tofloat(vertex[0].y),tofloat(vertex[0].z),tofloat( normal.dot( vertex[0] ) ) );
- return (normal.dot(vertex[0]) >= 0) ? CLOCKWISE : COUNTERCLOCKWISE;
-}
-
bool Face3::intersects_aabb(const AABB &p_aabb) const {
/** TEST PLANE **/
if (!p_aabb.intersects_plane(get_plane())) {
diff --git a/core/math/face3.h b/core/math/face3.h
index 3d87de03dc..3dd47d0226 100644
--- a/core/math/face3.h
+++ b/core/math/face3.h
@@ -57,19 +57,14 @@ struct _NO_DISCARD_ Face3 {
Plane get_plane(ClockDirection p_dir = CLOCKWISE) const;
Vector3 get_random_point_inside() const;
- Side get_side_of(const Face3 &p_face, ClockDirection p_clock_dir = CLOCKWISE) const;
-
bool is_degenerate() const;
real_t get_area() const;
- Vector3 get_median_point() const;
Vector3 get_closest_point_to(const Vector3 &p_point) const;
bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection = nullptr) const;
bool intersects_segment(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection = nullptr) const;
- ClockDirection get_clock_dir() const; ///< todo, test if this is returning the proper clockwisity
-
void get_support(const Vector3 &p_normal, const Transform3D &p_transform, Vector3 *p_vertices, int *p_count, int p_max) const;
void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const;
diff --git a/core/math/geometry_2d.cpp b/core/math/geometry_2d.cpp
index a0b76d31cb..74cb92539a 100644
--- a/core/math/geometry_2d.cpp
+++ b/core/math/geometry_2d.cpp
@@ -320,41 +320,6 @@ Vector<Vector<Point2>> Geometry2D::_polypath_offset(const Vector<Point2> &p_poly
return polypaths;
}
-Vector<Point2i> Geometry2D::pack_rects(const Vector<Size2i> &p_sizes, const Size2i &p_atlas_size) {
- Vector<stbrp_node> nodes;
- nodes.resize(p_atlas_size.width);
-
- stbrp_context context;
- stbrp_init_target(&context, p_atlas_size.width, p_atlas_size.height, nodes.ptrw(), p_atlas_size.width);
-
- Vector<stbrp_rect> rects;
- rects.resize(p_sizes.size());
-
- for (int i = 0; i < p_sizes.size(); i++) {
- rects.write[i].id = 0;
- rects.write[i].w = p_sizes[i].width;
- rects.write[i].h = p_sizes[i].height;
- rects.write[i].x = 0;
- rects.write[i].y = 0;
- rects.write[i].was_packed = 0;
- }
-
- int res = stbrp_pack_rects(&context, rects.ptrw(), rects.size());
- if (res == 0) { //pack failed
- return Vector<Point2i>();
- }
-
- Vector<Point2i> ret;
- ret.resize(p_sizes.size());
-
- for (int i = 0; i < p_sizes.size(); i++) {
- Point2i r(rects[i].x, rects[i].y);
- ret.write[i] = r;
- }
-
- return ret;
-}
-
Vector<Vector3i> Geometry2D::partial_pack_rects(const Vector<Vector2i> &p_sizes, const Size2i &p_atlas_size) {
Vector<stbrp_node> nodes;
nodes.resize(p_atlas_size.width);
diff --git a/core/math/geometry_2d.h b/core/math/geometry_2d.h
index b55aecf85e..0e5702e0af 100644
--- a/core/math/geometry_2d.h
+++ b/core/math/geometry_2d.h
@@ -464,7 +464,6 @@ public:
static Vector<Vector<Vector2>> decompose_polygon_in_convex(Vector<Point2> polygon);
static void make_atlas(const Vector<Size2i> &p_rects, Vector<Point2i> &r_result, Size2i &r_size);
- static Vector<Point2i> pack_rects(const Vector<Size2i> &p_sizes, const Size2i &p_atlas_size);
static Vector<Vector3i> partial_pack_rects(const Vector<Vector2i> &p_sizes, const Size2i &p_atlas_size);
private:
diff --git a/core/math/geometry_3d.cpp b/core/math/geometry_3d.cpp
index 3ac78e0709..51523ea296 100644
--- a/core/math/geometry_3d.cpp
+++ b/core/math/geometry_3d.cpp
@@ -198,149 +198,6 @@ struct _FaceClassify {
_FaceClassify() {}
};
-static bool _connect_faces(_FaceClassify *p_faces, int len, int p_group) {
- // Connect faces, error will occur if an edge is shared between more than 2 faces.
- // Clear connections.
-
- bool error = false;
-
- for (int i = 0; i < len; i++) {
- for (int j = 0; j < 3; j++) {
- p_faces[i].links[j].clear();
- }
- }
-
- for (int i = 0; i < len; i++) {
- if (p_faces[i].group != p_group) {
- continue;
- }
- for (int j = i + 1; j < len; j++) {
- if (p_faces[j].group != p_group) {
- continue;
- }
-
- for (int k = 0; k < 3; k++) {
- Vector3 vi1 = p_faces[i].face.vertex[k];
- Vector3 vi2 = p_faces[i].face.vertex[(k + 1) % 3];
-
- for (int l = 0; l < 3; l++) {
- Vector3 vj2 = p_faces[j].face.vertex[l];
- Vector3 vj1 = p_faces[j].face.vertex[(l + 1) % 3];
-
- if (vi1.distance_to(vj1) < 0.00001f &&
- vi2.distance_to(vj2) < 0.00001f) {
- if (p_faces[i].links[k].face != -1) {
- ERR_PRINT("already linked\n");
- error = true;
- break;
- }
- if (p_faces[j].links[l].face != -1) {
- ERR_PRINT("already linked\n");
- error = true;
- break;
- }
-
- p_faces[i].links[k].face = j;
- p_faces[i].links[k].edge = l;
- p_faces[j].links[l].face = i;
- p_faces[j].links[l].edge = k;
- }
- }
- if (error) {
- break;
- }
- }
- if (error) {
- break;
- }
- }
- if (error) {
- break;
- }
- }
-
- for (int i = 0; i < len; i++) {
- p_faces[i].valid = true;
- for (int j = 0; j < 3; j++) {
- if (p_faces[i].links[j].face == -1) {
- p_faces[i].valid = false;
- }
- }
- }
- return error;
-}
-
-static bool _group_face(_FaceClassify *p_faces, int len, int p_index, int p_group) {
- if (p_faces[p_index].group >= 0) {
- return false;
- }
-
- p_faces[p_index].group = p_group;
-
- for (int i = 0; i < 3; i++) {
- ERR_FAIL_INDEX_V(p_faces[p_index].links[i].face, len, true);
- _group_face(p_faces, len, p_faces[p_index].links[i].face, p_group);
- }
-
- return true;
-}
-
-Vector<Vector<Face3>> Geometry3D::separate_objects(Vector<Face3> p_array) {
- Vector<Vector<Face3>> objects;
-
- int len = p_array.size();
-
- const Face3 *arrayptr = p_array.ptr();
-
- Vector<_FaceClassify> fc;
-
- fc.resize(len);
-
- _FaceClassify *_fcptr = fc.ptrw();
-
- for (int i = 0; i < len; i++) {
- _fcptr[i].face = arrayptr[i];
- }
-
- bool error = _connect_faces(_fcptr, len, -1);
-
- ERR_FAIL_COND_V_MSG(error, Vector<Vector<Face3>>(), "Invalid geometry.");
-
- // Group connected faces in separate objects.
-
- int group = 0;
- for (int i = 0; i < len; i++) {
- if (!_fcptr[i].valid) {
- continue;
- }
- if (_group_face(_fcptr, len, i, group)) {
- group++;
- }
- }
-
- // Group connected faces in separate objects.
-
- for (int i = 0; i < len; i++) {
- _fcptr[i].face = arrayptr[i];
- }
-
- if (group >= 0) {
- objects.resize(group);
- Vector<Face3> *group_faces = objects.ptrw();
-
- for (int i = 0; i < len; i++) {
- if (!_fcptr[i].valid) {
- continue;
- }
- if (_fcptr[i].group >= 0 && _fcptr[i].group < group) {
- group_faces[_fcptr[i].group].push_back(_fcptr[i].face);
- }
- }
- }
-
- return objects;
-}
-
/*** GEOMETRY WRAPPER ***/
enum _CellFlags {
@@ -748,7 +605,7 @@ Geometry3D::MeshData Geometry3D::build_convex_mesh(const Vector<Plane> &p_planes
Vector3 right = p.normal.cross(ref).normalized();
Vector3 up = p.normal.cross(right).normalized();
- Vector3 center = p.center();
+ Vector3 center = p.get_center();
// make a quad clockwise
LocalVector<Vector3> vertices = {
diff --git a/core/math/geometry_3d.h b/core/math/geometry_3d.h
index 6759db5766..99c554fe05 100644
--- a/core/math/geometry_3d.h
+++ b/core/math/geometry_3d.h
@@ -532,8 +532,6 @@ public:
return clipped;
}
- static Vector<Vector<Face3>> separate_objects(Vector<Face3> p_array);
-
// Create a "wrap" that encloses the given geometry.
static Vector<Face3> wrap_geometry(Vector<Face3> p_array, real_t *p_error = nullptr);
diff --git a/core/math/plane.h b/core/math/plane.h
index 3bc7c54b9d..8159f25342 100644
--- a/core/math/plane.h
+++ b/core/math/plane.h
@@ -47,7 +47,7 @@ struct _NO_DISCARD_ Plane {
/* Plane-Point operations */
- _FORCE_INLINE_ Vector3 center() const { return normal * d; }
+ _FORCE_INLINE_ Vector3 get_center() const { return normal * d; }
Vector3 get_any_perpendicular_normal() const;
_FORCE_INLINE_ bool is_point_over(const Vector3 &p_point) const; ///< Point is over plane
diff --git a/core/math/transform_2d.cpp b/core/math/transform_2d.cpp
index 6a7ee32230..910995d717 100644
--- a/core/math/transform_2d.cpp
+++ b/core/math/transform_2d.cpp
@@ -221,12 +221,6 @@ Transform2D Transform2D::operator*(const Transform2D &p_transform) const {
return t;
}
-Transform2D Transform2D::basis_scaled(const Size2 &p_scale) const {
- Transform2D copy = *this;
- copy.scale_basis(p_scale);
- return copy;
-}
-
Transform2D Transform2D::scaled(const Size2 &p_scale) const {
// Equivalent to left multiplication
Transform2D copy = *this;
diff --git a/core/math/transform_2d.h b/core/math/transform_2d.h
index 2a0917c63f..4a17a9db37 100644
--- a/core/math/transform_2d.h
+++ b/core/math/transform_2d.h
@@ -85,7 +85,6 @@ struct _NO_DISCARD_ Transform2D {
_FORCE_INLINE_ const Vector2 &get_origin() const { return columns[2]; }
_FORCE_INLINE_ void set_origin(const Vector2 &p_origin) { columns[2] = p_origin; }
- Transform2D basis_scaled(const Size2 &p_scale) const;
Transform2D scaled(const Size2 &p_scale) const;
Transform2D scaled_local(const Size2 &p_scale) const;
Transform2D translated(const Vector2 &p_offset) const;
diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp
index 4b6921d38b..0da1b8c7ad 100644
--- a/core/math/triangle_mesh.cpp
+++ b/core/math/triangle_mesh.cpp
@@ -182,90 +182,6 @@ void TriangleMesh::create(const Vector<Vector3> &p_faces, const Vector<int32_t>
valid = true;
}
-Vector3 TriangleMesh::get_area_normal(const AABB &p_aabb) const {
- uint32_t *stack = (uint32_t *)alloca(sizeof(int) * max_depth);
-
- enum {
- TEST_AABB_BIT = 0,
- VISIT_LEFT_BIT = 1,
- VISIT_RIGHT_BIT = 2,
- VISIT_DONE_BIT = 3,
- VISITED_BIT_SHIFT = 29,
- NODE_IDX_MASK = (1 << VISITED_BIT_SHIFT) - 1,
- VISITED_BIT_MASK = ~NODE_IDX_MASK,
-
- };
-
- int n_count = 0;
- Vector3 n;
-
- int level = 0;
-
- const Triangle *triangleptr = triangles.ptr();
- // const Vector3 *verticesr = vertices.ptr();
- const BVH *bvhptr = bvh.ptr();
-
- int pos = bvh.size() - 1;
-
- stack[0] = pos;
- while (true) {
- uint32_t node = stack[level] & NODE_IDX_MASK;
- const BVH &b = bvhptr[node];
- bool done = false;
-
- switch (stack[level] >> VISITED_BIT_SHIFT) {
- case TEST_AABB_BIT: {
- if (!b.aabb.intersects(p_aabb)) {
- stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
- } else {
- if (b.face_index >= 0) {
- const Triangle &s = triangleptr[b.face_index];
- n += s.normal;
- n_count++;
-
- stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
-
- } else {
- stack[level] = (VISIT_LEFT_BIT << VISITED_BIT_SHIFT) | node;
- }
- }
- continue;
- }
- case VISIT_LEFT_BIT: {
- stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node;
- level++;
- stack[level] = b.left | TEST_AABB_BIT;
- continue;
- }
- case VISIT_RIGHT_BIT: {
- stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
- level++;
- stack[level] = b.right | TEST_AABB_BIT;
- continue;
- }
- case VISIT_DONE_BIT: {
- if (level == 0) {
- done = true;
- break;
- } else {
- level--;
- }
- continue;
- }
- }
-
- if (done) {
- break;
- }
- }
-
- if (n_count > 0) {
- n /= n_count;
- }
-
- return n;
-}
-
bool TriangleMesh::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal, int32_t *r_surf_index) const {
uint32_t *stack = (uint32_t *)alloca(sizeof(int) * max_depth);
@@ -468,118 +384,6 @@ bool TriangleMesh::intersect_ray(const Vector3 &p_begin, const Vector3 &p_dir, V
return inters;
}
-bool TriangleMesh::intersect_convex_shape(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count) const {
- uint32_t *stack = (uint32_t *)alloca(sizeof(int) * max_depth);
-
- //p_fully_inside = true;
-
- enum {
- TEST_AABB_BIT = 0,
- VISIT_LEFT_BIT = 1,
- VISIT_RIGHT_BIT = 2,
- VISIT_DONE_BIT = 3,
- VISITED_BIT_SHIFT = 29,
- NODE_IDX_MASK = (1 << VISITED_BIT_SHIFT) - 1,
- VISITED_BIT_MASK = ~NODE_IDX_MASK,
-
- };
-
- int level = 0;
-
- const Triangle *triangleptr = triangles.ptr();
- const Vector3 *vertexptr = vertices.ptr();
- const BVH *bvhptr = bvh.ptr();
-
- int pos = bvh.size() - 1;
-
- stack[0] = pos;
- while (true) {
- uint32_t node = stack[level] & NODE_IDX_MASK;
- const BVH &b = bvhptr[node];
- bool done = false;
-
- switch (stack[level] >> VISITED_BIT_SHIFT) {
- case TEST_AABB_BIT: {
- if (!b.aabb.intersects_convex_shape(p_planes, p_plane_count, p_points, p_point_count)) {
- stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
- } else {
- if (b.face_index >= 0) {
- const Triangle &s = triangleptr[b.face_index];
-
- for (int j = 0; j < 3; ++j) {
- const Vector3 &point = vertexptr[s.indices[j]];
- const Vector3 &next_point = vertexptr[s.indices[(j + 1) % 3]];
- Vector3 res;
- bool over = true;
- for (int i = 0; i < p_plane_count; i++) {
- const Plane &p = p_planes[i];
-
- if (p.intersects_segment(point, next_point, &res)) {
- bool inisde = true;
- for (int k = 0; k < p_plane_count; k++) {
- if (k == i) {
- continue;
- }
- const Plane &pp = p_planes[k];
- if (pp.is_point_over(res)) {
- inisde = false;
- break;
- }
- }
- if (inisde) {
- return true;
- }
- }
-
- if (p.is_point_over(point)) {
- over = false;
- break;
- }
- }
- if (over) {
- return true;
- }
- }
-
- stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
-
- } else {
- stack[level] = (VISIT_LEFT_BIT << VISITED_BIT_SHIFT) | node;
- }
- }
- continue;
- }
- case VISIT_LEFT_BIT: {
- stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node;
- level++;
- stack[level] = b.left | TEST_AABB_BIT;
- continue;
- }
- case VISIT_RIGHT_BIT: {
- stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
- level++;
- stack[level] = b.right | TEST_AABB_BIT;
- continue;
- }
- case VISIT_DONE_BIT: {
- if (level == 0) {
- done = true;
- break;
- } else {
- level--;
- }
- continue;
- }
- }
-
- if (done) {
- break;
- }
- }
-
- return false;
-}
-
bool TriangleMesh::inside_convex_shape(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count, Vector3 p_scale) const {
uint32_t *stack = (uint32_t *)alloca(sizeof(int) * max_depth);
diff --git a/core/math/triangle_mesh.h b/core/math/triangle_mesh.h
index 728fd600d5..24fc12dda9 100644
--- a/core/math/triangle_mesh.h
+++ b/core/math/triangle_mesh.h
@@ -84,9 +84,7 @@ public:
bool is_valid() const;
bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal, int32_t *r_surf_index = nullptr) const;
bool intersect_ray(const Vector3 &p_begin, const Vector3 &p_dir, Vector3 &r_point, Vector3 &r_normal, int32_t *r_surf_index = nullptr) const;
- bool intersect_convex_shape(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count) const;
bool inside_convex_shape(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count, Vector3 p_scale = Vector3(1, 1, 1)) const;
- Vector3 get_area_normal(const AABB &p_aabb) const;
Vector<Face3> get_faces() const;
const Vector<Triangle> &get_triangles() const { return triangles; }
diff --git a/core/object/method_bind.h b/core/object/method_bind.h
index a59129c3e2..8334a7eef6 100644
--- a/core/object/method_bind.h
+++ b/core/object/method_bind.h
@@ -33,7 +33,7 @@
#include "core/variant/binder_common.h"
-VARIANT_ENUM_CAST(MethodFlags)
+VARIANT_BITFIELD_CAST(MethodFlags)
// some helpers
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 8bc2f89c27..2cb56dfe6c 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -1594,25 +1594,6 @@ bool Object::is_blocking_signals() const {
return _block_signals;
}
-void Object::get_translatable_strings(List<String> *p_strings) const {
- List<PropertyInfo> plist;
- get_property_list(&plist);
-
- for (const PropertyInfo &E : plist) {
- if (!(E.usage & PROPERTY_USAGE_INTERNATIONALIZED)) {
- continue;
- }
-
- String text = get(E.name);
-
- if (text.is_empty()) {
- continue;
- }
-
- p_strings->push_back(text);
- }
-}
-
Variant::Type Object::get_static_property_type(const StringName &p_property, bool *r_valid) const {
bool valid;
Variant::Type t = ClassDB::get_property_type(get_class_name(), p_property, &valid);
diff --git a/core/object/object.h b/core/object/object.h
index 2ba86c9d31..f78c7c34fd 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -74,14 +74,6 @@ enum PropertyHint {
PROPERTY_HINT_OBJECT_ID,
PROPERTY_HINT_TYPE_STRING, ///< a type string, the hint is the base type to choose
PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE, ///< so something else can provide this (used in scripts)
- PROPERTY_HINT_METHOD_OF_VARIANT_TYPE, ///< a method of a type
- PROPERTY_HINT_METHOD_OF_BASE_TYPE, ///< a method of a base type
- PROPERTY_HINT_METHOD_OF_INSTANCE, ///< a method of an instance
- PROPERTY_HINT_METHOD_OF_SCRIPT, ///< a method of a script & base
- PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE, ///< a property of a type
- PROPERTY_HINT_PROPERTY_OF_BASE_TYPE, ///< a property of a base type
- PROPERTY_HINT_PROPERTY_OF_INSTANCE, ///< a property of an instance
- PROPERTY_HINT_PROPERTY_OF_SCRIPT, ///< a property of a script & base
PROPERTY_HINT_OBJECT_TOO_BIG, ///< object is too big to send
PROPERTY_HINT_NODE_PATH_VALID_TYPES,
PROPERTY_HINT_SAVE_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,". This opens a save dialog
@@ -95,16 +87,15 @@ enum PropertyHint {
PROPERTY_HINT_HIDE_QUATERNION_EDIT, /// Only Node3D::transform should hide the quaternion editor.
PROPERTY_HINT_PASSWORD,
PROPERTY_HINT_MAX,
- // When updating PropertyHint, also sync the hardcoded list in VisualScriptEditorVariableEdit
};
enum PropertyUsageFlags {
PROPERTY_USAGE_NONE = 0,
PROPERTY_USAGE_STORAGE = 1 << 1,
PROPERTY_USAGE_EDITOR = 1 << 2,
- PROPERTY_USAGE_CHECKABLE = 1 << 3, // Used for editing global variables.
- PROPERTY_USAGE_CHECKED = 1 << 4, // Used for editing global variables.
- PROPERTY_USAGE_INTERNATIONALIZED = 1 << 5, // Hint for internationalized strings.
+ PROPERTY_USAGE_INTERNAL = 1 << 3,
+ PROPERTY_USAGE_CHECKABLE = 1 << 4, // Used for editing global variables.
+ PROPERTY_USAGE_CHECKED = 1 << 5, // Used for editing global variables.
PROPERTY_USAGE_GROUP = 1 << 6, // Used for grouping props in the editor.
PROPERTY_USAGE_CATEGORY = 1 << 7,
PROPERTY_USAGE_SUBGROUP = 1 << 8,
@@ -117,7 +108,7 @@ enum PropertyUsageFlags {
PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE = 1 << 15,
PROPERTY_USAGE_CLASS_IS_ENUM = 1 << 16,
PROPERTY_USAGE_NIL_IS_VARIANT = 1 << 17,
- PROPERTY_USAGE_INTERNAL = 1 << 18,
+ PROPERTY_USAGE_ARRAY = 1 << 18, // Used in the inspector to group properties as elements of an array.
PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE = 1 << 19, // If the object is duplicated also this property will be duplicated.
PROPERTY_USAGE_HIGH_END_GFX = 1 << 20,
PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT = 1 << 21,
@@ -127,10 +118,8 @@ enum PropertyUsageFlags {
PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT = 1 << 25, // For Object properties, instantiate them when creating in editor.
PROPERTY_USAGE_EDITOR_BASIC_SETTING = 1 << 26, //for project or editor settings, show when basic settings are selected.
PROPERTY_USAGE_READ_ONLY = 1 << 27, // Mark a property as read-only in the inspector.
- PROPERTY_USAGE_ARRAY = 1 << 28, // Used in the inspector to group properties as elements of an array.
PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR,
- PROPERTY_USAGE_DEFAULT_INTL = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNATIONALIZED,
PROPERTY_USAGE_NO_EDITOR = PROPERTY_USAGE_STORAGE,
};
@@ -894,8 +883,6 @@ public:
Variant::Type get_static_property_type(const StringName &p_property, bool *r_valid = nullptr) const;
Variant::Type get_static_property_type_indexed(const Vector<StringName> &p_path, bool *r_valid = nullptr) const;
- virtual void get_translatable_strings(List<String> *p_strings) const;
-
virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const;
// Translate message (internationalization).
diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp
index 7be3a6c688..66ef418e42 100644
--- a/core/object/script_language.cpp
+++ b/core/object/script_language.cpp
@@ -186,6 +186,7 @@ void ScriptServer::unregister_language(const ScriptLanguage *p_language) {
void ScriptServer::init_languages() {
{ // Load global classes.
global_classes_clear();
+#ifndef DISABLE_DEPRECATED
if (ProjectSettings::get_singleton()->has_setting("_global_script_classes")) {
Array script_classes = GLOBAL_GET("_global_script_classes");
@@ -196,6 +197,17 @@ void ScriptServer::init_languages() {
}
add_global_class(c["class"], c["base"], c["language"], c["path"]);
}
+ ProjectSettings::get_singleton()->clear("_global_script_classes");
+ }
+#endif
+
+ Array script_classes = ProjectSettings::get_singleton()->get_global_class_list();
+ for (int i = 0; i < script_classes.size(); i++) {
+ Dictionary c = script_classes[i];
+ if (!c.has("class") || !c.has("language") || !c.has("path") || !c.has("base")) {
+ continue;
+ }
+ add_global_class(c["class"], c["base"], c["language"], c["path"]);
}
}
@@ -251,6 +263,15 @@ void ScriptServer::remove_global_class(const StringName &p_class) {
global_classes.erase(p_class);
}
+void ScriptServer::remove_global_class_by_path(const String &p_path) {
+ for (const KeyValue<StringName, GlobalScriptClass> &kv : global_classes) {
+ if (kv.value.path == p_path) {
+ global_classes.erase(kv.key);
+ return;
+ }
+ }
+}
+
bool ScriptServer::is_global_class(const StringName &p_class) {
return global_classes.has(p_class);
}
@@ -291,6 +312,17 @@ void ScriptServer::get_global_class_list(List<StringName> *r_global_classes) {
}
void ScriptServer::save_global_classes() {
+ Dictionary class_icons;
+
+ Array script_classes = ProjectSettings::get_singleton()->get_global_class_list();
+ for (int i = 0; i < script_classes.size(); i++) {
+ Dictionary d = script_classes[i];
+ if (!d.has("name") || !d.has("icon")) {
+ continue;
+ }
+ class_icons[d["name"]] = d["icon"];
+ }
+
List<StringName> gc;
get_global_class_list(&gc);
Array gcarr;
@@ -300,25 +332,10 @@ void ScriptServer::save_global_classes() {
d["language"] = global_classes[E].language;
d["path"] = global_classes[E].path;
d["base"] = global_classes[E].base;
+ d["icon"] = class_icons.get(E, "");
gcarr.push_back(d);
}
-
- Array old;
- if (ProjectSettings::get_singleton()->has_setting("_global_script_classes")) {
- old = GLOBAL_GET("_global_script_classes");
- }
- if ((!old.is_empty() || gcarr.is_empty()) && gcarr.hash() == old.hash()) {
- return;
- }
-
- if (gcarr.is_empty()) {
- if (ProjectSettings::get_singleton()->has_setting("_global_script_classes")) {
- ProjectSettings::get_singleton()->clear("_global_script_classes");
- }
- } else {
- ProjectSettings::get_singleton()->set("_global_script_classes", gcarr);
- }
- ProjectSettings::get_singleton()->save();
+ ProjectSettings::get_singleton()->store_global_class_list(gcarr);
}
////////////////////
diff --git a/core/object/script_language.h b/core/object/script_language.h
index ff678bcd25..02d1880dc2 100644
--- a/core/object/script_language.h
+++ b/core/object/script_language.h
@@ -80,6 +80,7 @@ public:
static void global_classes_clear();
static void add_global_class(const StringName &p_class, const StringName &p_base, const StringName &p_language, const String &p_path);
static void remove_global_class(const StringName &p_class);
+ static void remove_global_class_by_path(const String &p_path);
static bool is_global_class(const StringName &p_class);
static StringName get_global_class_language(const StringName &p_class);
static String get_global_class_path(const String &p_class);
diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h
index b705d13cd6..912f2218c4 100644
--- a/core/object/script_language_extension.h
+++ b/core/object/script_language_extension.h
@@ -125,7 +125,8 @@ public:
}
Variant ret;
GDVIRTUAL_REQUIRED_CALL(_get_property_default_value, p_property, ret);
- return ret;
+ r_value = ret;
+ return true;
}
EXBIND0(update_exports)
diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp
index e0231b818f..5183b77cb1 100644
--- a/core/os/keyboard.cpp
+++ b/core/os/keyboard.cpp
@@ -63,12 +63,15 @@ static const _KeyCodeText _keycodes[] = {
{Key::CTRL ,"Ctrl"},
#if defined(MACOS_ENABLED)
{Key::META ,"Command"},
+ {Key::CMD_OR_CTRL ,"Command"},
{Key::ALT ,"Option"},
#elif defined(WINDOWS_ENABLED)
{Key::META ,"Windows"},
+ {Key::CMD_OR_CTRL ,"Ctrl"},
{Key::ALT ,"Alt"},
#else
{Key::META ,"Meta"},
+ {Key::CMD_OR_CTRL ,"Ctrl"},
{Key::ALT ,"Alt"},
#endif
{Key::CAPSLOCK ,"CapsLock"},
diff --git a/core/os/keyboard.h b/core/os/keyboard.h
index 389baee915..c78fa2a631 100644
--- a/core/os/keyboard.h
+++ b/core/os/keyboard.h
@@ -65,6 +65,11 @@ enum class Key {
SHIFT = SPECIAL | 0x15,
CTRL = SPECIAL | 0x16,
META = SPECIAL | 0x17,
+#if defined(MACOS_ENABLED)
+ CMD_OR_CTRL = META,
+#else
+ CMD_OR_CTRL = CTRL,
+#endif
ALT = SPECIAL | 0x18,
CAPSLOCK = SPECIAL | 0x19,
NUMLOCK = SPECIAL | 0x1A,
diff --git a/core/os/os.h b/core/os/os.h
index 3c0c05f575..4818e9281a 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -131,7 +131,7 @@ public:
void print_rich(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3;
void printerr(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3;
- virtual String get_stdin_string(bool p_block = true) = 0;
+ virtual String get_stdin_string() = 0;
virtual Error get_entropy(uint8_t *r_buffer, int p_bytes) = 0; // Should return cryptographically-safe random bytes.
@@ -167,7 +167,8 @@ public:
virtual bool has_environment(const String &p_var) const = 0;
virtual String get_environment(const String &p_var) const = 0;
- virtual bool set_environment(const String &p_var, const String &p_value) const = 0;
+ virtual void set_environment(const String &p_var, const String &p_value) const = 0;
+ virtual void unset_environment(const String &p_var) const = 0;
virtual String get_name() const = 0;
virtual String get_distribution_name() const = 0;
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 81866ee7e4..700174bdae 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -84,6 +84,7 @@
static Ref<ResourceFormatSaverBinary> resource_saver_binary;
static Ref<ResourceFormatLoaderBinary> resource_loader_binary;
static Ref<ResourceFormatImporter> resource_format_importer;
+static Ref<ResourceFormatImporterSaver> resource_format_importer_saver;
static Ref<ResourceFormatLoaderImage> resource_format_image;
static Ref<TranslationLoaderPO> resource_format_po;
static Ref<ResourceFormatSaverCrypto> resource_format_saver_crypto;
@@ -144,6 +145,9 @@ void register_core_types() {
resource_format_importer.instantiate();
ResourceLoader::add_resource_format_loader(resource_format_importer);
+ resource_format_importer_saver.instantiate();
+ ResourceSaver::add_resource_format_saver(resource_format_importer_saver);
+
resource_format_image.instantiate();
ResourceLoader::add_resource_format_loader(resource_format_image);
@@ -389,6 +393,9 @@ void unregister_core_types() {
ResourceLoader::remove_resource_format_loader(resource_format_importer);
resource_format_importer.unref();
+ ResourceSaver::remove_resource_format_saver(resource_format_importer_saver);
+ resource_format_importer_saver.unref();
+
ResourceLoader::remove_resource_format_loader(resource_format_po);
resource_format_po.unref();
diff --git a/core/templates/safe_refcount.h b/core/templates/safe_refcount.h
index 4d32e421cd..58ed019287 100644
--- a/core/templates/safe_refcount.h
+++ b/core/templates/safe_refcount.h
@@ -33,6 +33,10 @@
#include "core/typedefs.h"
+#ifdef DEV_ENABLED
+#include "core/error/error_macros.h"
+#endif
+
#include <atomic>
#include <type_traits>
@@ -163,6 +167,16 @@ public:
class SafeRefCount {
SafeNumeric<uint32_t> count;
+#ifdef DEV_ENABLED
+ _ALWAYS_INLINE_ void _check_unref_sanity() {
+ // This won't catch every misuse, but it's better than nothing.
+ CRASH_COND_MSG(count.get() == 0,
+ "Trying to unreference a SafeRefCount which is already zero is wrong and a symptom of it being misused.\n"
+ "Upon a SafeRefCount reaching zero any object whose lifetime is tied to it, as well as the ref count itself, must be destroyed.\n"
+ "Moreover, to guarantee that, no multiple threads should be racing to do the final unreferencing to zero.");
+ }
+#endif
+
public:
_ALWAYS_INLINE_ bool ref() { // true on success
return count.conditional_increment() != 0;
@@ -173,10 +187,16 @@ public:
}
_ALWAYS_INLINE_ bool unref() { // true if must be disposed of
+#ifdef DEV_ENABLED
+ _check_unref_sanity();
+#endif
return count.decrement() == 0;
}
_ALWAYS_INLINE_ uint32_t unrefval() { // 0 if must be disposed of
+#ifdef DEV_ENABLED
+ _check_unref_sanity();
+#endif
return count.decrement();
}
diff --git a/core/variant/array.cpp b/core/variant/array.cpp
index 0fecc2fe94..f8af78f3c1 100644
--- a/core/variant/array.cpp
+++ b/core/variant/array.cpp
@@ -54,16 +54,6 @@ void Array::_ref(const Array &p_from) const {
ERR_FAIL_COND(!_fp); // should NOT happen.
- if (unlikely(_fp->read_only != nullptr)) {
- // If p_from is a read-only array, just copy the contents to avoid further modification.
- _unref();
- _p = memnew(ArrayPrivate);
- _p->refcount.init();
- _p->array = _fp->array;
- _p->typed = _fp->typed;
- return;
- }
-
if (_fp == _p) {
return; // whatever it is, nothing to do here move along
}
diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h
index 358b3df0c5..81ac5adba7 100644
--- a/core/variant/binder_common.h
+++ b/core/variant/binder_common.h
@@ -146,22 +146,53 @@ VARIANT_ENUM_CAST(Side);
VARIANT_ENUM_CAST(ClockDirection);
VARIANT_ENUM_CAST(Corner);
VARIANT_ENUM_CAST(HatDir);
-VARIANT_ENUM_CAST(HatMask);
+VARIANT_BITFIELD_CAST(HatMask);
VARIANT_ENUM_CAST(JoyAxis);
VARIANT_ENUM_CAST(JoyButton);
-VARIANT_ENUM_CAST(Key);
-VARIANT_ENUM_CAST(KeyModifierMask);
+
VARIANT_ENUM_CAST(MIDIMessage);
VARIANT_ENUM_CAST(MouseButton);
+VARIANT_BITFIELD_CAST(MouseButtonMask);
VARIANT_ENUM_CAST(Orientation);
VARIANT_ENUM_CAST(HorizontalAlignment);
VARIANT_ENUM_CAST(VerticalAlignment);
VARIANT_ENUM_CAST(InlineAlignment);
VARIANT_ENUM_CAST(PropertyHint);
-VARIANT_ENUM_CAST(PropertyUsageFlags);
+VARIANT_BITFIELD_CAST(PropertyUsageFlags);
VARIANT_ENUM_CAST(Variant::Type);
VARIANT_ENUM_CAST(Variant::Operator);
+// Key
+
+VARIANT_ENUM_CAST(Key);
+VARIANT_BITFIELD_CAST(KeyModifierMask);
+
+static inline Key &operator|=(Key &a, BitField<KeyModifierMask> b) {
+ a = static_cast<Key>(static_cast<int>(a) | static_cast<int>(b.operator int64_t()));
+ return a;
+}
+
+static inline Key &operator&=(Key &a, BitField<KeyModifierMask> b) {
+ a = static_cast<Key>(static_cast<int>(a) & static_cast<int>(b.operator int64_t()));
+ return a;
+}
+
+static inline Key operator|(Key a, BitField<KeyModifierMask> b) {
+ return (Key)((int)a | (int)b.operator int64_t());
+}
+
+static inline Key operator&(Key a, BitField<KeyModifierMask> b) {
+ return (Key)((int)a & (int)b.operator int64_t());
+}
+
+static inline Key operator+(BitField<KeyModifierMask> a, Key b) {
+ return (Key)((int)a.operator int64_t() + (int)b);
+}
+
+static inline Key operator|(BitField<KeyModifierMask> a, Key b) {
+ return (Key)((int)a.operator int64_t() | (int)b);
+}
+
template <>
struct VariantCaster<char32_t> {
static _FORCE_INLINE_ char32_t cast(const Variant &p_variant) {
diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp
index ba3fc536d7..2f2acc55a6 100644
--- a/core/variant/callable.cpp
+++ b/core/variant/callable.cpp
@@ -102,7 +102,22 @@ Callable Callable::bindp(const Variant **p_arguments, int p_argcount) const {
}
return Callable(memnew(CallableCustomBind(*this, args)));
}
+
+Callable Callable::bindv(const Array &p_arguments) {
+ if (p_arguments.is_empty()) {
+ return *this; // No point in creating a new callable if nothing is bound.
+ }
+
+ Vector<Variant> args;
+ args.resize(p_arguments.size());
+ for (int i = 0; i < p_arguments.size(); i++) {
+ args.write[i] = p_arguments[i];
+ }
+ return Callable(memnew(CallableCustomBind(*this, args)));
+}
+
Callable Callable::unbind(int p_argcount) const {
+ ERR_FAIL_COND_V_MSG(p_argcount <= 0, Callable(*this), "Amount of unbind() arguments must be 1 or greater.");
return Callable(memnew(CallableCustomUnbind(*this, p_argcount)));
}
@@ -137,6 +152,35 @@ StringName Callable::get_method() const {
return method;
}
+int Callable::get_bound_arguments_count() const {
+ if (!is_null() && is_custom()) {
+ return custom->get_bound_arguments_count();
+ } else {
+ return 0;
+ }
+}
+
+void Callable::get_bound_arguments_ref(Vector<Variant> &r_arguments, int &r_argcount) const {
+ if (!is_null() && is_custom()) {
+ custom->get_bound_arguments(r_arguments, r_argcount);
+ } else {
+ r_arguments.clear();
+ r_argcount = 0;
+ }
+}
+
+Array Callable::get_bound_arguments() const {
+ Vector<Variant> arr;
+ int ac;
+ get_bound_arguments_ref(arr, ac);
+ Array ret;
+ ret.resize(arr.size());
+ for (int i = 0; i < arr.size(); i++) {
+ ret[i] = arr[i];
+ }
+ return ret;
+}
+
CallableCustom *Callable::get_custom() const {
ERR_FAIL_COND_V_MSG(!is_custom(), nullptr,
vformat("Can't get custom on non-CallableCustom \"%s\".", operator String()));
@@ -344,6 +388,15 @@ const Callable *CallableCustom::get_base_comparator() const {
return nullptr;
}
+int CallableCustom::get_bound_arguments_count() const {
+ return 0;
+}
+
+void CallableCustom::get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const {
+ r_arguments = Vector<Variant>();
+ r_argcount = 0;
+}
+
CallableCustom::CallableCustom() {
ref_count.init();
}
diff --git a/core/variant/callable.h b/core/variant/callable.h
index c9d32afb61..0abbb64c0b 100644
--- a/core/variant/callable.h
+++ b/core/variant/callable.h
@@ -98,6 +98,7 @@ public:
template <typename... VarArgs>
Callable bind(VarArgs... p_args);
+ Callable bindv(const Array &p_arguments);
Callable bindp(const Variant **p_arguments, int p_argcount) const;
Callable unbind(int p_argcount) const;
@@ -106,6 +107,9 @@ public:
ObjectID get_object_id() const;
StringName get_method() const;
CallableCustom *get_custom() const;
+ int get_bound_arguments_count() const;
+ void get_bound_arguments_ref(Vector<Variant> &r_arguments, int &r_argcount) const; // Internal engine use, the exposed one is below.
+ Array get_bound_arguments() const;
uint32_t hash() const;
@@ -146,6 +150,8 @@ public:
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const = 0;
virtual Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const;
virtual const Callable *get_base_comparator() const;
+ virtual int get_bound_arguments_count() const;
+ virtual void get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const;
CallableCustom();
virtual ~CallableCustom() {}
diff --git a/core/variant/callable_bind.cpp b/core/variant/callable_bind.cpp
index 4713a49303..5be91c6e11 100644
--- a/core/variant/callable_bind.cpp
+++ b/core/variant/callable_bind.cpp
@@ -87,6 +87,47 @@ const Callable *CallableCustomBind::get_base_comparator() const {
return &callable;
}
+int CallableCustomBind::get_bound_arguments_count() const {
+ return callable.get_bound_arguments_count() + binds.size();
+}
+
+void CallableCustomBind::get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const {
+ Vector<Variant> sub_args;
+ int sub_count;
+ callable.get_bound_arguments_ref(sub_args, sub_count);
+
+ if (sub_count == 0) {
+ r_arguments = binds;
+ r_argcount = binds.size();
+ return;
+ }
+
+ int new_count = sub_count + binds.size();
+ r_argcount = new_count;
+
+ if (new_count <= 0) {
+ // Removed more arguments than it adds.
+ r_arguments = Vector<Variant>();
+ return;
+ }
+
+ r_arguments.resize(new_count);
+
+ if (sub_count > 0) {
+ for (int i = 0; i < sub_count; i++) {
+ r_arguments.write[i] = sub_args[i];
+ }
+ for (int i = 0; i < binds.size(); i++) {
+ r_arguments.write[i + sub_count] = binds[i];
+ }
+ r_argcount = new_count;
+ } else {
+ for (int i = 0; i < binds.size() + sub_count; i++) {
+ r_arguments.write[i] = binds[i - sub_count];
+ }
+ }
+}
+
void CallableCustomBind::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
const Variant **args = (const Variant **)alloca(sizeof(const Variant **) * (binds.size() + p_argcount));
for (int i = 0; i < p_argcount; i++) {
@@ -164,6 +205,25 @@ const Callable *CallableCustomUnbind::get_base_comparator() const {
return &callable;
}
+int CallableCustomUnbind::get_bound_arguments_count() const {
+ return callable.get_bound_arguments_count() - argcount;
+}
+
+void CallableCustomUnbind::get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const {
+ Vector<Variant> sub_args;
+ int sub_count;
+ callable.get_bound_arguments_ref(sub_args, sub_count);
+
+ r_argcount = sub_args.size() - argcount;
+
+ if (argcount >= sub_args.size()) {
+ r_arguments = Vector<Variant>();
+ } else {
+ sub_args.resize(sub_args.size() - argcount);
+ r_arguments = sub_args;
+ }
+}
+
void CallableCustomUnbind::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
if (argcount > p_argcount) {
r_call_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
diff --git a/core/variant/callable_bind.h b/core/variant/callable_bind.h
index 2bdf7e4782..278ed335d0 100644
--- a/core/variant/callable_bind.h
+++ b/core/variant/callable_bind.h
@@ -51,7 +51,8 @@ public:
virtual ObjectID get_object() const override; //must always be able to provide an object
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
virtual const Callable *get_base_comparator() const override;
-
+ virtual int get_bound_arguments_count() const override;
+ virtual void get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const override;
Callable get_callable() { return callable; }
Vector<Variant> get_binds() { return binds; }
@@ -76,6 +77,8 @@ public:
virtual ObjectID get_object() const override; //must always be able to provide an object
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
virtual const Callable *get_base_comparator() const override;
+ virtual int get_bound_arguments_count() const override;
+ virtual void get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const override;
Callable get_callable() { return callable; }
int get_unbinds() { return argcount; }
diff --git a/core/variant/dictionary.cpp b/core/variant/dictionary.cpp
index c545109bd8..f87064a0d1 100644
--- a/core/variant/dictionary.cpp
+++ b/core/variant/dictionary.cpp
@@ -211,16 +211,6 @@ bool Dictionary::recursive_equal(const Dictionary &p_dictionary, int recursion_c
}
void Dictionary::_ref(const Dictionary &p_from) const {
- if (unlikely(p_from._p->read_only != nullptr)) {
- // If p_from is a read-only dictionary, just copy the contents to avoid further modification.
- if (_p) {
- _unref();
- }
- _p = memnew(DictionaryPrivate);
- _p->refcount.init();
- _p->variant_map = p_from._p->variant_map;
- return;
- }
//make a copy first (thread safe)
if (!p_from._p->refcount.ref()) {
return; // couldn't copy
diff --git a/core/variant/type_info.h b/core/variant/type_info.h
index d3b507ba4d..e89658d25b 100644
--- a/core/variant/type_info.h
+++ b/core/variant/type_info.h
@@ -287,11 +287,14 @@ class BitField {
int64_t value = 0;
public:
- _FORCE_INLINE_ void set_flag(T p_flag) { value |= p_flag; }
- _FORCE_INLINE_ bool has_flag(T p_flag) const { return value & p_flag; }
- _FORCE_INLINE_ void clear_flag(T p_flag) { return value &= ~p_flag; }
+ _FORCE_INLINE_ void set_flag(T p_flag) { value |= (int64_t)p_flag; }
+ _FORCE_INLINE_ bool has_flag(T p_flag) const { return value & (int64_t)p_flag; }
+ _FORCE_INLINE_ bool is_empty() const { return value == 0; }
+ _FORCE_INLINE_ void clear_flag(T p_flag) { value &= ~(int64_t)p_flag; }
+ _FORCE_INLINE_ void clear() { value = 0; }
_FORCE_INLINE_ BitField() = default;
_FORCE_INLINE_ BitField(int64_t p_value) { value = p_value; }
+ _FORCE_INLINE_ BitField(T p_value) { value = (int64_t)p_value; }
_FORCE_INLINE_ operator int64_t() const { return value; }
_FORCE_INLINE_ operator Variant() const { return value; }
};
diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp
index 7039a5d9c4..ca42738b05 100644
--- a/core/variant/variant.cpp
+++ b/core/variant/variant.cpp
@@ -3240,33 +3240,34 @@ uint32_t Variant::recursive_hash(int recursion_count) const {
}
#define hash_compare_scalar(p_lhs, p_rhs) \
- ((p_lhs) == (p_rhs)) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs))
-
-#define hash_compare_vector2(p_lhs, p_rhs) \
- (hash_compare_scalar((p_lhs).x, (p_rhs).x)) && \
- (hash_compare_scalar((p_lhs).y, (p_rhs).y))
-
-#define hash_compare_vector3(p_lhs, p_rhs) \
- (hash_compare_scalar((p_lhs).x, (p_rhs).x)) && \
- (hash_compare_scalar((p_lhs).y, (p_rhs).y)) && \
- (hash_compare_scalar((p_lhs).z, (p_rhs).z))
-#define hash_compare_vector4(p_lhs, p_rhs) \
- (hash_compare_scalar((p_lhs).x, (p_rhs).x)) && \
- (hash_compare_scalar((p_lhs).y, (p_rhs).y)) && \
- (hash_compare_scalar((p_lhs).z, (p_rhs).z)) && \
- (hash_compare_scalar((p_lhs).w, (p_rhs).w))
-
-#define hash_compare_quaternion(p_lhs, p_rhs) \
- (hash_compare_scalar((p_lhs).x, (p_rhs).x)) && \
- (hash_compare_scalar((p_lhs).y, (p_rhs).y)) && \
- (hash_compare_scalar((p_lhs).z, (p_rhs).z)) && \
- (hash_compare_scalar((p_lhs).w, (p_rhs).w))
-
-#define hash_compare_color(p_lhs, p_rhs) \
- (hash_compare_scalar((p_lhs).r, (p_rhs).r)) && \
- (hash_compare_scalar((p_lhs).g, (p_rhs).g)) && \
- (hash_compare_scalar((p_lhs).b, (p_rhs).b)) && \
- (hash_compare_scalar((p_lhs).a, (p_rhs).a))
+ (((p_lhs) == (p_rhs)) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs)))
+
+#define hash_compare_vector2(p_lhs, p_rhs) \
+ (hash_compare_scalar((p_lhs).x, (p_rhs).x) && \
+ hash_compare_scalar((p_lhs).y, (p_rhs).y))
+
+#define hash_compare_vector3(p_lhs, p_rhs) \
+ (hash_compare_scalar((p_lhs).x, (p_rhs).x) && \
+ hash_compare_scalar((p_lhs).y, (p_rhs).y) && \
+ hash_compare_scalar((p_lhs).z, (p_rhs).z))
+
+#define hash_compare_vector4(p_lhs, p_rhs) \
+ (hash_compare_scalar((p_lhs).x, (p_rhs).x) && \
+ hash_compare_scalar((p_lhs).y, (p_rhs).y) && \
+ hash_compare_scalar((p_lhs).z, (p_rhs).z) && \
+ hash_compare_scalar((p_lhs).w, (p_rhs).w))
+
+#define hash_compare_quaternion(p_lhs, p_rhs) \
+ (hash_compare_scalar((p_lhs).x, (p_rhs).x) && \
+ hash_compare_scalar((p_lhs).y, (p_rhs).y) && \
+ hash_compare_scalar((p_lhs).z, (p_rhs).z) && \
+ hash_compare_scalar((p_lhs).w, (p_rhs).w))
+
+#define hash_compare_color(p_lhs, p_rhs) \
+ (hash_compare_scalar((p_lhs).r, (p_rhs).r) && \
+ hash_compare_scalar((p_lhs).g, (p_rhs).g) && \
+ hash_compare_scalar((p_lhs).b, (p_rhs).b) && \
+ hash_compare_scalar((p_lhs).a, (p_rhs).a))
#define hash_compare_packed_array(p_lhs, p_rhs, p_type, p_compare_func) \
const Vector<p_type> &l = PackedArrayRef<p_type>::get_array(p_lhs); \
@@ -3323,8 +3324,8 @@ bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const
const Rect2 *l = reinterpret_cast<const Rect2 *>(_data._mem);
const Rect2 *r = reinterpret_cast<const Rect2 *>(p_variant._data._mem);
- return (hash_compare_vector2(l->position, r->position)) &&
- (hash_compare_vector2(l->size, r->size));
+ return hash_compare_vector2(l->position, r->position) &&
+ hash_compare_vector2(l->size, r->size);
} break;
case RECT2I: {
const Rect2i *l = reinterpret_cast<const Rect2i *>(_data._mem);
@@ -3338,7 +3339,7 @@ bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const
Transform2D *r = p_variant._data._transform2d;
for (int i = 0; i < 3; i++) {
- if (!(hash_compare_vector2(l->columns[i], r->columns[i]))) {
+ if (!hash_compare_vector2(l->columns[i], r->columns[i])) {
return false;
}
}
@@ -3375,16 +3376,16 @@ bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const
const Plane *l = reinterpret_cast<const Plane *>(_data._mem);
const Plane *r = reinterpret_cast<const Plane *>(p_variant._data._mem);
- return (hash_compare_vector3(l->normal, r->normal)) &&
- (hash_compare_scalar(l->d, r->d));
+ return hash_compare_vector3(l->normal, r->normal) &&
+ hash_compare_scalar(l->d, r->d);
} break;
case AABB: {
const ::AABB *l = _data._aabb;
const ::AABB *r = p_variant._data._aabb;
- return (hash_compare_vector3(l->position, r->position) &&
- (hash_compare_vector3(l->size, r->size)));
+ return hash_compare_vector3(l->position, r->position) &&
+ hash_compare_vector3(l->size, r->size);
} break;
@@ -3400,7 +3401,7 @@ bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const
const Basis *r = p_variant._data._basis;
for (int i = 0; i < 3; i++) {
- if (!(hash_compare_vector3(l->rows[i], r->rows[i]))) {
+ if (!hash_compare_vector3(l->rows[i], r->rows[i])) {
return false;
}
}
@@ -3413,7 +3414,7 @@ bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const
const Transform3D *r = p_variant._data._transform3d;
for (int i = 0; i < 3; i++) {
- if (!(hash_compare_vector3(l->basis.rows[i], r->basis.rows[i]))) {
+ if (!hash_compare_vector3(l->basis.rows[i], r->basis.rows[i])) {
return false;
}
}
@@ -3425,7 +3426,7 @@ bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const
const Projection *r = p_variant._data._projection;
for (int i = 0; i < 4; i++) {
- if (!(hash_compare_vector4(l->columns[i], r->columns[i]))) {
+ if (!hash_compare_vector4(l->columns[i], r->columns[i])) {
return false;
}
}
@@ -3653,7 +3654,22 @@ String Variant::get_call_error_text(Object *p_base, const StringName &p_method,
}
String Variant::get_callable_error_text(const Callable &p_callable, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce) {
- return get_call_error_text(p_callable.get_object(), p_callable.get_method(), p_argptrs, p_argcount, ce);
+ Vector<Variant> binds;
+ int args_bound;
+ p_callable.get_bound_arguments_ref(binds, args_bound);
+ if (args_bound <= 0) {
+ return get_call_error_text(p_callable.get_object(), p_callable.get_method(), p_argptrs, MAX(0, p_argcount + args_bound), ce);
+ } else {
+ Vector<const Variant *> argptrs;
+ argptrs.resize(p_argcount + binds.size());
+ for (int i = 0; i < p_argcount; i++) {
+ argptrs.write[i] = p_argptrs[i];
+ }
+ for (int i = 0; i < binds.size(); i++) {
+ argptrs.write[i + p_argcount] = &binds[i];
+ }
+ return get_call_error_text(p_callable.get_object(), p_callable.get_method(), (const Variant **)argptrs.ptr(), argptrs.size(), ce);
+ }
}
void Variant::register_types() {
diff --git a/core/variant/variant.h b/core/variant/variant.h
index fff59c43a6..b9294de77d 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -655,6 +655,7 @@ public:
static bool has_indexing(Variant::Type p_type);
static Variant::Type get_indexed_element_type(Variant::Type p_type);
+ static uint32_t get_indexed_element_usage(Variant::Type p_type);
typedef void (*ValidatedIndexedSetter)(Variant *base, int64_t index, const Variant *value, bool *oob);
typedef void (*ValidatedIndexedGetter)(const Variant *base, int64_t index, Variant *value, bool *oob);
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index bc00bfca0f..2cc0b3a8d7 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -1923,7 +1923,7 @@ static void _register_variant_builtin_methods() {
/* Plane */
bind_method(Plane, normalized, sarray(), varray());
- bind_method(Plane, center, sarray(), varray());
+ bind_method(Plane, get_center, sarray(), varray());
bind_method(Plane, is_equal_approx, sarray("to_plane"), varray());
bind_method(Plane, is_finite, sarray(), varray());
bind_method(Plane, is_point_over, sarray("point"), varray());
@@ -2016,7 +2016,10 @@ static void _register_variant_builtin_methods() {
bind_method(Callable, get_object, sarray(), varray());
bind_method(Callable, get_object_id, sarray(), varray());
bind_method(Callable, get_method, sarray(), varray());
+ bind_method(Callable, get_bound_arguments_count, sarray(), varray());
+ bind_method(Callable, get_bound_arguments, sarray(), varray());
bind_method(Callable, hash, sarray(), varray());
+ bind_method(Callable, bindv, sarray("arguments"), varray());
bind_method(Callable, unbind, sarray("argcount"), varray());
bind_custom(Callable, call, _VariantCall::func_Callable_call, true, Variant);
diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp
index 39a039ffe8..87874deb8d 100644
--- a/core/variant/variant_parser.cpp
+++ b/core/variant/variant_parser.cpp
@@ -1358,6 +1358,7 @@ Error VariantParser::_parse_tag(Token &token, Stream *p_stream, int &line, Strin
if (p_simple_tag) {
r_tag.name = "";
r_tag.fields.clear();
+ bool escaping = false;
if (p_stream->is_utf8()) {
CharString cs;
@@ -1368,7 +1369,15 @@ Error VariantParser::_parse_tag(Token &token, Stream *p_stream, int &line, Strin
return ERR_PARSE_ERROR;
}
if (c == ']') {
- break;
+ if (escaping) {
+ escaping = false;
+ } else {
+ break;
+ }
+ } else if (c == '\\') {
+ escaping = true;
+ } else {
+ escaping = false;
}
cs += c;
}
@@ -1381,7 +1390,15 @@ Error VariantParser::_parse_tag(Token &token, Stream *p_stream, int &line, Strin
return ERR_PARSE_ERROR;
}
if (c == ']') {
- break;
+ if (escaping) {
+ escaping = false;
+ } else {
+ break;
+ }
+ } else if (c == '\\') {
+ escaping = true;
+ } else {
+ escaping = false;
}
r_tag.name += String::chr(c);
}
diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp
index b8d4495702..ba37e15f31 100644
--- a/core/variant/variant_setget.cpp
+++ b/core/variant/variant_setget.cpp
@@ -389,6 +389,7 @@ Variant Variant::get_named(const StringName &p_member, bool &r_valid) const {
v.write[index] = PtrToArg<m_elem_type>::convert(member); \
} \
static Variant::Type get_index_type() { return GetTypeInfo<m_elem_type>::VARIANT_TYPE; } \
+ static uint32_t get_index_usage() { return GetTypeInfo<m_elem_type>::get_class_info().usage; } \
static uint64_t get_indexed_size(const Variant *base) { return VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); } \
};
@@ -460,6 +461,7 @@ Variant Variant::get_named(const StringName &p_member, bool &r_valid) const {
v.write[index] = PtrToArg<m_elem_type>::convert(member); \
} \
static Variant::Type get_index_type() { return GetTypeInfo<m_elem_type>::VARIANT_TYPE; } \
+ static uint32_t get_index_usage() { return GetTypeInfo<m_elem_type>::get_class_info().usage; } \
static uint64_t get_indexed_size(const Variant *base) { return VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); } \
};
@@ -515,6 +517,7 @@ Variant Variant::get_named(const StringName &p_member, bool &r_valid) const {
v[index] = PtrToArg<m_elem_type>::convert(member); \
} \
static Variant::Type get_index_type() { return GetTypeInfo<m_elem_type>::VARIANT_TYPE; } \
+ static uint32_t get_index_usage() { return GetTypeInfo<m_elem_type>::get_class_info().usage; } \
static uint64_t get_indexed_size(const Variant *base) { return m_max; } \
};
@@ -564,6 +567,7 @@ Variant Variant::get_named(const StringName &p_member, bool &r_valid) const {
v m_accessor[index] = PtrToArg<m_elem_type>::convert(member); \
} \
static Variant::Type get_index_type() { return GetTypeInfo<m_elem_type>::VARIANT_TYPE; } \
+ static uint32_t get_index_usage() { return GetTypeInfo<m_elem_type>::get_class_info().usage; } \
static uint64_t get_indexed_size(const Variant *base) { return m_max; } \
};
@@ -613,6 +617,7 @@ Variant Variant::get_named(const StringName &p_member, bool &r_valid) const {
v.m_set(index, PtrToArg<m_elem_type>::convert(member)); \
} \
static Variant::Type get_index_type() { return GetTypeInfo<m_elem_type>::VARIANT_TYPE; } \
+ static uint32_t get_index_usage() { return GetTypeInfo<m_elem_type>::get_class_info().usage; } \
static uint64_t get_indexed_size(const Variant *base) { return m_max; } \
};
@@ -683,6 +688,7 @@ struct VariantIndexedSetGet_Array {
v.set(index, PtrToArg<Variant>::convert(member));
}
static Variant::Type get_index_type() { return Variant::NIL; }
+ static uint32_t get_index_usage() { return PROPERTY_USAGE_NIL_IS_VARIANT; }
static uint64_t get_indexed_size(const Variant *base) { return 0; }
};
@@ -768,6 +774,7 @@ struct VariantIndexedSetGet_String {
}
}
static Variant::Type get_index_type() { return Variant::STRING; }
+ static uint32_t get_index_usage() { return PROPERTY_USAGE_DEFAULT; }
static uint64_t get_indexed_size(const Variant *base) { return VariantInternal::get_string(base)->length(); }
};
@@ -812,6 +819,7 @@ struct VariantIndexedSetGet_String {
v[index] = PtrToArg<Variant>::convert(member); \
} \
static Variant::Type get_index_type() { return Variant::NIL; } \
+ static uint32_t get_index_usage() { return PROPERTY_USAGE_DEFAULT; } \
static uint64_t get_indexed_size(const Variant *base) { return VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); } \
};
@@ -852,7 +860,8 @@ struct VariantIndexedSetterGetterInfo {
uint64_t (*get_indexed_size)(const Variant *base) = nullptr;
- Variant::Type index_type;
+ Variant::Type index_type = Variant::NIL;
+ uint32_t index_usage = PROPERTY_USAGE_DEFAULT;
bool valid = false;
};
@@ -872,6 +881,7 @@ static void register_indexed_member(Variant::Type p_type) {
sgi.ptr_getter = T::ptr_get;
sgi.index_type = T::get_index_type();
+ sgi.index_usage = T::get_index_usage();
sgi.get_indexed_size = T::get_indexed_size;
sgi.valid = true;
@@ -920,6 +930,11 @@ Variant::Type Variant::get_indexed_element_type(Variant::Type p_type) {
return variant_indexed_setters_getters[p_type].index_type;
}
+uint32_t Variant::get_indexed_element_usage(Variant::Type p_type) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, PROPERTY_USAGE_DEFAULT);
+ return variant_indexed_setters_getters[p_type].index_usage;
+}
+
Variant::ValidatedIndexedSetter Variant::get_member_validated_indexed_setter(Variant::Type p_type) {
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr);
return variant_indexed_setters_getters[p_type].validated_setter;
@@ -1253,7 +1268,7 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
return _data._int > 0;
} break;
case FLOAT: {
- r_iter = 0;
+ r_iter = 0.0;
return _data._float > 0.0;
} break;
case VECTOR2: {
@@ -1457,7 +1472,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
return true;
} break;
case FLOAT: {
- int64_t idx = r_iter;
+ double idx = r_iter;
idx++;
if (idx >= _data._float) {
return false;