summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/config/project_settings.cpp4
-rw-r--r--core/core_bind.cpp7
-rw-r--r--core/core_constants.cpp1
-rw-r--r--core/crypto/crypto.cpp4
-rw-r--r--core/debugger/engine_debugger.cpp2
-rw-r--r--core/debugger/remote_debugger_peer.cpp7
-rw-r--r--core/input/input.cpp4
-rw-r--r--core/input/input_map.cpp1
-rw-r--r--core/io/compression.cpp6
-rw-r--r--core/io/file_access_compressed.cpp6
-rw-r--r--core/io/file_access_encrypted.cpp4
-rw-r--r--core/io/file_access_memory.cpp2
-rw-r--r--core/io/file_access_network.cpp3
-rw-r--r--core/io/file_access_pack.cpp3
-rw-r--r--core/io/file_access_zip.cpp2
-rw-r--r--core/io/multiplayer_api.cpp8
-rw-r--r--core/io/packet_peer_udp.cpp2
-rw-r--r--core/io/resource_format_binary.cpp2
-rw-r--r--core/io/resource_loader.cpp6
-rw-r--r--core/io/translation_loader_po.cpp2
-rw-r--r--core/io/xml_parser.cpp2
-rw-r--r--core/math/basis.cpp6
-rw-r--r--core/math/expression.cpp2
-rw-r--r--core/math/geometry_2d.cpp6
-rw-r--r--core/math/quick_hull.cpp2
-rw-r--r--core/math/triangulate.cpp2
-rw-r--r--core/object/method_bind.h1
-rw-r--r--core/object/object.cpp8
-rw-r--r--core/os/file_access.cpp2
-rw-r--r--core/os/pool_allocator.cpp2
-rw-r--r--core/string/compressed_translation.cpp2
-rw-r--r--core/string/translation_po.cpp2
-rw-r--r--core/string/ustring.cpp4
-rw-r--r--core/variant/array.cpp2
-rw-r--r--core/variant/binder_common.h164
-rw-r--r--core/variant/callable.cpp4
-rw-r--r--core/variant/variant.h3
-rw-r--r--core/variant/variant_call.cpp157
-rw-r--r--core/variant/variant_setget.cpp2
39 files changed, 398 insertions, 51 deletions
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index 02effc2001..f87dc6704e 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -393,7 +393,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
if (exec_path != "") {
// We do several tests sequentially until one succeeds to find a PCK,
- // and if so we attempt loading it at the end.
+ // and if so, we attempt loading it at the end.
// Attempt with PCK bundled into executable.
bool found = _load_resource_pack(exec_path);
@@ -643,7 +643,6 @@ Error ProjectSettings::_load_settings_text_or_binary(const String &p_text_path,
} else if (err != ERR_FILE_NOT_FOUND) {
// If the file exists but can't be loaded, we want to know it.
ERR_PRINT("Couldn't load file '" + p_bin_path + "', error code " + itos(err) + ".");
- return err;
}
// Fallback to text-based project.godot file if binary was not found.
@@ -652,7 +651,6 @@ Error ProjectSettings::_load_settings_text_or_binary(const String &p_text_path,
return OK;
} else if (err != ERR_FILE_NOT_FOUND) {
ERR_PRINT("Couldn't load file '" + p_text_path + "', error code " + itos(err) + ".");
- return err;
}
return err;
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index e7a77384da..c3d547c2c7 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -373,6 +373,9 @@ Dictionary _OS::get_time(bool utc) const {
* @return epoch calculated
*/
int64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const {
+ // if datetime is an empty Dictionary throws an error
+ ERR_FAIL_COND_V_MSG(datetime.is_empty(), 0, "Invalid datetime Dictionary: Dictionary is empty");
+
// Bunch of conversion constants
static const unsigned int SECONDS_PER_MINUTE = 60;
static const unsigned int MINUTES_PER_HOUR = 60;
@@ -1374,9 +1377,9 @@ Vector<String> _File::get_csv_line(const String &p_delim) const {
return f->get_csv_line(p_delim);
}
-/**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac)
+/**< use this for files WRITTEN in _big_ endian machines (i.e. amiga/mac)
* It's not about the current CPU type but file formats.
- * this flags get reset to false (little endian) on each open
+ * These flags get reset to false (little endian) on each open
*/
void _File::set_endian_swap(bool p_swap) {
diff --git a/core/core_constants.cpp b/core/core_constants.cpp
index a99df93638..5abfee05bf 100644
--- a/core/core_constants.cpp
+++ b/core/core_constants.cpp
@@ -564,6 +564,7 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_REVERSE);
BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_VIRTUAL);
BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_FROM_SCRIPT);
+ BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_STATIC);
BIND_CORE_ENUM_CONSTANT(METHOD_FLAGS_DEFAULT);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_NIL", Variant::NIL);
diff --git a/core/crypto/crypto.cpp b/core/crypto/crypto.cpp
index f43f3e3290..6b3953f588 100644
--- a/core/crypto/crypto.cpp
+++ b/core/crypto/crypto.cpp
@@ -100,7 +100,7 @@ void Crypto::load_default_certificates(String p_path) {
PackedByteArray Crypto::hmac_digest(HashingContext::HashType p_hash_type, PackedByteArray p_key, PackedByteArray p_msg) {
Ref<HMACContext> ctx = Ref<HMACContext>(HMACContext::create());
- ERR_FAIL_COND_V_MSG(ctx.is_null(), PackedByteArray(), "HMAC is not available witout mbedtls module.");
+ ERR_FAIL_COND_V_MSG(ctx.is_null(), PackedByteArray(), "HMAC is not available without mbedtls module.");
Error err = ctx->start(p_hash_type, p_key);
ERR_FAIL_COND_V(err != OK, PackedByteArray());
err = ctx->update(p_msg);
@@ -108,7 +108,7 @@ PackedByteArray Crypto::hmac_digest(HashingContext::HashType p_hash_type, Packed
return ctx->finish();
}
-// Compares two HMACS for equality without leaking timing information in order to prevent timing attakcs.
+// Compares two HMACS for equality without leaking timing information in order to prevent timing attacks.
// @see: https://paragonie.com/blog/2015/11/preventing-timing-attacks-on-string-comparison-with-double-hmac-strategy
bool Crypto::constant_time_compare(PackedByteArray p_trusted, PackedByteArray p_received) {
const uint8_t *t = p_trusted.ptr();
diff --git a/core/debugger/engine_debugger.cpp b/core/debugger/engine_debugger.cpp
index 895b8c23a9..e5dba029c9 100644
--- a/core/debugger/engine_debugger.cpp
+++ b/core/debugger/engine_debugger.cpp
@@ -192,7 +192,7 @@ void EngineDebugger::deinitialize() {
singleton = nullptr;
}
- // Clear profilers/captuers/protocol handlers.
+ // Clear profilers/captures/protocol handlers.
profilers.clear();
captures.clear();
protocols.clear();
diff --git a/core/debugger/remote_debugger_peer.cpp b/core/debugger/remote_debugger_peer.cpp
index 857e3af268..90b0975159 100644
--- a/core/debugger/remote_debugger_peer.cpp
+++ b/core/debugger/remote_debugger_peer.cpp
@@ -190,13 +190,18 @@ Error RemoteDebuggerPeerTCP::connect_to_host(const String &p_host, uint16_t p_po
}
void RemoteDebuggerPeerTCP::_thread_func(void *p_ud) {
+ const uint64_t min_tick = 100;
RemoteDebuggerPeerTCP *peer = (RemoteDebuggerPeerTCP *)p_ud;
while (peer->running && peer->is_peer_connected()) {
+ uint64_t ticks_usec = OS::get_singleton()->get_ticks_usec();
peer->_poll();
if (!peer->is_peer_connected()) {
break;
}
- peer->tcp_client->poll(NetSocket::POLL_TYPE_IN_OUT, 1);
+ ticks_usec = OS::get_singleton()->get_ticks_usec() - ticks_usec;
+ if (ticks_usec < min_tick) {
+ OS::get_singleton()->delay_usec(min_tick - ticks_usec);
+ }
}
}
diff --git a/core/input/input.cpp b/core/input/input.cpp
index f928ae7654..3a8c1c1628 100644
--- a/core/input/input.cpp
+++ b/core/input/input.cpp
@@ -723,7 +723,7 @@ void Input::warp_mouse_position(const Vector2 &p_to) {
Point2i Input::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect) {
// The relative distance reported for the next event after a warp is in the boundaries of the
- // size of the rect on that axis, but it may be greater, in which case there's not problem as fmod()
+ // size of the rect on that axis, but it may be greater, in which case there's no problem as fmod()
// will warp it, but if the pointer has moved in the opposite direction between the pointer relocation
// and the subsequent event, the reported relative distance will be less than the size of the rect
// and thus fmod() will be disabled for handling the situation.
@@ -779,7 +779,7 @@ bool Input::is_emulating_touch_from_mouse() const {
return emulate_touch_from_mouse;
}
-// Calling this whenever the game window is focused helps unstucking the "touch mouse"
+// Calling this whenever the game window is focused helps unsticking the "touch mouse"
// if the OS or its abstraction class hasn't properly reported that touch pointers raised
void Input::ensure_touch_mouse_raised() {
if (mouse_from_touch_index != -1) {
diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp
index e0b25fa092..7d85fd6492 100644
--- a/core/input/input_map.cpp
+++ b/core/input/input_map.cpp
@@ -567,6 +567,7 @@ const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
inputs.push_back(InputEventKey::create_reference(KEY_E | KEY_MASK_CTRL));
inputs.push_back(InputEventKey::create_reference(KEY_RIGHT | KEY_MASK_CMD));
default_builtin_cache.insert("ui_text_caret_line_end.OSX", inputs);
+
// Text Caret Movement Page Up/Down
inputs = List<Ref<InputEvent>>();
diff --git a/core/io/compression.cpp b/core/io/compression.cpp
index 456023e2a6..980234cbfc 100644
--- a/core/io/compression.cpp
+++ b/core/io/compression.cpp
@@ -181,8 +181,8 @@ int Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p
}
/**
- This will handle both Gzip and Deflat streams. It will automatically allocate the output buffer into the provided p_dst_vect Vector.
- This is required for compressed data who's final uncompressed size is unknown, as is the case for HTTP response bodies.
+ This will handle both Gzip and Deflate streams. It will automatically allocate the output buffer into the provided p_dst_vect Vector.
+ This is required for compressed data whose final uncompressed size is unknown, as is the case for HTTP response bodies.
This is much slower however than using Compression::decompress because it may result in multiple full copies of the output buffer.
*/
int Compression::decompress_dynamic(Vector<uint8_t> *p_dst_vect, int p_max_dst_size, const uint8_t *p_src, int p_src_size, Mode p_mode) {
@@ -248,7 +248,7 @@ int Compression::decompress_dynamic(Vector<uint8_t> *p_dst_vect, int p_max_dst_s
out_mark += gzip_chunk;
- // Encorce max output size
+ // Enforce max output size
if (p_max_dst_size > -1 && strm.total_out > (uint64_t)p_max_dst_size) {
(void)inflateEnd(&strm);
p_dst_vect->resize(0);
diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp
index 9ec2b27e88..b2440629e3 100644
--- a/core/io/file_access_compressed.cpp
+++ b/core/io/file_access_compressed.cpp
@@ -286,8 +286,10 @@ uint8_t FileAccessCompressed::get_8() const {
}
int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
- ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode.");
+ ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
+ ERR_FAIL_COND_V(p_length < 0, -1);
+ ERR_FAIL_COND_V_MSG(!f, -1, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(writing, -1, "File has not been opened in read mode.");
if (at_end) {
read_eof = true;
diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp
index 8b4c57ce64..8ace897f18 100644
--- a/core/io/file_access_encrypted.cpp
+++ b/core/io/file_access_encrypted.cpp
@@ -237,7 +237,9 @@ uint8_t FileAccessEncrypted::get_8() const {
}
int FileAccessEncrypted::get_buffer(uint8_t *p_dst, int p_length) const {
- ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode.");
+ ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
+ ERR_FAIL_COND_V(p_length < 0, -1);
+ ERR_FAIL_COND_V_MSG(writing, -1, "File has not been opened in read mode.");
int to_copy = MIN(p_length, data.size() - pos);
for (int i = 0; i < to_copy; i++) {
diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp
index 04270de77f..58670d5246 100644
--- a/core/io/file_access_memory.cpp
+++ b/core/io/file_access_memory.cpp
@@ -138,6 +138,8 @@ uint8_t FileAccessMemory::get_8() const {
}
int FileAccessMemory::get_buffer(uint8_t *p_dst, int p_length) const {
+ ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
+ ERR_FAIL_COND_V(p_length < 0, -1);
ERR_FAIL_COND_V(!data, -1);
int left = length - pos;
diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp
index 97838fd14c..31b7d658d0 100644
--- a/core/io/file_access_network.cpp
+++ b/core/io/file_access_network.cpp
@@ -366,6 +366,9 @@ void FileAccessNetwork::_queue_page(int p_page) const {
}
int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const {
+ ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
+ ERR_FAIL_COND_V(p_length < 0, -1);
+
//bool eof=false;
if (pos + p_length > total_size) {
eof_flag = true;
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index faf4fca14f..e24dc40166 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -299,6 +299,9 @@ uint8_t FileAccessPack::get_8() const {
}
int FileAccessPack::get_buffer(uint8_t *p_dst, int p_length) const {
+ ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
+ ERR_FAIL_COND_V(p_length < 0, -1);
+
if (eof) {
return 0;
}
diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp
index 01f9337a80..586c988974 100644
--- a/core/io/file_access_zip.cpp
+++ b/core/io/file_access_zip.cpp
@@ -303,6 +303,8 @@ uint8_t FileAccessZip::get_8() const {
}
int FileAccessZip::get_buffer(uint8_t *p_dst, int p_length) const {
+ ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
+ ERR_FAIL_COND_V(p_length < 0, -1);
ERR_FAIL_COND_V(!zfile, -1);
at_eof = unzeof(zfile);
if (at_eof) {
diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp
index 6b550e69c8..94060cfe0b 100644
--- a/core/io/multiplayer_api.cpp
+++ b/core/io/multiplayer_api.cpp
@@ -50,7 +50,7 @@ _FORCE_INLINE_ bool _should_call_local(MultiplayerAPI::RPCMode mode, bool is_mas
// Do nothing.
} break;
case MultiplayerAPI::RPC_MODE_REMOTE: {
- // Do nothing also. Remote cannot produce a local call.
+ // Do nothing. Remote cannot produce a local call.
} break;
case MultiplayerAPI::RPC_MODE_MASTERSYNC: {
if (is_master) {
@@ -675,7 +675,7 @@ Error MultiplayerAPI::_encode_and_compress_variant(const Variant &p_variant, uin
return err;
}
if (r_buffer) {
- // The first byte is not used by the marshaling, so store the type
+ // The first byte is not used by the marshalling, so store the type
// so we know how to decompress and decode this variant.
r_buffer[0] = p_variant.get_type();
}
@@ -791,7 +791,7 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p
packet_cache.resize(m_amount);
// Encode meta.
- // The meta is composed by a single byte that contains (starting from the least segnificant bit):
+ // The meta is composed by a single byte that contains (starting from the least significant bit):
// - `NetworkCommands` in the first three bits.
// - `NetworkNodeIdCompression` in the next 2 bits.
// - `NetworkNameIdCompression` in the next 1 bit.
@@ -830,7 +830,7 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p
ofs += 4;
}
} else {
- // The targets doesn't know the node yet, so we need to use 32 bits int.
+ // The targets don't know the node yet, so we need to use 32 bits int.
node_id_compression = NETWORK_NODE_ID_COMPRESSION_32;
MAKE_ROOM(ofs + 4);
encode_uint32(psc->id, &(packet_cache.write[ofs]));
diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp
index d8d63d976f..3f46f2706e 100644
--- a/core/io/packet_peer_udp.cpp
+++ b/core/io/packet_peer_udp.cpp
@@ -224,7 +224,7 @@ Error PacketPeerUDP::connect_to_host(const IP_Address &p_host, int p_port) {
// I see no reason why we should get ERR_BUSY (wouldblock/eagain) here.
// This is UDP, so connect is only used to tell the OS to which socket
- // it shuold deliver packets when multiple are bound on the same address/port.
+ // it should deliver packets when multiple are bound on the same address/port.
if (err != OK) {
close();
ERR_FAIL_V_MSG(FAILED, "Unable to connect");
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index fb6ad7d65e..c4eb2a20bb 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -1245,7 +1245,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
String ResourceFormatLoaderBinary::get_resource_type(const String &p_path) const {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
if (!f) {
- return ""; //could not rwead
+ return ""; //could not read
}
ResourceLoaderBinary loader;
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 8275dd0ad4..dcf71bb4a9 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -215,7 +215,7 @@ void ResourceLoader::_thread_load_function(void *p_userdata) {
load_task.loader_id = Thread::get_caller_id();
if (load_task.semaphore) {
- //this is an actual thread, so wait for Ok fom semaphore
+ //this is an actual thread, so wait for Ok from semaphore
thread_load_semaphore->wait(); //wait until its ok to start loading
}
load_task.resource = _load(load_task.remapped_path, load_task.remapped_path != load_task.local_path ? load_task.local_path : String(), load_task.type_hint, load_task.cache_mode, &load_task.error, load_task.use_sub_threads, &load_task.progress);
@@ -443,7 +443,7 @@ RES ResourceLoader::load_threaded_get(const String &p_path, Error *r_error) {
ThreadLoadTask &load_task = thread_load_tasks[local_path];
- //semaphore still exists, meaning its still loading, request poll
+ //semaphore still exists, meaning it's still loading, request poll
Semaphore *semaphore = load_task.semaphore;
if (semaphore) {
load_task.poll_requests++;
@@ -452,7 +452,7 @@ RES ResourceLoader::load_threaded_get(const String &p_path, Error *r_error) {
// As we got a semaphore, this means we are going to have to wait
// until the sub-resource is done loading
//
- // As this thread will become 'blocked' we should "echange" its
+ // As this thread will become 'blocked' we should "exchange" its
// active status with a waiting one, to ensure load continues.
//
// This ensures loading is never blocked and that is also within
diff --git a/core/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp
index 0e11ff514a..9adf912224 100644
--- a/core/io/translation_loader_po.cpp
+++ b/core/io/translation_loader_po.cpp
@@ -194,7 +194,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
l = l.substr(1, l.length());
// Find final quote, ignoring escaped ones (\").
// The escape_next logic is necessary to properly parse things like \\"
- // where the blackslash is the one being escaped, not the quote.
+ // where the backslash is the one being escaped, not the quote.
int end_pos = -1;
bool escape_next = false;
for (int i = 0; i < l.length(); i++) {
diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp
index 1574634aad..d5eb32513b 100644
--- a/core/io/xml_parser.cpp
+++ b/core/io/xml_parser.cpp
@@ -344,7 +344,7 @@ void XMLParser::_bind_methods() {
}
Error XMLParser::read() {
- // if not end reached, parse the node
+ // if end not reached, parse the node
if (P && (P - data) < (int64_t)length - 1 && *P != 0) {
_parse_current_node();
return OK;
diff --git a/core/math/basis.cpp b/core/math/basis.cpp
index cbdd8a8c9f..cc2b7c6611 100644
--- a/core/math/basis.cpp
+++ b/core/math/basis.cpp
@@ -132,7 +132,7 @@ bool Basis::is_symmetric() const {
Basis Basis::diagonalize() {
//NOTE: only implemented for symmetric matrices
-//with the Jacobi iterative method method
+//with the Jacobi iterative method
#ifdef MATH_CHECKS
ERR_FAIL_COND_V(!is_symmetric(), Basis());
#endif
@@ -317,7 +317,7 @@ Vector3 Basis::rotref_posscale_decomposition(Basis &rotref) const {
// Multiplies the matrix from left by the rotation matrix: M -> R.M
// Note that this does *not* rotate the matrix itself.
//
-// The main use of Basis is as Transform.basis, which is used a the transformation matrix
+// The main use of Basis is as Transform.basis, which is used by the transformation matrix
// of 3D object. Rotate here refers to rotation of the object (which is R * (*this)),
// not the matrix itself (which is R * (*this) * R.transposed()).
Basis Basis::rotated(const Vector3 &p_axis, real_t p_phi) const {
@@ -881,7 +881,7 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
if ((Math::abs(elements[1][0] - elements[0][1]) < epsilon) && (Math::abs(elements[2][0] - elements[0][2]) < epsilon) && (Math::abs(elements[2][1] - elements[1][2]) < epsilon)) {
// singularity found
// first check for identity matrix which must have +1 for all terms
- // in leading diagonaland zero in other terms
+ // in leading diagonal and zero in other terms
if ((Math::abs(elements[1][0] + elements[0][1]) < epsilon2) && (Math::abs(elements[2][0] + elements[0][2]) < epsilon2) && (Math::abs(elements[2][1] + elements[1][2]) < epsilon2) && (Math::abs(elements[0][0] + elements[1][1] + elements[2][2] - 3) < epsilon2)) {
// this singularity is identity matrix so angle = 0
r_axis = Vector3(0, 1, 0);
diff --git a/core/math/expression.cpp b/core/math/expression.cpp
index 636ea601c7..f7ac44d321 100644
--- a/core/math/expression.cpp
+++ b/core/math/expression.cpp
@@ -978,7 +978,7 @@ Expression::ENode *Expression::_parse_expression() {
}
}
- /* Reduce the set set of expressions and place them in an operator tree, respecting precedence */
+ /* Reduce the set of expressions and place them in an operator tree, respecting precedence */
while (expression.size() > 1) {
int next_op = -1;
diff --git a/core/math/geometry_2d.cpp b/core/math/geometry_2d.cpp
index d67be14d33..feb1fb2fb8 100644
--- a/core/math/geometry_2d.cpp
+++ b/core/math/geometry_2d.cpp
@@ -87,9 +87,9 @@ struct _AtlasWorkRectResult {
void Geometry2D::make_atlas(const Vector<Size2i> &p_rects, Vector<Point2i> &r_result, Size2i &r_size) {
// Super simple, almost brute force scanline stacking fitter.
// It's pretty basic for now, but it tries to make sure that the aspect ratio of the
- // resulting atlas is somehow square. This is necessary because video cards have limits.
- // On texture size (usually 2048 or 4096), so the more square a texture, the more chances.
- // It will work in every hardware.
+ // resulting atlas is somehow square. This is necessary because video cards have limits
+ // on texture size (usually 2048 or 4096), so the squarer a texture, the more the chances
+ // that it will work in every hardware.
// For example, it will prioritize a 1024x1024 atlas (works everywhere) instead of a
// 256x8192 atlas (won't work anywhere).
diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp
index ad28967d7a..fe18cc3d41 100644
--- a/core/math/quick_hull.cpp
+++ b/core/math/quick_hull.cpp
@@ -268,7 +268,7 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_
for (Map<Edge, FaceConnect>::Element *E = lit_edges.front(); E; E = E->next()) {
FaceConnect &fc = E->get();
if (fc.left && fc.right) {
- continue; //edge is uninteresting, not on horizont
+ continue; //edge is uninteresting, not on horizon
}
//create new face!
diff --git a/core/math/triangulate.cpp b/core/math/triangulate.cpp
index 0047c0705d..fa1588dbc5 100644
--- a/core/math/triangulate.cpp
+++ b/core/math/triangulate.cpp
@@ -97,7 +97,7 @@ bool Triangulate::snip(const Vector<Vector2> &p_contour, int u, int v, int w, in
// It can happen that the triangulation ends up with three aligned vertices to deal with.
// In this scenario, making the check below strict may reject the possibility of
- // forming a last triangle with these aligned vertices, preventing the triangulatiom
+ // forming a last triangle with these aligned vertices, preventing the triangulation
// from completing.
// To avoid that we allow zero-area triangles if all else failed.
float threshold = relaxed ? -CMP_EPSILON : CMP_EPSILON;
diff --git a/core/object/method_bind.h b/core/object/method_bind.h
index 7cf4f8d4e8..7030ae201b 100644
--- a/core/object/method_bind.h
+++ b/core/object/method_bind.h
@@ -42,6 +42,7 @@ enum MethodFlags {
METHOD_FLAG_VIRTUAL = 32,
METHOD_FLAG_FROM_SCRIPT = 64,
METHOD_FLAG_VARARG = 128,
+ METHOD_FLAG_STATIC = 256,
METHOD_FLAGS_DEFAULT = METHOD_FLAG_NORMAL,
};
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 1a9cce49d8..413f917518 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -596,7 +596,7 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
_get_property_listv(p_list, p_reversed);
- if (!is_class("Script")) { // can still be set, but this is for userfriendlyness
+ if (!is_class("Script")) { // can still be set, but this is for user-friendliness
p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT));
}
if (!metadata.is_empty()) {
@@ -1671,7 +1671,7 @@ Variant::Type Object::get_static_property_type_indexed(const Vector<StringName>
for (int i = 1; i < p_path.size(); i++) {
if (check.get_type() == Variant::OBJECT || check.get_type() == Variant::DICTIONARY || check.get_type() == Variant::ARRAY) {
- // We cannot be sure about the type of properties this types can have
+ // We cannot be sure about the type of properties this type can have
if (r_valid) {
*r_valid = false;
}
@@ -1719,10 +1719,10 @@ void *Object::get_script_instance_binding(int p_script_language_index) {
ERR_FAIL_INDEX_V(p_script_language_index, MAX_SCRIPT_INSTANCE_BINDINGS, nullptr);
#endif
- //it's up to the script language to make this thread safe, if the function is called twice due to threads being out of syncro
+ //it's up to the script language to make this thread safe, if the function is called twice due to threads being out of sync
//just return the same pointer.
//if you want to put a big lock in the entire function and keep allocated pointers in a map or something, feel free to do it
- //as it should not really affect performance much (won't be called too often), as in far most caes the condition below will be false afterwards
+ //as it should not really affect performance much (won't be called too often), as in far most cases the condition below will be false afterwards
if (!_script_instance_bindings[p_script_language_index]) {
void *script_data = ScriptServer::get_language(p_script_language_index)->alloc_instance_binding_data(this);
diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp
index 5a3df88619..ad234c2d49 100644
--- a/core/os/file_access.cpp
+++ b/core/os/file_access.cpp
@@ -368,6 +368,8 @@ Vector<String> FileAccess::get_csv_line(const String &p_delim) const {
}
int FileAccess::get_buffer(uint8_t *p_dst, int p_length) const {
+ ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
+ ERR_FAIL_COND_V(p_length < 0, -1);
int i = 0;
for (i = 0; i < p_length && !eof_reached(); i++) {
p_dst[i] = get_8();
diff --git a/core/os/pool_allocator.cpp b/core/os/pool_allocator.cpp
index b538ca0c96..9be3a62e2f 100644
--- a/core/os/pool_allocator.cpp
+++ b/core/os/pool_allocator.cpp
@@ -136,7 +136,7 @@ void PoolAllocator::compact_up(int p_from) {
for (int i = entry_count - 1; i >= p_from; i--) {
Entry &entry = entry_array[entry_indices[i]];
- /* determine hole size to nextious entry */
+ /* determine hole size for next entry */
int hole_size = next_entry_end_pos - (entry.pos + aligned(entry.len));
diff --git a/core/string/compressed_translation.cpp b/core/string/compressed_translation.cpp
index ad90924293..15abf63f7e 100644
--- a/core/string/compressed_translation.cpp
+++ b/core/string/compressed_translation.cpp
@@ -44,7 +44,7 @@ struct _PHashTranslationCmp {
void PHashTranslation::generate(const Ref<Translation> &p_from) {
// This method compresses a Translation instance.
- // Right now it doesn't handle context or plurals, so Translation subclasses using plurals or context (i.e TranslationPO) shouldn't be compressed.
+ // Right now, it doesn't handle context or plurals, so Translation subclasses using plurals or context (i.e TranslationPO) shouldn't be compressed.
#ifdef TOOLS_ENABLED
List<StringName> keys;
p_from->get_message_list(&keys);
diff --git a/core/string/translation_po.cpp b/core/string/translation_po.cpp
index 846afe761b..42ba30fbe5 100644
--- a/core/string/translation_po.cpp
+++ b/core/string/translation_po.cpp
@@ -158,7 +158,7 @@ int TranslationPO::_get_plural_index(int p_n) const {
void TranslationPO::_cache_plural_tests(const String &p_plural_rule) {
// Some examples of p_plural_rule passed in can have the form:
// "n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5" (Arabic)
- // "n >= 2" (French) // When evaluating the last, esp careful with this one.
+ // "n >= 2" (French) // When evaluating the last, especially careful with this one.
// "n != 1" (English)
int first_ques_mark = p_plural_rule.find("?");
if (first_ques_mark == -1) {
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index 9f931ef30b..28228e4a83 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -1764,7 +1764,7 @@ bool String::parse_utf8(const char *p_utf8, int p_len) {
if (skip) {
_UNICERROR("no space left");
- return true; //not enough spac
+ return true; //not enough space
}
}
@@ -4480,7 +4480,7 @@ String String::sprintf(const Array &values, bool *error) const {
for (; *self; self++) {
const char32_t c = *self;
- if (in_format) { // We have % - lets see what else we get.
+ if (in_format) { // We have % - let's see what else we get.
switch (c) {
case '%': { // Replace %% with %
formatted += chr(c);
diff --git a/core/variant/array.cpp b/core/variant/array.cpp
index 9a2922a777..347c6cd82e 100644
--- a/core/variant/array.cpp
+++ b/core/variant/array.cpp
@@ -141,7 +141,7 @@ uint32_t Array::hash() const {
void Array::_assign(const Array &p_array) {
if (_p->typed.type != Variant::OBJECT && _p->typed.type == p_array._p->typed.type) {
- //same type or untyped, just reference, shuold be fine
+ //same type or untyped, just reference, should be fine
_ref(p_array);
} else if (_p->typed.type == Variant::NIL) { //from typed to untyped, must copy, but this is cheap anyway
_p->array = p_array._p->array;
diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h
index 490bd45b7b..8c0b7907e3 100644
--- a/core/variant/binder_common.h
+++ b/core/variant/binder_common.h
@@ -238,6 +238,16 @@ void call_with_ptr_args_static_retc_helper(T *p_instance, R (*p_method)(T *, P..
PtrToArg<R>::encode(p_method(p_instance, PtrToArg<P>::convert(p_args[Is])...), r_ret);
}
+template <class R, class... P, size_t... Is>
+void call_with_ptr_args_static_method_ret_helper(R (*p_method)(P...), const void **p_args, void *r_ret, IndexSequence<Is...>) {
+ PtrToArg<R>::encode(p_method(PtrToArg<P>::convert(p_args[Is])...), r_ret);
+}
+
+template <class... P, size_t... Is>
+void call_with_ptr_args_static_method_helper(void (*p_method)(P...), const void **p_args, IndexSequence<Is...>) {
+ p_method(PtrToArg<P>::convert(p_args[Is])...);
+}
+
template <class T, class... P, size_t... Is>
void call_with_validated_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, IndexSequence<Is...>) {
(p_instance->*p_method)((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...);
@@ -263,6 +273,16 @@ void call_with_validated_variant_args_static_retc_helper(T *p_instance, R (*p_me
VariantInternalAccessor<typename GetSimpleTypeT<R>::type_t>::set(r_ret, p_method(p_instance, (VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...));
}
+template <class R, class... P, size_t... Is>
+void call_with_validated_variant_args_static_method_ret_helper(R (*p_method)(P...), const Variant **p_args, Variant *r_ret, IndexSequence<Is...>) {
+ VariantInternalAccessor<typename GetSimpleTypeT<R>::type_t>::set(r_ret, p_method((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...));
+}
+
+template <class... P, size_t... Is>
+void call_with_validated_variant_args_static_method_helper(void (*p_method)(P...), const Variant **p_args, IndexSequence<Is...>) {
+ p_method((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...);
+}
+
template <class T, class... P>
void call_with_variant_args(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
#ifdef DEBUG_METHODS_ENABLED
@@ -456,6 +476,16 @@ void call_with_ptr_args_static_retc(T *p_instance, R (*p_method)(T *, P...), con
call_with_ptr_args_static_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}
+template <class R, class... P>
+void call_with_ptr_args_static_method_ret(R (*p_method)(P...), const void **p_args, void *r_ret) {
+ call_with_ptr_args_static_method_ret_helper<R, P...>(p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class... P>
+void call_with_ptr_args_static_method(void (*p_method)(P...), const void **p_args) {
+ call_with_ptr_args_static_method_helper<P...>(p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
+}
+
template <class T, class... P>
void call_with_validated_variant_args(Variant *base, void (T::*p_method)(P...), const Variant **p_args) {
call_with_validated_variant_args_helper<T, P...>(VariantGetInternalPtr<T>::get_ptr(base), p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
@@ -476,6 +506,16 @@ void call_with_validated_variant_args_static_retc(Variant *base, R (*p_method)(T
call_with_validated_variant_args_static_retc_helper<T, R, P...>(VariantGetInternalPtr<T>::get_ptr(base), p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}
+template <class... P>
+void call_with_validated_variant_args_static_method(void (*p_method)(P...), const Variant **p_args) {
+ call_with_validated_variant_args_static_method_helper<P...>(p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class R, class... P>
+void call_with_validated_variant_args_static_method_ret(R (*p_method)(P...), const Variant **p_args, Variant *r_ret) {
+ call_with_validated_variant_args_static_method_ret_helper<R, P...>(p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
+}
+
// GCC raises "parameter 'p_args' set but not used" when P = {},
// it's not clever enough to treat other P values as making this branch valid.
#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
@@ -566,6 +606,28 @@ void call_with_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), co
#endif
}
+template <class R, class... P, size_t... Is>
+void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_args, Variant &r_ret, Callable::CallError &r_error, IndexSequence<Is...>) {
+ r_error.error = Callable::CallError::CALL_OK;
+
+#ifdef DEBUG_METHODS_ENABLED
+ r_ret = (p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
+#else
+ r_ret = (p_method)(VariantCaster<P>::cast(*p_args[Is])...);
+#endif
+}
+
+template <class... P, size_t... Is>
+void call_with_variant_args_static(void (*p_method)(P...), const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) {
+ r_error.error = Callable::CallError::CALL_OK;
+
+#ifdef DEBUG_METHODS_ENABLED
+ (p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
+#else
+ (p_method)(VariantCaster<P>::cast(*p_args[Is])...);
+#endif
+}
+
template <class T, class R, class... P>
void call_with_variant_args_ret(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
#ifdef DEBUG_METHODS_ENABLED
@@ -596,6 +658,42 @@ void call_with_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) co
(void)p_args;
}
+template <class R, class... P>
+void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
+#ifdef DEBUG_METHODS_ENABLED
+ if ((size_t)p_argcount > sizeof...(P)) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.argument = sizeof...(P);
+ return;
+ }
+
+ if ((size_t)p_argcount < sizeof...(P)) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = sizeof...(P);
+ return;
+ }
+#endif
+ call_with_variant_args_static_ret<R, P...>(p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class... P>
+void call_with_variant_args_static_ret(void (*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
+#ifdef DEBUG_METHODS_ENABLED
+ if ((size_t)p_argcount > sizeof...(P)) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.argument = sizeof...(P);
+ return;
+ }
+
+ if ((size_t)p_argcount < sizeof...(P)) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = sizeof...(P);
+ return;
+ }
+#endif
+ call_with_variant_args_static<P...>(p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
+}
+
template <class T, class R, class... P>
void call_with_variant_args_retc(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
#ifdef DEBUG_METHODS_ENABLED
@@ -660,6 +758,72 @@ void call_with_variant_args_retc_static_helper_dv(T *p_instance, R (*p_method)(T
call_with_variant_args_retc_static_helper(p_instance, p_method, args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
}
+template <class R, class... P>
+void call_with_variant_args_static_ret_dv(R (*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error, const Vector<Variant> &default_values) {
+#ifdef DEBUG_ENABLED
+ if ((size_t)p_argcount > sizeof...(P)) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.argument = sizeof...(P);
+ return;
+ }
+#endif
+
+ int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
+
+ int32_t dvs = default_values.size();
+#ifdef DEBUG_ENABLED
+ if (missing > dvs) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = sizeof...(P);
+ return;
+ }
+#endif
+
+ const Variant *args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; //avoid zero sized array
+ for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
+ if (i < p_argcount) {
+ args[i] = p_args[i];
+ } else {
+ args[i] = &default_values[i - p_argcount + (dvs - missing)];
+ }
+ }
+
+ call_with_variant_args_static_ret(p_method, args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class... P>
+void call_with_variant_args_static_dv(void (*p_method)(P...), const Variant **p_args, int p_argcount, Callable::CallError &r_error, const Vector<Variant> &default_values) {
+#ifdef DEBUG_ENABLED
+ if ((size_t)p_argcount > sizeof...(P)) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.argument = sizeof...(P);
+ return;
+ }
+#endif
+
+ int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
+
+ int32_t dvs = default_values.size();
+#ifdef DEBUG_ENABLED
+ if (missing > dvs) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = sizeof...(P);
+ return;
+ }
+#endif
+
+ const Variant *args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; //avoid zero sized array
+ for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
+ if (i < p_argcount) {
+ args[i] = p_args[i];
+ } else {
+ args[i] = &default_values[i - p_argcount + (dvs - missing)];
+ }
+ }
+
+ call_with_variant_args_static(p_method, args, r_error, BuildIndexSequence<sizeof...(P)>{});
+}
+
#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp
index bd51e2dd1e..a1d9c5ed2f 100644
--- a/core/variant/callable.cpp
+++ b/core/variant/callable.cpp
@@ -126,7 +126,7 @@ bool Callable::operator==(const Callable &p_callable) const {
if (custom_a == custom_b) {
if (custom_a) {
if (custom == p_callable.custom) {
- return true; //same pointer, dont even compare
+ return true; //same pointer, don't even compare
}
CallableCustom::CompareEqualFunc eq_a = custom->get_compare_equal_func();
@@ -155,7 +155,7 @@ bool Callable::operator<(const Callable &p_callable) const {
if (custom_a == custom_b) {
if (custom_a) {
if (custom == p_callable.custom) {
- return false; //same pointer, dont even compare
+ return false; //same pointer, don't even compare
}
CallableCustom::CompareLessFunc less_a = custom->get_compare_less_func();
diff --git a/core/variant/variant.h b/core/variant/variant.h
index 5050aa24ec..0acafc64fa 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -495,6 +495,7 @@ public:
static bool has_builtin_method_return_value(Variant::Type p_type, const StringName &p_method);
static Variant::Type get_builtin_method_return_type(Variant::Type p_type, const StringName &p_method);
static bool is_builtin_method_const(Variant::Type p_type, const StringName &p_method);
+ static bool is_builtin_method_static(Variant::Type p_type, const StringName &p_method);
static bool is_builtin_method_vararg(Variant::Type p_type, const StringName &p_method);
static void get_builtin_method_list(Variant::Type p_type, List<StringName> *p_list);
static int get_builtin_method_count(Variant::Type p_type);
@@ -502,6 +503,8 @@ public:
void call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error);
Variant call(const StringName &p_method, const Variant &p_arg1 = Variant(), const Variant &p_arg2 = Variant(), const Variant &p_arg3 = Variant(), const Variant &p_arg4 = Variant(), const Variant &p_arg5 = Variant());
+ static void call_static(Variant::Type p_type, const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error);
+
static String get_call_error_text(const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce);
static String get_call_error_text(Object *p_base, const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce);
static String get_callable_error_text(const Callable &p_callable, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce);
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 90272ad5b4..8c1d8066d6 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -42,6 +42,16 @@
typedef void (*VariantFunc)(Variant &r_ret, Variant &p_self, const Variant **p_args);
typedef void (*VariantConstructFunc)(Variant &r_ret, const Variant **p_args);
+template <class R, class... P>
+static _FORCE_INLINE_ void vc_static_method_call(R (*method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
+ call_with_variant_args_static_ret_dv(method, p_args, p_argcount, r_ret, r_error, p_defvals);
+}
+
+template <class... P>
+static _FORCE_INLINE_ void vc_static_method_call(void (*method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
+ call_with_variant_args_static_dv(method, p_args, p_argcount, r_error, p_defvals);
+}
+
template <class R, class T, class... P>
static _FORCE_INLINE_ void vc_method_call(R (T::*method)(P...), Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
call_with_variant_args_ret_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_ret, r_error, p_defvals);
@@ -81,6 +91,16 @@ static _FORCE_INLINE_ void vc_validated_call(void (T::*method)(P...) const, Vari
call_with_validated_variant_argsc(base, method, p_args);
}
+template <class R, class... P>
+static _FORCE_INLINE_ void vc_validated_static_call(R (*method)(P...), const Variant **p_args, Variant *r_ret) {
+ call_with_validated_variant_args_static_method_ret(method, p_args, r_ret);
+}
+
+template <class... P>
+static _FORCE_INLINE_ void vc_validated_static_call(void (*method)(P...), const Variant **p_args, Variant *r_ret) {
+ call_with_validated_variant_args_static_method(method, p_args);
+}
+
template <class R, class T, class... P>
static _FORCE_INLINE_ void vc_ptrcall(R (T::*method)(P...), void *p_base, const void **p_args, void *r_ret) {
call_with_ptr_args_ret(reinterpret_cast<T *>(p_base), method, p_args, r_ret);
@@ -150,6 +170,11 @@ static _FORCE_INLINE_ int vc_get_argument_count(R (*method)(T *, P...)) {
return sizeof...(P);
}
+template <class R, class... P>
+static _FORCE_INLINE_ int vc_get_argument_count_static(R (*method)(P...)) {
+ return sizeof...(P);
+}
+
template <class R, class T, class... P>
static _FORCE_INLINE_ Variant::Type vc_get_argument_type(R (T::*method)(P...), int p_arg) {
return call_get_argument_type<P...>(p_arg);
@@ -174,6 +199,11 @@ static _FORCE_INLINE_ Variant::Type vc_get_argument_type(R (*method)(T *, P...),
return call_get_argument_type<P...>(p_arg);
}
+template <class R, class... P>
+static _FORCE_INLINE_ Variant::Type vc_get_argument_type_static(R (*method)(P...), int p_arg) {
+ return call_get_argument_type<P...>(p_arg);
+}
+
template <class R, class T, class... P>
static _FORCE_INLINE_ Variant::Type vc_get_return_type(R (T::*method)(P...)) {
return GetTypeInfo<R>::VARIANT_TYPE;
@@ -218,6 +248,16 @@ static _FORCE_INLINE_ bool vc_has_return_type(void (T::*method)(P...) const) {
return false;
}
+template <class... P>
+static _FORCE_INLINE_ bool vc_has_return_type_static(void (*method)(P...)) {
+ return false;
+}
+
+template <class R, class... P>
+static _FORCE_INLINE_ bool vc_has_return_type_static(R (*method)(P...)) {
+ return true;
+}
+
template <class R, class T, class... P>
static _FORCE_INLINE_ bool vc_is_const(R (T::*method)(P...)) {
return false;
@@ -283,6 +323,9 @@ static _FORCE_INLINE_ Variant::Type vc_get_base_type(void (T::*method)(P...) con
static bool is_const() { \
return vc_is_const(m_method_ptr); \
} \
+ static bool is_static() { \
+ return false; \
+ } \
static bool is_vararg() { \
return false; \
} \
@@ -294,6 +337,57 @@ static _FORCE_INLINE_ Variant::Type vc_get_base_type(void (T::*method)(P...) con
} \
};
+template <class R, class... P>
+static _FORCE_INLINE_ void vc_static_ptrcall(R (*method)(P...), const void **p_args, void *r_ret) {
+ call_with_ptr_args_static_method_ret<R, P...>(method, p_args, r_ret);
+}
+
+template <class... P>
+static _FORCE_INLINE_ void vc_static_ptrcall(void (*method)(P...), const void **p_args, void *r_ret) {
+ call_with_ptr_args_static_method<P...>(method, p_args);
+}
+
+#define STATIC_METHOD_CLASS(m_class, m_method_name, m_method_ptr) \
+ struct Method_##m_class##_##m_method_name { \
+ static void call(Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { \
+ vc_static_method_call(m_method_ptr, p_args, p_argcount, r_ret, p_defvals, r_error); \
+ } \
+ static void validated_call(Variant *base, const Variant **p_args, int p_argcount, Variant *r_ret) { \
+ vc_change_return_type(m_method_ptr, r_ret); \
+ vc_validated_static_call(m_method_ptr, p_args, r_ret); \
+ } \
+ static void ptrcall(void *p_base, const void **p_args, void *r_ret, int p_argcount) { \
+ vc_static_ptrcall(m_method_ptr, p_args, r_ret); \
+ } \
+ static int get_argument_count() { \
+ return vc_get_argument_count_static(m_method_ptr); \
+ } \
+ static Variant::Type get_argument_type(int p_arg) { \
+ return vc_get_argument_type_static(m_method_ptr, p_arg); \
+ } \
+ static Variant::Type get_return_type() { \
+ return vc_get_return_type(m_method_ptr); \
+ } \
+ static bool has_return_type() { \
+ return vc_has_return_type_static(m_method_ptr); \
+ } \
+ static bool is_const() { \
+ return false; \
+ } \
+ static bool is_static() { \
+ return true; \
+ } \
+ static bool is_vararg() { \
+ return false; \
+ } \
+ static Variant::Type get_base_type() { \
+ return GetTypeInfo<m_class>::VARIANT_TYPE; \
+ } \
+ static StringName get_name() { \
+ return #m_method_name; \
+ } \
+ };
+
template <class R, class T, class... P>
static _FORCE_INLINE_ void vc_ptrcall(R (*method)(T *, P...), void *p_base, const void **p_args, void *r_ret) {
call_with_ptr_args_static_retc<T, R, P...>(reinterpret_cast<T *>(p_base), method, p_args, r_ret);
@@ -326,6 +420,9 @@ static _FORCE_INLINE_ void vc_ptrcall(R (*method)(T *, P...), void *p_base, cons
static bool is_const() { \
return true; \
} \
+ static bool is_static() { \
+ return false; \
+ } \
static bool is_vararg() { \
return false; \
} \
@@ -379,6 +476,9 @@ static _FORCE_INLINE_ void vc_ptrcall(R (*method)(T *, P...), void *p_base, cons
static bool is_const() { \
return true; \
} \
+ static bool is_static() { \
+ return false; \
+ } \
static bool is_vararg() { \
return true; \
} \
@@ -549,6 +649,7 @@ struct VariantBuiltInMethodInfo {
Vector<String> argument_names;
bool is_const;
+ bool is_static;
bool has_return_type;
bool is_vararg;
Variant::Type return_type;
@@ -580,6 +681,7 @@ static void register_builtin_method(const Vector<String> &p_argnames, const Vect
imi.argument_names = p_argnames;
imi.is_const = T::is_const();
+ imi.is_static = T::is_static();
imi.is_vararg = T::is_vararg();
imi.has_return_type = T::has_return_type();
imi.return_type = T::get_return_type();
@@ -625,6 +727,24 @@ void Variant::call(const StringName &p_method, const Variant **p_args, int p_arg
}
}
+void Variant::call_static(Variant::Type p_type, const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
+ r_error.error = Callable::CallError::CALL_OK;
+
+ const VariantBuiltInMethodInfo *imf = builtin_method_info[p_type].lookup_ptr(p_method);
+
+ if (!imf) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
+ return;
+ }
+
+ if (!imf->is_static) {
+ r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL;
+ return;
+ }
+
+ imf->call(nullptr, p_args, p_argcount, r_ret, imf->default_arguments, r_error);
+}
+
bool Variant::has_method(const StringName &p_method) const {
if (type == OBJECT) {
Object *obj = get_validated_object();
@@ -724,6 +844,13 @@ bool Variant::is_builtin_method_const(Variant::Type p_type, const StringName &p_
return method->is_const;
}
+bool Variant::is_builtin_method_static(Variant::Type p_type, const StringName &p_method) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false);
+ const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
+ ERR_FAIL_COND_V(!method, false);
+ return method->is_static;
+}
+
bool Variant::is_builtin_method_vararg(Variant::Type p_type, const StringName &p_method) {
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false);
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
@@ -759,7 +886,9 @@ void Variant::get_method_list(List<MethodInfo> *p_list) const {
if (method->is_vararg) {
mi.flags |= METHOD_FLAG_VARARG;
}
-
+ if (method->is_static) {
+ mi.flags |= METHOD_FLAG_STATIC;
+ }
for (int i = 0; i < method->argument_count; i++) {
PropertyInfo pi;
#ifdef DEBUG_METHODS_ENABLED
@@ -855,6 +984,16 @@ Variant Variant::get_constant_value(Variant::Type p_type, const StringName &p_va
#endif
#ifdef DEBUG_METHODS_ENABLED
+#define bind_static_method(m_type, m_method, m_arg_names, m_default_args) \
+ STATIC_METHOD_CLASS(m_type, m_method, m_type::m_method); \
+ register_builtin_method<Method_##m_type##_##m_method>(m_arg_names, m_default_args);
+#else
+#define bind_static_method(m_type, m_method, m_arg_names, m_default_args) \
+ STATIC_METHOD_CLASS(m_type, m_method, m_type ::m_method); \
+ register_builtin_method<Method_##m_type##_##m_method>(sarray(), m_default_args);
+#endif
+
+#ifdef DEBUG_METHODS_ENABLED
#define bind_methodv(m_type, m_name, m_method, m_arg_names, m_default_args) \
METHOD_CLASS(m_type, m_name, m_method); \
register_builtin_method<Method_##m_type##_##m_name>(m_arg_names, m_default_args);
@@ -983,6 +1122,11 @@ static void _register_variant_builtin_methods() {
bind_method(String, to_utf16_buffer, sarray(), varray());
bind_method(String, to_utf32_buffer, sarray(), varray());
+ bind_static_method(String, num_scientific, sarray("number"), varray());
+ bind_static_method(String, num, sarray("number", "decimals"), varray(-1));
+ bind_static_method(String, chr, sarray("char"), varray());
+ bind_static_method(String, humanize_size, sarray("size"), varray());
+
/* Vector2 */
bind_method(Vector2, angle, sarray(), varray());
@@ -1147,6 +1291,17 @@ static void _register_variant_builtin_methods() {
//ADDFUNC4R(COLOR, COLOR, Color, from_hsv, FLOAT, "h", FLOAT, "s", FLOAT, "v", FLOAT, "a", varray(1.0));
bind_method(Color, is_equal_approx, sarray("to"), varray());
+ bind_static_method(Color, hex, sarray("hex"), varray());
+ bind_static_method(Color, hex64, sarray("hex"), varray());
+ bind_static_method(Color, html, sarray("rgba"), varray());
+ bind_static_method(Color, html_is_valid, sarray("color"), varray());
+ bind_static_method(Color, find_named_color, sarray("name"), varray());
+ bind_static_method(Color, get_named_color_count, sarray(), varray());
+ bind_static_method(Color, get_named_color_name, sarray("idx"), varray());
+ bind_static_method(Color, get_named_color, sarray("idx"), varray());
+ bind_static_method(Color, from_string, sarray("str", "default"), varray());
+ bind_static_method(Color, from_rgbe9995, sarray("rgbe"), varray());
+
/* RID */
bind_method(RID, get_id, sarray(), varray());
diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp
index ea8263402a..f9cc7c4ff4 100644
--- a/core/variant/variant_setget.cpp
+++ b/core/variant/variant_setget.cpp
@@ -2198,7 +2198,7 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
}
return;
case STRING: {
- //this is pretty funny and bizarre, but artists like to use it for typewritter effects
+ //this is pretty funny and bizarre, but artists like to use it for typewriter effects
String sa = *reinterpret_cast<const String *>(a._data._mem);
String sb = *reinterpret_cast<const String *>(b._data._mem);
String dst;