summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/bind/core_bind.cpp147
-rw-r--r--core/bind/core_bind.h2
-rw-r--r--core/class_db.cpp42
-rw-r--r--core/compressed_translation.cpp2
-rw-r--r--core/cowdata.h1
-rw-r--r--core/crypto/crypto.cpp2
-rw-r--r--core/engine.cpp2
-rw-r--r--core/hash_map.h3
-rw-r--r--core/image.cpp40
-rw-r--r--core/image.h2
-rw-r--r--core/input_map.cpp20
-rw-r--r--core/io/config_file.cpp10
-rw-r--r--core/io/config_file.h1
-rw-r--r--core/io/file_access_compressed.cpp26
-rw-r--r--core/io/file_access_encrypted.cpp12
-rw-r--r--core/io/file_access_memory.cpp2
-rw-r--r--core/io/file_access_network.cpp10
-rw-r--r--core/io/file_access_pack.cpp31
-rw-r--r--core/io/file_access_pack.h8
-rw-r--r--core/io/file_access_zip.cpp10
-rw-r--r--core/io/file_access_zip.h2
-rw-r--r--core/io/image_loader.cpp4
-rw-r--r--core/io/ip.cpp2
-rw-r--r--core/io/ip_address.cpp2
-rw-r--r--core/io/marshalls.cpp6
-rw-r--r--core/io/multiplayer_api.cpp3
-rw-r--r--core/io/packet_peer.cpp6
-rw-r--r--core/io/pck_packer.cpp2
-rw-r--r--core/io/resource_format_binary.cpp24
-rw-r--r--core/io/resource_loader.cpp2
-rw-r--r--core/io/resource_saver.cpp4
-rw-r--r--core/io/stream_peer.cpp2
-rw-r--r--core/io/stream_peer_tcp.cpp11
-rw-r--r--core/io/translation_loader_po.cpp2
-rw-r--r--core/io/xml_parser.cpp2
-rw-r--r--core/list.h1
-rw-r--r--core/map.h1
-rw-r--r--core/math/a_star.cpp12
-rw-r--r--core/math/a_star.h4
-rw-r--r--core/math/basis.cpp2
-rw-r--r--core/math/basis.h4
-rw-r--r--core/math/geometry.cpp5
-rw-r--r--core/math/math_funcs.cpp2
-rw-r--r--core/math/plane.cpp2
-rw-r--r--core/math/rect2.h4
-rw-r--r--core/math/vector3.cpp15
-rw-r--r--core/math/vector3.h22
-rw-r--r--core/message_queue.cpp2
-rw-r--r--core/node_path.cpp4
-rw-r--r--core/oa_hash_map.h47
-rw-r--r--core/object.cpp6
-rw-r--r--core/os/dir_access.cpp21
-rw-r--r--core/os/file_access.cpp10
-rw-r--r--core/os/main_loop.cpp2
-rw-r--r--core/os/memory.h1
-rw-r--r--core/os/os.cpp2
-rw-r--r--core/os/os.h2
-rw-r--r--core/packed_data_container.cpp2
-rw-r--r--core/pool_vector.h4
-rw-r--r--core/project_settings.cpp28
-rw-r--r--core/project_settings.h2
-rw-r--r--core/reference.cpp18
-rw-r--r--core/reference.h2
-rw-r--r--core/resource.cpp44
-rw-r--r--core/resource.h8
-rw-r--r--core/safe_refcount.h9
-rw-r--r--core/self_list.h1
-rw-r--r--core/sort_array.h1
-rw-r--r--core/string_builder.cpp3
-rw-r--r--core/typedefs.h1
-rw-r--r--core/ustring.cpp6
-rw-r--r--core/ustring.h2
-rw-r--r--core/variant.cpp2
-rw-r--r--core/variant_call.cpp35
-rw-r--r--core/vmap.h3
75 files changed, 430 insertions, 359 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 5161f8bab2..1d451b2982 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -145,13 +145,13 @@ _ResourceLoader::_ResourceLoader() {
}
Error _ResourceSaver::save(const String &p_path, const RES &p_resource, SaverFlags p_flags) {
- ERR_FAIL_COND_V_MSG(p_resource.is_null(), ERR_INVALID_PARAMETER, "Can't save empty resource to path: " + String(p_path) + ".");
+ ERR_FAIL_COND_V_MSG(p_resource.is_null(), ERR_INVALID_PARAMETER, "Can't save empty resource to path '" + String(p_path) + "'.");
return ResourceSaver::save(p_path, p_resource, p_flags);
}
PoolVector<String> _ResourceSaver::get_recognized_extensions(const RES &p_resource) {
- ERR_FAIL_COND_V(p_resource.is_null(), PoolVector<String>());
+ ERR_FAIL_COND_V_MSG(p_resource.is_null(), PoolVector<String>(), "It's not a reference to a valid Resource object.");
List<String> exts;
ResourceSaver::get_recognized_extensions(p_resource, &exts);
PoolVector<String> ret;
@@ -481,15 +481,18 @@ Error _OS::shell_open(String p_uri) {
int _OS::execute(const String &p_path, const Vector<String> &p_arguments, bool p_blocking, Array p_output, bool p_read_stderr) {
OS::ProcessID pid = -2;
+ int exitcode = 0;
List<String> args;
for (int i = 0; i < p_arguments.size(); i++)
args.push_back(p_arguments[i]);
String pipe;
- Error err = OS::get_singleton()->execute(p_path, args, p_blocking, &pid, &pipe, NULL, p_read_stderr);
+ Error err = OS::get_singleton()->execute(p_path, args, p_blocking, &pid, &pipe, &exitcode, p_read_stderr);
p_output.clear();
p_output.push_back(pipe);
if (err != OK)
return -1;
+ else if (p_blocking)
+ return exitcode;
else
return pid;
}
@@ -755,7 +758,7 @@ int64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const {
ERR_FAIL_COND_V_MSG(month > 12 || month == 0, 0, "Invalid month value of: " + itos(month) + ".");
// Do this check after month is tested as valid
- ERR_FAIL_COND_V_MSG(day > MONTH_DAYS_TABLE[LEAPYEAR(year)][month - 1] || day == 0, 0, "Invalid day value of: " + itos(day) + " which is larger than " + itos(MONTH_DAYS_TABLE[LEAPYEAR(year)][month - 1]) + " or 0.");
+ ERR_FAIL_COND_V_MSG(day > MONTH_DAYS_TABLE[LEAPYEAR(year)][month - 1] || day == 0, 0, "Invalid day value of '" + itos(day) + "' which is larger than '" + itos(MONTH_DAYS_TABLE[LEAPYEAR(year)][month - 1]) + "' or 0.");
// Calculate all the seconds from months past in this year
uint64_t SECONDS_FROM_MONTHS_PAST_THIS_YEAR = DAYS_PAST_THIS_YEAR_TABLE[LEAPYEAR(year)][month - 1] * SECONDS_PER_DAY;
@@ -1133,6 +1136,16 @@ bool _OS::request_permission(const String &p_name) {
return OS::get_singleton()->request_permission(p_name);
}
+bool _OS::request_permissions() {
+
+ return OS::get_singleton()->request_permissions();
+}
+
+Vector<String> _OS::get_granted_permissions() const {
+
+ return OS::get_singleton()->get_granted_permissions();
+}
+
_OS *_OS::singleton = NULL;
void _OS::_bind_methods() {
@@ -1316,6 +1329,8 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_power_percent_left"), &_OS::get_power_percent_left);
ClassDB::bind_method(D_METHOD("request_permission", "name"), &_OS::request_permission);
+ ClassDB::bind_method(D_METHOD("request_permissions"), &_OS::request_permissions);
+ ClassDB::bind_method(D_METHOD("get_granted_permissions"), &_OS::get_granted_permissions);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "clipboard"), "set_clipboard", "get_clipboard");
ADD_PROPERTY(PropertyInfo(Variant::INT, "current_screen"), "set_current_screen", "get_current_screen");
@@ -1866,92 +1881,92 @@ bool _File::is_open() const {
}
String _File::get_path() const {
- ERR_FAIL_COND_V(!f, "");
+ ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use.");
return f->get_path();
}
String _File::get_path_absolute() const {
- ERR_FAIL_COND_V(!f, "");
+ ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use.");
return f->get_path_absolute();
}
void _File::seek(int64_t p_position) {
- ERR_FAIL_COND(!f);
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->seek(p_position);
}
void _File::seek_end(int64_t p_position) {
- ERR_FAIL_COND(!f);
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->seek_end(p_position);
}
int64_t _File::get_position() const {
- ERR_FAIL_COND_V(!f, 0);
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
return f->get_position();
}
int64_t _File::get_len() const {
- ERR_FAIL_COND_V(!f, 0);
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
return f->get_len();
}
bool _File::eof_reached() const {
- ERR_FAIL_COND_V(!f, false);
+ ERR_FAIL_COND_V_MSG(!f, false, "File must be opened before use.");
return f->eof_reached();
}
uint8_t _File::get_8() const {
- ERR_FAIL_COND_V(!f, 0);
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
return f->get_8();
}
uint16_t _File::get_16() const {
- ERR_FAIL_COND_V(!f, 0);
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
return f->get_16();
}
uint32_t _File::get_32() const {
- ERR_FAIL_COND_V(!f, 0);
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
return f->get_32();
}
uint64_t _File::get_64() const {
- ERR_FAIL_COND_V(!f, 0);
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
return f->get_64();
}
float _File::get_float() const {
- ERR_FAIL_COND_V(!f, 0);
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
return f->get_float();
}
double _File::get_double() const {
- ERR_FAIL_COND_V(!f, 0);
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
return f->get_double();
}
real_t _File::get_real() const {
- ERR_FAIL_COND_V(!f, 0);
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
return f->get_real();
}
PoolVector<uint8_t> _File::get_buffer(int p_length) const {
PoolVector<uint8_t> data;
- ERR_FAIL_COND_V(!f, data);
+ ERR_FAIL_COND_V_MSG(!f, data, "File must be opened before use.");
- ERR_FAIL_COND_V(p_length < 0, data);
+ ERR_FAIL_COND_V_MSG(p_length < 0, data, "Length of buffer cannot be smaller than 0.");
if (p_length == 0)
return data;
Error err = data.resize(p_length);
- ERR_FAIL_COND_V(err != OK, data);
+ ERR_FAIL_COND_V_MSG(err != OK, data, "Can't resize data to " + itos(p_length) + " elements.");
PoolVector<uint8_t>::Write w = data.write();
int len = f->get_buffer(&w[0], p_length);
@@ -1967,7 +1982,7 @@ PoolVector<uint8_t> _File::get_buffer(int p_length) const {
String _File::get_as_text() const {
- ERR_FAIL_COND_V(!f, String());
+ ERR_FAIL_COND_V_MSG(!f, String(), "File must be opened before use.");
String text;
size_t original_pos = f->get_position();
@@ -1997,12 +2012,12 @@ String _File::get_sha256(const String &p_path) const {
String _File::get_line() const {
- ERR_FAIL_COND_V(!f, String());
+ ERR_FAIL_COND_V_MSG(!f, String(), "File must be opened before use.");
return f->get_line();
}
Vector<String> _File::get_csv_line(const String &p_delim) const {
- ERR_FAIL_COND_V(!f, Vector<String>());
+ ERR_FAIL_COND_V_MSG(!f, Vector<String>(), "File must be opened before use.");
return f->get_csv_line(p_delim);
}
@@ -2031,83 +2046,83 @@ Error _File::get_error() const {
void _File::store_8(uint8_t p_dest) {
- ERR_FAIL_COND(!f);
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->store_8(p_dest);
}
void _File::store_16(uint16_t p_dest) {
- ERR_FAIL_COND(!f);
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->store_16(p_dest);
}
void _File::store_32(uint32_t p_dest) {
- ERR_FAIL_COND(!f);
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->store_32(p_dest);
}
void _File::store_64(uint64_t p_dest) {
- ERR_FAIL_COND(!f);
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->store_64(p_dest);
}
void _File::store_float(float p_dest) {
- ERR_FAIL_COND(!f);
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->store_float(p_dest);
}
void _File::store_double(double p_dest) {
- ERR_FAIL_COND(!f);
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->store_double(p_dest);
}
void _File::store_real(real_t p_real) {
- ERR_FAIL_COND(!f);
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->store_real(p_real);
}
void _File::store_string(const String &p_string) {
- ERR_FAIL_COND(!f);
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->store_string(p_string);
}
void _File::store_pascal_string(const String &p_string) {
- ERR_FAIL_COND(!f);
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->store_pascal_string(p_string);
};
String _File::get_pascal_string() {
- ERR_FAIL_COND_V(!f, "");
+ ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use.");
return f->get_pascal_string();
};
void _File::store_line(const String &p_string) {
- ERR_FAIL_COND(!f);
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->store_line(p_string);
}
void _File::store_csv_line(const Vector<String> &p_values, const String &p_delim) {
- ERR_FAIL_COND(!f);
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->store_csv_line(p_values, p_delim);
}
void _File::store_buffer(const PoolVector<uint8_t> &p_buffer) {
- ERR_FAIL_COND(!f);
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
int len = p_buffer.size();
if (len == 0)
@@ -2125,17 +2140,17 @@ bool _File::file_exists(const String &p_name) const {
void _File::store_var(const Variant &p_var, bool p_full_objects) {
- ERR_FAIL_COND(!f);
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
int len;
Error err = encode_variant(p_var, NULL, len, p_full_objects);
- ERR_FAIL_COND(err != OK);
+ ERR_FAIL_COND_MSG(err != OK, "Error when trying to encode Variant.");
PoolVector<uint8_t> buff;
buff.resize(len);
PoolVector<uint8_t>::Write w = buff.write();
err = encode_variant(p_var, &w[0], len, p_full_objects);
- ERR_FAIL_COND(err != OK);
+ ERR_FAIL_COND_MSG(err != OK, "Error when trying to encode Variant.");
w.release();
store_32(len);
@@ -2144,7 +2159,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(!f, Variant());
+ ERR_FAIL_COND_V_MSG(!f, Variant(), "File must be opened before use.");
uint32_t len = get_32();
PoolVector<uint8_t> buff = get_buffer(len);
ERR_FAIL_COND_V((uint32_t)buff.size() != len, Variant());
@@ -2153,7 +2168,7 @@ Variant _File::get_var(bool p_allow_objects) const {
Variant v;
Error err = decode_variant(v, &r[0], len, NULL, p_allow_objects);
- ERR_FAIL_COND_V(err != OK, Variant());
+ ERR_FAIL_COND_V_MSG(err != OK, Variant(), "Error when trying to encode Variant.");
return v;
}
@@ -2258,7 +2273,7 @@ Error _Directory::open(const String &p_path) {
Error _Directory::list_dir_begin(bool p_skip_navigational, bool p_skip_hidden) {
- ERR_FAIL_COND_V(!d, ERR_UNCONFIGURED);
+ ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory must be opened before use.");
_list_skip_navigational = p_skip_navigational;
_list_skip_hidden = p_skip_hidden;
@@ -2268,7 +2283,7 @@ Error _Directory::list_dir_begin(bool p_skip_navigational, bool p_skip_hidden) {
String _Directory::get_next() {
- ERR_FAIL_COND_V(!d, "");
+ ERR_FAIL_COND_V_MSG(!d, "", "Directory must be opened before use.");
String next = d->get_next();
while (next != "" && ((_list_skip_navigational && (next == "." || next == "..")) || (_list_skip_hidden && d->current_is_hidden()))) {
@@ -2279,44 +2294,44 @@ String _Directory::get_next() {
}
bool _Directory::current_is_dir() const {
- ERR_FAIL_COND_V(!d, false);
+ ERR_FAIL_COND_V_MSG(!d, false, "Directory must be opened before use.");
return d->current_is_dir();
}
void _Directory::list_dir_end() {
- ERR_FAIL_COND(!d);
+ ERR_FAIL_COND_MSG(!d, "Directory must be opened before use.");
d->list_dir_end();
}
int _Directory::get_drive_count() {
- ERR_FAIL_COND_V(!d, 0);
+ ERR_FAIL_COND_V_MSG(!d, 0, "Directory must be opened before use.");
return d->get_drive_count();
}
String _Directory::get_drive(int p_drive) {
- ERR_FAIL_COND_V(!d, "");
+ ERR_FAIL_COND_V_MSG(!d, "", "Directory must be opened before use.");
return d->get_drive(p_drive);
}
int _Directory::get_current_drive() {
- ERR_FAIL_COND_V(!d, 0);
+ ERR_FAIL_COND_V_MSG(!d, 0, "Directory must be opened before use.");
return d->get_current_drive();
}
Error _Directory::change_dir(String p_dir) {
- ERR_FAIL_COND_V(!d, ERR_UNCONFIGURED);
+ ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory must be opened before use.");
return d->change_dir(p_dir);
}
String _Directory::get_current_dir() {
- ERR_FAIL_COND_V(!d, "");
+ ERR_FAIL_COND_V_MSG(!d, "", "Directory must be opened before use.");
return d->get_current_dir();
}
Error _Directory::make_dir(String p_dir) {
- ERR_FAIL_COND_V(!d, ERR_UNCONFIGURED);
+ ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory must be opened before use.");
if (!p_dir.is_rel_path()) {
DirAccess *d = DirAccess::create_for_path(p_dir);
Error err = d->make_dir(p_dir);
@@ -2327,7 +2342,7 @@ Error _Directory::make_dir(String p_dir) {
}
Error _Directory::make_dir_recursive(String p_dir) {
- ERR_FAIL_COND_V(!d, ERR_UNCONFIGURED);
+ ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory must be opened before use.");
if (!p_dir.is_rel_path()) {
DirAccess *d = DirAccess::create_for_path(p_dir);
Error err = d->make_dir_recursive(p_dir);
@@ -2339,7 +2354,7 @@ Error _Directory::make_dir_recursive(String p_dir) {
bool _Directory::file_exists(String p_file) {
- ERR_FAIL_COND_V(!d, false);
+ ERR_FAIL_COND_V_MSG(!d, false, "Directory must be opened before use.");
if (!p_file.is_rel_path()) {
return FileAccess::exists(p_file);
@@ -2349,7 +2364,7 @@ bool _Directory::file_exists(String p_file) {
}
bool _Directory::dir_exists(String p_dir) {
- ERR_FAIL_COND_V(!d, false);
+ ERR_FAIL_COND_V_MSG(!d, false, "Directory must be opened before use.");
if (!p_dir.is_rel_path()) {
DirAccess *d = DirAccess::create_for_path(p_dir);
@@ -2364,18 +2379,18 @@ bool _Directory::dir_exists(String p_dir) {
int _Directory::get_space_left() {
- ERR_FAIL_COND_V(!d, 0);
+ ERR_FAIL_COND_V_MSG(!d, 0, "Directory must be opened before use.");
return d->get_space_left() / 1024 * 1024; //return value in megabytes, given binding is int
}
Error _Directory::copy(String p_from, String p_to) {
- ERR_FAIL_COND_V(!d, ERR_UNCONFIGURED);
+ ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory must be opened before use.");
return d->copy(p_from, p_to);
}
Error _Directory::rename(String p_from, String p_to) {
- ERR_FAIL_COND_V(!d, ERR_UNCONFIGURED);
+ ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory must be opened before use.");
if (!p_from.is_rel_path()) {
DirAccess *d = DirAccess::create_for_path(p_from);
Error err = d->rename(p_from, p_to);
@@ -2387,7 +2402,7 @@ Error _Directory::rename(String p_from, String p_to) {
}
Error _Directory::remove(String p_name) {
- ERR_FAIL_COND_V(!d, ERR_UNCONFIGURED);
+ ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory must be opened before use.");
if (!p_name.is_rel_path()) {
DirAccess *d = DirAccess::create_for_path(p_name);
Error err = d->remove(p_name);
@@ -2442,14 +2457,14 @@ String _Marshalls::variant_to_base64(const Variant &p_var, bool p_full_objects)
int len;
Error err = encode_variant(p_var, NULL, len, p_full_objects);
- ERR_FAIL_COND_V(err != OK, "");
+ ERR_FAIL_COND_V_MSG(err != OK, "", "Error when trying to encode Variant.");
PoolVector<uint8_t> buff;
buff.resize(len);
PoolVector<uint8_t>::Write w = buff.write();
err = encode_variant(p_var, &w[0], len, p_full_objects);
- ERR_FAIL_COND_V(err != OK, "");
+ ERR_FAIL_COND_V_MSG(err != OK, "", "Error when trying to encode Variant.");
String ret = CryptoCore::b64_encode_str(&w[0], len);
ERR_FAIL_COND_V(ret == "", ret);
@@ -2471,7 +2486,7 @@ Variant _Marshalls::base64_to_variant(const String &p_str, bool p_allow_objects)
Variant v;
Error err = decode_variant(v, &w[0], len, NULL, p_allow_objects);
- ERR_FAIL_COND_V(err != OK, Variant());
+ ERR_FAIL_COND_V_MSG(err != OK, Variant(), "Error when trying to decode Variant.");
return v;
};
@@ -2638,13 +2653,13 @@ void _Thread::_start_func(void *ud) {
}
}
- ERR_FAIL_MSG("Could not call function '" + t->target_method.operator String() + "'' starting thread ID: " + t->get_id() + " Reason: " + reason + ".");
+ ERR_FAIL_MSG("Could not call function '" + t->target_method.operator String() + "' to start thread " + t->get_id() + ": " + reason + ".");
}
}
Error _Thread::start(Object *p_instance, const StringName &p_method, const Variant &p_userdata, Priority p_priority) {
- ERR_FAIL_COND_V(active, ERR_ALREADY_IN_USE);
+ ERR_FAIL_COND_V_MSG(active, ERR_ALREADY_IN_USE, "Thread already started.");
ERR_FAIL_COND_V(!p_instance, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(p_method == StringName(), ERR_INVALID_PARAMETER);
ERR_FAIL_INDEX_V(p_priority, PRIORITY_MAX, ERR_INVALID_PARAMETER);
@@ -2685,8 +2700,8 @@ bool _Thread::is_active() const {
}
Variant _Thread::wait_to_finish() {
- ERR_FAIL_COND_V(!thread, Variant());
- ERR_FAIL_COND_V(!active, Variant());
+ ERR_FAIL_COND_V_MSG(!thread, Variant(), "Thread must exist to wait for its completion.");
+ ERR_FAIL_COND_V_MSG(!active, Variant(), "Thread must be active to wait for its completion.");
Thread::wait_to_finish(thread);
Variant r = ret;
active = false;
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 693b85710a..1a4fd1d5cb 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -349,6 +349,8 @@ public:
bool has_feature(const String &p_feature) const;
bool request_permission(const String &p_name);
+ bool request_permissions();
+ Vector<String> get_granted_permissions() const;
static _OS *get_singleton() { return singleton; }
diff --git a/core/class_db.cpp b/core/class_db.cpp
index 3ad59bc309..f52937bdca 100644
--- a/core/class_db.cpp
+++ b/core/class_db.cpp
@@ -340,7 +340,7 @@ StringName ClassDB::get_parent_class(const StringName &p_class) {
OBJTYPE_RLOCK;
ClassInfo *ti = classes.getptr(p_class);
- ERR_FAIL_COND_V(!ti, StringName());
+ ERR_FAIL_COND_V_MSG(!ti, StringName(), "Cannot get class '" + String(p_class) + "'.");
return ti->inherits;
}
@@ -350,7 +350,7 @@ ClassDB::APIType ClassDB::get_api_type(const StringName &p_class) {
ClassInfo *ti = classes.getptr(p_class);
- ERR_FAIL_COND_V(!ti, API_NONE);
+ ERR_FAIL_COND_V_MSG(!ti, API_NONE, "Cannot get class '" + String(p_class) + "'.");
return ti->api;
}
@@ -375,7 +375,7 @@ uint64_t ClassDB::get_api_hash(APIType p_api) {
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
ClassInfo *t = classes.getptr(E->get());
- ERR_FAIL_COND_V(!t, 0);
+ ERR_FAIL_COND_V_MSG(!t, 0, "Cannot get class '" + String(E->get()) + "'.");
if (t->api != p_api || !t->exposed)
continue;
hash = hash_djb2_one_64(t->name.hash(), hash);
@@ -528,8 +528,8 @@ Object *ClassDB::instance(const StringName &p_class) {
ti = classes.getptr(compat_classes[p_class]);
}
}
- ERR_FAIL_COND_V(!ti, NULL);
- ERR_FAIL_COND_V(ti->disabled, NULL);
+ ERR_FAIL_COND_V_MSG(!ti, NULL, "Cannot get class '" + String(p_class) + "'.");
+ ERR_FAIL_COND_V_MSG(ti->disabled, NULL, "Class '" + String(p_class) + "' is disabled.");
ERR_FAIL_COND_V(!ti->creation_func, NULL);
}
#ifdef TOOLS_ENABLED
@@ -545,7 +545,7 @@ bool ClassDB::can_instance(const StringName &p_class) {
OBJTYPE_RLOCK;
ClassInfo *ti = classes.getptr(p_class);
- ERR_FAIL_COND_V(!ti, false);
+ ERR_FAIL_COND_V_MSG(!ti, false, "Cannot get class '" + String(p_class) + "'.");
#ifdef TOOLS_ENABLED
if (ti->api == API_EDITOR && !Engine::get_singleton()->is_editor_hint()) {
return false;
@@ -560,7 +560,7 @@ void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherit
const StringName &name = p_class;
- ERR_FAIL_COND(classes.has(name));
+ ERR_FAIL_COND_MSG(classes.has(name), "Class '" + String(p_class) + "' already exists.");
classes[name] = ClassInfo();
ClassInfo &ti = classes[name];
@@ -836,7 +836,7 @@ void ClassDB::add_signal(StringName p_class, const MethodInfo &p_signal) {
#ifdef DEBUG_METHODS_ENABLED
ClassInfo *check = type;
while (check) {
- ERR_FAIL_COND_MSG(check->signal_map.has(sname), "Type " + String(p_class) + " already has signal: " + String(sname) + ".");
+ ERR_FAIL_COND_MSG(check->signal_map.has(sname), "Class '" + String(p_class) + "' already has signal '" + String(sname) + "'.");
check = check->inherits_ptr;
}
#endif
@@ -922,10 +922,10 @@ void ClassDB::add_property(StringName p_class, const PropertyInfo &p_pinfo, cons
mb_set = get_method(p_class, p_setter);
#ifdef DEBUG_METHODS_ENABLED
- ERR_FAIL_COND_MSG(!mb_set, "Invalid setter: " + p_class + "::" + p_setter + " for property: " + p_pinfo.name + ".");
+ ERR_FAIL_COND_MSG(!mb_set, "Invalid setter '" + p_class + "::" + p_setter + "' for property '" + p_pinfo.name + "'.");
int exp_args = 1 + (p_index >= 0 ? 1 : 0);
- ERR_FAIL_COND_MSG(mb_set->get_argument_count() != exp_args, "Invalid function for setter: " + p_class + "::" + p_setter + " for property: " + p_pinfo.name + ".");
+ ERR_FAIL_COND_MSG(mb_set->get_argument_count() != exp_args, "Invalid function for setter '" + p_class + "::" + p_setter + " for property '" + p_pinfo.name + "'.");
#endif
}
@@ -935,15 +935,15 @@ void ClassDB::add_property(StringName p_class, const PropertyInfo &p_pinfo, cons
mb_get = get_method(p_class, p_getter);
#ifdef DEBUG_METHODS_ENABLED
- ERR_FAIL_COND_MSG(!mb_get, "Invalid getter: " + p_class + "::" + p_getter + " for property: " + p_pinfo.name + ".");
+ ERR_FAIL_COND_MSG(!mb_get, "Invalid getter '" + p_class + "::" + p_getter + "' for property '" + p_pinfo.name + "'.");
int exp_args = 0 + (p_index >= 0 ? 1 : 0);
- ERR_FAIL_COND_MSG(mb_get->get_argument_count() != exp_args, "Invalid function for getter: " + p_class + "::" + p_getter + " for property: " + p_pinfo.name + ".");
+ ERR_FAIL_COND_MSG(mb_get->get_argument_count() != exp_args, "Invalid function for getter '" + p_class + "::" + p_getter + "' for property: '" + p_pinfo.name + "'.");
#endif
}
#ifdef DEBUG_METHODS_ENABLED
- ERR_FAIL_COND_MSG(type->property_setget.has(p_pinfo.name), "Object " + p_class + " already has property: " + p_pinfo.name + ".");
+ ERR_FAIL_COND_MSG(type->property_setget.has(p_pinfo.name), "Object '" + p_class + "' already has property '" + p_pinfo.name + "'.");
#endif
OBJTYPE_WLOCK
@@ -1228,20 +1228,20 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const c
ClassInfo *type = classes.getptr(instance_type);
if (!type) {
memdelete(p_bind);
- ERR_FAIL_V_MSG(NULL, "Couldn't bind method '" + mdname + "' for instance: " + instance_type + ".");
+ ERR_FAIL_V_MSG(NULL, "Couldn't bind method '" + mdname + "' for instance '" + instance_type + "'.");
}
if (type->method_map.has(mdname)) {
memdelete(p_bind);
// overloading not supported
- ERR_FAIL_V_MSG(NULL, "Method already bound: " + instance_type + "::" + mdname + ".");
+ ERR_FAIL_V_MSG(NULL, "Method already bound '" + instance_type + "::" + mdname + "'.");
}
#ifdef DEBUG_METHODS_ENABLED
if (method_name.args.size() > p_bind->get_argument_count()) {
memdelete(p_bind);
- ERR_FAIL_V_MSG(NULL, "Method definition provides more arguments than the method actually has: " + instance_type + "::" + mdname + ".");
+ ERR_FAIL_V_MSG(NULL, "Method definition provides more arguments than the method actually has '" + instance_type + "::" + mdname + "'.");
}
p_bind->set_argument_names(method_name.args);
@@ -1265,7 +1265,7 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const c
}
void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_method, bool p_virtual) {
- ERR_FAIL_COND(!classes.has(p_class));
+ ERR_FAIL_COND_MSG(!classes.has(p_class), "Request for nonexistent class '" + p_class + "'.");
OBJTYPE_WLOCK;
@@ -1280,7 +1280,7 @@ void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_
void ClassDB::get_virtual_methods(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance) {
- ERR_FAIL_COND(!classes.has(p_class));
+ ERR_FAIL_COND_MSG(!classes.has(p_class), "Request for nonexistent class '" + p_class + "'.");
#ifdef DEBUG_METHODS_ENABLED
@@ -1304,7 +1304,7 @@ void ClassDB::set_class_enabled(StringName p_class, bool p_enable) {
OBJTYPE_WLOCK;
- ERR_FAIL_COND(!classes.has(p_class));
+ ERR_FAIL_COND_MSG(!classes.has(p_class), "Request for nonexistent class '" + p_class + "'.");
classes[p_class].disabled = !p_enable;
}
@@ -1319,7 +1319,7 @@ bool ClassDB::is_class_enabled(StringName p_class) {
}
}
- ERR_FAIL_COND_V(!ti, false);
+ ERR_FAIL_COND_V_MSG(!ti, false, "Cannot get class '" + String(p_class) + "'.");
return !ti->disabled;
}
@@ -1328,7 +1328,7 @@ bool ClassDB::is_class_exposed(StringName p_class) {
OBJTYPE_RLOCK;
ClassInfo *ti = classes.getptr(p_class);
- ERR_FAIL_COND_V(!ti, false);
+ ERR_FAIL_COND_V_MSG(!ti, false, "Cannot get class '" + String(p_class) + "'.");
return ti->exposed;
}
diff --git a/core/compressed_translation.cpp b/core/compressed_translation.cpp
index f102721470..d927b74897 100644
--- a/core/compressed_translation.cpp
+++ b/core/compressed_translation.cpp
@@ -136,6 +136,8 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) {
bucket_table_size += 2 + b.size() * 4;
}
+ ERR_FAIL_COND(bucket_table_size == 0);
+
hash_table.resize(size);
bucket_table.resize(bucket_table_size);
diff --git a/core/cowdata.h b/core/cowdata.h
index 3e40ad0f4b..c92e20920c 100644
--- a/core/cowdata.h
+++ b/core/cowdata.h
@@ -33,6 +33,7 @@
#include <string.h>
+#include "core/error_macros.h"
#include "core/os/memory.h"
#include "core/safe_refcount.h"
diff --git a/core/crypto/crypto.cpp b/core/crypto/crypto.cpp
index 925a01b36a..83a25da901 100644
--- a/core/crypto/crypto.cpp
+++ b/core/crypto/crypto.cpp
@@ -149,7 +149,7 @@ Error ResourceFormatSaverCrypto::save(const String &p_path, const RES &p_resourc
} else {
ERR_FAIL_V(ERR_INVALID_PARAMETER);
}
- ERR_FAIL_COND_V(err != OK, err);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save Crypto resource to file '" + p_path + "'.");
return OK;
}
diff --git a/core/engine.cpp b/core/engine.cpp
index 937439faaf..b9dc057257 100644
--- a/core/engine.cpp
+++ b/core/engine.cpp
@@ -38,7 +38,7 @@
void Engine::set_iterations_per_second(int p_ips) {
- ERR_FAIL_COND(p_ips <= 0);
+ ERR_FAIL_COND_MSG(p_ips <= 0, "Engine iterations per second must be greater than 0.");
ips = p_ips;
}
int Engine::get_iterations_per_second() const {
diff --git a/core/hash_map.h b/core/hash_map.h
index 81ddc376d0..edc67e7806 100644
--- a/core/hash_map.h
+++ b/core/hash_map.h
@@ -112,7 +112,7 @@ private:
void erase_hash_table() {
- ERR_FAIL_COND(elements);
+ ERR_FAIL_COND_MSG(elements, "Cannot erase hash table if there are still elements inside.");
memdelete_arr(hash_table);
hash_table = 0;
@@ -210,6 +210,7 @@ private:
e->next = hash_table[index];
e->hash = hash;
e->pair.key = p_key;
+ e->pair.data = TData();
hash_table[index] = e;
elements++;
diff --git a/core/image.cpp b/core/image.cpp
index 900efb0eb0..e0b0a1f8be 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -885,10 +885,10 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
bool mipmap_aware = p_interpolation == INTERPOLATE_TRILINEAR /* || p_interpolation == INTERPOLATE_TRICUBIC */;
- ERR_FAIL_COND(p_width <= 0);
- ERR_FAIL_COND(p_height <= 0);
- ERR_FAIL_COND(p_width > MAX_WIDTH);
- ERR_FAIL_COND(p_height > MAX_HEIGHT);
+ ERR_FAIL_COND_MSG(p_width <= 0, "Image width cannot be greater than 0.");
+ ERR_FAIL_COND_MSG(p_height <= 0, "Image height cannot be greater than 0.");
+ ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, "Image width cannot be greater than " + itos(MAX_WIDTH) + ".");
+ ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, "Image height cannot be greater than " + itos(MAX_HEIGHT) + ".");
if (p_width == width && p_height == height)
return;
@@ -1096,12 +1096,12 @@ void Image::crop_from_point(int p_x, int p_y, int p_width, int p_height) {
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot crop in compressed or custom image formats.");
- ERR_FAIL_COND(p_x < 0);
- ERR_FAIL_COND(p_y < 0);
- ERR_FAIL_COND(p_width <= 0);
- ERR_FAIL_COND(p_height <= 0);
- ERR_FAIL_COND(p_x + p_width > MAX_WIDTH);
- ERR_FAIL_COND(p_y + p_height > MAX_HEIGHT);
+ ERR_FAIL_COND_MSG(p_x < 0, "Start x position cannot be smaller than 0.");
+ ERR_FAIL_COND_MSG(p_y < 0, "Start y position cannot be smaller than 0.");
+ ERR_FAIL_COND_MSG(p_width <= 0, "Width of image must be greater than 0.");
+ ERR_FAIL_COND_MSG(p_height <= 0, "Height of image must be greater than 0.");
+ ERR_FAIL_COND_MSG(p_x + p_width > MAX_WIDTH, "End x position cannot be greater than " + itos(MAX_WIDTH) + ".");
+ ERR_FAIL_COND_MSG(p_y + p_height > MAX_HEIGHT, "End y position cannot be greater than " + itos(MAX_HEIGHT) + ".");
/* to save memory, cropping should be done in-place, however, since this function
will most likely either not be used much, or in critical areas, for now it won't, because
@@ -2055,7 +2055,7 @@ Ref<Image> Image::get_rect(const Rect2 &p_area) const {
void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest) {
- ERR_FAIL_COND(p_src.is_null());
+ ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object.");
int dsize = data.size();
int srcdsize = p_src->data.size();
ERR_FAIL_COND(dsize == 0);
@@ -2105,16 +2105,16 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po
void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest) {
- ERR_FAIL_COND(p_src.is_null());
- ERR_FAIL_COND(p_mask.is_null());
+ ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object.");
+ ERR_FAIL_COND_MSG(p_mask.is_null(), "It's not a reference to a valid Image object.");
int dsize = data.size();
int srcdsize = p_src->data.size();
int maskdsize = p_mask->data.size();
ERR_FAIL_COND(dsize == 0);
ERR_FAIL_COND(srcdsize == 0);
ERR_FAIL_COND(maskdsize == 0);
- ERR_FAIL_COND(p_src->width != p_mask->width);
- ERR_FAIL_COND(p_src->height != p_mask->height);
+ ERR_FAIL_COND_MSG(p_src->width != p_mask->width, "Source image width is different from mask width.");
+ ERR_FAIL_COND_MSG(p_src->height != p_mask->height, "Source image height is different from mask height.");
ERR_FAIL_COND(format != p_src->format);
Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).clip(p_src_rect);
@@ -2168,7 +2168,7 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co
void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest) {
- ERR_FAIL_COND(p_src.is_null());
+ ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object.");
int dsize = data.size();
int srcdsize = p_src->data.size();
ERR_FAIL_COND(dsize == 0);
@@ -2218,16 +2218,16 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P
void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest) {
- ERR_FAIL_COND(p_src.is_null());
- ERR_FAIL_COND(p_mask.is_null());
+ ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object.");
+ ERR_FAIL_COND_MSG(p_mask.is_null(), "It's not a reference to a valid Image object.");
int dsize = data.size();
int srcdsize = p_src->data.size();
int maskdsize = p_mask->data.size();
ERR_FAIL_COND(dsize == 0);
ERR_FAIL_COND(srcdsize == 0);
ERR_FAIL_COND(maskdsize == 0);
- ERR_FAIL_COND(p_src->width != p_mask->width);
- ERR_FAIL_COND(p_src->height != p_mask->height);
+ ERR_FAIL_COND_MSG(p_src->width != p_mask->width, "Source image width is different from mask width.");
+ ERR_FAIL_COND_MSG(p_src->height != p_mask->height, "Source image height is different from mask height.");
ERR_FAIL_COND(format != p_src->format);
Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).clip(p_src_rect);
diff --git a/core/image.h b/core/image.h
index f29a30cda0..94ee8a2c33 100644
--- a/core/image.h
+++ b/core/image.h
@@ -356,7 +356,7 @@ public:
void set_pixel(int p_x, int p_y, const Color &p_color);
void copy_internals_from(const Ref<Image> &p_image) {
- ERR_FAIL_COND(p_image.is_null());
+ ERR_FAIL_COND_MSG(p_image.is_null(), "It's not a reference to a valid Image object.");
format = p_image->format;
width = p_image->width;
height = p_image->height;
diff --git a/core/input_map.cpp b/core/input_map.cpp
index 2a8ac435fe..05c75febf2 100644
--- a/core/input_map.cpp
+++ b/core/input_map.cpp
@@ -56,7 +56,7 @@ void InputMap::_bind_methods() {
void InputMap::add_action(const StringName &p_action, float p_deadzone) {
- ERR_FAIL_COND(input_map.has(p_action));
+ ERR_FAIL_COND_MSG(input_map.has(p_action), "InputMap already has action '" + String(p_action) + "'.");
input_map[p_action] = Action();
static int last_id = 1;
input_map[p_action].id = last_id;
@@ -66,7 +66,7 @@ void InputMap::add_action(const StringName &p_action, float p_deadzone) {
void InputMap::erase_action(const StringName &p_action) {
- ERR_FAIL_COND(!input_map.has(p_action));
+ ERR_FAIL_COND_MSG(!input_map.has(p_action), "Request for nonexistent InputMap action '" + String(p_action) + "'.");
input_map.erase(p_action);
}
@@ -126,15 +126,15 @@ bool InputMap::has_action(const StringName &p_action) const {
void InputMap::action_set_deadzone(const StringName &p_action, float p_deadzone) {
- ERR_FAIL_COND(!input_map.has(p_action));
+ ERR_FAIL_COND_MSG(!input_map.has(p_action), "Request for nonexistent InputMap action '" + String(p_action) + "'.");
input_map[p_action].deadzone = p_deadzone;
}
void InputMap::action_add_event(const StringName &p_action, const Ref<InputEvent> &p_event) {
- ERR_FAIL_COND(p_event.is_null());
- ERR_FAIL_COND(!input_map.has(p_action));
+ ERR_FAIL_COND_MSG(p_event.is_null(), "It's not a reference to a valid InputEvent object.");
+ ERR_FAIL_COND_MSG(!input_map.has(p_action), "Request for nonexistent InputMap action '" + String(p_action) + "'.");
if (_find_event(input_map[p_action], p_event))
return; //already gots
@@ -143,13 +143,13 @@ void InputMap::action_add_event(const StringName &p_action, const Ref<InputEvent
bool InputMap::action_has_event(const StringName &p_action, const Ref<InputEvent> &p_event) {
- ERR_FAIL_COND_V(!input_map.has(p_action), false);
+ ERR_FAIL_COND_V_MSG(!input_map.has(p_action), false, "Request for nonexistent InputMap action '" + String(p_action) + "'.");
return (_find_event(input_map[p_action], p_event) != NULL);
}
void InputMap::action_erase_event(const StringName &p_action, const Ref<InputEvent> &p_event) {
- ERR_FAIL_COND(!input_map.has(p_action));
+ ERR_FAIL_COND_MSG(!input_map.has(p_action), "Request for nonexistent InputMap action '" + String(p_action) + "'.");
List<Ref<InputEvent> >::Element *E = _find_event(input_map[p_action], p_event);
if (E)
@@ -158,7 +158,7 @@ void InputMap::action_erase_event(const StringName &p_action, const Ref<InputEve
void InputMap::action_erase_events(const StringName &p_action) {
- ERR_FAIL_COND(!input_map.has(p_action));
+ ERR_FAIL_COND_MSG(!input_map.has(p_action), "Request for nonexistent InputMap action '" + String(p_action) + "'.");
input_map[p_action].inputs.clear();
}
@@ -192,7 +192,7 @@ bool InputMap::event_is_action(const Ref<InputEvent> &p_event, const StringName
bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool *p_pressed, float *p_strength) const {
Map<StringName, Action>::Element *E = input_map.find(p_action);
- ERR_FAIL_COND_V_MSG(!E, false, "Request for nonexistent InputMap action: " + String(p_action) + ".");
+ ERR_FAIL_COND_V_MSG(!E, false, "Request for nonexistent InputMap action '" + String(p_action) + "'.");
Ref<InputEventAction> input_event_action = p_event;
if (input_event_action.is_valid()) {
@@ -333,6 +333,6 @@ void InputMap::load_default() {
InputMap::InputMap() {
- ERR_FAIL_COND(singleton);
+ ERR_FAIL_COND_MSG(singleton, "Singleton in InputMap already exist.");
singleton = this;
}
diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp
index 9063e028be..5684c82d1c 100644
--- a/core/io/config_file.cpp
+++ b/core/io/config_file.cpp
@@ -111,7 +111,7 @@ void ConfigFile::get_sections(List<String> *r_sections) const {
}
void ConfigFile::get_section_keys(const String &p_section, List<String> *r_keys) const {
- ERR_FAIL_COND(!values.has(p_section));
+ ERR_FAIL_COND_MSG(!values.has(p_section), "Cannont get keys from nonexistent section '" + p_section + "'.");
for (OrderedHashMap<String, Variant>::ConstElement E = values[p_section].front(); E; E = E.next()) {
r_keys->push_back(E.key());
@@ -123,6 +123,13 @@ void ConfigFile::erase_section(const String &p_section) {
values.erase(p_section);
}
+void ConfigFile::erase_section_key(const String &p_section, const String &p_key) {
+
+ ERR_FAIL_COND_MSG(!values.has(p_section), "Cannot erase key from nonexistent section '" + p_section + "'.");
+
+ values[p_section].erase(p_key);
+}
+
Error ConfigFile::save(const String &p_path) {
Error err;
@@ -293,6 +300,7 @@ void ConfigFile::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_section_keys", "section"), &ConfigFile::_get_section_keys);
ClassDB::bind_method(D_METHOD("erase_section", "section"), &ConfigFile::erase_section);
+ ClassDB::bind_method(D_METHOD("erase_section_key", "section", "key"), &ConfigFile::erase_section_key);
ClassDB::bind_method(D_METHOD("load", "path"), &ConfigFile::load);
ClassDB::bind_method(D_METHOD("save", "path"), &ConfigFile::save);
diff --git a/core/io/config_file.h b/core/io/config_file.h
index 3ab6fef868..d927779f9c 100644
--- a/core/io/config_file.h
+++ b/core/io/config_file.h
@@ -60,6 +60,7 @@ public:
void get_section_keys(const String &p_section, List<String> *r_keys) const;
void erase_section(const String &p_section);
+ void erase_section_key(const String &p_section, const String &p_key);
Error save(const String &p_path);
Error load(const String &p_path);
diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp
index 102cd9cf6c..a52c6f79c9 100644
--- a/core/io/file_access_compressed.cpp
+++ b/core/io/file_access_compressed.cpp
@@ -195,7 +195,7 @@ bool FileAccessCompressed::is_open() const {
void FileAccessCompressed::seek(size_t p_position) {
- ERR_FAIL_COND(!f);
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
if (writing) {
ERR_FAIL_COND(p_position > write_max);
@@ -227,7 +227,7 @@ void FileAccessCompressed::seek(size_t p_position) {
void FileAccessCompressed::seek_end(int64_t p_position) {
- ERR_FAIL_COND(!f);
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
if (writing) {
seek(write_max + p_position);
@@ -238,7 +238,7 @@ void FileAccessCompressed::seek_end(int64_t p_position) {
}
size_t FileAccessCompressed::get_position() const {
- ERR_FAIL_COND_V(!f, 0);
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
if (writing) {
return write_pos;
@@ -249,7 +249,7 @@ size_t FileAccessCompressed::get_position() const {
}
size_t FileAccessCompressed::get_len() const {
- ERR_FAIL_COND_V(!f, 0);
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
if (writing) {
return write_max;
@@ -260,7 +260,7 @@ size_t FileAccessCompressed::get_len() const {
bool FileAccessCompressed::eof_reached() const {
- ERR_FAIL_COND_V(!f, false);
+ ERR_FAIL_COND_V_MSG(!f, false, "File must be opened before use.");
if (writing) {
return false;
} else {
@@ -270,8 +270,8 @@ bool FileAccessCompressed::eof_reached() const {
uint8_t FileAccessCompressed::get_8() const {
- ERR_FAIL_COND_V(writing, 0);
- ERR_FAIL_COND_V(!f, 0);
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode.");
if (at_end) {
read_eof = true;
@@ -301,8 +301,8 @@ uint8_t FileAccessCompressed::get_8() const {
}
int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) const {
- ERR_FAIL_COND_V(writing, 0);
- ERR_FAIL_COND_V(!f, 0);
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode.");
if (at_end) {
read_eof = true;
@@ -342,16 +342,16 @@ Error FileAccessCompressed::get_error() const {
}
void FileAccessCompressed::flush() {
- ERR_FAIL_COND(!f);
- ERR_FAIL_COND(!writing);
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!writing, "File has not been opened in read mode.");
// compressed files keep data in memory till close()
}
void FileAccessCompressed::store_8(uint8_t p_dest) {
- ERR_FAIL_COND(!f);
- ERR_FAIL_COND(!writing);
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!writing, "File has not been opened in read mode.");
WRITE_FIT(1);
write_ptr[write_pos++] = p_dest;
diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp
index 0eef0ee79f..c2e4e0f575 100644
--- a/core/io/file_access_encrypted.cpp
+++ b/core/io/file_access_encrypted.cpp
@@ -41,7 +41,7 @@
Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8_t> &p_key, Mode p_mode) {
- ERR_FAIL_COND_V(file != NULL, ERR_ALREADY_IN_USE);
+ ERR_FAIL_COND_V_MSG(file != NULL, ERR_ALREADY_IN_USE, "Can't open file while another file from path '" + file->get_path_absolute() + "' is open.");
ERR_FAIL_COND_V(p_key.size() != 32, ERR_INVALID_PARAMETER);
pos = 0;
@@ -221,7 +221,7 @@ bool FileAccessEncrypted::eof_reached() const {
uint8_t FileAccessEncrypted::get_8() const {
- ERR_FAIL_COND_V(writing, 0);
+ ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode.");
if (pos >= data.size()) {
eofed = true;
return 0;
@@ -233,7 +233,7 @@ uint8_t FileAccessEncrypted::get_8() const {
}
int FileAccessEncrypted::get_buffer(uint8_t *p_dst, int p_length) const {
- ERR_FAIL_COND_V(writing, 0);
+ ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode.");
int to_copy = MIN(p_length, data.size() - pos);
for (int i = 0; i < to_copy; i++) {
@@ -255,7 +255,7 @@ Error FileAccessEncrypted::get_error() const {
void FileAccessEncrypted::store_buffer(const uint8_t *p_src, int p_length) {
- ERR_FAIL_COND(!writing);
+ ERR_FAIL_COND_MSG(!writing, "File has not been opened in read mode.");
if (pos < data.size()) {
@@ -275,14 +275,14 @@ void FileAccessEncrypted::store_buffer(const uint8_t *p_src, int p_length) {
}
void FileAccessEncrypted::flush() {
- ERR_FAIL_COND(!writing);
+ ERR_FAIL_COND_MSG(!writing, "File has not been opened in read mode.");
// encrypted files keep data in memory till close()
}
void FileAccessEncrypted::store_8(uint8_t p_dest) {
- ERR_FAIL_COND(!writing);
+ ERR_FAIL_COND_MSG(!writing, "File has not been opened in read mode.");
if (pos < data.size()) {
data.write[pos] = p_dest;
diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp
index fbcf5b8021..c0acd36751 100644
--- a/core/io/file_access_memory.cpp
+++ b/core/io/file_access_memory.cpp
@@ -90,7 +90,7 @@ Error FileAccessMemory::_open(const String &p_path, int p_mode_flags) {
//name = DirAccess::normalize_path(name);
Map<String, Vector<uint8_t> >::Element *E = files->find(name);
- ERR_FAIL_COND_V(!E, ERR_FILE_NOT_FOUND);
+ ERR_FAIL_COND_V_MSG(!E, ERR_FILE_NOT_FOUND, "Can't find file '" + p_path + "'.");
data = E->get().ptrw();
length = E->get().size();
diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp
index d1c7f5c334..e653a924ba 100644
--- a/core/io/file_access_network.cpp
+++ b/core/io/file_access_network.cpp
@@ -195,7 +195,7 @@ Error FileAccessNetworkClient::connect(const String &p_host, int p_port, const S
DEBUG_PRINT("IP: " + String(ip) + " port " + itos(p_port));
Error err = client->connect_to_host(ip, p_port);
- ERR_FAIL_COND_V(err, err);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot connect to host with IP: " + String(ip) + " and port: " + itos(p_port));
while (client->get_status() == StreamPeerTCP::STATUS_CONNECTING) {
//DEBUG_PRINT("trying to connect....");
OS::get_singleton()->delay_usec(1000);
@@ -339,7 +339,7 @@ bool FileAccessNetwork::is_open() const {
void FileAccessNetwork::seek(size_t p_position) {
- ERR_FAIL_COND(!opened);
+ ERR_FAIL_COND_MSG(!opened, "File must be opened before use.");
eof_flag = p_position > total_size;
if (p_position >= total_size) {
@@ -355,18 +355,18 @@ void FileAccessNetwork::seek_end(int64_t p_position) {
}
size_t FileAccessNetwork::get_position() const {
- ERR_FAIL_COND_V(!opened, 0);
+ ERR_FAIL_COND_V_MSG(!opened, 0, "File must be opened before use.");
return pos;
}
size_t FileAccessNetwork::get_len() const {
- ERR_FAIL_COND_V(!opened, 0);
+ ERR_FAIL_COND_V_MSG(!opened, 0, "File must be opened before use.");
return total_size;
}
bool FileAccessNetwork::eof_reached() const {
- ERR_FAIL_COND_V(!opened, false);
+ ERR_FAIL_COND_V_MSG(!opened, false, "File must be opened before use.");
return eof_flag;
}
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index d49d36c2b9..34d3eb5344 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -36,11 +36,11 @@
#define PACK_VERSION 1
-Error PackedData::add_pack(const String &p_path) {
+Error PackedData::add_pack(const String &p_path, bool p_replace_files) {
for (int i = 0; i < sources.size(); i++) {
- if (sources[i]->try_open_pack(p_path)) {
+ if (sources[i]->try_open_pack(p_path, p_replace_files)) {
return OK;
};
@@ -49,7 +49,7 @@ Error PackedData::add_pack(const String &p_path) {
return ERR_FILE_UNRECOGNIZED;
};
-void PackedData::add_path(const String &pkg_path, const String &path, uint64_t ofs, uint64_t size, const uint8_t *p_md5, PackSource *p_src) {
+void PackedData::add_path(const String &pkg_path, const String &path, uint64_t ofs, uint64_t size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files) {
PathMD5 pmd5(path.md5_buffer());
//printf("adding path %ls, %lli, %lli\n", path.c_str(), pmd5.a, pmd5.b);
@@ -64,7 +64,8 @@ void PackedData::add_path(const String &pkg_path, const String &path, uint64_t o
pf.md5[i] = p_md5[i];
pf.src = p_src;
- files[pmd5] = pf;
+ if (!exists || p_replace_files)
+ files[pmd5] = pf;
if (!exists) {
//search for dir
@@ -133,7 +134,7 @@ PackedData::~PackedData() {
//////////////////////////////////////////////////////////////////
-bool PackedSourcePCK::try_open_pack(const String &p_path) {
+bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files) {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
if (!f)
@@ -150,6 +151,7 @@ bool PackedSourcePCK::try_open_pack(const String &p_path) {
magic = f->get_32();
if (magic != 0x43504447) {
+ f->close();
memdelete(f);
return false;
}
@@ -161,6 +163,7 @@ bool PackedSourcePCK::try_open_pack(const String &p_path) {
magic = f->get_32();
if (magic != 0x43504447) {
+ f->close();
memdelete(f);
return false;
}
@@ -171,8 +174,16 @@ bool PackedSourcePCK::try_open_pack(const String &p_path) {
uint32_t ver_minor = f->get_32();
f->get_32(); // ver_rev
- ERR_FAIL_COND_V_MSG(version != PACK_VERSION, false, "Pack version unsupported: " + itos(version) + ".");
- ERR_FAIL_COND_V_MSG(ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR), false, "Pack created with a newer version of the engine: " + itos(ver_major) + "." + itos(ver_minor) + ".");
+ if (version != PACK_VERSION) {
+ f->close();
+ memdelete(f);
+ ERR_FAIL_V_MSG(false, "Pack version unsupported: " + itos(version) + ".");
+ }
+ if (ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR)) {
+ f->close();
+ memdelete(f);
+ ERR_FAIL_V_MSG(false, "Pack created with a newer version of the engine: " + itos(ver_major) + "." + itos(ver_minor) + ".");
+ }
for (int i = 0; i < 16; i++) {
//reserved
@@ -196,9 +207,11 @@ bool PackedSourcePCK::try_open_pack(const String &p_path) {
uint64_t size = f->get_64();
uint8_t md5[16];
f->get_buffer(md5, 16);
- PackedData::get_singleton()->add_path(p_path, path, ofs, size, md5, this);
+ PackedData::get_singleton()->add_path(p_path, path, ofs, size, md5, this, p_replace_files);
};
+ f->close();
+ memdelete(f);
return true;
};
@@ -321,7 +334,7 @@ FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFil
pf(p_file),
f(FileAccess::open(pf.pack, FileAccess::READ)) {
- ERR_FAIL_COND_MSG(!f, "Can't open pack-referenced file: " + String(pf.pack) + ".");
+ ERR_FAIL_COND_MSG(!f, "Can't open pack-referenced file '" + String(pf.pack) + "'.");
f->seek(pf.offset);
pos = 0;
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index a21dd7d22d..8c34069f3a 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -102,13 +102,13 @@ private:
public:
void add_pack_source(PackSource *p_source);
- void add_path(const String &pkg_path, const String &path, uint64_t ofs, uint64_t size, const uint8_t *p_md5, PackSource *p_src); // for PackSource
+ void add_path(const String &pkg_path, const String &path, uint64_t ofs, uint64_t size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files); // for PackSource
void set_disabled(bool p_disabled) { disabled = p_disabled; }
_FORCE_INLINE_ bool is_disabled() const { return disabled; }
static PackedData *get_singleton() { return singleton; }
- Error add_pack(const String &p_path);
+ Error add_pack(const String &p_path, bool p_replace_files);
_FORCE_INLINE_ FileAccess *try_open_path(const String &p_path);
_FORCE_INLINE_ bool has_path(const String &p_path);
@@ -120,7 +120,7 @@ public:
class PackSource {
public:
- virtual bool try_open_pack(const String &p_path) = 0;
+ virtual bool try_open_pack(const String &p_path, bool p_replace_files) = 0;
virtual FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file) = 0;
virtual ~PackSource() {}
};
@@ -128,7 +128,7 @@ public:
class PackedSourcePCK : public PackSource {
public:
- virtual bool try_open_pack(const String &p_path);
+ virtual bool try_open_pack(const String &p_path, bool p_replace_files);
virtual FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file);
};
diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp
index abc0bd064d..3187f3bab6 100644
--- a/core/io/file_access_zip.cpp
+++ b/core/io/file_access_zip.cpp
@@ -117,7 +117,7 @@ static void godot_free(voidpf opaque, voidpf address) {
void ZipArchive::close_handle(unzFile p_file) const {
- ERR_FAIL_COND(!p_file);
+ ERR_FAIL_COND_MSG(!p_file, "Cannot close a file if none is open.");
FileAccess *f = (FileAccess *)unzGetOpaque(p_file);
unzCloseCurrentFile(p_file);
unzClose(p_file);
@@ -126,11 +126,11 @@ void ZipArchive::close_handle(unzFile p_file) const {
unzFile ZipArchive::get_file_handle(String p_file) const {
- ERR_FAIL_COND_V(!file_exists(p_file), NULL);
+ ERR_FAIL_COND_V_MSG(!file_exists(p_file), NULL, "File '" + p_file + " doesn't exist.");
File file = files[p_file];
FileAccess *f = FileAccess::open(packages[file.package].filename, FileAccess::READ);
- ERR_FAIL_COND_V(!f, NULL);
+ ERR_FAIL_COND_V_MSG(!f, NULL, "Cannot open file '" + packages[file.package].filename + "'.");
zlib_filefunc_def io;
zeromem(&io, sizeof(io));
@@ -160,7 +160,7 @@ unzFile ZipArchive::get_file_handle(String p_file) const {
return pkg;
}
-bool ZipArchive::try_open_pack(const String &p_path) {
+bool ZipArchive::try_open_pack(const String &p_path, bool p_replace_files) {
//printf("opening zip pack %ls, %i, %i\n", p_name.c_str(), p_name.extension().nocasecmp_to("zip"), p_name.extension().nocasecmp_to("pcz"));
if (p_path.get_extension().nocasecmp_to("zip") != 0 && p_path.get_extension().nocasecmp_to("pcz") != 0)
@@ -210,7 +210,7 @@ bool ZipArchive::try_open_pack(const String &p_path) {
files[fname] = f;
uint8_t md5[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- PackedData::get_singleton()->add_path(p_path, fname, 1, 0, md5, this);
+ PackedData::get_singleton()->add_path(p_path, fname, 1, 0, md5, this, p_replace_files);
//printf("packed data add path %ls, %ls\n", p_name.c_str(), fname.c_str());
if ((i + 1) < gi.number_entry) {
diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h
index 217176c0af..cdd50f9eb3 100644
--- a/core/io/file_access_zip.h
+++ b/core/io/file_access_zip.h
@@ -74,7 +74,7 @@ public:
bool file_exists(String p_name) const;
- virtual bool try_open_pack(const String &p_path);
+ virtual bool try_open_pack(const String &p_path, bool p_replace_files);
FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file);
static ZipArchive *get_singleton();
diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp
index a759e615c7..095c2abb54 100644
--- a/core/io/image_loader.cpp
+++ b/core/io/image_loader.cpp
@@ -46,14 +46,14 @@ bool ImageFormatLoader::recognize(const String &p_extension) const {
}
Error ImageLoader::load_image(String p_file, Ref<Image> p_image, FileAccess *p_custom, bool p_force_linear, float p_scale) {
- ERR_FAIL_COND_V(p_image.is_null(), ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V_MSG(p_image.is_null(), ERR_INVALID_PARAMETER, "It's not a reference to a valid Image object.");
FileAccess *f = p_custom;
if (!f) {
Error err;
f = FileAccess::open(p_file, FileAccess::READ, &err);
if (!f) {
- ERR_PRINTS("Error opening file: " + p_file);
+ ERR_PRINTS("Error opening file '" + p_file + "'.");
return err;
}
}
diff --git a/core/io/ip.cpp b/core/io/ip.cpp
index 3d87131b51..f1b6570799 100644
--- a/core/io/ip.cpp
+++ b/core/io/ip.cpp
@@ -305,7 +305,7 @@ IP *(*IP::_create)() = NULL;
IP *IP::create() {
- ERR_FAIL_COND_V(singleton, NULL);
+ ERR_FAIL_COND_V_MSG(singleton, NULL, "IP singleton already exist.");
ERR_FAIL_COND_V(!_create, NULL);
return _create();
}
diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp
index df4be9b9fd..0980027f42 100644
--- a/core/io/ip_address.cpp
+++ b/core/io/ip_address.cpp
@@ -181,7 +181,7 @@ bool IP_Address::is_ipv4() const {
}
const uint8_t *IP_Address::get_ipv4() const {
- ERR_FAIL_COND_V(!is_ipv4(), &(field8[12])); // Not the correct IPv4 (it's an IPv6), but we don't want to return a null pointer risking an engine crash.
+ ERR_FAIL_COND_V_MSG(!is_ipv4(), &(field8[12]), "IPv4 requested, but current IP is IPv6."); // Not the correct IPv4 (it's an IPv6), but we don't want to return a null pointer risking an engine crash.
return &(field8[12]);
}
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index b386feb14c..2ae542bca7 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -478,7 +478,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
int used;
Error err = decode_variant(key, buf, len, &used, p_allow_objects);
- ERR_FAIL_COND_V(err, err);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Error when trying to decode Variant.");
buf += used;
len -= used;
@@ -487,7 +487,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
}
err = decode_variant(value, buf, len, &used, p_allow_objects);
- ERR_FAIL_COND_V(err, err);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Error when trying to decode Variant.");
buf += used;
len -= used;
@@ -522,7 +522,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
int used = 0;
Variant v;
Error err = decode_variant(v, buf, len, &used, p_allow_objects);
- ERR_FAIL_COND_V(err, err);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Error when trying to decode Variant.");
buf += used;
len -= used;
varr.push_back(v);
diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp
index ed6905c9a6..0ba84d0c8f 100644
--- a/core/io/multiplayer_api.cpp
+++ b/core/io/multiplayer_api.cpp
@@ -917,8 +917,7 @@ int MultiplayerAPI::_get_bandwidth_usage(const Vector<BandwidthFrame> &p_buffer,
i = (i + p_buffer.size() - 1) % p_buffer.size();
}
- ERR_EXPLAIN("Reached the end of the bandwidth profiler buffer, values might be inaccurate.");
- ERR_FAIL_COND_V(i == p_pointer, total_bandwidth);
+ ERR_FAIL_COND_V_MSG(i == p_pointer, total_bandwidth, "Reached the end of the bandwidth profiler buffer, values might be inaccurate.");
return total_bandwidth;
}
diff --git a/core/io/packet_peer.cpp b/core/io/packet_peer.cpp
index 1c792c43d1..821a04ebad 100644
--- a/core/io/packet_peer.cpp
+++ b/core/io/packet_peer.cpp
@@ -101,9 +101,9 @@ Error PacketPeer::put_var(const Variant &p_packet, bool p_full_objects) {
return OK;
uint8_t *buf = (uint8_t *)alloca(len);
- ERR_FAIL_COND_V(!buf, ERR_OUT_OF_MEMORY);
+ ERR_FAIL_COND_V_MSG(!buf, ERR_OUT_OF_MEMORY, "Out of memory.");
err = encode_variant(p_packet, buf, len, p_full_objects || allow_object_decoding);
- ERR_FAIL_COND_V(err, err);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Error when trying to encode Variant.");
return put_packet(buf, len);
}
@@ -150,7 +150,7 @@ void PacketPeer::_bind_methods() {
void PacketPeerStream::_set_stream_peer(REF p_peer) {
- ERR_FAIL_COND(p_peer.is_null());
+ ERR_FAIL_COND_MSG(p_peer.is_null(), "It's not a reference to a valid Resource object.");
set_stream_peer(p_peer);
}
diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp
index 1c89bc6268..443f390bb7 100644
--- a/core/io/pck_packer.cpp
+++ b/core/io/pck_packer.cpp
@@ -107,7 +107,7 @@ Error PCKPacker::add_file(const String &p_file, const String &p_src) {
Error PCKPacker::flush(bool p_verbose) {
- ERR_FAIL_COND_V(!file, ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V_MSG(!file, ERR_INVALID_PARAMETER, "File must be opened before use.");
// write the index
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index 0ad2479b05..e91dd579b5 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -378,10 +378,10 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) {
for (uint32_t i = 0; i < len; i++) {
Variant key;
Error err = parse_variant(key);
- ERR_FAIL_COND_V(err, ERR_FILE_CORRUPT);
+ ERR_FAIL_COND_V_MSG(err, ERR_FILE_CORRUPT, "Error when trying to parse Variant.");
Variant value;
err = parse_variant(value);
- ERR_FAIL_COND_V(err, ERR_FILE_CORRUPT);
+ ERR_FAIL_COND_V_MSG(err, ERR_FILE_CORRUPT, "Error when trying to parse Variant.");
d[key] = value;
}
r_v = d;
@@ -395,7 +395,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) {
for (uint32_t i = 0; i < len; i++) {
Variant val;
Error err = parse_variant(val);
- ERR_FAIL_COND_V(err, ERR_FILE_CORRUPT);
+ ERR_FAIL_COND_V_MSG(err, ERR_FILE_CORRUPT, "Error when trying to parse Variant.");
a[i] = val;
}
r_v = a;
@@ -983,7 +983,7 @@ Ref<ResourceInteractiveLoader> ResourceFormatLoaderBinary::load_interactive(cons
Error err;
FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
- ERR_FAIL_COND_V(err != OK, Ref<ResourceInteractiveLoader>());
+ ERR_FAIL_COND_V_MSG(err != OK, Ref<ResourceInteractiveLoader>(), "Cannot open file '" + p_path + "'.");
Ref<ResourceInteractiveLoaderBinary> ria = memnew(ResourceInteractiveLoaderBinary);
String path = p_original_path != "" ? p_original_path : p_path;
@@ -1032,7 +1032,7 @@ bool ResourceFormatLoaderBinary::handles_type(const String &p_type) const {
void ResourceFormatLoaderBinary::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND(!f);
+ ERR_FAIL_COND_MSG(!f, "Cannot open file '" + p_path + "'.");
Ref<ResourceInteractiveLoaderBinary> ria = memnew(ResourceInteractiveLoaderBinary);
ria->local_path = ProjectSettings::get_singleton()->localize_path(p_path);
@@ -1046,7 +1046,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
//Error error=OK;
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);
+ ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot open file '" + p_path + "'.");
FileAccess *fw = NULL; //=FileAccess::open(p_path+".depren");
@@ -1066,7 +1066,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
if (err) {
memdelete(fac);
memdelete(facw);
- ERR_FAIL_COND_V(err, ERR_FILE_CORRUPT);
+ ERR_FAIL_COND_V_MSG(err, ERR_FILE_CORRUPT, "Cannot create file '" + p_path + ".depren'.");
}
fw = facw;
@@ -1076,13 +1076,13 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
//error=ERR_FILE_UNRECOGNIZED;
memdelete(f);
- ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "Unrecognized binary resource file: " + local_path + ".");
+ ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "Unrecognized binary resource file '" + local_path + "'.");
} else {
fw = FileAccess::open(p_path + ".depren", FileAccess::WRITE);
if (!fw) {
memdelete(f);
}
- ERR_FAIL_COND_V(!fw, ERR_CANT_CREATE);
+ ERR_FAIL_COND_V_MSG(!fw, ERR_CANT_CREATE, "Cannot create file '" + p_path + ".depren'.");
uint8_t magic[4] = { 'R', 'S', 'R', 'C' };
fw->store_buffer(magic, 4);
@@ -1113,12 +1113,12 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
memdelete(da);
//use the old approach
- WARN_PRINTS("This file is old, so it can't refactor dependencies, opening and resaving: " + p_path + ".");
+ WARN_PRINTS("This file is old, so it can't refactor dependencies, opening and resaving '" + p_path + "'.");
Error err;
f = FileAccess::open(p_path, FileAccess::READ, &err);
- ERR_FAIL_COND_V(err != OK, ERR_FILE_CANT_OPEN);
+ ERR_FAIL_COND_V_MSG(err != OK, ERR_FILE_CANT_OPEN, "Cannot open file '" + p_path + "'.");
Ref<ResourceInteractiveLoaderBinary> ria = memnew(ResourceInteractiveLoaderBinary);
ria->local_path = ProjectSettings::get_singleton()->localize_path(p_path);
@@ -1751,7 +1751,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
f = FileAccess::open(p_path, FileAccess::WRITE, &err);
}
- ERR_FAIL_COND_V(err, err);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot create file '" + p_path + "'.");
relative_paths = p_flags & ResourceSaver::FLAG_RELATIVE_PATHS;
skip_editor = p_flags & ResourceSaver::FLAG_OMIT_EDITOR_PROPERTIES;
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 9e954890bc..f3eba44973 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -205,7 +205,7 @@ RES ResourceFormatLoader::load(const String &p_path, const String &p_original_pa
if (r_error)
*r_error = err;
- ERR_FAIL_COND_V(err != OK, RES());
+ ERR_FAIL_COND_V_MSG(err != OK, RES(), "Failed to load resource '" + p_path + "'.");
}
}
diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp
index a9ad62afe6..7aa8732366 100644
--- a/core/io/resource_saver.cpp
+++ b/core/io/resource_saver.cpp
@@ -158,7 +158,7 @@ void ResourceSaver::get_recognized_extensions(const RES &p_resource, List<String
void ResourceSaver::add_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver, bool p_at_front) {
- ERR_FAIL_COND(p_format_saver.is_null());
+ ERR_FAIL_COND_MSG(p_format_saver.is_null(), "It's not a reference to a valid ResourceFormatSaver object.");
ERR_FAIL_COND(saver_count >= MAX_SAVERS);
if (p_at_front) {
@@ -174,7 +174,7 @@ void ResourceSaver::add_resource_format_saver(Ref<ResourceFormatSaver> p_format_
void ResourceSaver::remove_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver) {
- ERR_FAIL_COND(p_format_saver.is_null());
+ ERR_FAIL_COND_MSG(p_format_saver.is_null(), "It's not a reference to a valid ResourceFormatSaver object.");
// Find saver
int i = 0;
diff --git a/core/io/stream_peer.cpp b/core/io/stream_peer.cpp
index 84b8554d54..f19e055b64 100644
--- a/core/io/stream_peer.cpp
+++ b/core/io/stream_peer.cpp
@@ -370,7 +370,7 @@ Variant StreamPeer::get_var(bool p_allow_objects) {
Variant ret;
err = decode_variant(ret, var.ptr(), len, NULL, p_allow_objects);
- ERR_FAIL_COND_V(err != OK, Variant());
+ ERR_FAIL_COND_V_MSG(err != OK, Variant(), "Error when trying to decode Variant.");
return ret;
}
diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp
index 310bb12bc0..b9c5896b24 100644
--- a/core/io/stream_peer_tcp.cpp
+++ b/core/io/stream_peer_tcp.cpp
@@ -248,16 +248,7 @@ void StreamPeerTCP::set_no_delay(bool p_enabled) {
bool StreamPeerTCP::is_connected_to_host() const {
- if (status == STATUS_NONE || status == STATUS_ERROR) {
-
- return false;
- }
-
- if (status != STATUS_CONNECTED) {
- return true;
- }
-
- return _sock.is_valid() && _sock->is_open();
+ return _sock.is_valid() && _sock->is_open() && (status == STATUS_CONNECTED || status == STATUS_CONNECTING);
}
StreamPeerTCP::Status StreamPeerTCP::get_status() {
diff --git a/core/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp
index e8e71c10ca..9b6888ac21 100644
--- a/core/io/translation_loader_po.cpp
+++ b/core/io/translation_loader_po.cpp
@@ -182,7 +182,7 @@ RES TranslationLoaderPO::load(const String &p_path, const String &p_original_pat
*r_error = ERR_CANT_OPEN;
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND_V(!f, RES());
+ ERR_FAIL_COND_V_MSG(!f, RES(), "Cannot open file '" + p_path + "'.");
return load_translation(f, r_error);
}
diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp
index 9487947365..575c78734f 100644
--- a/core/io/xml_parser.cpp
+++ b/core/io/xml_parser.cpp
@@ -484,7 +484,7 @@ Error XMLParser::open(const String &p_path) {
Error err;
FileAccess *file = FileAccess::open(p_path, FileAccess::READ, &err);
- ERR_FAIL_COND_V(err != OK, err);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot open file '" + p_path + "'.");
length = file->get_len();
ERR_FAIL_COND_V(length < 1, ERR_FILE_CORRUPT);
diff --git a/core/list.h b/core/list.h
index d1b528562d..c46888e01c 100644
--- a/core/list.h
+++ b/core/list.h
@@ -31,6 +31,7 @@
#ifndef GLOBALS_LIST_H
#define GLOBALS_LIST_H
+#include "core/error_macros.h"
#include "core/os/memory.h"
#include "core/sort_array.h"
diff --git a/core/map.h b/core/map.h
index c87ee42e1b..77e73d70cb 100644
--- a/core/map.h
+++ b/core/map.h
@@ -31,6 +31,7 @@
#ifndef MAP_H
#define MAP_H
+#include "core/error_macros.h"
#include "core/set.h"
// based on the very nice implementation of rb-trees by:
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp
index 60b7326c29..ae2b56e7b7 100644
--- a/core/math/a_star.cpp
+++ b/core/math/a_star.cpp
@@ -257,14 +257,14 @@ void AStar::reserve_space(int p_num_nodes) {
points.reserve(p_num_nodes);
}
-int AStar::get_closest_point(const Vector3 &p_point) const {
+int AStar::get_closest_point(const Vector3 &p_point, bool p_include_disabled) const {
int closest_id = -1;
real_t closest_dist = 1e20;
for (OAHashMap<int, Point *>::Iterator it = points.iter(); it.valid; it = points.next_iter(it)) {
- if (!(*it.value)->enabled) continue; // Disabled points should not be considered.
+ if (!p_include_disabled && !(*it.value)->enabled) continue; // Disabled points should not be considered.
real_t d = p_point.distance_squared_to((*it.value)->pos);
if (closest_id < 0 || d < closest_dist) {
@@ -540,7 +540,7 @@ void AStar::_bind_methods() {
ClassDB::bind_method(D_METHOD("reserve_space", "num_nodes"), &AStar::reserve_space);
ClassDB::bind_method(D_METHOD("clear"), &AStar::clear);
- ClassDB::bind_method(D_METHOD("get_closest_point", "to_position"), &AStar::get_closest_point);
+ ClassDB::bind_method(D_METHOD("get_closest_point", "to_position", "include_disabled"), &AStar::get_closest_point, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_closest_position_in_segment", "to_position"), &AStar::get_closest_position_in_segment);
ClassDB::bind_method(D_METHOD("get_point_path", "from_id", "to_id"), &AStar::get_point_path);
@@ -638,8 +638,8 @@ void AStar2D::reserve_space(int p_num_nodes) {
astar.reserve_space(p_num_nodes);
}
-int AStar2D::get_closest_point(const Vector2 &p_point) const {
- return astar.get_closest_point(Vector3(p_point.x, p_point.y, 0));
+int AStar2D::get_closest_point(const Vector2 &p_point, bool p_include_disabled) const {
+ return astar.get_closest_point(Vector3(p_point.x, p_point.y, 0), p_include_disabled);
}
Vector2 AStar2D::get_closest_position_in_segment(const Vector2 &p_point) const {
@@ -693,7 +693,7 @@ void AStar2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("reserve_space", "num_nodes"), &AStar2D::reserve_space);
ClassDB::bind_method(D_METHOD("clear"), &AStar2D::clear);
- ClassDB::bind_method(D_METHOD("get_closest_point", "to_position"), &AStar2D::get_closest_point);
+ ClassDB::bind_method(D_METHOD("get_closest_point", "to_position", "include_disabled"), &AStar2D::get_closest_point, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_closest_position_in_segment", "to_position"), &AStar2D::get_closest_position_in_segment);
ClassDB::bind_method(D_METHOD("get_point_path", "from_id", "to_id"), &AStar2D::get_point_path);
diff --git a/core/math/a_star.h b/core/math/a_star.h
index ec2a06f07f..0a5d3e992c 100644
--- a/core/math/a_star.h
+++ b/core/math/a_star.h
@@ -141,7 +141,7 @@ public:
void reserve_space(int p_num_nodes);
void clear();
- int get_closest_point(const Vector3 &p_point) const;
+ int get_closest_point(const Vector3 &p_point, bool p_include_disabled = false) const;
Vector3 get_closest_position_in_segment(const Vector3 &p_point) const;
PoolVector<Vector3> get_point_path(int p_from_id, int p_to_id);
@@ -183,7 +183,7 @@ public:
void reserve_space(int p_num_nodes);
void clear();
- int get_closest_point(const Vector2 &p_point) const;
+ int get_closest_point(const Vector2 &p_point, bool p_include_disabled = false) const;
Vector2 get_closest_position_in_segment(const Vector2 &p_point) const;
PoolVector<Vector2> get_point_path(int p_from_id, int p_to_id);
diff --git a/core/math/basis.cpp b/core/math/basis.cpp
index 2985959113..0a491010e2 100644
--- a/core/math/basis.cpp
+++ b/core/math/basis.cpp
@@ -807,7 +807,7 @@ void Basis::set_quat(const Quat &p_quat) {
void Basis::set_axis_angle(const Vector3 &p_axis, real_t p_phi) {
// Rotation matrix from axis and angle, see https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_angle
#ifdef MATH_CHECKS
- ERR_FAIL_COND(!p_axis.is_normalized());
+ ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "Axis must be normalized.");
#endif
Vector3 axis_sq(p_axis.x * p_axis.x, p_axis.y * p_axis.y, p_axis.z * p_axis.z);
real_t cosine = Math::cos(p_phi);
diff --git a/core/math/basis.h b/core/math/basis.h
index 053effda69..4be4ea4cd3 100644
--- a/core/math/basis.h
+++ b/core/math/basis.h
@@ -28,13 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-// Circular dependency between Vector3 and Basis :/
-#include "core/math/vector3.h"
-
#ifndef BASIS_H
#define BASIS_H
#include "core/math/quat.h"
+#include "core/math/vector3.h"
class Basis {
public:
diff --git a/core/math/geometry.cpp b/core/math/geometry.cpp
index 77383e2839..e0ead8446f 100644
--- a/core/math/geometry.cpp
+++ b/core/math/geometry.cpp
@@ -241,10 +241,7 @@ PoolVector<PoolVector<Face3> > Geometry::separate_objects(PoolVector<Face3> p_ar
bool error = _connect_faces(_fcptr, len, -1);
- if (error) {
-
- ERR_FAIL_COND_V(error, PoolVector<PoolVector<Face3> >()); // Invalid geometry.
- }
+ ERR_FAIL_COND_V_MSG(error, PoolVector<PoolVector<Face3> >(), "Invalid geometry.");
// Group connected faces in separate objects.
diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp
index f04e40cb6c..50fcdb2c13 100644
--- a/core/math/math_funcs.cpp
+++ b/core/math/math_funcs.cpp
@@ -30,6 +30,8 @@
#include "math_funcs.h"
+#include "core/error_macros.h"
+
RandomPCG Math::default_rand(RandomPCG::DEFAULT_SEED, RandomPCG::DEFAULT_INC);
#define PHI 0x9e3779b9
diff --git a/core/math/plane.cpp b/core/math/plane.cpp
index b01853c4ac..b6bcac4b27 100644
--- a/core/math/plane.cpp
+++ b/core/math/plane.cpp
@@ -91,7 +91,7 @@ bool Plane::intersect_3(const Plane &p_plane1, const Plane &p_plane2, Vector3 *r
real_t denom = vec3_cross(normal0, normal1).dot(normal2);
- if (ABS(denom) <= CMP_EPSILON)
+ if (Math::is_zero_approx(denom))
return false;
if (r_result) {
diff --git a/core/math/rect2.h b/core/math/rect2.h
index d636aa223f..f58756ee40 100644
--- a/core/math/rect2.h
+++ b/core/math/rect2.h
@@ -99,8 +99,8 @@ struct Rect2 {
inline bool encloses(const Rect2 &p_rect) const {
return (p_rect.position.x >= position.x) && (p_rect.position.y >= position.y) &&
- ((p_rect.position.x + p_rect.size.x) < (position.x + size.x)) &&
- ((p_rect.position.y + p_rect.size.y) < (position.y + size.y));
+ ((p_rect.position.x + p_rect.size.x) <= (position.x + size.x)) &&
+ ((p_rect.position.y + p_rect.size.y) <= (position.y + size.y));
}
_FORCE_INLINE_ bool has_no_area() const {
diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp
index 73927821cf..ebc1599820 100644
--- a/core/math/vector3.cpp
+++ b/core/math/vector3.cpp
@@ -134,6 +134,21 @@ Vector3 Vector3::move_toward(const Vector3 &p_to, const real_t p_delta) const {
return len <= p_delta || len < CMP_EPSILON ? p_to : v + vd / len * p_delta;
}
+Basis Vector3::outer(const Vector3 &p_b) const {
+
+ Vector3 row0(x * p_b.x, x * p_b.y, x * p_b.z);
+ Vector3 row1(y * p_b.x, y * p_b.y, y * p_b.z);
+ Vector3 row2(z * p_b.x, z * p_b.y, z * p_b.z);
+
+ return Basis(row0, row1, row2);
+}
+
+Basis Vector3::to_diagonal_matrix() const {
+ return Basis(x, 0, 0,
+ 0, y, 0,
+ 0, 0, z);
+}
+
Vector3::operator String() const {
return (rtos(x) + ", " + rtos(y) + ", " + rtos(z));
diff --git a/core/math/vector3.h b/core/math/vector3.h
index c68b075613..de1743d88f 100644
--- a/core/math/vector3.h
+++ b/core/math/vector3.h
@@ -96,8 +96,8 @@ struct Vector3 {
_FORCE_INLINE_ Vector3 cross(const Vector3 &p_b) const;
_FORCE_INLINE_ real_t dot(const Vector3 &p_b) const;
- _FORCE_INLINE_ Basis outer(const Vector3 &p_b) const;
- _FORCE_INLINE_ Basis to_diagonal_matrix() const;
+ Basis outer(const Vector3 &p_b) const;
+ Basis to_diagonal_matrix() const;
_FORCE_INLINE_ Vector3 abs() const;
_FORCE_INLINE_ Vector3 floor() const;
@@ -154,9 +154,6 @@ struct Vector3 {
_FORCE_INLINE_ Vector3() { x = y = z = 0; }
};
-// Should be included after class definition, otherwise we get circular refs
-#include "core/math/basis.h"
-
Vector3 Vector3::cross(const Vector3 &p_b) const {
Vector3 ret(
@@ -172,21 +169,6 @@ real_t Vector3::dot(const Vector3 &p_b) const {
return x * p_b.x + y * p_b.y + z * p_b.z;
}
-Basis Vector3::outer(const Vector3 &p_b) const {
-
- Vector3 row0(x * p_b.x, x * p_b.y, x * p_b.z);
- Vector3 row1(y * p_b.x, y * p_b.y, y * p_b.z);
- Vector3 row2(z * p_b.x, z * p_b.y, z * p_b.z);
-
- return Basis(row0, row1, row2);
-}
-
-Basis Vector3::to_diagonal_matrix() const {
- return Basis(x, 0, 0,
- 0, y, 0,
- 0, 0, z);
-}
-
Vector3 Vector3::abs() const {
return Vector3(Math::abs(x), Math::abs(y), Math::abs(z));
diff --git a/core/message_queue.cpp b/core/message_queue.cpp
index 390989ac91..a76b5167b6 100644
--- a/core/message_queue.cpp
+++ b/core/message_queue.cpp
@@ -340,7 +340,7 @@ bool MessageQueue::is_flushing() const {
MessageQueue::MessageQueue() {
- ERR_FAIL_COND(singleton != NULL);
+ ERR_FAIL_COND_MSG(singleton != NULL, "MessageQueue singleton already exist.");
singleton = this;
flushing = false;
diff --git a/core/node_path.cpp b/core/node_path.cpp
index 8244785d84..970ed100fe 100644
--- a/core/node_path.cpp
+++ b/core/node_path.cpp
@@ -269,7 +269,7 @@ NodePath NodePath::rel_path_to(const NodePath &p_np) const {
NodePath NodePath::get_as_property_path() const {
- if (!data->path.size()) {
+ if (!data || !data->path.size()) {
return *this;
} else {
Vector<StringName> new_path = data->subpath;
@@ -375,7 +375,7 @@ NodePath::NodePath(const String &p_path) {
if (str == "") {
if (path[i] == 0) continue; // Allow end-of-path :
- ERR_FAIL_MSG("Invalid NodePath: " + p_path + ".");
+ ERR_FAIL_MSG("Invalid NodePath '" + p_path + "'.");
}
subpath.push_back(str);
diff --git a/core/oa_hash_map.h b/core/oa_hash_map.h
index 5ea6d8b0d4..1a466e57f4 100644
--- a/core/oa_hash_map.h
+++ b/core/oa_hash_map.h
@@ -37,10 +37,11 @@
#include "core/os/memory.h"
/**
- * A HashMap implementation that uses open addressing with robinhood hashing.
- * Robinhood hashing swaps out entries that have a smaller probing distance
+ * A HashMap implementation that uses open addressing with Robin Hood hashing.
+ * Robin Hood hashing swaps out entries that have a smaller probing distance
* than the to-be-inserted entry, that evens out the average probing distance
- * and enables faster lookups.
+ * and enables faster lookups. Backward shift deletion is employed to further
+ * improve the performance and to avoid infinite loops in rare cases.
*
* The entries are stored inplace, so huge keys or values might fill cache lines
* a lot faster.
@@ -60,25 +61,20 @@ private:
uint32_t num_elements;
static const uint32_t EMPTY_HASH = 0;
- static const uint32_t DELETED_HASH_BIT = 1 << 31;
_FORCE_INLINE_ uint32_t _hash(const TKey &p_key) const {
uint32_t hash = Hasher::hash(p_key);
if (hash == EMPTY_HASH) {
hash = EMPTY_HASH + 1;
- } else if (hash & DELETED_HASH_BIT) {
- hash &= ~DELETED_HASH_BIT;
}
return hash;
}
_FORCE_INLINE_ uint32_t _get_probe_length(uint32_t p_pos, uint32_t p_hash) const {
- p_hash = p_hash & ~DELETED_HASH_BIT; // we don't care if it was deleted or not
-
uint32_t original_pos = p_hash % capacity;
- return (p_pos - original_pos) % capacity;
+ return (p_pos - original_pos + capacity) % capacity;
}
_FORCE_INLINE_ void _construct(uint32_t p_pos, uint32_t p_hash, const TKey &p_key, const TValue &p_value) {
@@ -132,14 +128,6 @@ private:
// not an empty slot, let's check the probing length of the existing one
uint32_t existing_probe_len = _get_probe_length(pos, hashes[pos]);
if (existing_probe_len < distance) {
-
- if (hashes[pos] & DELETED_HASH_BIT) {
- // we found a place where we can fit in!
- _construct(pos, hash, key, value);
-
- return;
- }
-
SWAP(hash, hashes[pos]);
SWAP(key, keys[pos]);
SWAP(value, values[pos]);
@@ -173,9 +161,6 @@ private:
if (old_hashes[i] == EMPTY_HASH) {
continue;
}
- if (old_hashes[i] & DELETED_HASH_BIT) {
- continue;
- }
_insert_with_hash(old_hashes[i], old_keys[i], old_values[i]);
}
@@ -205,10 +190,6 @@ public:
continue;
}
- if (hashes[i] & DELETED_HASH_BIT) {
- continue;
- }
-
hashes[i] = EMPTY_HASH;
values[i].~TValue();
keys[i].~TKey();
@@ -219,7 +200,7 @@ public:
void insert(const TKey &p_key, const TValue &p_value) {
- if ((float)num_elements / (float)capacity > 0.9) {
+ if (num_elements + 1 > 0.9 * capacity) {
_resize_and_rehash();
}
@@ -272,9 +253,20 @@ public:
return;
}
- hashes[pos] |= DELETED_HASH_BIT;
+ uint32_t next_pos = (pos + 1) % capacity;
+ while (hashes[next_pos] != EMPTY_HASH &&
+ _get_probe_length(next_pos, hashes[next_pos]) != 0) {
+ SWAP(hashes[next_pos], hashes[pos]);
+ SWAP(keys[next_pos], keys[pos]);
+ SWAP(values[next_pos], values[pos]);
+ pos = next_pos;
+ next_pos = (pos + 1) % capacity;
+ }
+
+ hashes[pos] = EMPTY_HASH;
values[pos].~TValue();
keys[pos].~TKey();
+
num_elements--;
}
@@ -326,9 +318,6 @@ public:
if (hashes[i] == EMPTY_HASH) {
continue;
}
- if (hashes[i] & DELETED_HASH_BIT) {
- continue;
- }
it.valid = true;
it.key = &keys[i];
diff --git a/core/object.cpp b/core/object.cpp
index 62bfa31480..6facf38733 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -1100,9 +1100,9 @@ void Object::get_meta_list(List<String> *p_list) const {
void Object::add_user_signal(const MethodInfo &p_signal) {
- ERR_FAIL_COND(p_signal.name == "");
- ERR_FAIL_COND(ClassDB::has_signal(get_class_name(), p_signal.name));
- ERR_FAIL_COND(signal_map.has(p_signal.name));
+ ERR_FAIL_COND_MSG(p_signal.name == "", "Signal name cannot be empty.");
+ ERR_FAIL_COND_MSG(ClassDB::has_signal(get_class_name(), p_signal.name), "User signal's name conflicts with a built-in signal of '" + get_class_name() + "'.");
+ ERR_FAIL_COND_MSG(signal_map.has(p_signal.name), "Trying to add already existing signal '" + p_signal.name + "'.");
Signal s;
s.user = p_signal;
signal_map[p_signal.name] = s;
diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp
index b444f0ae1e..e7496055ec 100644
--- a/core/os/dir_access.cpp
+++ b/core/os/dir_access.cpp
@@ -244,7 +244,7 @@ DirAccess *DirAccess::open(const String &p_path, Error *r_error) {
DirAccess *da = create_for_path(p_path);
- ERR_FAIL_COND_V(!da, NULL);
+ ERR_FAIL_COND_V_MSG(!da, NULL, "Cannot create DirAccess for path '" + p_path + "'.");
Error err = da->change_dir(p_path);
if (r_error)
*r_error = err;
@@ -384,39 +384,36 @@ Error DirAccess::_copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flag
String target_dir = p_to + rel_path;
if (!p_target_da->dir_exists(target_dir)) {
Error err = p_target_da->make_dir(target_dir);
- ERR_FAIL_COND_V(err, err);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot create directory '" + target_dir + "'.");
}
Error err = change_dir(E->get());
- ERR_FAIL_COND_V(err, err);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot change current directory to '" + E->get() + "'.");
+
err = _copy_dir(p_target_da, p_to + rel_path + "/", p_chmod_flags);
if (err) {
change_dir("..");
- ERR_PRINT("Failed to copy recursively");
- return err;
+ ERR_FAIL_V_MSG(err, "Failed to copy recursively.");
}
err = change_dir("..");
- if (err) {
- ERR_PRINT("Failed to go back");
- return err;
- }
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to go back.");
}
return OK;
}
Error DirAccess::copy_dir(String p_from, String p_to, int p_chmod_flags) {
- ERR_FAIL_COND_V(!dir_exists(p_from), ERR_FILE_NOT_FOUND);
+ ERR_FAIL_COND_V_MSG(!dir_exists(p_from), ERR_FILE_NOT_FOUND, "Source directory doesn't exist.");
DirAccess *target_da = DirAccess::create_for_path(p_to);
- ERR_FAIL_COND_V(!target_da, ERR_CANT_CREATE);
+ ERR_FAIL_COND_V_MSG(!target_da, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_to + "'.");
if (!target_da->dir_exists(p_to)) {
Error err = target_da->make_dir_recursive(p_to);
if (err) {
memdelete(target_da);
}
- ERR_FAIL_COND_V(err, err);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot create directory '" + p_to + "'.");
}
if (!p_to.ends_with("/")) {
diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp
index 9a8315a3bb..738e597730 100644
--- a/core/os/file_access.cpp
+++ b/core/os/file_access.cpp
@@ -498,7 +498,7 @@ uint64_t FileAccess::get_modified_time(const String &p_file) {
return 0;
FileAccess *fa = create_for_path(p_file);
- ERR_FAIL_COND_V(!fa, 0);
+ ERR_FAIL_COND_V_MSG(!fa, 0, "Cannot create FileAccess for path '" + p_file + "'.");
uint64_t mt = fa->_get_modified_time(p_file);
memdelete(fa);
@@ -511,7 +511,7 @@ uint32_t FileAccess::get_unix_permissions(const String &p_file) {
return 0;
FileAccess *fa = create_for_path(p_file);
- ERR_FAIL_COND_V(!fa, 0);
+ ERR_FAIL_COND_V_MSG(!fa, 0, "Cannot create FileAccess for path '" + p_file + "'.");
uint32_t mt = fa->_get_unix_permissions(p_file);
memdelete(fa);
@@ -521,7 +521,7 @@ uint32_t FileAccess::get_unix_permissions(const String &p_file) {
Error FileAccess::set_unix_permissions(const String &p_file, uint32_t p_permissions) {
FileAccess *fa = create_for_path(p_file);
- ERR_FAIL_COND_V(!fa, ERR_CANT_CREATE);
+ ERR_FAIL_COND_V_MSG(!fa, ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'.");
Error err = fa->_set_unix_permissions(p_file, p_permissions);
memdelete(fa);
@@ -599,7 +599,7 @@ Vector<uint8_t> FileAccess::get_file_as_array(const String &p_path, Error *r_err
if (r_error) { // if error requested, do not throw error
return Vector<uint8_t>();
}
- ERR_FAIL_V_MSG(Vector<uint8_t>(), "Can't open file from path: " + String(p_path) + ".");
+ ERR_FAIL_V_MSG(Vector<uint8_t>(), "Can't open file from path '" + String(p_path) + "'.");
}
Vector<uint8_t> data;
data.resize(f->get_len());
@@ -619,7 +619,7 @@ String FileAccess::get_file_as_string(const String &p_path, Error *r_error) {
if (r_error) {
return String();
}
- ERR_FAIL_V_MSG(String(), "Can't get file as string from path: " + String(p_path) + ".");
+ ERR_FAIL_V_MSG(String(), "Can't get file as string from path '" + String(p_path) + "'.");
}
String ret;
diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp
index 5587e827ba..146a301995 100644
--- a/core/os/main_loop.cpp
+++ b/core/os/main_loop.cpp
@@ -65,6 +65,8 @@ void MainLoop::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_OS_IME_UPDATE);
BIND_CONSTANT(NOTIFICATION_APP_RESUMED);
BIND_CONSTANT(NOTIFICATION_APP_PAUSED);
+
+ ADD_SIGNAL(MethodInfo("on_request_permissions_result", PropertyInfo(Variant::STRING, "permission"), PropertyInfo(Variant::BOOL, "granted")));
};
void MainLoop::set_init_script(const Ref<Script> &p_init_script) {
diff --git a/core/os/memory.h b/core/os/memory.h
index 8778cb63ad..a68a359546 100644
--- a/core/os/memory.h
+++ b/core/os/memory.h
@@ -31,6 +31,7 @@
#ifndef MEMORY_H
#define MEMORY_H
+#include "core/error_macros.h"
#include "core/safe_refcount.h"
#include <stddef.h>
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 7531900480..b44487b908 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -722,7 +722,7 @@ int OS::get_audio_driver_count() const {
const char *OS::get_audio_driver_name(int p_driver) const {
AudioDriver *driver = AudioDriverManager::get_driver(p_driver);
- ERR_FAIL_COND_V(!driver, "");
+ ERR_FAIL_COND_V_MSG(!driver, "", "Cannot get audio driver at index '" + itos(p_driver) + "'.");
return AudioDriverManager::get_driver(p_driver)->get_name();
}
diff --git a/core/os/os.h b/core/os/os.h
index 9b46b43081..b5224c4f63 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -530,6 +530,8 @@ public:
List<String> get_restart_on_exit_arguments() const;
virtual bool request_permission(const String &p_name) { return true; }
+ virtual bool request_permissions() { return true; }
+ virtual Vector<String> get_granted_permissions() const { return Vector<String>(); }
virtual void process_and_drop_events() {}
OS();
diff --git a/core/packed_data_container.cpp b/core/packed_data_container.cpp
index 54bf12b314..003e7e7428 100644
--- a/core/packed_data_container.cpp
+++ b/core/packed_data_container.cpp
@@ -119,7 +119,7 @@ Variant PackedDataContainer::_get_at_ofs(uint32_t p_ofs, const uint8_t *p_buf, b
if (rerr != OK) {
err = true;
- ERR_FAIL_COND_V(err != OK, Variant());
+ ERR_FAIL_COND_V_MSG(err != OK, Variant(), "Error when trying to decode Variant.");
}
return v;
}
diff --git a/core/pool_vector.h b/core/pool_vector.h
index 957a72483c..fbd4d630be 100644
--- a/core/pool_vector.h
+++ b/core/pool_vector.h
@@ -508,7 +508,7 @@ T PoolVector<T>::operator[](int p_index) const {
template <class T>
Error PoolVector<T>::resize(int p_size) {
- ERR_FAIL_COND_V(p_size < 0, ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V_MSG(p_size < 0, ERR_INVALID_PARAMETER, "Size of PoolVector cannot be negative.");
if (alloc == NULL) {
@@ -536,7 +536,7 @@ Error PoolVector<T>::resize(int p_size) {
} else {
- ERR_FAIL_COND_V(alloc->lock > 0, ERR_LOCKED); //can't resize if locked!
+ ERR_FAIL_COND_V_MSG(alloc->lock > 0, ERR_LOCKED, "Can't resize PoolVector if locked."); //can't resize if locked!
}
size_t new_size = sizeof(T) * p_size;
diff --git a/core/project_settings.cpp b/core/project_settings.cpp
index ec2c5ecbb3..c2241ed926 100644
--- a/core/project_settings.cpp
+++ b/core/project_settings.cpp
@@ -113,12 +113,12 @@ String ProjectSettings::localize_path(const String &p_path) const {
void ProjectSettings::set_initial_value(const String &p_name, const Variant &p_value) {
- ERR_FAIL_COND(!props.has(p_name));
+ ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + ".");
props[p_name].initial = p_value;
}
void ProjectSettings::set_restart_if_changed(const String &p_name, bool p_restart) {
- ERR_FAIL_COND(!props.has(p_name));
+ ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + ".");
props[p_name].restart_if_changed = p_restart;
}
@@ -264,12 +264,12 @@ void ProjectSettings::_get_property_list(List<PropertyInfo> *p_list) const {
}
}
-bool ProjectSettings::_load_resource_pack(const String &p_pack) {
+bool ProjectSettings::_load_resource_pack(const String &p_pack, bool p_replace_files) {
if (PackedData::get_singleton()->is_disabled())
return false;
- bool ok = PackedData::get_singleton()->add_pack(p_pack) == OK;
+ bool ok = PackedData::get_singleton()->add_pack(p_pack, p_replace_files) == OK;
if (!ok)
return false;
@@ -336,7 +336,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
if (p_main_pack != "") {
bool ok = _load_resource_pack(p_main_pack);
- ERR_FAIL_COND_V(!ok, ERR_CANT_OPEN);
+ ERR_FAIL_COND_V_MSG(!ok, ERR_CANT_OPEN, "Cannot open resource pack '" + p_main_pack + "'.");
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
if (err == OK) {
@@ -421,7 +421,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
// or, if requested (`p_upwards`) in parent directories.
DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- ERR_FAIL_COND_V(!d, ERR_CANT_CREATE);
+ ERR_FAIL_COND_V_MSG(!d, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_path + "'.");
d->change_dir(p_path);
String current_dir = d->get_current_dir();
@@ -609,19 +609,19 @@ Error ProjectSettings::_load_settings_text_or_binary(const String &p_text_path,
int ProjectSettings::get_order(const String &p_name) const {
- ERR_FAIL_COND_V(!props.has(p_name), -1);
+ ERR_FAIL_COND_V_MSG(!props.has(p_name), -1, "Request for nonexistent project setting: " + p_name + ".");
return props[p_name].order;
}
void ProjectSettings::set_order(const String &p_name, int p_order) {
- ERR_FAIL_COND(!props.has(p_name));
+ ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + ".");
props[p_name].order = p_order;
}
void ProjectSettings::set_builtin_order(const String &p_name) {
- ERR_FAIL_COND(!props.has(p_name));
+ ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + ".");
if (props[p_name].order >= NO_BUILTIN_ORDER_BASE) {
props[p_name].order = last_builtin_order++;
}
@@ -629,7 +629,7 @@ void ProjectSettings::set_builtin_order(const String &p_name) {
void ProjectSettings::clear(const String &p_name) {
- ERR_FAIL_COND(!props.has(p_name));
+ ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + ".");
props.erase(p_name);
}
@@ -706,7 +706,7 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str
err = encode_variant(value, NULL, len, true);
if (err != OK)
memdelete(file);
- ERR_FAIL_COND_V(err != OK, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V_MSG(err != OK, ERR_INVALID_DATA, "Error when trying to encode Variant.");
Vector<uint8_t> buff;
buff.resize(len);
@@ -714,7 +714,7 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str
err = encode_variant(value, buff.ptrw(), len, true);
if (err != OK)
memdelete(file);
- ERR_FAIL_COND_V(err != OK, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V_MSG(err != OK, ERR_INVALID_DATA, "Error when trying to encode Variant.");
file->store_32(len);
file->store_buffer(buff.ptr(), buff.size());
}
@@ -787,7 +787,7 @@ Error ProjectSettings::_save_custom_bnd(const String &p_file) { // add other par
Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_custom, const Vector<String> &p_custom_features, bool p_merge_with_current) {
- ERR_FAIL_COND_V(p_path == "", ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V_MSG(p_path == "", ERR_INVALID_PARAMETER, "Project settings save path cannot be empty.");
Set<_VCSort> vclist;
@@ -979,7 +979,7 @@ void ProjectSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("localize_path", "path"), &ProjectSettings::localize_path);
ClassDB::bind_method(D_METHOD("globalize_path", "path"), &ProjectSettings::globalize_path);
ClassDB::bind_method(D_METHOD("save"), &ProjectSettings::save);
- ClassDB::bind_method(D_METHOD("load_resource_pack", "pack"), &ProjectSettings::_load_resource_pack);
+ ClassDB::bind_method(D_METHOD("load_resource_pack", "pack", "replace_files"), &ProjectSettings::_load_resource_pack, DEFVAL(true));
ClassDB::bind_method(D_METHOD("property_can_revert", "name"), &ProjectSettings::property_can_revert);
ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &ProjectSettings::property_get_revert);
diff --git a/core/project_settings.h b/core/project_settings.h
index a8deab028c..b32470361b 100644
--- a/core/project_settings.h
+++ b/core/project_settings.h
@@ -104,7 +104,7 @@ protected:
void _convert_to_last_version(int p_from_version);
- bool _load_resource_pack(const String &p_pack);
+ bool _load_resource_pack(const String &p_pack, bool p_replace_files = true);
void _add_property_info_bind(const Dictionary &p_info);
diff --git a/core/reference.cpp b/core/reference.cpp
index 1984af9a34..92bbdacd5d 100644
--- a/core/reference.cpp
+++ b/core/reference.cpp
@@ -36,12 +36,7 @@ bool Reference::init_ref() {
if (reference()) {
- // this may fail in the scenario of two threads assigning the pointer for the FIRST TIME
- // at the same time, which is never likely to happen (would be crazy to do)
- // so don't do it.
-
- if (refcount_init.get() > 0) {
- refcount_init.unref();
+ if (!is_referenced() && refcount_init.unref()) {
unreference(); // first referencing is already 1, so compensate for the ref above
}
@@ -64,9 +59,11 @@ int Reference::reference_get_count() const {
}
bool Reference::reference() {
- bool success = refcount.ref();
- if (success && refcount.get() <= 2 /* higher is not relevant */) {
+ uint32_t rc_val = refcount.refval();
+ bool success = rc_val != 0;
+
+ if (success && rc_val <= 2 /* higher is not relevant */) {
if (get_script_instance()) {
get_script_instance()->refcount_incremented();
}
@@ -84,9 +81,10 @@ bool Reference::reference() {
bool Reference::unreference() {
- bool die = refcount.unref();
+ uint32_t rc_val = refcount.unrefval();
+ bool die = rc_val == 0;
- if (refcount.get() <= 1 /* higher is not relevant */) {
+ if (rc_val <= 1 /* higher is not relevant */) {
if (get_script_instance()) {
bool script_ret = get_script_instance()->refcount_decremented();
die = die && script_ret;
diff --git a/core/reference.h b/core/reference.h
index 20ee22ddfc..b8d00a94ad 100644
--- a/core/reference.h
+++ b/core/reference.h
@@ -47,7 +47,7 @@ protected:
static void _bind_methods();
public:
- _FORCE_INLINE_ bool is_referenced() const { return refcount_init.get() < 1; }
+ _FORCE_INLINE_ bool is_referenced() const { return refcount_init.get() != 1; }
bool init_ref();
bool reference(); // returns false if refcount is at zero and didn't get increased
bool unreference();
diff --git a/core/resource.cpp b/core/resource.cpp
index 5a5efa4644..e0a40b6f3c 100644
--- a/core/resource.cpp
+++ b/core/resource.cpp
@@ -75,7 +75,7 @@ void Resource::set_path(const String &p_path, bool p_take_over) {
bool exists = ResourceCache::resources.has(p_path);
ResourceCache::lock->read_unlock();
- ERR_FAIL_COND_MSG(exists, "Another resource is loaded from path: " + p_path + " (possible cyclic resource inclusion).");
+ ERR_FAIL_COND_MSG(exists, "Another resource is loaded from path '" + p_path + "' (possible cyclic resource inclusion).");
}
}
path_cache = p_path;
@@ -365,17 +365,38 @@ bool Resource::is_translation_remapped() const {
//helps keep IDs same number when loading/saving scenes. -1 clears ID and it Returns -1 when no id stored
void Resource::set_id_for_path(const String &p_path, int p_id) {
if (p_id == -1) {
- id_for_path.erase(p_path);
+ if (ResourceCache::path_cache_lock) {
+ ResourceCache::path_cache_lock->write_lock();
+ }
+ ResourceCache::resource_path_cache[p_path].erase(get_path());
+ if (ResourceCache::path_cache_lock) {
+ ResourceCache::path_cache_lock->write_unlock();
+ }
} else {
- id_for_path[p_path] = p_id;
+ if (ResourceCache::path_cache_lock) {
+ ResourceCache::path_cache_lock->write_lock();
+ }
+ ResourceCache::resource_path_cache[p_path][get_path()] = p_id;
+ if (ResourceCache::path_cache_lock) {
+ ResourceCache::path_cache_lock->write_unlock();
+ }
}
}
int Resource::get_id_for_path(const String &p_path) const {
-
- if (id_for_path.has(p_path)) {
- return id_for_path[p_path];
+ if (ResourceCache::path_cache_lock) {
+ ResourceCache::path_cache_lock->read_lock();
+ }
+ if (ResourceCache::resource_path_cache[p_path].has(get_path())) {
+ int result = ResourceCache::resource_path_cache[p_path][get_path()];
+ if (ResourceCache::path_cache_lock) {
+ ResourceCache::path_cache_lock->read_unlock();
+ }
+ return result;
} else {
+ if (ResourceCache::path_cache_lock) {
+ ResourceCache::path_cache_lock->read_unlock();
+ }
return -1;
}
}
@@ -430,12 +451,21 @@ Resource::~Resource() {
}
HashMap<String, Resource *> ResourceCache::resources;
+#ifdef TOOLS_ENABLED
+HashMap<String, HashMap<String, int> > ResourceCache::resource_path_cache;
+#endif
RWLock *ResourceCache::lock = NULL;
+#ifdef TOOLS_ENABLED
+RWLock *ResourceCache::path_cache_lock = NULL;
+#endif
void ResourceCache::setup() {
lock = RWLock::create();
+#ifdef TOOLS_ENABLED
+ path_cache_lock = RWLock::create();
+#endif
}
void ResourceCache::clear() {
@@ -509,7 +539,7 @@ void ResourceCache::dump(const char *p_file, bool p_short) {
FileAccess *f = NULL;
if (p_file) {
f = FileAccess::open(p_file, FileAccess::WRITE);
- ERR_FAIL_COND(!f);
+ ERR_FAIL_COND_MSG(!f, "Cannot create file at path '" + String(p_file) + "'.");
}
const String *K = NULL;
diff --git a/core/resource.h b/core/resource.h
index 038b4f6278..3e1fe07137 100644
--- a/core/resource.h
+++ b/core/resource.h
@@ -84,9 +84,7 @@ protected:
void _set_path(const String &p_path);
void _take_over_path(const String &p_path);
-#ifdef TOOLS_ENABLED
- Map<String, int> id_for_path;
-#endif
+
public:
static Node *(*_get_local_scene_func)(); //used by editor
@@ -152,6 +150,10 @@ class ResourceCache {
friend class ResourceLoader; //need the lock
static RWLock *lock;
static HashMap<String, Resource *> resources;
+#ifdef TOOLS_ENABLED
+ static HashMap<String, HashMap<String, int> > resource_path_cache; // each tscn has a set of resource paths and IDs
+ static RWLock *path_cache_lock;
+#endif // TOOLS_ENABLED
friend void unregister_core_types();
static void clear();
friend void register_core_types();
diff --git a/core/safe_refcount.h b/core/safe_refcount.h
index 54f540b0c7..47161eed57 100644
--- a/core/safe_refcount.h
+++ b/core/safe_refcount.h
@@ -177,12 +177,12 @@ struct SafeRefCount {
public:
// destroy() is called when weak_count_ drops to zero.
- _ALWAYS_INLINE_ bool ref() { //true on success
+ _ALWAYS_INLINE_ bool ref() { // true on success
return atomic_conditional_increment(&count) != 0;
}
- _ALWAYS_INLINE_ uint32_t refval() { //true on success
+ _ALWAYS_INLINE_ uint32_t refval() { // none-zero on success
return atomic_conditional_increment(&count);
}
@@ -192,6 +192,11 @@ public:
return atomic_decrement(&count) == 0;
}
+ _ALWAYS_INLINE_ uint32_t unrefval() { // 0 if must be disposed of
+
+ return atomic_decrement(&count);
+ }
+
_ALWAYS_INLINE_ uint32_t get() const { // nothrow
return count;
diff --git a/core/self_list.h b/core/self_list.h
index 314d440977..07abcd1d53 100644
--- a/core/self_list.h
+++ b/core/self_list.h
@@ -31,6 +31,7 @@
#ifndef SELF_LIST_H
#define SELF_LIST_H
+#include "core/error_macros.h"
#include "core/typedefs.h"
template <class T>
diff --git a/core/sort_array.h b/core/sort_array.h
index 8660ee3333..d330e0c647 100644
--- a/core/sort_array.h
+++ b/core/sort_array.h
@@ -31,6 +31,7 @@
#ifndef SORT_ARRAY_H
#define SORT_ARRAY_H
+#include "core/error_macros.h"
#include "core/typedefs.h"
#define ERR_BAD_COMPARE(cond) \
diff --git a/core/string_builder.cpp b/core/string_builder.cpp
index 35526e0d70..22eed70f8b 100644
--- a/core/string_builder.cpp
+++ b/core/string_builder.cpp
@@ -34,6 +34,9 @@
StringBuilder &StringBuilder::append(const String &p_string) {
+ if (p_string == String())
+ return *this;
+
strings.push_back(p_string);
appended_strings.push_back(-1);
diff --git a/core/typedefs.h b/core/typedefs.h
index 660139b90a..767a97ac38 100644
--- a/core/typedefs.h
+++ b/core/typedefs.h
@@ -108,7 +108,6 @@ T *_nullptr() {
#include "core/int_types.h"
#include "core/error_list.h"
-#include "core/error_macros.h"
/** Generic ABS function, for math uses please use Math::abs */
diff --git a/core/ustring.cpp b/core/ustring.cpp
index 07caa3a018..f029ae4200 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -3288,9 +3288,7 @@ String String::simplify_path() const {
static int _humanize_digits(int p_num) {
- if (p_num < 10)
- return 2;
- else if (p_num < 100)
+ if (p_num < 100)
return 2;
else if (p_num < 1024)
return 1;
@@ -3298,7 +3296,7 @@ static int _humanize_digits(int p_num) {
return 0;
}
-String String::humanize_size(size_t p_size) {
+String String::humanize_size(uint64_t p_size) {
uint64_t _div = 1;
Vector<String> prefixes;
diff --git a/core/ustring.h b/core/ustring.h
index 87a14bfad7..15e2c07d9f 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -322,7 +322,7 @@ public:
String path_to_file(const String &p_path) const;
String get_base_dir() const;
String get_file() const;
- static String humanize_size(size_t p_size);
+ static String humanize_size(uint64_t p_size);
String simplify_path() const;
String xml_escape(bool p_escape_quotes = false) const;
diff --git a/core/variant.cpp b/core/variant.cpp
index 16bbf94c54..e0cc6685f4 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -3299,7 +3299,7 @@ String vformat(const String &p_text, const Variant &p1, const Variant &p2, const
bool error = false;
String fmt = p_text.sprintf(args, &error);
- ERR_FAIL_COND_V(error, String());
+ ERR_FAIL_COND_V_MSG(error, String(), fmt);
return fmt;
}
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 53f64fcde6..40b944744b 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -284,6 +284,7 @@ struct _VariantCall {
VCALL_LOCALMEM0R(String, sha1_buffer);
VCALL_LOCALMEM0R(String, sha256_buffer);
VCALL_LOCALMEM0R(String, empty);
+ VCALL_LOCALMEM1R(String, humanize_size);
VCALL_LOCALMEM0R(String, is_abs_path);
VCALL_LOCALMEM0R(String, is_rel_path);
VCALL_LOCALMEM0R(String, get_base_dir);
@@ -315,6 +316,10 @@ struct _VariantCall {
static void _call_String_to_ascii(Variant &r_ret, Variant &p_self, const Variant **p_args) {
String *s = reinterpret_cast<String *>(p_self._data._mem);
+ if (s->empty()) {
+ r_ret = PoolByteArray();
+ return;
+ }
CharString charstr = s->ascii();
PoolByteArray retval;
@@ -330,6 +335,10 @@ struct _VariantCall {
static void _call_String_to_utf8(Variant &r_ret, Variant &p_self, const Variant **p_args) {
String *s = reinterpret_cast<String *>(p_self._data._mem);
+ if (s->empty()) {
+ r_ret = PoolByteArray();
+ return;
+ }
CharString charstr = s->utf8();
PoolByteArray retval;
@@ -544,7 +553,7 @@ struct _VariantCall {
PoolByteArray *ba = reinterpret_cast<PoolByteArray *>(p_self._data._mem);
String s;
- if (ba->size() >= 0) {
+ if (ba->size() > 0) {
PoolByteArray::Read r = ba->read();
CharString cs;
cs.resize(ba->size() + 1);
@@ -560,7 +569,7 @@ struct _VariantCall {
PoolByteArray *ba = reinterpret_cast<PoolByteArray *>(p_self._data._mem);
String s;
- if (ba->size() >= 0) {
+ if (ba->size() > 0) {
PoolByteArray::Read r = ba->read();
s.parse_utf8((const char *)r.ptr(), ba->size());
}
@@ -571,14 +580,15 @@ struct _VariantCall {
PoolByteArray *ba = reinterpret_cast<PoolByteArray *>(p_self._data._mem);
PoolByteArray compressed;
- Compression::Mode mode = (Compression::Mode)(int)(*p_args[0]);
+ if (ba->size() > 0) {
+ Compression::Mode mode = (Compression::Mode)(int)(*p_args[0]);
- compressed.resize(Compression::get_max_compressed_buffer_size(ba->size(), mode));
- int result = Compression::compress(compressed.write().ptr(), ba->read().ptr(), ba->size(), mode);
-
- result = result >= 0 ? result : 0;
- compressed.resize(result);
+ compressed.resize(Compression::get_max_compressed_buffer_size(ba->size(), mode));
+ int result = Compression::compress(compressed.write().ptr(), ba->read().ptr(), ba->size(), mode);
+ result = result >= 0 ? result : 0;
+ compressed.resize(result);
+ }
r_ret = compressed;
}
@@ -590,9 +600,9 @@ struct _VariantCall {
int buffer_size = (int)(*p_args[0]);
- if (buffer_size < 0) {
+ if (buffer_size <= 0) {
r_ret = decompressed;
- ERR_FAIL_MSG("Decompression buffer size is less than zero.");
+ ERR_FAIL_MSG("Decompression buffer size must be greater than zero.");
}
decompressed.resize(buffer_size);
@@ -606,6 +616,10 @@ struct _VariantCall {
static void _call_PoolByteArray_hex_encode(Variant &r_ret, Variant &p_self, const Variant **p_args) {
PoolByteArray *ba = reinterpret_cast<PoolByteArray *>(p_self._data._mem);
+ if (ba->size() == 0) {
+ r_ret = String();
+ return;
+ }
PoolByteArray::Read r = ba->read();
String s = String::hex_encode_buffer(&r[0], ba->size());
r_ret = s;
@@ -1561,6 +1575,7 @@ void register_variant_methods() {
ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, sha1_buffer, varray());
ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, sha256_buffer, varray());
ADDFUNC0R(STRING, BOOL, String, empty, varray());
+ ADDFUNC1R(STRING, STRING, String, humanize_size, INT, "size", varray());
ADDFUNC0R(STRING, BOOL, String, is_abs_path, varray());
ADDFUNC0R(STRING, BOOL, String, is_rel_path, varray());
ADDFUNC0R(STRING, STRING, String, get_base_dir, varray());
diff --git a/core/vmap.h b/core/vmap.h
index fde9723d71..ed66b46993 100644
--- a/core/vmap.h
+++ b/core/vmap.h
@@ -196,8 +196,7 @@ public:
int pos = _find_exact(p_key);
if (pos < 0) {
- V val;
- pos = insert(p_key, val);
+ pos = insert(p_key, V());
}
return _cowdata.get_m(pos).value;