summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/SCsub1
-rw-r--r--core/bind/core_bind.cpp5
-rw-r--r--core/bind/core_bind.h1
-rw-r--r--core/color.h4
-rw-r--r--core/func_ref.cpp10
-rw-r--r--core/func_ref.h1
-rw-r--r--core/input/input_map.cpp4
-rw-r--r--core/io/file_access_zip.h2
-rw-r--r--core/io/resource_format_binary.cpp7
-rw-r--r--core/io/resource_importer.cpp3
-rw-r--r--core/list.h40
-rw-r--r--core/math/basis.cpp21
-rw-r--r--core/math/basis.h5
-rw-r--r--core/math/math_funcs.h19
-rw-r--r--core/math/quat.h4
-rw-r--r--core/math/random_pcg.h5
-rw-r--r--core/math/vector2.h30
-rw-r--r--core/message_queue.h3
-rw-r--r--core/object.h2
-rw-r--r--core/os/os.cpp4
-rw-r--r--core/os/os.h2
-rw-r--r--core/project_settings.cpp2
-rw-r--r--core/project_settings.h1
-rw-r--r--core/register_core_types.cpp2
-rw-r--r--core/script_language.cpp8
-rw-r--r--core/translation_po.h2
-rw-r--r--core/ustring.cpp46
-rw-r--r--core/variant_call.cpp4
-rw-r--r--core/variant_op.cpp63
-rw-r--r--core/variant_parser.cpp4
30 files changed, 210 insertions, 95 deletions
diff --git a/core/SCsub b/core/SCsub
index 16ee49d003..59fe63b4b3 100644
--- a/core/SCsub
+++ b/core/SCsub
@@ -121,6 +121,7 @@ if env["builtin_zstd"]:
"compress/zstdmt_compress.c",
"compress/zstd_compress_literals.c",
"compress/zstd_compress_sequences.c",
+ "compress/zstd_compress_superblock.c",
"decompress/huf_decompress.c",
"decompress/zstd_ddict.c",
"decompress/zstd_decompress_block.c",
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 489ff762c9..c68222c767 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -519,10 +519,6 @@ uint64_t _OS::get_ticks_usec() const {
return OS::get_singleton()->get_ticks_usec();
}
-uint32_t _OS::get_splash_tick_msec() const {
- return OS::get_singleton()->get_splash_tick_msec();
-}
-
bool _OS::can_use_threads() const {
return OS::get_singleton()->can_use_threads();
}
@@ -730,7 +726,6 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("delay_msec", "msec"), &_OS::delay_msec);
ClassDB::bind_method(D_METHOD("get_ticks_msec"), &_OS::get_ticks_msec);
ClassDB::bind_method(D_METHOD("get_ticks_usec"), &_OS::get_ticks_usec);
- ClassDB::bind_method(D_METHOD("get_splash_tick_msec"), &_OS::get_splash_tick_msec);
ClassDB::bind_method(D_METHOD("get_locale"), &_OS::get_locale);
ClassDB::bind_method(D_METHOD("get_model_name"), &_OS::get_model_name);
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index a59fcda60c..5c9520d7fe 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -208,7 +208,6 @@ public:
void delay_msec(uint32_t p_msec) const;
uint32_t get_ticks_msec() const;
uint64_t get_ticks_usec() const;
- uint32_t get_splash_tick_msec() const;
bool can_use_threads() const;
diff --git a/core/color.h b/core/color.h
index 096e97e9ae..2dbbc52905 100644
--- a/core/color.h
+++ b/core/color.h
@@ -234,4 +234,8 @@ bool Color::operator<(const Color &p_color) const {
}
}
+_FORCE_INLINE_ Color operator*(const real_t &p_real, const Color &p_color) {
+ return p_color * p_real;
+}
+
#endif // COLOR_H
diff --git a/core/func_ref.cpp b/core/func_ref.cpp
index 4427d94d2a..7e062f16d0 100644
--- a/core/func_ref.cpp
+++ b/core/func_ref.cpp
@@ -64,6 +64,10 @@ void FuncRef::set_function(const StringName &p_func) {
function = p_func;
}
+StringName FuncRef::get_function() {
+ return function;
+}
+
bool FuncRef::is_valid() const {
if (id.is_null()) {
return false;
@@ -88,6 +92,10 @@ void FuncRef::_bind_methods() {
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);
+
+ ClassDB::bind_method(D_METHOD("set_function", "name"), &FuncRef::set_function);
+ ClassDB::bind_method(D_METHOD("get_function"), &FuncRef::get_function);
+
+ ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "function"), "set_function", "get_function");
}
diff --git a/core/func_ref.h b/core/func_ref.h
index 6b0b22bab5..75b84e705e 100644
--- a/core/func_ref.h
+++ b/core/func_ref.h
@@ -46,6 +46,7 @@ public:
Variant call_funcv(const Array &p_args);
void set_instance(Object *p_obj);
void set_function(const StringName &p_func);
+ StringName get_function();
bool is_valid() const;
FuncRef() {}
diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp
index ac032b7d10..6319ffc8f1 100644
--- a/core/input/input_map.cpp
+++ b/core/input/input_map.cpp
@@ -95,6 +95,8 @@ List<StringName> InputMap::get_actions() const {
}
List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength) const {
+ ERR_FAIL_COND_V(!p_event.is_valid(), nullptr);
+
for (List<Ref<InputEvent>>::Element *E = p_action.inputs.front(); E; E = E->next()) {
const Ref<InputEvent> e = E->get();
@@ -126,7 +128,7 @@ void InputMap::action_add_event(const StringName &p_action, const Ref<InputEvent
ERR_FAIL_COND_MSG(p_event.is_null(), "It's not a reference to a valid InputEvent object.");
ERR_FAIL_COND_MSG(!input_map.has(p_action), "Request for nonexistent InputMap action '" + String(p_action) + "'.");
if (_find_event(input_map[p_action], p_event)) {
- return; //already gots
+ return; // Already addded.
}
input_map[p_action].inputs.push_back(p_event);
diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h
index 2cce24e878..c251b3c424 100644
--- a/core/io/file_access_zip.h
+++ b/core/io/file_access_zip.h
@@ -79,7 +79,7 @@ public:
};
class FileAccessZip : public FileAccess {
- unzFile zfile;
+ unzFile zfile = nullptr;
unz_file_info64 file_info;
mutable bool at_eof;
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index 5097f6d98b..21de7835ce 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -863,7 +863,8 @@ void ResourceLoaderBinary::open(FileAccess *p_f) {
if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) {
f->close();
- 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 + ".");
+ ERR_FAIL_MSG(vformat("File '%s' can't be loaded, as it uses a format version (%d) or engine version (%d.%d) which are not supported by your engine version (%s).",
+ local_path, ver_format, ver_major, ver_minor, VERSION_BRANCH));
}
type = get_unicode_string();
@@ -1136,7 +1137,9 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) {
memdelete(f);
memdelete(fw);
- 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 + ".");
+ ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED,
+ vformat("File '%s' can't be loaded, as it uses a format version (%d) or engine version (%d.%d) which are not supported by your engine version (%s).",
+ local_path, ver_format, ver_major, ver_minor, VERSION_BRANCH));
}
// Since we're not actually converting the file contents, leave the version
diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp
index 9ed159bd20..4d980bcf1a 100644
--- a/core/io/resource_importer.cpp
+++ b/core/io/resource_importer.cpp
@@ -31,6 +31,7 @@
#include "resource_importer.h"
#include "core/os/os.h"
+#include "core/project_settings.h"
#include "core/variant_parser.h"
bool ResourceFormatImporter::SortImporterByName::operator()(const Ref<ResourceImporter> &p_a, const Ref<ResourceImporter> &p_b) const {
@@ -374,7 +375,7 @@ Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_extension(const St
}
String ResourceFormatImporter::get_import_base_path(const String &p_for_file) const {
- return "res://.import/" + p_for_file.get_file() + "-" + p_for_file.md5_text();
+ return ProjectSettings::IMPORTED_FILES_PATH.plus_file(p_for_file.get_file() + "-" + p_for_file.md5_text());
}
bool ResourceFormatImporter::are_import_settings_valid(const String &p_path) const {
diff --git a/core/list.h b/core/list.h
index f850db5241..1cef3c484d 100644
--- a/core/list.h
+++ b/core/list.h
@@ -395,28 +395,38 @@ public:
ERR_FAIL_COND(p_A->data != _data);
ERR_FAIL_COND(p_B->data != _data);
+ if (p_A == p_B) {
+ return;
+ }
Element *A_prev = p_A->prev_ptr;
Element *A_next = p_A->next_ptr;
+ Element *B_prev = p_B->prev_ptr;
+ Element *B_next = p_B->next_ptr;
- p_A->next_ptr = p_B->next_ptr;
- p_A->prev_ptr = p_B->prev_ptr;
-
- p_B->next_ptr = A_next;
- p_B->prev_ptr = A_prev;
-
- if (p_A->prev_ptr) {
- p_A->prev_ptr->next_ptr = p_A;
+ if (A_prev) {
+ A_prev->next_ptr = p_B;
+ } else {
+ _data->first = p_B;
}
- if (p_A->next_ptr) {
- p_A->next_ptr->prev_ptr = p_A;
+ if (B_prev) {
+ B_prev->next_ptr = p_A;
+ } else {
+ _data->first = p_A;
}
-
- if (p_B->prev_ptr) {
- p_B->prev_ptr->next_ptr = p_B;
+ if (A_next) {
+ A_next->prev_ptr = p_B;
+ } else {
+ _data->last = p_B;
}
- if (p_B->next_ptr) {
- p_B->next_ptr->prev_ptr = p_B;
+ if (B_next) {
+ B_next->prev_ptr = p_A;
+ } else {
+ _data->last = p_A;
}
+ p_A->prev_ptr = A_next == p_B ? p_B : B_prev;
+ p_A->next_ptr = B_next == p_A ? p_B : B_next;
+ p_B->prev_ptr = B_next == p_A ? p_A : A_prev;
+ p_B->next_ptr = A_next == p_B ? p_A : A_next;
}
/**
* copy the list
diff --git a/core/math/basis.cpp b/core/math/basis.cpp
index dd38e25bb1..a712ae7e3e 100644
--- a/core/math/basis.cpp
+++ b/core/math/basis.cpp
@@ -113,19 +113,22 @@ bool Basis::is_rotation() const {
return Math::is_equal_approx(determinant(), 1, UNIT_EPSILON) && is_orthogonal();
}
+#ifdef MATH_CHECKS
+// This method is only used once, in diagonalize. If it's desired elsewhere, feel free to remove the #ifdef.
bool Basis::is_symmetric() const {
- if (!Math::is_equal_approx_ratio(elements[0][1], elements[1][0], UNIT_EPSILON)) {
+ if (!Math::is_equal_approx(elements[0][1], elements[1][0])) {
return false;
}
- if (!Math::is_equal_approx_ratio(elements[0][2], elements[2][0], UNIT_EPSILON)) {
+ if (!Math::is_equal_approx(elements[0][2], elements[2][0])) {
return false;
}
- if (!Math::is_equal_approx_ratio(elements[1][2], elements[2][1], UNIT_EPSILON)) {
+ if (!Math::is_equal_approx(elements[1][2], elements[2][1])) {
return false;
}
return true;
}
+#endif
Basis Basis::diagonalize() {
//NOTE: only implemented for symmetric matrices
@@ -737,18 +740,6 @@ bool Basis::is_equal_approx(const Basis &p_basis) const {
return elements[0].is_equal_approx(p_basis.elements[0]) && elements[1].is_equal_approx(p_basis.elements[1]) && elements[2].is_equal_approx(p_basis.elements[2]);
}
-bool Basis::is_equal_approx_ratio(const Basis &a, const Basis &b, real_t p_epsilon) const {
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++) {
- if (!Math::is_equal_approx_ratio(a.elements[i][j], b.elements[i][j], p_epsilon)) {
- return false;
- }
- }
- }
-
- return true;
-}
-
bool Basis::operator==(const Basis &p_matrix) const {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
diff --git a/core/math/basis.h b/core/math/basis.h
index a86937ceb4..2584f1ff48 100644
--- a/core/math/basis.h
+++ b/core/math/basis.h
@@ -146,9 +146,6 @@ public:
}
bool is_equal_approx(const Basis &p_basis) const;
- // TODO: Break compatibility in 4.0 by getting rid of this so that it's only an instance method. See also TODO in variant_call.cpp
- bool is_equal_approx(const Basis &a, const Basis &b) const { return a.is_equal_approx(b); }
- bool is_equal_approx_ratio(const Basis &a, const Basis &b, real_t p_epsilon = UNIT_EPSILON) const;
bool operator==(const Basis &p_matrix) const;
bool operator!=(const Basis &p_matrix) const;
@@ -238,7 +235,9 @@ public:
void orthonormalize();
Basis orthonormalized() const;
+#ifdef MATH_CHECKS
bool is_symmetric() const;
+#endif
Basis diagonalize();
operator Quat() const { return get_quat(); }
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index 9f8d4da5b3..f83ee44f4a 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -46,7 +46,8 @@ class Math {
public:
Math() {} // useless to instance
- static const uint64_t RANDOM_MAX = 0xFFFFFFFF;
+ // Not using 'RANDOM_MAX' to avoid conflict with system headers on some OSes (at least NetBSD).
+ static const uint64_t RANDOM_32BIT_MAX = 0xFFFFFFFF;
static _ALWAYS_INLINE_ double sin(double p_x) { return ::sin(p_x); }
static _ALWAYS_INLINE_ float sin(float p_x) { return ::sinf(p_x); }
@@ -283,25 +284,13 @@ public:
static void randomize();
static uint32_t rand_from_seed(uint64_t *seed);
static uint32_t rand();
- static _ALWAYS_INLINE_ double randd() { return (double)rand() / (double)Math::RANDOM_MAX; }
- static _ALWAYS_INLINE_ float randf() { return (float)rand() / (float)Math::RANDOM_MAX; }
+ static _ALWAYS_INLINE_ double randd() { return (double)rand() / (double)Math::RANDOM_32BIT_MAX; }
+ static _ALWAYS_INLINE_ float randf() { return (float)rand() / (float)Math::RANDOM_32BIT_MAX; }
static double random(double from, double to);
static float random(float from, float to);
static real_t random(int from, int to) { return (real_t)random((real_t)from, (real_t)to); }
- static _ALWAYS_INLINE_ bool is_equal_approx_ratio(real_t a, real_t b, real_t epsilon = CMP_EPSILON, real_t min_epsilon = CMP_EPSILON) {
- // this is an approximate way to check that numbers are close, as a ratio of their average size
- // helps compare approximate numbers that may be very big or very small
- real_t diff = abs(a - b);
- if (diff == 0.0 || diff < min_epsilon) {
- return true;
- }
- real_t avg_size = (abs(a) + abs(b)) / 2.0;
- diff /= avg_size;
- return diff < epsilon;
- }
-
static _ALWAYS_INLINE_ bool is_equal_approx(real_t a, real_t b) {
// Check for exact equality first, required to handle "infinity" values.
if (a == b) {
diff --git a/core/math/quat.h b/core/math/quat.h
index 8619ea3c5c..3152b7d233 100644
--- a/core/math/quat.h
+++ b/core/math/quat.h
@@ -224,4 +224,8 @@ bool Quat::operator!=(const Quat &p_quat) const {
return x != p_quat.x || y != p_quat.y || z != p_quat.z || w != p_quat.w;
}
+_FORCE_INLINE_ Quat operator*(const real_t &p_real, const Quat &p_quat) {
+ return p_quat * p_real;
+}
+
#endif // QUAT_H
diff --git a/core/math/random_pcg.h b/core/math/random_pcg.h
index 8fd5a056fa..09b13ab74d 100644
--- a/core/math/random_pcg.h
+++ b/core/math/random_pcg.h
@@ -31,12 +31,12 @@
#ifndef RANDOM_PCG_H
#define RANDOM_PCG_H
-#include <math.h>
-
#include "core/math/math_defs.h"
#include "thirdparty/misc/pcg.h"
+#include <math.h>
+
#if defined(__GNUC__)
#define CLZ32(x) __builtin_clz(x)
#elif defined(_MSC_VER)
@@ -67,7 +67,6 @@ class RandomPCG {
public:
static const uint64_t DEFAULT_SEED = 12047754176567800795U;
static const uint64_t DEFAULT_INC = PCG_DEFAULT_INC_64;
- static const uint64_t RANDOM_MAX = 0xFFFFFFFF;
RandomPCG(uint64_t p_seed = DEFAULT_SEED, uint64_t p_inc = DEFAULT_INC);
diff --git a/core/math/vector2.h b/core/math/vector2.h
index 0966d3392f..f41bcc15bc 100644
--- a/core/math/vector2.h
+++ b/core/math/vector2.h
@@ -150,7 +150,19 @@ _FORCE_INLINE_ Vector2 Vector2::plane_project(real_t p_d, const Vector2 &p_vec)
return p_vec - *this * (dot(p_vec) - p_d);
}
-_FORCE_INLINE_ Vector2 operator*(real_t p_scalar, const Vector2 &p_vec) {
+_FORCE_INLINE_ Vector2 operator*(float p_scalar, const Vector2 &p_vec) {
+ return p_vec * p_scalar;
+}
+
+_FORCE_INLINE_ Vector2 operator*(double p_scalar, const Vector2 &p_vec) {
+ return p_vec * p_scalar;
+}
+
+_FORCE_INLINE_ Vector2 operator*(int32_t p_scalar, const Vector2 &p_vec) {
+ return p_vec * p_scalar;
+}
+
+_FORCE_INLINE_ Vector2 operator*(int64_t p_scalar, const Vector2 &p_vec) {
return p_vec * p_scalar;
}
@@ -304,6 +316,22 @@ struct Vector2i {
}
};
+_FORCE_INLINE_ Vector2i operator*(const int32_t &p_scalar, const Vector2i &p_vector) {
+ return p_vector * p_scalar;
+}
+
+_FORCE_INLINE_ Vector2i operator*(const int64_t &p_scalar, const Vector2i &p_vector) {
+ return p_vector * p_scalar;
+}
+
+_FORCE_INLINE_ Vector2i operator*(const float &p_scalar, const Vector2i &p_vector) {
+ return p_vector * p_scalar;
+}
+
+_FORCE_INLINE_ Vector2i operator*(const double &p_scalar, const Vector2i &p_vector) {
+ return p_vector * p_scalar;
+}
+
typedef Vector2i Size2i;
typedef Vector2i Point2i;
diff --git a/core/message_queue.h b/core/message_queue.h
index 7d13e26208..710a605371 100644
--- a/core/message_queue.h
+++ b/core/message_queue.h
@@ -38,8 +38,7 @@ class MessageQueue {
_THREAD_SAFE_CLASS_
enum {
-
- DEFAULT_QUEUE_SIZE_KB = 1024
+ DEFAULT_QUEUE_SIZE_KB = 4096
};
enum {
diff --git a/core/object.h b/core/object.h
index f9a12da8f6..12ef600dfc 100644
--- a/core/object.h
+++ b/core/object.h
@@ -658,7 +658,7 @@ public:
Variant call(const StringName &p_name, VARIANT_ARG_LIST); // C++ helper
void notification(int p_notification, bool p_reversed = false);
- String to_string();
+ virtual String to_string();
//used mainly by script, get and set all INCLUDING string
virtual Variant getvar(const Variant &p_key, bool *r_valid = nullptr) const;
diff --git a/core/os/os.cpp b/core/os/os.cpp
index dc8bd5ee69..3a398316bd 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -80,10 +80,6 @@ String OS::get_iso_date_time(bool local) const {
timezone;
}
-uint64_t OS::get_splash_tick_msec() const {
- return _msec_splash;
-}
-
double OS::get_unix_time() const {
return 0;
}
diff --git a/core/os/os.h b/core/os/os.h
index 8e5c0c26e0..4c1d930107 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -52,7 +52,6 @@ class OS {
bool _verbose_stdout = false;
bool _debug_stdout = false;
String _local_clipboard;
- uint64_t _msec_splash;
bool _no_window = false;
int _exit_code = 0;
int _orientation;
@@ -220,7 +219,6 @@ public:
virtual uint64_t get_ticks_usec() const = 0;
uint32_t get_ticks_msec() const;
- uint64_t get_splash_tick_msec() const;
virtual bool is_userfs_persistent() const { return true; }
diff --git a/core/project_settings.cpp b/core/project_settings.cpp
index efe13e740d..90f56694c2 100644
--- a/core/project_settings.cpp
+++ b/core/project_settings.cpp
@@ -53,6 +53,8 @@ String ProjectSettings::get_resource_path() const {
return resource_path;
}
+const String ProjectSettings::IMPORTED_FILES_PATH("res://.godot/imported");
+
String ProjectSettings::localize_path(const String &p_path) const {
if (resource_path == "") {
return p_path; //not initialized yet
diff --git a/core/project_settings.h b/core/project_settings.h
index 29b2406dd2..6cbb02d30e 100644
--- a/core/project_settings.h
+++ b/core/project_settings.h
@@ -41,6 +41,7 @@ class ProjectSettings : public Object {
public:
typedef Map<String, Variant> CustomMap;
+ static const String IMPORTED_FILES_PATH;
enum {
//properties that are not for built in values begin from this value, so builtin ones are displayed first
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 4f094dd6c6..a2b3f75bea 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -232,7 +232,7 @@ void register_core_types() {
}
void register_core_settings() {
- //since in register core types, globals may not e present
+ // Since in register core types, globals may not be present.
GLOBAL_DEF("network/limits/tcp/connect_timeout_seconds", (30));
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));
diff --git a/core/script_language.cpp b/core/script_language.cpp
index b63aeb952c..d535c54dea 100644
--- a/core/script_language.cpp
+++ b/core/script_language.cpp
@@ -275,7 +275,13 @@ void ScriptServer::save_global_classes() {
gcarr.push_back(d);
}
- ProjectSettings::get_singleton()->set("_global_script_classes", gcarr);
+ if (gcarr.empty()) {
+ if (ProjectSettings::get_singleton()->has_setting("_global_script_classes")) {
+ ProjectSettings::get_singleton()->clear("_global_script_classes");
+ }
+ } else {
+ ProjectSettings::get_singleton()->set("_global_script_classes", gcarr);
+ }
ProjectSettings::get_singleton()->save();
}
diff --git a/core/translation_po.h b/core/translation_po.h
index 730635f63d..88830210ef 100644
--- a/core/translation_po.h
+++ b/core/translation_po.h
@@ -42,7 +42,7 @@ class TranslationPO : public Translation {
// TLDR: Maps context to a list of source strings and translated strings. In PO terms, maps msgctxt to a list of msgid and msgstr.
// The first key corresponds to context, and the second key (of the contained HashMap) corresponds to source string.
// The value Vector<StringName> in the second map stores the translated strings. Index 0, 1, 2 matches msgstr[0], msgstr[1], msgstr[2]... in the case of plurals.
- // Otherwise index 0 mathes to msgstr in a singular translation.
+ // Otherwise index 0 matches to msgstr in a singular translation.
// Strings without context have "" as first key.
HashMap<StringName, HashMap<StringName, Vector<StringName>>> translation_map;
diff --git a/core/ustring.cpp b/core/ustring.cpp
index d5afbc2b47..e382ef3746 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -787,29 +787,46 @@ signed char String::naturalnocasecmp_to(const String &p_str) const {
if (!*that_str) {
return 1;
} else if (IS_DIGIT(*this_str)) {
- int64_t this_int, that_int;
-
if (!IS_DIGIT(*that_str)) {
return -1;
}
- /* Compare the numbers */
- this_int = to_int(this_str, -1, true);
- that_int = to_int(that_str, -1, true);
-
- if (this_int < that_int) {
- return -1;
- } else if (this_int > that_int) {
- return 1;
- }
+ // Keep ptrs to start of numerical sequences
+ const char32_t *this_substr = this_str;
+ const char32_t *that_substr = that_str;
- /* Skip */
+ // Compare lengths of both numerical sequences, ignoring leading zeros
while (IS_DIGIT(*this_str)) {
this_str++;
}
while (IS_DIGIT(*that_str)) {
that_str++;
}
+ while (*this_substr == '0') {
+ this_substr++;
+ }
+ while (*that_substr == '0') {
+ that_substr++;
+ }
+ int this_len = this_str - this_substr;
+ int that_len = that_str - that_substr;
+
+ if (this_len < that_len) {
+ return -1;
+ } else if (this_len > that_len) {
+ return 1;
+ }
+
+ // If lengths equal, compare lexicographically
+ while (this_substr != this_str && that_substr != that_str) {
+ if (*this_substr < *that_substr) {
+ return -1;
+ } else if (*this_substr > *that_substr) {
+ return 1;
+ }
+ this_substr++;
+ that_substr++;
+ }
} else if (IS_DIGIT(*that_str)) {
return 1;
} else {
@@ -4484,11 +4501,12 @@ String String::sprintf(const Array &values, bool *error) const {
int number_len = str.length();
// Padding.
+ int pad_chars_count = (value < 0 || show_sign) ? min_chars - 1 : min_chars;
String pad_char = pad_with_zeroes ? String("0") : String(" ");
if (left_justified) {
- str = str.rpad(min_chars, pad_char);
+ str = str.rpad(pad_chars_count, pad_char);
} else {
- str = str.lpad(min_chars, pad_char);
+ str = str.lpad(pad_chars_count, pad_char);
}
// Sign.
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 0ebb2f04a1..5fd970c8e1 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -1035,7 +1035,7 @@ struct _VariantCall {
VCALL_PTR0R(Basis, get_orthogonal_index);
VCALL_PTR0R(Basis, orthonormalized);
VCALL_PTR2R(Basis, slerp);
- VCALL_PTR2R(Basis, is_equal_approx); // TODO: Break compatibility in 4.0 to change this to an instance method (a.is_equal_approx(b) as VCALL_PTR1R) for consistency.
+ VCALL_PTR1R(Basis, is_equal_approx);
VCALL_PTR0R(Basis, get_rotation_quat);
VCALL_PTR0R(Transform, inverse);
@@ -2356,7 +2356,7 @@ void register_variant_methods() {
ADDFUNC1R(BASIS, VECTOR3, Basis, xform_inv, VECTOR3, "v", varray());
ADDFUNC0R(BASIS, INT, Basis, get_orthogonal_index, varray());
ADDFUNC2R(BASIS, BASIS, Basis, slerp, BASIS, "b", FLOAT, "t", varray());
- ADDFUNC2R(BASIS, BOOL, Basis, is_equal_approx, BASIS, "b", FLOAT, "epsilon", varray(CMP_EPSILON)); // TODO: Replace in 4.0, see other TODO.
+ ADDFUNC1R(BASIS, BOOL, Basis, is_equal_approx, BASIS, "b", varray());
ADDFUNC0R(BASIS, QUAT, Basis, get_rotation_quat, varray());
ADDFUNC0R(TRANSFORM, TRANSFORM, Transform, inverse, varray());
diff --git a/core/variant_op.cpp b/core/variant_op.cpp
index ec4eea05bf..533b056f91 100644
--- a/core/variant_op.cpp
+++ b/core/variant_op.cpp
@@ -1031,6 +1031,9 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
case FLOAT: {
_RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * p_b._data._float);
}
+ case INT: {
+ _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * p_b._data._int);
+ }
default:
_RETURN_FAIL;
}
@@ -1062,8 +1065,64 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
}
}
- DEFAULT_OP_NUM_VEC(math, OP_MULTIPLY, INT, *, _int);
- DEFAULT_OP_NUM_VEC(math, OP_MULTIPLY, FLOAT, *, _float);
+ CASE_TYPE(math, OP_MULTIPLY, INT) {
+ if (p_b.type == INT) {
+ _RETURN(p_a._data._int * p_b._data._int);
+ }
+ if (p_b.type == FLOAT) {
+ _RETURN(p_a._data._int * p_b._data._float);
+ }
+ if (p_b.type == VECTOR2) {
+ _RETURN(p_a._data._int * *reinterpret_cast<const Vector2 *>(p_b._data._mem));
+ }
+ if (p_b.type == VECTOR3) {
+ _RETURN(p_a._data._int * *reinterpret_cast<const Vector3 *>(p_b._data._mem));
+ }
+ if (p_b.type == VECTOR2I) {
+ _RETURN(p_a._data._int * *reinterpret_cast<const Vector2i *>(p_b._data._mem));
+ }
+ if (p_b.type == VECTOR3I) {
+ _RETURN(p_a._data._int * *reinterpret_cast<const Vector3i *>(p_b._data._mem));
+ }
+ if (p_b.type == QUAT) {
+ _RETURN(p_a._data._int * *reinterpret_cast<const Quat *>(p_b._data._mem));
+ }
+ if (p_b.type == COLOR) {
+ _RETURN(p_a._data._int * *reinterpret_cast<const Color *>(p_b._data._mem));
+ }
+
+ _RETURN_FAIL
+ }
+
+ CASE_TYPE(math, OP_MULTIPLY, FLOAT) {
+ if (p_b.type == INT) {
+ _RETURN(p_a._data._float * p_b._data._int);
+ }
+ if (p_b.type == FLOAT) {
+ _RETURN(p_a._data._float * p_b._data._float);
+ }
+ if (p_b.type == VECTOR2) {
+ _RETURN(p_a._data._float * *reinterpret_cast<const Vector2 *>(p_b._data._mem));
+ }
+ if (p_b.type == VECTOR3) {
+ _RETURN(p_a._data._float * *reinterpret_cast<const Vector3 *>(p_b._data._mem));
+ }
+ if (p_b.type == VECTOR2I) {
+ _RETURN(p_a._data._float * *reinterpret_cast<const Vector2i *>(p_b._data._mem));
+ }
+ if (p_b.type == VECTOR3I) {
+ _RETURN(p_a._data._float * *reinterpret_cast<const Vector3i *>(p_b._data._mem));
+ }
+ if (p_b.type == QUAT) {
+ _RETURN(p_a._data._float * *reinterpret_cast<const Quat *>(p_b._data._mem));
+ }
+ if (p_b.type == COLOR) {
+ _RETURN(p_a._data._float * *reinterpret_cast<const Color *>(p_b._data._mem));
+ }
+
+ _RETURN_FAIL
+ }
+
DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, VECTOR2, *, Vector2);
DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, VECTOR2I, *, Vector2i);
DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, VECTOR3, *, Vector3);
diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp
index 3c4fed68fb..04cd4c1b9b 100644
--- a/core/variant_parser.cpp
+++ b/core/variant_parser.cpp
@@ -1608,10 +1608,12 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
write(dict[E->get()], p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud);
if (E->next()) {
p_store_string_func(p_store_string_ud, ",\n");
+ } else {
+ p_store_string_func(p_store_string_ud, "\n");
}
}
- p_store_string_func(p_store_string_ud, "\n}");
+ p_store_string_func(p_store_string_ud, "}");
} break;
case Variant::ARRAY: {