summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/SCsub1
-rw-r--r--core/config/engine.cpp8
-rw-r--r--core/config/project_settings.cpp17
-rw-r--r--core/config/project_settings.h6
-rw-r--r--core/core_bind.cpp88
-rw-r--r--core/core_bind.h5
-rw-r--r--core/debugger/engine_debugger.h2
-rw-r--r--core/debugger/local_debugger.cpp2
-rw-r--r--core/debugger/local_debugger.h2
-rw-r--r--core/debugger/remote_debugger.cpp6
-rw-r--r--core/debugger/remote_debugger.h4
-rw-r--r--core/debugger/script_debugger.cpp4
-rw-r--r--core/debugger/script_debugger.h2
-rw-r--r--core/error/error_macros.cpp36
-rw-r--r--core/error/error_macros.h251
-rw-r--r--core/extension/gdnative_interface.cpp6
-rw-r--r--core/extension/gdnative_interface.h4
-rw-r--r--core/extension/native_extension.cpp4
-rw-r--r--core/extension/native_extension.h2
-rw-r--r--core/extension/native_extension_manager.cpp2
-rw-r--r--core/input/SCsub14
-rw-r--r--core/input/input.cpp4
-rw-r--r--core/input/input_event.cpp9
-rw-r--r--core/io/file_access_compressed.cpp2
-rw-r--r--core/io/file_access_zip.cpp2
-rw-r--r--core/io/logger.cpp10
-rw-r--r--core/io/logger.h4
-rw-r--r--core/io/resource.cpp1
-rw-r--r--core/io/resource_importer.cpp2
-rw-r--r--core/io/resource_uid.cpp17
-rw-r--r--core/io/resource_uid.h2
-rw-r--r--core/io/zip_io.cpp2
-rw-r--r--core/math/bvh.h2
-rw-r--r--core/math/face3.cpp2
-rw-r--r--core/math/geometry_3d.cpp16
-rw-r--r--core/math/plane.h6
-rw-r--r--core/multiplayer/multiplayer.h2
-rw-r--r--core/multiplayer/multiplayer_replicator.cpp2
-rw-r--r--core/multiplayer/rpc_manager.cpp6
-rw-r--r--core/object/class_db.cpp21
-rw-r--r--core/object/class_db.h29
-rw-r--r--core/object/method_bind.cpp11
-rw-r--r--core/object/method_bind.h38
-rw-r--r--core/object/undo_redo.cpp46
-rw-r--r--core/object/undo_redo.h5
-rw-r--r--core/os/os.cpp4
-rw-r--r--core/os/os.h2
-rw-r--r--core/string/optimized_translation.cpp5
-rw-r--r--core/templates/hash_map.h18
-rw-r--r--core/templates/hashfuncs.h9
-rw-r--r--core/typedefs.h4
-rw-r--r--core/variant/binder_common.h14
-rw-r--r--core/variant/variant.cpp114
-rw-r--r--core/variant/variant.h1
-rw-r--r--core/variant/variant_construct.cpp3
-rw-r--r--core/variant/variant_internal.h4
-rw-r--r--core/variant/variant_op.cpp5
-rw-r--r--core/variant/variant_op.h28
-rw-r--r--core/variant/variant_parser.cpp76
-rw-r--r--core/variant/variant_setget.cpp3
-rw-r--r--core/variant/variant_utility.cpp22
61 files changed, 632 insertions, 387 deletions
diff --git a/core/SCsub b/core/SCsub
index 14dfa3487f..c12dd4e60e 100644
--- a/core/SCsub
+++ b/core/SCsub
@@ -146,6 +146,7 @@ env.core_sources += thirdparty_obj
# Godot source files
env.add_source_files(env.core_sources, "*.cpp")
+env.add_source_files(env.core_sources, "script_encryption_key.gen.cpp")
# Certificates
env.Depends(
diff --git a/core/config/engine.cpp b/core/config/engine.cpp
index d8fbb50a75..dc5b3e25c6 100644
--- a/core/config/engine.cpp
+++ b/core/config/engine.cpp
@@ -111,7 +111,7 @@ Dictionary Engine::get_version_info() const {
static Array array_from_info(const char *const *info_list) {
Array arr;
for (int i = 0; info_list[i] != nullptr; i++) {
- arr.push_back(info_list[i]);
+ arr.push_back(String::utf8(info_list[i]));
}
return arr;
}
@@ -119,7 +119,7 @@ static Array array_from_info(const char *const *info_list) {
static Array array_from_info_count(const char *const *info_list, int info_count) {
Array arr;
for (int i = 0; i < info_count; i++) {
- arr.push_back(info_list[i]);
+ arr.push_back(String::utf8(info_list[i]));
}
return arr;
}
@@ -140,14 +140,14 @@ Array Engine::get_copyright_info() const {
for (int component_index = 0; component_index < COPYRIGHT_INFO_COUNT; component_index++) {
const ComponentCopyright &cp_info = COPYRIGHT_INFO[component_index];
Dictionary component_dict;
- component_dict["name"] = cp_info.name;
+ component_dict["name"] = String::utf8(cp_info.name);
Array parts;
for (int i = 0; i < cp_info.part_count; i++) {
const ComponentCopyrightPart &cp_part = cp_info.parts[i];
Dictionary part_dict;
part_dict["files"] = array_from_info_count(cp_part.files, cp_part.file_count);
part_dict["copyright"] = array_from_info_count(cp_part.copyright_statements, cp_part.copyright_count);
- part_dict["license"] = cp_part.license;
+ part_dict["license"] = String::utf8(cp_part.license);
parts.push_back(part_dict);
}
component_dict["parts"] = parts;
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index 85e83ff7f2..562cbbdd27 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -48,11 +48,21 @@ ProjectSettings *ProjectSettings::get_singleton() {
return singleton;
}
+String ProjectSettings::get_project_data_dir_name() const {
+ return project_data_dir_name;
+}
+
+String ProjectSettings::get_project_data_path() const {
+ return "res://" + get_project_data_dir_name();
+}
+
String ProjectSettings::get_resource_path() const {
return resource_path;
}
-const String ProjectSettings::IMPORTED_FILES_PATH("res://.godot/imported");
+String ProjectSettings::get_imported_files_path() const {
+ return get_project_data_path().plus_file("imported");
+}
String ProjectSettings::localize_path(const String &p_path) const {
if (resource_path.is_empty() || p_path.begins_with("res://") || p_path.begins_with("user://") ||
@@ -509,6 +519,10 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bo
_load_settings_text(custom_settings);
}
}
+
+ // Updating the default value after the project settings have loaded.
+ project_data_dir_name = GLOBAL_GET("application/config/project_data_dir_name");
+
// Using GLOBAL_GET on every block for compressing can be slow, so assigning here.
Compression::zstd_long_distance_matching = GLOBAL_GET("compression/formats/zstd/long_distance_matching");
Compression::zstd_level = GLOBAL_GET("compression/formats/zstd/compression_level");
@@ -1080,6 +1094,7 @@ ProjectSettings::ProjectSettings() {
custom_prop_info["application/run/main_scene"] = PropertyInfo(Variant::STRING, "application/run/main_scene", PROPERTY_HINT_FILE, "*.tscn,*.scn,*.res");
GLOBAL_DEF("application/run/disable_stdout", false);
GLOBAL_DEF("application/run/disable_stderr", false);
+ project_data_dir_name = GLOBAL_DEF_RST("application/config/project_data_dir_name", ".godot");
GLOBAL_DEF("application/config/use_custom_user_dir", false);
GLOBAL_DEF("application/config/custom_user_dir_name", "");
GLOBAL_DEF("application/config/project_settings_override", "");
diff --git a/core/config/project_settings.h b/core/config/project_settings.h
index 7e93f26f0d..82f04b94df 100644
--- a/core/config/project_settings.h
+++ b/core/config/project_settings.h
@@ -42,7 +42,6 @@ class ProjectSettings : public Object {
public:
typedef Map<String, Variant> CustomMap;
- static const String IMPORTED_FILES_PATH;
enum {
//properties that are not for built in values begin from this value, so builtin ones are displayed first
@@ -94,6 +93,8 @@ protected:
OrderedHashMap<StringName, AutoloadInfo> autoloads;
+ String project_data_dir_name;
+
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
@@ -141,7 +142,10 @@ public:
bool property_can_revert(const String &p_name);
Variant property_get_revert(const String &p_name);
+ String get_project_data_dir_name() const;
+ String get_project_data_path() const;
String get_resource_path() const;
+ String get_imported_files_path() const;
static ProjectSettings *get_singleton();
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index f630adc39e..3a4fddc670 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -1077,79 +1077,79 @@ bool File::is_open() const {
}
String File::get_path() const {
- ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use, or is lacking read-write permission.");
return f->get_path();
}
String File::get_path_absolute() const {
- ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use, or is lacking read-write permission.");
return f->get_path_absolute();
}
void File::seek(int64_t p_position) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
ERR_FAIL_COND_MSG(p_position < 0, "Seek position must be a positive integer.");
f->seek(p_position);
}
void File::seek_end(int64_t p_position) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->seek_end(p_position);
}
uint64_t File::get_position() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_position();
}
uint64_t File::get_length() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_length();
}
bool File::eof_reached() const {
- ERR_FAIL_COND_V_MSG(!f, false, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, false, "File must be opened before use, or is lacking read-write permission.");
return f->eof_reached();
}
uint8_t File::get_8() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_8();
}
uint16_t File::get_16() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_16();
}
uint32_t File::get_32() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_32();
}
uint64_t File::get_64() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_64();
}
float File::get_float() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_float();
}
double File::get_double() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_double();
}
real_t File::get_real() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_real();
}
Vector<uint8_t> File::get_buffer(int64_t p_length) const {
Vector<uint8_t> data;
- ERR_FAIL_COND_V_MSG(!f, data, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, data, "File must be opened before use, or is lacking read-write permission.");
ERR_FAIL_COND_V_MSG(p_length < 0, data, "Length of buffer cannot be smaller than 0.");
if (p_length == 0) {
@@ -1170,7 +1170,7 @@ Vector<uint8_t> File::get_buffer(int64_t p_length) const {
}
String File::get_as_text() const {
- ERR_FAIL_COND_V_MSG(!f, String(), "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, String(), "File must be opened before use, or is lacking read-write permission.");
String text;
uint64_t original_pos = f->get_position();
@@ -1197,12 +1197,12 @@ String File::get_sha256(const String &p_path) const {
}
String File::get_line() const {
- ERR_FAIL_COND_V_MSG(!f, String(), "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, String(), "File must be opened before use, or is lacking read-write permission.");
return f->get_line();
}
Vector<String> File::get_csv_line(const String &p_delim) const {
- ERR_FAIL_COND_V_MSG(!f, Vector<String>(), "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, Vector<String>(), "File must be opened before use, or is lacking read-write permission.");
return f->get_csv_line(p_delim);
}
@@ -1230,77 +1230,77 @@ Error File::get_error() const {
}
void File::store_8(uint8_t p_dest) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->store_8(p_dest);
}
void File::store_16(uint16_t p_dest) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->store_16(p_dest);
}
void File::store_32(uint32_t p_dest) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->store_32(p_dest);
}
void File::store_64(uint64_t p_dest) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->store_64(p_dest);
}
void File::store_float(float p_dest) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->store_float(p_dest);
}
void File::store_double(double p_dest) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->store_double(p_dest);
}
void File::store_real(real_t p_real) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->store_real(p_real);
}
void File::store_string(const String &p_string) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->store_string(p_string);
}
void File::store_pascal_string(const String &p_string) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->store_pascal_string(p_string);
}
String File::get_pascal_string() {
- ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use, or is lacking read-write permission.");
return f->get_pascal_string();
}
void File::store_line(const String &p_string) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->store_line(p_string);
}
void File::store_csv_line(const Vector<String> &p_values, const String &p_delim) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->store_csv_line(p_values, p_delim);
}
void File::store_buffer(const Vector<uint8_t> &p_buffer) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
uint64_t len = p_buffer.size();
if (len == 0) {
@@ -1317,7 +1317,7 @@ bool File::file_exists(const String &p_name) const {
}
void File::store_var(const Variant &p_var, bool p_full_objects) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
int len;
Error err = encode_variant(p_var, nullptr, len, p_full_objects);
ERR_FAIL_COND_MSG(err != OK, "Error when trying to encode Variant.");
@@ -1334,7 +1334,7 @@ void File::store_var(const Variant &p_var, bool p_full_objects) {
}
Variant File::get_var(bool p_allow_objects) const {
- ERR_FAIL_COND_V_MSG(!f, Variant(), "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, Variant(), "File must be opened before use, or is lacking read-write permission.");
uint32_t len = get_32();
Vector<uint8_t> buff = get_buffer(len);
ERR_FAIL_COND_V((uint32_t)buff.size() != len, Variant());
@@ -1771,6 +1771,7 @@ void Thread::_start_func(void *ud) {
Object *target_instance = t->target_callable.get_object();
if (!target_instance) {
+ t->running.clear();
ERR_FAIL_MSG(vformat("Could not call function '%s' on previously freed instance to start thread %s.", t->target_callable.get_method(), t->get_id()));
}
@@ -1813,19 +1814,22 @@ void Thread::_start_func(void *ud) {
t->target_callable.call(arg, argc, t->ret, ce);
if (ce.error != Callable::CallError::CALL_OK) {
+ t->running.clear();
ERR_FAIL_MSG("Could not call function '" + t->target_callable.get_method().operator String() + "' to start thread " + t->get_id() + ": " + Variant::get_callable_error_text(t->target_callable, arg, argc, ce) + ".");
}
+
+ t->running.clear();
}
Error Thread::start(const Callable &p_callable, const Variant &p_userdata, Priority p_priority) {
- ERR_FAIL_COND_V_MSG(active.is_set(), ERR_ALREADY_IN_USE, "Thread already started.");
+ ERR_FAIL_COND_V_MSG(is_started(), ERR_ALREADY_IN_USE, "Thread already started.");
ERR_FAIL_COND_V(p_callable.is_null(), ERR_INVALID_PARAMETER);
ERR_FAIL_INDEX_V(p_priority, PRIORITY_MAX, ERR_INVALID_PARAMETER);
ret = Variant();
target_callable = p_callable;
userdata = p_userdata;
- active.set();
+ running.set();
Ref<Thread> *ud = memnew(Ref<Thread>(this));
@@ -1840,15 +1844,18 @@ String Thread::get_id() const {
return itos(thread.get_id());
}
-bool Thread::is_active() const {
- return active.is_set();
+bool Thread::is_started() const {
+ return thread.is_started();
+}
+
+bool Thread::is_alive() const {
+ return running.is_set();
}
Variant Thread::wait_to_finish() {
- ERR_FAIL_COND_V_MSG(!active.is_set(), Variant(), "Thread must be active to wait for its completion.");
+ ERR_FAIL_COND_V_MSG(!is_started(), Variant(), "Thread must have been started to wait for its completion.");
thread.wait_to_finish();
Variant r = ret;
- active.clear();
target_callable = Callable();
userdata = Variant();
@@ -1858,7 +1865,8 @@ Variant Thread::wait_to_finish() {
void Thread::_bind_methods() {
ClassDB::bind_method(D_METHOD("start", "callable", "userdata", "priority"), &Thread::start, DEFVAL(Variant()), DEFVAL(PRIORITY_NORMAL));
ClassDB::bind_method(D_METHOD("get_id"), &Thread::get_id);
- ClassDB::bind_method(D_METHOD("is_active"), &Thread::is_active);
+ ClassDB::bind_method(D_METHOD("is_started"), &Thread::is_started);
+ ClassDB::bind_method(D_METHOD("is_alive"), &Thread::is_alive);
ClassDB::bind_method(D_METHOD("wait_to_finish"), &Thread::wait_to_finish);
BIND_ENUM_CONSTANT(PRIORITY_LOW);
diff --git a/core/core_bind.h b/core/core_bind.h
index 84a284f948..4eab085dda 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -538,7 +538,7 @@ class Thread : public RefCounted {
protected:
Variant ret;
Variant userdata;
- SafeFlag active;
+ SafeFlag running;
Callable target_callable;
::Thread thread;
static void _bind_methods();
@@ -554,7 +554,8 @@ public:
Error start(const Callable &p_callable, const Variant &p_userdata = Variant(), Priority p_priority = PRIORITY_NORMAL);
String get_id() const;
- bool is_active() const;
+ bool is_started() const;
+ bool is_alive() const;
Variant wait_to_finish();
};
diff --git a/core/debugger/engine_debugger.h b/core/debugger/engine_debugger.h
index 22c6ef943e..41142bf305 100644
--- a/core/debugger/engine_debugger.h
+++ b/core/debugger/engine_debugger.h
@@ -128,7 +128,7 @@ public:
virtual void poll_events(bool p_is_idle) {}
virtual void send_message(const String &p_msg, const Array &p_data) = 0;
- virtual void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type) = 0;
+ virtual void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type) = 0;
virtual void debug(bool p_can_continue = true, bool p_is_error_breakpoint = false) = 0;
virtual ~EngineDebugger();
diff --git a/core/debugger/local_debugger.cpp b/core/debugger/local_debugger.cpp
index f7e56351b0..60aa3e6be7 100644
--- a/core/debugger/local_debugger.cpp
+++ b/core/debugger/local_debugger.cpp
@@ -358,7 +358,7 @@ void LocalDebugger::send_message(const String &p_message, const Array &p_args) {
// print_line("MESSAGE: '" + p_message + "' - " + String(Variant(p_args)));
}
-void LocalDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type) {
+void LocalDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type) {
print_line("ERROR: '" + (p_descr.is_empty() ? p_err : p_descr) + "'");
}
diff --git a/core/debugger/local_debugger.h b/core/debugger/local_debugger.h
index e793b2a859..cb59eb82e9 100644
--- a/core/debugger/local_debugger.h
+++ b/core/debugger/local_debugger.h
@@ -50,7 +50,7 @@ private:
public:
void debug(bool p_can_continue, bool p_is_error_breakpoint);
void send_message(const String &p_message, const Array &p_args);
- void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type);
+ void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type);
LocalDebugger();
~LocalDebugger();
diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp
index 032c7d55c0..9967d1e361 100644
--- a/core/debugger/remote_debugger.cpp
+++ b/core/debugger/remote_debugger.cpp
@@ -455,7 +455,7 @@ Error RemoteDebugger::_put_msg(String p_message, Array p_data) {
return err;
}
-void RemoteDebugger::_err_handler(void *p_this, const char *p_func, const char *p_file, int p_line, const char *p_err, const char *p_descr, ErrorHandlerType p_type) {
+void RemoteDebugger::_err_handler(void *p_this, const char *p_func, const char *p_file, int p_line, const char *p_err, const char *p_descr, bool p_editor_notify, ErrorHandlerType p_type) {
if (p_type == ERR_HANDLER_SCRIPT) {
return; //ignore script errors, those go through debugger
}
@@ -475,7 +475,7 @@ void RemoteDebugger::_err_handler(void *p_this, const char *p_func, const char *
}
// send_error will lock internally.
- rd->script_debugger->send_error(p_func, p_file, p_line, p_err, p_descr, p_type, si);
+ rd->script_debugger->send_error(p_func, p_file, p_line, p_err, p_descr, p_editor_notify, p_type, si);
}
void RemoteDebugger::_print_handler(void *p_this, const String &p_string, bool p_error) {
@@ -605,7 +605,7 @@ void RemoteDebugger::send_message(const String &p_message, const Array &p_args)
}
}
-void RemoteDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type) {
+void RemoteDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type) {
ErrorMessage oe;
oe.error = p_err;
oe.error_descr = p_descr;
diff --git a/core/debugger/remote_debugger.h b/core/debugger/remote_debugger.h
index 28e670747e..73799e3f81 100644
--- a/core/debugger/remote_debugger.h
+++ b/core/debugger/remote_debugger.h
@@ -89,7 +89,7 @@ private:
PrintHandlerList phl;
static void _print_handler(void *p_this, const String &p_string, bool p_error);
ErrorHandlerList eh;
- static void _err_handler(void *p_this, const char *p_func, const char *p_file, int p_line, const char *p_err, const char *p_descr, ErrorHandlerType p_type);
+ static void _err_handler(void *p_this, const char *p_func, const char *p_file, int p_line, const char *p_err, const char *p_descr, bool p_editor_notify, ErrorHandlerType p_type);
ErrorMessage _create_overflow_error(const String &p_what, const String &p_descr);
Error _put_msg(String p_message, Array p_data);
@@ -111,7 +111,7 @@ public:
// Overrides
void poll_events(bool p_is_idle);
void send_message(const String &p_message, const Array &p_args);
- void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type);
+ void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type);
void debug(bool p_can_continue = true, bool p_is_error_breakpoint = false);
RemoteDebugger(Ref<RemoteDebuggerPeer> p_peer);
diff --git a/core/debugger/script_debugger.cpp b/core/debugger/script_debugger.cpp
index 6d1e4ed101..70ec101a03 100644
--- a/core/debugger/script_debugger.cpp
+++ b/core/debugger/script_debugger.cpp
@@ -100,10 +100,10 @@ void ScriptDebugger::debug(ScriptLanguage *p_lang, bool p_can_continue, bool p_i
break_lang = prev;
}
-void ScriptDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type, const Vector<StackInfo> &p_stack_info) {
+void ScriptDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type, const Vector<StackInfo> &p_stack_info) {
// Store stack info, this is ugly, but allows us to separate EngineDebugger and ScriptDebugger. There might be a better way.
error_stack_info.append_array(p_stack_info);
- EngineDebugger::get_singleton()->send_error(p_func, p_file, p_line, p_err, p_descr, p_type);
+ EngineDebugger::get_singleton()->send_error(p_func, p_file, p_line, p_err, p_descr, p_editor_notify, p_type);
error_stack_info.resize(0);
}
diff --git a/core/debugger/script_debugger.h b/core/debugger/script_debugger.h
index 9f034a5e5d..c1d0170334 100644
--- a/core/debugger/script_debugger.h
+++ b/core/debugger/script_debugger.h
@@ -71,7 +71,7 @@ public:
void debug(ScriptLanguage *p_lang, bool p_can_continue = true, bool p_is_error_breakpoint = false);
ScriptLanguage *get_break_language() const;
- void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type, const Vector<StackInfo> &p_stack_info);
+ void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type, const Vector<StackInfo> &p_stack_info);
Vector<StackInfo> get_error_stack_info() const;
ScriptDebugger() {}
};
diff --git a/core/error/error_macros.cpp b/core/error/error_macros.cpp
index 272dda97d8..719ea8afb5 100644
--- a/core/error/error_macros.cpp
+++ b/core/error/error_macros.cpp
@@ -65,45 +65,49 @@ void remove_error_handler(ErrorHandlerList *p_handler) {
_global_unlock();
}
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, ErrorHandlerType p_type) {
- _err_print_error(p_function, p_file, p_line, p_error, "", p_type);
+// Errors without messages.
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, bool p_editor_notify, ErrorHandlerType p_type) {
+ _err_print_error(p_function, p_file, p_line, p_error, "", p_editor_notify, p_type);
}
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, ErrorHandlerType p_type) {
- _err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), "", p_type);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, bool p_editor_notify, ErrorHandlerType p_type) {
+ _err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), "", p_editor_notify, p_type);
}
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, ErrorHandlerType p_type) {
+// Main error printing function.
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_editor_notify, ErrorHandlerType p_type) {
OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, p_message, (Logger::ErrorType)p_type);
_global_lock();
ErrorHandlerList *l = error_handler_list;
while (l) {
- l->errfunc(l->userdata, p_function, p_file, p_line, p_error, p_message, p_type);
+ l->errfunc(l->userdata, p_function, p_file, p_line, p_error, p_message, p_editor_notify, p_type);
l = l->next;
}
_global_unlock();
}
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, ErrorHandlerType p_type) {
- _err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_message, p_type);
+// Errors with message. (All combinations of p_error and p_message as String or char*.)
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, bool p_editor_notify, ErrorHandlerType p_type) {
+ _err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_message, p_editor_notify, p_type);
}
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, ErrorHandlerType p_type) {
- _err_print_error(p_function, p_file, p_line, p_error, p_message.utf8().get_data(), p_type);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, bool p_editor_notify, ErrorHandlerType p_type) {
+ _err_print_error(p_function, p_file, p_line, p_error, p_message.utf8().get_data(), p_editor_notify, p_type);
}
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, ErrorHandlerType p_type) {
- _err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_message.utf8().get_data(), p_type);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, bool p_editor_notify, ErrorHandlerType p_type) {
+ _err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_message.utf8().get_data(), p_editor_notify, p_type);
}
-void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message, bool fatal) {
- String fstr(fatal ? "FATAL: " : "");
+// Index errors. (All combinations of p_message as String or char*.)
+void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message, bool p_editor_notify, bool p_fatal) {
+ String fstr(p_fatal ? "FATAL: " : "");
String err(fstr + "Index " + p_index_str + " = " + itos(p_index) + " is out of bounds (" + p_size_str + " = " + itos(p_size) + ").");
_err_print_error(p_function, p_file, p_line, err.utf8().get_data(), p_message);
}
-void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool fatal) {
- _err_print_index_error(p_function, p_file, p_line, p_index, p_size, p_index_str, p_size_str, p_message.utf8().get_data(), fatal);
+void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool p_editor_notify, bool p_fatal) {
+ _err_print_index_error(p_function, p_file, p_line, p_index, p_size, p_index_str, p_size_str, p_message.utf8().get_data(), p_fatal);
}
diff --git a/core/error/error_macros.h b/core/error/error_macros.h
index 1bed8d366b..4eb862dce2 100644
--- a/core/error/error_macros.h
+++ b/core/error/error_macros.h
@@ -46,7 +46,7 @@ enum ErrorHandlerType {
// Pointer to the error handler printing function. Reassign to any function to have errors printed.
// Parameters: userdata, function, file, line, error, explanation, type.
-typedef void (*ErrorHandlerFunc)(void *, const char *, const char *, int p_line, const char *, const char *, ErrorHandlerType p_type);
+typedef void (*ErrorHandlerFunc)(void *, const char *, const char *, int p_line, const char *, const char *, bool p_editor_notify, ErrorHandlerType p_type);
struct ErrorHandlerList {
ErrorHandlerFunc errfunc = nullptr;
@@ -61,14 +61,14 @@ void add_error_handler(ErrorHandlerList *p_handler);
void remove_error_handler(ErrorHandlerList *p_handler);
// Functions used by the error macros.
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
-void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message = "", bool fatal = false);
-void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool fatal = false);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
+void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message = "", bool p_editor_notify = false, bool fatal = false);
+void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool p_editor_notify = false, bool fatal = false);
#ifdef __GNUC__
//#define FUNCTION_STR __PRETTY_FUNCTION__ - too annoying
@@ -136,6 +136,17 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
((void)0)
/**
+ * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
+ * If not, prints `m_msg`, notifies in the editor, and the current function returns.
+ */
+#define ERR_FAIL_INDEX_EDMSG(m_index, m_size, m_msg) \
+ if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
+ return; \
+ } else \
+ ((void)0)
+
+/**
* Try using `ERR_FAIL_INDEX_V_MSG`.
* Only use this macro if there is no sensible error message.
*
@@ -161,6 +172,17 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
((void)0)
/**
+ * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
+ * If not, prints `m_msg`, notifies in the editor, and the current function returns `m_retval`.
+ */
+#define ERR_FAIL_INDEX_V_EDMSG(m_index, m_size, m_retval, m_msg) \
+ if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
+ return m_retval; \
+ } else \
+ ((void)0)
+
+/**
* Try using `ERR_FAIL_INDEX_MSG` or `ERR_FAIL_INDEX_V_MSG`.
* Only use this macro if there is no sensible fallback i.e. the error is unrecoverable, and
* there is no sensible error message.
@@ -215,6 +237,16 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
return; \
} else \
((void)0)
+/**
+ * Ensures an unsigned integer index `m_index` is less than `m_size`.
+ * If not, prints `m_msg`, notifies in the editor, and the current function returns.
+ */
+#define ERR_FAIL_UNSIGNED_INDEX_EDMSG(m_index, m_size, m_msg) \
+ if (unlikely((m_index) >= (m_size))) { \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
+ return; \
+ } else \
+ ((void)0)
/**
* Try using `ERR_FAIL_UNSIGNED_INDEX_V_MSG`.
@@ -242,6 +274,17 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
((void)0)
/**
+ * Ensures an unsigned integer index `m_index` is less than `m_size`.
+ * If not, prints `m_msg`, notifies in the editor, and the current function returns `m_retval`.
+ */
+#define ERR_FAIL_UNSIGNED_INDEX_V_EDMSG(m_index, m_size, m_retval, m_msg) \
+ if (unlikely((m_index) >= (m_size))) { \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
+ return m_retval; \
+ } else \
+ ((void)0)
+
+/**
* Try using `ERR_FAIL_UNSIGNED_INDEX_MSG` or `ERR_FAIL_UNSIGNED_INDEX_V_MSG`.
* Only use this macro if there is no sensible fallback i.e. the error is unrecoverable, and
* there is no sensible error message.
@@ -298,6 +341,17 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
((void)0)
/**
+ * Ensures a pointer `m_param` is not null.
+ * If it is null, prints `m_msg`, notifies in the editor, and the current function returns.
+ */
+#define ERR_FAIL_NULL_EDMSG(m_param, m_msg) \
+ if (unlikely(m_param == nullptr)) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg, true); \
+ return; \
+ } else \
+ ((void)0)
+
+/**
* Try using `ERR_FAIL_NULL_V_MSG`.
* Only use this macro if there is no sensible error message.
*
@@ -323,6 +377,17 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
((void)0)
/**
+ * Ensures a pointer `m_param` is not null.
+ * If it is null, prints `m_msg`, notifies in the editor, and the current function returns `m_retval`.
+ */
+#define ERR_FAIL_NULL_V_EDMSG(m_param, m_retval, m_msg) \
+ if (unlikely(m_param == nullptr)) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg, true); \
+ return m_retval; \
+ } else \
+ ((void)0)
+
+/**
* Try using `ERR_FAIL_COND_MSG`.
* Only use this macro if there is no sensible error message.
* If checking for null use ERR_FAIL_NULL_MSG instead.
@@ -353,6 +418,20 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
((void)0)
/**
+ * Ensures `m_cond` is false.
+ * If `m_cond` is true, prints `m_msg`, notifies in the editor, and the current function returns.
+ *
+ * If checking for null use ERR_FAIL_NULL_MSG instead.
+ * If checking index bounds use ERR_FAIL_INDEX_MSG instead.
+ */
+#define ERR_FAIL_COND_EDMSG(m_cond, m_msg) \
+ if (unlikely(m_cond)) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true.", m_msg, true); \
+ return; \
+ } else \
+ ((void)0)
+
+/**
* Try using `ERR_FAIL_COND_V_MSG`.
* Only use this macro if there is no sensible error message.
* If checking for null use ERR_FAIL_NULL_V_MSG instead.
@@ -383,6 +462,20 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
((void)0)
/**
+ * Ensures `m_cond` is false.
+ * If `m_cond` is true, prints `m_msg`, notifies in the editor, and the current function returns `m_retval`.
+ *
+ * If checking for null use ERR_FAIL_NULL_V_MSG instead.
+ * If checking index bounds use ERR_FAIL_INDEX_V_MSG instead.
+ */
+#define ERR_FAIL_COND_V_EDMSG(m_cond, m_retval, m_msg) \
+ if (unlikely(m_cond)) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval), m_msg, true); \
+ return m_retval; \
+ } else \
+ ((void)0)
+
+/**
* Try using `ERR_CONTINUE_MSG`.
* Only use this macro if there is no sensible error message.
*
@@ -408,6 +501,17 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
((void)0)
/**
+ * Ensures `m_cond` is false.
+ * If `m_cond` is true, prints `m_msg`, notifies in the editor, and the current loop continues.
+ */
+#define ERR_CONTINUE_EDMSG(m_cond, m_msg) \
+ if (unlikely(m_cond)) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing.", m_msg, true); \
+ continue; \
+ } else \
+ ((void)0)
+
+/**
* Try using `ERR_BREAK_MSG`.
* Only use this macro if there is no sensible error message.
*
@@ -433,6 +537,17 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
((void)0)
/**
+ * Ensures `m_cond` is false.
+ * If `m_cond` is true, prints `m_msg`, notifies in the editor, and the current loop breaks.
+ */
+#define ERR_BREAK_EDMSG(m_cond, m_msg) \
+ if (unlikely(m_cond)) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking.", m_msg, true); \
+ break; \
+ } else \
+ ((void)0)
+
+/**
* Try using `ERR_FAIL_COND_MSG` or `ERR_FAIL_COND_V_MSG`.
* Only use this macro if there is no sensible fallback i.e. the error is unrecoverable, and
* there is no sensible error message.
@@ -491,6 +606,19 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
((void)0)
/**
+ * Try using `ERR_FAIL_COND_MSG`.
+ * Only use this macro if more complex error detection or recovery is required.
+ *
+ * Prints `m_msg`, notifies in the editor, and the current function returns.
+ */
+#define ERR_FAIL_EDMSG(m_msg) \
+ if (true) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed.", m_msg, true); \
+ return; \
+ } else \
+ ((void)0)
+
+/**
* Try using `ERR_FAIL_COND_V_MSG` or `ERR_FAIL_V_MSG`.
* Only use this macro if more complex error detection or recovery is required, and
* there is no sensible error message.
@@ -518,6 +646,19 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
((void)0)
/**
+ * Try using `ERR_FAIL_COND_V_MSG`.
+ * Only use this macro if more complex error detection or recovery is required.
+ *
+ * Prints `m_msg`, notifies in the editor, and the current function returns `m_retval`.
+ */
+#define ERR_FAIL_V_EDMSG(m_retval, m_msg) \
+ if (true) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval), m_msg, true); \
+ return m_retval; \
+ } else \
+ ((void)0)
+
+/**
* Try using `ERR_FAIL_COND_MSG`, `ERR_FAIL_COND_V_MSG`, `ERR_CONTINUE_MSG` or ERR_BREAK_MSG.
* Only use this macro at the start of a function that has not been implemented yet, or
* if more complex error detection or recovery is required.
@@ -528,6 +669,16 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg)
/**
+ * Try using `ERR_FAIL_COND_MSG`, `ERR_FAIL_COND_V_MSG`, `ERR_CONTINUE_MSG` or ERR_BREAK_MSG.
+ * Only use this macro at the start of a function that has not been implemented yet, or
+ * if more complex error detection or recovery is required.
+ *
+ * Prints `m_msg` and notifies the editor.
+ */
+#define ERR_PRINT_ED(m_msg) \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, )
+
+/**
* Prints `m_msg` once during the application lifetime.
*/
#define ERR_PRINT_ONCE(m_msg) \
@@ -540,6 +691,19 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
} else \
((void)0)
+/**
+ * Prints `m_msg` and notifies the editor once during the application lifetime.
+ */
+#define ERR_PRINT_ONCE_ED(m_msg) \
+ if (true) { \
+ static bool first_print = true; \
+ if (first_print) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true); \
+ first_print = false; \
+ } \
+ } else \
+ ((void)0)
+
// Print warning message macros.
/**
@@ -548,52 +712,75 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
* If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead.
*/
#define WARN_PRINT(m_msg) \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, ERR_HANDLER_WARNING)
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, false, ERR_HANDLER_WARNING)
+
+/**
+ * Prints `m_msg` and notifies the editor.
+ *
+ * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead.
+ */
+#define WARN_PRINT_ED(m_msg) \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true, ERR_HANDLER_WARNING)
/**
* Prints `m_msg` once during the application lifetime.
*
* If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead.
*/
-#define WARN_PRINT_ONCE(m_msg) \
- if (true) { \
- static bool first_print = true; \
- if (first_print) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, ERR_HANDLER_WARNING); \
- first_print = false; \
- } \
- } else \
+#define WARN_PRINT_ONCE(m_msg) \
+ if (true) { \
+ static bool first_print = true; \
+ if (first_print) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, false, ERR_HANDLER_WARNING); \
+ first_print = false; \
+ } \
+ } else \
((void)0)
-// Print deprecated warning message macros.
-
/**
- * Warns that the current function is deprecated.
+ * Prints `m_msg` and notifies the editor once during the application lifetime.
+ *
+ * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead.
*/
-#define WARN_DEPRECATED \
- if (true) { \
- static SafeFlag warning_shown; \
- if (!warning_shown.is_set()) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", ERR_HANDLER_WARNING); \
- warning_shown.set(); \
- } \
- } else \
+#define WARN_PRINT_ONCE_ED(m_msg) \
+ if (true) { \
+ static bool first_print = true; \
+ if (first_print) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true, ERR_HANDLER_WARNING); \
+ first_print = false; \
+ } \
+ } else \
((void)0)
+// Print deprecated warning message macros.
+
/**
- * Warns that the current function is deprecated and prints `m_msg`.
+ * Warns that the current function is deprecated.
*/
-#define WARN_DEPRECATED_MSG(m_msg) \
+#define WARN_DEPRECATED \
if (true) { \
static SafeFlag warning_shown; \
if (!warning_shown.is_set()) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", m_msg, ERR_HANDLER_WARNING); \
+ _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(); \
} \
} else \
((void)0)
/**
+ * Warns that the current function is deprecated and prints `m_msg`.
+ */
+#define WARN_DEPRECATED_MSG(m_msg) \
+ if (true) { \
+ static SafeFlag warning_shown; \
+ if (!warning_shown.is_set()) { \
+ _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(); \
+ } \
+ } else \
+ ((void)0)
+
+/**
* Do not use.
* If the application should never reach this point use CRASH_NOW_MSG(m_msg) to explain why.
*
diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp
index ff09b0b86c..4770c9c65f 100644
--- a/core/extension/gdnative_interface.cpp
+++ b/core/extension/gdnative_interface.cpp
@@ -51,13 +51,13 @@ static void gdnative_free(void *p_mem) {
// Helper print functions.
static void gdnative_print_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) {
- _err_print_error(p_function, p_file, p_line, p_description, ERR_HANDLER_ERROR);
+ _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_ERROR);
}
static void gdnative_print_warning(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) {
- _err_print_error(p_function, p_file, p_line, p_description, ERR_HANDLER_WARNING);
+ _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_WARNING);
}
static void gdnative_print_script_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) {
- _err_print_error(p_function, p_file, p_line, p_description, ERR_HANDLER_SCRIPT);
+ _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_SCRIPT);
}
// Variant functions
diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h
index 73f78bde54..8f8cb5a3e0 100644
--- a/core/extension/gdnative_interface.h
+++ b/core/extension/gdnative_interface.h
@@ -182,11 +182,11 @@ typedef void *(*GDNativeInstanceBindingCreateCallback)(void *p_token, void *p_in
typedef void (*GDNativeInstanceBindingFreeCallback)(void *p_token, void *p_instance, void *p_binding);
typedef GDNativeBool (*GDNativeInstanceBindingReferenceCallback)(void *p_token, void *p_binding, GDNativeBool p_reference);
-struct GDNativeInstanceBindingCallbacks {
+typedef struct {
GDNativeInstanceBindingCreateCallback create_callback;
GDNativeInstanceBindingFreeCallback free_callback;
GDNativeInstanceBindingReferenceCallback reference_callback;
-};
+} GDNativeInstanceBindingCallbacks;
/* EXTENSION CLASSES */
diff --git a/core/extension/native_extension.cpp b/core/extension/native_extension.cpp
index 635e53fa9c..a6b0a708c3 100644
--- a/core/extension/native_extension.cpp
+++ b/core/extension/native_extension.cpp
@@ -35,7 +35,9 @@
#include "core/object/method_bind.h"
#include "core/os/os.h"
-const char *NativeExtension::EXTENSION_LIST_CONFIG_FILE = "res://.godot/extension_list.cfg";
+String NativeExtension::get_extension_list_config_file() {
+ return ProjectSettings::get_singleton()->get_project_data_path().plus_file("extension_list.cfg");
+}
class NativeExtensionMethodBind : public MethodBind {
GDNativeExtensionClassMethodCall call_func;
diff --git a/core/extension/native_extension.h b/core/extension/native_extension.h
index 52e869ad4d..f7f235d8fc 100644
--- a/core/extension/native_extension.h
+++ b/core/extension/native_extension.h
@@ -62,7 +62,7 @@ protected:
static void _bind_methods();
public:
- static const char *EXTENSION_LIST_CONFIG_FILE;
+ static String get_extension_list_config_file();
Error open_library(const String &p_path, const String &p_entry_symbol);
void close_library();
diff --git a/core/extension/native_extension_manager.cpp b/core/extension/native_extension_manager.cpp
index 4eac5249c9..c8755250d5 100644
--- a/core/extension/native_extension_manager.cpp
+++ b/core/extension/native_extension_manager.cpp
@@ -112,7 +112,7 @@ void NativeExtensionManager::deinitialize_extensions(NativeExtension::Initializa
}
void NativeExtensionManager::load_extensions() {
- FileAccessRef f = FileAccess::open(NativeExtension::EXTENSION_LIST_CONFIG_FILE, FileAccess::READ);
+ FileAccessRef f = FileAccess::open(NativeExtension::get_extension_list_config_file(), FileAccess::READ);
while (f && !f->eof_reached()) {
String s = f->get_line().strip_edges();
if (s != String()) {
diff --git a/core/input/SCsub b/core/input/SCsub
index 740398b266..b12bf561de 100644
--- a/core/input/SCsub
+++ b/core/input/SCsub
@@ -7,19 +7,15 @@ import input_builders
# Order matters here. Higher index controller database files write on top of lower index database files.
controller_databases = [
- "#core/input/gamecontrollerdb.txt",
- "#core/input/godotcontrollerdb.txt",
+ "gamecontrollerdb.txt",
+ "godotcontrollerdb.txt",
]
-env.Depends("#core/input/default_controller_mappings.gen.cpp", controller_databases)
-env.CommandNoCache(
- "#core/input/default_controller_mappings.gen.cpp",
+gensource = env.CommandNoCache(
+ "default_controller_mappings.gen.cpp",
controller_databases,
env.Run(input_builders.make_default_controller_mappings, "Generating default controller mappings."),
)
env.add_source_files(env.core_sources, "*.cpp")
-
-# Don't warn about duplicate entry here, we need it registered manually for first build,
-# even if later builds will pick it up twice due to above *.cpp globbing.
-env.add_source_files(env.core_sources, "#core/input/default_controller_mappings.gen.cpp", warn_duplicates=False)
+env.add_source_files(env.core_sources, gensource)
diff --git a/core/input/input.cpp b/core/input/input.cpp
index f9a361c761..296aa1f071 100644
--- a/core/input/input.cpp
+++ b/core/input/input.cpp
@@ -117,6 +117,10 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_accelerometer"), &Input::get_accelerometer);
ClassDB::bind_method(D_METHOD("get_magnetometer"), &Input::get_magnetometer);
ClassDB::bind_method(D_METHOD("get_gyroscope"), &Input::get_gyroscope);
+ ClassDB::bind_method(D_METHOD("set_gravity", "value"), &Input::set_gravity);
+ ClassDB::bind_method(D_METHOD("set_accelerometer", "value"), &Input::set_accelerometer);
+ ClassDB::bind_method(D_METHOD("set_magnetometer", "value"), &Input::set_magnetometer);
+ ClassDB::bind_method(D_METHOD("set_gyroscope", "value"), &Input::set_gyroscope);
ClassDB::bind_method(D_METHOD("get_last_mouse_speed"), &Input::get_last_mouse_speed);
ClassDB::bind_method(D_METHOD("get_mouse_button_mask"), &Input::get_mouse_button_mask);
ClassDB::bind_method(D_METHOD("set_mouse_mode", "mode"), &Input::set_mouse_mode);
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index 1d2b5f19ee..c6448b1e44 100644
--- a/core/input/input_event.cpp
+++ b/core/input/input_event.cpp
@@ -452,8 +452,13 @@ bool InputEventKey::is_match(const Ref<InputEvent> &p_event, bool p_exact_match)
return false;
}
- return keycode == key->keycode &&
- (!p_exact_match || get_modifiers_mask() == key->get_modifiers_mask());
+ if (keycode == 0) {
+ return physical_keycode == key->physical_keycode &&
+ (!p_exact_match || get_modifiers_mask() == key->get_modifiers_mask());
+ } else {
+ return keycode == key->keycode &&
+ (!p_exact_match || get_modifiers_mask() == key->get_modifiers_mask());
+ }
}
void InputEventKey::_bind_methods() {
diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp
index e54c947340..df631053b8 100644
--- a/core/io/file_access_compressed.cpp
+++ b/core/io/file_access_compressed.cpp
@@ -233,7 +233,7 @@ uint64_t FileAccessCompressed::get_position() const {
if (writing) {
return write_pos;
} else {
- return read_block * block_size + read_pos;
+ return (uint64_t)read_block * block_size + read_pos;
}
}
diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp
index b5c882e9ce..53bf7456e6 100644
--- a/core/io/file_access_zip.cpp
+++ b/core/io/file_access_zip.cpp
@@ -99,7 +99,7 @@ static int godot_testerror(voidpf opaque, voidpf stream) {
}
static voidpf godot_alloc(voidpf opaque, uInt items, uInt size) {
- return memalloc(items * size);
+ return memalloc((size_t)items * size);
}
static void godot_free(voidpf opaque, voidpf address) {
diff --git a/core/io/logger.cpp b/core/io/logger.cpp
index 09539f716c..b68a8b20a5 100644
--- a/core/io/logger.cpp
+++ b/core/io/logger.cpp
@@ -50,7 +50,7 @@ void Logger::set_flush_stdout_on_print(bool value) {
_flush_stdout_on_print = value;
}
-void Logger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
+void Logger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type) {
if (!should_log(true)) {
return;
}
@@ -81,7 +81,11 @@ void Logger::log_error(const char *p_function, const char *p_file, int p_line, c
err_details = p_code;
}
- logf_error("%s: %s\n", err_type, err_details);
+ if (p_editor_notify) {
+ logf_error("%s: %s\n", err_type, err_details);
+ } else {
+ logf_error("USER %s: %s\n", err_type, err_details);
+ }
logf_error(" at: %s (%s:%i) - %s\n", p_function, p_file, p_line, p_code);
}
@@ -256,7 +260,7 @@ void CompositeLogger::logv(const char *p_format, va_list p_list, bool p_err) {
}
}
-void CompositeLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
+void CompositeLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type) {
if (!should_log(true)) {
return;
}
diff --git a/core/io/logger.h b/core/io/logger.h
index ccf68562d6..f244f70e7e 100644
--- a/core/io/logger.h
+++ b/core/io/logger.h
@@ -54,7 +54,7 @@ public:
static void set_flush_stdout_on_print(bool value);
virtual void logv(const char *p_format, va_list p_list, bool p_err) _PRINTF_FORMAT_ATTRIBUTE_2_0 = 0;
- virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
+ virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, ErrorType p_type = ERR_ERROR);
void logf(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3;
void logf_error(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3;
@@ -103,7 +103,7 @@ public:
CompositeLogger(Vector<Logger *> p_loggers);
virtual void logv(const char *p_format, va_list p_list, bool p_err) _PRINTF_FORMAT_ATTRIBUTE_2_0;
- virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
+ virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type = ERR_ERROR);
void add_logger(Logger *p_logger);
diff --git a/core/io/resource.cpp b/core/io/resource.cpp
index 1cefa52d69..972076e397 100644
--- a/core/io/resource.cpp
+++ b/core/io/resource.cpp
@@ -136,6 +136,7 @@ String Resource::get_scene_unique_id() const {
void Resource::set_name(const String &p_name) {
name = p_name;
+ emit_changed();
}
String Resource::get_name() const {
diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp
index 1e166015b0..cd44c537a8 100644
--- a/core/io/resource_importer.cpp
+++ b/core/io/resource_importer.cpp
@@ -418,7 +418,7 @@ Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_extension(const St
}
String ResourceFormatImporter::get_import_base_path(const String &p_for_file) const {
- return ProjectSettings::IMPORTED_FILES_PATH.plus_file(p_for_file.get_file() + "-" + p_for_file.md5_text());
+ return ProjectSettings::get_singleton()->get_imported_files_path().plus_file(p_for_file.get_file() + "-" + p_for_file.md5_text());
}
bool ResourceFormatImporter::are_import_settings_valid(const String &p_path) const {
diff --git a/core/io/resource_uid.cpp b/core/io/resource_uid.cpp
index 290a71043c..b7d01712ff 100644
--- a/core/io/resource_uid.cpp
+++ b/core/io/resource_uid.cpp
@@ -29,6 +29,8 @@
/*************************************************************************/
#include "resource_uid.h"
+
+#include "core/config/project_settings.h"
#include "core/crypto/crypto.h"
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
@@ -36,7 +38,9 @@
static constexpr uint32_t char_count = ('z' - 'a');
static constexpr uint32_t base = char_count + ('9' - '0');
-const char *ResourceUID::CACHE_FILE = "res://.godot/uid_cache.bin";
+String ResourceUID::get_cache_file() {
+ return ProjectSettings::get_singleton()->get_project_data_path().plus_file("uid_cache.bin");
+}
String ResourceUID::id_to_text(ID p_id) const {
if (p_id < 0) {
@@ -135,12 +139,13 @@ void ResourceUID::remove_id(ID p_id) {
}
Error ResourceUID::save_to_cache() {
- if (!FileAccess::exists(CACHE_FILE)) {
+ String cache_file = get_cache_file();
+ if (!FileAccess::exists(cache_file)) {
DirAccessRef d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- d->make_dir_recursive(String(CACHE_FILE).get_base_dir()); //ensure base dir exists
+ d->make_dir_recursive(String(cache_file).get_base_dir()); //ensure base dir exists
}
- FileAccessRef f = FileAccess::open(CACHE_FILE, FileAccess::WRITE);
+ FileAccessRef f = FileAccess::open(cache_file, FileAccess::WRITE);
if (!f) {
return ERR_CANT_OPEN;
}
@@ -164,7 +169,7 @@ Error ResourceUID::save_to_cache() {
}
Error ResourceUID::load_from_cache() {
- FileAccessRef f = FileAccess::open(CACHE_FILE, FileAccess::READ);
+ FileAccessRef f = FileAccess::open(get_cache_file(), FileAccess::READ);
if (!f) {
return ERR_CANT_OPEN;
}
@@ -206,7 +211,7 @@ Error ResourceUID::update_cache() {
for (OrderedHashMap<ID, Cache>::Element E = unique_ids.front(); E; E = E.next()) {
if (!E.get().saved_to_cache) {
if (f == nullptr) {
- f = FileAccess::open(CACHE_FILE, FileAccess::READ_WRITE); //append
+ f = FileAccess::open(get_cache_file(), FileAccess::READ_WRITE); //append
if (!f) {
return ERR_CANT_OPEN;
}
diff --git a/core/io/resource_uid.h b/core/io/resource_uid.h
index b12138425a..2f1bfdf243 100644
--- a/core/io/resource_uid.h
+++ b/core/io/resource_uid.h
@@ -44,7 +44,7 @@ public:
INVALID_ID = -1
};
- static const char *CACHE_FILE;
+ static String get_cache_file();
private:
mutable Ref<Crypto> crypto;
diff --git a/core/io/zip_io.cpp b/core/io/zip_io.cpp
index fb4c76aa7a..24808cc8d6 100644
--- a/core/io/zip_io.cpp
+++ b/core/io/zip_io.cpp
@@ -100,7 +100,7 @@ int zipio_testerror(voidpf opaque, voidpf stream) {
}
voidpf zipio_alloc(voidpf opaque, uInt items, uInt size) {
- voidpf ptr = memalloc(items * size);
+ voidpf ptr = memalloc((size_t)items * size);
memset(ptr, 0, items * size);
return ptr;
}
diff --git a/core/math/bvh.h b/core/math/bvh.h
index cefbc9b0db..65b8b102a3 100644
--- a/core/math/bvh.h
+++ b/core/math/bvh.h
@@ -200,7 +200,7 @@ public:
// use in conjunction with activate if you have deferred the collision check, and
// set pairable has never been called.
- // (deferred collision checks are a workaround for visual server for historical reasons)
+ // (deferred collision checks are a workaround for rendering server for historical reasons)
void force_collision_check(BVHHandle p_handle) {
if (USE_PAIRS) {
// the aabb should already be up to date in the BVH
diff --git a/core/math/face3.cpp b/core/math/face3.cpp
index 045ab67ce8..31a853e1a9 100644
--- a/core/math/face3.cpp
+++ b/core/math/face3.cpp
@@ -229,7 +229,7 @@ bool Face3::intersects_aabb(const AABB &p_aabb) const {
axis.normalize();
real_t minA, maxA, minB, maxB;
- p_aabb.project_range_in_plane(Plane(axis, 0), minA, maxA);
+ p_aabb.project_range_in_plane(Plane(axis), minA, maxA);
project_range(axis, Transform3D(), minB, maxB);
if (maxA < minB || maxB < minA) {
diff --git a/core/math/geometry_3d.cpp b/core/math/geometry_3d.cpp
index 6628b760e0..88d2656025 100644
--- a/core/math/geometry_3d.cpp
+++ b/core/math/geometry_3d.cpp
@@ -819,11 +819,9 @@ Vector<Plane> Geometry3D::build_sphere_planes(real_t p_radius, int p_lats, int p
planes.push_back(Plane(normal, p_radius));
for (int j = 1; j <= p_lats; j++) {
- // FIXME: This is stupid.
- Vector3 angle = normal.lerp(axis, j / (real_t)p_lats).normalized();
- Vector3 pos = angle * p_radius;
- planes.push_back(Plane(pos, angle));
- planes.push_back(Plane(pos * axis_neg, angle * axis_neg));
+ Vector3 plane_normal = normal.lerp(axis, j / (real_t)p_lats).normalized();
+ planes.push_back(Plane(plane_normal, p_radius));
+ planes.push_back(Plane(plane_normal * axis_neg, p_radius));
}
}
@@ -852,10 +850,10 @@ Vector<Plane> Geometry3D::build_capsule_planes(real_t p_radius, real_t p_height,
planes.push_back(Plane(normal, p_radius));
for (int j = 1; j <= p_lats; j++) {
- Vector3 angle = normal.lerp(axis, j / (real_t)p_lats).normalized();
- Vector3 pos = axis * p_height * 0.5 + angle * p_radius;
- planes.push_back(Plane(pos, angle));
- planes.push_back(Plane(pos * axis_neg, angle * axis_neg));
+ Vector3 plane_normal = normal.lerp(axis, j / (real_t)p_lats).normalized();
+ Vector3 position = axis * p_height * 0.5 + plane_normal * p_radius;
+ planes.push_back(Plane(plane_normal, position));
+ planes.push_back(Plane(plane_normal * axis_neg, position * axis_neg));
}
}
diff --git a/core/math/plane.h b/core/math/plane.h
index 2267b28c53..18be5d5d12 100644
--- a/core/math/plane.h
+++ b/core/math/plane.h
@@ -85,8 +85,8 @@ public:
normal(p_a, p_b, p_c),
d(p_d) {}
- _FORCE_INLINE_ Plane(const Vector3 &p_normal, real_t p_d);
- _FORCE_INLINE_ Plane(const Vector3 &p_point, const Vector3 &p_normal);
+ _FORCE_INLINE_ Plane(const Vector3 &p_normal, real_t p_d = 0.0);
+ _FORCE_INLINE_ Plane(const Vector3 &p_normal, const Vector3 &p_point);
_FORCE_INLINE_ Plane(const Vector3 &p_point1, const Vector3 &p_point2, const Vector3 &p_point3, ClockDirection p_dir = CLOCKWISE);
};
@@ -109,7 +109,7 @@ Plane::Plane(const Vector3 &p_normal, real_t p_d) :
d(p_d) {
}
-Plane::Plane(const Vector3 &p_point, const Vector3 &p_normal) :
+Plane::Plane(const Vector3 &p_normal, const Vector3 &p_point) :
normal(p_normal),
d(p_normal.dot(p_point)) {
}
diff --git a/core/multiplayer/multiplayer.h b/core/multiplayer/multiplayer.h
index 31b7bf0043..be398f02c8 100644
--- a/core/multiplayer/multiplayer.h
+++ b/core/multiplayer/multiplayer.h
@@ -52,7 +52,7 @@ enum RPCMode {
struct RPCConfig {
StringName name;
RPCMode rpc_mode = RPC_MODE_DISABLED;
- bool sync = false;
+ bool call_local = false;
TransferMode transfer_mode = TRANSFER_MODE_RELIABLE;
int channel = 0;
diff --git a/core/multiplayer/multiplayer_replicator.cpp b/core/multiplayer/multiplayer_replicator.cpp
index a4ea74327c..6604510394 100644
--- a/core/multiplayer/multiplayer_replicator.cpp
+++ b/core/multiplayer/multiplayer_replicator.cpp
@@ -572,7 +572,7 @@ Error MultiplayerReplicator::_spawn_despawn(ResourceUID::ID p_scene_id, Object *
args[0] = p_peer;
args[1] = p_scene_id;
args[2] = p_obj;
- args[3] = true;
+ args[3] = p_spawn;
const Variant *argp[] = { &args[0], &args[1], &args[2], &args[3] };
Callable::CallError ce;
Variant ret;
diff --git a/core/multiplayer/rpc_manager.cpp b/core/multiplayer/rpc_manager.cpp
index 20ab7a25bb..d8e875c3e6 100644
--- a/core/multiplayer/rpc_manager.cpp
+++ b/core/multiplayer/rpc_manager.cpp
@@ -476,9 +476,9 @@ void RPCManager::rpcp(Node *p_node, int p_peer_id, const StringName &p_method, c
vformat("Unable to get the RPC configuration for the function \"%s\" at path: \"%s\". This happens when the method is not marked for RPCs.", p_method, p_node->get_path()));
if (p_peer_id == 0 || p_peer_id == node_id || (p_peer_id < 0 && p_peer_id != -node_id)) {
if (rpc_id & (1 << 15)) {
- call_local_native = config.sync;
+ call_local_native = config.call_local;
} else {
- call_local_script = config.sync;
+ call_local_script = config.call_local;
}
}
@@ -521,5 +521,5 @@ void RPCManager::rpcp(Node *p_node, int p_peer_id, const StringName &p_method, c
}
}
- ERR_FAIL_COND_MSG(p_peer_id == node_id && !config.sync, "RPC '" + p_method + "' on yourself is not allowed by selected mode.");
+ ERR_FAIL_COND_MSG(p_peer_id == node_id && !config.call_local, "RPC '" + p_method + "' on yourself is not allowed by selected mode.");
}
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index d5509c50f1..4b3c8b123f 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -37,8 +37,6 @@
#define OBJTYPE_RLOCK RWLockRead _rw_lockr_(lock);
#define OBJTYPE_WLOCK RWLockWrite _rw_lockw_(lock);
-#ifdef DEBUG_METHODS_ENABLED
-
MethodDefinition D_METHOD(const char *p_name) {
MethodDefinition md;
md.name = StaticCString::create(p_name);
@@ -226,8 +224,6 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_
return md;
}
-#endif
-
ClassDB::APIType ClassDB::current_api = API_CORE;
void ClassDB::set_current_api(APIType p_api) {
@@ -589,7 +585,6 @@ void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherit
}
}
-#ifdef DEBUG_METHODS_ENABLED
static MethodInfo info_from_bind(MethodBind *p_method) {
MethodInfo minfo;
minfo.name = p_method->get_name();
@@ -610,7 +605,6 @@ static MethodInfo info_from_bind(MethodBind *p_method) {
return minfo;
}
-#endif
void ClassDB::get_method_list(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance, bool p_exclude_from_properties) {
OBJTYPE_RLOCK;
@@ -650,9 +644,8 @@ void ClassDB::get_method_list(const StringName &p_class, List<MethodInfo> *p_met
while ((K = type->method_map.next(K))) {
MethodBind *m = type->method_map[*K];
- MethodInfo mi;
- mi.name = m->get_name();
- p_methods->push_back(mi);
+ MethodInfo minfo = info_from_bind(m);
+ p_methods->push_back(minfo);
}
#endif
@@ -698,9 +691,8 @@ bool ClassDB::get_method_info(const StringName &p_class, const StringName &p_met
if (type->method_map.has(p_method)) {
if (r_info) {
MethodBind *m = type->method_map[p_method];
- MethodInfo mi;
- mi.name = m->get_name();
- *r_info = mi;
+ MethodInfo minfo = info_from_bind(m);
+ *r_info = minfo;
}
return true;
}
@@ -1411,13 +1403,8 @@ void ClassDB::bind_method_custom(const StringName &p_class, MethodBind *p_method
type->method_map[p_method->get_name()] = p_method;
}
-#ifdef DEBUG_METHODS_ENABLED
MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const Variant **p_defs, int p_defcount) {
StringName mdname = method_name.name;
-#else
-MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const char *method_name, const Variant **p_defs, int p_defcount) {
- StringName mdname = StaticCString::create(method_name);
-#endif
OBJTYPE_WLOCK;
ERR_FAIL_COND_V(!p_bind, nullptr);
diff --git a/core/object/class_db.h b/core/object/class_db.h
index 3a1cbf8559..d9eec4e4a8 100644
--- a/core/object/class_db.h
+++ b/core/object/class_db.h
@@ -45,8 +45,6 @@
#define DEFVAL(m_defval) (m_defval)
-#ifdef DEBUG_METHODS_ENABLED
-
struct MethodDefinition {
StringName name;
Vector<StringName> args;
@@ -72,26 +70,6 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10, const char *p_arg11, const char *p_arg12);
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10, const char *p_arg11, const char *p_arg12, const char *p_arg13);
-#else
-
-//#define NO_VARIADIC_MACROS
-
-#ifdef NO_VARIADIC_MACROS
-
-static _FORCE_INLINE_ const char *D_METHOD(const char *m_name, ...) {
- return m_name;
-}
-
-#else
-
-// When DEBUG_METHODS_ENABLED is set this will let the engine know
-// the argument names for easier debugging.
-#define D_METHOD(m_c, ...) m_c
-
-#endif
-
-#endif
-
class ClassDB {
public:
enum APIType {
@@ -156,11 +134,7 @@ public:
static HashMap<StringName, StringName> resource_base_extensions;
static HashMap<StringName, StringName> compat_classes;
-#ifdef DEBUG_METHODS_ENABLED
static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const Variant **p_defs, int p_defcount);
-#else
- static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const char *method_name, const Variant **p_defs, int p_defcount);
-#endif
static APIType current_api;
@@ -190,6 +164,7 @@ public:
t->creation_func = &creator<T>;
t->exposed = true;
t->class_ptr = T::get_class_ptr_static();
+ t->api = current_api;
T::register_custom_data_to_otdb();
}
@@ -201,6 +176,7 @@ public:
ERR_FAIL_COND(!t);
t->exposed = true;
t->class_ptr = T::get_class_ptr_static();
+ t->api = current_api;
//nothing
}
@@ -221,6 +197,7 @@ public:
t->creation_func = &_create_ptr_func<T>;
t->exposed = true;
t->class_ptr = T::get_class_ptr_static();
+ t->api = current_api;
T::register_custom_data_to_otdb();
}
diff --git a/core/object/method_bind.cpp b/core/object/method_bind.cpp
index c53104fe3f..642e27c41d 100644
--- a/core/object/method_bind.cpp
+++ b/core/object/method_bind.cpp
@@ -63,12 +63,15 @@ uint32_t MethodBind::get_hash() const {
return hash;
}
-#ifdef DEBUG_METHODS_ENABLED
PropertyInfo MethodBind::get_argument_info(int p_argument) const {
ERR_FAIL_INDEX_V(p_argument, get_argument_count(), PropertyInfo());
PropertyInfo info = _gen_argument_type_info(p_argument);
+#ifdef DEBUG_METHODS_ENABLED
info.name = p_argument < arg_names.size() ? String(arg_names[p_argument]) : String("arg" + itos(p_argument));
+#else
+ info.name = String("arg" + itos(p_argument));
+#endif
return info;
}
@@ -76,7 +79,6 @@ PropertyInfo MethodBind::get_return_info() const {
return _gen_argument_type_info(-1);
}
-#endif
void MethodBind::_set_const(bool p_const) {
_const = p_const;
}
@@ -109,7 +111,6 @@ void MethodBind::set_default_arguments(const Vector<Variant> &p_defargs) {
default_argument_count = default_arguments.size();
}
-#ifdef DEBUG_METHODS_ENABLED
void MethodBind::_generate_argument_types(int p_count) {
set_argument_count(p_count);
@@ -123,17 +124,13 @@ void MethodBind::_generate_argument_types(int p_count) {
argument_types = argt;
}
-#endif
-
MethodBind::MethodBind() {
static int last_id = 0;
method_id = last_id++;
}
MethodBind::~MethodBind() {
-#ifdef DEBUG_METHODS_ENABLED
if (argument_types) {
memdelete_arr(argument_types);
}
-#endif
}
diff --git a/core/object/method_bind.h b/core/object/method_bind.h
index b0b379873e..ee003099a0 100644
--- a/core/object/method_bind.h
+++ b/core/object/method_bind.h
@@ -64,18 +64,16 @@ class MethodBind {
bool _returns = false;
protected:
-#ifdef DEBUG_METHODS_ENABLED
Variant::Type *argument_types = nullptr;
+#ifdef DEBUG_METHODS_ENABLED
Vector<StringName> arg_names;
#endif
void _set_const(bool p_const);
void _set_returns(bool p_returns);
-#ifdef DEBUG_METHODS_ENABLED
virtual Variant::Type _gen_argument_type(int p_arg) const = 0;
virtual PropertyInfo _gen_argument_type_info(int p_arg) const = 0;
void _generate_argument_types(int p_count);
-#endif
void set_argument_count(int p_count) { argument_count = p_count; }
public:
@@ -102,7 +100,6 @@ public:
}
}
-#ifdef DEBUG_METHODS_ENABLED
_FORCE_INLINE_ Variant::Type get_argument_type(int p_argument) const {
ERR_FAIL_COND_V(p_argument < -1 || p_argument > argument_count, Variant::NIL);
return argument_types[p_argument + 1];
@@ -111,6 +108,7 @@ public:
PropertyInfo get_argument_info(int p_argument) const;
PropertyInfo get_return_info() const;
+#ifdef DEBUG_METHODS_ENABLED
void set_argument_names(const Vector<StringName> &p_names); // Set by ClassDB, can't be inferred otherwise.
Vector<StringName> get_argument_names() const;
@@ -149,12 +147,9 @@ public:
protected:
NativeCall call_method = nullptr;
-#ifdef DEBUG_METHODS_ENABLED
MethodInfo arguments;
-#endif
public:
-#ifdef DEBUG_METHODS_ENABLED
virtual PropertyInfo _gen_argument_type_info(int p_arg) const {
if (p_arg < 0) {
return arguments.return_val;
@@ -169,13 +164,10 @@ public:
return _gen_argument_type_info(p_arg).type;
}
+#ifdef DEBUG_METHODS_ENABLED
virtual GodotTypeInfo::Metadata get_argument_meta(int) const {
return GodotTypeInfo::METADATA_NONE;
}
-#else
- virtual Variant::Type _gen_argument_type(int p_arg) const {
- return Variant::NIL;
- }
#endif
virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
@@ -185,25 +177,29 @@ public:
void set_method_info(const MethodInfo &p_info, bool p_return_nil_is_variant) {
set_argument_count(p_info.arguments.size());
-#ifdef DEBUG_METHODS_ENABLED
Variant::Type *at = memnew_arr(Variant::Type, p_info.arguments.size() + 1);
at[0] = p_info.return_val.type;
if (p_info.arguments.size()) {
+#ifdef DEBUG_METHODS_ENABLED
Vector<StringName> names;
names.resize(p_info.arguments.size());
+#endif
for (int i = 0; i < p_info.arguments.size(); i++) {
at[i + 1] = p_info.arguments[i].type;
+#ifdef DEBUG_METHODS_ENABLED
names.write[i] = p_info.arguments[i].name;
+#endif
}
+#ifdef DEBUG_METHODS_ENABLED
set_argument_names(names);
+#endif
}
argument_types = at;
arguments = p_info;
if (p_return_nil_is_variant) {
arguments.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
}
-#endif
}
virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) {
@@ -248,7 +244,6 @@ class MethodBindT : public MethodBind {
void (MB_T::*method)(P...);
protected:
-#ifdef DEBUG_METHODS_ENABLED
// GCC raises warnings in the case P = {} as the comparison is always false...
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
@@ -270,7 +265,6 @@ protected:
call_get_argument_type_info<P...>(p_arg, pi);
return pi;
}
-#endif
public:
#ifdef DEBUG_METHODS_ENABLED
@@ -298,9 +292,7 @@ public:
MethodBindT(void (MB_T::*p_method)(P...)) {
method = p_method;
-#ifdef DEBUG_METHODS_ENABLED
_generate_argument_types(sizeof...(P));
-#endif
set_argument_count(sizeof...(P));
}
};
@@ -327,7 +319,6 @@ class MethodBindTC : public MethodBind {
void (MB_T::*method)(P...) const;
protected:
-#ifdef DEBUG_METHODS_ENABLED
// GCC raises warnings in the case P = {} as the comparison is always false...
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
@@ -349,7 +340,6 @@ protected:
call_get_argument_type_info<P...>(p_arg, pi);
return pi;
}
-#endif
public:
#ifdef DEBUG_METHODS_ENABLED
@@ -378,9 +368,7 @@ public:
MethodBindTC(void (MB_T::*p_method)(P...) const) {
method = p_method;
_set_const(true);
-#ifdef DEBUG_METHODS_ENABLED
_generate_argument_types(sizeof...(P));
-#endif
set_argument_count(sizeof...(P));
}
};
@@ -408,7 +396,6 @@ class MethodBindTR : public MethodBind {
(P...);
protected:
-#ifdef DEBUG_METHODS_ENABLED
// GCC raises warnings in the case P = {} as the comparison is always false...
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
@@ -434,7 +421,6 @@ protected:
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
-#endif
public:
#ifdef DEBUG_METHODS_ENABLED
@@ -468,9 +454,7 @@ public:
MethodBindTR(R (MB_T::*p_method)(P...)) {
method = p_method;
_set_returns(true);
-#ifdef DEBUG_METHODS_ENABLED
_generate_argument_types(sizeof...(P));
-#endif
set_argument_count(sizeof...(P));
}
};
@@ -499,7 +483,6 @@ class MethodBindTRC : public MethodBind {
(P...) const;
protected:
-#ifdef DEBUG_METHODS_ENABLED
// GCC raises warnings in the case P = {} as the comparison is always false...
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
@@ -525,7 +508,6 @@ protected:
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
-#endif
public:
#ifdef DEBUG_METHODS_ENABLED
@@ -560,9 +542,7 @@ public:
method = p_method;
_set_returns(true);
_set_const(true);
-#ifdef DEBUG_METHODS_ENABLED
_generate_argument_types(sizeof...(P));
-#endif
set_argument_count(sizeof...(P));
}
};
diff --git a/core/object/undo_redo.cpp b/core/object/undo_redo.cpp
index b7d2bac96d..9c84c2add7 100644
--- a/core/object/undo_redo.cpp
+++ b/core/object/undo_redo.cpp
@@ -32,6 +32,7 @@
#include "core/io/resource.h"
#include "core/os/os.h"
+#include "core/templates/local_vector.h"
void UndoRedo::_discard_redo() {
if (current_action == actions.size() - 1) {
@@ -85,10 +86,17 @@ void UndoRedo::create_action(const String &p_name, MergeMode p_mode) {
current_action = actions.size() - 2;
if (p_mode == MERGE_ENDS) {
- // Clear all do ops from last action, and delete all object references
- List<Operation>::Element *E = actions.write[current_action + 1].do_ops.front();
+ // Clear all do ops from last action if they are not forced kept
+ LocalVector<List<Operation>::Element *> to_remove;
+ for (List<Operation>::Element *E = actions.write[current_action + 1].do_ops.front(); E; E = E->next()) {
+ if (!E->get().force_keep_in_merge_ends) {
+ to_remove.push_back(E);
+ }
+ }
- while (E) {
+ for (unsigned int i = 0; i < to_remove.size(); i++) {
+ List<Operation>::Element *E = to_remove[i];
+ // Delete all object references
if (E->get().type == Operation::TYPE_REFERENCE) {
Object *obj = ObjectDB::get_instance(E->get().object);
@@ -96,9 +104,7 @@ void UndoRedo::create_action(const String &p_name, MergeMode p_mode) {
memdelete(obj);
}
}
-
- E = E->next();
- actions.write[current_action + 1].do_ops.pop_front();
+ E->erase();
}
}
@@ -117,6 +123,8 @@ void UndoRedo::create_action(const String &p_name, MergeMode p_mode) {
}
action_level++;
+
+ force_keep_in_merge_ends = false;
}
void UndoRedo::add_do_method(Object *p_object, const StringName &p_method, VARIANT_ARG_DECLARE) {
@@ -146,7 +154,7 @@ void UndoRedo::add_undo_method(Object *p_object, const StringName &p_method, VAR
ERR_FAIL_COND((current_action + 1) >= actions.size());
// No undo if the merge mode is MERGE_ENDS
- if (merge_mode == MERGE_ENDS) {
+ if (!force_keep_in_merge_ends && merge_mode == MERGE_ENDS) {
return;
}
@@ -157,6 +165,7 @@ void UndoRedo::add_undo_method(Object *p_object, const StringName &p_method, VAR
}
undo_op.type = Operation::TYPE_METHOD;
+ undo_op.force_keep_in_merge_ends = force_keep_in_merge_ends;
undo_op.name = p_method;
for (int i = 0; i < VARIANT_ARG_MAX; i++) {
@@ -187,7 +196,7 @@ void UndoRedo::add_undo_property(Object *p_object, const StringName &p_property,
ERR_FAIL_COND((current_action + 1) >= actions.size());
// No undo if the merge mode is MERGE_ENDS
- if (merge_mode == MERGE_ENDS) {
+ if (!force_keep_in_merge_ends && merge_mode == MERGE_ENDS) {
return;
}
@@ -198,6 +207,7 @@ void UndoRedo::add_undo_property(Object *p_object, const StringName &p_property,
}
undo_op.type = Operation::TYPE_PROPERTY;
+ undo_op.force_keep_in_merge_ends = force_keep_in_merge_ends;
undo_op.name = p_property;
undo_op.args[0] = p_value;
actions.write[current_action + 1].undo_ops.push_back(undo_op);
@@ -223,7 +233,7 @@ void UndoRedo::add_undo_reference(Object *p_object) {
ERR_FAIL_COND((current_action + 1) >= actions.size());
// No undo if the merge mode is MERGE_ENDS
- if (merge_mode == MERGE_ENDS) {
+ if (!force_keep_in_merge_ends && merge_mode == MERGE_ENDS) {
return;
}
@@ -234,9 +244,24 @@ void UndoRedo::add_undo_reference(Object *p_object) {
}
undo_op.type = Operation::TYPE_REFERENCE;
+ undo_op.force_keep_in_merge_ends = force_keep_in_merge_ends;
actions.write[current_action + 1].undo_ops.push_back(undo_op);
}
+void UndoRedo::start_force_keep_in_merge_ends() {
+ ERR_FAIL_COND(action_level <= 0);
+ ERR_FAIL_COND((current_action + 1) >= actions.size());
+
+ force_keep_in_merge_ends = true;
+}
+
+void UndoRedo::end_force_keep_in_merge_ends() {
+ ERR_FAIL_COND(action_level <= 0);
+ ERR_FAIL_COND((current_action + 1) >= actions.size());
+
+ force_keep_in_merge_ends = false;
+}
+
void UndoRedo::_pop_history_tail() {
_discard_redo();
@@ -538,6 +563,9 @@ void UndoRedo::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_do_reference", "object"), &UndoRedo::add_do_reference);
ClassDB::bind_method(D_METHOD("add_undo_reference", "object"), &UndoRedo::add_undo_reference);
+ ClassDB::bind_method(D_METHOD("start_force_keep_in_merge_ends"), &UndoRedo::start_force_keep_in_merge_ends);
+ ClassDB::bind_method(D_METHOD("end_force_keep_in_merge_ends"), &UndoRedo::end_force_keep_in_merge_ends);
+
ClassDB::bind_method(D_METHOD("get_history_count"), &UndoRedo::get_history_count);
ClassDB::bind_method(D_METHOD("get_current_action"), &UndoRedo::get_current_action);
ClassDB::bind_method(D_METHOD("get_action_name", "id"), &UndoRedo::get_action_name);
diff --git a/core/object/undo_redo.h b/core/object/undo_redo.h
index d1ce252d86..a757d154e2 100644
--- a/core/object/undo_redo.h
+++ b/core/object/undo_redo.h
@@ -61,6 +61,7 @@ private:
};
Type type;
+ bool force_keep_in_merge_ends;
Ref<RefCounted> ref;
ObjectID object;
StringName name;
@@ -76,6 +77,7 @@ private:
Vector<Action> actions;
int current_action = -1;
+ bool force_keep_in_merge_ends = false;
int action_level = 0;
MergeMode merge_mode = MERGE_DISABLE;
bool merging = false;
@@ -109,6 +111,9 @@ public:
void add_do_reference(Object *p_object);
void add_undo_reference(Object *p_object);
+ void start_force_keep_in_merge_ends();
+ void end_force_keep_in_merge_ends();
+
bool is_committing_action() const;
void commit_action(bool p_execute = true);
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 12f85858c3..7404ffdcd5 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -75,12 +75,12 @@ void OS::add_logger(Logger *p_logger) {
}
}
-void OS::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, Logger::ErrorType p_type) {
+void OS::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, Logger::ErrorType p_type) {
if (!_stderr_enabled) {
return;
}
- _logger->log_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
+ _logger->log_error(p_function, p_file, p_line, p_code, p_rationale, p_editor_notify, p_type);
}
void OS::print(const char *p_format, ...) {
diff --git a/core/os/os.h b/core/os/os.h
index 29d33ce4f0..6d7bc47407 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -110,7 +110,7 @@ public:
static OS *get_singleton();
- void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, Logger::ErrorType p_type = Logger::ERR_ERROR);
+ void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, Logger::ErrorType p_type = Logger::ERR_ERROR);
void print(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3;
void printerr(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3;
diff --git a/core/string/optimized_translation.cpp b/core/string/optimized_translation.cpp
index 839b7a9c01..f8be564740 100644
--- a/core/string/optimized_translation.cpp
+++ b/core/string/optimized_translation.cpp
@@ -64,7 +64,6 @@ void OptimizedTranslation::generate(const Ref<Translation> &p_from) {
int idx = 0;
int total_compression_size = 0;
- int total_string_size = 0;
for (const StringName &E : keys) {
//hash string
@@ -102,7 +101,6 @@ void OptimizedTranslation::generate(const Ref<Translation> &p_from) {
compressed.write[idx] = ps;
total_compression_size += ps.compressed.size();
- total_string_size += src_s.size();
idx++;
}
@@ -147,15 +145,12 @@ void OptimizedTranslation::generate(const Ref<Translation> &p_from) {
uint32_t *btw = (uint32_t *)&btwb[0];
int btindex = 0;
- int collisions = 0;
for (int i = 0; i < size; i++) {
const Map<uint32_t, int> &t = table[i];
if (t.size() == 0) {
htw[i] = 0xFFFFFFFF; //nothing
continue;
- } else if (t.size() > 1) {
- collisions += t.size() - 1;
}
htw[i] = btindex;
diff --git a/core/templates/hash_map.h b/core/templates/hash_map.h
index 1257b54449..1634219c23 100644
--- a/core/templates/hash_map.h
+++ b/core/templates/hash_map.h
@@ -62,7 +62,9 @@ public:
TKey key;
TData data;
- Pair() {}
+ Pair(const TKey &p_key) :
+ key(p_key),
+ data() {}
Pair(const TKey &p_key, const TData &p_data) :
key(p_key),
data(p_data) {
@@ -90,6 +92,12 @@ public:
const TData &value() const {
return pair.value();
}
+
+ Element(const TKey &p_key) :
+ pair(p_key) {}
+ Element(const Element &p_other) :
+ hash(p_other.hash),
+ pair(p_other.pair.key, p_other.pair.data) {}
};
private:
@@ -192,14 +200,12 @@ private:
Element *create_element(const TKey &p_key) {
/* if element doesn't exist, create it */
- Element *e = memnew(Element);
+ Element *e = memnew(Element(p_key));
ERR_FAIL_COND_V_MSG(!e, nullptr, "Out of memory.");
uint32_t hash = Hasher::hash(p_key);
uint32_t index = hash & ((1 << hash_table_power) - 1);
e->next = hash_table[index];
e->hash = hash;
- e->pair.key = p_key;
- e->pair.data = TData();
hash_table[index] = e;
elements++;
@@ -228,9 +234,7 @@ private:
const Element *e = p_t.hash_table[i];
while (e) {
- Element *le = memnew(Element); /* local element */
-
- *le = *e; /* copy data */
+ Element *le = memnew(Element(*e)); /* local element */
/* add to list and reassign pointers */
le->next = hash_table[i];
diff --git a/core/templates/hashfuncs.h b/core/templates/hashfuncs.h
index 2e932f9f26..c1a7c4146e 100644
--- a/core/templates/hashfuncs.h
+++ b/core/templates/hashfuncs.h
@@ -74,6 +74,13 @@ static inline uint32_t hash_djb2_one_32(uint32_t p_in, uint32_t p_prev = 5381) {
return ((p_prev << 5) + p_prev) + p_in;
}
+/**
+ * Thomas Wang's 64-bit to 32-bit Hash function:
+ * https://web.archive.org/web/20071223173210/https:/www.concentric.net/~Ttwang/tech/inthash.htm
+ *
+ * @param p_int - 64-bit unsigned integer key to be hashed
+ * @return unsigned 32-bit value representing hashcode
+ */
static inline uint32_t hash_one_uint64(const uint64_t p_int) {
uint64_t v = p_int;
v = (~v) + (v << 18); // v = (v << 18) - v - 1;
@@ -82,7 +89,7 @@ static inline uint32_t hash_one_uint64(const uint64_t p_int) {
v = v ^ (v >> 11);
v = v + (v << 6);
v = v ^ (v >> 22);
- return (int)v;
+ return uint32_t(v);
}
static inline uint32_t hash_djb2_one_float(double p_in, uint32_t p_prev = 5381) {
diff --git a/core/typedefs.h b/core/typedefs.h
index dde254af23..8ca3d13e63 100644
--- a/core/typedefs.h
+++ b/core/typedefs.h
@@ -62,9 +62,9 @@
#endif
#endif
-// Should always inline, except in debug builds because it makes debugging harder.
+// Should always inline, except in dev builds because it makes debugging harder.
#ifndef _FORCE_INLINE_
-#ifdef DISABLE_FORCED_INLINE
+#ifdef DEV_ENABLED
#define _FORCE_INLINE_ inline
#else
#define _FORCE_INLINE_ _ALWAYS_INLINE_
diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h
index 3b2c837096..8592a1dc62 100644
--- a/core/variant/binder_common.h
+++ b/core/variant/binder_common.h
@@ -563,13 +563,11 @@ void call_with_validated_variant_args_static_method_ret(R (*p_method)(P...), con
// GCC raises "parameter 'p_args' set but not used" when P = {},
// it's not clever enough to treat other P values as making this branch valid.
-#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
+#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#endif
-#ifdef DEBUG_METHODS_ENABLED
-
template <class Q>
void call_get_argument_type_helper(int p_arg, int &index, Variant::Type &type) {
if (p_arg == index) {
@@ -608,6 +606,7 @@ void call_get_argument_type_info(int p_arg, PropertyInfo &info) {
(void)index; // Suppress GCC warning.
}
+#ifdef DEBUG_METHODS_ENABLED
template <class Q>
void call_get_argument_metadata_helper(int p_arg, int &index, GodotTypeInfo::Metadata &md) {
if (p_arg == index) {
@@ -629,13 +628,6 @@ GodotTypeInfo::Metadata call_get_argument_metadata(int p_arg) {
return md;
}
-#else
-
-template <class... P>
-Variant::Type call_get_argument_type(int p_arg) {
- return Variant::NIL;
-}
-
#endif // DEBUG_METHODS_ENABLED
//////////////////////
@@ -915,7 +907,7 @@ void call_with_variant_args_static_dv(void (*p_method)(P...), const Variant **p_
call_with_variant_args_static(p_method, args, r_error, BuildIndexSequence<sizeof...(P)>{});
}
-#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
+#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp
index 0dbeb6e4cb..3214fc125d 100644
--- a/core/variant/variant.cpp
+++ b/core/variant/variant.cpp
@@ -1624,6 +1624,19 @@ Variant::operator String() const {
return stringify(stack);
}
+template <class T>
+String stringify_vector(const T &vec, List<const void *> &stack) {
+ String str("[");
+ for (int i = 0; i < vec.size(); i++) {
+ if (i > 0) {
+ str += ", ";
+ }
+ str = str + Variant(vec[i]).stringify(stack);
+ }
+ str += "]";
+ return str;
+}
+
String Variant::stringify(List<const void *> &stack) const {
switch (type) {
case NIL:
@@ -1703,88 +1716,31 @@ String Variant::stringify(List<const void *> &stack) const {
return str;
} break;
case PACKED_VECTOR2_ARRAY: {
- Vector<Vector2> vec = operator Vector<Vector2>();
- String str("[");
- for (int i = 0; i < vec.size(); i++) {
- if (i > 0) {
- str += ", ";
- }
- str = str + Variant(vec[i]);
- }
- str += "]";
- return str;
+ return stringify_vector(operator Vector<Vector2>(), stack);
} break;
case PACKED_VECTOR3_ARRAY: {
- Vector<Vector3> vec = operator Vector<Vector3>();
- String str("[");
- for (int i = 0; i < vec.size(); i++) {
- if (i > 0) {
- str += ", ";
- }
- str = str + Variant(vec[i]);
- }
- str += "]";
- return str;
+ return stringify_vector(operator Vector<Vector3>(), stack);
+ } break;
+ case PACKED_COLOR_ARRAY: {
+ return stringify_vector(operator Vector<Color>(), stack);
} break;
case PACKED_STRING_ARRAY: {
- Vector<String> vec = operator Vector<String>();
- String str("[");
- for (int i = 0; i < vec.size(); i++) {
- if (i > 0) {
- str += ", ";
- }
- str = str + vec[i];
- }
- str += "]";
- return str;
+ return stringify_vector(operator Vector<String>(), stack);
+ } break;
+ case PACKED_BYTE_ARRAY: {
+ return stringify_vector(operator Vector<uint8_t>(), stack);
} break;
case PACKED_INT32_ARRAY: {
- Vector<int32_t> vec = operator Vector<int32_t>();
- String str("[");
- for (int i = 0; i < vec.size(); i++) {
- if (i > 0) {
- str += ", ";
- }
- str = str + itos(vec[i]);
- }
- str += "]";
- return str;
+ return stringify_vector(operator Vector<int32_t>(), stack);
} break;
case PACKED_INT64_ARRAY: {
- Vector<int64_t> vec = operator Vector<int64_t>();
- String str("[");
- for (int i = 0; i < vec.size(); i++) {
- if (i > 0) {
- str += ", ";
- }
- str = str + itos(vec[i]);
- }
- str += "]";
- return str;
+ return stringify_vector(operator Vector<int64_t>(), stack);
} break;
case PACKED_FLOAT32_ARRAY: {
- Vector<float> vec = operator Vector<float>();
- String str("[");
- for (int i = 0; i < vec.size(); i++) {
- if (i > 0) {
- str += ", ";
- }
- str = str + rtos(vec[i]);
- }
- str += "]";
- return str;
+ return stringify_vector(operator Vector<float>(), stack);
} break;
case PACKED_FLOAT64_ARRAY: {
- Vector<double> vec = operator Vector<double>();
- String str("[");
- for (int i = 0; i < vec.size(); i++) {
- if (i > 0) {
- str += ", ";
- }
- str = str + rtos(vec[i]);
- }
- str += "]";
- return str;
+ return stringify_vector(operator Vector<double>(), stack);
} break;
case ARRAY: {
Array arr = operator Array();
@@ -1793,16 +1749,8 @@ String Variant::stringify(List<const void *> &stack) const {
}
stack.push_back(arr.id());
- String str("[");
- for (int i = 0; i < arr.size(); i++) {
- if (i) {
- str += ", ";
- }
-
- str += arr[i].stringify(stack);
- }
+ String str = stringify_vector(arr, stack);
- str += "]";
stack.erase(arr.id());
return str;
@@ -3145,10 +3093,18 @@ bool Variant::hash_compare(const Variant &p_variant) const {
}
switch (type) {
+ case INT: {
+ return _data._int == p_variant._data._int;
+ } break;
+
case FLOAT: {
return hash_compare_scalar(_data._float, p_variant._data._float);
} break;
+ case STRING: {
+ return *reinterpret_cast<const String *>(_data._mem) == *reinterpret_cast<const String *>(p_variant._data._mem);
+ } break;
+
case VECTOR2: {
const Vector2 *l = reinterpret_cast<const Vector2 *>(_data._mem);
const Vector2 *r = reinterpret_cast<const Vector2 *>(p_variant._data._mem);
diff --git a/core/variant/variant.h b/core/variant/variant.h
index 9ec131a1b8..d3f694e7ca 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -641,6 +641,7 @@ public:
static UtilityFunctionType get_utility_function_type(const StringName &p_name);
+ static MethodInfo get_utility_function_info(const StringName &p_name);
static int get_utility_function_argument_count(const StringName &p_name);
static Variant::Type get_utility_function_argument_type(const StringName &p_name, int p_arg);
static String get_utility_function_argument_name(const StringName &p_name, int p_arg);
diff --git a/core/variant/variant_construct.cpp b/core/variant/variant_construct.cpp
index 4317b9dc98..6aba7d7d58 100644
--- a/core/variant/variant_construct.cpp
+++ b/core/variant/variant_construct.cpp
@@ -119,8 +119,9 @@ void Variant::_register_variant_constructors() {
add_constructor<VariantConstructNoArgs<Plane>>(sarray());
add_constructor<VariantConstructor<Plane, Plane>>(sarray("from"));
+ add_constructor<VariantConstructor<Plane, Vector3>>(sarray("normal"));
add_constructor<VariantConstructor<Plane, Vector3, double>>(sarray("normal", "d"));
- add_constructor<VariantConstructor<Plane, Vector3, Vector3>>(sarray("point", "normal"));
+ add_constructor<VariantConstructor<Plane, Vector3, Vector3>>(sarray("normal", "point"));
add_constructor<VariantConstructor<Plane, Vector3, Vector3, Vector3>>(sarray("point1", "point2", "point3"));
add_constructor<VariantConstructor<Plane, double, double, double, double>>(sarray("a", "b", "c", "d"));
diff --git a/core/variant/variant_internal.h b/core/variant/variant_internal.h
index 40c8a1bfde..37383ff2ec 100644
--- a/core/variant/variant_internal.h
+++ b/core/variant/variant_internal.h
@@ -1301,12 +1301,12 @@ struct VariantZeroAssigner<Signal> {
template <>
struct VariantZeroAssigner<Dictionary> {
- static _FORCE_INLINE_ void zero(Variant *v) {}
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_dictionary(v) = Dictionary(); }
};
template <>
struct VariantZeroAssigner<Array> {
- static _FORCE_INLINE_ void zero(Variant *v) {}
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_array(v) = Array(); }
};
template <>
diff --git a/core/variant/variant_op.cpp b/core/variant/variant_op.cpp
index b94588f480..b85ece338c 100644
--- a/core/variant/variant_op.cpp
+++ b/core/variant/variant_op.cpp
@@ -641,7 +641,10 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorNotFloat>(Variant::OP_NOT, Variant::FLOAT, Variant::NIL);
register_op<OperatorEvaluatorNotObject>(Variant::OP_NOT, Variant::OBJECT, Variant::NIL);
- register_op<OperatorEvaluatorInStringFind>(Variant::OP_IN, Variant::STRING, Variant::STRING);
+ register_op<OperatorEvaluatorInStringFind<String>>(Variant::OP_IN, Variant::STRING, Variant::STRING);
+ register_op<OperatorEvaluatorInStringFind<StringName>>(Variant::OP_IN, Variant::STRING_NAME, Variant::STRING);
+ register_op<OperatorEvaluatorInStringNameFind<String>>(Variant::OP_IN, Variant::STRING, Variant::STRING_NAME);
+ register_op<OperatorEvaluatorInStringNameFind<StringName>>(Variant::OP_IN, Variant::STRING_NAME, Variant::STRING_NAME);
register_op<OperatorEvaluatorInDictionaryHasNil>(Variant::OP_IN, Variant::NIL, Variant::DICTIONARY);
register_op<OperatorEvaluatorInDictionaryHas<bool>>(Variant::OP_IN, Variant::BOOL, Variant::DICTIONARY);
diff --git a/core/variant/variant_op.h b/core/variant/variant_op.h
index 3c9f849a4f..353524469a 100644
--- a/core/variant/variant_op.h
+++ b/core/variant/variant_op.h
@@ -1213,22 +1213,44 @@ public:
////
+template <class Left>
class OperatorEvaluatorInStringFind {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
- const String &str_a = *VariantGetInternalPtr<String>::get_ptr(&p_left);
+ const Left &str_a = *VariantGetInternalPtr<Left>::get_ptr(&p_left);
const String &str_b = *VariantGetInternalPtr<String>::get_ptr(&p_right);
*r_ret = str_b.find(str_a) != -1;
r_valid = true;
}
static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
- const String &str_a = *VariantGetInternalPtr<String>::get_ptr(left);
+ const Left &str_a = *VariantGetInternalPtr<Left>::get_ptr(left);
const String &str_b = *VariantGetInternalPtr<String>::get_ptr(right);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = str_b.find(str_a) != -1;
}
static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
- PtrToArg<bool>::encode(PtrToArg<String>::convert(right).find(PtrToArg<String>::convert(left)) != -1, r_ret);
+ PtrToArg<bool>::encode(PtrToArg<String>::convert(right).find(PtrToArg<Left>::convert(left)) != -1, r_ret);
+ }
+ static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+template <class Left>
+class OperatorEvaluatorInStringNameFind {
+public:
+ static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+ const Left &str_a = *VariantGetInternalPtr<Left>::get_ptr(&p_left);
+ const String str_b = VariantGetInternalPtr<StringName>::get_ptr(&p_right)->operator String();
+
+ *r_ret = str_b.find(str_a) != -1;
+ r_valid = true;
+ }
+ static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ const Left &str_a = *VariantGetInternalPtr<Left>::get_ptr(left);
+ const String str_b = VariantGetInternalPtr<StringName>::get_ptr(right)->operator String();
+ *VariantGetInternalPtr<bool>::get_ptr(r_ret) = str_b.find(str_a) != -1;
+ }
+ static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+ PtrToArg<bool>::encode(PtrToArg<StringName>::convert(right).operator String().find(PtrToArg<Left>::convert(left)) != -1, r_ret);
}
static Variant::Type get_return_type() { return Variant::BOOL; }
};
diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp
index a214a238a6..221a8c4f98 100644
--- a/core/variant/variant_parser.cpp
+++ b/core/variant/variant_parser.cpp
@@ -90,6 +90,17 @@ const char *VariantParser::tk_name[TK_MAX] = {
"ERROR"
};
+static double stor_fix(const String &p_str) {
+ if (p_str == "inf") {
+ return INFINITY;
+ } else if (p_str == "inf_neg") {
+ return -INFINITY;
+ } else if (p_str == "nan") {
+ return NAN;
+ }
+ return -1;
+}
+
Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, String &r_err_str) {
bool string_name = false;
@@ -469,8 +480,19 @@ Error VariantParser::_parse_construct(Stream *p_stream, Vector<T> &r_construct,
if (first && token.type == TK_PARENTHESIS_CLOSE) {
break;
} else if (token.type != TK_NUMBER) {
- r_err_str = "Expected float in constructor";
- return ERR_PARSE_ERROR;
+ bool valid = false;
+ if (token.type == TK_IDENTIFIER) {
+ double real = stor_fix(token.value);
+ if (real != -1) {
+ token.type = TK_NUMBER;
+ token.value = real;
+ valid = true;
+ }
+ }
+ if (!valid) {
+ r_err_str = "Expected float in constructor";
+ return ERR_PARSE_ERROR;
+ }
}
r_construct.push_back(token.value);
@@ -507,6 +529,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
value = Variant();
} else if (id == "inf") {
value = INFINITY;
+ } else if (id == "inf_neg") {
+ value = -INFINITY;
} else if (id == "nan") {
value = NAN;
} else if (id == "Vector2") {
@@ -1401,11 +1425,19 @@ Error VariantParser::parse(Stream *p_stream, Variant &r_ret, String &r_err_str,
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////
-static String rtosfix(double p_value) {
+static String rtos_fix(double p_value) {
if (p_value == 0.0) {
return "0"; //avoid negative zero (-0) being written, which may annoy git, svn, etc. for changes when they don't exist.
+ } else if (isnan(p_value)) {
+ return "nan";
+ } else if (isinf(p_value)) {
+ if (p_value > 0) {
+ return "inf";
+ } else {
+ return "inf_neg";
+ }
} else {
return rtoss(p_value);
}
@@ -1423,8 +1455,8 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
p_store_string_func(p_store_string_ud, itos(p_variant.operator int64_t()));
} break;
case Variant::FLOAT: {
- String s = rtosfix(p_variant.operator double());
- if (s != "inf" && s != "nan") {
+ String s = rtos_fix(p_variant.operator double());
+ if (s != "inf" && s != "inf_neg" && s != "nan") {
if (s.find(".") == -1 && s.find("e") == -1) {
s += ".0";
}
@@ -1439,7 +1471,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
} break;
case Variant::VECTOR2: {
Vector2 v = p_variant;
- p_store_string_func(p_store_string_ud, "Vector2(" + rtosfix(v.x) + ", " + rtosfix(v.y) + ")");
+ p_store_string_func(p_store_string_ud, "Vector2(" + rtos_fix(v.x) + ", " + rtos_fix(v.y) + ")");
} break;
case Variant::VECTOR2I: {
Vector2i v = p_variant;
@@ -1447,7 +1479,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
} break;
case Variant::RECT2: {
Rect2 aabb = p_variant;
- p_store_string_func(p_store_string_ud, "Rect2(" + rtosfix(aabb.position.x) + ", " + rtosfix(aabb.position.y) + ", " + rtosfix(aabb.size.x) + ", " + rtosfix(aabb.size.y) + ")");
+ p_store_string_func(p_store_string_ud, "Rect2(" + rtos_fix(aabb.position.x) + ", " + rtos_fix(aabb.position.y) + ", " + rtos_fix(aabb.size.x) + ", " + rtos_fix(aabb.size.y) + ")");
} break;
case Variant::RECT2I: {
@@ -1457,7 +1489,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
} break;
case Variant::VECTOR3: {
Vector3 v = p_variant;
- p_store_string_func(p_store_string_ud, "Vector3(" + rtosfix(v.x) + ", " + rtosfix(v.y) + ", " + rtosfix(v.z) + ")");
+ p_store_string_func(p_store_string_ud, "Vector3(" + rtos_fix(v.x) + ", " + rtos_fix(v.y) + ", " + rtos_fix(v.z) + ")");
} break;
case Variant::VECTOR3I: {
Vector3i v = p_variant;
@@ -1465,17 +1497,17 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
} break;
case Variant::PLANE: {
Plane p = p_variant;
- p_store_string_func(p_store_string_ud, "Plane(" + rtosfix(p.normal.x) + ", " + rtosfix(p.normal.y) + ", " + rtosfix(p.normal.z) + ", " + rtosfix(p.d) + ")");
+ p_store_string_func(p_store_string_ud, "Plane(" + rtos_fix(p.normal.x) + ", " + rtos_fix(p.normal.y) + ", " + rtos_fix(p.normal.z) + ", " + rtos_fix(p.d) + ")");
} break;
case Variant::AABB: {
AABB aabb = p_variant;
- p_store_string_func(p_store_string_ud, "AABB(" + rtosfix(aabb.position.x) + ", " + rtosfix(aabb.position.y) + ", " + rtosfix(aabb.position.z) + ", " + rtosfix(aabb.size.x) + ", " + rtosfix(aabb.size.y) + ", " + rtosfix(aabb.size.z) + ")");
+ p_store_string_func(p_store_string_ud, "AABB(" + rtos_fix(aabb.position.x) + ", " + rtos_fix(aabb.position.y) + ", " + rtos_fix(aabb.position.z) + ", " + rtos_fix(aabb.size.x) + ", " + rtos_fix(aabb.size.y) + ", " + rtos_fix(aabb.size.z) + ")");
} break;
case Variant::QUATERNION: {
Quaternion quaternion = p_variant;
- p_store_string_func(p_store_string_ud, "Quaternion(" + rtosfix(quaternion.x) + ", " + rtosfix(quaternion.y) + ", " + rtosfix(quaternion.z) + ", " + rtosfix(quaternion.w) + ")");
+ p_store_string_func(p_store_string_ud, "Quaternion(" + rtos_fix(quaternion.x) + ", " + rtos_fix(quaternion.y) + ", " + rtos_fix(quaternion.z) + ", " + rtos_fix(quaternion.w) + ")");
} break;
case Variant::TRANSFORM2D: {
@@ -1486,7 +1518,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
if (i != 0 || j != 0) {
s += ", ";
}
- s += rtosfix(m3.elements[i][j]);
+ s += rtos_fix(m3.elements[i][j]);
}
}
@@ -1501,7 +1533,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
if (i != 0 || j != 0) {
s += ", ";
}
- s += rtosfix(m3.elements[i][j]);
+ s += rtos_fix(m3.elements[i][j]);
}
}
@@ -1517,11 +1549,11 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
if (i != 0 || j != 0) {
s += ", ";
}
- s += rtosfix(m3.elements[i][j]);
+ s += rtos_fix(m3.elements[i][j]);
}
}
- s = s + ", " + rtosfix(t.origin.x) + ", " + rtosfix(t.origin.y) + ", " + rtosfix(t.origin.z);
+ s = s + ", " + rtos_fix(t.origin.x) + ", " + rtos_fix(t.origin.y) + ", " + rtos_fix(t.origin.z);
p_store_string_func(p_store_string_ud, s + ")");
} break;
@@ -1529,7 +1561,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
// misc types
case Variant::COLOR: {
Color c = p_variant;
- p_store_string_func(p_store_string_ud, "Color(" + rtosfix(c.r) + ", " + rtosfix(c.g) + ", " + rtosfix(c.b) + ", " + rtosfix(c.a) + ")");
+ p_store_string_func(p_store_string_ud, "Color(" + rtos_fix(c.r) + ", " + rtos_fix(c.g) + ", " + rtos_fix(c.b) + ", " + rtos_fix(c.a) + ")");
} break;
case Variant::STRING_NAME: {
@@ -1707,7 +1739,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
if (i > 0) {
p_store_string_func(p_store_string_ud, ", ");
}
- p_store_string_func(p_store_string_ud, rtosfix(ptr[i]));
+ p_store_string_func(p_store_string_ud, rtos_fix(ptr[i]));
}
p_store_string_func(p_store_string_ud, ")");
@@ -1723,7 +1755,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
if (i > 0) {
p_store_string_func(p_store_string_ud, ", ");
}
- p_store_string_func(p_store_string_ud, rtosfix(ptr[i]));
+ p_store_string_func(p_store_string_ud, rtos_fix(ptr[i]));
}
p_store_string_func(p_store_string_ud, ")");
@@ -1759,7 +1791,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
if (i > 0) {
p_store_string_func(p_store_string_ud, ", ");
}
- p_store_string_func(p_store_string_ud, rtosfix(ptr[i].x) + ", " + rtosfix(ptr[i].y));
+ p_store_string_func(p_store_string_ud, rtos_fix(ptr[i].x) + ", " + rtos_fix(ptr[i].y));
}
p_store_string_func(p_store_string_ud, ")");
@@ -1775,7 +1807,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
if (i > 0) {
p_store_string_func(p_store_string_ud, ", ");
}
- p_store_string_func(p_store_string_ud, rtosfix(ptr[i].x) + ", " + rtosfix(ptr[i].y) + ", " + rtosfix(ptr[i].z));
+ p_store_string_func(p_store_string_ud, rtos_fix(ptr[i].x) + ", " + rtos_fix(ptr[i].y) + ", " + rtos_fix(ptr[i].z));
}
p_store_string_func(p_store_string_ud, ")");
@@ -1792,7 +1824,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
p_store_string_func(p_store_string_ud, ", ");
}
- p_store_string_func(p_store_string_ud, rtosfix(ptr[i].r) + ", " + rtosfix(ptr[i].g) + ", " + rtosfix(ptr[i].b) + ", " + rtosfix(ptr[i].a));
+ p_store_string_func(p_store_string_ud, rtos_fix(ptr[i].r) + ", " + rtos_fix(ptr[i].g) + ", " + rtos_fix(ptr[i].b) + ", " + rtos_fix(ptr[i].a));
}
p_store_string_func(p_store_string_ud, ")");
diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp
index 3bba68d75e..4abb51ca7c 100644
--- a/core/variant/variant_setget.cpp
+++ b/core/variant/variant_setget.cpp
@@ -239,7 +239,8 @@ void Variant::set_named(const StringName &p_member, const Variant &p_value, bool
*v = p_value;
r_valid = true;
} else {
- r_valid = false;
+ VariantGetInternalPtr<Dictionary>::get_ptr(this)->operator[](p_member) = p_value;
+ r_valid = true;
}
} else {
diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp
index 55c1376031..666b582e39 100644
--- a/core/variant/variant_utility.cpp
+++ b/core/variant/variant_utility.cpp
@@ -1333,6 +1333,28 @@ Variant::UtilityFunctionType Variant::get_utility_function_type(const StringName
return bfi->type;
}
+MethodInfo Variant::get_utility_function_info(const StringName &p_name) {
+ MethodInfo info;
+ const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
+ if (bfi) {
+ info.name = p_name;
+ if (bfi->returns_value && bfi->return_type == Variant::NIL) {
+ info.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
+ }
+ info.return_val.type = bfi->return_type;
+ if (bfi->is_vararg) {
+ info.flags |= METHOD_FLAG_VARARG;
+ }
+ for (int i = 0; i < bfi->argnames.size(); ++i) {
+ PropertyInfo arg;
+ arg.type = bfi->get_arg_type(i);
+ arg.name = bfi->argnames[i];
+ info.arguments.push_back(arg);
+ }
+ }
+ return info;
+}
+
int Variant::get_utility_function_argument_count(const StringName &p_name) {
const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
if (!bfi) {