summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/SCsub1
-rw-r--r--core/array.cpp10
-rw-r--r--core/bind/core_bind.cpp36
-rw-r--r--core/class_db.cpp52
-rw-r--r--core/class_db.h7
-rw-r--r--core/color.cpp34
-rw-r--r--core/color.h4
-rw-r--r--core/command_queue_mt.h4
-rw-r--r--core/crypto/SCsub38
-rw-r--r--core/crypto/crypto.cpp170
-rw-r--r--core/crypto/crypto.h105
-rw-r--r--core/crypto/crypto_core.cpp (renamed from core/math/crypto_core.cpp)32
-rw-r--r--core/crypto/crypto_core.h (renamed from core/math/crypto_core.h)20
-rw-r--r--core/crypto/hashing_context.cpp137
-rw-r--r--core/crypto/hashing_context.h66
-rw-r--r--core/engine.cpp5
-rw-r--r--core/error_macros.h137
-rw-r--r--core/func_ref.cpp13
-rw-r--r--core/func_ref.h1
-rw-r--r--core/hash_map.h16
-rw-r--r--core/image.cpp96
-rw-r--r--core/image.h4
-rw-r--r--core/input_map.cpp5
-rw-r--r--core/io/config_file.cpp9
-rw-r--r--core/io/file_access_buffered.cpp12
-rw-r--r--core/io/file_access_buffered_fa.h5
-rw-r--r--core/io/file_access_compressed.cpp3
-rw-r--r--core/io/file_access_encrypted.cpp7
-rw-r--r--core/io/file_access_pack.cpp19
-rw-r--r--core/io/image_loader.h16
-rw-r--r--core/io/ip_address.cpp14
-rw-r--r--core/io/marshalls.cpp10
-rw-r--r--core/io/multiplayer_api.cpp162
-rw-r--r--core/io/packet_peer.cpp3
-rw-r--r--core/io/pck_packer.cpp5
-rw-r--r--core/io/resource_format_binary.cpp46
-rw-r--r--core/io/resource_loader.cpp45
-rw-r--r--core/io/resource_loader.h3
-rw-r--r--core/io/resource_saver.cpp9
-rw-r--r--core/io/resource_saver.h4
-rw-r--r--core/io/stream_peer_ssl.cpp68
-rw-r--r--core/io/stream_peer_ssl.h13
-rw-r--r--core/io/translation_loader_po.cpp25
-rw-r--r--core/io/xml_parser.cpp6
-rw-r--r--core/map.h4
-rw-r--r--core/math/SCsub33
-rw-r--r--core/math/a_star.cpp239
-rw-r--r--core/math/a_star.h27
-rw-r--r--core/math/basis.cpp5
-rw-r--r--core/math/basis.h4
-rw-r--r--core/math/bsp_tree.h4
-rw-r--r--core/math/camera_matrix.h4
-rw-r--r--core/math/delaunay.h4
-rw-r--r--core/math/expression.cpp11
-rw-r--r--core/math/geometry.h7
-rw-r--r--core/math/math_funcs.h12
-rw-r--r--core/math/octree.h9
-rw-r--r--core/math/quat.h4
-rw-r--r--core/math/transform.cpp5
-rw-r--r--core/math/transform.h5
-rw-r--r--core/math/vector2.cpp13
-rw-r--r--core/math/vector2.h24
-rw-r--r--core/math/vector3.h40
-rw-r--r--core/message_queue.cpp11
-rw-r--r--core/method_bind.h4
-rw-r--r--core/node_path.cpp3
-rw-r--r--core/node_path.h4
-rw-r--r--core/oa_hash_map.h34
-rw-r--r--core/object.cpp79
-rw-r--r--core/object.h9
-rw-r--r--core/os/dir_access.h16
-rw-r--r--core/os/file_access.cpp8
-rw-r--r--core/os/input.cpp1
-rw-r--r--core/os/input.h1
-rw-r--r--core/os/input_event.h4
-rw-r--r--core/os/keyboard.h4
-rw-r--r--core/os/main_loop.h4
-rw-r--r--core/os/memory.h4
-rw-r--r--core/os/os.cpp13
-rw-r--r--core/os/os.h5
-rw-r--r--core/os/semaphore.h4
-rw-r--r--core/os/thread.h4
-rw-r--r--core/pool_allocator.cpp11
-rw-r--r--core/pool_vector.cpp3
-rw-r--r--core/pool_vector.h10
-rw-r--r--core/project_settings.cpp26
-rw-r--r--core/project_settings.h4
-rw-r--r--core/reference.h3
-rw-r--r--core/register_core_types.cpp24
-rw-r--r--core/register_core_types.h4
-rw-r--r--core/resource.cpp8
-rw-r--r--core/resource.h4
-rw-r--r--core/rid.h4
-rw-r--r--core/safe_refcount.h16
-rw-r--r--core/script_debugger_remote.cpp80
-rw-r--r--core/script_debugger_remote.h6
-rw-r--r--core/script_language.h4
-rw-r--r--core/set.h4
-rw-r--r--core/string_name.h3
-rw-r--r--core/translation.cpp67
-rw-r--r--core/ustring.cpp17
-rw-r--r--core/ustring.h4
-rw-r--r--core/variant.cpp5
-rw-r--r--core/variant.h4
-rw-r--r--core/variant_call.cpp55
105 files changed, 1470 insertions, 1039 deletions
diff --git a/core/SCsub b/core/SCsub
index 85e5f1b089..ed9a0a231d 100644
--- a/core/SCsub
+++ b/core/SCsub
@@ -159,6 +159,7 @@ env.CommandNoCache('#core/license.gen.h', ["../COPYRIGHT.txt", "../LICENSE.txt"]
# Chain load SCsubs
SConscript('os/SCsub')
SConscript('math/SCsub')
+SConscript('crypto/SCsub')
SConscript('io/SCsub')
SConscript('bind/SCsub')
diff --git a/core/array.cpp b/core/array.cpp
index a334af2c04..108d9f7386 100644
--- a/core/array.cpp
+++ b/core/array.cpp
@@ -133,18 +133,12 @@ void Array::erase(const Variant &p_value) {
}
Variant Array::front() const {
- if (_p->array.size() == 0) {
- ERR_EXPLAIN("Can't take value from empty array");
- ERR_FAIL_V(Variant());
- }
+ ERR_FAIL_COND_V_MSG(_p->array.size() == 0, Variant(), "Can't take value from empty array.");
return operator[](0);
}
Variant Array::back() const {
- if (_p->array.size() == 0) {
- ERR_EXPLAIN("Can't take value from empty array");
- ERR_FAIL_V(Variant());
- }
+ ERR_FAIL_COND_V_MSG(_p->array.size() == 0, Variant(), "Can't take value from empty array.");
return operator[](_p->array.size() - 1);
}
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index b41b84ab1e..8e0d156438 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -30,11 +30,11 @@
#include "core_bind.h"
+#include "core/crypto/crypto_core.h"
#include "core/io/file_access_compressed.h"
#include "core/io/file_access_encrypted.h"
#include "core/io/json.h"
#include "core/io/marshalls.h"
-#include "core/math/crypto_core.h"
#include "core/math/geometry.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
@@ -73,10 +73,7 @@ RES _ResourceLoader::load(const String &p_path, const String &p_type_hint, bool
Error err = OK;
RES ret = ResourceLoader::load(p_path, p_type_hint, p_no_cache, &err);
- if (err != OK) {
- ERR_EXPLAIN("Error loading resource: '" + p_path + "'");
- ERR_FAIL_V(ret);
- }
+ ERR_FAIL_COND_V_MSG(err != OK, ret, "Error loading resource: '" + p_path + "'.");
return ret;
}
@@ -148,10 +145,7 @@ _ResourceLoader::_ResourceLoader() {
}
Error _ResourceSaver::save(const String &p_path, const RES &p_resource, SaverFlags p_flags) {
- if (p_resource.is_null()) {
- ERR_EXPLAIN("Can't save empty resource to path: " + String(p_path))
- ERR_FAIL_V(ERR_INVALID_PARAMETER);
- }
+ 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);
}
@@ -727,22 +721,16 @@ int64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const {
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
};
- ERR_EXPLAIN("Invalid second value of: " + itos(second));
- ERR_FAIL_COND_V(second > 59, 0);
+ ERR_FAIL_COND_V_MSG(second > 59, 0, "Invalid second value of: " + itos(second) + ".");
- ERR_EXPLAIN("Invalid minute value of: " + itos(minute));
- ERR_FAIL_COND_V(minute > 59, 0);
+ ERR_FAIL_COND_V_MSG(minute > 59, 0, "Invalid minute value of: " + itos(minute) + ".");
- ERR_EXPLAIN("Invalid hour value of: " + itos(hour));
- ERR_FAIL_COND_V(hour > 23, 0);
+ ERR_FAIL_COND_V_MSG(hour > 23, 0, "Invalid hour value of: " + itos(hour) + ".");
- ERR_EXPLAIN("Invalid month value of: " + itos(month));
- ERR_FAIL_COND_V(month > 12 || month == 0, 0);
+ 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_EXPLAIN("Invalid day value of: " + itos(day) + " which is larger than " + itos(MONTH_DAYS_TABLE[LEAPYEAR(year)][month - 1]) + " or 0");
- ERR_FAIL_COND_V(day > MONTH_DAYS_TABLE[LEAPYEAR(year)][month - 1] || day == 0, 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;
@@ -2621,8 +2609,7 @@ void _Thread::_start_func(void *ud) {
}
}
- ERR_EXPLAIN("Could not call function '" + t->target_method.operator String() + "'' starting thread ID: " + t->get_id() + " Reason: " + reason);
- ERR_FAIL();
+ ERR_FAIL_MSG("Could not call function '" + t->target_method.operator String() + "'' starting thread ID: " + t->get_id() + " Reason: " + reason + ".");
}
}
@@ -2704,10 +2691,7 @@ _Thread::_Thread() {
_Thread::~_Thread() {
- if (active) {
- ERR_EXPLAIN("Reference to a Thread object object was lost while the thread is still running...");
- }
- ERR_FAIL_COND(active);
+ ERR_FAIL_COND_MSG(active, "Reference to a Thread object object was lost while the thread is still running...");
}
/////////////////////////////////////
diff --git a/core/class_db.cpp b/core/class_db.cpp
index 49e3f94d8f..3ad59bc309 100644
--- a/core/class_db.cpp
+++ b/core/class_db.cpp
@@ -836,10 +836,7 @@ void ClassDB::add_signal(StringName p_class, const MethodInfo &p_signal) {
#ifdef DEBUG_METHODS_ENABLED
ClassInfo *check = type;
while (check) {
- if (check->signal_map.has(sname)) {
- ERR_EXPLAIN("Type " + String(p_class) + " already has signal: " + String(sname));
- ERR_FAIL();
- }
+ ERR_FAIL_COND_MSG(check->signal_map.has(sname), "Type " + String(p_class) + " already has signal: " + String(sname) + ".");
check = check->inherits_ptr;
}
#endif
@@ -924,16 +921,11 @@ void ClassDB::add_property(StringName p_class, const PropertyInfo &p_pinfo, cons
if (p_setter) {
mb_set = get_method(p_class, p_setter);
#ifdef DEBUG_METHODS_ENABLED
- if (!mb_set) {
- ERR_EXPLAIN("Invalid Setter: " + p_class + "::" + p_setter + " for property: " + p_pinfo.name);
- ERR_FAIL();
- } else {
- int exp_args = 1 + (p_index >= 0 ? 1 : 0);
- if (mb_set->get_argument_count() != exp_args) {
- ERR_EXPLAIN("Invalid Function for Setter: " + p_class + "::" + p_setter + " for property: " + p_pinfo.name);
- ERR_FAIL();
- }
- }
+
+ 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 + ".");
#endif
}
@@ -943,25 +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
- if (!mb_get) {
- ERR_EXPLAIN("Invalid Getter: " + p_class + "::" + p_getter + " for property: " + p_pinfo.name);
- ERR_FAIL();
- } else {
+ 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);
- if (mb_get->get_argument_count() != exp_args) {
- ERR_EXPLAIN("Invalid Function for Getter: " + p_class + "::" + p_getter + " for property: " + p_pinfo.name);
- ERR_FAIL();
- }
- }
+ 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 + ".");
#endif
}
#ifdef DEBUG_METHODS_ENABLED
- if (type->property_setget.has(p_pinfo.name)) {
- ERR_EXPLAIN("Object " + p_class + " already has property: " + p_pinfo.name);
- ERR_FAIL();
- }
+ ERR_FAIL_COND_MSG(type->property_setget.has(p_pinfo.name), "Object " + p_class + " already has property: " + p_pinfo.name + ".");
#endif
OBJTYPE_WLOCK
@@ -1240,32 +1222,26 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const c
#ifdef DEBUG_ENABLED
- if (has_method(instance_type, mdname)) {
- ERR_EXPLAIN("Class " + String(instance_type) + " already has a method " + String(mdname));
- ERR_FAIL_V(NULL);
- }
+ ERR_FAIL_COND_V_MSG(has_method(instance_type, mdname), NULL, "Class " + String(instance_type) + " already has a method " + String(mdname) + ".");
#endif
ClassInfo *type = classes.getptr(instance_type);
if (!type) {
- ERR_PRINTS("Couldn't bind method '" + mdname + "' for instance: " + instance_type);
memdelete(p_bind);
- ERR_FAIL_V(NULL);
+ 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_EXPLAIN("Method already bound: " + instance_type + "::" + mdname);
- ERR_FAIL_V(NULL);
+ 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_EXPLAIN("Method definition provides more arguments than the method actually has: " + instance_type + "::" + mdname);
- ERR_FAIL_V(NULL);
+ 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);
diff --git a/core/class_db.h b/core/class_db.h
index 3d9a695f02..092469beb7 100644
--- a/core/class_db.h
+++ b/core/class_db.h
@@ -35,10 +35,6 @@
#include "core/object.h"
#include "core/print_string.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
/** To bind more then 6 parameters include this:
* #include "core/method_bind_ext.gen.inc"
*/
@@ -310,8 +306,7 @@ public:
if (type->method_map.has(p_name)) {
memdelete(bind);
// overloading not supported
- ERR_EXPLAIN("Method already bound: " + instance_type + "::" + p_name);
- ERR_FAIL_V(NULL);
+ ERR_FAIL_V_MSG(NULL, "Method already bound: " + instance_type + "::" + p_name + ".");
}
type->method_map[p_name] = bind;
#ifdef DEBUG_METHODS_ENABLED
diff --git a/core/color.cpp b/core/color.cpp
index 1843532124..a54a3115cc 100644
--- a/core/color.cpp
+++ b/core/color.cpp
@@ -335,36 +335,23 @@ Color Color::html(const String &p_color) {
} else if (color.length() == 6) {
alpha = false;
} else {
- ERR_EXPLAIN("Invalid Color Code: " + p_color);
- ERR_FAIL_V(Color());
+ ERR_FAIL_V_MSG(Color(), "Invalid color code: " + p_color + ".");
}
int a = 255;
if (alpha) {
a = _parse_col(color, 0);
- if (a < 0) {
- ERR_EXPLAIN("Invalid Color Code: " + p_color);
- ERR_FAIL_V(Color());
- }
+ ERR_FAIL_COND_V_MSG(a < 0, Color(), "Invalid color code: " + p_color + ".");
}
int from = alpha ? 2 : 0;
int r = _parse_col(color, from + 0);
- if (r < 0) {
- ERR_EXPLAIN("Invalid Color Code: " + p_color);
- ERR_FAIL_V(Color());
- }
+ ERR_FAIL_COND_V_MSG(r < 0, Color(), "Invalid color code: " + p_color + ".");
int g = _parse_col(color, from + 2);
- if (g < 0) {
- ERR_EXPLAIN("Invalid Color Code: " + p_color);
- ERR_FAIL_V(Color());
- }
+ ERR_FAIL_COND_V_MSG(g < 0, Color(), "Invalid color code: " + p_color + ".");
int b = _parse_col(color, from + 4);
- if (b < 0) {
- ERR_EXPLAIN("Invalid Color Code: " + p_color);
- ERR_FAIL_V(Color());
- }
+ ERR_FAIL_COND_V_MSG(b < 0, Color(), "Invalid color code: " + p_color + ".");
return Color(r / 255.0, g / 255.0, b / 255.0, a / 255.0);
}
@@ -425,12 +412,8 @@ Color Color::named(const String &p_name) {
name = name.to_lower();
const Map<String, Color>::Element *color = _named_colors.find(name);
- if (color) {
- return color->value();
- } else {
- ERR_EXPLAIN("Invalid Color Name: " + p_name);
- ERR_FAIL_V(Color());
- }
+ ERR_FAIL_NULL_V_MSG(color, Color(), "Invalid color name: " + p_name + ".");
+ return color->value();
}
String _to_hex(float p_val) {
@@ -523,8 +506,7 @@ Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) const {
// FIXME: Remove once Godot 3.1 has been released
float Color::gray() const {
- ERR_EXPLAIN("Color.gray() is deprecated and will be removed in a future version. Use Color.get_v() for a better grayscale approximation.");
- WARN_DEPRECATED;
+ WARN_DEPRECATED_MSG("Color.gray() is deprecated and will be removed in a future version. Use Color.get_v() for a better grayscale approximation.");
return (r + g + b) / 3.0;
}
diff --git a/core/color.h b/core/color.h
index 77f95b5dc9..8fb78d1ced 100644
--- a/core/color.h
+++ b/core/color.h
@@ -33,9 +33,7 @@
#include "core/math/math_funcs.h"
#include "core/ustring.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
+
struct Color {
union {
diff --git a/core/command_queue_mt.h b/core/command_queue_mt.h
index 3789eda5db..98f5bc56d7 100644
--- a/core/command_queue_mt.h
+++ b/core/command_queue_mt.h
@@ -37,10 +37,6 @@
#include "core/simple_type.h"
#include "core/typedefs.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
#define COMMA(N) _COMMA_##N
#define _COMMA_0
#define _COMMA_1 ,
diff --git a/core/crypto/SCsub b/core/crypto/SCsub
new file mode 100644
index 0000000000..0a3f05d87a
--- /dev/null
+++ b/core/crypto/SCsub
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+Import('env')
+
+env_crypto = env.Clone()
+
+is_builtin = env["builtin_mbedtls"]
+has_module = env["module_mbedtls_enabled"]
+
+if is_builtin or not has_module:
+ # Use our headers for builtin or if the module is not going to be compiled.
+ # We decided not to depend on system mbedtls just for these few files that can
+ # be easily extracted.
+ env_crypto.Prepend(CPPPATH=["#thirdparty/mbedtls/include"])
+
+# MbedTLS core functions (for CryptoCore).
+# If the mbedtls module is compiled we don't need to add the .c files with our
+# custom config since they will be built by the module itself.
+# Only if the module is not enabled, we must compile here the required sources
+# to make a "light" build with only the necessary mbedtls files.
+if not has_module:
+ env_thirdparty = env_crypto.Clone()
+ env_thirdparty.disable_warnings()
+ # Custom config file
+ env_thirdparty.Append(CPPDEFINES=[('MBEDTLS_CONFIG_FILE', '\\"thirdparty/mbedtls/include/godot_core_mbedtls_config.h\\"')])
+ thirdparty_mbedtls_dir = "#thirdparty/mbedtls/library/"
+ thirdparty_mbedtls_sources = [
+ "aes.c",
+ "base64.c",
+ "md5.c",
+ "sha1.c",
+ "sha256.c",
+ "godot_core_mbedtls_platform.c"
+ ]
+ thirdparty_mbedtls_sources = [thirdparty_mbedtls_dir + file for file in thirdparty_mbedtls_sources]
+ env_thirdparty.add_source_files(env.core_sources, thirdparty_mbedtls_sources)
+
+env_crypto.add_source_files(env.core_sources, "*.cpp")
diff --git a/core/crypto/crypto.cpp b/core/crypto/crypto.cpp
new file mode 100644
index 0000000000..925a01b36a
--- /dev/null
+++ b/core/crypto/crypto.cpp
@@ -0,0 +1,170 @@
+/*************************************************************************/
+/* crypto.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "crypto.h"
+
+#include "core/engine.h"
+#include "core/io/certs_compressed.gen.h"
+#include "core/io/compression.h"
+
+/// Resources
+
+CryptoKey *(*CryptoKey::_create)() = NULL;
+CryptoKey *CryptoKey::create() {
+ if (_create)
+ return _create();
+ return NULL;
+}
+
+void CryptoKey::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("save", "path"), &CryptoKey::save);
+ ClassDB::bind_method(D_METHOD("load", "path"), &CryptoKey::load);
+}
+
+X509Certificate *(*X509Certificate::_create)() = NULL;
+X509Certificate *X509Certificate::create() {
+ if (_create)
+ return _create();
+ return NULL;
+}
+
+void X509Certificate::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("save", "path"), &X509Certificate::save);
+ ClassDB::bind_method(D_METHOD("load", "path"), &X509Certificate::load);
+}
+
+/// Crypto
+
+void (*Crypto::_load_default_certificates)(String p_path) = NULL;
+Crypto *(*Crypto::_create)() = NULL;
+Crypto *Crypto::create() {
+ if (_create)
+ return _create();
+ return memnew(Crypto);
+}
+
+void Crypto::load_default_certificates(String p_path) {
+
+ if (_load_default_certificates)
+ _load_default_certificates(p_path);
+}
+
+void Crypto::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("generate_random_bytes", "size"), &Crypto::generate_random_bytes);
+ ClassDB::bind_method(D_METHOD("generate_rsa", "size"), &Crypto::generate_rsa);
+ ClassDB::bind_method(D_METHOD("generate_self_signed_certificate", "key", "issuer_name", "not_before", "not_after"), &Crypto::generate_self_signed_certificate, DEFVAL("CN=myserver,O=myorganisation,C=IT"), DEFVAL("20140101000000"), DEFVAL("20340101000000"));
+}
+
+PoolByteArray Crypto::generate_random_bytes(int p_bytes) {
+ ERR_FAIL_V_MSG(PoolByteArray(), "generate_random_bytes is not available when mbedtls module is disabled.");
+}
+
+Ref<CryptoKey> Crypto::generate_rsa(int p_bytes) {
+ ERR_FAIL_V_MSG(NULL, "generate_rsa is not available when mbedtls module is disabled.");
+}
+
+Ref<X509Certificate> Crypto::generate_self_signed_certificate(Ref<CryptoKey> p_key, String p_issuer_name, String p_not_before, String p_not_after) {
+ ERR_FAIL_V_MSG(NULL, "generate_self_signed_certificate is not available when mbedtls module is disabled.");
+}
+
+Crypto::Crypto() {
+}
+
+/// Resource loader/saver
+
+RES ResourceFormatLoaderCrypto::load(const String &p_path, const String &p_original_path, Error *r_error) {
+
+ String el = p_path.get_extension().to_lower();
+ if (el == "crt") {
+ X509Certificate *cert = X509Certificate::create();
+ if (cert)
+ cert->load(p_path);
+ return cert;
+ } else if (el == "key") {
+ CryptoKey *key = CryptoKey::create();
+ if (key)
+ key->load(p_path);
+ return key;
+ }
+ return NULL;
+}
+
+void ResourceFormatLoaderCrypto::get_recognized_extensions(List<String> *p_extensions) const {
+
+ p_extensions->push_back("crt");
+ p_extensions->push_back("key");
+}
+
+bool ResourceFormatLoaderCrypto::handles_type(const String &p_type) const {
+
+ return p_type == "X509Certificate" || p_type == "CryptoKey";
+}
+
+String ResourceFormatLoaderCrypto::get_resource_type(const String &p_path) const {
+
+ String el = p_path.get_extension().to_lower();
+ if (el == "crt")
+ return "X509Certificate";
+ else if (el == "key")
+ return "CryptoKey";
+ return "";
+}
+
+Error ResourceFormatSaverCrypto::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
+
+ Error err;
+ Ref<X509Certificate> cert = p_resource;
+ Ref<CryptoKey> key = p_resource;
+ if (cert.is_valid()) {
+ err = cert->save(p_path);
+ } else if (key.is_valid()) {
+ err = key->save(p_path);
+ } else {
+ ERR_FAIL_V(ERR_INVALID_PARAMETER);
+ }
+ ERR_FAIL_COND_V(err != OK, err);
+ return OK;
+}
+
+void ResourceFormatSaverCrypto::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const {
+
+ const X509Certificate *cert = Object::cast_to<X509Certificate>(*p_resource);
+ const CryptoKey *key = Object::cast_to<CryptoKey>(*p_resource);
+ if (cert) {
+ p_extensions->push_back("crt");
+ }
+ if (key) {
+ p_extensions->push_back("key");
+ }
+}
+bool ResourceFormatSaverCrypto::recognize(const RES &p_resource) const {
+
+ return Object::cast_to<X509Certificate>(*p_resource) || Object::cast_to<CryptoKey>(*p_resource);
+}
diff --git a/core/crypto/crypto.h b/core/crypto/crypto.h
new file mode 100644
index 0000000000..2de81f5b57
--- /dev/null
+++ b/core/crypto/crypto.h
@@ -0,0 +1,105 @@
+/*************************************************************************/
+/* crypto.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef CRYPTO_H
+#define CRYPTO_H
+
+#include "core/reference.h"
+#include "core/resource.h"
+
+#include "core/io/resource_loader.h"
+#include "core/io/resource_saver.h"
+
+class CryptoKey : public Resource {
+ GDCLASS(CryptoKey, Resource);
+
+protected:
+ static void _bind_methods();
+ static CryptoKey *(*_create)();
+
+public:
+ static CryptoKey *create();
+ virtual Error load(String p_path) = 0;
+ virtual Error save(String p_path) = 0;
+};
+
+class X509Certificate : public Resource {
+ GDCLASS(X509Certificate, Resource);
+
+protected:
+ static void _bind_methods();
+ static X509Certificate *(*_create)();
+
+public:
+ static X509Certificate *create();
+ virtual Error load(String p_path) = 0;
+ virtual Error load_from_memory(const uint8_t *p_buffer, int p_len) = 0;
+ virtual Error save(String p_path) = 0;
+};
+
+class Crypto : public Reference {
+ GDCLASS(Crypto, Reference);
+
+protected:
+ static void _bind_methods();
+ static Crypto *(*_create)();
+ static void (*_load_default_certificates)(String p_path);
+
+public:
+ static Crypto *create();
+ static void load_default_certificates(String p_path);
+
+ virtual PoolByteArray generate_random_bytes(int p_bytes);
+ virtual Ref<CryptoKey> generate_rsa(int p_bytes);
+ virtual Ref<X509Certificate> generate_self_signed_certificate(Ref<CryptoKey> p_key, String p_issuer_name, String p_not_before, String p_not_after);
+
+ Crypto();
+};
+
+class ResourceFormatLoaderCrypto : public ResourceFormatLoader {
+ GDCLASS(ResourceFormatLoaderCrypto, ResourceFormatLoader);
+
+public:
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL);
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual bool handles_type(const String &p_type) const;
+ virtual String get_resource_type(const String &p_path) const;
+};
+
+class ResourceFormatSaverCrypto : public ResourceFormatSaver {
+ GDCLASS(ResourceFormatSaverCrypto, ResourceFormatSaver);
+
+public:
+ virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0);
+ virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const;
+ virtual bool recognize(const RES &p_resource) const;
+};
+
+#endif // CRYPTO_H
diff --git a/core/math/crypto_core.cpp b/core/crypto/crypto_core.cpp
index d7ba54e469..51c2e3c9e5 100644
--- a/core/math/crypto_core.cpp
+++ b/core/crypto/crypto_core.cpp
@@ -52,7 +52,7 @@ Error CryptoCore::MD5Context::start() {
return ret ? FAILED : OK;
}
-Error CryptoCore::MD5Context::update(uint8_t *p_src, size_t p_len) {
+Error CryptoCore::MD5Context::update(const uint8_t *p_src, size_t p_len) {
int ret = mbedtls_md5_update_ret((mbedtls_md5_context *)ctx, p_src, p_len);
return ret ? FAILED : OK;
}
@@ -62,6 +62,32 @@ Error CryptoCore::MD5Context::finish(unsigned char r_hash[16]) {
return ret ? FAILED : OK;
}
+// SHA1
+CryptoCore::SHA1Context::SHA1Context() {
+ ctx = memalloc(sizeof(mbedtls_sha1_context));
+ mbedtls_sha1_init((mbedtls_sha1_context *)ctx);
+}
+
+CryptoCore::SHA1Context::~SHA1Context() {
+ mbedtls_sha1_free((mbedtls_sha1_context *)ctx);
+ memfree((mbedtls_sha1_context *)ctx);
+}
+
+Error CryptoCore::SHA1Context::start() {
+ int ret = mbedtls_sha1_starts_ret((mbedtls_sha1_context *)ctx);
+ return ret ? FAILED : OK;
+}
+
+Error CryptoCore::SHA1Context::update(const uint8_t *p_src, size_t p_len) {
+ int ret = mbedtls_sha1_update_ret((mbedtls_sha1_context *)ctx, p_src, p_len);
+ return ret ? FAILED : OK;
+}
+
+Error CryptoCore::SHA1Context::finish(unsigned char r_hash[20]) {
+ int ret = mbedtls_sha1_finish_ret((mbedtls_sha1_context *)ctx, r_hash);
+ return ret ? FAILED : OK;
+}
+
// SHA256
CryptoCore::SHA256Context::SHA256Context() {
ctx = memalloc(sizeof(mbedtls_sha256_context));
@@ -78,12 +104,12 @@ Error CryptoCore::SHA256Context::start() {
return ret ? FAILED : OK;
}
-Error CryptoCore::SHA256Context::update(uint8_t *p_src, size_t p_len) {
+Error CryptoCore::SHA256Context::update(const uint8_t *p_src, size_t p_len) {
int ret = mbedtls_sha256_update_ret((mbedtls_sha256_context *)ctx, p_src, p_len);
return ret ? FAILED : OK;
}
-Error CryptoCore::SHA256Context::finish(unsigned char r_hash[16]) {
+Error CryptoCore::SHA256Context::finish(unsigned char r_hash[32]) {
int ret = mbedtls_sha256_finish_ret((mbedtls_sha256_context *)ctx, r_hash);
return ret ? FAILED : OK;
}
diff --git a/core/math/crypto_core.h b/core/crypto/crypto_core.h
index e28cb5a792..c859d612d4 100644
--- a/core/math/crypto_core.h
+++ b/core/crypto/crypto_core.h
@@ -46,10 +46,24 @@ public:
~MD5Context();
Error start();
- Error update(uint8_t *p_src, size_t p_len);
+ Error update(const uint8_t *p_src, size_t p_len);
Error finish(unsigned char r_hash[16]);
};
+ class SHA1Context {
+
+ private:
+ void *ctx; // To include, or not to include...
+
+ public:
+ SHA1Context();
+ ~SHA1Context();
+
+ Error start();
+ Error update(const uint8_t *p_src, size_t p_len);
+ Error finish(unsigned char r_hash[20]);
+ };
+
class SHA256Context {
private:
@@ -60,8 +74,8 @@ public:
~SHA256Context();
Error start();
- Error update(uint8_t *p_src, size_t p_len);
- Error finish(unsigned char r_hash[16]);
+ Error update(const uint8_t *p_src, size_t p_len);
+ Error finish(unsigned char r_hash[32]);
};
class AESContext {
diff --git a/core/crypto/hashing_context.cpp b/core/crypto/hashing_context.cpp
new file mode 100644
index 0000000000..bdccb258dd
--- /dev/null
+++ b/core/crypto/hashing_context.cpp
@@ -0,0 +1,137 @@
+/*************************************************************************/
+/* hashing_context.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "hashing_context.h"
+
+#include "core/crypto/crypto_core.h"
+
+Error HashingContext::start(HashType p_type) {
+ ERR_FAIL_COND_V(ctx != NULL, ERR_ALREADY_IN_USE);
+ _create_ctx(p_type);
+ ERR_FAIL_COND_V(ctx == NULL, ERR_UNAVAILABLE);
+ switch (type) {
+ case HASH_MD5:
+ return ((CryptoCore::MD5Context *)ctx)->start();
+ case HASH_SHA1:
+ return ((CryptoCore::SHA1Context *)ctx)->start();
+ case HASH_SHA256:
+ return ((CryptoCore::SHA256Context *)ctx)->start();
+ }
+ return ERR_UNAVAILABLE;
+}
+
+Error HashingContext::update(PoolByteArray p_chunk) {
+ ERR_FAIL_COND_V(ctx == NULL, ERR_UNCONFIGURED);
+ size_t len = p_chunk.size();
+ PoolByteArray::Read r = p_chunk.read();
+ switch (type) {
+ case HASH_MD5:
+ return ((CryptoCore::MD5Context *)ctx)->update(&r[0], len);
+ case HASH_SHA1:
+ return ((CryptoCore::SHA1Context *)ctx)->update(&r[0], len);
+ case HASH_SHA256:
+ return ((CryptoCore::SHA256Context *)ctx)->update(&r[0], len);
+ }
+ return ERR_UNAVAILABLE;
+}
+
+PoolByteArray HashingContext::finish() {
+ ERR_FAIL_COND_V(ctx == NULL, PoolByteArray());
+ PoolByteArray out;
+ Error err = FAILED;
+ switch (type) {
+ case HASH_MD5:
+ out.resize(16);
+ err = ((CryptoCore::MD5Context *)ctx)->finish(out.write().ptr());
+ break;
+ case HASH_SHA1:
+ out.resize(20);
+ err = ((CryptoCore::SHA1Context *)ctx)->finish(out.write().ptr());
+ break;
+ case HASH_SHA256:
+ out.resize(32);
+ err = ((CryptoCore::SHA256Context *)ctx)->finish(out.write().ptr());
+ break;
+ }
+ _delete_ctx();
+ ERR_FAIL_COND_V(err != OK, PoolByteArray());
+ return out;
+}
+
+void HashingContext::_create_ctx(HashType p_type) {
+ type = p_type;
+ switch (type) {
+ case HASH_MD5:
+ ctx = memnew(CryptoCore::MD5Context);
+ break;
+ case HASH_SHA1:
+ ctx = memnew(CryptoCore::SHA1Context);
+ break;
+ case HASH_SHA256:
+ ctx = memnew(CryptoCore::SHA256Context);
+ break;
+ default:
+ ctx = NULL;
+ }
+}
+
+void HashingContext::_delete_ctx() {
+ return;
+ switch (type) {
+ case HASH_MD5:
+ memdelete((CryptoCore::MD5Context *)ctx);
+ break;
+ case HASH_SHA1:
+ memdelete((CryptoCore::SHA1Context *)ctx);
+ break;
+ case HASH_SHA256:
+ memdelete((CryptoCore::SHA256Context *)ctx);
+ break;
+ }
+ ctx = NULL;
+}
+
+void HashingContext::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("start", "type"), &HashingContext::start);
+ ClassDB::bind_method(D_METHOD("update", "chunk"), &HashingContext::update);
+ ClassDB::bind_method(D_METHOD("finish"), &HashingContext::finish);
+ BIND_ENUM_CONSTANT(HASH_MD5);
+ BIND_ENUM_CONSTANT(HASH_SHA1);
+ BIND_ENUM_CONSTANT(HASH_SHA256);
+}
+
+HashingContext::HashingContext() {
+ ctx = NULL;
+}
+
+HashingContext::~HashingContext() {
+ if (ctx != NULL)
+ _delete_ctx();
+}
diff --git a/core/crypto/hashing_context.h b/core/crypto/hashing_context.h
new file mode 100644
index 0000000000..aa69636f2c
--- /dev/null
+++ b/core/crypto/hashing_context.h
@@ -0,0 +1,66 @@
+/*************************************************************************/
+/* hashing_context.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef HASHING_CONTEXT_H
+#define HASHING_CONTEXT_H
+
+#include "core/reference.h"
+
+class HashingContext : public Reference {
+ GDCLASS(HashingContext, Reference);
+
+public:
+ enum HashType {
+ HASH_MD5,
+ HASH_SHA1,
+ HASH_SHA256
+ };
+
+private:
+ void *ctx;
+ HashType type;
+
+protected:
+ static void _bind_methods();
+ void _create_ctx(HashType p_type);
+ void _delete_ctx();
+
+public:
+ Error start(HashType p_type);
+ Error update(PoolByteArray p_chunk);
+ PoolByteArray finish();
+
+ HashingContext();
+ ~HashingContext();
+};
+
+VARIANT_ENUM_CAST(HashingContext::HashType);
+
+#endif // HASHING_CONTEXT_H
diff --git a/core/engine.cpp b/core/engine.cpp
index 0dd0459403..937439faaf 100644
--- a/core/engine.cpp
+++ b/core/engine.cpp
@@ -197,10 +197,7 @@ void Engine::add_singleton(const Singleton &p_singleton) {
Object *Engine::get_singleton_object(const String &p_name) const {
const Map<StringName, Object *>::Element *E = singleton_ptrs.find(p_name);
- if (!E) {
- ERR_EXPLAIN("Failed to retrieve non-existent singleton '" + p_name + "'");
- ERR_FAIL_V(NULL);
- }
+ ERR_FAIL_COND_V_MSG(!E, NULL, "Failed to retrieve non-existent singleton '" + p_name + "'.");
return E->get();
};
diff --git a/core/error_macros.h b/core/error_macros.h
index 69874e280b..65802de9d2 100644
--- a/core/error_macros.h
+++ b/core/error_macros.h
@@ -140,6 +140,16 @@ extern bool _err_error_exists;
_err_error_exists = false; \
} while (0); // (*)
+#define ERR_FAIL_INDEX_MSG(m_index, m_size, m_msg) \
+ do { \
+ if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
+ ERR_EXPLAIN(m_msg); \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
+ return; \
+ } \
+ _err_error_exists = false; \
+ } while (0); // (*)
+
/** An index has failed if m_index<0 or m_index >=m_size, the function exits.
* This function returns an error value, if returning Error, please select the most
* appropriate error condition from error_macros.h
@@ -154,6 +164,16 @@ extern bool _err_error_exists;
_err_error_exists = false; \
} while (0); // (*)
+#define ERR_FAIL_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \
+ do { \
+ if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
+ ERR_EXPLAIN(m_msg); \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
+ return m_retval; \
+ } \
+ _err_error_exists = false; \
+ } while (0); // (*)
+
/** An index has failed if m_index >=m_size, the function exits.
* This function returns an error value, if returning Error, please select the most
* appropriate error condition from error_macros.h
@@ -168,6 +188,16 @@ extern bool _err_error_exists;
_err_error_exists = false; \
} while (0); // (*)
+#define ERR_FAIL_UNSIGNED_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \
+ do { \
+ if (unlikely((m_index) >= (m_size))) { \
+ ERR_EXPLAIN(m_msg); \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
+ return m_retval; \
+ } \
+ _err_error_exists = false; \
+ } while (0); // (*)
+
/** Use this one if there is no sensible fallback, that is, the error is unrecoverable.
* We'll return a null reference and try to keep running.
*/
@@ -179,6 +209,15 @@ extern bool _err_error_exists;
} \
} while (0); // (*)
+#define CRASH_BAD_INDEX_MSG(m_index, m_size, m_msg) \
+ do { \
+ if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
+ ERR_EXPLAIN(m_msg); \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), true); \
+ GENERATE_TRAP \
+ } \
+ } while (0); // (*)
+
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
* the function will exit.
*/
@@ -192,6 +231,16 @@ extern bool _err_error_exists;
_err_error_exists = false; \
}
+#define ERR_FAIL_NULL_MSG(m_param, m_msg) \
+ { \
+ if (unlikely(!m_param)) { \
+ ERR_EXPLAIN(m_msg); \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter ' " _STR(m_param) " ' is null."); \
+ return; \
+ } \
+ _err_error_exists = false; \
+ }
+
#define ERR_FAIL_NULL_V(m_param, m_retval) \
{ \
if (unlikely(!m_param)) { \
@@ -201,6 +250,16 @@ extern bool _err_error_exists;
_err_error_exists = false; \
}
+#define ERR_FAIL_NULL_V_MSG(m_param, m_retval, m_msg) \
+ { \
+ if (unlikely(!m_param)) { \
+ ERR_EXPLAIN(m_msg); \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter ' " _STR(m_param) " ' is null."); \
+ return m_retval; \
+ } \
+ _err_error_exists = false; \
+ }
+
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
* the function will exit.
*/
@@ -214,6 +273,16 @@ extern bool _err_error_exists;
_err_error_exists = false; \
}
+#define ERR_FAIL_COND_MSG(m_cond, m_msg) \
+ { \
+ if (unlikely(m_cond)) { \
+ ERR_EXPLAIN(m_msg); \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true."); \
+ return; \
+ } \
+ _err_error_exists = false; \
+ }
+
/** Use this one if there is no sensible fallback, that is, the error is unrecoverable.
*/
@@ -225,6 +294,15 @@ extern bool _err_error_exists;
} \
}
+#define CRASH_COND_MSG(m_cond, m_msg) \
+ { \
+ if (unlikely(m_cond)) { \
+ ERR_EXPLAIN(m_msg); \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition ' " _STR(m_cond) " ' is true."); \
+ GENERATE_TRAP \
+ } \
+ }
+
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
* the function will exit.
* This function returns an error value, if returning Error, please select the most
@@ -240,6 +318,16 @@ extern bool _err_error_exists;
_err_error_exists = false; \
}
+#define ERR_FAIL_COND_V_MSG(m_cond, m_retval, m_msg) \
+ { \
+ if (unlikely(m_cond)) { \
+ ERR_EXPLAIN(m_msg); \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. returned: " _STR(m_retval)); \
+ return m_retval; \
+ } \
+ _err_error_exists = false; \
+ }
+
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
* the loop will skip to the next iteration.
*/
@@ -253,6 +341,16 @@ extern bool _err_error_exists;
_err_error_exists = false; \
}
+#define ERR_CONTINUE_MSG(m_cond, m_msg) \
+ { \
+ if (unlikely(m_cond)) { \
+ ERR_EXPLAIN(m_msg); \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. Continuing..:"); \
+ continue; \
+ } \
+ _err_error_exists = false; \
+ }
+
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
* the loop will break
*/
@@ -266,6 +364,16 @@ extern bool _err_error_exists;
_err_error_exists = false; \
}
+#define ERR_BREAK_MSG(m_cond, m_msg) \
+ { \
+ if (unlikely(m_cond)) { \
+ ERR_EXPLAIN(m_msg); \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. Breaking..:"); \
+ break; \
+ } \
+ _err_error_exists = false; \
+ }
+
/** Print an error string and return
*/
@@ -276,6 +384,12 @@ extern bool _err_error_exists;
return; \
}
+#define ERR_FAIL_MSG(m_msg) \
+ { \
+ ERR_EXPLAIN(m_msg); \
+ ERR_FAIL(); \
+ }
+
/** Print an error string and return with value
*/
@@ -286,6 +400,12 @@ extern bool _err_error_exists;
return m_value; \
}
+#define ERR_FAIL_V_MSG(m_value, m_msg) \
+ { \
+ ERR_EXPLAIN(m_msg); \
+ ERR_FAIL_V(m_value); \
+ }
+
/** Use this one if there is no sensible fallback, that is, the error is unrecoverable.
*/
@@ -295,6 +415,12 @@ extern bool _err_error_exists;
GENERATE_TRAP \
}
+#define CRASH_NOW_MSG(m_msg) \
+ { \
+ ERR_EXPLAIN(m_msg); \
+ CRASH_NOW(); \
+ }
+
/** Print an error string.
*/
@@ -355,4 +481,15 @@ extern bool _err_error_exists;
} \
}
+#define WARN_DEPRECATED_MSG(m_msg) \
+ { \
+ static volatile bool warning_shown = false; \
+ if (!warning_shown) { \
+ ERR_EXPLAIN(m_msg); \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future", ERR_HANDLER_WARNING); \
+ _err_error_exists = false; \
+ warning_shown = true; \
+ } \
+ }
+
#endif
diff --git a/core/func_ref.cpp b/core/func_ref.cpp
index 3d03137d09..66ef27f6b9 100644
--- a/core/func_ref.cpp
+++ b/core/func_ref.cpp
@@ -46,6 +46,17 @@ Variant FuncRef::call_func(const Variant **p_args, int p_argcount, Variant::Call
return obj->call(function, p_args, p_argcount, r_error);
}
+Variant FuncRef::call_funcv(const Array &p_args) {
+
+ ERR_FAIL_COND_V(id == 0, Variant());
+
+ Object *obj = ObjectDB::get_instance(id);
+
+ ERR_FAIL_COND_V(!obj, Variant());
+
+ return obj->callv(function, p_args);
+}
+
void FuncRef::set_instance(Object *p_obj) {
ERR_FAIL_NULL(p_obj);
@@ -77,6 +88,8 @@ void FuncRef::_bind_methods() {
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call_func", &FuncRef::call_func, mi, defargs);
}
+ ClassDB::bind_method(D_METHOD("call_funcv", "arg_array"), &FuncRef::call_funcv);
+
ClassDB::bind_method(D_METHOD("set_instance", "instance"), &FuncRef::set_instance);
ClassDB::bind_method(D_METHOD("set_function", "name"), &FuncRef::set_function);
ClassDB::bind_method(D_METHOD("is_valid"), &FuncRef::is_valid);
diff --git a/core/func_ref.h b/core/func_ref.h
index a143b58bf0..af0bf63203 100644
--- a/core/func_ref.h
+++ b/core/func_ref.h
@@ -44,6 +44,7 @@ protected:
public:
Variant call_func(const Variant **p_args, int p_argcount, Variant::CallError &r_error);
+ Variant call_funcv(const Array &p_args);
void set_instance(Object *p_obj);
void set_function(const StringName &p_func);
bool is_valid() const;
diff --git a/core/hash_map.h b/core/hash_map.h
index 1513d7a65b..81ddc376d0 100644
--- a/core/hash_map.h
+++ b/core/hash_map.h
@@ -151,11 +151,7 @@ private:
return;
Element **new_hash_table = memnew_arr(Element *, ((uint64_t)1 << new_hash_table_power));
- if (!new_hash_table) {
-
- ERR_PRINT("Out of Memory");
- return;
- }
+ ERR_FAIL_COND_MSG(!new_hash_table, "Out of memory.");
for (int i = 0; i < (1 << new_hash_table_power); i++) {
@@ -208,10 +204,7 @@ private:
/* if element doesn't exist, create it */
Element *e = memnew(Element);
- if (!e) {
- ERR_EXPLAIN("Out of memory");
- ERR_FAIL_V(NULL);
- }
+ ERR_FAIL_COND_V_MSG(!e, NULL, "Out of memory.");
uint32_t hash = Hasher::hash(p_key);
uint32_t index = hash & ((1 << hash_table_power) - 1);
e->next = hash_table[index];
@@ -498,10 +491,7 @@ public:
} else { /* get the next key */
const Element *e = get_element(*p_key);
- if (!e) {
- ERR_EXPLAIN("Invalid key supplied")
- ERR_FAIL_V(NULL);
- }
+ ERR_FAIL_COND_V_MSG(!e, NULL, "Invalid key supplied.");
if (e->next) {
/* if there is a "next" in the list, return that */
return &e->next->pair.key;
diff --git a/core/image.cpp b/core/image.cpp
index 10778eced6..d8d667dbd5 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -83,6 +83,7 @@ const char *Image::format_names[Image::FORMAT_MAX] = {
};
SavePNGFunc Image::save_png_func = NULL;
+SaveEXRFunc Image::save_exr_func = NULL;
void Image::_put_pixelb(int p_x, int p_y, uint32_t p_pixelsize, uint8_t *p_data, const uint8_t *p_pixel) {
@@ -422,8 +423,7 @@ void Image::convert(Format p_new_format) {
if (format > FORMAT_RGBE9995 || p_new_format > FORMAT_RGBE9995) {
- ERR_EXPLAIN("Cannot convert to <-> from compressed formats. Use compress() and decompress() instead.");
- ERR_FAIL();
+ ERR_FAIL_MSG("Cannot convert to <-> from compressed formats. Use compress() and decompress() instead.");
} else if (format > FORMAT_RGBA8 || p_new_format > FORMAT_RGBA8) {
@@ -753,15 +753,14 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict
for (int32_t buffer_x = 0; buffer_x < dst_width; buffer_x++) {
- float src_real_x = buffer_x * x_scale;
- int32_t src_x = src_real_x;
-
- int32_t start_x = MAX(0, src_x - half_kernel + 1);
- int32_t end_x = MIN(src_width - 1, src_x + half_kernel);
+ // The corresponding point on the source image
+ float src_x = (buffer_x + 0.5f) * x_scale; // Offset by 0.5 so it uses the pixel's center
+ int32_t start_x = MAX(0, int32_t(src_x) - half_kernel + 1);
+ int32_t end_x = MIN(src_width - 1, int32_t(src_x) + half_kernel);
// Create the kernel used by all the pixels of the column
for (int32_t target_x = start_x; target_x <= end_x; target_x++)
- kernel[target_x - start_x] = _lanczos((src_real_x - target_x) / scale_factor);
+ kernel[target_x - start_x] = _lanczos((target_x + 0.5f - src_x) / scale_factor);
for (int32_t buffer_y = 0; buffer_y < src_height; buffer_y++) {
@@ -804,14 +803,12 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict
for (int32_t dst_y = 0; dst_y < dst_height; dst_y++) {
- float buffer_real_y = dst_y * y_scale;
- int32_t buffer_y = buffer_real_y;
-
- int32_t start_y = MAX(0, buffer_y - half_kernel + 1);
- int32_t end_y = MIN(src_height - 1, buffer_y + half_kernel);
+ float buffer_y = (dst_y + 0.5f) * y_scale;
+ int32_t start_y = MAX(0, int32_t(buffer_y) - half_kernel + 1);
+ int32_t end_y = MIN(src_height - 1, int32_t(buffer_y) + half_kernel);
for (int32_t target_y = start_y; target_y <= end_y; target_y++)
- kernel[target_y - start_y] = _lanczos((buffer_real_y - target_y) / scale_factor);
+ kernel[target_y - start_y] = _lanczos((target_y + 0.5f - buffer_y) / scale_factor);
for (int32_t dst_x = 0; dst_x < dst_width; dst_x++) {
@@ -866,10 +863,7 @@ bool Image::is_size_po2() const {
void Image::resize_to_po2(bool p_square) {
- if (!_can_modify(format)) {
- ERR_EXPLAIN("Cannot resize in indexed, compressed or custom image formats.");
- ERR_FAIL();
- }
+ ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot resize in indexed, compressed or custom image formats.");
int w = next_power_of_2(width);
int h = next_power_of_2(height);
@@ -885,15 +879,9 @@ void Image::resize_to_po2(bool p_square) {
void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
- if (data.size() == 0) {
- ERR_EXPLAIN("Cannot resize image before creating it, use create() or create_from_data() first.");
- ERR_FAIL();
- }
+ ERR_FAIL_COND_MSG(data.size() == 0, "Cannot resize image before creating it, use create() or create_from_data() first.");
- if (!_can_modify(format)) {
- ERR_EXPLAIN("Cannot resize in indexed, compressed or custom image formats.");
- ERR_FAIL();
- }
+ ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot resize in indexed, compressed or custom image formats.");
bool mipmap_aware = p_interpolation == INTERPOLATE_TRILINEAR /* || p_interpolation == INTERPOLATE_TRICUBIC */;
@@ -1106,10 +1094,8 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
void Image::crop_from_point(int p_x, int p_y, int p_width, int p_height) {
- if (!_can_modify(format)) {
- ERR_EXPLAIN("Cannot crop in indexed, compressed or custom image formats.");
- ERR_FAIL();
- }
+ ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot crop in indexed, compressed or custom image formats.");
+
ERR_FAIL_COND(p_x < 0);
ERR_FAIL_COND(p_y < 0);
ERR_FAIL_COND(p_width <= 0);
@@ -1163,10 +1149,7 @@ void Image::crop(int p_width, int p_height) {
void Image::flip_y() {
- if (!_can_modify(format)) {
- ERR_EXPLAIN("Cannot flip_y in indexed, compressed or custom image formats.");
- ERR_FAIL();
- }
+ ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot flip_y in indexed, compressed or custom image formats.");
bool used_mipmaps = has_mipmaps();
if (used_mipmaps) {
@@ -1199,10 +1182,7 @@ void Image::flip_y() {
void Image::flip_x() {
- if (!_can_modify(format)) {
- ERR_EXPLAIN("Cannot flip_x in indexed, compressed or custom image formats.");
- ERR_FAIL();
- }
+ ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot flip_x in indexed, compressed or custom image formats.");
bool used_mipmaps = has_mipmaps();
if (used_mipmaps) {
@@ -1461,15 +1441,9 @@ void Image::normalize() {
Error Image::generate_mipmaps(bool p_renormalize) {
- if (!_can_modify(format)) {
- ERR_EXPLAIN("Cannot generate mipmaps in indexed, compressed or custom image formats.");
- ERR_FAIL_V(ERR_UNAVAILABLE);
- }
+ ERR_FAIL_COND_V_MSG(!_can_modify(format), ERR_UNAVAILABLE, "Cannot generate mipmaps in indexed, compressed or custom image formats.");
- if (width == 0 || height == 0) {
- ERR_EXPLAIN("Cannot generate mipmaps with width or height equal to 0.");
- ERR_FAIL_V(ERR_UNCONFIGURED);
- }
+ ERR_FAIL_COND_V_MSG(width == 0 || height == 0, ERR_UNCONFIGURED, "Cannot generate mipmaps with width or height equal to 0.");
int mmcount;
@@ -1620,10 +1594,7 @@ void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_forma
int mm;
int size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0);
- if (size != p_data.size()) {
- ERR_EXPLAIN("Expected data size of " + itos(size) + " bytes in Image::create(), got instead " + itos(p_data.size()) + " bytes.");
- ERR_FAIL_COND(p_data.size() != size);
- }
+ ERR_FAIL_COND_MSG(p_data.size() != size, "Expected data size of " + itos(size) + " bytes in Image::create(), got instead " + itos(p_data.size()) + " bytes.");
height = p_height;
width = p_width;
@@ -1917,6 +1888,14 @@ Error Image::save_png(const String &p_path) const {
return save_png_func(p_path, Ref<Image>((Image *)this));
}
+Error Image::save_exr(const String &p_path, bool p_grayscale) const {
+
+ if (save_exr_func == NULL)
+ return ERR_UNAVAILABLE;
+
+ return save_exr_func(p_path, Ref<Image>((Image *)this), p_grayscale);
+}
+
int Image::get_image_data_size(int p_width, int p_height, Format p_format, bool p_mipmaps) {
int mm;
@@ -2405,10 +2384,7 @@ Color Image::get_pixel(int p_x, int p_y) const {
uint8_t *ptr = write_lock.ptr();
#ifdef DEBUG_ENABLED
- if (!ptr) {
- ERR_EXPLAIN("Image must be locked with 'lock()' before using get_pixel()");
- ERR_FAIL_V(Color());
- }
+ ERR_FAIL_COND_V_MSG(!ptr, Color(), "Image must be locked with 'lock()' before using get_pixel().");
ERR_FAIL_INDEX_V(p_x, width, Color());
ERR_FAIL_INDEX_V(p_y, height, Color());
@@ -2524,8 +2500,7 @@ Color Image::get_pixel(int p_x, int p_y) const {
return Color::from_rgbe9995(((uint32_t *)ptr)[ofs]);
}
default: {
- ERR_EXPLAIN("Can't get_pixel() on compressed image, sorry.");
- ERR_FAIL_V(Color());
+ ERR_FAIL_V_MSG(Color(), "Can't get_pixel() on compressed image, sorry.");
}
}
}
@@ -2538,10 +2513,7 @@ void Image::set_pixel(int p_x, int p_y, const Color &p_color) {
uint8_t *ptr = write_lock.ptr();
#ifdef DEBUG_ENABLED
- if (!ptr) {
- ERR_EXPLAIN("Image must be locked with 'lock()' before using set_pixel()");
- ERR_FAIL();
- }
+ ERR_FAIL_COND_MSG(!ptr, "Image must be locked with 'lock()' before using set_pixel().");
ERR_FAIL_INDEX(p_x, width);
ERR_FAIL_INDEX(p_y, height);
@@ -2653,8 +2625,7 @@ void Image::set_pixel(int p_x, int p_y, const Color &p_color) {
} break;
default: {
- ERR_EXPLAIN("Can't set_pixel() on compressed image, sorry.");
- ERR_FAIL();
+ ERR_FAIL_MSG("Can't set_pixel() on compressed image, sorry.");
}
}
}
@@ -2746,6 +2717,7 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("load", "path"), &Image::load);
ClassDB::bind_method(D_METHOD("save_png", "path"), &Image::save_png);
+ ClassDB::bind_method(D_METHOD("save_exr", "path", "grayscale"), &Image::save_exr, DEFVAL(false));
ClassDB::bind_method(D_METHOD("detect_alpha"), &Image::detect_alpha);
ClassDB::bind_method(D_METHOD("is_invisible"), &Image::is_invisible);
diff --git a/core/image.h b/core/image.h
index cc796789cd..d17571399d 100644
--- a/core/image.h
+++ b/core/image.h
@@ -49,11 +49,14 @@ class Image;
typedef Error (*SavePNGFunc)(const String &p_path, const Ref<Image> &p_img);
typedef Ref<Image> (*ImageMemLoadFunc)(const uint8_t *p_png, int p_size);
+typedef Error (*SaveEXRFunc)(const String &p_path, const Ref<Image> &p_img, bool p_grayscale);
+
class Image : public Resource {
GDCLASS(Image, Resource);
public:
static SavePNGFunc save_png_func;
+ static SaveEXRFunc save_exr_func;
enum {
MAX_WIDTH = 16384, // force a limit somehow
@@ -258,6 +261,7 @@ public:
Error load(const String &p_path);
Error save_png(const String &p_path) const;
+ Error save_exr(const String &p_path, bool p_grayscale) const;
/**
* create an empty image
diff --git a/core/input_map.cpp b/core/input_map.cpp
index 165999f081..2a8ac435fe 100644
--- a/core/input_map.cpp
+++ b/core/input_map.cpp
@@ -192,10 +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);
- if (!E) {
- ERR_EXPLAIN("Request for nonexistent InputMap action: " + String(p_action));
- ERR_FAIL_V(false);
- }
+ 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()) {
diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp
index f7fb72c089..9063e028be 100644
--- a/core/io/config_file.cpp
+++ b/core/io/config_file.cpp
@@ -86,10 +86,7 @@ void ConfigFile::set_value(const String &p_section, const String &p_key, const V
Variant ConfigFile::get_value(const String &p_section, const String &p_key, Variant p_default) const {
if (!values.has(p_section) || !values[p_section].has(p_key)) {
- if (p_default.get_type() == Variant::NIL) {
- ERR_EXPLAIN("Couldn't find the given section/key and no default was given");
- ERR_FAIL_V(p_default);
- }
+ ERR_FAIL_COND_V_MSG(p_default.get_type() == Variant::NIL, p_default, "Couldn't find the given section/key and no default was given.");
return p_default;
}
return values[p_section][p_key];
@@ -204,7 +201,7 @@ Error ConfigFile::load(const String &p_path) {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
if (!f)
- return ERR_CANT_OPEN;
+ return err;
return _internal_load(p_path, f);
}
@@ -271,7 +268,7 @@ Error ConfigFile::_internal_load(const String &p_path, FileAccess *f) {
memdelete(f);
return OK;
} else if (err != OK) {
- ERR_PRINTS("ConfgFile::load - " + p_path + ":" + itos(lines) + " error: " + error_text);
+ ERR_PRINTS("ConfgFile::load - " + p_path + ":" + itos(lines) + " error: " + error_text + ".");
memdelete(f);
return err;
}
diff --git a/core/io/file_access_buffered.cpp b/core/io/file_access_buffered.cpp
index 15523a49a9..f72ad61da6 100644
--- a/core/io/file_access_buffered.cpp
+++ b/core/io/file_access_buffered.cpp
@@ -87,10 +87,8 @@ bool FileAccessBuffered::eof_reached() const {
}
uint8_t FileAccessBuffered::get_8() const {
- if (!file.open) {
- ERR_EXPLAIN("Can't get data, when file is not opened.");
- ERR_FAIL_V(0);
- }
+
+ ERR_FAIL_COND_V_MSG(!file.open, 0, "Can't get data, when file is not opened.");
uint8_t byte = 0;
if (cache_data_left() >= 1) {
@@ -104,10 +102,8 @@ uint8_t FileAccessBuffered::get_8() const {
}
int FileAccessBuffered::get_buffer(uint8_t *p_dest, int p_length) const {
- if (!file.open) {
- ERR_EXPLAIN("Can't get buffer, when file is not opened.");
- ERR_FAIL_V(-1);
- }
+
+ ERR_FAIL_COND_V_MSG(!file.open, -1, "Can't get buffer, when file is not opened.");
if (p_length > cache_size) {
diff --git a/core/io/file_access_buffered_fa.h b/core/io/file_access_buffered_fa.h
index 6e806e7b3f..c8cee04208 100644
--- a/core/io/file_access_buffered_fa.h
+++ b/core/io/file_access_buffered_fa.h
@@ -40,10 +40,7 @@ class FileAccessBufferedFA : public FileAccessBuffered {
int read_data_block(int p_offset, int p_size, uint8_t *p_dest = 0) const {
- if (!f.is_open()) {
- ERR_EXPLAIN("Can't read data block, when file is not opened.");
- ERR_FAIL_V(-1);
- }
+ ERR_FAIL_COND_V_MSG(!f.is_open(), -1, "Can't read data block when file is not opened.");
((T *)&f)->seek(p_offset);
diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp
index 6c4310a572..102cd9cf6c 100644
--- a/core/io/file_access_compressed.cpp
+++ b/core/io/file_access_compressed.cpp
@@ -208,7 +208,8 @@ void FileAccessCompressed::seek(size_t p_position) {
if (p_position == read_total) {
at_end = true;
} else {
-
+ at_end = false;
+ read_eof = false;
int block_idx = p_position / block_size;
if (block_idx != read_block) {
diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp
index ccee6aeb15..77decc107d 100644
--- a/core/io/file_access_encrypted.cpp
+++ b/core/io/file_access_encrypted.cpp
@@ -30,7 +30,7 @@
#include "file_access_encrypted.h"
-#include "core/math/crypto_core.h"
+#include "core/crypto/crypto_core.h"
#include "core/os/copymem.h"
#include "core/print_string.h"
#include "core/variant.h"
@@ -94,8 +94,7 @@ Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8
unsigned char hash[16];
ERR_FAIL_COND_V(CryptoCore::md5(data.ptr(), data.size(), hash) != OK, ERR_BUG);
- ERR_EXPLAIN("The MD5 sum of the decrypted file does not match the expected value. It could be that the file is corrupt, or that the provided decryption key is invalid.");
- ERR_FAIL_COND_V(String::md5(hash) != String::md5(md5d), ERR_FILE_CORRUPT);
+ ERR_FAIL_COND_V_MSG(String::md5(hash) != String::md5(md5d), ERR_FILE_CORRUPT, "The MD5 sum of the decrypted file does not match the expected value. It could be that the file is corrupt, or that the provided decryption key is invalid.");
file = p_base;
}
@@ -298,7 +297,7 @@ uint32_t FileAccessEncrypted::_get_unix_permissions(const String &p_file) {
}
Error FileAccessEncrypted::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
- ERR_PRINT("Setting UNIX permissions on encrypted files is not implemented yet");
+ ERR_PRINT("Setting UNIX permissions on encrypted files is not implemented yet.");
return ERR_UNAVAILABLE;
}
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index ca66b34e17..d49d36c2b9 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -90,7 +90,7 @@ void PackedData::add_path(const String &pkg_path, const String &path, uint64_t o
}
}
String filename = path.get_file();
- // Don't add as a file if the path points to a directoryy
+ // Don't add as a file if the path points to a directory
if (!filename.empty()) {
cd->files.insert(filename);
}
@@ -171,10 +171,8 @@ bool PackedSourcePCK::try_open_pack(const String &p_path) {
uint32_t ver_minor = f->get_32();
f->get_32(); // ver_rev
- ERR_EXPLAIN("Pack version unsupported: " + itos(version));
- ERR_FAIL_COND_V(version != PACK_VERSION, false);
- ERR_EXPLAIN("Pack created with a newer version of the engine: " + itos(ver_major) + "." + itos(ver_minor));
- ERR_FAIL_COND_V(ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR), false);
+ 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) + ".");
for (int i = 0; i < 16; i++) {
//reserved
@@ -322,10 +320,9 @@ bool FileAccessPack::file_exists(const String &p_name) {
FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file) :
pf(p_file),
f(FileAccess::open(pf.pack, FileAccess::READ)) {
- if (!f) {
- ERR_EXPLAIN("Can't open pack-referenced file: " + String(pf.pack));
- ERR_FAIL_COND(!f);
- }
+
+ ERR_FAIL_COND_MSG(!f, "Can't open pack-referenced file: " + String(pf.pack) + ".");
+
f->seek(pf.offset);
pos = 0;
eof = false;
@@ -463,11 +460,15 @@ String DirAccessPack::get_current_dir() {
bool DirAccessPack::file_exists(String p_file) {
+ p_file = fix_path(p_file);
+
return current->files.has(p_file);
}
bool DirAccessPack::dir_exists(String p_dir) {
+ p_dir = fix_path(p_dir);
+
return current->subdirs.has(p_dir);
}
diff --git a/core/io/image_loader.h b/core/io/image_loader.h
index ae4b72a534..af6b0551a3 100644
--- a/core/io/image_loader.h
+++ b/core/io/image_loader.h
@@ -37,24 +37,8 @@
#include "core/os/file_access.h"
#include "core/ustring.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-/**
- * @class ImageScanLineLoader
- * @author Juan Linietsky <reduzio@gmail.com>
- *
-
- */
class ImageLoader;
-/**
- * @class ImageLoader
- * Base Class and singleton for loading images from disk
- * Can load images in one go, or by scanline
- */
-
class ImageFormatLoader {
friend class ImageLoader;
friend class ResourceFormatLoaderImage;
diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp
index 9305afac5f..df4be9b9fd 100644
--- a/core/io/ip_address.cpp
+++ b/core/io/ip_address.cpp
@@ -81,8 +81,7 @@ static void _parse_hex(const String &p_string, int p_start, uint8_t *p_dst) {
} else if (c == ':') {
break;
} else {
- ERR_EXPLAIN("Invalid character in ipv6 address: " + p_string);
- ERR_FAIL();
+ ERR_FAIL_MSG("Invalid character in IPv6 address: " + p_string + ".");
};
ret = ret << 4;
ret += n;
@@ -126,9 +125,7 @@ void IP_Address::_parse_ipv6(const String &p_string) {
++parts_count;
};
} else {
-
- ERR_EXPLAIN("Invalid character in IPv6 address: " + p_string);
- ERR_FAIL();
+ ERR_FAIL_MSG("Invalid character in IPv6 address: " + p_string + ".");
};
};
@@ -166,10 +163,7 @@ void IP_Address::_parse_ipv4(const String &p_string, int p_start, uint8_t *p_ret
};
int slices = ip.get_slice_count(".");
- if (slices != 4) {
- ERR_EXPLAIN("Invalid IP Address String: " + ip);
- ERR_FAIL();
- }
+ ERR_FAIL_COND_MSG(slices != 4, "Invalid IP address string: " + ip + ".");
for (int i = 0; i < 4; i++) {
p_ret[i] = ip.get_slicec('.', i).to_int();
}
@@ -229,7 +223,7 @@ IP_Address::IP_Address(const String &p_string) {
valid = true;
} else {
- ERR_PRINT("Invalid IP address");
+ ERR_PRINT("Invalid IP address.");
}
}
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index dc5581ea01..b386feb14c 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -377,11 +377,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
}
} break;
- /*case Variant::RESOURCE: {
-
- ERR_EXPLAIN("Can't marshallize resources");
- ERR_FAIL_V(ERR_INVALID_DATA); //no, i'm sorry, no go
- } break;*/
case Variant::_RID: {
r_variant = RID();
@@ -1066,11 +1061,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
r_len += 4 * 4;
} break;
- /*case Variant::RESOURCE: {
-
- ERR_EXPLAIN("Can't marshallize resources");
- ERR_FAIL_V(ERR_INVALID_DATA); //no, i'm sorry, no go
- } break;*/
case Variant::_RID: {
} break;
diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp
index 33dc4dbde4..d20133642b 100644
--- a/core/io/multiplayer_api.cpp
+++ b/core/io/multiplayer_api.cpp
@@ -146,8 +146,7 @@ void MultiplayerAPI::set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_pee
network_peer = p_peer;
- ERR_EXPLAIN("Supplied NetworkedNetworkPeer must be connecting or connected.");
- ERR_FAIL_COND(p_peer.is_valid() && p_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED);
+ ERR_FAIL_COND_MSG(p_peer.is_valid() && p_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED, "Supplied NetworkedNetworkPeer must be connecting or connected.");
if (network_peer.is_valid()) {
network_peer->connect("peer_connected", this, "_add_peer");
@@ -164,10 +163,8 @@ Ref<NetworkedMultiplayerPeer> MultiplayerAPI::get_network_peer() const {
void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_packet_len) {
- ERR_EXPLAIN("Multiplayer root node was not initialized. If you are using custom multiplayer, remember to set the root node via MultiplayerAPI.set_root_node before using it");
- ERR_FAIL_COND(root_node == NULL);
- ERR_EXPLAIN("Invalid packet received. Size too small.");
- ERR_FAIL_COND(p_packet_len < 1);
+ ERR_FAIL_COND_MSG(root_node == NULL, "Multiplayer root node was not initialized. If you are using custom multiplayer, remember to set the root node via MultiplayerAPI.set_root_node before using it.");
+ ERR_FAIL_COND_MSG(p_packet_len < 1, "Invalid packet received. Size too small.");
uint8_t packet_type = p_packet[0];
@@ -186,13 +183,11 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_
case NETWORK_COMMAND_REMOTE_CALL:
case NETWORK_COMMAND_REMOTE_SET: {
- ERR_EXPLAIN("Invalid packet received. Size too small.");
- ERR_FAIL_COND(p_packet_len < 6);
+ ERR_FAIL_COND_MSG(p_packet_len < 6, "Invalid packet received. Size too small.");
Node *node = _process_get_node(p_from, p_packet, p_packet_len);
- ERR_EXPLAIN("Invalid packet received. Requested node was not found.");
- ERR_FAIL_COND(node == NULL);
+ ERR_FAIL_COND_MSG(node == NULL, "Invalid packet received. Requested node was not found.");
// Detect cstring end.
int len_end = 5;
@@ -202,8 +197,7 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_
}
}
- ERR_EXPLAIN("Invalid packet received. Size too small.");
- ERR_FAIL_COND(len_end >= p_packet_len);
+ ERR_FAIL_COND_MSG(len_end >= p_packet_len, "Invalid packet received. Size too small.");
StringName name = String::utf8((const char *)&p_packet[5]);
@@ -235,8 +229,7 @@ Node *MultiplayerAPI::_process_get_node(int p_from, const uint8_t *p_packet, int
int ofs = target & 0x7FFFFFFF;
- ERR_EXPLAIN("Invalid packet received. Size smaller than declared.");
- ERR_FAIL_COND_V(ofs >= p_packet_len, NULL);
+ ERR_FAIL_COND_V_MSG(ofs >= p_packet_len, NULL, "Invalid packet received. Size smaller than declared.");
String paths;
paths.parse_utf8((const char *)&p_packet[ofs], p_packet_len - ofs);
@@ -246,33 +239,30 @@ Node *MultiplayerAPI::_process_get_node(int p_from, const uint8_t *p_packet, int
node = root_node->get_node(np);
if (!node)
- ERR_PRINTS("Failed to get path from RPC: " + String(np));
+ ERR_PRINTS("Failed to get path from RPC: " + String(np) + ".");
} else {
// Use cached path.
int id = target;
Map<int, PathGetCache>::Element *E = path_get_cache.find(p_from);
- ERR_EXPLAIN("Invalid packet received. Requests invalid peer cache.");
- ERR_FAIL_COND_V(!E, NULL);
+ ERR_FAIL_COND_V_MSG(!E, NULL, "Invalid packet received. Requests invalid peer cache.");
Map<int, PathGetCache::NodeInfo>::Element *F = E->get().nodes.find(id);
- ERR_EXPLAIN("Invalid packet received. Unabled to find requested cached node.");
- ERR_FAIL_COND_V(!F, NULL);
+ ERR_FAIL_COND_V_MSG(!F, NULL, "Invalid packet received. Unabled to find requested cached node.");
PathGetCache::NodeInfo *ni = &F->get();
// Do proper caching later.
node = root_node->get_node(ni->path);
if (!node)
- ERR_PRINTS("Failed to get cached path from RPC: " + String(ni->path));
+ ERR_PRINTS("Failed to get cached path from RPC: " + String(ni->path) + ".");
}
return node;
}
void MultiplayerAPI::_process_rpc(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) {
- ERR_EXPLAIN("Invalid packet received. Size too small.");
- ERR_FAIL_COND(p_offset >= p_packet_len);
+ ERR_FAIL_COND_MSG(p_offset >= p_packet_len, "Invalid packet received. Size too small.");
// Check that remote can call the RPC on this node.
RPCMode rpc_mode = RPC_MODE_DISABLED;
@@ -284,8 +274,7 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const StringName &p_name, int p_
}
bool can_call = _can_call_mode(p_node, rpc_mode, p_from);
- ERR_EXPLAIN("RPC '" + String(p_name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rpc_mode) + ", master is " + itos(p_node->get_network_master()) + ".");
- ERR_FAIL_COND(!can_call);
+ ERR_FAIL_COND_MSG(!can_call, "RPC '" + String(p_name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rpc_mode) + ", master is " + itos(p_node->get_network_master()) + ".");
int argc = p_packet[p_offset];
Vector<Variant> args;
@@ -297,13 +286,11 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const StringName &p_name, int p_
for (int i = 0; i < argc; i++) {
- ERR_EXPLAIN("Invalid packet received. Size too small.");
- ERR_FAIL_COND(p_offset >= p_packet_len);
+ ERR_FAIL_COND_MSG(p_offset >= p_packet_len, "Invalid packet received. Size too small.");
int vlen;
Error err = decode_variant(args.write[i], &p_packet[p_offset], p_packet_len - p_offset, &vlen, allow_object_decoding || network_peer->is_object_decoding_allowed());
- ERR_EXPLAIN("Invalid packet received. Unable to decode RPC argument.");
- ERR_FAIL_COND(err != OK);
+ ERR_FAIL_COND_MSG(err != OK, "Invalid packet received. Unable to decode RPC argument.");
argp.write[i] = &args[i];
p_offset += vlen;
@@ -321,8 +308,7 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const StringName &p_name, int p_
void MultiplayerAPI::_process_rset(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) {
- ERR_EXPLAIN("Invalid packet received. Size too small.");
- ERR_FAIL_COND(p_offset >= p_packet_len);
+ ERR_FAIL_COND_MSG(p_offset >= p_packet_len, "Invalid packet received. Size too small.");
// Check that remote can call the RSET on this node.
RPCMode rset_mode = RPC_MODE_DISABLED;
@@ -334,28 +320,25 @@ void MultiplayerAPI::_process_rset(Node *p_node, const StringName &p_name, int p
}
bool can_call = _can_call_mode(p_node, rset_mode, p_from);
- ERR_EXPLAIN("RSET '" + String(p_name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rset_mode) + ", master is " + itos(p_node->get_network_master()) + ".");
- ERR_FAIL_COND(!can_call);
+ ERR_FAIL_COND_MSG(!can_call, "RSET '" + String(p_name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rset_mode) + ", master is " + itos(p_node->get_network_master()) + ".");
Variant value;
Error err = decode_variant(value, &p_packet[p_offset], p_packet_len - p_offset, NULL, allow_object_decoding || network_peer->is_object_decoding_allowed());
- ERR_EXPLAIN("Invalid packet received. Unable to decode RSET value.");
- ERR_FAIL_COND(err != OK);
+ ERR_FAIL_COND_MSG(err != OK, "Invalid packet received. Unable to decode RSET value.");
bool valid;
p_node->set(p_name, value, &valid);
if (!valid) {
- String error = "Error setting remote property '" + String(p_name) + "', not found in object of type " + p_node->get_class();
+ String error = "Error setting remote property '" + String(p_name) + "', not found in object of type " + p_node->get_class() + ".";
ERR_PRINTS(error);
}
}
void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len) {
- ERR_EXPLAIN("Invalid packet received. Size too small.");
- ERR_FAIL_COND(p_packet_len < 5);
+ ERR_FAIL_COND_MSG(p_packet_len < 5, "Invalid packet received. Size too small.");
int id = decode_uint32(&p_packet[1]);
String paths;
@@ -390,8 +373,7 @@ void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet,
void MultiplayerAPI::_process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len) {
- ERR_EXPLAIN("Invalid packet received. Size too small.");
- ERR_FAIL_COND(p_packet_len < 2);
+ ERR_FAIL_COND_MSG(p_packet_len < 2, "Invalid packet received. Size too small.");
String paths;
paths.parse_utf8((const char *)&p_packet[1], p_packet_len - 1);
@@ -399,12 +381,10 @@ void MultiplayerAPI::_process_confirm_path(int p_from, const uint8_t *p_packet,
NodePath path = paths;
PathSentCache *psc = path_send_cache.getptr(path);
- ERR_EXPLAIN("Invalid packet received. Tries to confirm a path which was not found in cache.");
- ERR_FAIL_COND(!psc);
+ ERR_FAIL_COND_MSG(!psc, "Invalid packet received. Tries to confirm a path which was not found in cache.");
Map<int, bool>::Element *E = psc->confirmed_peers.find(p_from);
- ERR_EXPLAIN("Invalid packet received. Source peer was not found in cache for the given path.");
- ERR_FAIL_COND(!E);
+ ERR_FAIL_COND_MSG(!E, "Invalid packet received. Source peer was not found in cache for the given path.");
E->get() = true;
}
@@ -460,39 +440,22 @@ bool MultiplayerAPI::_send_confirm_path(NodePath p_path, PathSentCache *psc, int
void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p_set, const StringName &p_name, const Variant **p_arg, int p_argcount) {
- if (network_peer.is_null()) {
- ERR_EXPLAIN("Attempt to remote call/set when networking is not active in SceneTree.");
- ERR_FAIL();
- }
+ ERR_FAIL_COND_MSG(network_peer.is_null(), "Attempt to remote call/set when networking is not active in SceneTree.");
- if (network_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_CONNECTING) {
- ERR_EXPLAIN("Attempt to remote call/set when networking is not connected yet in SceneTree.");
- ERR_FAIL();
- }
+ ERR_FAIL_COND_MSG(network_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_CONNECTING, "Attempt to remote call/set when networking is not connected yet in SceneTree.");
- if (network_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED) {
- ERR_EXPLAIN("Attempt to remote call/set when networking is disconnected.");
- ERR_FAIL();
- }
+ ERR_FAIL_COND_MSG(network_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED, "Attempt to remote call/set when networking is disconnected.");
- if (p_argcount > 255) {
- ERR_EXPLAIN("Too many arguments >255.");
- ERR_FAIL();
- }
+ ERR_FAIL_COND_MSG(p_argcount > 255, "Too many arguments >255.");
if (p_to != 0 && !connected_peers.has(ABS(p_to))) {
- if (p_to == network_peer->get_unique_id()) {
- ERR_EXPLAIN("Attempt to remote call/set yourself! unique ID: " + itos(network_peer->get_unique_id()));
- } else {
- ERR_EXPLAIN("Attempt to remote call unexisting ID: " + itos(p_to));
- }
+ ERR_FAIL_COND_MSG(p_to == network_peer->get_unique_id(), "Attempt to remote call/set yourself! unique ID: " + itos(network_peer->get_unique_id()) + ".");
- ERR_FAIL();
+ ERR_FAIL_MSG("Attempt to remote call unexisting ID: " + itos(p_to) + ".");
}
NodePath from_path = (root_node->get_path()).rel_path_to(p_from->get_path());
- ERR_EXPLAIN("Unable to send RPC. Relative path is empty. THIS IS LIKELY A BUG IN THE ENGINE!");
- ERR_FAIL_COND(from_path.is_empty());
+ ERR_FAIL_COND_MSG(from_path.is_empty(), "Unable to send RPC. Relative path is empty. THIS IS LIKELY A BUG IN THE ENGINE!");
// See if the path is cached.
PathSentCache *psc = path_send_cache.getptr(from_path);
@@ -530,8 +493,7 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p
if (p_set) {
// Set argument.
Error err = encode_variant(*p_arg[0], NULL, len, allow_object_decoding || network_peer->is_object_decoding_allowed());
- ERR_EXPLAIN("Unable to encode RSET value. THIS IS LIKELY A BUG IN THE ENGINE!");
- ERR_FAIL_COND(err != OK);
+ ERR_FAIL_COND_MSG(err != OK, "Unable to encode RSET value. THIS IS LIKELY A BUG IN THE ENGINE!");
MAKE_ROOM(ofs + len);
encode_variant(*p_arg[0], &(packet_cache.write[ofs]), len, allow_object_decoding || network_peer->is_object_decoding_allowed());
ofs += len;
@@ -543,8 +505,7 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p
ofs += 1;
for (int i = 0; i < p_argcount; i++) {
Error err = encode_variant(*p_arg[i], NULL, len, allow_object_decoding || network_peer->is_object_decoding_allowed());
- ERR_EXPLAIN("Unable to encode RPC argument. THIS IS LIKELY A BUG IN THE ENGINE!");
- ERR_FAIL_COND(err != OK);
+ ERR_FAIL_COND_MSG(err != OK, "Unable to encode RPC argument. THIS IS LIKELY A BUG IN THE ENGINE!");
MAKE_ROOM(ofs + len);
encode_variant(*p_arg[i], &(packet_cache.write[ofs]), len, allow_object_decoding || network_peer->is_object_decoding_allowed());
ofs += len;
@@ -626,12 +587,9 @@ void MultiplayerAPI::_server_disconnected() {
void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_method, const Variant **p_arg, int p_argcount) {
- ERR_EXPLAIN("Trying to call an RPC while no network peer is active.");
- ERR_FAIL_COND(!network_peer.is_valid());
- ERR_EXPLAIN("Trying to call an RPC on a node which is not inside SceneTree.");
- ERR_FAIL_COND(!p_node->is_inside_tree());
- ERR_EXPLAIN("Trying to call an RPC via a network peer which is not connected.");
- ERR_FAIL_COND(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED);
+ ERR_FAIL_COND_MSG(!network_peer.is_valid(), "Trying to call an RPC while no network peer is active.");
+ ERR_FAIL_COND_MSG(!p_node->is_inside_tree(), "Trying to call an RPC on a node which is not inside SceneTree.");
+ ERR_FAIL_COND_MSG(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED, "Trying to call an RPC via a network peer which is not connected.");
int node_id = network_peer->get_unique_id();
bool skip_rpc = node_id == p_peer_id;
@@ -668,7 +626,7 @@ void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const
rpc_sender_id = temp_id;
if (ce.error != Variant::CallError::CALL_OK) {
String error = Variant::get_call_error_text(p_node, p_method, p_arg, p_argcount, ce);
- error = "rpc() aborted in local call: - " + error;
+ error = "rpc() aborted in local call: - " + error + ".";
ERR_PRINTS(error);
return;
}
@@ -683,24 +641,20 @@ void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const
rpc_sender_id = temp_id;
if (ce.error != Variant::CallError::CALL_OK) {
String error = Variant::get_call_error_text(p_node, p_method, p_arg, p_argcount, ce);
- error = "rpc() aborted in script local call: - " + error;
+ error = "rpc() aborted in script local call: - " + error + ".";
ERR_PRINTS(error);
return;
}
}
- ERR_EXPLAIN("RPC '" + p_method + "' on yourself is not allowed by selected mode");
- ERR_FAIL_COND(skip_rpc && !(call_local_native || call_local_script));
+ ERR_FAIL_COND_MSG(skip_rpc && !(call_local_native || call_local_script), "RPC '" + p_method + "' on yourself is not allowed by selected mode.");
}
void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_property, const Variant &p_value) {
- ERR_EXPLAIN("Trying to RSET while no network peer is active.");
- ERR_FAIL_COND(!network_peer.is_valid());
- ERR_EXPLAIN("Trying to RSET on a node which is not inside SceneTree.");
- ERR_FAIL_COND(!p_node->is_inside_tree());
- ERR_EXPLAIN("Trying to send an RSET via a network peer which is not connected.");
- ERR_FAIL_COND(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED);
+ ERR_FAIL_COND_MSG(!network_peer.is_valid(), "Trying to RSET while no network peer is active.");
+ ERR_FAIL_COND_MSG(!p_node->is_inside_tree(), "Trying to RSET on a node which is not inside SceneTree.");
+ ERR_FAIL_COND_MSG(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED, "Trying to send an RSET via a network peer which is not connected.");
int node_id = network_peer->get_unique_id();
bool is_master = p_node->is_network_master();
@@ -724,7 +678,7 @@ void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const
rpc_sender_id = temp_id;
if (!valid) {
- String error = "rset() aborted in local set, property not found: - " + String(p_property);
+ String error = "rset() aborted in local set, property not found: - " + String(p_property) + ".";
ERR_PRINTS(error);
return;
}
@@ -742,7 +696,7 @@ void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const
rpc_sender_id = temp_id;
if (!valid) {
- String error = "rset() aborted in local script set, property not found: - " + String(p_property);
+ String error = "rset() aborted in local script set, property not found: - " + String(p_property) + ".";
ERR_PRINTS(error);
return;
}
@@ -751,8 +705,7 @@ void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const
}
if (skip_rset) {
- ERR_EXPLAIN("RSET for '" + p_property + "' on yourself is not allowed by selected mode");
- ERR_FAIL_COND(!set_local);
+ ERR_FAIL_COND_MSG(!set_local, "RSET for '" + p_property + "' on yourself is not allowed by selected mode.");
return;
}
@@ -763,12 +716,9 @@ void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const
Error MultiplayerAPI::send_bytes(PoolVector<uint8_t> p_data, int p_to, NetworkedMultiplayerPeer::TransferMode p_mode) {
- ERR_EXPLAIN("Trying to send an empty raw packet.");
- ERR_FAIL_COND_V(p_data.size() < 1, ERR_INVALID_DATA);
- ERR_EXPLAIN("Trying to send a raw packet while no network peer is active.");
- ERR_FAIL_COND_V(!network_peer.is_valid(), ERR_UNCONFIGURED);
- ERR_EXPLAIN("Trying to send a raw packet via a network peer which is not connected.");
- ERR_FAIL_COND_V(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED, ERR_UNCONFIGURED);
+ ERR_FAIL_COND_V_MSG(p_data.size() < 1, ERR_INVALID_DATA, "Trying to send an empty raw packet.");
+ ERR_FAIL_COND_V_MSG(!network_peer.is_valid(), ERR_UNCONFIGURED, "Trying to send a raw packet while no network peer is active.");
+ ERR_FAIL_COND_V_MSG(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED, ERR_UNCONFIGURED, "Trying to send a raw packet via a network peer which is not connected.");
MAKE_ROOM(p_data.size() + 1);
PoolVector<uint8_t>::Read r = p_data.read();
@@ -783,8 +733,7 @@ Error MultiplayerAPI::send_bytes(PoolVector<uint8_t> p_data, int p_to, Networked
void MultiplayerAPI::_process_raw(int p_from, const uint8_t *p_packet, int p_packet_len) {
- ERR_EXPLAIN("Invalid packet received. Size too small.");
- ERR_FAIL_COND(p_packet_len < 2);
+ ERR_FAIL_COND_MSG(p_packet_len < 2, "Invalid packet received. Size too small.");
PoolVector<uint8_t> out;
int len = p_packet_len - 1;
@@ -798,37 +747,32 @@ void MultiplayerAPI::_process_raw(int p_from, const uint8_t *p_packet, int p_pac
int MultiplayerAPI::get_network_unique_id() const {
- ERR_EXPLAIN("No network peer is assigned. Unable to get unique network ID.");
- ERR_FAIL_COND_V(!network_peer.is_valid(), 0);
+ ERR_FAIL_COND_V_MSG(!network_peer.is_valid(), 0, "No network peer is assigned. Unable to get unique network ID.");
return network_peer->get_unique_id();
}
bool MultiplayerAPI::is_network_server() const {
// XXX Maybe fail silently? Maybe should actually return true to make development of both local and online multiplayer easier?
- ERR_EXPLAIN("No network peer is assigned. I can't be a server.");
- ERR_FAIL_COND_V(!network_peer.is_valid(), false);
+ ERR_FAIL_COND_V_MSG(!network_peer.is_valid(), false, "No network peer is assigned. I can't be a server.");
return network_peer->is_server();
}
void MultiplayerAPI::set_refuse_new_network_connections(bool p_refuse) {
- ERR_EXPLAIN("No network peer is assigned. Unable to set 'refuse_new_connections'.");
- ERR_FAIL_COND(!network_peer.is_valid());
+ ERR_FAIL_COND_MSG(!network_peer.is_valid(), "No network peer is assigned. Unable to set 'refuse_new_connections'.");
network_peer->set_refuse_new_connections(p_refuse);
}
bool MultiplayerAPI::is_refusing_new_network_connections() const {
- ERR_EXPLAIN("No network peer is assigned. Unable to get 'refuse_new_connections'.");
- ERR_FAIL_COND_V(!network_peer.is_valid(), false);
+ ERR_FAIL_COND_V_MSG(!network_peer.is_valid(), false, "No network peer is assigned. Unable to get 'refuse_new_connections'.");
return network_peer->is_refusing_new_connections();
}
Vector<int> MultiplayerAPI::get_network_connected_peers() const {
- ERR_EXPLAIN("No network peer is assigned. Assume no peers are connected.");
- ERR_FAIL_COND_V(!network_peer.is_valid(), Vector<int>());
+ ERR_FAIL_COND_V_MSG(!network_peer.is_valid(), Vector<int>(), "No network peer is assigned. Assume no peers are connected.");
Vector<int> ret;
for (Set<int>::Element *E = connected_peers.front(); E; E = E->next()) {
diff --git a/core/io/packet_peer.cpp b/core/io/packet_peer.cpp
index 1e4ea715b3..1c792c43d1 100644
--- a/core/io/packet_peer.cpp
+++ b/core/io/packet_peer.cpp
@@ -280,8 +280,7 @@ Ref<StreamPeer> PacketPeerStream::get_stream_peer() const {
void PacketPeerStream::set_input_buffer_max_size(int p_max_size) {
//warning may lose packets
- ERR_EXPLAIN("Buffer in use, resizing would cause loss of data");
- ERR_FAIL_COND(ring_buffer.data_left());
+ ERR_FAIL_COND_MSG(ring_buffer.data_left(), "Buffer in use, resizing would cause loss of data.");
ring_buffer.resize(nearest_shift(p_max_size + 4));
input_buffer.resize(next_power_of_2(p_max_size + 4));
}
diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp
index c16d89d695..1c89bc6268 100644
--- a/core/io/pck_packer.cpp
+++ b/core/io/pck_packer.cpp
@@ -64,10 +64,7 @@ Error PCKPacker::pck_start(const String &p_file, int p_alignment) {
file = FileAccess::open(p_file, FileAccess::WRITE);
- if (!file) {
- ERR_EXPLAIN("Can't open file to write: " + String(p_file));
- ERR_FAIL_V(ERR_CANT_CREATE);
- }
+ ERR_FAIL_COND_V_MSG(!file, ERR_CANT_CREATE, "Can't open file to write: " + String(p_file) + ".");
alignment = p_alignment;
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index 146480e5a2..de10fe1376 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -490,8 +490,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) {
#endif
} else {
- ERR_EXPLAIN("Vector2 size is NOT 8!");
- ERR_FAIL_V(ERR_UNAVAILABLE);
+ ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Vector2 size is NOT 8!");
}
w.release();
r_v = array;
@@ -518,8 +517,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) {
#endif
} else {
- ERR_EXPLAIN("Vector3 size is NOT 12!");
- ERR_FAIL_V(ERR_UNAVAILABLE);
+ ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Vector3 size is NOT 12!");
}
w.release();
r_v = array;
@@ -546,8 +544,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) {
#endif
} else {
- ERR_EXPLAIN("Color size is NOT 16!");
- ERR_FAIL_V(ERR_UNAVAILABLE);
+ ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Color size is NOT 16!");
}
w.release();
r_v = array;
@@ -571,7 +568,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) {
const uint32_t current_version = 0;
if (format_version > current_version) {
- ERR_PRINT("Format version for encoded binary image is too new");
+ ERR_PRINT("Format version for encoded binary image is too new.");
return ERR_PARSE_ERROR;
}
@@ -655,8 +652,7 @@ Error ResourceInteractiveLoaderBinary::poll() {
} else {
error = ERR_FILE_MISSING_DEPENDENCIES;
- ERR_EXPLAIN("Can't load dependency: " + path);
- ERR_FAIL_V(error);
+ ERR_FAIL_V_MSG(error, "Can't load dependency: " + path + ".");
}
} else {
@@ -711,16 +707,15 @@ Error ResourceInteractiveLoaderBinary::poll() {
Object *obj = ClassDB::instance(t);
if (!obj) {
error = ERR_FILE_CORRUPT;
- ERR_EXPLAIN(local_path + ":Resource of unrecognized type in file: " + t);
- ERR_FAIL_V(ERR_FILE_CORRUPT);
+ ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, local_path + ":Resource of unrecognized type in file: " + t + ".");
}
Resource *r = Object::cast_to<Resource>(obj);
if (!r) {
+ String obj_class = obj->get_class();
error = ERR_FILE_CORRUPT;
- ERR_EXPLAIN(local_path + ":Resource type in resource field not a resource, type is: " + obj->get_class());
memdelete(obj); //bye
- ERR_FAIL_V(ERR_FILE_CORRUPT);
+ ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, local_path + ":Resource type in resource field not a resource, type is: " + obj_class + ".");
}
RES res = RES(r);
@@ -850,8 +845,7 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) {
//not normal
error = ERR_FILE_UNRECOGNIZED;
- ERR_EXPLAIN("Unrecognized binary resource file: " + local_path);
- ERR_FAIL();
+ ERR_FAIL_MSG("Unrecognized binary resource file: " + local_path + ".");
}
bool big_endian = f->get_32();
@@ -877,8 +871,7 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) {
if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) {
f->close();
- ERR_EXPLAIN("File Format '" + itos(FORMAT_VERSION) + "." + itos(ver_major) + "." + itos(ver_minor) + "' is too new! Please upgrade to a new engine version: " + local_path);
- ERR_FAIL();
+ ERR_FAIL_MSG("File format '" + itos(FORMAT_VERSION) + "." + itos(ver_major) + "." + itos(ver_minor) + "' is too new! Please upgrade to a new engine version: " + local_path + ".");
}
type = get_unicode_string();
@@ -926,8 +919,7 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) {
if (f->eof_reached()) {
error = ERR_FILE_CORRUPT;
- ERR_EXPLAIN("Premature End Of File: " + local_path);
- ERR_FAIL();
+ ERR_FAIL_MSG("Premature end of file (EOF): " + local_path + ".");
}
}
@@ -1084,8 +1076,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
//error=ERR_FILE_UNRECOGNIZED;
memdelete(f);
- ERR_EXPLAIN("Unrecognized binary resource file: " + local_path);
- ERR_FAIL_V(ERR_FILE_UNRECOGNIZED);
+ ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "Unrecognized binary resource file: " + local_path + ".");
} else {
fw = FileAccess::open(p_path + ".depren", FileAccess::WRITE);
if (!fw) {
@@ -1122,7 +1113,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
memdelete(da);
//use the old approach
- WARN_PRINT(("This file is old, so it can't refactor dependencies, opening and resaving: " + p_path).utf8().get_data());
+ 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);
@@ -1153,8 +1144,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
memdelete(f);
memdelete(fw);
- ERR_EXPLAIN("File Format '" + itos(FORMAT_VERSION) + "." + itos(ver_major) + "." + itos(ver_minor) + "' is too new! Please upgrade to a new engine version: " + local_path);
- ERR_FAIL_V(ERR_FILE_UNRECOGNIZED);
+ ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "File format '" + itos(FORMAT_VERSION) + "." + itos(ver_major) + "." + itos(ver_minor) + "' is too new! Please upgrade to a new engine version: " + local_path + ".");
}
// Since we're not actually converting the file contents, leave the version
@@ -1477,7 +1467,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
case Variant::_RID: {
f->store_32(VARIANT_RID);
- WARN_PRINT("Can't save RIDs");
+ WARN_PRINT("Can't save RIDs.");
RID val = p_property;
f->store_32(val.get_id());
} break;
@@ -1497,8 +1487,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
if (!resource_set.has(res)) {
f->store_32(OBJECT_EMPTY);
- ERR_EXPLAIN("Resource was not pre cached for the resource section, most likely due to circular refedence.");
- ERR_FAIL();
+ ERR_FAIL_MSG("Resource was not pre cached for the resource section, most likely due to circular reference.");
}
f->store_32(OBJECT_INTERNAL_RESOURCE);
@@ -1629,8 +1618,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
} break;
default: {
- ERR_EXPLAIN("Invalid variant");
- ERR_FAIL();
+ ERR_FAIL_MSG("Invalid variant.");
}
}
}
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index a29b9d1ddb..9e954890bc 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -275,12 +275,9 @@ RES ResourceLoader::_load(const String &p_path, const String &p_original_path, c
return res;
}
- if (found) {
- ERR_EXPLAIN("Failed loading resource: " + p_path);
- } else {
- ERR_EXPLAIN("No loader found for resource: " + p_path);
- }
- ERR_FAIL_V(RES());
+ ERR_FAIL_COND_V_MSG(found, RES(), "Failed loading resource: " + p_path + ".");
+
+ ERR_FAIL_V_MSG(RES(), "No loader found for resource: " + p_path + ".");
}
bool ResourceLoader::_add_to_loading_map(const String &p_path) {
@@ -355,10 +352,7 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p
{
bool success = _add_to_loading_map(local_path);
- if (!success) {
- ERR_EXPLAIN("Resource: '" + local_path + "' is already being loaded. Cyclic reference?");
- ERR_FAIL_V(RES());
- }
+ ERR_FAIL_COND_V_MSG(!success, RES(), "Resource: '" + local_path + "' is already being loaded. Cyclic reference?");
}
//lock first if possible
@@ -395,8 +389,7 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p
if (!p_no_cache) {
_remove_from_loading_map(local_path);
}
- ERR_EXPLAIN("Remapping '" + local_path + "'failed.");
- ERR_FAIL_V(RES());
+ ERR_FAIL_V_MSG(RES(), "Remapping '" + local_path + "' failed.");
}
print_verbose("Loading resource: " + path);
@@ -479,10 +472,7 @@ Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_
if (!p_no_cache) {
bool success = _add_to_loading_map(local_path);
- if (!success) {
- ERR_EXPLAIN("Resource: '" + local_path + "' is already being loaded. Cyclic reference?");
- ERR_FAIL_V(RES());
- }
+ ERR_FAIL_COND_V_MSG(!success, RES(), "Resource: '" + local_path + "' is already being loaded. Cyclic reference?");
if (ResourceCache::has(local_path)) {
@@ -503,8 +493,7 @@ Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_
if (!p_no_cache) {
_remove_from_loading_map(local_path);
}
- ERR_EXPLAIN("Remapping '" + local_path + "'failed.");
- ERR_FAIL_V(RES());
+ ERR_FAIL_V_MSG(RES(), "Remapping '" + local_path + "' failed.");
}
print_verbose("Loading resource: " + path);
@@ -534,12 +523,9 @@ Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_
_remove_from_loading_map(local_path);
}
- if (found) {
- ERR_EXPLAIN("Failed loading resource: " + path);
- } else {
- ERR_EXPLAIN("No loader found for resource: " + path);
- }
- ERR_FAIL_V(Ref<ResourceInteractiveLoader>());
+ ERR_FAIL_COND_V_MSG(found, Ref<ResourceInteractiveLoader>(), "Failed loading resource: " + path + ".");
+
+ ERR_FAIL_V_MSG(Ref<ResourceInteractiveLoader>(), "No loader found for resource: " + path + ".");
}
void ResourceLoader::add_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader, bool p_at_front) {
@@ -801,7 +787,7 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem
if (err == ERR_FILE_EOF) {
break;
} else if (err != OK) {
- ERR_PRINTS("Parse error: " + p_path + ".remap:" + itos(lines) + " error: " + error_text);
+ ERR_PRINTS("Parse error: " + p_path + ".remap:" + itos(lines) + " error: " + error_text + ".");
break;
}
@@ -932,16 +918,13 @@ bool ResourceLoader::add_custom_resource_format_loader(String script_path) {
Ref<Script> s = res;
StringName ibt = s->get_instance_base_type();
bool valid_type = ClassDB::is_parent_class(ibt, "ResourceFormatLoader");
- ERR_EXPLAIN("Script does not inherit a CustomResourceLoader: " + script_path);
- ERR_FAIL_COND_V(!valid_type, false);
+ ERR_FAIL_COND_V_MSG(!valid_type, false, "Script does not inherit a CustomResourceLoader: " + script_path + ".");
Object *obj = ClassDB::instance(ibt);
- ERR_EXPLAIN("Cannot instance script as custom resource loader, expected 'ResourceFormatLoader' inheritance, got: " + String(ibt));
- ERR_FAIL_COND_V(obj == NULL, false);
+ ERR_FAIL_COND_V_MSG(obj == NULL, false, "Cannot instance script as custom resource loader, expected 'ResourceFormatLoader' inheritance, got: " + String(ibt) + ".");
- ResourceFormatLoader *crl = NULL;
- crl = Object::cast_to<ResourceFormatLoader>(obj);
+ ResourceFormatLoader *crl = Object::cast_to<ResourceFormatLoader>(obj);
crl->set_script(s.get_ref_ptr());
ResourceLoader::add_resource_format_loader(crl);
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index 70e7bdc224..93df8cadb0 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -33,9 +33,6 @@
#include "core/os/thread.h"
#include "core/resource.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
class ResourceInteractiveLoader : public Reference {
diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp
index e2c1c3402a..a9ad62afe6 100644
--- a/core/io/resource_saver.cpp
+++ b/core/io/resource_saver.cpp
@@ -214,16 +214,13 @@ bool ResourceSaver::add_custom_resource_format_saver(String script_path) {
Ref<Script> s = res;
StringName ibt = s->get_instance_base_type();
bool valid_type = ClassDB::is_parent_class(ibt, "ResourceFormatSaver");
- ERR_EXPLAIN("Script does not inherit a CustomResourceSaver: " + script_path);
- ERR_FAIL_COND_V(!valid_type, false);
+ ERR_FAIL_COND_V_MSG(!valid_type, false, "Script does not inherit a CustomResourceSaver: " + script_path + ".");
Object *obj = ClassDB::instance(ibt);
- ERR_EXPLAIN("Cannot instance script as custom resource saver, expected 'ResourceFormatSaver' inheritance, got: " + String(ibt));
- ERR_FAIL_COND_V(obj == NULL, false);
+ ERR_FAIL_COND_V_MSG(obj == NULL, false, "Cannot instance script as custom resource saver, expected 'ResourceFormatSaver' inheritance, got: " + String(ibt) + ".");
- ResourceFormatSaver *crl = NULL;
- crl = Object::cast_to<ResourceFormatSaver>(obj);
+ ResourceFormatSaver *crl = Object::cast_to<ResourceFormatSaver>(obj);
crl->set_script(s.get_ref_ptr());
ResourceSaver::add_resource_format_saver(crl);
diff --git a/core/io/resource_saver.h b/core/io/resource_saver.h
index 0fba47a5e8..20e05d827a 100644
--- a/core/io/resource_saver.h
+++ b/core/io/resource_saver.h
@@ -33,10 +33,6 @@
#include "core/resource.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
class ResourceFormatSaver : public Reference {
GDCLASS(ResourceFormatSaver, Reference);
diff --git a/core/io/stream_peer_ssl.cpp b/core/io/stream_peer_ssl.cpp
index ccce48ccd7..f2eaf57acc 100644
--- a/core/io/stream_peer_ssl.cpp
+++ b/core/io/stream_peer_ssl.cpp
@@ -30,10 +30,7 @@
#include "stream_peer_ssl.h"
-#include "core/io/certs_compressed.gen.h"
-#include "core/io/compression.h"
-#include "core/os/file_access.h"
-#include "core/project_settings.h"
+#include "core/engine.h"
StreamPeerSSL *(*StreamPeerSSL::_create)() = NULL;
@@ -44,22 +41,8 @@ StreamPeerSSL *StreamPeerSSL::create() {
return NULL;
}
-StreamPeerSSL::LoadCertsFromMemory StreamPeerSSL::load_certs_func = NULL;
bool StreamPeerSSL::available = false;
-void StreamPeerSSL::load_certs_from_memory(const PoolByteArray &p_memory) {
- if (load_certs_func)
- load_certs_func(p_memory);
-}
-
-void StreamPeerSSL::load_certs_from_file(String p_path) {
- if (p_path != "") {
- PoolByteArray certs = get_cert_file_as_array(p_path);
- if (certs.size() > 0)
- load_certs_func(certs);
- }
-}
-
bool StreamPeerSSL::is_available() {
return available;
}
@@ -72,56 +55,11 @@ bool StreamPeerSSL::is_blocking_handshake_enabled() const {
return blocking_handshake;
}
-PoolByteArray StreamPeerSSL::get_cert_file_as_array(String p_path) {
-
- PoolByteArray out;
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
- if (f) {
- int flen = f->get_len();
- out.resize(flen + 1);
- PoolByteArray::Write w = out.write();
- f->get_buffer(w.ptr(), flen);
- w[flen] = 0; // Make sure it ends with string terminator
- memdelete(f);
-#ifdef DEBUG_ENABLED
- print_verbose(vformat("Loaded certs from '%s'.", p_path));
-#endif
- }
-
- return out;
-}
-
-PoolByteArray StreamPeerSSL::get_project_cert_array() {
-
- PoolByteArray out;
- String certs_path = GLOBAL_DEF("network/ssl/certificates", "");
- ProjectSettings::get_singleton()->set_custom_property_info("network/ssl/certificates", PropertyInfo(Variant::STRING, "network/ssl/certificates", PROPERTY_HINT_FILE, "*.crt"));
-
- if (certs_path != "") {
- // Use certs defined in project settings.
- return get_cert_file_as_array(certs_path);
- }
-#ifdef BUILTIN_CERTS_ENABLED
- else {
- // Use builtin certs only if user did not override it in project settings.
- out.resize(_certs_uncompressed_size + 1);
- PoolByteArray::Write w = out.write();
- Compression::decompress(w.ptr(), _certs_uncompressed_size, _certs_compressed, _certs_compressed_size, Compression::MODE_DEFLATE);
- w[_certs_uncompressed_size] = 0; // Make sure it ends with string terminator
-#ifdef DEBUG_ENABLED
- print_verbose("Loaded builtin certs");
-#endif
- }
-#endif
-
- return out;
-}
-
void StreamPeerSSL::_bind_methods() {
ClassDB::bind_method(D_METHOD("poll"), &StreamPeerSSL::poll);
- ClassDB::bind_method(D_METHOD("accept_stream", "base"), &StreamPeerSSL::accept_stream);
- ClassDB::bind_method(D_METHOD("connect_to_stream", "stream", "validate_certs", "for_hostname"), &StreamPeerSSL::connect_to_stream, DEFVAL(false), DEFVAL(String()));
+ ClassDB::bind_method(D_METHOD("accept_stream", "stream", "private_key", "certificate", "chain"), &StreamPeerSSL::accept_stream, DEFVAL(Ref<X509Certificate>()));
+ ClassDB::bind_method(D_METHOD("connect_to_stream", "stream", "validate_certs", "for_hostname", "valid_certificate"), &StreamPeerSSL::connect_to_stream, DEFVAL(false), DEFVAL(String()), DEFVAL(Ref<X509Certificate>()));
ClassDB::bind_method(D_METHOD("get_status"), &StreamPeerSSL::get_status);
ClassDB::bind_method(D_METHOD("disconnect_from_stream"), &StreamPeerSSL::disconnect_from_stream);
ClassDB::bind_method(D_METHOD("set_blocking_handshake_enabled", "enabled"), &StreamPeerSSL::set_blocking_handshake_enabled);
diff --git a/core/io/stream_peer_ssl.h b/core/io/stream_peer_ssl.h
index 482576c4c6..dedc35b9ac 100644
--- a/core/io/stream_peer_ssl.h
+++ b/core/io/stream_peer_ssl.h
@@ -31,19 +31,16 @@
#ifndef STREAM_PEER_SSL_H
#define STREAM_PEER_SSL_H
+#include "core/crypto/crypto.h"
#include "core/io/stream_peer.h"
class StreamPeerSSL : public StreamPeer {
GDCLASS(StreamPeerSSL, StreamPeer);
-public:
- typedef void (*LoadCertsFromMemory)(const PoolByteArray &p_certs);
-
protected:
static StreamPeerSSL *(*_create)();
static void _bind_methods();
- static LoadCertsFromMemory load_certs_func;
static bool available;
bool blocking_handshake;
@@ -61,18 +58,14 @@ public:
bool is_blocking_handshake_enabled() const;
virtual void poll() = 0;
- virtual Error accept_stream(Ref<StreamPeer> p_base) = 0;
- virtual Error connect_to_stream(Ref<StreamPeer> p_base, bool p_validate_certs = false, const String &p_for_hostname = String()) = 0;
+ virtual Error accept_stream(Ref<StreamPeer> p_base, Ref<CryptoKey> p_key, Ref<X509Certificate> p_cert, Ref<X509Certificate> p_ca_chain = Ref<X509Certificate>()) = 0;
+ virtual Error connect_to_stream(Ref<StreamPeer> p_base, bool p_validate_certs = false, const String &p_for_hostname = String(), Ref<X509Certificate> p_valid_cert = Ref<X509Certificate>()) = 0;
virtual Status get_status() const = 0;
virtual void disconnect_from_stream() = 0;
static StreamPeerSSL *create();
- static PoolByteArray get_cert_file_as_array(String p_path);
- static PoolByteArray get_project_cert_array();
- static void load_certs_from_file(String p_path);
- static void load_certs_from_memory(const PoolByteArray &p_memory);
static bool is_available();
StreamPeerSSL();
diff --git a/core/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp
index 67a0a905bd..e8e71c10ca 100644
--- a/core/io/translation_loader_po.cpp
+++ b/core/io/translation_loader_po.cpp
@@ -67,8 +67,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const S
if (status == STATUS_READING_ID) {
memdelete(f);
- ERR_EXPLAIN(p_path + ":" + itos(line) + " Unexpected EOF while reading 'msgid' at file: ");
- ERR_FAIL_V(RES());
+ ERR_FAIL_V_MSG(RES(), p_path + ":" + itos(line) + " Unexpected EOF while reading 'msgid' at file: ");
} else {
break;
}
@@ -79,8 +78,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const S
if (status == STATUS_READING_ID) {
memdelete(f);
- ERR_EXPLAIN(p_path + ":" + itos(line) + " Unexpected 'msgid', was expecting 'msgstr' while parsing: ");
- ERR_FAIL_V(RES());
+ ERR_FAIL_V_MSG(RES(), p_path + ":" + itos(line) + " Unexpected 'msgid', was expecting 'msgstr' while parsing: ");
}
if (msg_id != "") {
@@ -102,8 +100,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const S
if (status != STATUS_READING_ID) {
memdelete(f);
- ERR_EXPLAIN(p_path + ":" + itos(line) + " Unexpected 'msgstr', was expecting 'msgid' while parsing: ");
- ERR_FAIL_V(RES());
+ ERR_FAIL_V_MSG(RES(), p_path + ":" + itos(line) + " Unexpected 'msgstr', was expecting 'msgid' while parsing: ");
}
l = l.substr(6, l.length()).strip_edges();
@@ -118,11 +115,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const S
continue; //nothing to read or comment
}
- if (!l.begins_with("\"") || status == STATUS_NONE) {
- //not a string? failure!
- ERR_EXPLAIN(p_path + ":" + itos(line) + " Invalid line '" + l + "' while parsing: ");
- ERR_FAIL_V(RES());
- }
+ ERR_FAIL_COND_V_MSG(!l.begins_with("\"") || status == STATUS_NONE, RES(), p_path + ":" + itos(line) + " Invalid line '" + l + "' while parsing: ");
l = l.substr(1, l.length());
//find final quote
@@ -135,10 +128,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const S
}
}
- if (end_pos == -1) {
- ERR_EXPLAIN(p_path + ":" + itos(line) + " Expected '\"' at end of message while parsing file: ");
- ERR_FAIL_V(RES());
- }
+ ERR_FAIL_COND_V_MSG(end_pos == -1, RES(), p_path + ":" + itos(line) + " Expected '\"' at end of message while parsing file: ");
l = l.substr(0, end_pos);
l = l.c_unescape();
@@ -163,10 +153,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const S
config = msg_str;
}
- if (config == "") {
- ERR_EXPLAIN("No config found in file: " + p_path);
- ERR_FAIL_V(RES());
- }
+ ERR_FAIL_COND_V_MSG(config == "", RES(), "No config found in file: " + p_path + ".");
Vector<String> configs = config.split("\n");
for (int i = 0; i < configs.size(); i++) {
diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp
index 82527d3f38..9487947365 100644
--- a/core/io/xml_parser.cpp
+++ b/core/io/xml_parser.cpp
@@ -443,10 +443,8 @@ String XMLParser::get_attribute_value(const String &p_name) const {
}
}
- if (idx < 0) {
- ERR_EXPLAIN("Attribute not found: " + p_name);
- }
- ERR_FAIL_COND_V(idx < 0, "");
+ ERR_FAIL_COND_V_MSG(idx < 0, "", "Attribute not found: " + p_name + ".");
+
return attributes[idx].value;
}
diff --git a/core/map.h b/core/map.h
index c8197639f2..c87ee42e1b 100644
--- a/core/map.h
+++ b/core/map.h
@@ -33,10 +33,6 @@
#include "core/set.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
// based on the very nice implementation of rb-trees by:
// https://web.archive.org/web/20120507164830/http://web.mit.edu/~emin/www/source_code/red_black_tree/index.html
diff --git a/core/math/SCsub b/core/math/SCsub
index 0995298a4b..be438fcfbe 100644
--- a/core/math/SCsub
+++ b/core/math/SCsub
@@ -2,37 +2,6 @@
Import('env')
-env_math = env.Clone() # Maybe make one specific for crypto?
-
-is_builtin = env["builtin_mbedtls"]
-has_module = env["module_mbedtls_enabled"]
-
-if is_builtin or not has_module:
- # Use our headers for builtin or if the module is not going to be compiled.
- # We decided not to depend on system mbedtls just for these few files that can
- # be easily extracted.
- env_math.Prepend(CPPPATH=["#thirdparty/mbedtls/include"])
-
-# MbedTLS core functions (for CryptoCore).
-# If the mbedtls module is compiled we don't need to add the .c files with our
-# custom config since they will be built by the module itself.
-# Only if the module is not enabled, we must compile here the required sources
-# to make a "light" build with only the necessary mbedtls files.
-if not has_module:
- env_thirdparty = env_math.Clone()
- env_thirdparty.disable_warnings()
- # Custom config file
- env_thirdparty.Append(CPPDEFINES=[('MBEDTLS_CONFIG_FILE', '\\"thirdparty/mbedtls/include/godot_core_mbedtls_config.h\\"')])
- thirdparty_mbedtls_dir = "#thirdparty/mbedtls/library/"
- thirdparty_mbedtls_sources = [
- "aes.c",
- "base64.c",
- "md5.c",
- "sha1.c",
- "sha256.c",
- "godot_core_mbedtls_platform.c"
- ]
- thirdparty_mbedtls_sources = [thirdparty_mbedtls_dir + file for file in thirdparty_mbedtls_sources]
- env_thirdparty.add_source_files(env.core_sources, thirdparty_mbedtls_sources)
+env_math = env.Clone()
env_math.add_source_files(env.core_sources, "*.cpp")
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp
index b61119d8df..aea42a1edf 100644
--- a/core/math/a_star.cpp
+++ b/core/math/a_star.cpp
@@ -40,7 +40,17 @@ int AStar::get_available_point_id() const {
return 1;
}
- return points.back()->key() + 1;
+ // calculate our new next available point id if bigger than before or next id already contained in set of points.
+ if (points.has(last_free_id)) {
+ int cur_new_id = last_free_id;
+ while (points.has(cur_new_id)) {
+ cur_new_id++;
+ }
+ int &non_const = const_cast<int &>(last_free_id);
+ non_const = cur_new_id;
+ }
+
+ return last_free_id;
}
void AStar::add_point(int p_id, const Vector3 &p_pos, real_t p_weight_scale) {
@@ -48,7 +58,10 @@ void AStar::add_point(int p_id, const Vector3 &p_pos, real_t p_weight_scale) {
ERR_FAIL_COND(p_id < 0);
ERR_FAIL_COND(p_weight_scale < 1);
- if (!points.has(p_id)) {
+ Point *found_pt;
+ bool p_exists = points.lookup(p_id, found_pt);
+
+ if (!p_exists) {
Point *pt = memnew(Point);
pt->id = p_id;
pt->pos = p_pos;
@@ -57,84 +70,98 @@ void AStar::add_point(int p_id, const Vector3 &p_pos, real_t p_weight_scale) {
pt->open_pass = 0;
pt->closed_pass = 0;
pt->enabled = true;
- points[p_id] = pt;
+ points.set(p_id, pt);
} else {
- points[p_id]->pos = p_pos;
- points[p_id]->weight_scale = p_weight_scale;
+ found_pt->pos = p_pos;
+ found_pt->weight_scale = p_weight_scale;
}
}
Vector3 AStar::get_point_position(int p_id) const {
- ERR_FAIL_COND_V(!points.has(p_id), Vector3());
+ Point *p;
+ bool p_exists = points.lookup(p_id, p);
+ ERR_FAIL_COND_V(!p_exists, Vector3());
- return points[p_id]->pos;
+ return p->pos;
}
void AStar::set_point_position(int p_id, const Vector3 &p_pos) {
- ERR_FAIL_COND(!points.has(p_id));
+ Point *p;
+ bool p_exists = points.lookup(p_id, p);
+ ERR_FAIL_COND(!p_exists);
- points[p_id]->pos = p_pos;
+ p->pos = p_pos;
}
real_t AStar::get_point_weight_scale(int p_id) const {
- ERR_FAIL_COND_V(!points.has(p_id), 0);
+ Point *p;
+ bool p_exists = points.lookup(p_id, p);
+ ERR_FAIL_COND_V(!p_exists, 0);
- return points[p_id]->weight_scale;
+ return p->weight_scale;
}
void AStar::set_point_weight_scale(int p_id, real_t p_weight_scale) {
- ERR_FAIL_COND(!points.has(p_id));
+ Point *p;
+ bool p_exists = points.lookup(p_id, p);
+ ERR_FAIL_COND(!p_exists);
ERR_FAIL_COND(p_weight_scale < 1);
- points[p_id]->weight_scale = p_weight_scale;
+ p->weight_scale = p_weight_scale;
}
void AStar::remove_point(int p_id) {
- ERR_FAIL_COND(!points.has(p_id));
-
- Point *p = points[p_id];
+ Point *p;
+ bool p_exists = points.lookup(p_id, p);
+ ERR_FAIL_COND(!p_exists);
- for (Set<Point *>::Element *E = p->neighbours.front(); E; E = E->next()) {
+ for (OAHashMap<int, Point *>::Iterator it = p->neighbours.iter(); it.valid; it = p->neighbours.next_iter(it)) {
- Segment s(p_id, E->get()->id);
+ Segment s(p_id, (*it.key));
segments.erase(s);
- E->get()->neighbours.erase(p);
- E->get()->unlinked_neighbours.erase(p);
+ (*it.value)->neighbours.remove(p->id);
+ (*it.value)->unlinked_neighbours.remove(p->id);
}
- for (Set<Point *>::Element *E = p->unlinked_neighbours.front(); E; E = E->next()) {
+ for (OAHashMap<int, Point *>::Iterator it = p->unlinked_neighbours.iter(); it.valid; it = p->unlinked_neighbours.next_iter(it)) {
- Segment s(p_id, E->get()->id);
+ Segment s(p_id, (*it.key));
segments.erase(s);
- E->get()->neighbours.erase(p);
- E->get()->unlinked_neighbours.erase(p);
+ (*it.value)->neighbours.remove(p->id);
+ (*it.value)->unlinked_neighbours.remove(p->id);
}
memdelete(p);
- points.erase(p_id);
+ points.remove(p_id);
+ last_free_id = p_id;
}
void AStar::connect_points(int p_id, int p_with_id, bool bidirectional) {
- ERR_FAIL_COND(!points.has(p_id));
- ERR_FAIL_COND(!points.has(p_with_id));
ERR_FAIL_COND(p_id == p_with_id);
- Point *a = points[p_id];
- Point *b = points[p_with_id];
- a->neighbours.insert(b);
+ Point *a;
+ bool from_exists = points.lookup(p_id, a);
+ ERR_FAIL_COND(!from_exists);
- if (bidirectional)
- b->neighbours.insert(a);
- else
- b->unlinked_neighbours.insert(a);
+ Point *b;
+ bool to_exists = points.lookup(p_with_id, b);
+ ERR_FAIL_COND(!to_exists);
+
+ a->neighbours.set(b->id, b);
+
+ if (bidirectional) {
+ b->neighbours.set(a->id, a);
+ } else {
+ b->unlinked_neighbours.set(a->id, a);
+ }
Segment s(p_id, p_with_id);
if (s.from == p_id) {
@@ -147,6 +174,7 @@ void AStar::connect_points(int p_id, int p_with_id, bool bidirectional) {
segments.insert(s);
}
+
void AStar::disconnect_points(int p_id, int p_with_id) {
Segment s(p_id, p_with_id);
@@ -154,12 +182,18 @@ void AStar::disconnect_points(int p_id, int p_with_id) {
segments.erase(s);
- Point *a = points[p_id];
- Point *b = points[p_with_id];
- a->neighbours.erase(b);
- a->unlinked_neighbours.erase(b);
- b->neighbours.erase(a);
- b->unlinked_neighbours.erase(a);
+ Point *a;
+ bool a_exists = points.lookup(p_id, a);
+ CRASH_COND(!a_exists);
+
+ Point *b;
+ bool b_exists = points.lookup(p_with_id, b);
+ CRASH_COND(!b_exists);
+
+ a->neighbours.remove(b->id);
+ a->unlinked_neighbours.remove(b->id);
+ b->neighbours.remove(a->id);
+ b->unlinked_neighbours.remove(a->id);
}
bool AStar::has_point(int p_id) const {
@@ -171,8 +205,8 @@ Array AStar::get_points() {
Array point_list;
- for (const Map<int, Point *>::Element *E = points.front(); E; E = E->next()) {
- point_list.push_back(E->key());
+ for (OAHashMap<int, Point *>::Iterator it = points.iter(); it.valid; it = points.next_iter(it)) {
+ point_list.push_back(*(it.key));
}
return point_list;
@@ -180,14 +214,14 @@ Array AStar::get_points() {
PoolVector<int> AStar::get_point_connections(int p_id) {
- ERR_FAIL_COND_V(!points.has(p_id), PoolVector<int>());
+ Point *p;
+ bool p_exists = points.lookup(p_id, p);
+ ERR_FAIL_COND_V(!p_exists, PoolVector<int>());
PoolVector<int> point_list;
- Point *p = points[p_id];
-
- for (Set<Point *>::Element *E = p->neighbours.front(); E; E = E->next()) {
- point_list.push_back(E->get()->id);
+ for (OAHashMap<int, Point *>::Iterator it = p->neighbours.iter(); it.valid; it = p->neighbours.next_iter(it)) {
+ point_list.push_back((*it.key));
}
return point_list;
@@ -201,9 +235,9 @@ bool AStar::are_points_connected(int p_id, int p_with_id) const {
void AStar::clear() {
- for (const Map<int, Point *>::Element *E = points.front(); E; E = E->next()) {
-
- memdelete(E->get());
+ last_free_id = 0;
+ for (OAHashMap<int, Point *>::Iterator it = points.iter(); it.valid; it = points.next_iter(it)) {
+ memdelete(*(it.value));
}
segments.clear();
points.clear();
@@ -214,14 +248,14 @@ int AStar::get_closest_point(const Vector3 &p_point) const {
int closest_id = -1;
real_t closest_dist = 1e20;
- for (const Map<int, Point *>::Element *E = points.front(); E; E = E->next()) {
+ 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 (!E->get()->enabled)
- continue; //Disabled points should not be considered
- real_t d = p_point.distance_squared_to(E->get()->pos);
+ real_t d = p_point.distance_squared_to((*it.value)->pos);
if (closest_id < 0 || d < closest_dist) {
closest_dist = d;
- closest_id = E->key();
+ closest_id = *(it.key);
}
}
@@ -230,8 +264,8 @@ int AStar::get_closest_point(const Vector3 &p_point) const {
Vector3 AStar::get_closest_position_in_segment(const Vector3 &p_point) const {
- real_t closest_dist = 1e20;
bool found = false;
+ real_t closest_dist = 1e20;
Vector3 closest_point;
for (const Set<Segment>::Element *E = segments.front(); E; E = E->next()) {
@@ -262,8 +296,7 @@ bool AStar::_solve(Point *begin_point, Point *end_point) {
pass++;
- if (!end_point->enabled)
- return false;
+ if (!end_point->enabled) return false;
bool found_route = false;
@@ -272,13 +305,9 @@ bool AStar::_solve(Point *begin_point, Point *end_point) {
begin_point->g_score = 0;
begin_point->f_score = _estimate_cost(begin_point->id, end_point->id);
-
open_list.push_back(begin_point);
- while (true) {
-
- if (open_list.size() == 0) // No path found
- break;
+ while (!open_list.empty()) {
Point *p = open_list[0]; // The currently processed point
@@ -291,24 +320,23 @@ bool AStar::_solve(Point *begin_point, Point *end_point) {
open_list.remove(open_list.size() - 1);
p->closed_pass = pass; // Mark the point as closed
- for (Set<Point *>::Element *E = p->neighbours.front(); E; E = E->next()) {
+ for (OAHashMap<int, Point *>::Iterator it = p->neighbours.iter(); it.valid; it = p->neighbours.next_iter(it)) {
- Point *e = E->get(); // The neighbour point
+ Point *e = *(it.value); // The neighbour point
- if (!e->enabled || e->closed_pass == pass)
+ if (!e->enabled || e->closed_pass == pass) {
continue;
+ }
real_t tentative_g_score = p->g_score + _compute_cost(p->id, e->id) * e->weight_scale;
bool new_point = false;
- if (e->open_pass != pass) { // The point wasn't inside the open list
-
+ if (e->open_pass != pass) { // The point wasn't inside the open list.
e->open_pass = pass;
open_list.push_back(e);
new_point = true;
- } else if (tentative_g_score >= e->g_score) { // The new path is worse than the previous
-
+ } else if (tentative_g_score >= e->g_score) { // The new path is worse than the previous.
continue;
}
@@ -316,10 +344,11 @@ bool AStar::_solve(Point *begin_point, Point *end_point) {
e->g_score = tentative_g_score;
e->f_score = e->g_score + _estimate_cost(e->id, end_point->id);
- if (new_point) // The position of the new points is already known
+ if (new_point) { // The position of the new points is already known.
sorter.push_heap(0, open_list.size() - 1, 0, e, open_list.ptrw());
- else
+ } else {
sorter.push_heap(0, open_list.find(e), 0, e, open_list.ptrw());
+ }
}
}
@@ -331,7 +360,15 @@ float AStar::_estimate_cost(int p_from_id, int p_to_id) {
if (get_script_instance() && get_script_instance()->has_method(SceneStringNames::get_singleton()->_estimate_cost))
return get_script_instance()->call(SceneStringNames::get_singleton()->_estimate_cost, p_from_id, p_to_id);
- return points[p_from_id]->pos.distance_to(points[p_to_id]->pos);
+ Point *from_point;
+ bool from_exists = points.lookup(p_from_id, from_point);
+ CRASH_COND(!from_exists);
+
+ Point *to_point;
+ bool to_exists = points.lookup(p_to_id, to_point);
+ CRASH_COND(!to_exists);
+
+ return from_point->pos.distance_to(to_point->pos);
}
float AStar::_compute_cost(int p_from_id, int p_to_id) {
@@ -339,16 +376,26 @@ float AStar::_compute_cost(int p_from_id, int p_to_id) {
if (get_script_instance() && get_script_instance()->has_method(SceneStringNames::get_singleton()->_compute_cost))
return get_script_instance()->call(SceneStringNames::get_singleton()->_compute_cost, p_from_id, p_to_id);
- return points[p_from_id]->pos.distance_to(points[p_to_id]->pos);
+ Point *from_point;
+ bool from_exists = points.lookup(p_from_id, from_point);
+ CRASH_COND(!from_exists);
+
+ Point *to_point;
+ bool to_exists = points.lookup(p_to_id, to_point);
+ CRASH_COND(!to_exists);
+
+ return from_point->pos.distance_to(to_point->pos);
}
PoolVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) {
- ERR_FAIL_COND_V(!points.has(p_from_id), PoolVector<Vector3>());
- ERR_FAIL_COND_V(!points.has(p_to_id), PoolVector<Vector3>());
+ Point *a;
+ bool from_exists = points.lookup(p_from_id, a);
+ ERR_FAIL_COND_V(!from_exists, PoolVector<Vector3>());
- Point *a = points[p_from_id];
- Point *b = points[p_to_id];
+ Point *b;
+ bool to_exists = points.lookup(p_to_id, b);
+ ERR_FAIL_COND_V(!to_exists, PoolVector<Vector3>());
if (a == b) {
PoolVector<Vector3> ret;
@@ -360,11 +407,8 @@ PoolVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) {
Point *end_point = b;
bool found_route = _solve(begin_point, end_point);
+ if (!found_route) return PoolVector<Vector3>();
- if (!found_route)
- return PoolVector<Vector3>();
-
- // Midpoints
Point *p = end_point;
int pc = 1; // Begin point
while (p != begin_point) {
@@ -393,11 +437,13 @@ PoolVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) {
PoolVector<int> AStar::get_id_path(int p_from_id, int p_to_id) {
- ERR_FAIL_COND_V(!points.has(p_from_id), PoolVector<int>());
- ERR_FAIL_COND_V(!points.has(p_to_id), PoolVector<int>());
+ Point *a;
+ bool from_exists = points.lookup(p_from_id, a);
+ ERR_FAIL_COND_V(!from_exists, PoolVector<int>());
- Point *a = points[p_from_id];
- Point *b = points[p_to_id];
+ Point *b;
+ bool to_exists = points.lookup(p_to_id, b);
+ ERR_FAIL_COND_V(!to_exists, PoolVector<int>());
if (a == b) {
PoolVector<int> ret;
@@ -409,11 +455,8 @@ PoolVector<int> AStar::get_id_path(int p_from_id, int p_to_id) {
Point *end_point = b;
bool found_route = _solve(begin_point, end_point);
+ if (!found_route) return PoolVector<int>();
- if (!found_route)
- return PoolVector<int>();
-
- // Midpoints
Point *p = end_point;
int pc = 1; // Begin point
while (p != begin_point) {
@@ -442,16 +485,20 @@ PoolVector<int> AStar::get_id_path(int p_from_id, int p_to_id) {
void AStar::set_point_disabled(int p_id, bool p_disabled) {
- ERR_FAIL_COND(!points.has(p_id));
+ Point *p;
+ bool p_exists = points.lookup(p_id, p);
+ ERR_FAIL_COND(!p_exists);
- points[p_id]->enabled = !p_disabled;
+ p->enabled = !p_disabled;
}
bool AStar::is_point_disabled(int p_id) const {
- ERR_FAIL_COND_V(!points.has(p_id), false);
+ Point *p;
+ bool p_exists = points.lookup(p_id, p);
+ ERR_FAIL_COND_V(!p_exists, false);
- return !points[p_id]->enabled;
+ return !p->enabled;
}
void AStar::_bind_methods() {
@@ -487,13 +534,11 @@ void AStar::_bind_methods() {
}
AStar::AStar() {
-
+ last_free_id = 0;
pass = 1;
}
AStar::~AStar() {
-
- pass = 1;
clear();
}
diff --git a/core/math/a_star.h b/core/math/a_star.h
index ec333efc1d..53aaaa1f6c 100644
--- a/core/math/a_star.h
+++ b/core/math/a_star.h
@@ -31,8 +31,8 @@
#ifndef ASTAR_H
#define ASTAR_H
+#include "core/oa_hash_map.h"
#include "core/reference.h"
-#include "core/self_list.h"
/**
A* pathfinding algorithm
@@ -44,8 +44,6 @@ class AStar : public Reference {
GDCLASS(AStar, Reference);
- uint64_t pass;
-
struct Point {
int id;
@@ -53,10 +51,10 @@ class AStar : public Reference {
real_t weight_scale;
bool enabled;
- Set<Point *> neighbours;
- Set<Point *> unlinked_neighbours;
+ OAHashMap<int, Point *> neighbours;
+ OAHashMap<int, Point *> unlinked_neighbours;
- // Used for pathfinding
+ // Used for pathfinding.
Point *prev_point;
real_t g_score;
real_t f_score;
@@ -64,16 +62,15 @@ class AStar : public Reference {
uint64_t closed_pass;
};
- Map<int, Point *> points;
-
struct SortPoints {
- _FORCE_INLINE_ bool operator()(const Point *A, const Point *B) const { // Returns true when the Point A is worse than Point B
- if (A->f_score > B->f_score)
+ _FORCE_INLINE_ bool operator()(const Point *A, const Point *B) const { // Returns true when the Point A is worse than Point B.
+ if (A->f_score > B->f_score) {
return true;
- else if (A->f_score < B->f_score)
+ } else if (A->f_score < B->f_score) {
return false;
- else
- return A->g_score < B->g_score; // If the f_costs are the same then prioritize the points that are further away from the start
+ } else {
+ return A->g_score < B->g_score; // If the f_costs are the same then prioritize the points that are further away from the start.
+ }
}
};
@@ -101,6 +98,10 @@ class AStar : public Reference {
}
};
+ int last_free_id;
+ uint64_t pass;
+
+ OAHashMap<int, Point *> points;
Set<Segment> segments;
bool _solve(Point *begin_point, Point *end_point);
diff --git a/core/math/basis.cpp b/core/math/basis.cpp
index 400f342018..2985959113 100644
--- a/core/math/basis.cpp
+++ b/core/math/basis.cpp
@@ -618,10 +618,7 @@ Basis::operator String() const {
Quat Basis::get_quat() const {
#ifdef MATH_CHECKS
- if (!is_rotation()) {
- ERR_EXPLAIN("Basis must be normalized in order to be casted to a Quaternion. Use get_rotation_quat() or call orthonormalized() instead.");
- ERR_FAIL_V(Quat());
- }
+ ERR_FAIL_COND_V_MSG(!is_rotation(), Quat(), "Basis must be normalized in order to be casted to a Quaternion. Use get_rotation_quat() or call orthonormalized() instead.");
#endif
/* Allow getting a quaternion from an unnormalized transform */
Basis m = *this;
diff --git a/core/math/basis.h b/core/math/basis.h
index d3adad3d90..053effda69 100644
--- a/core/math/basis.h
+++ b/core/math/basis.h
@@ -36,10 +36,6 @@
#include "core/math/quat.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
class Basis {
public:
Vector3 elements[3];
diff --git a/core/math/bsp_tree.h b/core/math/bsp_tree.h
index a7a3697990..90b5e8322a 100644
--- a/core/math/bsp_tree.h
+++ b/core/math/bsp_tree.h
@@ -38,9 +38,7 @@
#include "core/pool_vector.h"
#include "core/variant.h"
#include "core/vector.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
+
class BSP_Tree {
public:
enum {
diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h
index 3bcf48f5da..63cc88553d 100644
--- a/core/math/camera_matrix.h
+++ b/core/math/camera_matrix.h
@@ -34,10 +34,6 @@
#include "core/math/rect2.h"
#include "core/math/transform.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
struct CameraMatrix {
enum Planes {
diff --git a/core/math/delaunay.h b/core/math/delaunay.h
index ed52c506db..3f8013a3e6 100644
--- a/core/math/delaunay.h
+++ b/core/math/delaunay.h
@@ -80,11 +80,11 @@ public:
}
static bool edge_compare(const Vector<Vector2> &p_vertices, const Edge &p_a, const Edge &p_b) {
- if (Math::is_zero_approx(p_vertices[p_a.edge[0]].distance_to(p_vertices[p_b.edge[0]])) && Math::is_zero_approx(p_vertices[p_a.edge[1]].distance_to(p_vertices[p_b.edge[1]]))) {
+ if (p_vertices[p_a.edge[0]] == p_vertices[p_b.edge[0]] && p_vertices[p_a.edge[1]] == p_vertices[p_b.edge[1]]) {
return true;
}
- if (Math::is_zero_approx(p_vertices[p_a.edge[0]].distance_to(p_vertices[p_b.edge[1]])) && Math::is_zero_approx(p_vertices[p_a.edge[1]].distance_to(p_vertices[p_b.edge[0]]))) {
+ if (p_vertices[p_a.edge[0]] == p_vertices[p_b.edge[1]] && p_vertices[p_a.edge[1]] == p_vertices[p_b.edge[0]]) {
return true;
}
diff --git a/core/math/expression.cpp b/core/math/expression.cpp
index 15eea1d308..46f81ce5c3 100644
--- a/core/math/expression.cpp
+++ b/core/math/expression.cpp
@@ -2161,10 +2161,8 @@ Error Expression::parse(const String &p_expression, const Vector<String> &p_inpu
}
Variant Expression::execute(Array p_inputs, Object *p_base, bool p_show_error) {
- if (error_set) {
- ERR_EXPLAIN("There was previously a parse error: " + error_str);
- ERR_FAIL_V(Variant());
- }
+
+ ERR_FAIL_COND_V_MSG(error_set, Variant(), "There was previously a parse error: " + error_str + ".");
execution_error = false;
Variant output;
@@ -2173,10 +2171,7 @@ Variant Expression::execute(Array p_inputs, Object *p_base, bool p_show_error) {
if (err) {
execution_error = true;
error_str = error_txt;
- if (p_show_error) {
- ERR_EXPLAIN(error_str);
- ERR_FAIL_V(Variant());
- }
+ ERR_FAIL_COND_V_MSG(p_show_error, Variant(), error_str);
}
return output;
diff --git a/core/math/geometry.h b/core/math/geometry.h
index e4f3ff799e..82d9884e9b 100644
--- a/core/math/geometry.h
+++ b/core/math/geometry.h
@@ -41,10 +41,6 @@
#include "core/print_string.h"
#include "core/vector.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
class Geometry {
Geometry();
@@ -838,8 +834,7 @@ public:
static Vector<Vector<Point2> > offset_polyline_2d(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) {
- ERR_EXPLAIN("Attempt to offset a polyline like a polygon (use offset_polygon_2d instead).");
- ERR_FAIL_COND_V(p_end_type == END_POLYGON, Vector<Vector<Point2> >());
+ ERR_FAIL_COND_V_MSG(p_end_type == END_POLYGON, Vector<Vector<Point2> >(), "Attempt to offset a polyline like a polygon (use offset_polygon_2d instead).");
return _polypath_offset(p_polygon, p_delta, p_join_type, p_end_type);
}
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index a712356ddc..af845ca01e 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -255,16 +255,16 @@ public:
static _ALWAYS_INLINE_ float round(float p_val) { return (p_val >= 0) ? Math::floor(p_val + 0.5) : -Math::floor(-p_val + 0.5); }
static _ALWAYS_INLINE_ int64_t wrapi(int64_t value, int64_t min, int64_t max) {
- int64_t rng = max - min;
- return (rng != 0) ? min + ((((value - min) % rng) + rng) % rng) : min;
+ int64_t range = max - min;
+ return range == 0 ? min : min + ((((value - min) % range) + range) % range);
}
static _ALWAYS_INLINE_ double wrapf(double value, double min, double max) {
- double rng = max - min;
- return (!is_equal_approx(rng, 0.0)) ? value - (rng * Math::floor((value - min) / rng)) : min;
+ double range = max - min;
+ return is_zero_approx(range) ? min : value - (range * Math::floor((value - min) / range));
}
static _ALWAYS_INLINE_ float wrapf(float value, float min, float max) {
- float rng = max - min;
- return (!is_equal_approx(rng, 0.0f)) ? value - (rng * Math::floor((value - min) / rng)) : min;
+ float range = max - min;
+ return is_zero_approx(range) ? min : value - (range * Math::floor((value - min) / range));
}
// double only, as these functions are mainly used by the editor and not performance-critical,
diff --git a/core/math/octree.h b/core/math/octree.h
index d6fc9776bc..db15c8a1f8 100644
--- a/core/math/octree.h
+++ b/core/math/octree.h
@@ -38,10 +38,6 @@
#include "core/print_string.h"
#include "core/variant.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
typedef uint32_t OctreeElementID;
#define OCTREE_ELEMENT_INVALID_ID 0
@@ -568,10 +564,7 @@ void Octree<T, use_pairs, AL>::_ensure_valid_root(const AABB &p_aabb) {
while (!base.encloses(p_aabb)) {
- if (base.size.x > OCTREE_SIZE_LIMIT) {
- ERR_EXPLAIN("Octree upper size limit reeached, does the AABB supplied contain NAN?");
- ERR_FAIL();
- }
+ ERR_FAIL_COND_MSG(base.size.x > OCTREE_SIZE_LIMIT, "Octree upper size limit reached, does the AABB supplied contain NAN?");
Octant *gp = memnew_allocator(Octant, AL);
octant_count++;
diff --git a/core/math/quat.h b/core/math/quat.h
index 8ed2fa7cc2..3d6602e466 100644
--- a/core/math/quat.h
+++ b/core/math/quat.h
@@ -38,10 +38,6 @@
#include "core/math/math_funcs.h"
#include "core/ustring.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
class Quat {
public:
real_t x, y, z, w;
diff --git a/core/math/transform.cpp b/core/math/transform.cpp
index 7ff7cac914..4056975da8 100644
--- a/core/math/transform.cpp
+++ b/core/math/transform.cpp
@@ -213,3 +213,8 @@ Transform::Transform(const Basis &p_basis, const Vector3 &p_origin) :
basis(p_basis),
origin(p_origin) {
}
+
+Transform::Transform(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz) {
+ basis = Basis(xx, xy, xz, yx, yy, yz, zx, zy, zz);
+ origin = Vector3(ox, oy, oz);
+}
diff --git a/core/math/transform.h b/core/math/transform.h
index 2f43f6b035..4c8d915305 100644
--- a/core/math/transform.h
+++ b/core/math/transform.h
@@ -35,10 +35,6 @@
#include "core/math/basis.h"
#include "core/math/plane.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
class Transform {
public:
Basis basis;
@@ -108,6 +104,7 @@ public:
operator String() const;
+ Transform(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz);
Transform(const Basis &p_basis, const Vector3 &p_origin = Vector3());
Transform() {}
};
diff --git a/core/math/vector2.cpp b/core/math/vector2.cpp
index 779a28be66..972bccc0ac 100644
--- a/core/math/vector2.cpp
+++ b/core/math/vector2.cpp
@@ -98,6 +98,11 @@ real_t Vector2::cross(const Vector2 &p_other) const {
return x * p_other.y - y * p_other.x;
}
+Vector2 Vector2::sign() const {
+
+ return Vector2(SGN(x), SGN(y));
+}
+
Vector2 Vector2::floor() const {
return Vector2(Math::floor(x), Math::floor(y));
@@ -121,6 +126,14 @@ Vector2 Vector2::rotated(real_t p_by) const {
return v;
}
+Vector2 Vector2::posmod(const real_t p_mod) const {
+ return Vector2(Math::fposmod(x, p_mod), Math::fposmod(y, p_mod));
+}
+
+Vector2 Vector2::posmodv(const Vector2 &p_modv) const {
+ return Vector2(Math::fposmod(x, p_modv.x), Math::fposmod(y, p_modv.y));
+}
+
Vector2 Vector2::project(const Vector2 &p_b) const {
return p_b * (dot(p_b) / p_b.length_squared());
}
diff --git a/core/math/vector2.h b/core/math/vector2.h
index 78a1641c1e..1a73831891 100644
--- a/core/math/vector2.h
+++ b/core/math/vector2.h
@@ -38,6 +38,11 @@ struct Vector2i;
struct Vector2 {
+ enum Axis {
+ AXIS_X,
+ AXIS_Y,
+ };
+
union {
real_t x;
real_t width;
@@ -69,6 +74,8 @@ struct Vector2 {
real_t dot(const Vector2 &p_other) const;
real_t cross(const Vector2 &p_other) const;
+ Vector2 posmod(const real_t p_mod) const;
+ Vector2 posmodv(const Vector2 &p_modv) const;
Vector2 project(const Vector2 &p_b) const;
Vector2 plane_project(real_t p_d, const Vector2 &p_vec) const;
@@ -107,8 +114,10 @@ struct Vector2 {
bool operator==(const Vector2 &p_vec2) const;
bool operator!=(const Vector2 &p_vec2) const;
- bool operator<(const Vector2 &p_vec2) const { return (Math::is_equal_approx(x, p_vec2.x)) ? (y < p_vec2.y) : (x < p_vec2.x); }
- bool operator<=(const Vector2 &p_vec2) const { return (Math::is_equal_approx(x, p_vec2.x)) ? (y <= p_vec2.y) : (x < p_vec2.x); }
+ bool operator<(const Vector2 &p_vec2) const { return Math::is_equal_approx(x, p_vec2.x) ? (y < p_vec2.y) : (x < p_vec2.x); }
+ bool operator>(const Vector2 &p_vec2) const { return Math::is_equal_approx(x, p_vec2.x) ? (y > p_vec2.y) : (x > p_vec2.x); }
+ bool operator<=(const Vector2 &p_vec2) const { return Math::is_equal_approx(x, p_vec2.x) ? (y <= p_vec2.y) : (x < p_vec2.x); }
+ bool operator>=(const Vector2 &p_vec2) const { return Math::is_equal_approx(x, p_vec2.x) ? (y >= p_vec2.y) : (x > p_vec2.x); }
real_t angle() const;
@@ -129,6 +138,7 @@ struct Vector2 {
return Vector2(y, -x);
}
+ Vector2 sign() const;
Vector2 floor() const;
Vector2 ceil() const;
Vector2 round() const;
@@ -141,10 +151,7 @@ struct Vector2 {
x = p_x;
y = p_y;
}
- _FORCE_INLINE_ Vector2() {
- x = 0;
- y = 0;
- }
+ _FORCE_INLINE_ Vector2() { x = y = 0; }
};
_FORCE_INLINE_ Vector2 Vector2::plane_project(real_t p_d, const Vector2 &p_vec) const {
@@ -262,6 +269,11 @@ typedef Vector2 Point2;
struct Vector2i {
+ enum Axis {
+ AXIS_X,
+ AXIS_Y,
+ };
+
union {
int x;
int width;
diff --git a/core/math/vector3.h b/core/math/vector3.h
index 45bdfee487..597d3c22a8 100644
--- a/core/math/vector3.h
+++ b/core/math/vector3.h
@@ -31,9 +31,7 @@
#ifndef VECTOR3_H
#define VECTOR3_H
-#include "core/math/math_defs.h"
#include "core/math/math_funcs.h"
-#include "core/typedefs.h"
#include "core/ustring.h"
class Basis;
@@ -110,6 +108,8 @@ struct Vector3 {
_FORCE_INLINE_ real_t distance_to(const Vector3 &p_b) const;
_FORCE_INLINE_ real_t distance_squared_to(const Vector3 &p_b) const;
+ _FORCE_INLINE_ Vector3 posmod(const real_t p_mod) const;
+ _FORCE_INLINE_ Vector3 posmodv(const Vector3 &p_modv) const;
_FORCE_INLINE_ Vector3 project(const Vector3 &p_b) const;
_FORCE_INLINE_ real_t angle_to(const Vector3 &p_b) const;
@@ -141,15 +141,17 @@ struct Vector3 {
_FORCE_INLINE_ bool operator!=(const Vector3 &p_v) const;
_FORCE_INLINE_ bool operator<(const Vector3 &p_v) const;
_FORCE_INLINE_ bool operator<=(const Vector3 &p_v) const;
+ _FORCE_INLINE_ bool operator>(const Vector3 &p_v) const;
+ _FORCE_INLINE_ bool operator>=(const Vector3 &p_v) const;
operator String() const;
- _FORCE_INLINE_ Vector3() { x = y = z = 0; }
_FORCE_INLINE_ Vector3(real_t p_x, real_t p_y, real_t p_z) {
x = p_x;
y = p_y;
z = p_z;
}
+ _FORCE_INLINE_ Vector3() { x = y = z = 0; }
};
// Should be included after class definition, otherwise we get circular refs
@@ -233,6 +235,14 @@ real_t Vector3::distance_squared_to(const Vector3 &p_b) const {
return (p_b - *this).length_squared();
}
+Vector3 Vector3::posmod(const real_t p_mod) const {
+ return Vector3(Math::fposmod(x, p_mod), Math::fposmod(y, p_mod), Math::fposmod(z, p_mod));
+}
+
+Vector3 Vector3::posmodv(const Vector3 &p_modv) const {
+ return Vector3(Math::fposmod(x, p_modv.x), Math::fposmod(y, p_modv.y), Math::fposmod(z, p_modv.z));
+}
+
Vector3 Vector3::project(const Vector3 &p_b) const {
return p_b * (dot(p_b) / p_b.length_squared());
}
@@ -357,6 +367,18 @@ bool Vector3::operator<(const Vector3 &p_v) const {
}
}
+bool Vector3::operator>(const Vector3 &p_v) const {
+
+ if (x == p_v.x) {
+ if (y == p_v.y)
+ return z > p_v.z;
+ else
+ return y > p_v.y;
+ } else {
+ return x > p_v.x;
+ }
+}
+
bool Vector3::operator<=(const Vector3 &p_v) const {
if (Math::is_equal_approx(x, p_v.x)) {
@@ -369,6 +391,18 @@ bool Vector3::operator<=(const Vector3 &p_v) const {
}
}
+bool Vector3::operator>=(const Vector3 &p_v) const {
+
+ if (x == p_v.x) {
+ if (y == p_v.y)
+ return z >= p_v.z;
+ else
+ return y > p_v.y;
+ } else {
+ return x > p_v.x;
+ }
+}
+
_FORCE_INLINE_ Vector3 vec3_cross(const Vector3 &p_a, const Vector3 &p_b) {
return p_a.cross(p_b);
diff --git a/core/message_queue.cpp b/core/message_queue.cpp
index 32d2b805f6..390989ac91 100644
--- a/core/message_queue.cpp
+++ b/core/message_queue.cpp
@@ -52,8 +52,7 @@ Error MessageQueue::push_call(ObjectID p_id, const StringName &p_method, const V
type = ObjectDB::get_instance(p_id)->get_class();
print_line("Failed method: " + type + ":" + p_method + " target ID: " + itos(p_id));
statistics();
- ERR_EXPLAIN("Message queue out of memory. Try increasing 'message_queue_size_kb' in project settings.");
- ERR_FAIL_V(ERR_OUT_OF_MEMORY);
+ ERR_FAIL_V_MSG(ERR_OUT_OF_MEMORY, "Message queue out of memory. Try increasing 'message_queue_size_kb' in project settings.");
}
Message *msg = memnew_placement(&buffer[buffer_end], Message);
@@ -103,8 +102,7 @@ Error MessageQueue::push_set(ObjectID p_id, const StringName &p_prop, const Vari
type = ObjectDB::get_instance(p_id)->get_class();
print_line("Failed set: " + type + ":" + p_prop + " target ID: " + itos(p_id));
statistics();
- ERR_EXPLAIN("Message queue out of memory. Try increasing 'message_queue_size_kb' in project settings.");
- ERR_FAIL_V(ERR_OUT_OF_MEMORY);
+ ERR_FAIL_V_MSG(ERR_OUT_OF_MEMORY, "Message queue out of memory. Try increasing 'message_queue_size_kb' in project settings.");
}
Message *msg = memnew_placement(&buffer[buffer_end], Message);
@@ -136,8 +134,7 @@ Error MessageQueue::push_notification(ObjectID p_id, int p_notification) {
type = ObjectDB::get_instance(p_id)->get_class();
print_line("Failed notification: " + itos(p_notification) + " target ID: " + itos(p_id));
statistics();
- ERR_EXPLAIN("Message queue out of memory. Try increasing 'message_queue_size_kb' in project settings.");
- ERR_FAIL_V(ERR_OUT_OF_MEMORY);
+ ERR_FAIL_V_MSG(ERR_OUT_OF_MEMORY, "Message queue out of memory. Try increasing 'message_queue_size_kb' in project settings.");
}
Message *msg = memnew_placement(&buffer[buffer_end], Message);
@@ -256,7 +253,7 @@ void MessageQueue::_call_function(Object *p_target, const StringName &p_func, co
p_target->call(p_func, argptrs, p_argcount, ce);
if (p_show_error && ce.error != Variant::CallError::CALL_OK) {
- ERR_PRINTS("Error calling deferred method: " + Variant::get_call_error_text(p_target, p_func, argptrs, p_argcount, ce));
+ ERR_PRINTS("Error calling deferred method: " + Variant::get_call_error_text(p_target, p_func, argptrs, p_argcount, ce) + ".");
}
}
diff --git a/core/method_bind.h b/core/method_bind.h
index 1b0c3b27c0..7bb75e778f 100644
--- a/core/method_bind.h
+++ b/core/method_bind.h
@@ -38,10 +38,6 @@
#include <stdio.h>
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
#ifdef DEBUG_ENABLED
#define DEBUG_METHODS_ENABLED
#endif
diff --git a/core/node_path.cpp b/core/node_path.cpp
index a4b7cbe2eb..8244785d84 100644
--- a/core/node_path.cpp
+++ b/core/node_path.cpp
@@ -375,8 +375,7 @@ NodePath::NodePath(const String &p_path) {
if (str == "") {
if (path[i] == 0) continue; // Allow end-of-path :
- ERR_EXPLAIN("Invalid NodePath: " + p_path);
- ERR_FAIL();
+ ERR_FAIL_MSG("Invalid NodePath: " + p_path + ".");
}
subpath.push_back(str);
diff --git a/core/node_path.h b/core/node_path.h
index 24725123d6..1b21c4ef1c 100644
--- a/core/node_path.h
+++ b/core/node_path.h
@@ -34,10 +34,6 @@
#include "core/string_name.h"
#include "core/ustring.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
class NodePath {
struct Data {
diff --git a/core/oa_hash_map.h b/core/oa_hash_map.h
index e52d36a859..83621bec14 100644
--- a/core/oa_hash_map.h
+++ b/core/oa_hash_map.h
@@ -62,7 +62,7 @@ private:
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) {
+ _FORCE_INLINE_ uint32_t _hash(const TKey &p_key) const {
uint32_t hash = Hasher::hash(p_key);
if (hash == EMPTY_HASH) {
@@ -74,7 +74,7 @@ private:
return hash;
}
- _FORCE_INLINE_ uint32_t _get_probe_length(uint32_t p_pos, uint32_t p_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;
@@ -90,7 +90,7 @@ private:
num_elements++;
}
- bool _lookup_pos(const TKey &p_key, uint32_t &r_pos) {
+ bool _lookup_pos(const TKey &p_key, uint32_t &r_pos) const {
uint32_t hash = _hash(p_key);
uint32_t pos = hash % capacity;
uint32_t distance = 0;
@@ -151,6 +151,7 @@ private:
distance++;
}
}
+
void _resize_and_rehash() {
TKey *old_keys = keys;
@@ -190,6 +191,26 @@ public:
_FORCE_INLINE_ uint32_t get_capacity() const { return capacity; }
_FORCE_INLINE_ uint32_t get_num_elements() const { return num_elements; }
+ bool empty() const {
+ return num_elements == 0;
+ }
+
+ void clear() {
+
+ for (uint32_t i = 0; i < capacity; i++) {
+
+ if (hashes[i] & DELETED_HASH_BIT) {
+ continue;
+ }
+
+ hashes[i] |= DELETED_HASH_BIT;
+ values[i].~TValue();
+ keys[i].~TKey();
+ }
+
+ num_elements = 0;
+ }
+
void insert(const TKey &p_key, const TValue &p_value) {
if ((float)num_elements / (float)capacity > 0.9) {
@@ -219,7 +240,7 @@ public:
* if r_data is not NULL then the value will be written to the object
* it points to.
*/
- bool lookup(const TKey &p_key, TValue &r_data) {
+ bool lookup(const TKey &p_key, TValue &r_data) const {
uint32_t pos = 0;
bool exists = _lookup_pos(p_key, pos);
@@ -232,7 +253,7 @@ public:
return false;
}
- _FORCE_INLINE_ bool has(const TKey &p_key) {
+ _FORCE_INLINE_ bool has(const TKey &p_key) const {
uint32_t _pos = 0;
return _lookup_pos(p_key, _pos);
}
@@ -302,6 +323,9 @@ public:
return it;
}
+ OAHashMap(const OAHashMap &) = delete; // Delete the copy constructor so we don't get unexpected copies and dangling pointers.
+ OAHashMap &operator=(const OAHashMap &) = delete; // Same for assignment operator.
+
OAHashMap(uint32_t p_initial_capacity = 64) {
capacity = p_initial_capacity;
diff --git a/core/object.cpp b/core/object.cpp
index 3367d6b6c3..62bfa31480 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -709,20 +709,17 @@ static void _test_call_error(const StringName &p_func, const Variant::CallError
break;
case Variant::CallError::CALL_ERROR_INVALID_ARGUMENT: {
- ERR_EXPLAIN("Error Calling Function: " + String(p_func) + " - Invalid type for argument " + itos(error.argument) + ", expected " + Variant::get_type_name(error.expected));
- ERR_FAIL();
+ ERR_FAIL_MSG("Error calling function: " + String(p_func) + " - Invalid type for argument " + itos(error.argument) + ", expected " + Variant::get_type_name(error.expected) + ".");
break;
}
case Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS: {
- ERR_EXPLAIN("Error Calling Function: " + String(p_func) + " - Too many arguments, expected " + itos(error.argument));
- ERR_FAIL();
+ ERR_FAIL_MSG("Error calling function: " + String(p_func) + " - Too many arguments, expected " + itos(error.argument) + ".");
break;
}
case Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS: {
- ERR_EXPLAIN("Error Calling Function: " + String(p_func) + " - Too few arguments, expected " + itos(error.argument));
- ERR_FAIL();
+ ERR_FAIL_MSG("Error calling function: " + String(p_func) + " - Too few arguments, expected " + itos(error.argument) + ".");
break;
}
case Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL:
@@ -739,15 +736,9 @@ void Object::call_multilevel(const StringName &p_method, const Variant **p_args,
if (p_method == CoreStringNames::get_singleton()->_free) {
#ifdef DEBUG_ENABLED
- if (Object::cast_to<Reference>(this)) {
- ERR_EXPLAIN("Can't 'free' a reference.");
- ERR_FAIL();
- }
+ ERR_FAIL_COND_MSG(Object::cast_to<Reference>(this), "Can't 'free' a reference.");
- if (_lock_index.get() > 1) {
- ERR_EXPLAIN("Object is locked and can't be freed.");
- ERR_FAIL();
- }
+ ERR_FAIL_COND_MSG(_lock_index.get() > 1, "Object is locked and can't be freed.");
#endif
//must be here, must be before everything,
@@ -835,8 +826,7 @@ Variant Object::callv(const StringName &p_method, const Array &p_args) {
Variant::CallError ce;
Variant ret = call(p_method, argptrs, p_args.size(), ce);
if (ce.error != Variant::CallError::CALL_OK) {
- ERR_EXPLAIN("Error calling method from 'callv': " + Variant::get_call_error_text(this, p_method, argptrs, p_args.size(), ce));
- ERR_FAIL_V(Variant());
+ ERR_FAIL_V_MSG(Variant(), "Error calling method from 'callv': " + Variant::get_call_error_text(this, p_method, argptrs, p_args.size(), ce) + ".");
}
return ret;
}
@@ -888,15 +878,13 @@ Variant Object::call(const StringName &p_method, const Variant **p_args, int p_a
if (Object::cast_to<Reference>(this)) {
r_error.argument = 0;
r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
- ERR_EXPLAIN("Can't 'free' a reference.");
- ERR_FAIL_V(Variant());
+ ERR_FAIL_V_MSG(Variant(), "Can't 'free' a reference.");
}
if (_lock_index.get() > 1) {
r_error.argument = 0;
r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
- ERR_EXPLAIN("Object is locked and can't be freed.");
- ERR_FAIL_V(Variant());
+ ERR_FAIL_V_MSG(Variant(), "Object is locked and can't be freed.");
}
#endif
@@ -1172,10 +1160,7 @@ Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int
#ifdef DEBUG_ENABLED
bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_name);
//check in script
- if (!signal_is_valid && !script.is_null() && !Ref<Script>(script)->has_script_signal(p_name)) {
- ERR_EXPLAIN("Can't emit non-existing signal " + String("\"") + p_name + "\".");
- ERR_FAIL_V(ERR_UNAVAILABLE);
- }
+ ERR_FAIL_COND_V_MSG(!signal_is_valid && !script.is_null() && !Ref<Script>(script)->has_script_signal(p_name), ERR_UNAVAILABLE, "Can't emit non-existing signal " + String("\"") + p_name + "\".");
#endif
//not connected? just return
return ERR_UNAVAILABLE;
@@ -1240,7 +1225,7 @@ Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int
if (ce.error == Variant::CallError::CALL_ERROR_INVALID_METHOD && !ClassDB::class_exists(target->get_class_name())) {
//most likely object is not initialized yet, do not throw error.
} else {
- ERR_PRINTS("Error calling method from signal '" + String(p_name) + "': " + Variant::get_call_error_text(target, c.method, args, argc, ce));
+ ERR_PRINTS("Error calling method from signal '" + String(p_name) + "': " + Variant::get_call_error_text(target, c.method, args, argc, ce) + ".");
err = ERR_METHOD_NOT_FOUND;
}
}
@@ -1415,8 +1400,9 @@ void Object::get_signal_connection_list(const StringName &p_signal, List<Connect
p_connections->push_back(s->slot_map.getv(i).conn);
}
-bool Object::has_persistent_signal_connections() const {
+int Object::get_persistent_signal_connection_count() const {
+ int count = 0;
const StringName *S = NULL;
while ((S = signal_map.next(S))) {
@@ -1424,13 +1410,13 @@ bool Object::has_persistent_signal_connections() const {
const Signal *s = &signal_map[*S];
for (int i = 0; i < s->slot_map.size(); i++) {
-
- if (s->slot_map.getv(i).conn.flags & CONNECT_PERSIST)
- return true;
+ if (s->slot_map.getv(i).conn.flags & CONNECT_PERSIST) {
+ count += 1;
+ }
}
}
- return false;
+ return count;
}
void Object::get_signals_connected_to_this(List<Connection> *p_connections) const {
@@ -1463,10 +1449,8 @@ Error Object::connect(const StringName &p_signal, Object *p_to_object, const Str
#endif
}
- if (!signal_is_valid) {
- ERR_EXPLAIN("In Object of type '" + String(get_class()) + "': Attempt to connect nonexistent signal '" + p_signal + "' to method '" + p_to_object->get_class() + "." + p_to_method + "'");
- ERR_FAIL_V(ERR_INVALID_PARAMETER);
- }
+ ERR_FAIL_COND_V_MSG(!signal_is_valid, ERR_INVALID_PARAMETER, "In Object of type '" + String(get_class()) + "': Attempt to connect nonexistent signal '" + p_signal + "' to method '" + p_to_object->get_class() + "." + p_to_method + "'.");
+
signal_map[p_signal] = Signal();
s = &signal_map[p_signal];
}
@@ -1477,8 +1461,7 @@ Error Object::connect(const StringName &p_signal, Object *p_to_object, const Str
s->slot_map[target].reference_count++;
return OK;
} else {
- ERR_EXPLAIN("Signal '" + p_signal + "' is already connected to given method '" + p_to_method + "' in that object.");
- ERR_FAIL_V(ERR_INVALID_PARAMETER);
+ ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Signal '" + p_signal + "' is already connected to given method '" + p_to_method + "' in that object.");
}
}
@@ -1514,8 +1497,7 @@ bool Object::is_connected(const StringName &p_signal, Object *p_to_object, const
if (!script.is_null() && Ref<Script>(script)->has_script_signal(p_signal))
return false;
- ERR_EXPLAIN("Nonexistent signal: " + p_signal);
- ERR_FAIL_V(false);
+ ERR_FAIL_V_MSG(false, "Nonexistent signal: " + p_signal + ".");
}
Signal::Target target(p_to_object->get_instance_id(), p_to_method);
@@ -1533,21 +1515,13 @@ void Object::_disconnect(const StringName &p_signal, Object *p_to_object, const
ERR_FAIL_NULL(p_to_object);
Signal *s = signal_map.getptr(p_signal);
- if (!s) {
- ERR_EXPLAIN("Nonexistent signal: " + p_signal);
- ERR_FAIL();
- }
- if (s->lock > 0) {
- ERR_EXPLAIN("Attempt to disconnect signal '" + p_signal + "' while emitting (locks: " + itos(s->lock) + ")");
- ERR_FAIL();
- }
+ ERR_FAIL_COND_MSG(!s, "Nonexistent signal: " + p_signal + ".");
+
+ ERR_FAIL_COND_MSG(s->lock > 0, "Attempt to disconnect signal '" + p_signal + "' while emitting (locks: " + itos(s->lock) + ").");
Signal::Target target(p_to_object->get_instance_id(), p_to_method);
- if (!s->slot_map.has(target)) {
- ERR_EXPLAIN("Disconnecting nonexistent signal '" + p_signal + "', slot: " + itos(target._id) + ":" + target.method);
- ERR_FAIL();
- }
+ ERR_FAIL_COND_MSG(!s->slot_map.has(target), "Disconnecting nonexistent signal '" + p_signal + "', slot: " + itos(target._id) + ":" + target.method + ".");
Signal::Slot *slot = &s->slot_map[target];
@@ -1974,10 +1948,7 @@ Object::~Object() {
Signal *s = &signal_map[*S];
- if (s->lock) {
- ERR_EXPLAIN("Attempt to delete an object in the middle of a signal emission from it");
- ERR_CONTINUE(s->lock > 0);
- }
+ ERR_CONTINUE_MSG(s->lock > 0, "Attempt to delete an object in the middle of a signal emission from it.");
//brute force disconnect for performance
int slot_count = s->slot_map.size();
diff --git a/core/object.h b/core/object.h
index dce1cc74ae..ac8620757c 100644
--- a/core/object.h
+++ b/core/object.h
@@ -707,7 +707,7 @@ public:
void get_signal_list(List<MethodInfo> *p_signals) const;
void get_signal_connection_list(const StringName &p_signal, List<Connection> *p_connections) const;
void get_all_signal_connections(List<Connection> *p_connections) const;
- bool has_persistent_signal_connections() const;
+ int get_persistent_signal_connection_count() const;
void get_signals_connected_to_this(List<Connection> *p_connections) const;
Error connect(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method, const Vector<Variant> &p_binds = Vector<Variant>(), uint32_t p_flags = 0);
@@ -794,8 +794,13 @@ public:
static int get_object_count();
_FORCE_INLINE_ static bool instance_validate(Object *p_ptr) {
+ rw_lock->read_lock();
- return instance_checks.has(p_ptr);
+ bool exists = instance_checks.has(p_ptr);
+
+ rw_lock->read_unlock();
+
+ return exists;
}
};
diff --git a/core/os/dir_access.h b/core/os/dir_access.h
index 704eedae5b..d3eb1e13f6 100644
--- a/core/os/dir_access.h
+++ b/core/os/dir_access.h
@@ -34,10 +34,6 @@
#include "core/typedefs.h"
#include "core/ustring.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
//@ TODO, excellent candidate for THREAD_SAFE MACRO, should go through all these and add THREAD_SAFE where it applies
class DirAccess {
public:
@@ -97,6 +93,18 @@ public:
virtual Error rename(String p_from, String p_to) = 0;
virtual Error remove(String p_name) = 0;
+ // Meant for editor code when we want to quickly remove a file without custom
+ // handling (e.g. removing a cache file).
+ static void remove_file_or_error(String p_path) {
+ DirAccess *da = create(ACCESS_FILESYSTEM);
+ if (da->file_exists(p_path)) {
+ if (da->remove(p_path) != OK) {
+ ERR_FAIL_MSG("Cannot remove file or directory: " + p_path);
+ }
+ }
+ memdelete(da);
+ }
+
virtual String get_filesystem_type() const = 0;
static String get_full_path(const String &p_path, AccessType p_access);
static DirAccess *create_for_path(const String &p_path);
diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp
index 7509050b2b..9a8315a3bb 100644
--- a/core/os/file_access.cpp
+++ b/core/os/file_access.cpp
@@ -30,9 +30,9 @@
#include "file_access.h"
+#include "core/crypto/crypto_core.h"
#include "core/io/file_access_pack.h"
#include "core/io/marshalls.h"
-#include "core/math/crypto_core.h"
#include "core/os/os.h"
#include "core/project_settings.h"
@@ -599,8 +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_EXPLAIN("Can't open file from path: " + String(p_path));
- ERR_FAIL_V(Vector<uint8_t>());
+ 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());
@@ -620,8 +619,7 @@ String FileAccess::get_file_as_string(const String &p_path, Error *r_error) {
if (r_error) {
return String();
}
- ERR_EXPLAIN("Can't get file as string from path: " + String(p_path));
- ERR_FAIL_V(String());
+ ERR_FAIL_V_MSG(String(), "Can't get file as string from path: " + String(p_path) + ".");
}
String ret;
diff --git a/core/os/input.cpp b/core/os/input.cpp
index f04d4a1b3e..51cb41b184 100644
--- a/core/os/input.cpp
+++ b/core/os/input.cpp
@@ -80,6 +80,7 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_joy_axis_index_from_string", "axis"), &Input::get_joy_axis_index_from_string);
ClassDB::bind_method(D_METHOD("start_joy_vibration", "device", "weak_magnitude", "strong_magnitude", "duration"), &Input::start_joy_vibration, DEFVAL(0));
ClassDB::bind_method(D_METHOD("stop_joy_vibration", "device"), &Input::stop_joy_vibration);
+ ClassDB::bind_method(D_METHOD("vibrate_handheld", "duration_ms"), &Input::vibrate_handheld, DEFVAL(500));
ClassDB::bind_method(D_METHOD("get_gravity"), &Input::get_gravity);
ClassDB::bind_method(D_METHOD("get_accelerometer"), &Input::get_accelerometer);
ClassDB::bind_method(D_METHOD("get_magnetometer"), &Input::get_magnetometer);
diff --git a/core/os/input.h b/core/os/input.h
index de04f239e6..a12ded176b 100644
--- a/core/os/input.h
+++ b/core/os/input.h
@@ -100,6 +100,7 @@ public:
virtual uint64_t get_joy_vibration_timestamp(int p_device) = 0;
virtual void start_joy_vibration(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration = 0) = 0;
virtual void stop_joy_vibration(int p_device) = 0;
+ virtual void vibrate_handheld(int p_duration_ms = 500) = 0;
virtual Point2 get_mouse_position() const = 0;
virtual Point2 get_last_mouse_speed() const = 0;
diff --git a/core/os/input_event.h b/core/os/input_event.h
index 4f5762e756..28658e3865 100644
--- a/core/os/input_event.h
+++ b/core/os/input_event.h
@@ -38,10 +38,6 @@
#include "core/ustring.h"
/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-/**
* Input Event classes. These are used in the main loop.
* The events are pretty obvious.
*/
diff --git a/core/os/keyboard.h b/core/os/keyboard.h
index 58a0807579..5c8a2e90e9 100644
--- a/core/os/keyboard.h
+++ b/core/os/keyboard.h
@@ -33,10 +33,6 @@
#include "core/ustring.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
/*
Special Key:
diff --git a/core/os/main_loop.h b/core/os/main_loop.h
index ad734d3fc8..6ddaf5bee7 100644
--- a/core/os/main_loop.h
+++ b/core/os/main_loop.h
@@ -35,10 +35,6 @@
#include "core/reference.h"
#include "core/script_language.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
class MainLoop : public Object {
GDCLASS(MainLoop, Object);
diff --git a/core/os/memory.h b/core/os/memory.h
index e073b11e76..8778cb63ad 100644
--- a/core/os/memory.h
+++ b/core/os/memory.h
@@ -35,10 +35,6 @@
#include <stddef.h>
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
#ifndef PAD_ALIGN
#define PAD_ALIGN 16 //must always be greater than this at much
#endif
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 925154af7d..7531900480 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -186,6 +186,11 @@ int OS::get_process_id() const {
return -1;
};
+void OS::vibrate_handheld(int p_duration_ms) {
+
+ WARN_PRINTS("vibrate_handheld() only works with Android and iOS");
+}
+
bool OS::is_stdout_verbose() const {
return _verbose_stdout;
@@ -268,8 +273,7 @@ void OS::print_all_resources(String p_to_file) {
_OSPRF = FileAccess::open(p_to_file, FileAccess::WRITE, &err);
if (err != OK) {
_OSPRF = NULL;
- ERR_EXPLAIN("Can't print all resources to file: " + String(p_to_file));
- ERR_FAIL();
+ ERR_FAIL_MSG("Can't print all resources to file: " + String(p_to_file) + ".");
}
}
@@ -487,10 +491,7 @@ void OS::_ensure_user_data_dir() {
da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
Error err = da->make_dir_recursive(dd);
- if (err != OK) {
- ERR_EXPLAIN("Error attempting to create data dir: " + dd);
- }
- ERR_FAIL_COND(err != OK);
+ ERR_FAIL_COND_MSG(err != OK, "Error attempting to create data dir: " + dd + ".");
memdelete(da);
}
diff --git a/core/os/os.h b/core/os/os.h
index 2224d3b006..e627773d88 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -41,10 +41,6 @@
#include <stdarg.h>
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
class Mutex;
class OS {
@@ -269,6 +265,7 @@ public:
virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false, Mutex *p_pipe_mutex = NULL) = 0;
virtual Error kill(const ProcessID &p_pid) = 0;
virtual int get_process_id() const;
+ virtual void vibrate_handheld(int p_duration_ms = 500);
virtual Error shell_open(String p_uri);
virtual Error set_cwd(const String &p_cwd);
diff --git a/core/os/semaphore.h b/core/os/semaphore.h
index ccbba0dacd..a0862dce84 100644
--- a/core/os/semaphore.h
+++ b/core/os/semaphore.h
@@ -33,10 +33,6 @@
#include "core/error_list.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
class Semaphore {
protected:
static Semaphore *(*create_func)();
diff --git a/core/os/thread.h b/core/os/thread.h
index e7a6e8cb1f..169280a208 100644
--- a/core/os/thread.h
+++ b/core/os/thread.h
@@ -34,10 +34,6 @@
#include "core/typedefs.h"
#include "core/ustring.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
typedef void (*ThreadCreateCallback)(void *p_userdata);
class Thread {
diff --git a/core/pool_allocator.cpp b/core/pool_allocator.cpp
index 9b342ef913..6c1f2756f2 100644
--- a/core/pool_allocator.cpp
+++ b/core/pool_allocator.cpp
@@ -204,10 +204,8 @@ PoolAllocator::ID PoolAllocator::alloc(int p_size) {
/* Then search again */
if (!find_hole(&new_entry_indices_pos, size_to_alloc)) {
-
mt_unlock();
- ERR_EXPLAIN("Memory can't be compacted further");
- ERR_FAIL_V(POOL_ALLOCATOR_INVALID_ID);
+ ERR_FAIL_V_MSG(POOL_ALLOCATOR_INVALID_ID, "Memory can't be compacted further.");
}
}
@@ -217,8 +215,7 @@ PoolAllocator::ID PoolAllocator::alloc(int p_size) {
if (!found_free_entry) {
mt_unlock();
- ERR_EXPLAIN("No free entry found in PoolAllocator");
- ERR_FAIL_V(POOL_ALLOCATOR_INVALID_ID);
+ ERR_FAIL_V_MSG(POOL_ALLOCATOR_INVALID_ID, "No free entry found in PoolAllocator.");
}
/* move all entry indices up, make room for this one */
@@ -539,6 +536,10 @@ void PoolAllocator::unlock(ID p_mem) {
return;
mt_lock();
Entry *e = get_entry(p_mem);
+ if (!e) {
+ mt_unlock();
+ ERR_FAIL_COND(!e);
+ }
if (e->lock == 0) {
mt_unlock();
ERR_PRINT("e->lock == 0");
diff --git a/core/pool_vector.cpp b/core/pool_vector.cpp
index b9d2316315..50ea898bef 100644
--- a/core/pool_vector.cpp
+++ b/core/pool_vector.cpp
@@ -66,6 +66,5 @@ void MemoryPool::cleanup() {
memdelete_arr(allocs);
memdelete(alloc_mutex);
- ERR_EXPLAINC("There are still MemoryPool allocs in use at exit!");
- ERR_FAIL_COND(allocs_used > 0);
+ ERR_FAIL_COND_MSG(allocs_used > 0, "There are still MemoryPool allocs in use at exit!");
}
diff --git a/core/pool_vector.h b/core/pool_vector.h
index 3d28d86803..957a72483c 100644
--- a/core/pool_vector.h
+++ b/core/pool_vector.h
@@ -77,10 +77,6 @@ struct MemoryPool {
static void cleanup();
};
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
template <class T>
class PoolVector {
@@ -102,8 +98,7 @@ class PoolVector {
MemoryPool::alloc_mutex->lock();
if (MemoryPool::allocs_used == MemoryPool::alloc_count) {
MemoryPool::alloc_mutex->unlock();
- ERR_EXPLAINC("All memory pool allocations are in use, can't COW.");
- ERR_FAIL();
+ ERR_FAIL_MSG("All memory pool allocations are in use, can't COW.");
}
MemoryPool::Alloc *old_alloc = alloc;
@@ -524,8 +519,7 @@ Error PoolVector<T>::resize(int p_size) {
MemoryPool::alloc_mutex->lock();
if (MemoryPool::allocs_used == MemoryPool::alloc_count) {
MemoryPool::alloc_mutex->unlock();
- ERR_EXPLAINC("All memory pool allocations are in use.");
- ERR_FAIL_V(ERR_OUT_OF_MEMORY);
+ ERR_FAIL_V_MSG(ERR_OUT_OF_MEMORY, "All memory pool allocations are in use.");
}
//take one from the free list
diff --git a/core/project_settings.cpp b/core/project_settings.cpp
index c1d4967f55..eb88143db3 100644
--- a/core/project_settings.cpp
+++ b/core/project_settings.cpp
@@ -500,8 +500,7 @@ Error ProjectSettings::_load_settings_binary(const String &p_path) {
if (hdr[0] != 'E' || hdr[1] != 'C' || hdr[2] != 'F' || hdr[3] != 'G') {
memdelete(f);
- ERR_EXPLAIN("Corrupted header in binary project.binary (not ECFG)");
- ERR_FAIL_V(ERR_FILE_CORRUPT);
+ ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Corrupted header in binary project.binary (not ECFG).");
}
uint32_t count = f->get_32();
@@ -522,8 +521,7 @@ Error ProjectSettings::_load_settings_binary(const String &p_path) {
f->get_buffer(d.ptrw(), vlen);
Variant value;
err = decode_variant(value, d.ptr(), d.size(), NULL, true);
- ERR_EXPLAIN("Error decoding property: " + key);
- ERR_CONTINUE(err != OK);
+ ERR_CONTINUE_MSG(err != OK, "Error decoding property: " + key + ".");
set(key, value);
}
@@ -577,8 +575,7 @@ Error ProjectSettings::_load_settings_text(const String &p_path) {
config_version = value;
if (config_version > CONFIG_VERSION) {
memdelete(f);
- ERR_EXPLAIN(vformat("Can't open project at '%s', its `config_version` (%d) is from a more recent and incompatible version of the engine. Expected config version: %d.", p_path, config_version, CONFIG_VERSION));
- ERR_FAIL_V(ERR_FILE_CANT_OPEN);
+ ERR_FAIL_V_MSG(ERR_FILE_CANT_OPEN, vformat("Can't open project at '%s', its `config_version` (%d) is from a more recent and incompatible version of the engine. Expected config version: %d.", p_path, config_version, CONFIG_VERSION));
}
} else {
if (section == String()) {
@@ -645,11 +642,7 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str
Error err;
FileAccess *file = FileAccess::open(p_file, FileAccess::WRITE, &err);
- if (err != OK) {
-
- ERR_EXPLAIN("Couldn't save project.binary at " + p_file);
- ERR_FAIL_COND_V(err, err);
- }
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Couldn't save project.binary at " + p_file + ".");
uint8_t hdr[4] = { 'E', 'C', 'F', 'G' };
file->store_buffer(hdr, 4);
@@ -738,10 +731,7 @@ Error ProjectSettings::_save_settings_text(const String &p_file, const Map<Strin
Error err;
FileAccess *file = FileAccess::open(p_file, FileAccess::WRITE, &err);
- if (err) {
- ERR_EXPLAIN("Couldn't save project.godot - " + p_file);
- ERR_FAIL_COND_V(err, err);
- }
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Couldn't save project.godot - " + p_file + ".");
file->store_line("; Engine configuration file.");
file->store_line("; It's best edited using the editor UI and not directly,");
@@ -872,8 +862,7 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust
return _save_settings_binary(p_path, props, p_custom, custom_features);
else {
- ERR_EXPLAIN("Unknown config file format: " + p_path);
- ERR_FAIL_V(ERR_FILE_UNRECOGNIZED);
+ ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "Unknown config file format: " + p_path + ".");
}
}
@@ -1030,6 +1019,9 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("editor/search_in_file_extensions", extensions);
custom_prop_info["editor/search_in_file_extensions"] = PropertyInfo(Variant::POOL_STRING_ARRAY, "editor/search_in_file_extensions");
+ GLOBAL_DEF("editor/script_templates_search_path", "res://script_templates");
+ custom_prop_info["editor/script_templates_search_path"] = PropertyInfo(Variant::STRING, "editor/script_templates_search_path", PROPERTY_HINT_DIR);
+
action = Dictionary();
action["deadzone"] = Variant(0.5f);
events = Array();
diff --git a/core/project_settings.h b/core/project_settings.h
index d7651417d5..a8deab028c 100644
--- a/core/project_settings.h
+++ b/core/project_settings.h
@@ -35,10 +35,6 @@
#include "core/os/thread_safe.h"
#include "core/set.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
class ProjectSettings : public Object {
GDCLASS(ProjectSettings, Object);
diff --git a/core/reference.h b/core/reference.h
index 8a19f846c7..20ee22ddfc 100644
--- a/core/reference.h
+++ b/core/reference.h
@@ -36,9 +36,6 @@
#include "core/ref_ptr.h"
#include "core/safe_refcount.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
class Reference : public Object {
GDCLASS(Reference, Object);
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index e442546124..efc77bde48 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -34,6 +34,8 @@
#include "core/class_db.h"
#include "core/compressed_translation.h"
#include "core/core_string_names.h"
+#include "core/crypto/crypto.h"
+#include "core/crypto/hashing_context.h"
#include "core/engine.h"
#include "core/func_ref.h"
#include "core/input_map.h"
@@ -70,6 +72,8 @@ static Ref<ResourceFormatLoaderBinary> resource_loader_binary;
static Ref<ResourceFormatImporter> resource_format_importer;
static Ref<ResourceFormatLoaderImage> resource_format_image;
static Ref<TranslationLoaderPO> resource_format_po;
+static Ref<ResourceFormatSaverCrypto> resource_format_saver_crypto;
+static Ref<ResourceFormatLoaderCrypto> resource_format_loader_crypto;
static _ResourceLoader *_resource_loader = NULL;
static _ResourceSaver *_resource_saver = NULL;
@@ -151,7 +155,19 @@ void register_core_types() {
ClassDB::register_class<StreamPeerTCP>();
ClassDB::register_class<TCP_Server>();
ClassDB::register_class<PacketPeerUDP>();
+
+ // Crypto
+ ClassDB::register_class<HashingContext>();
+ ClassDB::register_custom_instance_class<X509Certificate>();
+ ClassDB::register_custom_instance_class<CryptoKey>();
+ ClassDB::register_custom_instance_class<Crypto>();
ClassDB::register_custom_instance_class<StreamPeerSSL>();
+
+ resource_format_saver_crypto.instance();
+ ResourceSaver::add_resource_format_saver(resource_format_saver_crypto);
+ resource_format_loader_crypto.instance();
+ ResourceLoader::add_resource_format_loader(resource_format_loader_crypto);
+
ClassDB::register_virtual_class<IP>();
ClassDB::register_virtual_class<PacketPeer>();
ClassDB::register_class<PacketPeerStream>();
@@ -211,6 +227,9 @@ void register_core_settings() {
ProjectSettings::get_singleton()->set_custom_property_info("network/limits/tcp/connect_timeout_seconds", PropertyInfo(Variant::INT, "network/limits/tcp/connect_timeout_seconds", PROPERTY_HINT_RANGE, "1,1800,1"));
GLOBAL_DEF_RST("network/limits/packet_peer_stream/max_buffer_po2", (16));
ProjectSettings::get_singleton()->set_custom_property_info("network/limits/packet_peer_stream/max_buffer_po2", PropertyInfo(Variant::INT, "network/limits/packet_peer_stream/max_buffer_po2", PROPERTY_HINT_RANGE, "0,64,1,or_greater"));
+
+ GLOBAL_DEF("network/ssl/certificates", "");
+ ProjectSettings::get_singleton()->set_custom_property_info("network/ssl/certificates", PropertyInfo(Variant::STRING, "network/ssl/certificates", PROPERTY_HINT_FILE, "*.crt"));
}
void register_core_singletons() {
@@ -272,6 +291,11 @@ void unregister_core_types() {
ResourceLoader::remove_resource_format_loader(resource_format_po);
resource_format_po.unref();
+ ResourceSaver::remove_resource_format_saver(resource_format_saver_crypto);
+ resource_format_saver_crypto.unref();
+ ResourceLoader::remove_resource_format_loader(resource_format_loader_crypto);
+ resource_format_loader_crypto.unref();
+
if (ip)
memdelete(ip);
diff --git a/core/register_core_types.h b/core/register_core_types.h
index b5a6aa985b..2d397b55f9 100644
--- a/core/register_core_types.h
+++ b/core/register_core_types.h
@@ -31,10 +31,6 @@
#ifndef REGISTER_CORE_TYPES_H
#define REGISTER_CORE_TYPES_H
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
void register_core_types();
void register_core_settings();
void register_core_singletons();
diff --git a/core/resource.cpp b/core/resource.cpp
index 74e2c1ed6b..5a5efa4644 100644
--- a/core/resource.cpp
+++ b/core/resource.cpp
@@ -75,8 +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_EXPLAIN("Another resource is loaded from path: " + p_path + " (possible cyclic resource inclusion)");
- ERR_FAIL_COND(exists);
+ ERR_FAIL_COND_MSG(exists, "Another resource is loaded from path: " + p_path + " (possible cyclic resource inclusion).");
}
}
path_cache = p_path;
@@ -277,8 +276,7 @@ void Resource::notify_change_to_owners() {
for (Set<ObjectID>::Element *E = owners.front(); E; E = E->next()) {
Object *obj = ObjectDB::get_instance(E->get());
- ERR_EXPLAIN("Object was deleted, while still owning a resource");
- ERR_CONTINUE(!obj); //wtf
+ ERR_CONTINUE_MSG(!obj, "Object was deleted, while still owning a resource."); //wtf
//TODO store string
obj->call("resource_changed", RES(this));
}
@@ -427,7 +425,7 @@ Resource::~Resource() {
ResourceCache::lock->write_unlock();
}
if (owners.size()) {
- WARN_PRINT("Resource is still owned");
+ WARN_PRINT("Resource is still owned.");
}
}
diff --git a/core/resource.h b/core/resource.h
index 853b2859c7..038b4f6278 100644
--- a/core/resource.h
+++ b/core/resource.h
@@ -38,10 +38,6 @@
#include "core/safe_refcount.h"
#include "core/self_list.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
#define RES_BASE_EXTENSION(m_ext) \
public: \
static void register_custom_data_to_otdb() { ClassDB::add_resource_base_extension(m_ext, get_class_static()); } \
diff --git a/core/rid.h b/core/rid.h
index c7a71a03a0..381eee645b 100644
--- a/core/rid.h
+++ b/core/rid.h
@@ -37,10 +37,6 @@
#include "core/set.h"
#include "core/typedefs.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
class RID_OwnerBase;
class RID_Data {
diff --git a/core/safe_refcount.h b/core/safe_refcount.h
index 54f540b0c7..0b65ffb9ca 100644
--- a/core/safe_refcount.h
+++ b/core/safe_refcount.h
@@ -97,8 +97,8 @@ static _ALWAYS_INLINE_ T atomic_exchange_if_greater(volatile T *pw, volatile V v
/* Implementation for GCC & Clang */
-// GCC guarantees atomic intrinsics for sizes of 1, 2, 4 and 8 bytes.
-// Clang states it supports GCC atomic builtins.
+#include <stdbool.h>
+#include <atomic>
template <class T>
static _ALWAYS_INLINE_ T atomic_conditional_increment(volatile T *pw) {
@@ -107,7 +107,7 @@ static _ALWAYS_INLINE_ T atomic_conditional_increment(volatile T *pw) {
T tmp = static_cast<T const volatile &>(*pw);
if (tmp == 0)
return 0; // if zero, can't add to it anymore
- if (__sync_val_compare_and_swap(pw, tmp, tmp + 1) == tmp)
+ if (__atomic_compare_exchange_n(pw, &tmp, tmp + 1, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) == true)
return tmp + 1;
}
}
@@ -115,25 +115,25 @@ static _ALWAYS_INLINE_ T atomic_conditional_increment(volatile T *pw) {
template <class T>
static _ALWAYS_INLINE_ T atomic_decrement(volatile T *pw) {
- return __sync_sub_and_fetch(pw, 1);
+ return __atomic_sub_fetch(pw, 1, __ATOMIC_SEQ_CST);
}
template <class T>
static _ALWAYS_INLINE_ T atomic_increment(volatile T *pw) {
- return __sync_add_and_fetch(pw, 1);
+ return __atomic_add_fetch(pw, 1, __ATOMIC_SEQ_CST);
}
template <class T, class V>
static _ALWAYS_INLINE_ T atomic_sub(volatile T *pw, volatile V val) {
- return __sync_sub_and_fetch(pw, val);
+ return __atomic_sub_fetch(pw, val, __ATOMIC_SEQ_CST);
}
template <class T, class V>
static _ALWAYS_INLINE_ T atomic_add(volatile T *pw, volatile V val) {
- return __sync_add_and_fetch(pw, val);
+ return __atomic_add_fetch(pw, val, __ATOMIC_SEQ_CST);
}
template <class T, class V>
@@ -143,7 +143,7 @@ static _ALWAYS_INLINE_ T atomic_exchange_if_greater(volatile T *pw, volatile V v
T tmp = static_cast<T const volatile &>(*pw);
if (tmp >= val)
return tmp; // already greater, or equal
- if (__sync_val_compare_and_swap(pw, tmp, val) == tmp)
+ if (__atomic_compare_exchange_n(pw, &tmp, val, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) == true)
return val;
}
}
diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp
index e7ff7a3aef..2a061f0947 100644
--- a/core/script_debugger_remote.cpp
+++ b/core/script_debugger_remote.cpp
@@ -89,7 +89,7 @@ Error ScriptDebuggerRemote::connect_to_host(const String &p_host, uint16_t p_por
if (tcp_client->get_status() != StreamPeerTCP::STATUS_CONNECTED) {
- ERR_PRINTS("Remote Debugger: Unable to connect. Status: " + String::num(tcp_client->get_status()));
+ ERR_PRINTS("Remote Debugger: Unable to connect. Status: " + String::num(tcp_client->get_status()) + ".");
return FAILED;
};
@@ -110,7 +110,7 @@ void ScriptDebuggerRemote::_put_variable(const String &p_name, const Variant &p_
int len = 0;
Error err = encode_variant(var, NULL, len, true);
if (err != OK)
- ERR_PRINT("Failed to encode variant");
+ ERR_PRINT("Failed to encode variant.");
if (len > packet_peer_stream->get_output_buffer_max_size()) { //limit to max size
packet_peer_stream->put_var(Variant());
@@ -134,10 +134,7 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue)
//this function is called when there is a debugger break (bug on script)
//or when execution is paused from editor
- if (!tcp_client->is_connected_to_host()) {
- ERR_EXPLAIN("Script Debugger failed to connect, but being used anyway.");
- ERR_FAIL();
- }
+ ERR_FAIL_COND_MSG(!tcp_client->is_connected_to_host(), "Script Debugger failed to connect, but being used anyway.");
packet_peer_stream->put_var("debug_enter");
packet_peer_stream->put_var(2);
@@ -357,10 +354,11 @@ void ScriptDebuggerRemote::_get_output() {
locking = false;
}
- if (n_errors_dropped > 0) {
+ if (n_errors_dropped == 1) {
+ // Only print one message about dropping per second
OutputError oe;
oe.error = "TOO_MANY_ERRORS";
- oe.error_descr = "Too many errors! " + String::num_int64(n_errors_dropped) + " errors were dropped.";
+ oe.error_descr = "Too many errors! Ignoring errors for up to 1 second.";
oe.warning = false;
uint64_t time = OS::get_singleton()->get_ticks_msec();
oe.hr = time / 3600000;
@@ -368,7 +366,20 @@ void ScriptDebuggerRemote::_get_output() {
oe.sec = (time / 1000) % 60;
oe.msec = time % 1000;
errors.push_back(oe);
- n_errors_dropped = 0;
+ }
+
+ if (n_warnings_dropped == 1) {
+ // Only print one message about dropping per second
+ OutputError oe;
+ oe.error = "TOO_MANY_WARNINGS";
+ oe.error_descr = "Too many warnings! Ignoring warnings for up to 1 second.";
+ oe.warning = true;
+ uint64_t time = OS::get_singleton()->get_ticks_msec();
+ oe.hr = time / 3600000;
+ oe.min = (time / 60000) % 60;
+ oe.sec = (time / 1000) % 60;
+ oe.msec = time % 1000;
+ errors.push_back(oe);
}
while (errors.size()) {
@@ -587,9 +598,19 @@ void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) {
}
}
}
+
if (Node *node = Object::cast_to<Node>(obj)) {
- PropertyInfo pi(Variant::NODE_PATH, String("Node/path"));
- properties.push_front(PropertyDesc(pi, node->get_path()));
+ // in some cases node will not be in tree here
+ // for instance where it created as variable and not yet added to tree
+ // in such cases we can't ask for it's path
+ if (node->is_inside_tree()) {
+ PropertyInfo pi(Variant::NODE_PATH, String("Node/path"));
+ properties.push_front(PropertyDesc(pi, node->get_path()));
+ } else {
+ PropertyInfo pi(Variant::STRING, String("Node/path"));
+ properties.push_front(PropertyDesc(pi, "[Orphan]"));
+ }
+
} else if (Resource *res = Object::cast_to<Resource>(obj)) {
if (Script *s = Object::cast_to<Script>(res)) {
Map<StringName, Variant> constants;
@@ -934,6 +955,19 @@ void ScriptDebuggerRemote::send_error(const String &p_func, const String &p_file
oe.msec = time % 1000;
Array cstack;
+ uint64_t ticks = OS::get_singleton()->get_ticks_usec() / 1000;
+ msec_count += ticks - last_msec;
+ last_msec = ticks;
+
+ if (msec_count > 1000) {
+ msec_count = 0;
+
+ err_count = 0;
+ n_errors_dropped = 0;
+ warn_count = 0;
+ n_warnings_dropped = 0;
+ }
+
cstack.resize(p_stack_info.size() * 3);
for (int i = 0; i < p_stack_info.size(); i++) {
cstack[i * 3 + 0] = p_stack_info[i].file;
@@ -942,15 +976,28 @@ void ScriptDebuggerRemote::send_error(const String &p_func, const String &p_file
}
oe.callstack = cstack;
+ if (oe.warning) {
+ warn_count++;
+ } else {
+ err_count++;
+ }
mutex->lock();
if (!locking && tcp_client->is_connected_to_host()) {
- if (errors.size() >= max_errors_per_frame) {
- n_errors_dropped++;
+ if (oe.warning) {
+ if (warn_count > max_warnings_per_second) {
+ n_warnings_dropped++;
+ } else {
+ errors.push_back(oe);
+ }
} else {
- errors.push_back(oe);
+ if (err_count > max_errors_per_second) {
+ n_errors_dropped++;
+ } else {
+ errors.push_back(oe);
+ }
}
}
@@ -1070,10 +1117,13 @@ ScriptDebuggerRemote::ScriptDebuggerRemote() :
mutex(Mutex::create()),
max_messages_per_frame(GLOBAL_GET("network/limits/debugger_stdout/max_messages_per_frame")),
n_messages_dropped(0),
- max_errors_per_frame(GLOBAL_GET("network/limits/debugger_stdout/max_errors_per_frame")),
+ max_errors_per_second(GLOBAL_GET("network/limits/debugger_stdout/max_errors_per_second")),
+ max_warnings_per_second(GLOBAL_GET("network/limits/debugger_stdout/max_warnings_per_second")),
n_errors_dropped(0),
max_cps(GLOBAL_GET("network/limits/debugger_stdout/max_chars_per_second")),
char_count(0),
+ err_count(0),
+ warn_count(0),
last_msec(0),
msec_count(0),
locking(false),
diff --git a/core/script_debugger_remote.h b/core/script_debugger_remote.h
index 1fc9d7c7f1..a5bfd7a32d 100644
--- a/core/script_debugger_remote.h
+++ b/core/script_debugger_remote.h
@@ -91,11 +91,15 @@ class ScriptDebuggerRemote : public ScriptDebugger {
int max_messages_per_frame;
int n_messages_dropped;
List<OutputError> errors;
- int max_errors_per_frame;
+ int max_errors_per_second;
+ int max_warnings_per_second;
int n_errors_dropped;
+ int n_warnings_dropped;
int max_cps;
int char_count;
+ int err_count;
+ int warn_count;
uint64_t last_msec;
uint64_t msec_count;
diff --git a/core/script_language.h b/core/script_language.h
index 87f103bb33..dfb2e0ad31 100644
--- a/core/script_language.h
+++ b/core/script_language.h
@@ -36,10 +36,6 @@
#include "core/pair.h"
#include "core/resource.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
class ScriptLanguage;
typedef void (*ScriptEditRequestFunction)(const String &p_path);
diff --git a/core/set.h b/core/set.h
index b2c717880d..68431c294a 100644
--- a/core/set.h
+++ b/core/set.h
@@ -34,10 +34,6 @@
#include "core/os/memory.h"
#include "core/typedefs.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
// based on the very nice implementation of rb-trees by:
// https://web.archive.org/web/20120507164830/http://web.mit.edu/~emin/www/source_code/red_black_tree/index.html
diff --git a/core/string_name.h b/core/string_name.h
index 0984b0181f..6dd960abd5 100644
--- a/core/string_name.h
+++ b/core/string_name.h
@@ -34,9 +34,6 @@
#include "core/os/mutex.h"
#include "core/safe_refcount.h"
#include "core/ustring.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
struct StaticCString {
diff --git a/core/translation.cpp b/core/translation.cpp
index 0b55badc61..a0902d71fc 100644
--- a/core/translation.cpp
+++ b/core/translation.cpp
@@ -848,8 +848,7 @@ void Translation::set_locale(const String &p_locale) {
if (!TranslationServer::is_locale_valid(univ_locale)) {
String trimmed_locale = get_trimmed_locale(univ_locale);
- ERR_EXPLAIN("Invalid locale: " + trimmed_locale);
- ERR_FAIL_COND(!TranslationServer::is_locale_valid(trimmed_locale));
+ ERR_FAIL_COND_MSG(!TranslationServer::is_locale_valid(trimmed_locale), "Invalid locale: " + trimmed_locale + ".");
locale = trimmed_locale;
} else {
@@ -1044,6 +1043,13 @@ StringName TranslationServer::translate(const StringName &p_message) const {
if (!enabled)
return p_message;
+ // Locale can be of the form 'll_CC', i.e. language code and regional code,
+ // e.g. 'en_US', 'en_GB', etc. It might also be simply 'll', e.g. 'en'.
+ // To find the relevant translation, we look for those with locale starting
+ // with the language code, and then if any is an exact match for the long
+ // form. If not found, we fall back to a near match (another locale with
+ // same language code).
+
StringName res;
bool near_match = false;
const CharType *lptr = &locale[0];
@@ -1053,13 +1059,11 @@ StringName TranslationServer::translate(const StringName &p_message) const {
const Ref<Translation> &t = E->get();
String l = t->get_locale();
if (lptr[0] != l[0] || lptr[1] != l[1])
- continue; // locale not match
-
- //near match
- bool match = (l != locale);
+ continue; // Language code does not match.
- if (near_match && !match)
- continue; //only near-match once
+ bool exact_match = (l == locale);
+ if (!exact_match && near_match)
+ continue; // Only near-match once, but keep looking for exact matches.
StringName r = t->get_message(p_message);
@@ -1068,43 +1072,38 @@ StringName TranslationServer::translate(const StringName &p_message) const {
res = r;
- if (match)
+ if (exact_match)
break;
else
near_match = true;
}
- if (!res) {
- //try again with fallback
- if (fallback.length() >= 2) {
-
- const CharType *fptr = &fallback[0];
- near_match = false;
- for (const Set<Ref<Translation> >::Element *E = translations.front(); E; E = E->next()) {
+ if (!res && fallback.length() >= 2) {
+ // Try again with the fallback locale.
+ const CharType *fptr = &fallback[0];
+ near_match = false;
+ for (const Set<Ref<Translation> >::Element *E = translations.front(); E; E = E->next()) {
- const Ref<Translation> &t = E->get();
- String l = t->get_locale();
- if (fptr[0] != l[0] || fptr[1] != l[1])
- continue; // locale not match
+ const Ref<Translation> &t = E->get();
+ String l = t->get_locale();
+ if (fptr[0] != l[0] || fptr[1] != l[1])
+ continue; // Language code does not match.
- //near match
- bool match = (l != fallback);
+ bool exact_match = (l == fallback);
+ if (!exact_match && near_match)
+ continue; // Only near-match once, but keep looking for exact matches.
- if (near_match && !match)
- continue; //only near-match once
+ StringName r = t->get_message(p_message);
- StringName r = t->get_message(p_message);
+ if (!r)
+ continue;
- if (!r)
- continue;
+ res = r;
- res = r;
-
- if (match)
- break;
- else
- near_match = true;
- }
+ if (exact_match)
+ break;
+ else
+ near_match = true;
}
}
diff --git a/core/ustring.cpp b/core/ustring.cpp
index ed401c3763..3f5e198281 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -31,7 +31,7 @@
#include "ustring.h"
#include "core/color.h"
-#include "core/math/crypto_core.h"
+#include "core/crypto/crypto_core.h"
#include "core/math/math_funcs.h"
#include "core/os/memory.h"
#include "core/print_string.h"
@@ -40,6 +40,7 @@
#include "core/variant.h"
#include <wchar.h>
+#include <cstdint>
#ifndef NO_USE_STDLIB
#include <stdio.h>
@@ -1668,6 +1669,7 @@ int String::hex_to_int(bool p_with_prefix) const {
return 0;
}
+ ERR_FAIL_COND_V_MSG(hex > INT32_MAX / 16, sign == 1 ? INT32_MAX : INT32_MIN, "Cannot represent " + *this + " as integer, provided value is " + (sign == 1 ? "too big." : "too small."));
hex *= 16;
hex += n;
s++;
@@ -1709,6 +1711,7 @@ int64_t String::hex_to_int64(bool p_with_prefix) const {
return 0;
}
+ ERR_FAIL_COND_V_MSG(hex > INT64_MAX / 16, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + *this + " as 64-bit integer, provided value is " + (sign == 1 ? "too big." : "too small."));
hex *= 16;
hex += n;
s++;
@@ -1748,6 +1751,7 @@ int64_t String::bin_to_int64(bool p_with_prefix) const {
return 0;
}
+ ERR_FAIL_COND_V_MSG(binary > INT64_MAX / 2, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + *this + " as 64-bit integer, provided value is " + (sign == 1 ? "too big." : "too small."));
binary *= 2;
binary += n;
s++;
@@ -1771,6 +1775,7 @@ int String::to_int() const {
CharType c = operator[](i);
if (c >= '0' && c <= '9') {
+ ERR_FAIL_COND_V_MSG(integer > INT32_MAX / 10, sign == 1 ? INT32_MAX : INT32_MIN, "Cannot represent " + *this + " as integer, provided value is " + (sign == 1 ? "too big." : "too small."));
integer *= 10;
integer += c - '0';
@@ -1798,6 +1803,7 @@ int64_t String::to_int64() const {
CharType c = operator[](i);
if (c >= '0' && c <= '9') {
+ ERR_FAIL_COND_V_MSG(integer > INT64_MAX / 10, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + *this + " as 64-bit integer, provided value is " + (sign == 1 ? "too big." : "too small."));
integer *= 10;
integer += c - '0';
@@ -1828,6 +1834,7 @@ int String::to_int(const char *p_str, int p_len) {
char c = p_str[i];
if (c >= '0' && c <= '9') {
+ ERR_FAIL_COND_V_MSG(integer > INT32_MAX / 10, sign == 1 ? INT32_MAX : INT32_MIN, "Cannot represent " + String(p_str).substr(0, to) + " as integer, provided value is " + (sign == 1 ? "too big." : "too small."));
integer *= 10;
integer += c - '0';
@@ -2140,6 +2147,14 @@ int64_t String::to_int(const CharType *p_str, int p_len) {
if (c >= '0' && c <= '9') {
+ if (integer > INT32_MAX / 10) {
+ String number("");
+ str = p_str;
+ while (*str && str != limit) {
+ number += *(str++);
+ }
+ ERR_FAIL_V_MSG(sign == 1 ? INT32_MAX : INT32_MIN, "Cannot represent " + number + " as integer, provided value is " + (sign == 1 ? "too big." : "too small."));
+ }
integer *= 10;
integer += c - '0';
} else {
diff --git a/core/ustring.h b/core/ustring.h
index 3eb5c47b3a..bbd0bcceb5 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -36,10 +36,6 @@
#include "core/typedefs.h"
#include "core/vector.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
template <class T>
class CharProxy {
friend class CharString;
diff --git a/core/variant.cpp b/core/variant.cpp
index 1574af5239..e7d0e58367 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -1740,10 +1740,7 @@ Variant::operator RID() const {
} else if (type == OBJECT && _get_obj().obj) {
#ifdef DEBUG_ENABLED
if (ScriptDebugger::get_singleton()) {
- if (!ObjectDB::instance_validate(_get_obj().obj)) {
- ERR_EXPLAIN("Invalid pointer (object was deleted)");
- ERR_FAIL_V(RID());
- };
+ ERR_FAIL_COND_V_MSG(!ObjectDB::instance_validate(_get_obj().obj), RID(), "Invalid pointer (object was deleted).");
};
#endif
Variant::CallError ce;
diff --git a/core/variant.h b/core/variant.h
index a8e99c13f1..c4f69c3e8d 100644
--- a/core/variant.h
+++ b/core/variant.h
@@ -31,10 +31,6 @@
#ifndef VARIANT_H
#define VARIANT_H
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
#include "core/array.h"
#include "core/color.h"
#include "core/dictionary.h"
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 1f6e5bb653..05ef51cecd 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -32,8 +32,8 @@
#include "core/color_names.inc"
#include "core/core_string_names.h"
+#include "core/crypto/crypto_core.h"
#include "core/io/compression.h"
-#include "core/math/crypto_core.h"
#include "core/object.h"
#include "core/os/os.h"
#include "core/script_language.h"
@@ -347,6 +347,8 @@ struct _VariantCall {
VCALL_LOCALMEM0R(Vector2, is_normalized);
VCALL_LOCALMEM1R(Vector2, distance_to);
VCALL_LOCALMEM1R(Vector2, distance_squared_to);
+ VCALL_LOCALMEM1R(Vector2, posmod);
+ VCALL_LOCALMEM1R(Vector2, posmodv);
VCALL_LOCALMEM1R(Vector2, project);
VCALL_LOCALMEM1R(Vector2, angle_to);
VCALL_LOCALMEM1R(Vector2, angle_to_point);
@@ -370,6 +372,7 @@ struct _VariantCall {
VCALL_LOCALMEM1R(Vector2, cross);
VCALL_LOCALMEM0R(Vector2, abs);
VCALL_LOCALMEM1R(Vector2, clamped);
+ VCALL_LOCALMEM0R(Vector2, sign);
VCALL_LOCALMEM0R(Rect2, get_area);
VCALL_LOCALMEM1R(Rect2, intersects);
@@ -407,12 +410,15 @@ struct _VariantCall {
VCALL_LOCALMEM0R(Vector3, round);
VCALL_LOCALMEM1R(Vector3, distance_to);
VCALL_LOCALMEM1R(Vector3, distance_squared_to);
+ VCALL_LOCALMEM1R(Vector3, posmod);
+ VCALL_LOCALMEM1R(Vector3, posmodv);
VCALL_LOCALMEM1R(Vector3, project);
VCALL_LOCALMEM1R(Vector3, angle_to);
VCALL_LOCALMEM1R(Vector3, direction_to);
VCALL_LOCALMEM1R(Vector3, slide);
VCALL_LOCALMEM1R(Vector3, bounce);
VCALL_LOCALMEM1R(Vector3, reflect);
+ VCALL_LOCALMEM0R(Vector3, sign);
VCALL_LOCALMEM0R(Plane, normalized);
VCALL_LOCALMEM0R(Plane, center);
@@ -584,8 +590,7 @@ struct _VariantCall {
if (buffer_size < 0) {
r_ret = decompressed;
- ERR_EXPLAIN("Decompression buffer size is less than zero");
- ERR_FAIL();
+ ERR_FAIL_MSG("Decompression buffer size is less than zero.");
}
decompressed.resize(buffer_size);
@@ -597,13 +602,10 @@ struct _VariantCall {
r_ret = decompressed;
}
- static void _call_PoolByteArray_sha256_string(Variant &r_ret, Variant &p_self, const Variant **p_args) {
+ 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);
PoolByteArray::Read r = ba->read();
- String s;
- unsigned char hash[32];
- CryptoCore::sha256((unsigned char *)r.ptr(), ba->size(), hash);
- s = String::hex_encode_buffer(hash, 32);
+ String s = String::hex_encode_buffer(&r[0], ba->size());
r_ret = s;
}
@@ -1591,6 +1593,8 @@ void register_variant_methods() {
ADDFUNC1R(VECTOR2, VECTOR2, Vector2, direction_to, VECTOR2, "b", varray());
ADDFUNC1R(VECTOR2, REAL, Vector2, distance_to, VECTOR2, "to", varray());
ADDFUNC1R(VECTOR2, REAL, Vector2, distance_squared_to, VECTOR2, "to", varray());
+ ADDFUNC1R(VECTOR2, VECTOR2, Vector2, posmod, REAL, "mod", varray());
+ ADDFUNC1R(VECTOR2, VECTOR2, Vector2, posmodv, VECTOR2, "modv", varray());
ADDFUNC1R(VECTOR2, VECTOR2, Vector2, project, VECTOR2, "b", varray());
ADDFUNC1R(VECTOR2, REAL, Vector2, angle_to, VECTOR2, "to", varray());
ADDFUNC1R(VECTOR2, REAL, Vector2, angle_to_point, VECTOR2, "to", varray());
@@ -1612,6 +1616,7 @@ void register_variant_methods() {
ADDFUNC1R(VECTOR2, REAL, Vector2, cross, VECTOR2, "with", varray());
ADDFUNC0R(VECTOR2, VECTOR2, Vector2, abs, varray());
ADDFUNC1R(VECTOR2, VECTOR2, Vector2, clamped, REAL, "length", varray());
+ ADDFUNC0R(VECTOR2, VECTOR2, Vector2, sign, varray());
ADDFUNC0R(RECT2, REAL, Rect2, get_area, varray());
ADDFUNC1R(RECT2, BOOL, Rect2, intersects, RECT2, "b", varray());
@@ -1650,11 +1655,14 @@ void register_variant_methods() {
ADDFUNC0R(VECTOR3, VECTOR3, Vector3, round, varray());
ADDFUNC1R(VECTOR3, REAL, Vector3, distance_to, VECTOR3, "b", varray());
ADDFUNC1R(VECTOR3, REAL, Vector3, distance_squared_to, VECTOR3, "b", varray());
+ ADDFUNC1R(VECTOR3, VECTOR3, Vector3, posmod, REAL, "mod", varray());
+ ADDFUNC1R(VECTOR3, VECTOR3, Vector3, posmodv, VECTOR3, "modv", varray());
ADDFUNC1R(VECTOR3, VECTOR3, Vector3, project, VECTOR3, "b", varray());
ADDFUNC1R(VECTOR3, REAL, Vector3, angle_to, VECTOR3, "to", varray());
ADDFUNC1R(VECTOR3, VECTOR3, Vector3, slide, VECTOR3, "n", varray());
ADDFUNC1R(VECTOR3, VECTOR3, Vector3, bounce, VECTOR3, "n", varray());
ADDFUNC1R(VECTOR3, VECTOR3, Vector3, reflect, VECTOR3, "n", varray());
+ ADDFUNC0R(VECTOR3, VECTOR3, Vector3, sign, varray());
ADDFUNC0R(PLANE, PLANE, Plane, normalized, varray());
ADDFUNC0R(PLANE, VECTOR3, Plane, center, varray());
@@ -1763,7 +1771,7 @@ void register_variant_methods() {
ADDFUNC0R(POOL_BYTE_ARRAY, STRING, PoolByteArray, get_string_from_ascii, varray());
ADDFUNC0R(POOL_BYTE_ARRAY, STRING, PoolByteArray, get_string_from_utf8, varray());
- ADDFUNC0R(POOL_BYTE_ARRAY, STRING, PoolByteArray, sha256_string, varray());
+ ADDFUNC0R(POOL_BYTE_ARRAY, STRING, PoolByteArray, hex_encode, varray());
ADDFUNC1R(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, compress, INT, "compression_mode", varray(0));
ADDFUNC2R(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, decompress, INT, "buffer_size", INT, "compression_mode", varray(0));
@@ -1947,6 +1955,9 @@ void register_variant_methods() {
_VariantCall::add_variant_constant(Variant::VECTOR3, "FORWARD", Vector3(0, 0, -1));
_VariantCall::add_variant_constant(Variant::VECTOR3, "BACK", Vector3(0, 0, 1));
+ _VariantCall::add_constant(Variant::VECTOR2, "AXIS_X", Vector2::AXIS_X);
+ _VariantCall::add_constant(Variant::VECTOR2, "AXIS_Y", Vector2::AXIS_Y);
+
_VariantCall::add_variant_constant(Variant::VECTOR2, "ZERO", Vector2(0, 0));
_VariantCall::add_variant_constant(Variant::VECTOR2, "ONE", Vector2(1, 1));
_VariantCall::add_variant_constant(Variant::VECTOR2, "INF", Vector2(Math_INF, Math_INF));
@@ -1955,19 +1966,27 @@ void register_variant_methods() {
_VariantCall::add_variant_constant(Variant::VECTOR2, "UP", Vector2(0, -1));
_VariantCall::add_variant_constant(Variant::VECTOR2, "DOWN", Vector2(0, 1));
- _VariantCall::add_variant_constant(Variant::TRANSFORM2D, "IDENTITY", Transform2D(1, 0, 0, 1, 0, 0));
+ _VariantCall::add_variant_constant(Variant::TRANSFORM2D, "IDENTITY", Transform2D());
_VariantCall::add_variant_constant(Variant::TRANSFORM2D, "FLIP_X", Transform2D(-1, 0, 0, 1, 0, 0));
_VariantCall::add_variant_constant(Variant::TRANSFORM2D, "FLIP_Y", Transform2D(1, 0, 0, -1, 0, 0));
- Transform identity_transform, transform_x, transform_y, transform_z;
- identity_transform.set(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0);
+ Transform identity_transform = Transform();
+ Transform flip_x_transform = Transform(-1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0);
+ Transform flip_y_transform = Transform(1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0);
+ Transform flip_z_transform = Transform(1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0);
_VariantCall::add_variant_constant(Variant::TRANSFORM, "IDENTITY", identity_transform);
- transform_x.set(-1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0);
- _VariantCall::add_variant_constant(Variant::TRANSFORM, "FLIP_X", transform_x);
- transform_y.set(1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0);
- _VariantCall::add_variant_constant(Variant::TRANSFORM, "FLIP_Y", transform_y);
- transform_z.set(1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0);
- _VariantCall::add_variant_constant(Variant::TRANSFORM, "FLIP_Z", transform_z);
+ _VariantCall::add_variant_constant(Variant::TRANSFORM, "FLIP_X", flip_x_transform);
+ _VariantCall::add_variant_constant(Variant::TRANSFORM, "FLIP_Y", flip_y_transform);
+ _VariantCall::add_variant_constant(Variant::TRANSFORM, "FLIP_Z", flip_z_transform);
+
+ Basis identity_basis = Basis();
+ Basis flip_x_basis = Basis(-1, 0, 0, 0, 1, 0, 0, 0, 1);
+ Basis flip_y_basis = Basis(1, 0, 0, 0, -1, 0, 0, 0, 1);
+ Basis flip_z_basis = Basis(1, 0, 0, 0, 1, 0, 0, 0, -1);
+ _VariantCall::add_variant_constant(Variant::BASIS, "IDENTITY", identity_basis);
+ _VariantCall::add_variant_constant(Variant::BASIS, "FLIP_X", flip_x_basis);
+ _VariantCall::add_variant_constant(Variant::BASIS, "FLIP_Y", flip_y_basis);
+ _VariantCall::add_variant_constant(Variant::BASIS, "FLIP_Z", flip_z_basis);
_VariantCall::add_variant_constant(Variant::PLANE, "PLANE_YZ", Plane(Vector3(1, 0, 0), 0));
_VariantCall::add_variant_constant(Variant::PLANE, "PLANE_XZ", Plane(Vector3(0, 1, 0), 0));