diff options
Diffstat (limited to 'core')
63 files changed, 2721 insertions, 628 deletions
diff --git a/core/SCsub b/core/SCsub index 0ab4f11d87..d53988fae7 100644 --- a/core/SCsub +++ b/core/SCsub @@ -49,6 +49,7 @@ thirdparty_misc_dir = "#thirdparty/misc/" thirdparty_misc_sources = [ # C sources "fastlz.c", + "r128.c", "smaz.c", # C++ sources "hq2x.cpp", diff --git a/core/class_db.cpp b/core/class_db.cpp index 5e49688e9b..ee93ac73ae 100644 --- a/core/class_db.cpp +++ b/core/class_db.cpp @@ -1456,16 +1456,19 @@ Variant ClassDB::class_get_default_property_value(const StringName &p_class, con } if (!default_values.has(p_class)) { - if (r_valid != nullptr) *r_valid = false; + if (r_valid != nullptr) + *r_valid = false; return Variant(); } if (!default_values[p_class].has(p_property)) { - if (r_valid != nullptr) *r_valid = false; + if (r_valid != nullptr) + *r_valid = false; return Variant(); } - if (r_valid != nullptr) *r_valid = true; + if (r_valid != nullptr) + *r_valid = true; return default_values[p_class][p_property]; } diff --git a/core/color.cpp b/core/color.cpp index 03aeb2085b..79b9f70a99 100644 --- a/core/color.cpp +++ b/core/color.cpp @@ -406,7 +406,8 @@ bool Color::html_is_valid(const String &p_color) { } Color Color::named(const String &p_name) { - if (_named_colors.empty()) _populate_named_colors(); // from color_names.inc + if (_named_colors.empty()) + _populate_named_colors(); // from color_names.inc String name = p_name; // Normalize name name = name.replace(" ", ""); diff --git a/core/color_names.inc b/core/color_names.inc index 428a8473fe..f249ee9868 100644 --- a/core/color_names.inc +++ b/core/color_names.inc @@ -3,7 +3,8 @@ static Map<String, Color> _named_colors; static void _populate_named_colors() { - if (!_named_colors.empty()) return; + if (!_named_colors.empty()) + return; _named_colors.insert("aliceblue", Color(0.94, 0.97, 1.00)); _named_colors.insert("antiquewhite", Color(0.98, 0.92, 0.84)); _named_colors.insert("aqua", Color(0.00, 1.00, 1.00)); diff --git a/core/command_queue_mt.h b/core/command_queue_mt.h index 558453bdf5..2f2b3b783c 100644 --- a/core/command_queue_mt.h +++ b/core/command_queue_mt.h @@ -253,7 +253,8 @@ cmd->method = p_method; \ SEMIC_SEP_LIST(CMD_ASSIGN_PARAM, N); \ unlock(); \ - if (sync) sync->post(); \ + if (sync) \ + sync->post(); \ } #define CMD_RET_TYPE(N) CommandRet##N<T, M, COMMA_SEP_LIST(TYPE_ARG, N) COMMA(N) R> @@ -269,7 +270,8 @@ cmd->ret = r_ret; \ cmd->sync_sem = ss; \ unlock(); \ - if (sync) sync->post(); \ + if (sync) \ + sync->post(); \ ss->sem.wait(); \ ss->in_use = false; \ } @@ -286,7 +288,8 @@ SEMIC_SEP_LIST(CMD_ASSIGN_PARAM, N); \ cmd->sync_sem = ss; \ unlock(); \ - if (sync) sync->post(); \ + if (sync) \ + sync->post(); \ ss->sem.wait(); \ ss->in_use = false; \ } @@ -418,12 +421,14 @@ class CommandQueueMT { } bool flush_one(bool p_lock = true) { - if (p_lock) lock(); + if (p_lock) + lock(); tryagain: // tried to read an empty queue if (read_ptr == write_ptr) { - if (p_lock) unlock(); + if (p_lock) + unlock(); return false; } @@ -442,15 +447,18 @@ class CommandQueueMT { read_ptr += size; - if (p_lock) unlock(); + if (p_lock) + unlock(); cmd->call(); - if (p_lock) lock(); + if (p_lock) + lock(); cmd->post(); cmd->~CommandBase(); *(uint32_t *)&command_mem[size_ptr] &= ~1; - if (p_lock) unlock(); + if (p_lock) + unlock(); return true; } diff --git a/core/container_type_validate.h b/core/container_type_validate.h index 3721668033..7809e5f385 100644 --- a/core/container_type_validate.h +++ b/core/container_type_validate.h @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* container_type_validate.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + #ifndef CONTAINER_TYPE_VALIDATE_H #define CONTAINER_TYPE_VALIDATE_H diff --git a/core/error_macros.h b/core/error_macros.h index 18c46c9e7d..83f92129a5 100644 --- a/core/error_macros.h +++ b/core/error_macros.h @@ -530,19 +530,19 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Prints `m_msg`. */ #define ERR_PRINT(m_msg) \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, DEBUG_STR(m_msg)) + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg) /** * Prints `m_msg` once during the application lifetime. */ -#define ERR_PRINT_ONCE(m_msg) \ - if (1) { \ - static bool first_print = true; \ - if (first_print) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, DEBUG_STR(m_msg)); \ - first_print = false; \ - } \ - } else \ +#define ERR_PRINT_ONCE(m_msg) \ + if (1) { \ + static bool first_print = true; \ + if (first_print) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg); \ + first_print = false; \ + } \ + } else \ ((void)0) // Print warning message macros. @@ -553,21 +553,21 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead. */ #define WARN_PRINT(m_msg) \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, DEBUG_STR(m_msg), ERR_HANDLER_WARNING) + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, ERR_HANDLER_WARNING) /** * Prints `m_msg` once during the application lifetime. * * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead. */ -#define WARN_PRINT_ONCE(m_msg) \ - if (1) { \ - static bool first_print = true; \ - if (first_print) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, DEBUG_STR(m_msg), ERR_HANDLER_WARNING); \ - first_print = false; \ - } \ - } else \ +#define WARN_PRINT_ONCE(m_msg) \ + if (1) { \ + static bool first_print = true; \ + if (first_print) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, ERR_HANDLER_WARNING); \ + first_print = false; \ + } \ + } else \ ((void)0) // Print deprecated warning message macros. diff --git a/core/image.cpp b/core/image.cpp index 58351ae2e5..ff8acc54af 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -114,23 +114,36 @@ int Image::get_format_pixel_size(Format p_format) { return 1; //luminance case FORMAT_LA8: return 2; //luminance-alpha - case FORMAT_R8: return 1; - case FORMAT_RG8: return 2; - case FORMAT_RGB8: return 3; - case FORMAT_RGBA8: return 4; - case FORMAT_RGBA4444: return 2; - case FORMAT_RGB565: return 2; + case FORMAT_R8: + return 1; + case FORMAT_RG8: + return 2; + case FORMAT_RGB8: + return 3; + case FORMAT_RGBA8: + return 4; + case FORMAT_RGBA4444: + return 2; + case FORMAT_RGB565: + return 2; case FORMAT_RF: return 4; //float - case FORMAT_RGF: return 8; - case FORMAT_RGBF: return 12; - case FORMAT_RGBAF: return 16; + case FORMAT_RGF: + return 8; + case FORMAT_RGBF: + return 12; + case FORMAT_RGBAF: + return 16; case FORMAT_RH: return 2; //half float - case FORMAT_RGH: return 4; - case FORMAT_RGBH: return 6; - case FORMAT_RGBAH: return 8; - case FORMAT_RGBE9995: return 4; + case FORMAT_RGH: + return 4; + case FORMAT_RGBH: + return 6; + case FORMAT_RGBAH: + return 8; + case FORMAT_RGBE9995: + return 4; case FORMAT_DXT1: return 1; //s3tc bc1 case FORMAT_DXT3: @@ -149,22 +162,32 @@ int Image::get_format_pixel_size(Format p_format) { return 1; //unsigned float case FORMAT_PVRTC2: return 1; //pvrtc - case FORMAT_PVRTC2A: return 1; - case FORMAT_PVRTC4: return 1; - case FORMAT_PVRTC4A: return 1; + case FORMAT_PVRTC2A: + return 1; + case FORMAT_PVRTC4: + return 1; + case FORMAT_PVRTC4A: + return 1; case FORMAT_ETC: return 1; //etc1 case FORMAT_ETC2_R11: return 1; //etc2 case FORMAT_ETC2_R11S: return 1; //signed: return 1; NOT srgb. - case FORMAT_ETC2_RG11: return 1; - case FORMAT_ETC2_RG11S: return 1; - case FORMAT_ETC2_RGB8: return 1; - case FORMAT_ETC2_RGBA8: return 1; - case FORMAT_ETC2_RGB8A1: return 1; - case FORMAT_ETC2_RA_AS_RG: return 1; - case FORMAT_DXT5_RA_AS_RG: return 1; + case FORMAT_ETC2_RG11: + return 1; + case FORMAT_ETC2_RG11S: + return 1; + case FORMAT_ETC2_RGB8: + return 1; + case FORMAT_ETC2_RGBA8: + return 1; + case FORMAT_ETC2_RGB8A1: + return 1; + case FORMAT_ETC2_RA_AS_RG: + return 1; + case FORMAT_DXT5_RA_AS_RG: + return 1; case FORMAT_MAX: { } } @@ -478,36 +501,96 @@ void Image::convert(Format p_new_format) { switch (conversion_type) { - case FORMAT_L8 | (FORMAT_LA8 << 8): _convert<1, false, 1, true, true, true>(width, height, rptr, wptr); break; - case FORMAT_L8 | (FORMAT_R8 << 8): _convert<1, false, 1, false, true, false>(width, height, rptr, wptr); break; - case FORMAT_L8 | (FORMAT_RG8 << 8): _convert<1, false, 2, false, true, false>(width, height, rptr, wptr); break; - case FORMAT_L8 | (FORMAT_RGB8 << 8): _convert<1, false, 3, false, true, false>(width, height, rptr, wptr); break; - case FORMAT_L8 | (FORMAT_RGBA8 << 8): _convert<1, false, 3, true, true, false>(width, height, rptr, wptr); break; - case FORMAT_LA8 | (FORMAT_L8 << 8): _convert<1, true, 1, false, true, true>(width, height, rptr, wptr); break; - case FORMAT_LA8 | (FORMAT_R8 << 8): _convert<1, true, 1, false, true, false>(width, height, rptr, wptr); break; - case FORMAT_LA8 | (FORMAT_RG8 << 8): _convert<1, true, 2, false, true, false>(width, height, rptr, wptr); break; - case FORMAT_LA8 | (FORMAT_RGB8 << 8): _convert<1, true, 3, false, true, false>(width, height, rptr, wptr); break; - case FORMAT_LA8 | (FORMAT_RGBA8 << 8): _convert<1, true, 3, true, true, false>(width, height, rptr, wptr); break; - case FORMAT_R8 | (FORMAT_L8 << 8): _convert<1, false, 1, false, false, true>(width, height, rptr, wptr); break; - case FORMAT_R8 | (FORMAT_LA8 << 8): _convert<1, false, 1, true, false, true>(width, height, rptr, wptr); break; - case FORMAT_R8 | (FORMAT_RG8 << 8): _convert<1, false, 2, false, false, false>(width, height, rptr, wptr); break; - case FORMAT_R8 | (FORMAT_RGB8 << 8): _convert<1, false, 3, false, false, false>(width, height, rptr, wptr); break; - case FORMAT_R8 | (FORMAT_RGBA8 << 8): _convert<1, false, 3, true, false, false>(width, height, rptr, wptr); break; - case FORMAT_RG8 | (FORMAT_L8 << 8): _convert<2, false, 1, false, false, true>(width, height, rptr, wptr); break; - case FORMAT_RG8 | (FORMAT_LA8 << 8): _convert<2, false, 1, true, false, true>(width, height, rptr, wptr); break; - case FORMAT_RG8 | (FORMAT_R8 << 8): _convert<2, false, 1, false, false, false>(width, height, rptr, wptr); break; - case FORMAT_RG8 | (FORMAT_RGB8 << 8): _convert<2, false, 3, false, false, false>(width, height, rptr, wptr); break; - case FORMAT_RG8 | (FORMAT_RGBA8 << 8): _convert<2, false, 3, true, false, false>(width, height, rptr, wptr); break; - case FORMAT_RGB8 | (FORMAT_L8 << 8): _convert<3, false, 1, false, false, true>(width, height, rptr, wptr); break; - case FORMAT_RGB8 | (FORMAT_LA8 << 8): _convert<3, false, 1, true, false, true>(width, height, rptr, wptr); break; - case FORMAT_RGB8 | (FORMAT_R8 << 8): _convert<3, false, 1, false, false, false>(width, height, rptr, wptr); break; - case FORMAT_RGB8 | (FORMAT_RG8 << 8): _convert<3, false, 2, false, false, false>(width, height, rptr, wptr); break; - case FORMAT_RGB8 | (FORMAT_RGBA8 << 8): _convert<3, false, 3, true, false, false>(width, height, rptr, wptr); break; - case FORMAT_RGBA8 | (FORMAT_L8 << 8): _convert<3, true, 1, false, false, true>(width, height, rptr, wptr); break; - case FORMAT_RGBA8 | (FORMAT_LA8 << 8): _convert<3, true, 1, true, false, true>(width, height, rptr, wptr); break; - case FORMAT_RGBA8 | (FORMAT_R8 << 8): _convert<3, true, 1, false, false, false>(width, height, rptr, wptr); break; - case FORMAT_RGBA8 | (FORMAT_RG8 << 8): _convert<3, true, 2, false, false, false>(width, height, rptr, wptr); break; - case FORMAT_RGBA8 | (FORMAT_RGB8 << 8): _convert<3, true, 3, false, false, false>(width, height, rptr, wptr); break; + case FORMAT_L8 | (FORMAT_LA8 << 8): + _convert<1, false, 1, true, true, true>(width, height, rptr, wptr); + break; + case FORMAT_L8 | (FORMAT_R8 << 8): + _convert<1, false, 1, false, true, false>(width, height, rptr, wptr); + break; + case FORMAT_L8 | (FORMAT_RG8 << 8): + _convert<1, false, 2, false, true, false>(width, height, rptr, wptr); + break; + case FORMAT_L8 | (FORMAT_RGB8 << 8): + _convert<1, false, 3, false, true, false>(width, height, rptr, wptr); + break; + case FORMAT_L8 | (FORMAT_RGBA8 << 8): + _convert<1, false, 3, true, true, false>(width, height, rptr, wptr); + break; + case FORMAT_LA8 | (FORMAT_L8 << 8): + _convert<1, true, 1, false, true, true>(width, height, rptr, wptr); + break; + case FORMAT_LA8 | (FORMAT_R8 << 8): + _convert<1, true, 1, false, true, false>(width, height, rptr, wptr); + break; + case FORMAT_LA8 | (FORMAT_RG8 << 8): + _convert<1, true, 2, false, true, false>(width, height, rptr, wptr); + break; + case FORMAT_LA8 | (FORMAT_RGB8 << 8): + _convert<1, true, 3, false, true, false>(width, height, rptr, wptr); + break; + case FORMAT_LA8 | (FORMAT_RGBA8 << 8): + _convert<1, true, 3, true, true, false>(width, height, rptr, wptr); + break; + case FORMAT_R8 | (FORMAT_L8 << 8): + _convert<1, false, 1, false, false, true>(width, height, rptr, wptr); + break; + case FORMAT_R8 | (FORMAT_LA8 << 8): + _convert<1, false, 1, true, false, true>(width, height, rptr, wptr); + break; + case FORMAT_R8 | (FORMAT_RG8 << 8): + _convert<1, false, 2, false, false, false>(width, height, rptr, wptr); + break; + case FORMAT_R8 | (FORMAT_RGB8 << 8): + _convert<1, false, 3, false, false, false>(width, height, rptr, wptr); + break; + case FORMAT_R8 | (FORMAT_RGBA8 << 8): + _convert<1, false, 3, true, false, false>(width, height, rptr, wptr); + break; + case FORMAT_RG8 | (FORMAT_L8 << 8): + _convert<2, false, 1, false, false, true>(width, height, rptr, wptr); + break; + case FORMAT_RG8 | (FORMAT_LA8 << 8): + _convert<2, false, 1, true, false, true>(width, height, rptr, wptr); + break; + case FORMAT_RG8 | (FORMAT_R8 << 8): + _convert<2, false, 1, false, false, false>(width, height, rptr, wptr); + break; + case FORMAT_RG8 | (FORMAT_RGB8 << 8): + _convert<2, false, 3, false, false, false>(width, height, rptr, wptr); + break; + case FORMAT_RG8 | (FORMAT_RGBA8 << 8): + _convert<2, false, 3, true, false, false>(width, height, rptr, wptr); + break; + case FORMAT_RGB8 | (FORMAT_L8 << 8): + _convert<3, false, 1, false, false, true>(width, height, rptr, wptr); + break; + case FORMAT_RGB8 | (FORMAT_LA8 << 8): + _convert<3, false, 1, true, false, true>(width, height, rptr, wptr); + break; + case FORMAT_RGB8 | (FORMAT_R8 << 8): + _convert<3, false, 1, false, false, false>(width, height, rptr, wptr); + break; + case FORMAT_RGB8 | (FORMAT_RG8 << 8): + _convert<3, false, 2, false, false, false>(width, height, rptr, wptr); + break; + case FORMAT_RGB8 | (FORMAT_RGBA8 << 8): + _convert<3, false, 3, true, false, false>(width, height, rptr, wptr); + break; + case FORMAT_RGBA8 | (FORMAT_L8 << 8): + _convert<3, true, 1, false, false, true>(width, height, rptr, wptr); + break; + case FORMAT_RGBA8 | (FORMAT_LA8 << 8): + _convert<3, true, 1, true, false, true>(width, height, rptr, wptr); + break; + case FORMAT_RGBA8 | (FORMAT_R8 << 8): + _convert<3, true, 1, false, false, false>(width, height, rptr, wptr); + break; + case FORMAT_RGBA8 | (FORMAT_RG8 << 8): + _convert<3, true, 2, false, false, false>(width, height, rptr, wptr); + break; + case FORMAT_RGBA8 | (FORMAT_RGB8 << 8): + _convert<3, true, 3, false, false, false>(width, height, rptr, wptr); + break; } bool gen_mipmaps = mipmaps; @@ -949,25 +1032,49 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) { switch (get_format_pixel_size(format)) { - case 1: _scale_nearest<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 2: _scale_nearest<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 3: _scale_nearest<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 4: _scale_nearest<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 1: + _scale_nearest<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 2: + _scale_nearest<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 3: + _scale_nearest<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 4: + _scale_nearest<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; } } else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) { switch (get_format_pixel_size(format)) { - case 4: _scale_nearest<1, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 8: _scale_nearest<2, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 12: _scale_nearest<3, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 16: _scale_nearest<4, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 4: + _scale_nearest<1, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 8: + _scale_nearest<2, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 12: + _scale_nearest<3, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 16: + _scale_nearest<4, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; } } else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) { switch (get_format_pixel_size(format)) { - case 2: _scale_nearest<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 4: _scale_nearest<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 6: _scale_nearest<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 8: _scale_nearest<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 2: + _scale_nearest<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 4: + _scale_nearest<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 6: + _scale_nearest<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 8: + _scale_nearest<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; } } @@ -1013,24 +1120,48 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) { switch (get_format_pixel_size(format)) { - case 1: _scale_bilinear<1, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; - case 2: _scale_bilinear<2, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; - case 3: _scale_bilinear<3, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; - case 4: _scale_bilinear<4, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; + case 1: + _scale_bilinear<1, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; + case 2: + _scale_bilinear<2, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; + case 3: + _scale_bilinear<3, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; + case 4: + _scale_bilinear<4, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; } } else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) { switch (get_format_pixel_size(format)) { - case 4: _scale_bilinear<1, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; - case 8: _scale_bilinear<2, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; - case 12: _scale_bilinear<3, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; - case 16: _scale_bilinear<4, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; + case 4: + _scale_bilinear<1, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; + case 8: + _scale_bilinear<2, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; + case 12: + _scale_bilinear<3, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; + case 16: + _scale_bilinear<4, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; } } else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) { switch (get_format_pixel_size(format)) { - case 2: _scale_bilinear<1, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; - case 4: _scale_bilinear<2, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; - case 6: _scale_bilinear<3, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; - case 8: _scale_bilinear<4, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; + case 2: + _scale_bilinear<1, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; + case 4: + _scale_bilinear<2, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; + case 6: + _scale_bilinear<3, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; + case 8: + _scale_bilinear<4, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; } } } @@ -1046,24 +1177,48 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) { switch (get_format_pixel_size(format)) { - case 1: _scale_cubic<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 2: _scale_cubic<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 3: _scale_cubic<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 4: _scale_cubic<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 1: + _scale_cubic<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 2: + _scale_cubic<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 3: + _scale_cubic<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 4: + _scale_cubic<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; } } else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) { switch (get_format_pixel_size(format)) { - case 4: _scale_cubic<1, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 8: _scale_cubic<2, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 12: _scale_cubic<3, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 16: _scale_cubic<4, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 4: + _scale_cubic<1, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 8: + _scale_cubic<2, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 12: + _scale_cubic<3, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 16: + _scale_cubic<4, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; } } else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) { switch (get_format_pixel_size(format)) { - case 2: _scale_cubic<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 4: _scale_cubic<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 6: _scale_cubic<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 8: _scale_cubic<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 2: + _scale_cubic<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 4: + _scale_cubic<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 6: + _scale_cubic<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 8: + _scale_cubic<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; } } } break; @@ -1071,24 +1226,48 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) { switch (get_format_pixel_size(format)) { - case 1: _scale_lanczos<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 2: _scale_lanczos<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 3: _scale_lanczos<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 4: _scale_lanczos<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 1: + _scale_lanczos<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 2: + _scale_lanczos<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 3: + _scale_lanczos<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 4: + _scale_lanczos<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; } } else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) { switch (get_format_pixel_size(format)) { - case 4: _scale_lanczos<1, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 8: _scale_lanczos<2, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 12: _scale_lanczos<3, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 16: _scale_lanczos<4, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 4: + _scale_lanczos<1, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 8: + _scale_lanczos<2, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 12: + _scale_lanczos<3, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 16: + _scale_lanczos<4, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; } } else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) { switch (get_format_pixel_size(format)) { - case 2: _scale_lanczos<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 4: _scale_lanczos<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 6: _scale_lanczos<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 8: _scale_lanczos<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 2: + _scale_lanczos<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 4: + _scale_lanczos<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 6: + _scale_lanczos<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 8: + _scale_lanczos<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; } } } break; @@ -1403,23 +1582,51 @@ void Image::shrink_x2() { switch (format) { case FORMAT_L8: - case FORMAT_R8: _generate_po2_mipmap<uint8_t, 1, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); break; - case FORMAT_LA8: _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); break; - case FORMAT_RG8: _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); break; - case FORMAT_RGB8: _generate_po2_mipmap<uint8_t, 3, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); break; - case FORMAT_RGBA8: _generate_po2_mipmap<uint8_t, 4, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); break; - - case FORMAT_RF: _generate_po2_mipmap<float, 1, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); break; - case FORMAT_RGF: _generate_po2_mipmap<float, 2, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); break; - case FORMAT_RGBF: _generate_po2_mipmap<float, 3, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); break; - case FORMAT_RGBAF: _generate_po2_mipmap<float, 4, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); break; - - case FORMAT_RH: _generate_po2_mipmap<uint16_t, 1, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); break; - case FORMAT_RGH: _generate_po2_mipmap<uint16_t, 2, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); break; - case FORMAT_RGBH: _generate_po2_mipmap<uint16_t, 3, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); break; - case FORMAT_RGBAH: _generate_po2_mipmap<uint16_t, 4, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); break; - - case FORMAT_RGBE9995: _generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(reinterpret_cast<const uint32_t *>(r), reinterpret_cast<uint32_t *>(w), width, height); break; + case FORMAT_R8: + _generate_po2_mipmap<uint8_t, 1, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); + break; + case FORMAT_LA8: + _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); + break; + case FORMAT_RG8: + _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); + break; + case FORMAT_RGB8: + _generate_po2_mipmap<uint8_t, 3, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); + break; + case FORMAT_RGBA8: + _generate_po2_mipmap<uint8_t, 4, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); + break; + + case FORMAT_RF: + _generate_po2_mipmap<float, 1, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); + break; + case FORMAT_RGF: + _generate_po2_mipmap<float, 2, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); + break; + case FORMAT_RGBF: + _generate_po2_mipmap<float, 3, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); + break; + case FORMAT_RGBAF: + _generate_po2_mipmap<float, 4, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); + break; + + case FORMAT_RH: + _generate_po2_mipmap<uint16_t, 1, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); + break; + case FORMAT_RGH: + _generate_po2_mipmap<uint16_t, 2, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); + break; + case FORMAT_RGBH: + _generate_po2_mipmap<uint16_t, 3, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); + break; + case FORMAT_RGBAH: + _generate_po2_mipmap<uint16_t, 4, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); + break; + + case FORMAT_RGBE9995: + _generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(reinterpret_cast<const uint32_t *>(r), reinterpret_cast<uint32_t *>(w), width, height); + break; default: { } } @@ -1485,9 +1692,13 @@ Error Image::generate_mipmaps(bool p_renormalize) { switch (format) { case FORMAT_L8: - case FORMAT_R8: _generate_po2_mipmap<uint8_t, 1, false, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break; + case FORMAT_R8: + _generate_po2_mipmap<uint8_t, 1, false, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); + break; case FORMAT_LA8: - case FORMAT_RG8: _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break; + case FORMAT_RG8: + _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); + break; case FORMAT_RGB8: if (p_renormalize) _generate_po2_mipmap<uint8_t, 3, true, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); @@ -1911,12 +2122,24 @@ void Image::create(const char **p_xpm) { break; switch (i) { - case 0: col_r = v << 4; break; - case 1: col_r |= v; break; - case 2: col_g = v << 4; break; - case 3: col_g |= v; break; - case 4: col_b = v << 4; break; - case 5: col_b |= v; break; + case 0: + col_r = v << 4; + break; + case 1: + col_r |= v; + break; + case 2: + col_g = v << 4; + break; + case 3: + col_g |= v; + break; + case 4: + col_b = v << 4; + break; + case 5: + col_b |= v; + break; }; } @@ -2901,12 +3124,24 @@ Image::UsedChannels Image::detect_used_channels(CompressSource p_source) { void Image::optimize_channels() { switch (detect_used_channels()) { - case USED_CHANNELS_L: convert(FORMAT_L8); break; - case USED_CHANNELS_LA: convert(FORMAT_LA8); break; - case USED_CHANNELS_R: convert(FORMAT_R8); break; - case USED_CHANNELS_RG: convert(FORMAT_RG8); break; - case USED_CHANNELS_RGB: convert(FORMAT_RGB8); break; - case USED_CHANNELS_RGBA: convert(FORMAT_RGBA8); break; + case USED_CHANNELS_L: + convert(FORMAT_L8); + break; + case USED_CHANNELS_LA: + convert(FORMAT_LA8); + break; + case USED_CHANNELS_R: + convert(FORMAT_R8); + break; + case USED_CHANNELS_RG: + convert(FORMAT_RG8); + break; + case USED_CHANNELS_RGB: + convert(FORMAT_RGB8); + break; + case USED_CHANNELS_RGBA: + convert(FORMAT_RGBA8); + break; } } @@ -3152,11 +3387,13 @@ void Image::bumpmap_to_normalmap(float bump_scale) { for (int ty = 0; ty < height; ty++) { int py = ty + 1; - if (py >= height) py -= height; + if (py >= height) + py -= height; for (int tx = 0; tx < width; tx++) { int px = tx + 1; - if (px >= width) px -= width; + if (px >= width) + px -= width; float here = read_ptr[ty * width + tx]; float to_right = read_ptr[ty * width + px]; float above = read_ptr[py * width + tx]; @@ -3431,6 +3668,10 @@ Ref<Resource> Image::duplicate(bool p_subresources) const { return copy; } +void Image::set_as_black() { + zeromem(data.ptrw(), data.size()); +} + Image::Image() { width = 0; diff --git a/core/image.h b/core/image.h index 5bd73fa677..07b4f49751 100644 --- a/core/image.h +++ b/core/image.h @@ -376,6 +376,8 @@ public: void set_pixelv(const Point2 &p_dst, const Color &p_color); void set_pixel(int p_x, int p_y, const Color &p_color); + void set_as_black(); + void copy_internals_from(const Ref<Image> &p_image) { ERR_FAIL_COND_MSG(p_image.is_null(), "It's not a reference to a valid Image object."); format = p_image->format; diff --git a/core/input/godotcontrollerdb.txt b/core/input/godotcontrollerdb.txt index adc3649d64..51ddda1e4e 100644 --- a/core/input/godotcontrollerdb.txt +++ b/core/input/godotcontrollerdb.txt @@ -4,6 +4,9 @@ # Windows __XINPUT_DEVICE__,XInput Gamepad,a:b12,b:b13,x:b14,y:b15,start:b4,back:b5,leftstick:b6,rightstick:b7,leftshoulder:b8,rightshoulder:b9,dpup:b0,dpdown:b1,dpleft:b2,dpright:b3,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:Windows, +# Android +Default Android Gamepad,Default Controller,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b8,rightshoulder:b10,rightx:a2,start:b6,righty:a3,dpleft:h0.8,lefttrigger:a4,x:b2,dpup:h0.1,back:b4,leftstick:b7,leftshoulder:b9,y:b3,a:b0,dpright:h0.2,righttrigger:a5,b:b1,platform:Android, + # Javascript Default HTML5 Gamepad, Default Mapping,leftx:a0,lefty:a1,dpdown:b13,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a3,dpleft:b14,lefttrigger:a6,x:b2,dpup:b12,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b0,dpright:b15,righttrigger:a7,b:b1,platform:Javascript, c2a94d6963726f736f66742058626f78,Wireless X360 Controller,leftx:a0,lefty:a1,dpdown:b14,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:b11,lefttrigger:a2,x:b2,dpup:b13,back:b6,leftstick:b9,leftshoulder:b4,y:b3,a:b0,dpright:b12,righttrigger:a5,b:b1,platform:Javascript, diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index 0a7dee9444..fd9b83eaf9 100644 --- a/core/io/file_access_pack.cpp +++ b/core/io/file_access_pack.cpp @@ -414,7 +414,8 @@ Error DirAccessPack::change_dir(String p_dir) { nd = nd.simplify_path(); - if (nd == "") nd = "."; + if (nd == "") + nd = "."; if (nd.begins_with("/")) { nd = nd.replace_first("/", ""); diff --git a/core/io/ip_address.h b/core/io/ip_address.h index 89cf37ff8f..a59178063d 100644 --- a/core/io/ip_address.h +++ b/core/io/ip_address.h @@ -52,16 +52,20 @@ protected: public: //operator Variant() const; bool operator==(const IP_Address &p_ip) const { - if (p_ip.valid != valid) return false; - if (!valid) return false; + if (p_ip.valid != valid) + return false; + if (!valid) + return false; for (int i = 0; i < 4; i++) if (field32[i] != p_ip.field32[i]) return false; return true; } bool operator!=(const IP_Address &p_ip) const { - if (p_ip.valid != valid) return true; - if (!valid) return true; + if (p_ip.valid != valid) + return true; + if (!valid) + return true; for (int i = 0; i < 4; i++) if (field32[i] != p_ip.field32[i]) return true; diff --git a/core/io/json.cpp b/core/io/json.cpp index 3a0edceb81..0186547dd2 100644 --- a/core/io/json.cpp +++ b/core/io/json.cpp @@ -67,10 +67,14 @@ String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_ switch (p_var.get_type()) { - case Variant::NIL: return "null"; - case Variant::BOOL: return p_var.operator bool() ? "true" : "false"; - case Variant::INT: return itos(p_var); - case Variant::FLOAT: return rtos(p_var); + case Variant::NIL: + return "null"; + case Variant::BOOL: + return p_var.operator bool() ? "true" : "false"; + case Variant::INT: + return itos(p_var); + case Variant::FLOAT: + return rtos(p_var); case Variant::PACKED_INT32_ARRAY: case Variant::PACKED_INT64_ARRAY: case Variant::PACKED_FLOAT32_ARRAY: @@ -116,7 +120,8 @@ String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_ s += end_statement + _make_indent(p_indent, p_cur_indent) + "}"; return s; }; - default: return "\"" + String(p_var).json_escape() + "\""; + default: + return "\"" + String(p_var).json_escape() + "\""; } } @@ -199,11 +204,21 @@ Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_to switch (next) { - case 'b': res = 8; break; - case 't': res = 9; break; - case 'n': res = 10; break; - case 'f': res = 12; break; - case 'r': res = 13; break; + case 'b': + res = 8; + break; + case 't': + res = 9; + break; + case 'n': + res = 10; + break; + case 'f': + res = 12; + break; + case 'r': + res = 13; + break; case 'u': { // hex number for (int j = 0; j < 4; j++) { diff --git a/core/io/logger.cpp b/core/io/logger.cpp index ad0cc81023..02cc78538e 100644 --- a/core/io/logger.cpp +++ b/core/io/logger.cpp @@ -49,11 +49,21 @@ void Logger::log_error(const char *p_function, const char *p_file, int p_line, c const char *err_type = "ERROR"; switch (p_type) { - case ERR_ERROR: err_type = "ERROR"; break; - case ERR_WARNING: err_type = "WARNING"; break; - case ERR_SCRIPT: err_type = "SCRIPT ERROR"; break; - case ERR_SHADER: err_type = "SHADER ERROR"; break; - default: ERR_PRINT("Unknown error type"); break; + case ERR_ERROR: + err_type = "ERROR"; + break; + case ERR_WARNING: + err_type = "WARNING"; + break; + case ERR_SCRIPT: + err_type = "SCRIPT ERROR"; + break; + case ERR_SHADER: + err_type = "SHADER ERROR"; + break; + default: + ERR_PRINT("Unknown error type"); + break; } const char *err_details; diff --git a/core/io/marshalls.h b/core/io/marshalls.h index d029ed238c..650c95364a 100644 --- a/core/io/marshalls.h +++ b/core/io/marshalls.h @@ -121,7 +121,8 @@ static inline int encode_cstring(const char *p_string, uint8_t *p_data) { len++; }; - if (p_data) *p_data = 0; + if (p_data) + *p_data = 0; return len + 1; } diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp index 3bec52416e..94e2fdb72c 100644 --- a/core/io/multiplayer_api.cpp +++ b/core/io/multiplayer_api.cpp @@ -144,7 +144,8 @@ void MultiplayerAPI::set_root_node(Node *p_node) { void MultiplayerAPI::set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_peer) { - if (p_peer == network_peer) return; // Nothing to do + if (p_peer == network_peer) + return; // Nothing to do ERR_FAIL_COND_MSG(p_peer.is_valid() && p_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED, "Supplied NetworkedMultiplayerPeer must be connecting or connected."); @@ -787,8 +788,9 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p int ofs = 0; -#define MAKE_ROOM(m_amount) \ - if (packet_cache.size() < m_amount) packet_cache.resize(m_amount); +#define MAKE_ROOM(m_amount) \ + if (packet_cache.size() < m_amount) \ + packet_cache.resize(m_amount); // Encode meta. // The meta is composed by a single byte that contains (starting from the least segnificant bit): diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index 8c7559479b..e0fea143bb 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -337,10 +337,14 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { } break; case OBJECT_INTERNAL_RESOURCE: { uint32_t index = f->get_32(); + String path = res_path + "::" + itos(index); + if (use_nocache) { - r_v = internal_resources[index].cache; + if (!internal_index_cache.has(path)) { + WARN_PRINT(String("Couldn't load resource (no cache): " + path).utf8().get_data()); + } + r_v = internal_index_cache[path]; } else { - String path = res_path + "::" + itos(index); RES res = ResourceLoader::load(path); if (res.is_null()) { WARN_PRINT(String("Couldn't load resource: " + path).utf8().get_data()); @@ -720,13 +724,15 @@ Error ResourceLoaderBinary::load() { if (!main) { + path = internal_resources[i].path; + + if (path.begins_with("local://")) { + path = path.replace_first("local://", ""); + subindex = path.to_int(); + path = res_path + "::" + path; + } + if (!use_nocache) { - path = internal_resources[i].path; - if (path.begins_with("local://")) { - path = path.replace_first("local://", ""); - subindex = path.to_int(); - path = res_path + "::" + path; - } if (ResourceCache::has(path)) { //already loaded, don't do anything @@ -769,7 +775,7 @@ Error ResourceLoaderBinary::load() { r->set_subindex(subindex); if (!main) { - internal_resources.write[i].cache = res; + internal_index_cache[path] = res; } int pc = f->get_32(); diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h index 0f8fc9445b..3c8d916c0a 100644 --- a/core/io/resource_format_binary.h +++ b/core/io/resource_format_binary.h @@ -68,10 +68,10 @@ class ResourceLoaderBinary { struct IntResource { String path; uint64_t offset; - RES cache; }; Vector<IntResource> internal_resources; + Map<String, RES> internal_index_cache; String get_unicode_string(); void _advance_padding(uint32_t p_len); diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp index 643df53f8c..9e22bdced7 100644 --- a/core/io/resource_importer.cpp +++ b/core/io/resource_importer.cpp @@ -91,7 +91,7 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy r_path_and_type.path = value; path_found = true; //first match must have priority } else if (assign == "type") { - r_path_and_type.type = value; + r_path_and_type.type = ClassDB::get_compatibility_remapped_class(value); } else if (assign == "importer") { r_path_and_type.importer = value; } else if (assign == "group_file") { diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index 2d95d5545f..b10c08d693 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -160,7 +160,8 @@ public: static bool get_timestamp_on_load() { return timestamp_on_load; } static void notify_load_error(const String &p_err) { - if (err_notify) err_notify(err_notify_ud, p_err); + if (err_notify) + err_notify(err_notify_ud, p_err); } static void set_error_notify_func(void *p_ud, ResourceLoadErrorNotify p_err_notify) { err_notify = p_err_notify; @@ -168,7 +169,8 @@ public: } static void notify_dependency_error(const String &p_path, const String &p_dependency, const String &p_type) { - if (dep_err_notify) dep_err_notify(dep_err_notify_ud, p_path, p_dependency, p_type); + if (dep_err_notify) + dep_err_notify(dep_err_notify_ud, p_path, p_dependency, p_type); } static void set_dependency_error_notify_func(void *p_ud, DependencyErrorNotify p_err_notify) { dep_err_notify = p_err_notify; diff --git a/core/list.h b/core/list.h index be2dccd876..65d45ffdfc 100644 --- a/core/list.h +++ b/core/list.h @@ -353,7 +353,8 @@ public: Element *it = front(); while (it) { - if (it->value == p_val) return it; + if (it->value == p_val) + return it; it = it->next(); }; diff --git a/core/local_vector.h b/core/local_vector.h new file mode 100644 index 0000000000..0b0ef6dfdc --- /dev/null +++ b/core/local_vector.h @@ -0,0 +1,246 @@ +/*************************************************************************/ +/* local_vector.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef LOCAL_VECTOR_H +#define LOCAL_VECTOR_H + +#include "core/error_macros.h" +#include "core/os/copymem.h" +#include "core/os/memory.h" +#include "core/sort_array.h" +#include "core/vector.h" + +template <class T, class U = uint32_t, bool force_trivial = false> +class LocalVector { +private: + U count = 0; + U capacity = 0; + T *data = nullptr; + +public: + _FORCE_INLINE_ void push_back(T p_elem) { + if (unlikely(count == capacity)) { + if (capacity == 0) { + capacity = 1; + } else { + capacity <<= 1; + } + data = (T *)memrealloc(data, capacity * sizeof(T)); + CRASH_COND_MSG(!data, "Out of memory"); + } + + if (!__has_trivial_constructor(T) && !force_trivial) { + memnew_placement(&data[count++], T(p_elem)); + } else { + data[count++] = p_elem; + } + } + + void remove(U p_index) { + ERR_FAIL_UNSIGNED_INDEX(p_index, count); + for (U i = p_index; i < count; i++) { + data[i] = data[i + 1]; + } + count--; + if (!__has_trivial_destructor(T) && !force_trivial) { + data[count].~T(); + } + } + + void erase(const T &p_val) { + U idx = find(p_val); + if (idx >= 0) + remove(idx); + } + + void invert() { + + for (U i = 0; i < count / 2; i++) { + SWAP(data[i], data[count - i - 1]); + } + } + + _FORCE_INLINE_ void clear() { resize(0); } + _FORCE_INLINE_ void reset() { + clear(); + if (data) { + memfree(data); + data = nullptr; + capacity = 0; + } + } + _FORCE_INLINE_ bool empty() const { return count == 0; } + _FORCE_INLINE_ void reserve(U p_size) { + p_size = nearest_power_of_2_templated(p_size); + if (p_size > capacity) { + capacity = p_size; + data = (T *)memrealloc(data, capacity * sizeof(T)); + CRASH_COND_MSG(!data, "Out of memory"); + } + } + + _FORCE_INLINE_ U size() const { return count; } + void resize(U p_size) { + + if (p_size < count) { + + if (!__has_trivial_destructor(T) && !force_trivial) { + for (U i = p_size; i < count; i++) { + data[i].~T(); + } + } + count = p_size; + } else if (p_size > count) { + + if (unlikely(p_size > capacity)) { + if (capacity == 0) { + capacity = 1; + } + while (capacity < p_size) { + capacity <<= 1; + } + data = (T *)memrealloc(data, capacity * sizeof(T)); + CRASH_COND_MSG(!data, "Out of memory"); + } + if (!__has_trivial_constructor(T) && !force_trivial) { + for (U i = count; i < p_size; i++) { + memnew_placement(&data[i], T); + } + } + count = p_size; + } + } + _FORCE_INLINE_ const T &operator[](U p_index) const { + CRASH_BAD_UNSIGNED_INDEX(p_index, count); + return data[p_index]; + } + _FORCE_INLINE_ T &operator[](U p_index) { + CRASH_BAD_UNSIGNED_INDEX(p_index, count); + return data[p_index]; + } + + void insert(U p_pos, T p_val) { + ERR_FAIL_UNSIGNED_INDEX(p_pos, count + 1); + if (p_pos == count) { + push_back(p_val); + } else { + resize(count + 1); + for (U i = count; i > p_pos; i--) { + data[i] = data[i - 1]; + } + data[p_pos] = p_val; + } + } + + int64_t find(const T &p_val, U p_from = 0) const { + + for (U i = 0; i < count; i++) { + if (data[i] == p_val) { + return int64_t(i); + } + } + return -1; + } + + template <class C> + void sort_custom() { + + U len = count; + if (len == 0) + return; + + SortArray<T, C> sorter; + sorter.sort(data, len); + } + + void sort() { + + sort_custom<_DefaultComparator<T>>(); + } + + void ordered_insert(T p_val) { + + U i; + for (i = 0; i < count; i++) { + + if (p_val < data[i]) { + break; + }; + }; + insert(i, p_val); + } + + operator Vector<T>() const { + Vector<T> ret; + ret.resize(size()); + T *w = ret.ptrw(); + copymem(w, data, sizeof(T) * count); + return ret; + } + + Vector<uint8_t> to_byte_array() const { //useful to pass stuff to gpu or variant + Vector<uint8_t> ret; + ret.resize(count * sizeof(T)); + uint8_t *w = ret.ptrw(); + copymem(w, data, sizeof(T) * count); + return ret; + } + + _FORCE_INLINE_ LocalVector() {} + _FORCE_INLINE_ LocalVector(const LocalVector &p_from) { + resize(p_from.size()); + for (U i = 0; i < p_from.count; i++) { + data[i] = p_from.data[i]; + } + } + inline LocalVector &operator=(const LocalVector &p_from) { + resize(p_from.size()); + for (U i = 0; i < p_from.count; i++) { + data[i] = p_from.data[i]; + } + return *this; + } + inline LocalVector &operator=(const Vector<T> &p_from) { + resize(p_from.size()); + for (U i = 0; i < count; i++) { + data[i] = p_from[i]; + } + return *this; + } + + _FORCE_INLINE_ ~LocalVector() { + + if (data) { + reset(); + } + } +}; + +#endif // LOCAL_VECTOR_H diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp index 3e3e6c50a7..3aba753f51 100644 --- a/core/math/a_star.cpp +++ b/core/math/a_star.cpp @@ -164,7 +164,8 @@ void AStar::connect_points(int p_id, int p_with_id, bool bidirectional) { } Segment s(p_id, p_with_id); - if (bidirectional) s.direction = Segment::BIDIRECTIONAL; + if (bidirectional) + s.direction = Segment::BIDIRECTIONAL; Set<Segment>::Element *element = segments.find(s); if (element != nullptr) { @@ -290,7 +291,8 @@ int AStar::get_closest_point(const Vector3 &p_point, bool p_include_disabled) co for (OAHashMap<int, Point *>::Iterator it = points.iter(); it.valid; it = points.next_iter(it)) { - if (!p_include_disabled && !(*it.value)->enabled) continue; // Disabled points should not be considered. + if (!p_include_disabled && !(*it.value)->enabled) + continue; // Disabled points should not be considered. real_t d = p_point.distance_squared_to((*it.value)->pos); if (closest_id < 0 || d < closest_dist) { @@ -340,7 +342,8 @@ bool AStar::_solve(Point *begin_point, Point *end_point) { pass++; - if (!end_point->enabled) return false; + if (!end_point->enabled) + return false; bool found_route = false; @@ -451,7 +454,8 @@ Vector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) { Point *end_point = b; bool found_route = _solve(begin_point, end_point); - if (!found_route) return Vector<Vector3>(); + if (!found_route) + return Vector<Vector3>(); Point *p = end_point; int pc = 1; // Begin point @@ -499,7 +503,8 @@ Vector<int> AStar::get_id_path(int p_from_id, int p_to_id) { Point *end_point = b; bool found_route = _solve(begin_point, end_point); - if (!found_route) return Vector<int>(); + if (!found_route) + return Vector<int>(); Point *p = end_point; int pc = 1; // Begin point @@ -729,7 +734,8 @@ Vector<Vector2> AStar2D::get_point_path(int p_from_id, int p_to_id) { AStar::Point *end_point = b; bool found_route = _solve(begin_point, end_point); - if (!found_route) return Vector<Vector2>(); + if (!found_route) + return Vector<Vector2>(); AStar::Point *p = end_point; int pc = 1; // Begin point @@ -777,7 +783,8 @@ Vector<int> AStar2D::get_id_path(int p_from_id, int p_to_id) { AStar::Point *end_point = b; bool found_route = _solve(begin_point, end_point); - if (!found_route) return Vector<int>(); + if (!found_route) + return Vector<int>(); AStar::Point *p = end_point; int pc = 1; // Begin point @@ -809,7 +816,8 @@ bool AStar2D::_solve(AStar::Point *begin_point, AStar::Point *end_point) { astar.pass++; - if (!end_point->enabled) return false; + if (!end_point->enabled) + return false; bool found_route = false; diff --git a/core/math/aabb.h b/core/math/aabb.h index 7fdad07c89..f87fced12d 100644 --- a/core/math/aabb.h +++ b/core/math/aabb.h @@ -177,14 +177,22 @@ Vector3 AABB::get_support(const Vector3 &p_normal) const { Vector3 AABB::get_endpoint(int p_point) const { switch (p_point) { - case 0: return Vector3(position.x, position.y, position.z); - case 1: return Vector3(position.x, position.y, position.z + size.z); - case 2: return Vector3(position.x, position.y + size.y, position.z); - case 3: return Vector3(position.x, position.y + size.y, position.z + size.z); - case 4: return Vector3(position.x + size.x, position.y, position.z); - case 5: return Vector3(position.x + size.x, position.y, position.z + size.z); - case 6: return Vector3(position.x + size.x, position.y + size.y, position.z); - case 7: return Vector3(position.x + size.x, position.y + size.y, position.z + size.z); + case 0: + return Vector3(position.x, position.y, position.z); + case 1: + return Vector3(position.x, position.y, position.z + size.z); + case 2: + return Vector3(position.x, position.y + size.y, position.z); + case 3: + return Vector3(position.x, position.y + size.y, position.z + size.z); + case 4: + return Vector3(position.x + size.x, position.y, position.z); + case 5: + return Vector3(position.x + size.x, position.y, position.z + size.z); + case 6: + return Vector3(position.x + size.x, position.y + size.y, position.z); + case 7: + return Vector3(position.x + size.x, position.y + size.y, position.z + size.z); }; ERR_FAIL_V(Vector3()); diff --git a/core/math/basis.cpp b/core/math/basis.cpp index 0f519a20d8..6218b7e248 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -783,7 +783,8 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const { real_t s = Math::sqrt((elements[1][2] - elements[2][1]) * (elements[1][2] - elements[2][1]) + (elements[2][0] - elements[0][2]) * (elements[2][0] - elements[0][2]) + (elements[0][1] - elements[1][0]) * (elements[0][1] - elements[1][0])); // s=|axis||sin(angle)|, used to normalise angle = Math::acos((elements[0][0] + elements[1][1] + elements[2][2] - 1) / 2); - if (angle < 0) s = -s; + if (angle < 0) + s = -s; x = (elements[2][1] - elements[1][2]) / s; y = (elements[0][2] - elements[2][0]) / s; z = (elements[1][0] - elements[0][1]) / s; @@ -877,3 +878,114 @@ Basis Basis::slerp(const Basis &target, const real_t &t) const { return b; } + +void Basis::rotate_sh(real_t *p_values) { + + // code by John Hable + // http://filmicworlds.com/blog/simple-and-fast-spherical-harmonic-rotation/ + // this code is Public Domain + + const static real_t s_c3 = 0.94617469575; // (3*sqrt(5))/(4*sqrt(pi)) + const static real_t s_c4 = -0.31539156525; // (-sqrt(5))/(4*sqrt(pi)) + const static real_t s_c5 = 0.54627421529; // (sqrt(15))/(4*sqrt(pi)) + + const static real_t s_c_scale = 1.0 / 0.91529123286551084; + const static real_t s_c_scale_inv = 0.91529123286551084; + + const static real_t s_rc2 = 1.5853309190550713 * s_c_scale; + const static real_t s_c4_div_c3 = s_c4 / s_c3; + const static real_t s_c4_div_c3_x2 = (s_c4 / s_c3) * 2.0; + + const static real_t s_scale_dst2 = s_c3 * s_c_scale_inv; + const static real_t s_scale_dst4 = s_c5 * s_c_scale_inv; + + real_t src[9] = { p_values[0], p_values[1], p_values[2], p_values[3], p_values[4], p_values[5], p_values[6], p_values[7], p_values[8] }; + + real_t m00 = elements[0][0]; + real_t m01 = elements[0][1]; + real_t m02 = elements[0][2]; + real_t m10 = elements[1][0]; + real_t m11 = elements[1][1]; + real_t m12 = elements[1][2]; + real_t m20 = elements[2][0]; + real_t m21 = elements[2][1]; + real_t m22 = elements[2][2]; + + p_values[0] = src[0]; + p_values[1] = m11 * src[1] - m12 * src[2] + m10 * src[3]; + p_values[2] = -m21 * src[1] + m22 * src[2] - m20 * src[3]; + p_values[3] = m01 * src[1] - m02 * src[2] + m00 * src[3]; + + real_t sh0 = src[7] + src[8] + src[8] - src[5]; + real_t sh1 = src[4] + s_rc2 * src[6] + src[7] + src[8]; + real_t sh2 = src[4]; + real_t sh3 = -src[7]; + real_t sh4 = -src[5]; + + // Rotations. R0 and R1 just use the raw matrix columns + real_t r2x = m00 + m01; + real_t r2y = m10 + m11; + real_t r2z = m20 + m21; + + real_t r3x = m00 + m02; + real_t r3y = m10 + m12; + real_t r3z = m20 + m22; + + real_t r4x = m01 + m02; + real_t r4y = m11 + m12; + real_t r4z = m21 + m22; + + // dense matrix multiplication one column at a time + + // column 0 + real_t sh0_x = sh0 * m00; + real_t sh0_y = sh0 * m10; + real_t d0 = sh0_x * m10; + real_t d1 = sh0_y * m20; + real_t d2 = sh0 * (m20 * m20 + s_c4_div_c3); + real_t d3 = sh0_x * m20; + real_t d4 = sh0_x * m00 - sh0_y * m10; + + // column 1 + real_t sh1_x = sh1 * m02; + real_t sh1_y = sh1 * m12; + d0 += sh1_x * m12; + d1 += sh1_y * m22; + d2 += sh1 * (m22 * m22 + s_c4_div_c3); + d3 += sh1_x * m22; + d4 += sh1_x * m02 - sh1_y * m12; + + // column 2 + real_t sh2_x = sh2 * r2x; + real_t sh2_y = sh2 * r2y; + d0 += sh2_x * r2y; + d1 += sh2_y * r2z; + d2 += sh2 * (r2z * r2z + s_c4_div_c3_x2); + d3 += sh2_x * r2z; + d4 += sh2_x * r2x - sh2_y * r2y; + + // column 3 + real_t sh3_x = sh3 * r3x; + real_t sh3_y = sh3 * r3y; + d0 += sh3_x * r3y; + d1 += sh3_y * r3z; + d2 += sh3 * (r3z * r3z + s_c4_div_c3_x2); + d3 += sh3_x * r3z; + d4 += sh3_x * r3x - sh3_y * r3y; + + // column 4 + real_t sh4_x = sh4 * r4x; + real_t sh4_y = sh4 * r4y; + d0 += sh4_x * r4y; + d1 += sh4_y * r4z; + d2 += sh4 * (r4z * r4z + s_c4_div_c3_x2); + d3 += sh4_x * r4z; + d4 += sh4_x * r4x - sh4_y * r4y; + + // extra multipliers + p_values[4] = d0; + p_values[5] = -d1; + p_values[6] = d2 * s_scale_dst2; + p_values[7] = -d3; + p_values[8] = d4 * s_scale_dst4; +} diff --git a/core/math/basis.h b/core/math/basis.h index 0261cf67c6..2924a0ddbd 100644 --- a/core/math/basis.h +++ b/core/math/basis.h @@ -159,6 +159,7 @@ public: bool is_rotation() const; Basis slerp(const Basis &target, const real_t &t) const; + void rotate_sh(real_t *p_values); operator String() const; diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp index c36070e47f..5d3ebc9f6d 100644 --- a/core/math/camera_matrix.cpp +++ b/core/math/camera_matrix.cpp @@ -33,6 +33,22 @@ #include "core/math/math_funcs.h" #include "core/print_string.h" +float CameraMatrix::determinant() const { + + return matrix[0][3] * matrix[1][2] * matrix[2][1] * matrix[3][0] - matrix[0][2] * matrix[1][3] * matrix[2][1] * matrix[3][0] - + matrix[0][3] * matrix[1][1] * matrix[2][2] * matrix[3][0] + matrix[0][1] * matrix[1][3] * matrix[2][2] * matrix[3][0] + + matrix[0][2] * matrix[1][1] * matrix[2][3] * matrix[3][0] - matrix[0][1] * matrix[1][2] * matrix[2][3] * matrix[3][0] - + matrix[0][3] * matrix[1][2] * matrix[2][0] * matrix[3][1] + matrix[0][2] * matrix[1][3] * matrix[2][0] * matrix[3][1] + + matrix[0][3] * matrix[1][0] * matrix[2][2] * matrix[3][1] - matrix[0][0] * matrix[1][3] * matrix[2][2] * matrix[3][1] - + matrix[0][2] * matrix[1][0] * matrix[2][3] * matrix[3][1] + matrix[0][0] * matrix[1][2] * matrix[2][3] * matrix[3][1] + + matrix[0][3] * matrix[1][1] * matrix[2][0] * matrix[3][2] - matrix[0][1] * matrix[1][3] * matrix[2][0] * matrix[3][2] - + matrix[0][3] * matrix[1][0] * matrix[2][1] * matrix[3][2] + matrix[0][0] * matrix[1][3] * matrix[2][1] * matrix[3][2] + + matrix[0][1] * matrix[1][0] * matrix[2][3] * matrix[3][2] - matrix[0][0] * matrix[1][1] * matrix[2][3] * matrix[3][2] - + matrix[0][2] * matrix[1][1] * matrix[2][0] * matrix[3][3] + matrix[0][1] * matrix[1][2] * matrix[2][0] * matrix[3][3] + + matrix[0][2] * matrix[1][0] * matrix[2][1] * matrix[3][3] - matrix[0][0] * matrix[1][2] * matrix[2][1] * matrix[3][3] - + matrix[0][1] * matrix[1][0] * matrix[2][2] * matrix[3][3] + matrix[0][0] * matrix[1][1] * matrix[2][2] * matrix[3][3]; +} + void CameraMatrix::set_identity() { for (int i = 0; i < 4; i++) { @@ -473,20 +489,23 @@ void CameraMatrix::invert() { /** Divide column by minus pivot value **/ for (i = 0; i < 4; i++) { - if (i != k) matrix[i][k] /= (-pvt_val); + if (i != k) + matrix[i][k] /= (-pvt_val); } /** Reduce the matrix **/ for (i = 0; i < 4; i++) { hold = matrix[i][k]; for (j = 0; j < 4; j++) { - if (i != k && j != k) matrix[i][j] += hold * matrix[k][j]; + if (i != k && j != k) + matrix[i][j] += hold * matrix[k][j]; } } /** Divide row by pivot **/ for (j = 0; j < 4; j++) { - if (j != k) matrix[k][j] /= pvt_val; + if (j != k) + matrix[k][j] /= pvt_val; } /** Replace pivot by reciprocal (at last we can touch it). **/ diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h index c10193bc84..5420fa2984 100644 --- a/core/math/camera_matrix.h +++ b/core/math/camera_matrix.h @@ -47,6 +47,7 @@ struct CameraMatrix { real_t matrix[4][4]; + float determinant() const; void set_identity(); void set_zero(); void set_light_bias(); diff --git a/core/math/delaunay.h b/core/math/delaunay_2d.h index 29f84210d2..b8252e9d16 100644 --- a/core/math/delaunay.h +++ b/core/math/delaunay_2d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* delaunay.h */ +/* delaunay_2d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef DELAUNAY_H -#define DELAUNAY_H +#ifndef DELAUNAY_2D_H +#define DELAUNAY_2D_H #include "core/math/rect2.h" @@ -115,8 +115,6 @@ public: triangles.push_back(Triangle(p_points.size() + 0, p_points.size() + 1, p_points.size() + 2)); for (int i = 0; i < p_points.size(); i++) { - //std::cout << "Traitement du point " << *p << std::endl; - //std::cout << "_triangles contains " << _triangles.size() << " elements" << std::endl; Vector<Edge> polygon; @@ -172,4 +170,4 @@ public: } }; -#endif // DELAUNAY_H +#endif // DELAUNAY_2D_H diff --git a/core/math/delaunay_3d.h b/core/math/delaunay_3d.h new file mode 100644 index 0000000000..57f3a78d35 --- /dev/null +++ b/core/math/delaunay_3d.h @@ -0,0 +1,387 @@ +#ifndef DELAUNAY_3D_H +#define DELAUNAY_3D_H + +#include "core/local_vector.h" +#include "core/math/aabb.h" +#include "core/math/camera_matrix.h" +#include "core/math/vector3.h" +#include "core/oa_hash_map.h" +#include "core/os/file_access.h" +#include "core/print_string.h" +#include "core/variant.h" +#include "core/vector.h" + +#include "thirdparty/misc/r128.h" + +class Delaunay3D { + struct Simplex; + + enum { + ACCEL_GRID_SIZE = 16 + }; + struct GridPos { + Vector3i pos; + List<Simplex *>::Element *E = nullptr; + }; + + struct Simplex { + + uint32_t points[4]; + R128 circum_center_x; + R128 circum_center_y; + R128 circum_center_z; + R128 circum_r2; + LocalVector<GridPos> grid_positions; + List<Simplex *>::Element *SE = nullptr; + + _FORCE_INLINE_ Simplex() {} + _FORCE_INLINE_ Simplex(uint32_t p_a, uint32_t p_b, uint32_t p_c, uint32_t p_d) { + points[0] = p_a; + points[1] = p_b; + points[2] = p_c; + points[3] = p_d; + } + }; + + struct Triangle { + uint32_t triangle[3]; + bool bad; + _FORCE_INLINE_ bool operator==(const Triangle &p_triangle) const { + return triangle[0] == p_triangle.triangle[0] && triangle[1] == p_triangle.triangle[1] && triangle[2] == p_triangle.triangle[2]; + } + + _FORCE_INLINE_ Triangle() { bad = false; } + _FORCE_INLINE_ Triangle(uint32_t p_a, uint32_t p_b, uint32_t p_c) { + if (p_a > p_b) + SWAP(p_a, p_b); + if (p_b > p_c) + SWAP(p_b, p_c); + if (p_a > p_b) + SWAP(p_a, p_b); + + bad = false; + triangle[0] = p_a; + triangle[1] = p_b; + triangle[2] = p_c; + } + }; + + struct TriangleHasher { + _FORCE_INLINE_ static uint32_t hash(const Triangle &p_triangle) { + uint32_t h = hash_djb2_one_32(p_triangle.triangle[0]); + h = hash_djb2_one_32(p_triangle.triangle[1], h); + return hash_djb2_one_32(p_triangle.triangle[2], h); + } + }; + + struct FPVal { + }; + + _FORCE_INLINE_ static void circum_sphere_compute(const Vector3 *p_points, Simplex *p_simplex) { + + // the only part in the algorithm where there may be precision errors is this one, so ensure that + // we do it as maximum precision as possible + + R128 v0_x = p_points[p_simplex->points[0]].x; + R128 v0_y = p_points[p_simplex->points[0]].y; + R128 v0_z = p_points[p_simplex->points[0]].z; + R128 v1_x = p_points[p_simplex->points[1]].x; + R128 v1_y = p_points[p_simplex->points[1]].y; + R128 v1_z = p_points[p_simplex->points[1]].z; + R128 v2_x = p_points[p_simplex->points[2]].x; + R128 v2_y = p_points[p_simplex->points[2]].y; + R128 v2_z = p_points[p_simplex->points[2]].z; + R128 v3_x = p_points[p_simplex->points[3]].x; + R128 v3_y = p_points[p_simplex->points[3]].y; + R128 v3_z = p_points[p_simplex->points[3]].z; + + //Create the rows of our "unrolled" 3x3 matrix + R128 row1_x = v1_x - v0_x; + R128 row1_y = v1_y - v0_y; + R128 row1_z = v1_z - v0_z; + + R128 row2_x = v2_x - v0_x; + R128 row2_y = v2_y - v0_y; + R128 row2_z = v2_z - v0_z; + + R128 row3_x = v3_x - v0_x; + R128 row3_y = v3_y - v0_y; + R128 row3_z = v3_z - v0_z; + + R128 sq_lenght1 = row1_x * row1_x + row1_y * row1_y + row1_z * row1_z; + R128 sq_lenght2 = row2_x * row2_x + row2_y * row2_y + row2_z * row2_z; + R128 sq_lenght3 = row3_x * row3_x + row3_y * row3_y + row3_z * row3_z; + + //Compute the determinant of said matrix + R128 determinant = row1_x * (row2_y * row3_z - row3_y * row2_z) - row2_x * (row1_y * row3_z - row3_y * row1_z) + row3_x * (row1_y * row2_z - row2_y * row1_z); + + // Compute the volume of the tetrahedron, and precompute a scalar quantity for re-use in the formula + R128 volume = determinant / R128(6.f); + R128 i12volume = R128(1.f) / (volume * R128(12.f)); + + R128 center_x = v0_x + i12volume * ((row2_y * row3_z - row3_y * row2_z) * sq_lenght1 - (row1_y * row3_z - row3_y * row1_z) * sq_lenght2 + (row1_y * row2_z - row2_y * row1_z) * sq_lenght3); + R128 center_y = v0_y + i12volume * (-(row2_x * row3_z - row3_x * row2_z) * sq_lenght1 + (row1_x * row3_z - row3_x * row1_z) * sq_lenght2 - (row1_x * row2_z - row2_x * row1_z) * sq_lenght3); + R128 center_z = v0_z + i12volume * ((row2_x * row3_y - row3_x * row2_y) * sq_lenght1 - (row1_x * row3_y - row3_x * row1_y) * sq_lenght2 + (row1_x * row2_y - row2_x * row1_y) * sq_lenght3); + + //Once we know the center, the radius is clearly the distance to any vertex + + R128 rel1_x = center_x - v0_x; + R128 rel1_y = center_y - v0_y; + R128 rel1_z = center_z - v0_z; + + R128 radius1 = rel1_x * rel1_x + rel1_y * rel1_y + rel1_z * rel1_z; + + p_simplex->circum_center_x = center_x; + p_simplex->circum_center_y = center_y; + p_simplex->circum_center_z = center_z; + p_simplex->circum_r2 = radius1; + } + + _FORCE_INLINE_ static bool simplex_contains(const Vector3 *p_points, const Simplex &p_simplex, uint32_t p_vertex) { + + R128 v_x = p_points[p_vertex].x; + R128 v_y = p_points[p_vertex].y; + R128 v_z = p_points[p_vertex].z; + + R128 rel2_x = p_simplex.circum_center_x - v_x; + R128 rel2_y = p_simplex.circum_center_y - v_y; + R128 rel2_z = p_simplex.circum_center_z - v_z; + + R128 radius2 = rel2_x * rel2_x + rel2_y * rel2_y + rel2_z * rel2_z; + + return radius2 < (p_simplex.circum_r2 - R128(0.00001)); + } + + static bool simplex_is_coplanar(const Vector3 *p_points, const Simplex &p_simplex) { + + Plane p(p_points[p_simplex.points[0]], p_points[p_simplex.points[1]], p_points[p_simplex.points[2]]); + if (ABS(p.distance_to(p_points[p_simplex.points[3]])) < CMP_EPSILON) { + return true; + } + + CameraMatrix cm; + + cm.matrix[0][0] = p_points[p_simplex.points[0]].x; + cm.matrix[0][1] = p_points[p_simplex.points[1]].x; + cm.matrix[0][2] = p_points[p_simplex.points[2]].x; + cm.matrix[0][3] = p_points[p_simplex.points[3]].x; + + cm.matrix[1][0] = p_points[p_simplex.points[0]].y; + cm.matrix[1][1] = p_points[p_simplex.points[1]].y; + cm.matrix[1][2] = p_points[p_simplex.points[2]].y; + cm.matrix[1][3] = p_points[p_simplex.points[3]].y; + + cm.matrix[2][0] = p_points[p_simplex.points[0]].z; + cm.matrix[2][1] = p_points[p_simplex.points[1]].z; + cm.matrix[2][2] = p_points[p_simplex.points[2]].z; + cm.matrix[2][3] = p_points[p_simplex.points[3]].z; + + cm.matrix[3][0] = 1.0; + cm.matrix[3][1] = 1.0; + cm.matrix[3][2] = 1.0; + cm.matrix[3][3] = 1.0; + + return ABS(cm.determinant()) <= CMP_EPSILON; + } + +public: + struct OutputSimplex { + uint32_t points[4]; + }; + + static Vector<OutputSimplex> tetrahedralize(const Vector<Vector3> &p_points) { + + uint32_t point_count = p_points.size(); + Vector3 *points = (Vector3 *)memalloc(sizeof(Vector3) * (point_count + 4)); + + { + const Vector3 *src_points = p_points.ptr(); + AABB rect; + for (uint32_t i = 0; i < point_count; i++) { + Vector3 point = src_points[i]; + if (i == 0) { + rect.position = point; + } else { + rect.expand_to(point); + } + points[i] = point; + } + + for (uint32_t i = 0; i < point_count; i++) { + points[i] = (points[i] - rect.position) / rect.size; + } + + float delta_max = Math::sqrt(2.0) * 20.0; + Vector3 center = Vector3(0.5, 0.5, 0.5); + + // any simplex that contains everything is good + points[point_count + 0] = center + Vector3(0, 1, 0) * delta_max; + points[point_count + 1] = center + Vector3(0, -1, 1) * delta_max; + points[point_count + 2] = center + Vector3(1, -1, -1) * delta_max; + points[point_count + 3] = center + Vector3(-1, -1, -1) * delta_max; + } + + List<Simplex *> acceleration_grid[ACCEL_GRID_SIZE][ACCEL_GRID_SIZE][ACCEL_GRID_SIZE]; + + List<Simplex *> simplex_list; + { + //create root simplex + Simplex *root = memnew(Simplex(point_count + 0, point_count + 1, point_count + 2, point_count + 3)); + root->SE = simplex_list.push_back(root); + + for (uint32_t i = 0; i < ACCEL_GRID_SIZE; i++) { + for (uint32_t j = 0; j < ACCEL_GRID_SIZE; j++) { + for (uint32_t k = 0; k < ACCEL_GRID_SIZE; k++) { + GridPos gp; + gp.E = acceleration_grid[i][j][k].push_back(root); + gp.pos = Vector3i(i, j, k); + root->grid_positions.push_back(gp); + } + } + } + + circum_sphere_compute(points, root); + } + + OAHashMap<Triangle, uint32_t, TriangleHasher> triangles_inserted; + LocalVector<Triangle> triangles; + + for (uint32_t i = 0; i < point_count; i++) { + + bool unique = true; + for (uint32_t j = i + 1; j < point_count; j++) { + if (points[i].is_equal_approx(points[j])) { + unique = false; + break; + } + } + if (!unique) { + continue; + } + + Vector3i grid_pos = Vector3i(points[i] * ACCEL_GRID_SIZE); + grid_pos.x = CLAMP(grid_pos.x, 0, ACCEL_GRID_SIZE - 1); + grid_pos.y = CLAMP(grid_pos.y, 0, ACCEL_GRID_SIZE - 1); + grid_pos.z = CLAMP(grid_pos.z, 0, ACCEL_GRID_SIZE - 1); + + for (List<Simplex *>::Element *E = acceleration_grid[grid_pos.x][grid_pos.y][grid_pos.z].front(); E;) { + List<Simplex *>::Element *N = E->next(); //may be deleted + + Simplex *simplex = E->get(); + + if (simplex_contains(points, *simplex, i)) { + + static const uint32_t triangle_order[4][3] = { + { 0, 1, 2 }, + { 0, 1, 3 }, + { 0, 2, 3 }, + { 1, 2, 3 }, + }; + + for (uint32_t k = 0; k < 4; k++) { + Triangle t = Triangle(simplex->points[triangle_order[k][0]], simplex->points[triangle_order[k][1]], simplex->points[triangle_order[k][2]]); + uint32_t *p = triangles_inserted.lookup_ptr(t); + if (p) { + triangles[*p].bad = true; + } else { + triangles_inserted.insert(t, triangles.size()); + triangles.push_back(t); + } + } + + //remove simplex and continue + simplex_list.erase(simplex->SE); + + for (uint32_t k = 0; k < simplex->grid_positions.size(); k++) { + Vector3i p = simplex->grid_positions[k].pos; + acceleration_grid[p.x][p.y][p.z].erase(simplex->grid_positions[k].E); + } + memdelete(simplex); + } + E = N; + } + + uint32_t good_triangles = 0; + for (uint32_t j = 0; j < triangles.size(); j++) { + + if (triangles[j].bad) { + continue; + } + Simplex *new_simplex = memnew(Simplex(triangles[j].triangle[0], triangles[j].triangle[1], triangles[j].triangle[2], i)); + circum_sphere_compute(points, new_simplex); + new_simplex->SE = simplex_list.push_back(new_simplex); + { + Vector3 center; + center.x = double(new_simplex->circum_center_x); + center.y = double(new_simplex->circum_center_y); + center.z = double(new_simplex->circum_center_z); + + float radius2 = Math::sqrt(double(new_simplex->circum_r2)); + radius2 += 0.0001; // + Vector3 extents = Vector3(radius2, radius2, radius2); + Vector3i from = Vector3i((center - extents) * ACCEL_GRID_SIZE); + Vector3i to = Vector3i((center + extents) * ACCEL_GRID_SIZE); + from.x = CLAMP(from.x, 0, ACCEL_GRID_SIZE - 1); + from.y = CLAMP(from.y, 0, ACCEL_GRID_SIZE - 1); + from.z = CLAMP(from.z, 0, ACCEL_GRID_SIZE - 1); + to.x = CLAMP(to.x, 0, ACCEL_GRID_SIZE - 1); + to.y = CLAMP(to.y, 0, ACCEL_GRID_SIZE - 1); + to.z = CLAMP(to.z, 0, ACCEL_GRID_SIZE - 1); + + for (int32_t x = from.x; x <= to.x; x++) { + for (int32_t y = from.y; y <= to.y; y++) { + for (int32_t z = from.z; z <= to.z; z++) { + GridPos gp; + gp.pos = Vector3(x, y, z); + gp.E = acceleration_grid[x][y][z].push_back(new_simplex); + new_simplex->grid_positions.push_back(gp); + } + } + } + } + + good_triangles++; + } + + //print_line("at point " + itos(i) + "/" + itos(point_count) + " simplices added " + itos(good_triangles) + "/" + itos(simplex_list.size()) + " - triangles: " + itos(triangles.size())); + triangles.clear(); + triangles_inserted.clear(); + } + + //print_line("end with simplices: " + itos(simplex_list.size())); + Vector<OutputSimplex> ret_simplices; + ret_simplices.resize(simplex_list.size()); + OutputSimplex *ret_simplicesw = ret_simplices.ptrw(); + uint32_t simplices_written = 0; + + for (List<Simplex *>::Element *E = simplex_list.front(); E; E = E->next()) { + Simplex *simplex = E->get(); + bool invalid = false; + for (int j = 0; j < 4; j++) { + if (simplex->points[j] >= point_count) { + invalid = true; + break; + } + } + if (invalid || simplex_is_coplanar(points, *simplex)) { + memdelete(simplex); + continue; + } + + ret_simplicesw[simplices_written].points[0] = simplex->points[0]; + ret_simplicesw[simplices_written].points[1] = simplex->points[1]; + ret_simplicesw[simplices_written].points[2] = simplex->points[2]; + ret_simplicesw[simplices_written].points[3] = simplex->points[3]; + simplices_written++; + memdelete(simplex); + } + + ret_simplices.resize(simplices_written); + + memfree(points); + + return ret_simplices; + } +}; + +#endif // DELAUNAY_3D_H diff --git a/core/math/expression.cpp b/core/math/expression.cpp index 859b9be8c5..f7a124eae3 100644 --- a/core/math/expression.cpp +++ b/core/math/expression.cpp @@ -1023,11 +1023,21 @@ Error Expression::_get_token(Token &r_token) { switch (next) { - case 'b': res = 8; break; - case 't': res = 9; break; - case 'n': res = 10; break; - case 'f': res = 12; break; - case 'r': res = 13; break; + case 'b': + res = 8; + break; + case 't': + res = 9; + break; + case 'n': + res = 10; + break; + case 'f': + res = 12; + break; + case 'r': + res = 13; + break; case 'u': { // hex number for (int j = 0; j < 4; j++) { @@ -1703,27 +1713,69 @@ Expression::ENode *Expression::_parse_expression() { Variant::Operator op = Variant::OP_MAX; switch (tk.type) { - case TK_OP_IN: op = Variant::OP_IN; break; - case TK_OP_EQUAL: op = Variant::OP_EQUAL; break; - case TK_OP_NOT_EQUAL: op = Variant::OP_NOT_EQUAL; break; - case TK_OP_LESS: op = Variant::OP_LESS; break; - case TK_OP_LESS_EQUAL: op = Variant::OP_LESS_EQUAL; break; - case TK_OP_GREATER: op = Variant::OP_GREATER; break; - case TK_OP_GREATER_EQUAL: op = Variant::OP_GREATER_EQUAL; break; - case TK_OP_AND: op = Variant::OP_AND; break; - case TK_OP_OR: op = Variant::OP_OR; break; - case TK_OP_NOT: op = Variant::OP_NOT; break; - case TK_OP_ADD: op = Variant::OP_ADD; break; - case TK_OP_SUB: op = Variant::OP_SUBTRACT; break; - case TK_OP_MUL: op = Variant::OP_MULTIPLY; break; - case TK_OP_DIV: op = Variant::OP_DIVIDE; break; - case TK_OP_MOD: op = Variant::OP_MODULE; break; - case TK_OP_SHIFT_LEFT: op = Variant::OP_SHIFT_LEFT; break; - case TK_OP_SHIFT_RIGHT: op = Variant::OP_SHIFT_RIGHT; break; - case TK_OP_BIT_AND: op = Variant::OP_BIT_AND; break; - case TK_OP_BIT_OR: op = Variant::OP_BIT_OR; break; - case TK_OP_BIT_XOR: op = Variant::OP_BIT_XOR; break; - case TK_OP_BIT_INVERT: op = Variant::OP_BIT_NEGATE; break; + case TK_OP_IN: + op = Variant::OP_IN; + break; + case TK_OP_EQUAL: + op = Variant::OP_EQUAL; + break; + case TK_OP_NOT_EQUAL: + op = Variant::OP_NOT_EQUAL; + break; + case TK_OP_LESS: + op = Variant::OP_LESS; + break; + case TK_OP_LESS_EQUAL: + op = Variant::OP_LESS_EQUAL; + break; + case TK_OP_GREATER: + op = Variant::OP_GREATER; + break; + case TK_OP_GREATER_EQUAL: + op = Variant::OP_GREATER_EQUAL; + break; + case TK_OP_AND: + op = Variant::OP_AND; + break; + case TK_OP_OR: + op = Variant::OP_OR; + break; + case TK_OP_NOT: + op = Variant::OP_NOT; + break; + case TK_OP_ADD: + op = Variant::OP_ADD; + break; + case TK_OP_SUB: + op = Variant::OP_SUBTRACT; + break; + case TK_OP_MUL: + op = Variant::OP_MULTIPLY; + break; + case TK_OP_DIV: + op = Variant::OP_DIVIDE; + break; + case TK_OP_MOD: + op = Variant::OP_MODULE; + break; + case TK_OP_SHIFT_LEFT: + op = Variant::OP_SHIFT_LEFT; + break; + case TK_OP_SHIFT_RIGHT: + op = Variant::OP_SHIFT_RIGHT; + break; + case TK_OP_BIT_AND: + op = Variant::OP_BIT_AND; + break; + case TK_OP_BIT_OR: + op = Variant::OP_BIT_OR; + break; + case TK_OP_BIT_XOR: + op = Variant::OP_BIT_XOR; + break; + case TK_OP_BIT_INVERT: + op = Variant::OP_BIT_NEGATE; + break; default: { }; } @@ -1772,36 +1824,74 @@ Expression::ENode *Expression::_parse_expression() { unary = true; break; - case Variant::OP_MULTIPLY: priority = 2; break; - case Variant::OP_DIVIDE: priority = 2; break; - case Variant::OP_MODULE: priority = 2; break; + case Variant::OP_MULTIPLY: + priority = 2; + break; + case Variant::OP_DIVIDE: + priority = 2; + break; + case Variant::OP_MODULE: + priority = 2; + break; - case Variant::OP_ADD: priority = 3; break; - case Variant::OP_SUBTRACT: priority = 3; break; + case Variant::OP_ADD: + priority = 3; + break; + case Variant::OP_SUBTRACT: + priority = 3; + break; - case Variant::OP_SHIFT_LEFT: priority = 4; break; - case Variant::OP_SHIFT_RIGHT: priority = 4; break; + case Variant::OP_SHIFT_LEFT: + priority = 4; + break; + case Variant::OP_SHIFT_RIGHT: + priority = 4; + break; - case Variant::OP_BIT_AND: priority = 5; break; - case Variant::OP_BIT_XOR: priority = 6; break; - case Variant::OP_BIT_OR: priority = 7; break; + case Variant::OP_BIT_AND: + priority = 5; + break; + case Variant::OP_BIT_XOR: + priority = 6; + break; + case Variant::OP_BIT_OR: + priority = 7; + break; - case Variant::OP_LESS: priority = 8; break; - case Variant::OP_LESS_EQUAL: priority = 8; break; - case Variant::OP_GREATER: priority = 8; break; - case Variant::OP_GREATER_EQUAL: priority = 8; break; + case Variant::OP_LESS: + priority = 8; + break; + case Variant::OP_LESS_EQUAL: + priority = 8; + break; + case Variant::OP_GREATER: + priority = 8; + break; + case Variant::OP_GREATER_EQUAL: + priority = 8; + break; - case Variant::OP_EQUAL: priority = 8; break; - case Variant::OP_NOT_EQUAL: priority = 8; break; + case Variant::OP_EQUAL: + priority = 8; + break; + case Variant::OP_NOT_EQUAL: + priority = 8; + break; - case Variant::OP_IN: priority = 10; break; + case Variant::OP_IN: + priority = 10; + break; case Variant::OP_NOT: priority = 11; unary = true; break; - case Variant::OP_AND: priority = 12; break; - case Variant::OP_OR: priority = 13; break; + case Variant::OP_AND: + priority = 12; + break; + case Variant::OP_OR: + priority = 13; + break; default: { _set_error("Parser bug, invalid operator in expression: " + itos(expression[i].op)); diff --git a/core/math/geometry.cpp b/core/math/geometry.cpp index fa96fc4535..b0a46036f9 100644 --- a/core/math/geometry.cpp +++ b/core/math/geometry.cpp @@ -31,8 +31,11 @@ #include "geometry.h" #include "core/print_string.h" + #include "thirdparty/misc/clipper.hpp" #include "thirdparty/misc/triangulator.h" +#define STB_RECT_PACK_IMPLEMENTATION +#include "thirdparty/misc/stb_rect_pack.h" #define SCALE_FACTOR 100000.0 // Based on CMP_EPSILON. @@ -445,7 +448,8 @@ static inline void _mark_outside(uint8_t ***p_cell_status, int x, int y, int z, next_z--; prev = _CELL_PREV_Z_POS; } break; - default: ERR_FAIL(); + default: + ERR_FAIL(); } if (next_x < 0 || next_x >= len_x) @@ -1083,10 +1087,18 @@ Vector<Vector<Point2>> Geometry::_polypaths_do_operation(PolyBooleanOperation p_ ClipType op = ctUnion; switch (p_op) { - case OPERATION_UNION: op = ctUnion; break; - case OPERATION_DIFFERENCE: op = ctDifference; break; - case OPERATION_INTERSECTION: op = ctIntersection; break; - case OPERATION_XOR: op = ctXor; break; + case OPERATION_UNION: + op = ctUnion; + break; + case OPERATION_DIFFERENCE: + op = ctDifference; + break; + case OPERATION_INTERSECTION: + op = ctIntersection; + break; + case OPERATION_XOR: + op = ctXor; + break; } Path path_a, path_b; @@ -1135,19 +1147,35 @@ Vector<Vector<Point2>> Geometry::_polypath_offset(const Vector<Point2> &p_polypa JoinType jt = jtSquare; switch (p_join_type) { - case JOIN_SQUARE: jt = jtSquare; break; - case JOIN_ROUND: jt = jtRound; break; - case JOIN_MITER: jt = jtMiter; break; + case JOIN_SQUARE: + jt = jtSquare; + break; + case JOIN_ROUND: + jt = jtRound; + break; + case JOIN_MITER: + jt = jtMiter; + break; } EndType et = etClosedPolygon; switch (p_end_type) { - case END_POLYGON: et = etClosedPolygon; break; - case END_JOINED: et = etClosedLine; break; - case END_BUTT: et = etOpenButt; break; - case END_SQUARE: et = etOpenSquare; break; - case END_ROUND: et = etOpenRound; break; + case END_POLYGON: + et = etClosedPolygon; + break; + case END_JOINED: + et = etClosedLine; + break; + case END_BUTT: + et = etOpenButt; + break; + case END_SQUARE: + et = etOpenSquare; + break; + case END_ROUND: + et = etOpenRound; + break; } ClipperOffset co(2.0, 0.25 * SCALE_FACTOR); // Defaults from ClipperOffset. Path path; @@ -1217,3 +1245,195 @@ Vector<Vector3> Geometry::compute_convex_mesh_points(const Plane *p_planes, int return points; } + +Vector<Point2i> Geometry::pack_rects(const Vector<Size2i> &p_sizes, const Size2i &p_atlas_size) { + + Vector<stbrp_node> nodes; + nodes.resize(p_atlas_size.width); + + stbrp_context context; + stbrp_init_target(&context, p_atlas_size.width, p_atlas_size.height, nodes.ptrw(), p_atlas_size.width); + + Vector<stbrp_rect> rects; + rects.resize(p_sizes.size()); + + for (int i = 0; i < p_sizes.size(); i++) { + rects.write[i].id = 0; + rects.write[i].w = p_sizes[i].width; + rects.write[i].h = p_sizes[i].height; + rects.write[i].x = 0; + rects.write[i].y = 0; + rects.write[i].was_packed = 0; + } + + int res = stbrp_pack_rects(&context, rects.ptrw(), rects.size()); + if (res == 0) { //pack failed + return Vector<Point2i>(); + } + + Vector<Point2i> ret; + ret.resize(p_sizes.size()); + + for (int i = 0; i < p_sizes.size(); i++) { + Point2i r(rects[i].x, rects[i].y); + ret.write[i] = r; + } + + return ret; +} + +Vector<Vector3i> Geometry::partial_pack_rects(const Vector<Vector2i> &p_sizes, const Size2i &p_atlas_size) { + + Vector<stbrp_node> nodes; + nodes.resize(p_atlas_size.width); + zeromem(nodes.ptrw(), sizeof(stbrp_node) * nodes.size()); + + stbrp_context context; + stbrp_init_target(&context, p_atlas_size.width, p_atlas_size.height, nodes.ptrw(), p_atlas_size.width); + + Vector<stbrp_rect> rects; + rects.resize(p_sizes.size()); + + for (int i = 0; i < p_sizes.size(); i++) { + rects.write[i].id = i; + rects.write[i].w = p_sizes[i].width; + rects.write[i].h = p_sizes[i].height; + rects.write[i].x = 0; + rects.write[i].y = 0; + rects.write[i].was_packed = 0; + } + + stbrp_pack_rects(&context, rects.ptrw(), rects.size()); + + Vector<Vector3i> ret; + ret.resize(p_sizes.size()); + + for (int i = 0; i < p_sizes.size(); i++) { + ret.write[rects[i].id] = Vector3i(rects[i].x, rects[i].y, rects[i].was_packed != 0 ? 1 : 0); + } + + return ret; +} + +#define square(m_s) ((m_s) * (m_s)) +#define INF 1e20 + +/* dt of 1d function using squared distance */ +static void edt(float *f, int stride, int n) { + + float *d = (float *)alloca(sizeof(float) * n + sizeof(int) * n + sizeof(float) * (n + 1)); + int *v = (int *)&(d[n]); + float *z = (float *)&v[n]; + + int k = 0; + v[0] = 0; + z[0] = -INF; + z[1] = +INF; + for (int q = 1; q <= n - 1; q++) { + float s = ((f[q * stride] + square(q)) - (f[v[k] * stride] + square(v[k]))) / (2 * q - 2 * v[k]); + while (s <= z[k]) { + k--; + s = ((f[q * stride] + square(q)) - (f[v[k] * stride] + square(v[k]))) / (2 * q - 2 * v[k]); + } + k++; + v[k] = q; + + z[k] = s; + z[k + 1] = +INF; + } + + k = 0; + for (int q = 0; q <= n - 1; q++) { + while (z[k + 1] < q) + k++; + d[q] = square(q - v[k]) + f[v[k] * stride]; + } + + for (int i = 0; i < n; i++) { + f[i * stride] = d[i]; + } +} + +#undef square + +Vector<uint32_t> Geometry::generate_edf(const Vector<bool> &p_voxels, const Vector3i &p_size, bool p_negative) { + + uint32_t float_count = p_size.x * p_size.y * p_size.z; + + ERR_FAIL_COND_V((uint32_t)p_voxels.size() != float_count, Vector<uint32_t>()); + + float *work_memory = memnew_arr(float, float_count); + for (uint32_t i = 0; i < float_count; i++) { + work_memory[i] = INF; + } + + uint32_t y_mult = p_size.x; + uint32_t z_mult = y_mult * p_size.y; + + //plot solid cells + { + const bool *voxr = p_voxels.ptr(); + for (uint32_t i = 0; i < float_count; i++) { + + bool plot = voxr[i]; + if (p_negative) { + plot = !plot; + } + if (plot) { + work_memory[i] = 0; + } + } + } + + //process in each direction + + //xy->z + + for (int i = 0; i < p_size.x; i++) { + for (int j = 0; j < p_size.y; j++) { + edt(&work_memory[i + j * y_mult], z_mult, p_size.z); + } + } + + //xz->y + + for (int i = 0; i < p_size.x; i++) { + for (int j = 0; j < p_size.z; j++) { + edt(&work_memory[i + j * z_mult], y_mult, p_size.y); + } + } + + //yz->x + for (int i = 0; i < p_size.y; i++) { + for (int j = 0; j < p_size.z; j++) { + edt(&work_memory[i * y_mult + j * z_mult], 1, p_size.x); + } + } + + Vector<uint32_t> ret; + ret.resize(float_count); + { + uint32_t *w = ret.ptrw(); + for (uint32_t i = 0; i < float_count; i++) { + w[i] = uint32_t(Math::sqrt(work_memory[i])); + } + } + + return ret; +} + +Vector<int8_t> Geometry::generate_sdf8(const Vector<uint32_t> &p_positive, const Vector<uint32_t> &p_negative) { + ERR_FAIL_COND_V(p_positive.size() != p_negative.size(), Vector<int8_t>()); + Vector<int8_t> sdf8; + int s = p_positive.size(); + sdf8.resize(s); + + const uint32_t *rpos = p_positive.ptr(); + const uint32_t *rneg = p_negative.ptr(); + int8_t *wsdf = sdf8.ptrw(); + for (int i = 0; i < s; i++) { + int32_t diff = int32_t(rpos[i]) - int32_t(rneg[i]); + wsdf[i] = CLAMP(diff, -128, 127); + } + return sdf8; +} diff --git a/core/math/geometry.h b/core/math/geometry.h index ea063a8a59..45c8558fac 100644 --- a/core/math/geometry.h +++ b/core/math/geometry.h @@ -31,13 +31,12 @@ #ifndef GEOMETRY_H #define GEOMETRY_H -#include "core/math/delaunay.h" +#include "core/math/delaunay_2d.h" #include "core/math/face3.h" #include "core/math/rect2.h" #include "core/math/triangulate.h" #include "core/math/vector3.h" #include "core/object.h" - #include "core/print_string.h" #include "core/vector.h" @@ -113,10 +112,14 @@ public: real_t mub = (d_of(p1, q1, q2, q1) + mua * d_of(q2, q1, p2, p1)) / d_of(q2, q1, q2, q1); // Clip the value between [0..1] constraining the solution to lie on the original curves. - if (mua < 0) mua = 0; - if (mub < 0) mub = 0; - if (mua > 1) mua = 1; - if (mub > 1) mub = 1; + if (mua < 0) + mua = 0; + if (mub < 0) + mub = 0; + if (mua > 1) + mua = 1; + if (mub > 1) + mub = 1; c1 = p1.lerp(p2, mua); c2 = q1.lerp(q2, mub); } @@ -497,7 +500,8 @@ public: bool orientation = an.cross(bn) > 0; - if ((bn.cross(cn) > 0) != orientation) return false; + if ((bn.cross(cn) > 0) != orientation) + return false; return (cn.cross(an) > 0) == orientation; } @@ -683,7 +687,8 @@ public: // If the term we intend to square root is less than 0 then the answer won't be real, // so it definitely won't be t in the range 0 to 1. - if (sqrtterm < 0) return -1; + if (sqrtterm < 0) + return -1; // If we can assume that the line segment starts outside the circle (e.g. for continuous time collision detection) // then the following can be skipped and we can just return the equivalent of res1. @@ -691,8 +696,10 @@ public: real_t res1 = (-b - sqrtterm) / (2 * a); real_t res2 = (-b + sqrtterm) / (2 * a); - if (res1 >= 0 && res1 <= 1) return res1; - if (res2 >= 0 && res2 <= 1) return res2; + if (res1 >= 0 && res1 <= 1) + return res1; + if (res2 >= 0 && res2 <= 1) + return res2; return -1; } @@ -1016,6 +1023,249 @@ public: static Vector<Vector3> compute_convex_mesh_points(const Plane *p_planes, int p_plane_count); +#define FINDMINMAX(x0, x1, x2, min, max) \ + min = max = x0; \ + if (x1 < min) \ + min = x1; \ + if (x1 > max) \ + max = x1; \ + if (x2 < min) \ + min = x2; \ + if (x2 > max) \ + max = x2; + + _FORCE_INLINE_ static bool planeBoxOverlap(Vector3 normal, float d, Vector3 maxbox) { + int q; + Vector3 vmin, vmax; + for (q = 0; q <= 2; q++) { + if (normal[q] > 0.0f) { + vmin[q] = -maxbox[q]; + vmax[q] = maxbox[q]; + } else { + vmin[q] = maxbox[q]; + vmax[q] = -maxbox[q]; + } + } + if (normal.dot(vmin) + d > 0.0f) + return false; + if (normal.dot(vmax) + d >= 0.0f) + return true; + + return false; + } + +/*======================== X-tests ========================*/ +#define AXISTEST_X01(a, b, fa, fb) \ + p0 = a * v0.y - b * v0.z; \ + p2 = a * v2.y - b * v2.z; \ + if (p0 < p2) { \ + min = p0; \ + max = p2; \ + } else { \ + min = p2; \ + max = p0; \ + } \ + rad = fa * boxhalfsize.y + fb * boxhalfsize.z; \ + if (min > rad || max < -rad) \ + return false; + +#define AXISTEST_X2(a, b, fa, fb) \ + p0 = a * v0.y - b * v0.z; \ + p1 = a * v1.y - b * v1.z; \ + if (p0 < p1) { \ + min = p0; \ + max = p1; \ + } else { \ + min = p1; \ + max = p0; \ + } \ + rad = fa * boxhalfsize.y + fb * boxhalfsize.z; \ + if (min > rad || max < -rad) \ + return false; + +/*======================== Y-tests ========================*/ +#define AXISTEST_Y02(a, b, fa, fb) \ + p0 = -a * v0.x + b * v0.z; \ + p2 = -a * v2.x + b * v2.z; \ + if (p0 < p2) { \ + min = p0; \ + max = p2; \ + } else { \ + min = p2; \ + max = p0; \ + } \ + rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \ + if (min > rad || max < -rad) \ + return false; + +#define AXISTEST_Y1(a, b, fa, fb) \ + p0 = -a * v0.x + b * v0.z; \ + p1 = -a * v1.x + b * v1.z; \ + if (p0 < p1) { \ + min = p0; \ + max = p1; \ + } else { \ + min = p1; \ + max = p0; \ + } \ + rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \ + if (min > rad || max < -rad) \ + return false; + + /*======================== Z-tests ========================*/ + +#define AXISTEST_Z12(a, b, fa, fb) \ + p1 = a * v1.x - b * v1.y; \ + p2 = a * v2.x - b * v2.y; \ + if (p2 < p1) { \ + min = p2; \ + max = p1; \ + } else { \ + min = p1; \ + max = p2; \ + } \ + rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \ + if (min > rad || max < -rad) \ + return false; + +#define AXISTEST_Z0(a, b, fa, fb) \ + p0 = a * v0.x - b * v0.y; \ + p1 = a * v1.x - b * v1.y; \ + if (p0 < p1) { \ + min = p0; \ + max = p1; \ + } else { \ + min = p1; \ + max = p0; \ + } \ + rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \ + if (min > rad || max < -rad) \ + return false; + + _FORCE_INLINE_ static bool triangle_box_overlap(const Vector3 &boxcenter, const Vector3 boxhalfsize, const Vector3 *triverts) { + + /* use separating axis theorem to test overlap between triangle and box */ + /* need to test for overlap in these directions: */ + /* 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */ + /* we do not even need to test these) */ + /* 2) normal of the triangle */ + /* 3) crossproduct(edge from tri, {x,y,z}-directin) */ + /* this gives 3x3=9 more tests */ + Vector3 v0, v1, v2; + float min, max, d, p0, p1, p2, rad, fex, fey, fez; + Vector3 normal, e0, e1, e2; + + /* This is the fastest branch on Sun */ + /* move everything so that the boxcenter is in (0,0,0) */ + + v0 = triverts[0] - boxcenter; + v1 = triverts[1] - boxcenter; + v2 = triverts[2] - boxcenter; + + /* compute triangle edges */ + e0 = v1 - v0; /* tri edge 0 */ + e1 = v2 - v1; /* tri edge 1 */ + e2 = v0 - v2; /* tri edge 2 */ + + /* Bullet 3: */ + /* test the 9 tests first (this was faster) */ + fex = Math::abs(e0.x); + fey = Math::abs(e0.y); + fez = Math::abs(e0.z); + AXISTEST_X01(e0.z, e0.y, fez, fey); + AXISTEST_Y02(e0.z, e0.x, fez, fex); + AXISTEST_Z12(e0.y, e0.x, fey, fex); + + fex = Math::abs(e1.x); + fey = Math::abs(e1.y); + fez = Math::abs(e1.z); + AXISTEST_X01(e1.z, e1.y, fez, fey); + AXISTEST_Y02(e1.z, e1.x, fez, fex); + AXISTEST_Z0(e1.y, e1.x, fey, fex); + + fex = Math::abs(e2.x); + fey = Math::abs(e2.y); + fez = Math::abs(e2.z); + AXISTEST_X2(e2.z, e2.y, fez, fey); + AXISTEST_Y1(e2.z, e2.x, fez, fex); + AXISTEST_Z12(e2.y, e2.x, fey, fex); + + /* Bullet 1: */ + /* first test overlap in the {x,y,z}-directions */ + /* find min, max of the triangle each direction, and test for overlap in */ + /* that direction -- this is equivalent to testing a minimal AABB around */ + /* the triangle against the AABB */ + + /* test in X-direction */ + FINDMINMAX(v0.x, v1.x, v2.x, min, max); + if (min > boxhalfsize.x || max < -boxhalfsize.x) + return false; + + /* test in Y-direction */ + FINDMINMAX(v0.y, v1.y, v2.y, min, max); + if (min > boxhalfsize.y || max < -boxhalfsize.y) + return false; + + /* test in Z-direction */ + FINDMINMAX(v0.z, v1.z, v2.z, min, max); + if (min > boxhalfsize.z || max < -boxhalfsize.z) + return false; + + /* Bullet 2: */ + /* test if the box intersects the plane of the triangle */ + /* compute plane equation of triangle: normal*x+d=0 */ + normal = e0.cross(e1); + d = -normal.dot(v0); /* plane eq: normal.x+d=0 */ + return planeBoxOverlap(normal, d, boxhalfsize); /* if true, box and triangle overlaps */ + } + + static Vector<Point2i> pack_rects(const Vector<Size2i> &p_sizes, const Size2i &p_atlas_size); + static Vector<Vector3i> partial_pack_rects(const Vector<Vector2i> &p_sizes, const Size2i &p_atlas_size); + + static Vector<uint32_t> generate_edf(const Vector<bool> &p_voxels, const Vector3i &p_size, bool p_negative); + static Vector<int8_t> generate_sdf8(const Vector<uint32_t> &p_positive, const Vector<uint32_t> &p_negative); + + static Vector3 triangle_get_barycentric_coords(const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_c, const Vector3 &p_pos) { + Vector3 v0 = p_b - p_a; + Vector3 v1 = p_c - p_a; + Vector3 v2 = p_pos - p_a; + + float d00 = v0.dot(v0); + float d01 = v0.dot(v1); + float d11 = v1.dot(v1); + float d20 = v2.dot(v0); + float d21 = v2.dot(v1); + float denom = (d00 * d11 - d01 * d01); + if (denom == 0) { + return Vector3(); //invalid triangle, return empty + } + float v = (d11 * d20 - d01 * d21) / denom; + float w = (d00 * d21 - d01 * d20) / denom; + float u = 1.0f - v - w; + return Vector3(u, v, w); + } + + static Color tetrahedron_get_barycentric_coords(const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_c, const Vector3 &p_d, const Vector3 &p_pos) { + Vector3 vap = p_pos - p_a; + Vector3 vbp = p_pos - p_b; + + Vector3 vab = p_b - p_a; + Vector3 vac = p_c - p_a; + Vector3 vad = p_d - p_a; + + Vector3 vbc = p_c - p_b; + Vector3 vbd = p_d - p_b; + // ScTP computes the scalar triple product +#define STP(m_a, m_b, m_c) ((m_a).dot((m_b).cross((m_c)))) + float va6 = STP(vbp, vbd, vbc); + float vb6 = STP(vap, vac, vad); + float vc6 = STP(vap, vad, vab); + float vd6 = STP(vap, vab, vac); + float v6 = 1 / STP(vab, vac, vad); + return Color(va6 * v6, vb6 * v6, vc6 * v6, vd6 * v6); +#undef STP + } + private: static Vector<Vector<Point2>> _polypaths_do_operation(PolyBooleanOperation p_op, const Vector<Point2> &p_polypath_a, const Vector<Point2> &p_polypath_b, bool is_a_open = false); static Vector<Vector<Point2>> _polypath_offset(const Vector<Point2> &p_polypath, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type); diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 3e1eb14a6a..bd13c82894 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -233,12 +233,14 @@ public: static _ALWAYS_INLINE_ float range_lerp(float p_value, float p_istart, float p_istop, float p_ostart, float p_ostop) { return Math::lerp(p_ostart, p_ostop, Math::inverse_lerp(p_istart, p_istop, p_value)); } static _ALWAYS_INLINE_ double smoothstep(double p_from, double p_to, double p_weight) { - if (is_equal_approx(p_from, p_to)) return p_from; + if (is_equal_approx(p_from, p_to)) + return p_from; double x = CLAMP((p_weight - p_from) / (p_to - p_from), 0.0, 1.0); return x * x * (3.0 - 2.0 * x); } static _ALWAYS_INLINE_ float smoothstep(float p_from, float p_to, float p_weight) { - if (is_equal_approx(p_from, p_to)) return p_from; + if (is_equal_approx(p_from, p_to)) + return p_from; float x = CLAMP((p_weight - p_from) / (p_to - p_from), 0.0f, 1.0f); return x * x * (3.0f - 2.0f * x); } diff --git a/core/math/plane.cpp b/core/math/plane.cpp index a3818698bc..26ac0aac47 100644 --- a/core/math/plane.cpp +++ b/core/math/plane.cpp @@ -153,6 +153,10 @@ bool Plane::intersects_segment(const Vector3 &p_begin, const Vector3 &p_end, Vec /* misc */ +bool Plane::is_equal_approx_any_side(const Plane &p_plane) const { + return (normal.is_equal_approx(p_plane.normal) && Math::is_equal_approx(d, p_plane.d)) || (normal.is_equal_approx(-p_plane.normal) && Math::is_equal_approx(d, -p_plane.d)); +} + bool Plane::is_equal_approx(const Plane &p_plane) const { return normal.is_equal_approx(p_plane.normal) && Math::is_equal_approx(d, p_plane.d); diff --git a/core/math/plane.h b/core/math/plane.h index 771c8fc705..d4f23ff2b6 100644 --- a/core/math/plane.h +++ b/core/math/plane.h @@ -69,6 +69,7 @@ public: Plane operator-() const { return Plane(-normal, -d); } bool is_equal_approx(const Plane &p_plane) const; + bool is_equal_approx_any_side(const Plane &p_plane) const; _FORCE_INLINE_ bool operator==(const Plane &p_plane) const; _FORCE_INLINE_ bool operator!=(const Plane &p_plane) const; diff --git a/core/math/quat.cpp b/core/math/quat.cpp index 61cd41b23d..6fbea70279 100644 --- a/core/math/quat.cpp +++ b/core/math/quat.cpp @@ -206,7 +206,8 @@ Quat Quat::slerpni(const Quat &q, const real_t &t) const { real_t dot = from.dot(q); - if (Math::absf(dot) > 0.9999) return from; + if (Math::absf(dot) > 0.9999) + return from; real_t theta = Math::acos(dot), sinT = 1.0 / Math::sin(theta), diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp index 5c66721b9d..0f7350a260 100644 --- a/core/math/triangle_mesh.cpp +++ b/core/math/triangle_mesh.cpp @@ -558,14 +558,16 @@ bool TriangleMesh::intersect_convex_shape(const Plane *p_planes, int p_plane_cou if (p.intersects_segment(point, next_point, &res)) { bool inisde = true; for (int k = 0; k < p_plane_count; k++) { - if (k == i) continue; + if (k == i) + continue; const Plane &pp = p_planes[k]; if (pp.is_point_over(res)) { inisde = false; break; } } - if (inisde) return true; + if (inisde) + return true; } if (p.is_point_over(point)) { @@ -573,7 +575,8 @@ bool TriangleMesh::intersect_convex_shape(const Plane *p_planes, int p_plane_cou break; } } - if (over) return true; + if (over) + return true; } stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; @@ -652,7 +655,8 @@ bool TriangleMesh::inside_convex_shape(const Plane *p_planes, int p_plane_count, case TEST_AABB_BIT: { bool intersects = scale.xform(b.aabb).intersects_convex_shape(p_planes, p_plane_count, p_points, p_point_count); - if (!intersects) return false; + if (!intersects) + return false; bool inside = scale.xform(b.aabb).inside_convex_shape(p_planes, p_plane_count); if (inside) { @@ -667,7 +671,8 @@ bool TriangleMesh::inside_convex_shape(const Plane *p_planes, int p_plane_count, Vector3 point = scale.xform(vertexptr[s.indices[j]]); for (int i = 0; i < p_plane_count; i++) { const Plane &p = p_planes[i]; - if (p.is_point_over(point)) return false; + if (p.is_point_over(point)) + return false; } } diff --git a/core/math/triangulate.cpp b/core/math/triangulate.cpp index cbcb232745..ae278b034d 100644 --- a/core/math/triangulate.cpp +++ b/core/math/triangulate.cpp @@ -103,13 +103,16 @@ bool Triangulate::snip(const Vector<Vector2> &p_contour, int u, int v, int w, in // To avoid that we allow zero-area triangles if all else failed. float threshold = relaxed ? -CMP_EPSILON : CMP_EPSILON; - if (threshold > (((Bx - Ax) * (Cy - Ay)) - ((By - Ay) * (Cx - Ax)))) return false; + if (threshold > (((Bx - Ax) * (Cy - Ay)) - ((By - Ay) * (Cx - Ax)))) + return false; for (p = 0; p < n; p++) { - if ((p == u) || (p == v) || (p == w)) continue; + if ((p == u) || (p == v) || (p == w)) + continue; Px = contour[V[p]].x; Py = contour[V[p]].y; - if (is_inside_triangle(Ax, Ay, Bx, By, Cx, Cy, Px, Py, relaxed)) return false; + if (is_inside_triangle(Ax, Ay, Bx, By, Cx, Cy, Px, Py, relaxed)) + return false; } return true; @@ -119,7 +122,8 @@ bool Triangulate::triangulate(const Vector<Vector2> &contour, Vector<int> &resul /* allocate and initialize list of Vertices in polygon */ int n = contour.size(); - if (n < 3) return false; + if (n < 3) + return false; Vector<int> V; V.resize(n); @@ -161,11 +165,14 @@ bool Triangulate::triangulate(const Vector<Vector2> &contour, Vector<int> &resul /* three consecutive vertices in current polygon, <u,v,w> */ int u = v; - if (nv <= u) u = 0; /* previous */ + if (nv <= u) + u = 0; /* previous */ v = u + 1; - if (nv <= v) v = 0; /* new v */ + if (nv <= v) + v = 0; /* new v */ int w = v + 1; - if (nv <= w) w = 0; /* next */ + if (nv <= w) + w = 0; /* next */ if (snip(contour, u, v, w, nv, V, relaxed)) { int a, b, c, s, t; diff --git a/core/method_bind.h b/core/method_bind.h index d39f107ba6..b3d4f1bf9b 100644 --- a/core/method_bind.h +++ b/core/method_bind.h @@ -165,7 +165,8 @@ struct VariantObjectClassChecker<Control *> { #define CHECK_NOARG(m_arg) \ { \ if (p_arg##m_arg.get_type() != Variant::NIL) { \ - if (r_argerror) *r_argerror = (m_arg - 1); \ + if (r_argerror) \ + *r_argerror = (m_arg - 1); \ return CALL_ERROR_EXTRA_ARGUMENT; \ } \ } diff --git a/core/node_path.cpp b/core/node_path.cpp index 83233622a0..25f1b38346 100644 --- a/core/node_path.cpp +++ b/core/node_path.cpp @@ -373,7 +373,8 @@ NodePath::NodePath(const String &p_path) { String str = path.substr(from, i - from); if (str == "") { - if (path[i] == 0) continue; // Allow end-of-path : + if (path[i] == 0) + continue; // Allow end-of-path : ERR_FAIL_MSG("Invalid NodePath '" + p_path + "'."); } diff --git a/core/object.cpp b/core/object.cpp index b0e6f2bdae..94d957f3af 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -543,7 +543,8 @@ void Object::set_indexed(const Vector<StringName> &p_names, const Variant &p_val } bool valid = false; - if (!r_valid) r_valid = &valid; + if (!r_valid) + r_valid = &valid; List<Variant> value_stack; diff --git a/core/object.h b/core/object.h index b40aef2a42..3dec8a0480 100644 --- a/core/object.h +++ b/core/object.h @@ -346,7 +346,8 @@ protected: return (bool (Object::*)(const StringName &, const Variant &)) & m_class::_set; \ } \ virtual bool _setv(const StringName &p_name, const Variant &p_property) { \ - if (m_inherits::_setv(p_name, p_property)) return true; \ + if (m_inherits::_setv(p_name, p_property)) \ + return true; \ if (m_class::_get_set() != m_inherits::_get_set()) { \ return _set(p_name, p_property); \ } \ diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp index 94c8cd5d73..b26cd46fd8 100644 --- a/core/os/dir_access.cpp +++ b/core/os/dir_access.cpp @@ -39,18 +39,24 @@ String DirAccess::_get_root_path() const { switch (_access_type) { - case ACCESS_RESOURCES: return ProjectSettings::get_singleton()->get_resource_path(); - case ACCESS_USERDATA: return OS::get_singleton()->get_user_data_dir(); - default: return ""; + case ACCESS_RESOURCES: + return ProjectSettings::get_singleton()->get_resource_path(); + case ACCESS_USERDATA: + return OS::get_singleton()->get_user_data_dir(); + default: + return ""; } } String DirAccess::_get_root_string() const { switch (_access_type) { - case ACCESS_RESOURCES: return "res://"; - case ACCESS_USERDATA: return "user://"; - default: return ""; + case ACCESS_RESOURCES: + return "res://"; + case ACCESS_USERDATA: + return "user://"; + default: + return ""; } } @@ -220,7 +226,8 @@ String DirAccess::fix_path(String p_path) const { return p_path; } break; - case ACCESS_MAX: break; // Can't happen, but silences warning + case ACCESS_MAX: + break; // Can't happen, but silences warning } return p_path; diff --git a/core/os/dir_access.h b/core/os/dir_access.h index 60eb553968..6c876cde5a 100644 --- a/core/os/dir_access.h +++ b/core/os/dir_access.h @@ -145,7 +145,8 @@ struct DirAccessRef { DirAccess *f; DirAccessRef(DirAccess *fa) { f = fa; } ~DirAccessRef() { - if (f) memdelete(f); + if (f) + memdelete(f); } }; diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp index 3922f031b7..7055780f34 100644 --- a/core/os/file_access.cpp +++ b/core/os/file_access.cpp @@ -163,7 +163,8 @@ String FileAccess::fix_path(const String &p_path) const { return r_path; } break; - case ACCESS_MAX: break; // Can't happen, but silences warning + case ACCESS_MAX: + break; // Can't happen, but silences warning } return r_path; diff --git a/core/os/file_access.h b/core/os/file_access.h index 010cc74a87..0f85c447b6 100644 --- a/core/os/file_access.h +++ b/core/os/file_access.h @@ -192,7 +192,8 @@ struct FileAccessRef { operator FileAccess *() { return f; } FileAccessRef(FileAccess *fa) { f = fa; } ~FileAccessRef() { - if (f) memdelete(f); + if (f) + memdelete(f); } }; diff --git a/core/os/memory.h b/core/os/memory.h index dcaedd92ba..d377d54fad 100644 --- a/core/os/memory.h +++ b/core/os/memory.h @@ -130,9 +130,10 @@ void memdelete_allocator(T *p_class) { A::free(p_class); } -#define memdelete_notnull(m_v) \ - { \ - if (m_v) memdelete(m_v); \ +#define memdelete_notnull(m_v) \ + { \ + if (m_v) \ + memdelete(m_v); \ } #define memnew_arr(m_class, m_count) memnew_arr_template<m_class>(m_count) diff --git a/core/os/rw_lock.h b/core/os/rw_lock.h index 64dfbef20c..2ef4df9b70 100644 --- a/core/os/rw_lock.h +++ b/core/os/rw_lock.h @@ -58,10 +58,12 @@ class RWLockRead { public: RWLockRead(const RWLock *p_lock) { lock = const_cast<RWLock *>(p_lock); - if (lock) lock->read_lock(); + if (lock) + lock->read_lock(); } ~RWLockRead() { - if (lock) lock->read_unlock(); + if (lock) + lock->read_unlock(); } }; @@ -72,10 +74,12 @@ class RWLockWrite { public: RWLockWrite(RWLock *p_lock) { lock = p_lock; - if (lock) lock->write_lock(); + if (lock) + lock->write_lock(); } ~RWLockWrite() { - if (lock) lock->write_unlock(); + if (lock) + lock->write_unlock(); } }; diff --git a/core/pool_allocator.cpp b/core/pool_allocator.cpp index b74540395c..8fd67a47d2 100644 --- a/core/pool_allocator.cpp +++ b/core/pool_allocator.cpp @@ -182,7 +182,8 @@ PoolAllocator::ID PoolAllocator::alloc(int p_size) { ERR_FAIL_COND_V(p_size < 1, POOL_ALLOCATOR_INVALID_ID); #ifdef DEBUG_ENABLED - if (p_size > free_mem) OS::get_singleton()->debug_break(); + if (p_size > free_mem) + OS::get_singleton()->debug_break(); #endif ERR_FAIL_COND_V(p_size > free_mem, POOL_ALLOCATOR_INVALID_ID); diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 23f549be1a..4cf7e45205 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -233,8 +233,8 @@ void register_core_settings() { GLOBAL_DEF_RST("network/limits/packet_peer_stream/max_buffer_po2", (16)); ProjectSettings::get_singleton()->set_custom_property_info("network/limits/packet_peer_stream/max_buffer_po2", PropertyInfo(Variant::INT, "network/limits/packet_peer_stream/max_buffer_po2", PROPERTY_HINT_RANGE, "0,64,1,or_greater")); - GLOBAL_DEF("network/ssl/certificates", ""); - ProjectSettings::get_singleton()->set_custom_property_info("network/ssl/certificates", PropertyInfo(Variant::STRING, "network/ssl/certificates", PROPERTY_HINT_FILE, "*.crt")); + GLOBAL_DEF("network/ssl/certificate_bundle_override", ""); + ProjectSettings::get_singleton()->set_custom_property_info("network/ssl/certificate_bundle_override", PropertyInfo(Variant::STRING, "network/ssl/certificate_bundle_override", PROPERTY_HINT_FILE, "*.crt")); } void register_core_singletons() { diff --git a/core/self_list.h b/core/self_list.h index 19d2783208..2c44b0caec 100644 --- a/core/self_list.h +++ b/core/self_list.h @@ -120,6 +120,10 @@ private: public: _FORCE_INLINE_ bool in_list() const { return _root; } + _FORCE_INLINE_ void remove_from_list() { + if (_root) + _root->remove(this); + } _FORCE_INLINE_ SelfList<T> *next() { return _next; } _FORCE_INLINE_ SelfList<T> *prev() { return _prev; } _FORCE_INLINE_ const SelfList<T> *next() const { return _next; } diff --git a/core/translation.cpp b/core/translation.cpp index 3f45bb17c9..5f31bc7399 100644 --- a/core/translation.cpp +++ b/core/translation.cpp @@ -989,7 +989,8 @@ String TranslationServer::get_locale() const { String TranslationServer::get_locale_name(const String &p_locale) const { - if (!locale_name_map.has(p_locale)) return String(); + if (!locale_name_map.has(p_locale)) + return String(); return locale_name_map[p_locale]; } diff --git a/core/typed_array.cpp b/core/typed_array.cpp index 55e45f0b3f..a655a1b563 100644 --- a/core/typed_array.cpp +++ b/core/typed_array.cpp @@ -1 +1,31 @@ +/*************************************************************************/ +/* typed_array.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + #include "typed_array.h" diff --git a/core/typed_array.h b/core/typed_array.h index 5e95e81ea3..2c7b7e0384 100644 --- a/core/typed_array.h +++ b/core/typed_array.h @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* typed_array.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + #ifndef TYPED_ARRAY_H #define TYPED_ARRAY_H diff --git a/core/ustring.cpp b/core/ustring.cpp index fbe3fcb1b2..3e8a1ddbe3 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -548,8 +548,8 @@ signed char String::naturalnocasecmp_to(const String &p_str) const { return -1; /* Compare the numbers */ - this_int = to_int(this_str); - that_int = to_int(that_str); + this_int = to_int(this_str, -1, true); + that_int = to_int(that_str, -1, true); if (this_int < that_int) return -1; @@ -1882,7 +1882,8 @@ bool String::is_numeric() const { }; int s = 0; - if (operator[](0) == '-') ++s; + if (operator[](0) == '-') + ++s; bool dot = false; for (int i = s; i < length(); i++) { @@ -2137,7 +2138,7 @@ double String::to_double(const CharType *p_str, const CharType **r_end) { return built_in_strtod<CharType>(p_str, (CharType **)r_end); } -int64_t String::to_int(const CharType *p_str, int p_len) { +int64_t String::to_int(const CharType *p_str, int p_len, bool p_clamp) { if (p_len == 0 || !p_str[0]) return 0; @@ -2181,7 +2182,15 @@ int64_t String::to_int(const CharType *p_str, int p_len) { while (*str && str != limit) { number += *(str++); } - ERR_FAIL_V_MSG(sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + number + " as integer, provided value is " + (sign == 1 ? "too big." : "too small.")); + if (p_clamp) { + if (sign == 1) { + return INT64_MAX; + } else { + return INT64_MIN; + } + } else { + ERR_FAIL_V_MSG(sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + number + " as integer, provided value is " + (sign == 1 ? "too big." : "too small.")); + } } integer *= 10; integer += c - '0'; @@ -4182,9 +4191,14 @@ String String::sprintf(const Array &values, bool *error) const { int base = 16; bool capitalize = false; switch (c) { - case 'd': base = 10; break; - case 'o': base = 8; break; - case 'x': break; + case 'd': + base = 10; + break; + case 'o': + base = 8; + break; + case 'x': + break; case 'X': base = 16; capitalize = true; diff --git a/core/ustring.h b/core/ustring.h index ee7e3b1e16..15bc2b323c 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -254,7 +254,7 @@ public: static int 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); + static int64_t to_int(const CharType *p_str, int p_len = -1, bool p_clamp = false); String capitalize() const; String camelcase_to_underscore(bool lowercase = true) const; diff --git a/core/variant.cpp b/core/variant.cpp index a91876dd98..2eacb5d58c 100644 --- a/core/variant.cpp +++ b/core/variant.cpp @@ -1406,20 +1406,47 @@ void Variant::reference(const Variant &p_variant) { void Variant::zero() { switch (type) { - case NIL: break; - case BOOL: this->_data._bool = false; break; - case INT: this->_data._int = 0; break; - case FLOAT: this->_data._float = 0; break; - case VECTOR2: *reinterpret_cast<Vector2 *>(this->_data._mem) = Vector2(); break; - case VECTOR2I: *reinterpret_cast<Vector2i *>(this->_data._mem) = Vector2i(); break; - case RECT2: *reinterpret_cast<Rect2 *>(this->_data._mem) = Rect2(); break; - case RECT2I: *reinterpret_cast<Rect2i *>(this->_data._mem) = Rect2i(); break; - case VECTOR3: *reinterpret_cast<Vector3 *>(this->_data._mem) = Vector3(); break; - case VECTOR3I: *reinterpret_cast<Vector3i *>(this->_data._mem) = Vector3i(); break; - case PLANE: *reinterpret_cast<Plane *>(this->_data._mem) = Plane(); break; - case QUAT: *reinterpret_cast<Quat *>(this->_data._mem) = Quat(); break; - case COLOR: *reinterpret_cast<Color *>(this->_data._mem) = Color(); break; - default: this->clear(); break; + case NIL: + break; + case BOOL: + this->_data._bool = false; + break; + case INT: + this->_data._int = 0; + break; + case FLOAT: + this->_data._float = 0; + break; + case VECTOR2: + *reinterpret_cast<Vector2 *>(this->_data._mem) = Vector2(); + break; + case VECTOR2I: + *reinterpret_cast<Vector2i *>(this->_data._mem) = Vector2i(); + break; + case RECT2: + *reinterpret_cast<Rect2 *>(this->_data._mem) = Rect2(); + break; + case RECT2I: + *reinterpret_cast<Rect2i *>(this->_data._mem) = Rect2i(); + break; + case VECTOR3: + *reinterpret_cast<Vector3 *>(this->_data._mem) = Vector3(); + break; + case VECTOR3I: + *reinterpret_cast<Vector3i *>(this->_data._mem) = Vector3i(); + break; + case PLANE: + *reinterpret_cast<Plane *>(this->_data._mem) = Plane(); + break; + case QUAT: + *reinterpret_cast<Quat *>(this->_data._mem) = Quat(); + break; + case COLOR: + *reinterpret_cast<Color *>(this->_data._mem) = Color(); + break; + default: + this->clear(); + break; } } @@ -1545,11 +1572,16 @@ Variant::operator signed int() const { switch (type) { - case NIL: return 0; - case BOOL: return _data._bool ? 1 : 0; - case INT: return _data._int; - case FLOAT: return _data._float; - case STRING: return operator String().to_int(); + case NIL: + return 0; + case BOOL: + return _data._bool ? 1 : 0; + case INT: + return _data._int; + case FLOAT: + return _data._float; + case STRING: + return operator String().to_int(); default: { return 0; @@ -1560,11 +1592,16 @@ Variant::operator unsigned int() const { switch (type) { - case NIL: return 0; - case BOOL: return _data._bool ? 1 : 0; - case INT: return _data._int; - case FLOAT: return _data._float; - case STRING: return operator String().to_int(); + case NIL: + return 0; + case BOOL: + return _data._bool ? 1 : 0; + case INT: + return _data._int; + case FLOAT: + return _data._float; + case STRING: + return operator String().to_int(); default: { return 0; @@ -1576,11 +1613,16 @@ Variant::operator int64_t() const { switch (type) { - case NIL: return 0; - case BOOL: return _data._bool ? 1 : 0; - case INT: return _data._int; - case FLOAT: return _data._float; - case STRING: return operator String().to_int64(); + case NIL: + return 0; + case BOOL: + return _data._bool ? 1 : 0; + case INT: + return _data._int; + case FLOAT: + return _data._float; + case STRING: + return operator String().to_int64(); default: { return 0; @@ -1612,11 +1654,16 @@ Variant::operator uint64_t() const { switch (type) { - case NIL: return 0; - case BOOL: return _data._bool ? 1 : 0; - case INT: return _data._int; - case FLOAT: return _data._float; - case STRING: return operator String().to_int(); + case NIL: + return 0; + case BOOL: + return _data._bool ? 1 : 0; + case INT: + return _data._int; + case FLOAT: + return _data._float; + case STRING: + return operator String().to_int(); default: { return 0; @@ -1639,11 +1686,16 @@ Variant::operator signed long() const { switch (type) { - case NIL: return 0; - case BOOL: return _data._bool ? 1 : 0; - case INT: return _data._int; - case FLOAT: return _data._real; - case STRING: return operator String().to_int(); + case NIL: + return 0; + case BOOL: + return _data._bool ? 1 : 0; + case INT: + return _data._int; + case FLOAT: + return _data._real; + case STRING: + return operator String().to_int(); default: { return 0; @@ -1657,11 +1709,16 @@ Variant::operator unsigned long() const { switch (type) { - case NIL: return 0; - case BOOL: return _data._bool ? 1 : 0; - case INT: return _data._int; - case FLOAT: return _data._real; - case STRING: return operator String().to_int(); + case NIL: + return 0; + case BOOL: + return _data._bool ? 1 : 0; + case INT: + return _data._int; + case FLOAT: + return _data._real; + case STRING: + return operator String().to_int(); default: { return 0; @@ -1676,11 +1733,16 @@ Variant::operator signed short() const { switch (type) { - case NIL: return 0; - case BOOL: return _data._bool ? 1 : 0; - case INT: return _data._int; - case FLOAT: return _data._float; - case STRING: return operator String().to_int(); + case NIL: + return 0; + case BOOL: + return _data._bool ? 1 : 0; + case INT: + return _data._int; + case FLOAT: + return _data._float; + case STRING: + return operator String().to_int(); default: { return 0; @@ -1691,11 +1753,16 @@ Variant::operator unsigned short() const { switch (type) { - case NIL: return 0; - case BOOL: return _data._bool ? 1 : 0; - case INT: return _data._int; - case FLOAT: return _data._float; - case STRING: return operator String().to_int(); + case NIL: + return 0; + case BOOL: + return _data._bool ? 1 : 0; + case INT: + return _data._int; + case FLOAT: + return _data._float; + case STRING: + return operator String().to_int(); default: { return 0; @@ -1706,11 +1773,16 @@ Variant::operator signed char() const { switch (type) { - case NIL: return 0; - case BOOL: return _data._bool ? 1 : 0; - case INT: return _data._int; - case FLOAT: return _data._float; - case STRING: return operator String().to_int(); + case NIL: + return 0; + case BOOL: + return _data._bool ? 1 : 0; + case INT: + return _data._int; + case FLOAT: + return _data._float; + case STRING: + return operator String().to_int(); default: { return 0; @@ -1721,11 +1793,16 @@ Variant::operator unsigned char() const { switch (type) { - case NIL: return 0; - case BOOL: return _data._bool ? 1 : 0; - case INT: return _data._int; - case FLOAT: return _data._float; - case STRING: return operator String().to_int(); + case NIL: + return 0; + case BOOL: + return _data._bool ? 1 : 0; + case INT: + return _data._int; + case FLOAT: + return _data._float; + case STRING: + return operator String().to_int(); default: { return 0; @@ -1742,11 +1819,16 @@ Variant::operator float() const { switch (type) { - case NIL: return 0; - case BOOL: return _data._bool ? 1.0 : 0.0; - case INT: return (float)_data._int; - case FLOAT: return _data._float; - case STRING: return operator String().to_double(); + case NIL: + return 0; + case BOOL: + return _data._bool ? 1.0 : 0.0; + case INT: + return (float)_data._int; + case FLOAT: + return _data._float; + case STRING: + return operator String().to_double(); default: { return 0; @@ -1757,11 +1839,16 @@ Variant::operator double() const { switch (type) { - case NIL: return 0; - case BOOL: return _data._bool ? 1.0 : 0.0; - case INT: return (double)_data._int; - case FLOAT: return _data._float; - case STRING: return operator String().to_double(); + case NIL: + return 0; + case BOOL: + return _data._bool ? 1.0 : 0.0; + case INT: + return (double)_data._int; + case FLOAT: + return _data._float; + case STRING: + return operator String().to_double(); default: { return 0; @@ -1800,27 +1887,40 @@ Variant::operator String() const { String Variant::stringify(List<const void *> &stack) const { switch (type) { - case NIL: return "Null"; - case BOOL: return _data._bool ? "True" : "False"; - case INT: return itos(_data._int); - case FLOAT: return rtos(_data._float); - case STRING: return *reinterpret_cast<const String *>(_data._mem); - case VECTOR2: return "(" + operator Vector2() + ")"; - case VECTOR2I: return "(" + operator Vector2i() + ")"; - case RECT2: return "(" + operator Rect2() + ")"; - case RECT2I: return "(" + operator Rect2i() + ")"; + case NIL: + return "Null"; + case BOOL: + return _data._bool ? "True" : "False"; + case INT: + return itos(_data._int); + case FLOAT: + return rtos(_data._float); + case STRING: + return *reinterpret_cast<const String *>(_data._mem); + case VECTOR2: + return "(" + operator Vector2() + ")"; + case VECTOR2I: + return "(" + operator Vector2i() + ")"; + case RECT2: + return "(" + operator Rect2() + ")"; + case RECT2I: + return "(" + operator Rect2i() + ")"; case TRANSFORM2D: { Transform2D mat32 = operator Transform2D(); return "(" + Variant(mat32.elements[0]).operator String() + ", " + Variant(mat32.elements[1]).operator String() + ", " + Variant(mat32.elements[2]).operator String() + ")"; } break; - case VECTOR3: return "(" + operator Vector3() + ")"; - case VECTOR3I: return "(" + operator Vector3i() + ")"; + case VECTOR3: + return "(" + operator Vector3() + ")"; + case VECTOR3I: + return "(" + operator Vector3i() + ")"; case PLANE: return operator Plane(); //case QUAT: - case AABB: return operator ::AABB(); - case QUAT: return "(" + operator Quat() + ")"; + case AABB: + return operator ::AABB(); + case QUAT: + return "(" + operator Quat() + ")"; case BASIS: { Basis mat3 = operator Basis(); @@ -1846,10 +1946,14 @@ String Variant::stringify(List<const void *> &stack) const { return mtx + ")"; } break; - case TRANSFORM: return operator Transform(); - case STRING_NAME: return operator StringName(); - case NODE_PATH: return operator NodePath(); - case COLOR: return String::num(operator Color().r) + "," + String::num(operator Color().g) + "," + String::num(operator Color().b) + "," + String::num(operator Color().a); + case TRANSFORM: + return operator Transform(); + case STRING_NAME: + return operator StringName(); + case NODE_PATH: + return operator NodePath(); + case COLOR: + return String::num(operator Color().r) + "," + String::num(operator Color().g) + "," + String::num(operator Color().b) + "," + String::num(operator Color().a); case DICTIONARY: { const Dictionary &d = *reinterpret_cast<const Dictionary *>(_data._mem); @@ -3676,9 +3780,12 @@ bool Variant::is_shared() const { switch (type) { - case OBJECT: return true; - case ARRAY: return true; - case DICTIONARY: return true; + case OBJECT: + return true; + case ARRAY: + return true; + case DICTIONARY: + return true; default: { } } diff --git a/core/variant.h b/core/variant.h index 1ae09ad82f..8e924be00a 100644 --- a/core/variant.h +++ b/core/variant.h @@ -474,7 +474,8 @@ public: type = NIL; } _FORCE_INLINE_ ~Variant() { - if (type != Variant::NIL) clear(); + if (type != Variant::NIL) + clear(); } }; diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 9fffb42ff6..416a1a5fb8 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -262,6 +262,7 @@ struct _VariantCall { VCALL_LOCALMEM3R(String, split); VCALL_LOCALMEM3R(String, rsplit); VCALL_LOCALMEM2R(String, split_floats); + VCALL_LOCALMEM1R(String, join); VCALL_LOCALMEM0R(String, to_upper); VCALL_LOCALMEM0R(String, to_lower); VCALL_LOCALMEM1R(String, left); @@ -861,9 +862,15 @@ struct _VariantCall { static void _call_Transform2D_xform(Variant &r_ret, Variant &p_self, const Variant **p_args) { switch (p_args[0]->type) { - case Variant::VECTOR2: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform(p_args[0]->operator Vector2()); return; - case Variant::RECT2: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform(p_args[0]->operator Rect2()); return; - case Variant::PACKED_VECTOR2_ARRAY: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform(p_args[0]->operator PackedVector2Array()); return; + case Variant::VECTOR2: + r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform(p_args[0]->operator Vector2()); + return; + case Variant::RECT2: + r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform(p_args[0]->operator Rect2()); + return; + case Variant::PACKED_VECTOR2_ARRAY: + r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform(p_args[0]->operator PackedVector2Array()); + return; default: r_ret = Variant(); ERR_PRINT("Invalid type in function 'xform' in base 'Transform2D'. Valid types are Vector2, Rect2, and PackedVector2Array."); @@ -872,9 +879,15 @@ struct _VariantCall { static void _call_Transform2D_xform_inv(Variant &r_ret, Variant &p_self, const Variant **p_args) { switch (p_args[0]->type) { - case Variant::VECTOR2: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Vector2()); return; - case Variant::RECT2: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Rect2()); return; - case Variant::PACKED_VECTOR2_ARRAY: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform_inv(p_args[0]->operator PackedVector2Array()); return; + case Variant::VECTOR2: + r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Vector2()); + return; + case Variant::RECT2: + r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Rect2()); + return; + case Variant::PACKED_VECTOR2_ARRAY: + r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform_inv(p_args[0]->operator PackedVector2Array()); + return; default: r_ret = Variant(); ERR_PRINT("Invalid type in function 'xform_inv' in base 'Transform2D'. Valid types are Vector2, Rect2, and PackedVector2Array."); @@ -883,7 +896,9 @@ struct _VariantCall { static void _call_Transform2D_basis_xform(Variant &r_ret, Variant &p_self, const Variant **p_args) { switch (p_args[0]->type) { - case Variant::VECTOR2: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->basis_xform(p_args[0]->operator Vector2()); return; + case Variant::VECTOR2: + r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->basis_xform(p_args[0]->operator Vector2()); + return; default: r_ret = Variant(); ERR_PRINT("Invalid type in function 'basis_xform' in base 'Transform2D'. Only Vector2 is valid."); @@ -892,7 +907,9 @@ struct _VariantCall { static void _call_Transform2D_basis_xform_inv(Variant &r_ret, Variant &p_self, const Variant **p_args) { switch (p_args[0]->type) { - case Variant::VECTOR2: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->basis_xform_inv(p_args[0]->operator Vector2()); return; + case Variant::VECTOR2: + r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->basis_xform_inv(p_args[0]->operator Vector2()); + return; default: r_ret = Variant(); ERR_PRINT("Invalid type in function 'basis_xform_inv' in base 'Transform2D'. Only Vector2 is valid."); @@ -929,10 +946,18 @@ struct _VariantCall { static void _call_Transform_xform(Variant &r_ret, Variant &p_self, const Variant **p_args) { switch (p_args[0]->type) { - case Variant::VECTOR3: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator Vector3()); return; - case Variant::PLANE: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator Plane()); return; - case Variant::AABB: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator ::AABB()); return; - case Variant::PACKED_VECTOR3_ARRAY: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator ::PackedVector3Array()); return; + case Variant::VECTOR3: + r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator Vector3()); + return; + case Variant::PLANE: + r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator Plane()); + return; + case Variant::AABB: + r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator ::AABB()); + return; + case Variant::PACKED_VECTOR3_ARRAY: + r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator ::PackedVector3Array()); + return; default: r_ret = Variant(); ERR_PRINT("Invalid type in function 'xform' in base 'Transform'. Valid types are Vector3, Plane, AABB, and PackedVector3Array."); @@ -941,10 +966,18 @@ struct _VariantCall { static void _call_Transform_xform_inv(Variant &r_ret, Variant &p_self, const Variant **p_args) { switch (p_args[0]->type) { - case Variant::VECTOR3: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Vector3()); return; - case Variant::PLANE: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Plane()); return; - case Variant::AABB: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator ::AABB()); return; - case Variant::PACKED_VECTOR3_ARRAY: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator ::PackedVector3Array()); return; + case Variant::VECTOR3: + r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Vector3()); + return; + case Variant::PLANE: + r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Plane()); + return; + case Variant::AABB: + r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator ::AABB()); + return; + case Variant::PACKED_VECTOR3_ARRAY: + r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator ::PackedVector3Array()); + return; default: r_ret = Variant(); ERR_PRINT("Invalid type in function 'xform_inv' in base 'Transform'. Valid types are Vector3, Plane, AABB, and PackedVector3Array."); @@ -1280,50 +1313,74 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i return Variant(); // atomic types - case BOOL: return Variant(false); - case INT: return 0; - case FLOAT: return 0.0f; + case BOOL: + return Variant(false); + case INT: + return 0; + case FLOAT: + return 0.0f; case STRING: return String(); // math types case VECTOR2: return Vector2(); - case RECT2: return Rect2(); - case VECTOR3: return Vector3(); - case TRANSFORM2D: return Transform2D(); - case PLANE: return Plane(); - case QUAT: return Quat(); + case RECT2: + return Rect2(); + case VECTOR3: + return Vector3(); + case TRANSFORM2D: + return Transform2D(); + case PLANE: + return Plane(); + case QUAT: + return Quat(); case AABB: return ::AABB(); - case BASIS: return Basis(); + case BASIS: + return Basis(); case TRANSFORM: return Transform(); // misc types - case COLOR: return Color(); + case COLOR: + return Color(); case STRING_NAME: return StringName(); case NODE_PATH: return NodePath(); - case _RID: return RID(); - case OBJECT: return (Object *)nullptr; - case CALLABLE: return Callable(); - case SIGNAL: return Signal(); - case DICTIONARY: return Dictionary(); + case _RID: + return RID(); + case OBJECT: + return (Object *)nullptr; + case CALLABLE: + return Callable(); + case SIGNAL: + return Signal(); + case DICTIONARY: + return Dictionary(); case ARRAY: return Array(); - case PACKED_BYTE_ARRAY: return PackedByteArray(); - case PACKED_INT32_ARRAY: return PackedInt32Array(); - case PACKED_INT64_ARRAY: return PackedInt64Array(); - case PACKED_FLOAT32_ARRAY: return PackedFloat32Array(); - case PACKED_FLOAT64_ARRAY: return PackedFloat64Array(); - case PACKED_STRING_ARRAY: return PackedStringArray(); + case PACKED_BYTE_ARRAY: + return PackedByteArray(); + case PACKED_INT32_ARRAY: + return PackedInt32Array(); + case PACKED_INT64_ARRAY: + return PackedInt64Array(); + case PACKED_FLOAT32_ARRAY: + return PackedFloat32Array(); + case PACKED_FLOAT64_ARRAY: + return PackedFloat64Array(); + case PACKED_STRING_ARRAY: + return PackedStringArray(); case PACKED_VECTOR2_ARRAY: return PackedVector2Array(); - case PACKED_VECTOR3_ARRAY: return PackedVector3Array(); - case PACKED_COLOR_ARRAY: return PackedColorArray(); - default: return Variant(); + case PACKED_VECTOR3_ARRAY: + return PackedVector3Array(); + case PACKED_COLOR_ARRAY: + return PackedColorArray(); + default: + return Variant(); } } else if (p_argcount == 1 && p_args[0]->type == p_type) { @@ -1354,46 +1411,68 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i case VECTOR2I: { return Vector2i(*p_args[0]); } - case RECT2: return (Rect2(*p_args[0])); - case RECT2I: return (Rect2i(*p_args[0])); - case VECTOR3: return (Vector3(*p_args[0])); - case VECTOR3I: return (Vector3i(*p_args[0])); + case RECT2: + return (Rect2(*p_args[0])); + case RECT2I: + return (Rect2i(*p_args[0])); + case VECTOR3: + return (Vector3(*p_args[0])); + case VECTOR3I: + return (Vector3i(*p_args[0])); case TRANSFORM2D: return (Transform2D(p_args[0]->operator Transform2D())); - case PLANE: return (Plane(*p_args[0])); - case QUAT: return (p_args[0]->operator Quat()); + case PLANE: + return (Plane(*p_args[0])); + case QUAT: + return (p_args[0]->operator Quat()); case AABB: return (::AABB(*p_args[0])); - case BASIS: return (Basis(p_args[0]->operator Basis())); + case BASIS: + return (Basis(p_args[0]->operator Basis())); case TRANSFORM: return (Transform(p_args[0]->operator Transform())); // misc types - case COLOR: return p_args[0]->type == Variant::STRING ? Color::html(*p_args[0]) : Color::hex(*p_args[0]); + case COLOR: + return p_args[0]->type == Variant::STRING ? Color::html(*p_args[0]) : Color::hex(*p_args[0]); case STRING_NAME: return (StringName(p_args[0]->operator StringName())); case NODE_PATH: return (NodePath(p_args[0]->operator NodePath())); - case _RID: return (RID(*p_args[0])); - case OBJECT: return ((Object *)(p_args[0]->operator Object *())); - case CALLABLE: return ((Callable)(p_args[0]->operator Callable())); - case SIGNAL: return ((Signal)(p_args[0]->operator Signal())); - case DICTIONARY: return p_args[0]->operator Dictionary(); + case _RID: + return (RID(*p_args[0])); + case OBJECT: + return ((Object *)(p_args[0]->operator Object *())); + case CALLABLE: + return ((Callable)(p_args[0]->operator Callable())); + case SIGNAL: + return ((Signal)(p_args[0]->operator Signal())); + case DICTIONARY: + return p_args[0]->operator Dictionary(); case ARRAY: return p_args[0]->operator Array(); // arrays - case PACKED_BYTE_ARRAY: return (PackedByteArray(*p_args[0])); - case PACKED_INT32_ARRAY: return (PackedInt32Array(*p_args[0])); - case PACKED_INT64_ARRAY: return (PackedInt64Array(*p_args[0])); - case PACKED_FLOAT32_ARRAY: return (PackedFloat32Array(*p_args[0])); - case PACKED_FLOAT64_ARRAY: return (PackedFloat64Array(*p_args[0])); - case PACKED_STRING_ARRAY: return (PackedStringArray(*p_args[0])); + case PACKED_BYTE_ARRAY: + return (PackedByteArray(*p_args[0])); + case PACKED_INT32_ARRAY: + return (PackedInt32Array(*p_args[0])); + case PACKED_INT64_ARRAY: + return (PackedInt64Array(*p_args[0])); + case PACKED_FLOAT32_ARRAY: + return (PackedFloat32Array(*p_args[0])); + case PACKED_FLOAT64_ARRAY: + return (PackedFloat64Array(*p_args[0])); + case PACKED_STRING_ARRAY: + return (PackedStringArray(*p_args[0])); case PACKED_VECTOR2_ARRAY: return (PackedVector2Array(*p_args[0])); - case PACKED_VECTOR3_ARRAY: return (PackedVector3Array(*p_args[0])); - case PACKED_COLOR_ARRAY: return (PackedColorArray(*p_args[0])); - default: return Variant(); + case PACKED_VECTOR3_ARRAY: + return (PackedVector3Array(*p_args[0])); + case PACKED_COLOR_ARRAY: + return (PackedColorArray(*p_args[0])); + default: + return Variant(); } } else if (p_argcount >= 1) { @@ -1738,6 +1817,7 @@ void register_variant_methods() { ADDFUNC3R(STRING, PACKED_STRING_ARRAY, String, split, STRING, "delimiter", BOOL, "allow_empty", INT, "maxsplit", varray(true, 0)); ADDFUNC3R(STRING, PACKED_STRING_ARRAY, String, rsplit, STRING, "delimiter", BOOL, "allow_empty", INT, "maxsplit", varray(true, 0)); ADDFUNC2R(STRING, PACKED_FLOAT32_ARRAY, String, split_floats, STRING, "delimiter", BOOL, "allow_empty", varray(true)); + ADDFUNC1R(STRING, STRING, String, join, PACKED_STRING_ARRAY, "parts", varray()); ADDFUNC0R(STRING, STRING, String, to_upper, varray()); ADDFUNC0R(STRING, STRING, String, to_lower, varray()); diff --git a/core/variant_op.cpp b/core/variant_op.cpp index 27624b81ee..4c9848f26a 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -78,38 +78,38 @@ #define TYPE(PREFIX, OP, TYPE) &&PREFIX##_##OP##_##TYPE /* clang-format off */ -#define TYPES(PREFIX, OP) { \ - TYPE(PREFIX, OP, NIL), \ - TYPE(PREFIX, OP, BOOL), \ - TYPE(PREFIX, OP, INT), \ - TYPE(PREFIX, OP, FLOAT), \ - TYPE(PREFIX, OP, STRING), \ - TYPE(PREFIX, OP, VECTOR2), \ - TYPE(PREFIX, OP, VECTOR2I), \ - TYPE(PREFIX, OP, RECT2), \ - TYPE(PREFIX, OP, RECT2I), \ - TYPE(PREFIX, OP, VECTOR3), \ - TYPE(PREFIX, OP, VECTOR3I), \ - TYPE(PREFIX, OP, TRANSFORM2D), \ - TYPE(PREFIX, OP, PLANE), \ - TYPE(PREFIX, OP, QUAT), \ - TYPE(PREFIX, OP, AABB), \ - TYPE(PREFIX, OP, BASIS), \ - TYPE(PREFIX, OP, TRANSFORM), \ - TYPE(PREFIX, OP, COLOR), \ +#define TYPES(PREFIX, OP) { \ + TYPE(PREFIX, OP, NIL), \ + TYPE(PREFIX, OP, BOOL), \ + TYPE(PREFIX, OP, INT), \ + TYPE(PREFIX, OP, FLOAT), \ + TYPE(PREFIX, OP, STRING), \ + TYPE(PREFIX, OP, VECTOR2), \ + TYPE(PREFIX, OP, VECTOR2I), \ + TYPE(PREFIX, OP, RECT2), \ + TYPE(PREFIX, OP, RECT2I), \ + TYPE(PREFIX, OP, VECTOR3), \ + TYPE(PREFIX, OP, VECTOR3I), \ + TYPE(PREFIX, OP, TRANSFORM2D), \ + TYPE(PREFIX, OP, PLANE), \ + TYPE(PREFIX, OP, QUAT), \ + TYPE(PREFIX, OP, AABB), \ + TYPE(PREFIX, OP, BASIS), \ + TYPE(PREFIX, OP, TRANSFORM), \ + TYPE(PREFIX, OP, COLOR), \ TYPE(PREFIX, OP, STRING_NAME), \ - TYPE(PREFIX, OP, NODE_PATH), \ - TYPE(PREFIX, OP, _RID), \ - TYPE(PREFIX, OP, OBJECT), \ + TYPE(PREFIX, OP, NODE_PATH), \ + TYPE(PREFIX, OP, _RID), \ + TYPE(PREFIX, OP, OBJECT), \ TYPE(PREFIX, OP, CALLABLE), \ - TYPE(PREFIX, OP, SIGNAL), \ - TYPE(PREFIX, OP, DICTIONARY), \ - TYPE(PREFIX, OP, ARRAY), \ + TYPE(PREFIX, OP, SIGNAL), \ + TYPE(PREFIX, OP, DICTIONARY), \ + TYPE(PREFIX, OP, ARRAY), \ TYPE(PREFIX, OP, PACKED_BYTE_ARRAY), \ - TYPE(PREFIX, OP, PACKED_INT32_ARRAY), \ - TYPE(PREFIX, OP, PACKED_INT64_ARRAY), \ - TYPE(PREFIX, OP, PACKED_FLOAT32_ARRAY), \ - TYPE(PREFIX, OP, PACKED_FLOAT64_ARRAY), \ + TYPE(PREFIX, OP, PACKED_INT32_ARRAY), \ + TYPE(PREFIX, OP, PACKED_INT64_ARRAY), \ + TYPE(PREFIX, OP, PACKED_FLOAT32_ARRAY), \ + TYPE(PREFIX, OP, PACKED_FLOAT64_ARRAY), \ TYPE(PREFIX, OP, PACKED_STRING_ARRAY), \ TYPE(PREFIX, OP, PACKED_VECTOR2_ARRAY), \ TYPE(PREFIX, OP, PACKED_VECTOR3_ARRAY), \ @@ -181,21 +181,26 @@ bool Variant::booleanize() const { return; \ } -#define DEFAULT_OP_NUM(m_prefix, m_op_name, m_name, m_op, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == INT) _RETURN(p_a._data.m_type m_op p_b._data._int); \ - if (p_b.type == FLOAT) _RETURN(p_a._data.m_type m_op p_b._data._float); \ - \ - _RETURN_FAIL \ +#define DEFAULT_OP_NUM(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + if (p_b.type == INT) \ + _RETURN(p_a._data.m_type m_op p_b._data._int); \ + if (p_b.type == FLOAT) \ + _RETURN(p_a._data.m_type m_op p_b._data._float); \ + \ + _RETURN_FAIL \ }; -#define DEFAULT_OP_NUM_NULL(m_prefix, m_op_name, m_name, m_op, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == INT) _RETURN(p_a._data.m_type m_op p_b._data._int); \ - if (p_b.type == FLOAT) _RETURN(p_a._data.m_type m_op p_b._data._float); \ - if (p_b.type == NIL) _RETURN(!(p_b.type m_op NIL)); \ - \ - _RETURN_FAIL \ +#define DEFAULT_OP_NUM_NULL(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + if (p_b.type == INT) \ + _RETURN(p_a._data.m_type m_op p_b._data._int); \ + if (p_b.type == FLOAT) \ + _RETURN(p_a._data.m_type m_op p_b._data._float); \ + if (p_b.type == NIL) \ + _RETURN(!(p_b.type m_op NIL)); \ + \ + _RETURN_FAIL \ }; #ifdef DEBUG_ENABLED @@ -219,12 +224,14 @@ bool Variant::booleanize() const { _RETURN_FAIL \ }; #else -#define DEFAULT_OP_NUM_DIV(m_prefix, m_op_name, m_name, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == INT) _RETURN(p_a._data.m_type / p_b._data._int); \ - if (p_b.type == FLOAT) _RETURN(p_a._data.m_type / p_b._data._float); \ - \ - _RETURN_FAIL \ +#define DEFAULT_OP_NUM_DIV(m_prefix, m_op_name, m_name, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + if (p_b.type == INT) \ + _RETURN(p_a._data.m_type / p_b._data._int); \ + if (p_b.type == FLOAT) \ + _RETURN(p_a._data.m_type / p_b._data._float); \ + \ + _RETURN_FAIL \ }; #endif @@ -238,62 +245,84 @@ bool Variant::booleanize() const { _RETURN(p_a._data.m_type); \ }; -#define DEFAULT_OP_NUM_VEC(m_prefix, m_op_name, m_name, m_op, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == INT) _RETURN(p_a._data.m_type m_op p_b._data._int); \ - if (p_b.type == FLOAT) _RETURN(p_a._data.m_type m_op p_b._data._float); \ - if (p_b.type == VECTOR2) _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2 *>(p_b._data._mem)); \ - if (p_b.type == VECTOR3) _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector3 *>(p_b._data._mem)); \ - if (p_b.type == VECTOR2I) _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2 *>(p_b._data._mem)); \ - if (p_b.type == VECTOR3I) _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector3 *>(p_b._data._mem)); \ - \ - _RETURN_FAIL \ +#define DEFAULT_OP_NUM_VEC(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + if (p_b.type == INT) \ + _RETURN(p_a._data.m_type m_op p_b._data._int); \ + if (p_b.type == FLOAT) \ + _RETURN(p_a._data.m_type m_op p_b._data._float); \ + if (p_b.type == VECTOR2) \ + _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2 *>(p_b._data._mem)); \ + if (p_b.type == VECTOR3) \ + _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector3 *>(p_b._data._mem)); \ + if (p_b.type == VECTOR2I) \ + _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2 *>(p_b._data._mem)); \ + if (p_b.type == VECTOR3I) \ + _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector3 *>(p_b._data._mem)); \ + \ + _RETURN_FAIL \ }; -#define DEFAULT_OP_STR_REV(m_prefix, m_op_name, m_name, m_op, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == STRING) _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const String *>(p_a._data._mem)); \ - if (p_b.type == STRING_NAME) _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const StringName *>(p_a._data._mem)); \ - if (p_b.type == NODE_PATH) _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const NodePath *>(p_a._data._mem)); \ - \ - _RETURN_FAIL \ +#define DEFAULT_OP_STR_REV(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + if (p_b.type == STRING) \ + _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const String *>(p_a._data._mem)); \ + if (p_b.type == STRING_NAME) \ + _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const StringName *>(p_a._data._mem)); \ + if (p_b.type == NODE_PATH) \ + _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const NodePath *>(p_a._data._mem)); \ + \ + _RETURN_FAIL \ }; -#define DEFAULT_OP_STR(m_prefix, m_op_name, m_name, m_op, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == STRING) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \ - if (p_b.type == STRING_NAME) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const StringName *>(p_b._data._mem)); \ - if (p_b.type == NODE_PATH) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \ - \ - _RETURN_FAIL \ +#define DEFAULT_OP_STR(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + if (p_b.type == STRING) \ + _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \ + if (p_b.type == STRING_NAME) \ + _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const StringName *>(p_b._data._mem)); \ + if (p_b.type == NODE_PATH) \ + _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \ + \ + _RETURN_FAIL \ }; -#define DEFAULT_OP_STR_NULL(m_prefix, m_op_name, m_name, m_op, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == STRING) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \ - if (p_b.type == STRING_NAME) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const StringName *>(p_b._data._mem)); \ - if (p_b.type == NODE_PATH) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \ - if (p_b.type == NIL) _RETURN(!(p_b.type m_op NIL)); \ - \ - _RETURN_FAIL \ +#define DEFAULT_OP_STR_NULL(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + if (p_b.type == STRING) \ + _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \ + if (p_b.type == STRING_NAME) \ + _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const StringName *>(p_b._data._mem)); \ + if (p_b.type == NODE_PATH) \ + _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \ + if (p_b.type == NIL) \ + _RETURN(!(p_b.type m_op NIL)); \ + \ + _RETURN_FAIL \ }; -#define DEFAULT_OP_STR_NULL_NP(m_prefix, m_op_name, m_name, m_op, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == STRING) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \ - if (p_b.type == NODE_PATH) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \ - if (p_b.type == NIL) _RETURN(!(p_b.type m_op NIL)); \ - \ - _RETURN_FAIL \ +#define DEFAULT_OP_STR_NULL_NP(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + if (p_b.type == STRING) \ + _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \ + if (p_b.type == NODE_PATH) \ + _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \ + if (p_b.type == NIL) \ + _RETURN(!(p_b.type m_op NIL)); \ + \ + _RETURN_FAIL \ }; -#define DEFAULT_OP_STR_NULL_SN(m_prefix, m_op_name, m_name, m_op, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == STRING) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \ - if (p_b.type == STRING_NAME) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const StringName *>(p_b._data._mem)); \ - if (p_b.type == NIL) _RETURN(!(p_b.type m_op NIL)); \ - \ - _RETURN_FAIL \ +#define DEFAULT_OP_STR_NULL_SN(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + if (p_b.type == STRING) \ + _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \ + if (p_b.type == STRING_NAME) \ + _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const StringName *>(p_b._data._mem)); \ + if (p_b.type == NIL) \ + _RETURN(!(p_b.type m_op NIL)); \ + \ + _RETURN_FAIL \ }; #define DEFAULT_OP_LOCALMEM_REV(m_prefix, m_op_name, m_name, m_op, m_type) \ @@ -332,13 +361,16 @@ bool Variant::booleanize() const { _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem)); \ } -#define DEFAULT_OP_LOCALMEM_NUM(m_prefix, m_op_name, m_name, m_op, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == m_name) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const m_type *>(p_b._data._mem)); \ - if (p_b.type == INT) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._int); \ - if (p_b.type == FLOAT) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._float); \ - \ - _RETURN_FAIL \ +#define DEFAULT_OP_LOCALMEM_NUM(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + if (p_b.type == m_name) \ + _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const m_type *>(p_b._data._mem)); \ + if (p_b.type == INT) \ + _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._int); \ + if (p_b.type == FLOAT) \ + _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._float); \ + \ + _RETURN_FAIL \ } #define DEFAULT_OP_PTR(m_op, m_name, m_sub) \ @@ -436,7 +468,8 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, SWITCH(math, p_op, p_a.type) { SWITCH_OP(math, OP_EQUAL, p_a.type) { CASE_TYPE(math, OP_EQUAL, NIL) { - if (p_b.type == NIL) _RETURN(true); + if (p_b.type == NIL) + _RETURN(true); if (p_b.type == OBJECT) _RETURN(p_b._get_obj().obj == nullptr); @@ -532,7 +565,8 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, SWITCH_OP(math, OP_NOT_EQUAL, p_a.type) { CASE_TYPE(math, OP_NOT_EQUAL, NIL) { - if (p_b.type == NIL) _RETURN(false); + if (p_b.type == NIL) + _RETURN(false); if (p_b.type == OBJECT) _RETURN(p_b._get_obj().obj != nullptr); @@ -981,7 +1015,8 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, case VECTOR2: { _RETURN(p_a._data._transform2d->xform(*(const Vector2 *)p_b._data._mem)); } - default: _RETURN_FAIL; + default: + _RETURN_FAIL; } } @@ -996,7 +1031,8 @@ 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); } - default: _RETURN_FAIL; + default: + _RETURN_FAIL; } } @@ -1008,7 +1044,8 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, case BASIS: { _RETURN(*p_a._data._basis * *p_b._data._basis); } - default: _RETURN_FAIL; + default: + _RETURN_FAIL; } } @@ -1020,7 +1057,8 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, case TRANSFORM: { _RETURN(*p_a._data._transform * *p_b._data._transform); } - default: _RETURN_FAIL; + default: + _RETURN_FAIL; } } @@ -1983,7 +2021,8 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const { #define DEFAULT_OP_DVECTOR_SET(m_name, m_type, skip_cond) \ case m_name: { \ - if (skip_cond) return; \ + if (skip_cond) \ + return; \ \ if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { \ int index = p_index; \ @@ -3458,17 +3497,39 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const { return _data._float > 0.0; } break; case VECTOR2: { - int64_t from = reinterpret_cast<const Vector2 *>(_data._mem)->x; - int64_t to = reinterpret_cast<const Vector2 *>(_data._mem)->y; + double from = reinterpret_cast<const Vector2 *>(_data._mem)->x; + double to = reinterpret_cast<const Vector2 *>(_data._mem)->y; + + r_iter = from; + + return from < to; + } break; + case VECTOR2I: { + int64_t from = reinterpret_cast<const Vector2i *>(_data._mem)->x; + int64_t to = reinterpret_cast<const Vector2i *>(_data._mem)->y; r_iter = from; return from < to; } break; case VECTOR3: { - int64_t from = reinterpret_cast<const Vector3 *>(_data._mem)->x; - int64_t to = reinterpret_cast<const Vector3 *>(_data._mem)->y; - int64_t step = reinterpret_cast<const Vector3 *>(_data._mem)->z; + double from = reinterpret_cast<const Vector3 *>(_data._mem)->x; + double to = reinterpret_cast<const Vector3 *>(_data._mem)->y; + double step = reinterpret_cast<const Vector3 *>(_data._mem)->z; + + r_iter = from; + + if (from == to) { + return false; + } else if (from < to) { + return step > 0; + } + return step < 0; + } break; + case VECTOR3I: { + int64_t from = reinterpret_cast<const Vector3i *>(_data._mem)->x; + int64_t to = reinterpret_cast<const Vector3i *>(_data._mem)->y; + int64_t step = reinterpret_cast<const Vector3i *>(_data._mem)->z; r_iter = from; @@ -3476,10 +3537,8 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const { return false; } else if (from < to) { return step > 0; - } else { - return step < 0; } - //return true; + return step < 0; } break; case OBJECT: { @@ -3640,7 +3699,19 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const { return true; } break; case VECTOR2: { - int64_t to = reinterpret_cast<const Vector2 *>(_data._mem)->y; + double to = reinterpret_cast<const Vector2 *>(_data._mem)->y; + + double idx = r_iter; + idx++; + + if (idx >= to) + return false; + + r_iter = idx; + return true; + } break; + case VECTOR2I: { + int64_t to = reinterpret_cast<const Vector2i *>(_data._mem)->y; int64_t idx = r_iter; idx++; @@ -3652,8 +3723,24 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const { return true; } break; case VECTOR3: { - int64_t to = reinterpret_cast<const Vector3 *>(_data._mem)->y; - int64_t step = reinterpret_cast<const Vector3 *>(_data._mem)->z; + double to = reinterpret_cast<const Vector3 *>(_data._mem)->y; + double step = reinterpret_cast<const Vector3 *>(_data._mem)->z; + + double idx = r_iter; + idx += step; + + if (step < 0 && idx <= to) + return false; + + if (step > 0 && idx >= to) + return false; + + r_iter = idx; + return true; + } break; + case VECTOR3I: { + int64_t to = reinterpret_cast<const Vector3i *>(_data._mem)->y; + int64_t step = reinterpret_cast<const Vector3i *>(_data._mem)->z; int64_t idx = r_iter; idx += step; @@ -3844,10 +3931,18 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const { return r_iter; } break; + case VECTOR2I: { + + return r_iter; + } break; case VECTOR3: { return r_iter; } break; + case VECTOR3I: { + + return r_iter; + } break; case OBJECT: { if (!_get_obj().obj) { diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp index 0a578faf78..c9678c9933 100644 --- a/core/variant_parser.cpp +++ b/core/variant_parser.cpp @@ -243,11 +243,21 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri switch (next) { - case 'b': res = 8; break; - case 't': res = 9; break; - case 'n': res = 10; break; - case 'f': res = 12; break; - case 'r': res = 13; break; + case 'b': + res = 8; + break; + case 't': + res = 9; + break; + case 'n': + res = 10; + break; + case 'f': + res = 12; + break; + case 'r': + res = 13; + break; case 'u': { //hex number for (int j = 0; j < 4; j++) { diff --git a/core/vector.h b/core/vector.h index 7277179621..74e0ab91c0 100644 --- a/core/vector.h +++ b/core/vector.h @@ -39,6 +39,7 @@ #include "core/cowdata.h" #include "core/error_macros.h" +#include "core/os/copymem.h" #include "core/os/memory.h" #include "core/sort_array.h" @@ -69,7 +70,8 @@ public: void remove(int p_index) { _cowdata.remove(p_index); } void erase(const T &p_val) { int idx = find(p_val); - if (idx >= 0) remove(idx); + if (idx >= 0) + remove(idx); } void invert(); @@ -124,6 +126,13 @@ public: return *this; } + Vector<uint8_t> to_byte_array() const { + Vector<uint8_t> ret; + ret.resize(size() * sizeof(T)); + copymem(ret.ptrw(), ptr(), sizeof(T) * size()); + return ret; + } + Vector<T> subarray(int p_from, int p_to) const { if (p_from < 0) { |