summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/bind/core_bind.cpp2
-rw-r--r--core/debugger/engine_debugger.cpp2
-rw-r--r--core/debugger/remote_debugger.cpp22
-rw-r--r--core/debugger/remote_debugger_peer.cpp2
-rw-r--r--core/hash_map.h4
-rw-r--r--core/image.cpp20
-rw-r--r--core/image.h2
-rw-r--r--core/io/resource_loader.cpp2
-rw-r--r--core/list.h2
-rw-r--r--core/local_vector.h8
-rw-r--r--core/math/basis.cpp2
-rw-r--r--core/math/expression.cpp2
-rw-r--r--core/math/geometry_3d.cpp2
-rw-r--r--core/math/geometry_3d.h10
-rw-r--r--core/os/main_loop.cpp6
-rw-r--r--core/os/main_loop.h6
-rw-r--r--core/os/os.cpp36
-rw-r--r--core/os/os.h3
-rw-r--r--core/project_settings.cpp2
-rw-r--r--core/ustring.cpp123
-rw-r--r--core/ustring.h11
-rw-r--r--core/variant.cpp2
-rw-r--r--core/variant_call.cpp2
-rw-r--r--core/variant_op.cpp1
24 files changed, 146 insertions, 128 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 267391c4d6..cb82dc7f8f 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -454,7 +454,7 @@ Dictionary _OS::get_datetime_from_unix_time(int64_t unix_time_val) const {
} else {
dayno = (unix_time_val - SECS_DAY + 1) / SECS_DAY;
dayclock = unix_time_val - dayno * SECS_DAY;
- date.weekday = static_cast<OS::Weekday>((dayno - 3) % 7 + 7);
+ date.weekday = static_cast<OS::Weekday>(((dayno % 7) + 11) % 7);
do {
year--;
dayno += YEARSIZE(year);
diff --git a/core/debugger/engine_debugger.cpp b/core/debugger/engine_debugger.cpp
index 5c9fb67de4..4bf31aa55f 100644
--- a/core/debugger/engine_debugger.cpp
+++ b/core/debugger/engine_debugger.cpp
@@ -169,7 +169,7 @@ void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, Ve
for (int i = 0; i < p_breakpoints.size(); i++) {
String bp = p_breakpoints[i];
- int sp = bp.find_last(":");
+ int sp = bp.rfind(":");
ERR_CONTINUE_MSG(sp == -1, "Invalid breakpoint: '" + bp + "', expected file:line format.");
singleton_script_debugger->insert_breakpoint(bp.substr(sp + 1, bp.length()).to_int(), bp.substr(0, sp));
diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp
index 62f600c5e5..9d55e1312e 100644
--- a/core/debugger/remote_debugger.cpp
+++ b/core/debugger/remote_debugger.cpp
@@ -373,6 +373,7 @@ struct RemoteDebugger::VisualProfiler {
struct RemoteDebugger::PerformanceProfiler {
Object *performance = nullptr;
int last_perf_time = 0;
+ uint64_t last_monitor_modification_time = 0;
void toggle(bool p_enable, const Array &p_opts) {}
void add(const Array &p_data) {}
@@ -386,12 +387,31 @@ struct RemoteDebugger::PerformanceProfiler {
return;
}
last_perf_time = pt;
+
+ Array custom_monitor_names = performance->call("get_custom_monitor_names");
+
+ uint64_t monitor_modification_time = performance->call("get_monitor_modification_time");
+ if (monitor_modification_time > last_monitor_modification_time) {
+ last_monitor_modification_time = monitor_modification_time;
+ EngineDebugger::get_singleton()->send_message("performance:profile_names", custom_monitor_names);
+ }
+
int max = performance->get("MONITOR_MAX");
Array arr;
- arr.resize(max);
+ arr.resize(max + custom_monitor_names.size());
for (int i = 0; i < max; i++) {
arr[i] = performance->call("get_monitor", i);
}
+
+ for (int i = 0; i < custom_monitor_names.size(); i++) {
+ Variant monitor_value = performance->call("get_custom_monitor", custom_monitor_names[i]);
+ if (!monitor_value.is_num()) {
+ ERR_PRINT("Value of custom monitor '" + String(custom_monitor_names[i]) + "' is not a number");
+ arr[i + max] = Variant();
+ }
+ arr[i + max] = monitor_value;
+ }
+
EngineDebugger::get_singleton()->send_message("performance:profile_frame", arr);
}
diff --git a/core/debugger/remote_debugger_peer.cpp b/core/debugger/remote_debugger_peer.cpp
index faa3a75fda..0ce0042f50 100644
--- a/core/debugger/remote_debugger_peer.cpp
+++ b/core/debugger/remote_debugger_peer.cpp
@@ -225,7 +225,7 @@ RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create(const String &p_uri) {
uint16_t debug_port = 6007;
if (debug_host.find(":") != -1) {
- int sep_pos = debug_host.find_last(":");
+ int sep_pos = debug_host.rfind(":");
debug_port = debug_host.substr(sep_pos + 1).to_int();
debug_host = debug_host.substr(0, sep_pos);
}
diff --git a/core/hash_map.h b/core/hash_map.h
index 843430d082..10fc931e7a 100644
--- a/core/hash_map.h
+++ b/core/hash_map.h
@@ -280,13 +280,13 @@ public:
const TData &get(const TKey &p_key) const {
const TData *res = getptr(p_key);
- ERR_FAIL_COND_V(!res, *res);
+ CRASH_COND_MSG(!res, "Map key not found.");
return *res;
}
TData &get(const TKey &p_key) {
TData *res = getptr(p_key);
- ERR_FAIL_COND_V(!res, *res);
+ CRASH_COND_MSG(!res, "Map key not found.");
return *res;
}
diff --git a/core/image.cpp b/core/image.cpp
index 45f10625a9..e2f353698f 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -30,6 +30,7 @@
#include "image.h"
+#include "core/error_macros.h"
#include "core/hash_map.h"
#include "core/io/image_loader.h"
#include "core/io/resource_loader.h"
@@ -1894,8 +1895,10 @@ Vector<uint8_t> Image::get_data() const {
}
void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_format) {
- ERR_FAIL_INDEX(p_width - 1, MAX_WIDTH);
- ERR_FAIL_INDEX(p_height - 1, MAX_HEIGHT);
+ ERR_FAIL_COND_MSG(p_width <= 0, "Image width must be greater than 0.");
+ ERR_FAIL_COND_MSG(p_height <= 0, "Image height must be greater than 0.");
+ ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, "Image width cannot be greater than " + itos(MAX_WIDTH) + ".");
+ ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, "Image height cannot be greater than " + itos(MAX_HEIGHT) + ".");
ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, "Too many pixels for image, maximum is " + itos(MAX_PIXELS));
int mm = 0;
@@ -1914,8 +1917,10 @@ void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_forma
}
void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data) {
- ERR_FAIL_INDEX(p_width - 1, MAX_WIDTH);
- ERR_FAIL_INDEX(p_height - 1, MAX_HEIGHT);
+ ERR_FAIL_COND_MSG(p_width <= 0, "Image width must be greater than 0.");
+ ERR_FAIL_COND_MSG(p_height <= 0, "Image height must be greater than 0.");
+ ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, "Image width cannot be greater than " + itos(MAX_WIDTH) + ".");
+ ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, "Image height cannot be greater than " + itos(MAX_HEIGHT) + ".");
ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, "Too many pixels for image, maximum is " + itos(MAX_PIXELS));
int mm;
@@ -2629,6 +2634,7 @@ void Image::fill(const Color &c) {
ImageMemLoadFunc Image::_png_mem_loader_func = nullptr;
ImageMemLoadFunc Image::_jpg_mem_loader_func = nullptr;
ImageMemLoadFunc Image::_webp_mem_loader_func = nullptr;
+ImageMemLoadFunc Image::_tga_mem_loader_func = nullptr;
void (*Image::_image_compress_bc_func)(Image *, float, Image::UsedChannels) = nullptr;
void (*Image::_image_compress_bptc_func)(Image *, float, Image::UsedChannels) = nullptr;
@@ -3058,6 +3064,7 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("load_png_from_buffer", "buffer"), &Image::load_png_from_buffer);
ClassDB::bind_method(D_METHOD("load_jpg_from_buffer", "buffer"), &Image::load_jpg_from_buffer);
ClassDB::bind_method(D_METHOD("load_webp_from_buffer", "buffer"), &Image::load_webp_from_buffer);
+ ClassDB::bind_method(D_METHOD("load_tga_from_buffer", "buffer"), &Image::load_tga_from_buffer);
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "_set_data", "_get_data");
@@ -3389,6 +3396,11 @@ Error Image::load_webp_from_buffer(const Vector<uint8_t> &p_array) {
return _load_from_buffer(p_array, _webp_mem_loader_func);
}
+Error Image::load_tga_from_buffer(const Vector<uint8_t> &p_array) {
+ ERR_FAIL_NULL_V_MSG(_tga_mem_loader_func, ERR_UNAVAILABLE, "TGA module was not installed.");
+ return _load_from_buffer(p_array, _tga_mem_loader_func);
+}
+
void Image::convert_rg_to_ra_rgba8() {
ERR_FAIL_COND(format != FORMAT_RGBA8);
ERR_FAIL_COND(!data.size());
diff --git a/core/image.h b/core/image.h
index 53c203998e..711bf5721c 100644
--- a/core/image.h
+++ b/core/image.h
@@ -135,6 +135,7 @@ public:
static ImageMemLoadFunc _png_mem_loader_func;
static ImageMemLoadFunc _jpg_mem_loader_func;
static ImageMemLoadFunc _webp_mem_loader_func;
+ static ImageMemLoadFunc _tga_mem_loader_func;
static void (*_image_compress_bc_func)(Image *, float, UsedChannels p_channels);
static void (*_image_compress_bptc_func)(Image *, float p_lossy_quality, UsedChannels p_channels);
@@ -360,6 +361,7 @@ public:
Error load_png_from_buffer(const Vector<uint8_t> &p_array);
Error load_jpg_from_buffer(const Vector<uint8_t> &p_array);
Error load_webp_from_buffer(const Vector<uint8_t> &p_array);
+ Error load_tga_from_buffer(const Vector<uint8_t> &p_array);
void convert_rg_to_ra_rgba8();
void convert_ra_rgba8_to_rg();
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index f9d2c9067c..534f3e44de 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -865,7 +865,7 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem
bool near_match = false;
for (int i = 0; i < res_remaps.size(); i++) {
- int split = res_remaps[i].find_last(":");
+ int split = res_remaps[i].rfind(":");
if (split == -1) {
continue;
}
diff --git a/core/list.h b/core/list.h
index 6052a619fb..f850db5241 100644
--- a/core/list.h
+++ b/core/list.h
@@ -348,7 +348,7 @@ public:
* erase an element in the list, by iterator pointing to it. Return true if it was found/erased.
*/
bool erase(const Element *p_I) {
- if (_data) {
+ if (_data && p_I) {
bool ret = _data->erase(p_I);
if (_data->size_cache == 0) {
diff --git a/core/local_vector.h b/core/local_vector.h
index 7f96b25f8b..d97f3330dc 100644
--- a/core/local_vector.h
+++ b/core/local_vector.h
@@ -45,6 +45,14 @@ private:
T *data = nullptr;
public:
+ T *ptr() {
+ return data;
+ }
+
+ const T *ptr() const {
+ return data;
+ }
+
_FORCE_INLINE_ void push_back(T p_elem) {
if (unlikely(count == capacity)) {
if (capacity == 0) {
diff --git a/core/math/basis.cpp b/core/math/basis.cpp
index df5199b0f9..dd38e25bb1 100644
--- a/core/math/basis.cpp
+++ b/core/math/basis.cpp
@@ -773,7 +773,7 @@ Basis::operator String() const {
mtx += ", ";
}
- mtx += rtos(elements[i][j]);
+ mtx += rtos(elements[j][i]); //matrix is stored transposed for performance, so print it transposed
}
}
diff --git a/core/math/expression.cpp b/core/math/expression.cpp
index 6421606ca2..13a49feb6b 100644
--- a/core/math/expression.cpp
+++ b/core/math/expression.cpp
@@ -1064,7 +1064,7 @@ Error Expression::_get_token(Token &r_token) {
if (is_float) {
r_token.value = num.to_double();
} else {
- r_token.value = num.to_int64();
+ r_token.value = num.to_int();
}
return OK;
diff --git a/core/math/geometry_3d.cpp b/core/math/geometry_3d.cpp
index 7eef94c269..7807ab19a7 100644
--- a/core/math/geometry_3d.cpp
+++ b/core/math/geometry_3d.cpp
@@ -993,6 +993,8 @@ Vector<uint32_t> Geometry3D::generate_edf(const Vector<bool> &p_voxels, const Ve
}
}
+ memdelete_arr(work_memory);
+
return ret;
}
diff --git a/core/math/geometry_3d.h b/core/math/geometry_3d.h
index 64cd34892e..6bbf518141 100644
--- a/core/math/geometry_3d.h
+++ b/core/math/geometry_3d.h
@@ -945,6 +945,16 @@ public:
return Color(va6 * v6, vb6 * v6, vc6 * v6, vd6 * v6);
#undef STP
}
+
+ _FORCE_INLINE_ static Vector3 octahedron_map_decode(const Vector2 &p_uv) {
+ // https://twitter.com/Stubbesaurus/status/937994790553227264
+ Vector2 f = p_uv * 2.0 - Vector2(1.0, 1.0);
+ Vector3 n = Vector3(f.x, f.y, 1.0f - Math::abs(f.x) - Math::abs(f.y));
+ float t = CLAMP(-n.z, 0.0, 1.0);
+ n.x += n.x >= 0 ? -t : t;
+ n.y += n.y >= 0 ? -t : t;
+ return n.normalized();
+ }
};
#endif // GEOMETRY_3D_H
diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp
index dc68c2a9f9..434f6fa300 100644
--- a/core/os/main_loop.cpp
+++ b/core/os/main_loop.cpp
@@ -48,8 +48,10 @@ void MainLoop::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_WM_ABOUT);
BIND_CONSTANT(NOTIFICATION_CRASH);
BIND_CONSTANT(NOTIFICATION_OS_IME_UPDATE);
- BIND_CONSTANT(NOTIFICATION_APP_RESUMED);
- BIND_CONSTANT(NOTIFICATION_APP_PAUSED);
+ BIND_CONSTANT(NOTIFICATION_APPLICATION_RESUMED);
+ BIND_CONSTANT(NOTIFICATION_APPLICATION_PAUSED);
+ BIND_CONSTANT(NOTIFICATION_APPLICATION_FOCUS_IN);
+ BIND_CONSTANT(NOTIFICATION_APPLICATION_FOCUS_OUT);
ADD_SIGNAL(MethodInfo("on_request_permissions_result", PropertyInfo(Variant::STRING, "permission"), PropertyInfo(Variant::BOOL, "granted")));
};
diff --git a/core/os/main_loop.h b/core/os/main_loop.h
index 90790a45a1..2c34cf193c 100644
--- a/core/os/main_loop.h
+++ b/core/os/main_loop.h
@@ -52,8 +52,10 @@ public:
NOTIFICATION_WM_ABOUT = 2011,
NOTIFICATION_CRASH = 2012,
NOTIFICATION_OS_IME_UPDATE = 2013,
- NOTIFICATION_APP_RESUMED = 2014,
- NOTIFICATION_APP_PAUSED = 2015,
+ NOTIFICATION_APPLICATION_RESUMED = 2014,
+ NOTIFICATION_APPLICATION_PAUSED = 2015,
+ NOTIFICATION_APPLICATION_FOCUS_IN = 2016,
+ NOTIFICATION_APPLICATION_FOCUS_OUT = 2017,
};
virtual void init();
diff --git a/core/os/os.cpp b/core/os/os.cpp
index c842be333c..231069fcfb 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -41,6 +41,7 @@
#include <stdarg.h>
OS *OS::singleton = nullptr;
+uint64_t OS::target_ticks = 0;
OS *OS::get_singleton() {
return singleton;
@@ -468,6 +469,41 @@ void OS::close_midi_inputs() {
}
}
+void OS::add_frame_delay(bool p_can_draw) {
+ const uint32_t frame_delay = Engine::get_singleton()->get_frame_delay();
+ if (frame_delay) {
+ // Add fixed frame delay to decrease CPU/GPU usage. This doesn't take
+ // the actual frame time into account.
+ // Due to the high fluctuation of the actual sleep duration, it's not recommended
+ // to use this as a FPS limiter.
+ delay_usec(frame_delay * 1000);
+ }
+
+ // Add a dynamic frame delay to decrease CPU/GPU usage. This takes the
+ // previous frame time into account for a smoother result.
+ uint64_t dynamic_delay = 0;
+ if (is_in_low_processor_usage_mode() || !p_can_draw) {
+ dynamic_delay = get_low_processor_usage_mode_sleep_usec();
+ }
+ const int target_fps = Engine::get_singleton()->get_target_fps();
+ if (target_fps > 0 && !Engine::get_singleton()->is_editor_hint()) {
+ // Override the low processor usage mode sleep delay if the target FPS is lower.
+ dynamic_delay = MAX(dynamic_delay, (uint64_t)(1000000 / target_fps));
+ }
+
+ if (dynamic_delay > 0) {
+ target_ticks += dynamic_delay;
+ uint64_t current_ticks = get_ticks_usec();
+
+ if (current_ticks < target_ticks) {
+ delay_usec(target_ticks - current_ticks);
+ }
+
+ current_ticks = get_ticks_usec();
+ target_ticks = MIN(MAX(target_ticks, current_ticks - dynamic_delay), current_ticks + dynamic_delay);
+ }
+}
+
OS::OS() {
void *volatile stack_bottom;
diff --git a/core/os/os.h b/core/os/os.h
index 04e10518dc..f21c0d4df7 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -43,6 +43,7 @@
class OS {
static OS *singleton;
+ static uint64_t target_ticks;
String _execpath;
List<String> _cmdline;
bool _keep_screen_on = true; // set default value to true, because this had been true before godot 2.0.
@@ -212,6 +213,8 @@ public:
virtual double get_unix_time() const;
virtual void delay_usec(uint32_t p_usec) const = 0;
+ virtual void add_frame_delay(bool p_can_draw);
+
virtual uint64_t get_ticks_usec() const = 0;
uint32_t get_ticks_msec() const;
uint64_t get_splash_tick_msec() const;
diff --git a/core/project_settings.cpp b/core/project_settings.cpp
index 5247f6da40..7e96735d67 100644
--- a/core/project_settings.cpp
+++ b/core/project_settings.cpp
@@ -93,7 +93,7 @@ String ProjectSettings::localize_path(const String &p_path) const {
} else {
memdelete(dir);
- int sep = path.find_last("/");
+ int sep = path.rfind("/");
if (sep == -1) {
return "res://" + path;
}
diff --git a/core/ustring.cpp b/core/ustring.cpp
index 444338d5ae..5d3cf5f1a4 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -1618,49 +1618,7 @@ String::String(const StrRange &p_range) {
copy_from(p_range.c_str, p_range.len);
}
-int String::hex_to_int(bool p_with_prefix) const {
- if (p_with_prefix && length() < 3) {
- return 0;
- }
-
- const CharType *s = ptr();
-
- int sign = s[0] == '-' ? -1 : 1;
-
- if (sign < 0) {
- s++;
- }
-
- if (p_with_prefix) {
- if (s[0] != '0' || s[1] != 'x') {
- return 0;
- }
- s += 2;
- }
-
- int hex = 0;
-
- while (*s) {
- CharType c = LOWERCASE(*s);
- int n;
- if (c >= '0' && c <= '9') {
- n = c - '0';
- } else if (c >= 'a' && c <= 'f') {
- n = (c - 'a') + 10;
- } else {
- 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++;
- }
-
- return hex * sign;
-}
-
-int64_t String::hex_to_int64(bool p_with_prefix) const {
+int64_t String::hex_to_int(bool p_with_prefix) const {
if (p_with_prefix && length() < 3) {
return 0;
}
@@ -1692,8 +1650,9 @@ int64_t String::hex_to_int64(bool p_with_prefix) const {
} else {
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."));
+ // Check for overflow/underflow, with special case to ensure INT64_MIN does not result in error
+ bool overflow = ((hex > INT64_MAX / 16) && (sign == 1 || (sign == -1 && hex != (INT64_MAX >> 4) + 1))) || (sign == -1 && hex == (INT64_MAX >> 4) + 1 && c > '0');
+ ERR_FAIL_COND_V_MSG(overflow, 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++;
@@ -1702,7 +1661,7 @@ int64_t String::hex_to_int64(bool p_with_prefix) const {
return hex * sign;
}
-int64_t String::bin_to_int64(bool p_with_prefix) const {
+int64_t String::bin_to_int(bool p_with_prefix) const {
if (p_with_prefix && length() < 3) {
return 0;
}
@@ -1732,8 +1691,9 @@ int64_t String::bin_to_int64(bool p_with_prefix) const {
} else {
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."));
+ // Check for overflow/underflow, with special case to ensure INT64_MIN does not result in error
+ bool overflow = ((binary > INT64_MAX / 2) && (sign == 1 || (sign == -1 && binary != (INT64_MAX >> 1) + 1))) || (sign == -1 && binary == (INT64_MAX >> 1) + 1 && c > '0');
+ ERR_FAIL_COND_V_MSG(overflow, 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++;
@@ -1742,32 +1702,7 @@ int64_t String::bin_to_int64(bool p_with_prefix) const {
return binary * sign;
}
-int String::to_int() const {
- if (length() == 0) {
- return 0;
- }
-
- int to = (find(".") >= 0) ? find(".") : length();
-
- int integer = 0;
- int sign = 1;
-
- for (int i = 0; i < to; i++) {
- 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';
-
- } else if (integer == 0 && c == '-') {
- sign = -sign;
- }
- }
-
- return integer * sign;
-}
-
-int64_t String::to_int64() const {
+int64_t String::to_int() const {
if (length() == 0) {
return 0;
}
@@ -1780,7 +1715,8 @@ int64_t String::to_int64() const {
for (int i = 0; i < to; i++) {
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."));
+ bool overflow = (integer > INT64_MAX / 10) || (integer == INT64_MAX / 10 && ((sign == 1 && c > '7') || (sign == -1 && c > '8')));
+ ERR_FAIL_COND_V_MSG(overflow, 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';
@@ -1792,7 +1728,7 @@ int64_t String::to_int64() const {
return integer * sign;
}
-int String::to_int(const char *p_str, int p_len) {
+int64_t String::to_int(const char *p_str, int p_len) {
int to = 0;
if (p_len >= 0) {
to = p_len;
@@ -1802,13 +1738,14 @@ int String::to_int(const char *p_str, int p_len) {
}
}
- int integer = 0;
- int sign = 1;
+ int64_t integer = 0;
+ int64_t sign = 1;
for (int i = 0; i < to; i++) {
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."));
+ bool overflow = (integer > INT64_MAX / 10) || (integer == INT64_MAX / 10 && ((sign == 1 && c > '7') || (sign == -1 && c > '8')));
+ ERR_FAIL_COND_V_MSG(overflow, sign == 1 ? INT64_MAX : INT64_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';
@@ -2343,18 +2280,6 @@ String String::substr(int p_from, int p_chars) const {
return s;
}
-int String::find_last(const String &p_str) const {
- int pos = -1;
- int findfrom = 0;
- int findres = -1;
- while ((findres = find(p_str, findfrom)) != -1) {
- pos = findres;
- findfrom = pos + 1;
- }
-
- return pos;
-}
-
int String::find(const String &p_str, int p_from) const {
if (p_from < 0) {
return -1;
@@ -2645,7 +2570,7 @@ int String::rfindn(const String &p_str, int p_from) const {
}
bool String::ends_with(const String &p_string) const {
- int pos = find_last(p_string);
+ int pos = rfind(p_string);
if (pos == -1) {
return false;
}
@@ -3838,7 +3763,7 @@ bool String::is_valid_ip_address() const {
continue;
}
if (n.is_valid_hex_number(false)) {
- int nint = n.hex_to_int(false);
+ int64_t nint = n.hex_to_int(false);
if (nint < 0 || nint > 0xffff) {
return false;
}
@@ -3894,7 +3819,7 @@ String String::get_base_dir() const {
}
}
- int sep = MAX(rs.find_last("/"), rs.find_last("\\"));
+ int sep = MAX(rs.rfind("/"), rs.rfind("\\"));
if (sep == -1) {
return base;
}
@@ -3903,7 +3828,7 @@ String String::get_base_dir() const {
}
String String::get_file() const {
- int sep = MAX(find_last("/"), find_last("\\"));
+ int sep = MAX(rfind("/"), rfind("\\"));
if (sep == -1) {
return *this;
}
@@ -3912,8 +3837,8 @@ String String::get_file() const {
}
String String::get_extension() const {
- int pos = find_last(".");
- if (pos < 0 || pos < MAX(find_last("/"), find_last("\\"))) {
+ int pos = rfind(".");
+ if (pos < 0 || pos < MAX(rfind("/"), rfind("\\"))) {
return "";
}
@@ -4001,8 +3926,8 @@ String String::property_name_encode() const {
}
String String::get_basename() const {
- int pos = find_last(".");
- if (pos < 0 || pos < MAX(find_last("/"), find_last("\\"))) {
+ int pos = rfind(".");
+ if (pos < 0 || pos < MAX(rfind("/"), rfind("\\"))) {
return *this;
}
diff --git a/core/ustring.h b/core/ustring.h
index 5b13a1c704..e745475f11 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -202,7 +202,6 @@ public:
int find(const String &p_str, int p_from = 0) const; ///< return <0 if failed
int find(const char *p_str, int p_from = 0) const; ///< return <0 if failed
int find_char(const CharType &p_char, int p_from = 0) const; ///< return <0 if failed
- int find_last(const String &p_str) const; ///< return <0 if failed
int findn(const String &p_str, int p_from = 0) const; ///< return <0 if failed, case insensitive
int rfind(const String &p_str, int p_from = -1) const; ///< return <0 if failed
int rfindn(const String &p_str, int p_from = -1) const; ///< return <0 if failed, case insensitive
@@ -245,13 +244,11 @@ public:
bool is_numeric() const;
double to_double() const;
float to_float() const;
- int hex_to_int(bool p_with_prefix = true) const;
- int to_int() const;
- int64_t hex_to_int64(bool p_with_prefix = true) const;
- int64_t bin_to_int64(bool p_with_prefix = true) const;
- int64_t to_int64() const;
- static int to_int(const char *p_str, int p_len = -1);
+ int64_t hex_to_int(bool p_with_prefix = true) const;
+ int64_t bin_to_int(bool p_with_prefix = true) const;
+ int64_t to_int() const;
+ static int64_t to_int(const char *p_str, int p_len = -1);
static double to_double(const char *p_str);
static double to_double(const CharType *p_str, const CharType **r_end = nullptr);
static int64_t to_int(const CharType *p_str, int p_len = -1, bool p_clamp = false);
diff --git a/core/variant.cpp b/core/variant.cpp
index 21aaa0fe9e..f6b7e2821a 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -1409,7 +1409,7 @@ Variant::operator int64_t() const {
case FLOAT:
return _data._float;
case STRING:
- return operator String().to_int64();
+ return operator String().to_int();
default: {
return 0;
}
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index a8beac1e44..308fa3c407 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -244,7 +244,6 @@ struct _VariantCall {
VCALL_LOCALMEM3R(String, countn);
VCALL_LOCALMEM2R(String, substr);
VCALL_LOCALMEM2R(String, find);
- VCALL_LOCALMEM1R(String, find_last);
VCALL_LOCALMEM2R(String, findn);
VCALL_LOCALMEM2R(String, rfind);
VCALL_LOCALMEM2R(String, rfindn);
@@ -1780,7 +1779,6 @@ void register_variant_methods() {
ADDFUNC3R(STRING, INT, String, count, STRING, "what", INT, "from", INT, "to", varray(0, 0));
ADDFUNC3R(STRING, INT, String, countn, STRING, "what", INT, "from", INT, "to", varray(0, 0));
- ADDFUNC1R(STRING, INT, String, find_last, STRING, "what", varray());
ADDFUNC2R(STRING, INT, String, findn, STRING, "what", INT, "from", varray(0));
ADDFUNC2R(STRING, INT, String, rfind, STRING, "what", INT, "from", varray(-1));
ADDFUNC2R(STRING, INT, String, rfindn, STRING, "what", INT, "from", varray(-1));
diff --git a/core/variant_op.cpp b/core/variant_op.cpp
index 2c79e2029e..0c9a4a992a 100644
--- a/core/variant_op.cpp
+++ b/core/variant_op.cpp
@@ -1786,6 +1786,7 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const {
if (r_valid) {
*r_valid = true;
}
+
switch (type) {
case VECTOR2: {
const Vector2 *v = reinterpret_cast<const Vector2 *>(_data._mem);