diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/bind/core_bind.cpp | 16 | ||||
-rw-r--r-- | core/error_macros.h | 10 | ||||
-rw-r--r-- | core/image.cpp | 53 | ||||
-rw-r--r-- | core/image.h | 2 | ||||
-rw-r--r-- | core/input_map.cpp | 67 | ||||
-rw-r--r-- | core/input_map.h | 7 | ||||
-rw-r--r-- | core/io/pck_packer.cpp | 8 | ||||
-rw-r--r-- | core/math/matrix3.cpp | 63 | ||||
-rw-r--r-- | core/math/matrix3.h | 15 | ||||
-rw-r--r-- | core/math/transform.cpp | 4 | ||||
-rw-r--r-- | core/node_path.cpp | 3 | ||||
-rw-r--r-- | core/os/input.cpp | 3 | ||||
-rw-r--r-- | core/os/input.h | 1 | ||||
-rw-r--r-- | core/os/input_event.cpp | 85 | ||||
-rw-r--r-- | core/os/input_event.h | 22 | ||||
-rw-r--r-- | core/project_settings.cpp | 28 | ||||
-rw-r--r-- | core/project_settings.h | 2 | ||||
-rw-r--r-- | core/string_db.cpp | 13 | ||||
-rw-r--r-- | core/string_db.h | 1 | ||||
-rw-r--r-- | core/ustring.cpp | 80 | ||||
-rw-r--r-- | core/ustring.h | 4 | ||||
-rw-r--r-- | core/variant_call.cpp | 8 | ||||
-rw-r--r-- | core/variant_op.cpp | 21 |
23 files changed, 389 insertions, 127 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 85793f127d..a51f2397c6 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -639,8 +639,8 @@ uint64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const { unsigned int second = ((datetime.has(SECOND_KEY)) ? static_cast<unsigned int>(datetime[SECOND_KEY]) : 0); unsigned int minute = ((datetime.has(MINUTE_KEY)) ? static_cast<unsigned int>(datetime[MINUTE_KEY]) : 0); unsigned int hour = ((datetime.has(HOUR_KEY)) ? static_cast<unsigned int>(datetime[HOUR_KEY]) : 0); - unsigned int day = ((datetime.has(DAY_KEY)) ? static_cast<unsigned int>(datetime[DAY_KEY]) : 0); - unsigned int month = ((datetime.has(MONTH_KEY)) ? static_cast<unsigned int>(datetime[MONTH_KEY]) - 1 : 0); + unsigned int day = ((datetime.has(DAY_KEY)) ? static_cast<unsigned int>(datetime[DAY_KEY]) : 1); + unsigned int month = ((datetime.has(MONTH_KEY)) ? static_cast<unsigned int>(datetime[MONTH_KEY]) : 1); unsigned int year = ((datetime.has(YEAR_KEY)) ? static_cast<unsigned int>(datetime[YEAR_KEY]) : 0); /// How many days come before each month (0-12) @@ -660,15 +660,15 @@ uint64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const { ERR_EXPLAIN("Invalid hour value of: " + itos(hour)); ERR_FAIL_COND_V(hour > 23, 0); - ERR_EXPLAIN("Invalid month value of: " + itos(month + 1)); - ERR_FAIL_COND_V(month + 1 > 12, 0); + ERR_EXPLAIN("Invalid month value of: " + itos(month)); + ERR_FAIL_COND_V(month > 12 || month == 0, 0); // Do this check after month is tested as valid - ERR_EXPLAIN("Invalid day value of: " + itos(day) + " which is larger than " + itos(MONTH_DAYS_TABLE[LEAPYEAR(year)][month])); - ERR_FAIL_COND_V(day > MONTH_DAYS_TABLE[LEAPYEAR(year)][month], 0); + ERR_EXPLAIN("Invalid day value of: " + itos(day) + " which is larger than " + itos(MONTH_DAYS_TABLE[LEAPYEAR(year)][month - 1]) + " or 0"); + ERR_FAIL_COND_V(day > MONTH_DAYS_TABLE[LEAPYEAR(year)][month - 1] || day == 0, 0); // Calculate all the seconds from months past in this year - uint64_t SECONDS_FROM_MONTHS_PAST_THIS_YEAR = DAYS_PAST_THIS_YEAR_TABLE[LEAPYEAR(year)][month] * SECONDS_PER_DAY; + uint64_t SECONDS_FROM_MONTHS_PAST_THIS_YEAR = DAYS_PAST_THIS_YEAR_TABLE[LEAPYEAR(year)][month - 1] * SECONDS_PER_DAY; uint64_t SECONDS_FROM_YEARS_PAST = 0; for (unsigned int iyear = EPOCH_YR; iyear < year; iyear++) { @@ -2413,7 +2413,7 @@ _Thread::_Thread() { _Thread::~_Thread() { if (active) { - ERR_EXPLAIN("Reference to a Thread object object was lost while the thread is still running.."); + ERR_EXPLAIN("Reference to a Thread object object was lost while the thread is still running..."); } ERR_FAIL_COND(active == true); } diff --git a/core/error_macros.h b/core/error_macros.h index b8d0c7e0c3..168b2e06fe 100644 --- a/core/error_macros.h +++ b/core/error_macros.h @@ -311,4 +311,14 @@ extern bool _err_error_exists; _err_error_exists = false; \ } +#define WARN_DEPRECATED \ + { \ + static bool warning_shown=false;\ + if (!warning_shown) {\ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__,"This method has been deprecated and will be removed in the future", ERR_HANDLER_WARNING); \ + _err_error_exists = false; \ + warning_shown=true;\ + }\ + } + #endif diff --git a/core/image.cpp b/core/image.cpp index 2ac8ffea56..58f49d69e6 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -366,6 +366,8 @@ int Image::get_mipmap_count() const { template <uint32_t read_bytes, bool read_alpha, uint32_t write_bytes, bool write_alpha, bool read_gray, bool write_gray> static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p_dst) { + uint32_t max_bytes = MAX(read_bytes, write_bytes); + for (int y = 0; y < p_height; y++) { for (int x = 0; x < p_width; x++) { @@ -379,7 +381,8 @@ static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p rgba[1] = rofs[0]; rgba[2] = rofs[0]; } else { - for (uint32_t i = 0; i < MAX(read_bytes, write_bytes); i++) { + + for (uint32_t i = 0; i < max_bytes; i++) { rgba[i] = (i < read_bytes) ? rofs[i] : 0; } @@ -937,7 +940,7 @@ bool Image::_can_modify(Format p_format) const { return p_format <= FORMAT_RGBE9995; } -template <int CC> +template <int CC, bool renormalize> static void _generate_po2_mipmap(const uint8_t *p_src, uint8_t *p_dst, uint32_t p_width, uint32_t p_height) { //fast power of 2 mipmap generation @@ -963,6 +966,19 @@ static void _generate_po2_mipmap(const uint8_t *p_src, uint8_t *p_dst, uint32_t dst_ptr[j] = val >> 2; } + if (renormalize) { + Vector3 n(dst_ptr[0] / 255.0, dst_ptr[1] / 255.0, dst_ptr[2] / 255.0); + n *= 2.0; + n -= Vector3(1, 1, 1); + n.normalize(); + n += Vector3(1, 1, 1); + n *= 0.5; + n *= 255; + dst_ptr[0] = CLAMP(int(n.x), 0, 255); + dst_ptr[1] = CLAMP(int(n.y), 0, 255); + dst_ptr[2] = CLAMP(int(n.z), 0, 255); + } + dst_ptr += CC; rup_ptr += CC * 2; rdown_ptr += CC * 2; @@ -1045,11 +1061,11 @@ void Image::shrink_x2() { switch (format) { case FORMAT_L8: - case FORMAT_R8: _generate_po2_mipmap<1>(r.ptr(), w.ptr(), width, height); break; - case FORMAT_LA8: _generate_po2_mipmap<2>(r.ptr(), w.ptr(), width, height); break; - case FORMAT_RG8: _generate_po2_mipmap<2>(r.ptr(), w.ptr(), width, height); break; - case FORMAT_RGB8: _generate_po2_mipmap<3>(r.ptr(), w.ptr(), width, height); break; - case FORMAT_RGBA8: _generate_po2_mipmap<4>(r.ptr(), w.ptr(), width, height); break; + case FORMAT_R8: _generate_po2_mipmap<1, false>(r.ptr(), w.ptr(), width, height); break; + case FORMAT_LA8: _generate_po2_mipmap<2, false>(r.ptr(), w.ptr(), width, height); break; + case FORMAT_RG8: _generate_po2_mipmap<2, false>(r.ptr(), w.ptr(), width, height); break; + case FORMAT_RGB8: _generate_po2_mipmap<3, false>(r.ptr(), w.ptr(), width, height); break; + case FORMAT_RGBA8: _generate_po2_mipmap<4, false>(r.ptr(), w.ptr(), width, height); break; default: {} } } @@ -1060,7 +1076,7 @@ void Image::shrink_x2() { } } -Error Image::generate_mipmaps() { +Error Image::generate_mipmaps(bool p_renormalize) { if (!_can_modify(format)) { ERR_EXPLAIN("Cannot generate mipmaps in indexed, compressed or custom image formats."); @@ -1089,11 +1105,22 @@ Error Image::generate_mipmaps() { switch (format) { case FORMAT_L8: - case FORMAT_R8: _generate_po2_mipmap<1>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break; + case FORMAT_R8: _generate_po2_mipmap<1, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break; case FORMAT_LA8: - case FORMAT_RG8: _generate_po2_mipmap<2>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break; - case FORMAT_RGB8: _generate_po2_mipmap<3>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break; - case FORMAT_RGBA8: _generate_po2_mipmap<4>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break; + case FORMAT_RG8: _generate_po2_mipmap<2, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break; + case FORMAT_RGB8: + if (p_renormalize) + _generate_po2_mipmap<3, true>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); + else + _generate_po2_mipmap<3, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); + + break; + case FORMAT_RGBA8: + if (p_renormalize) + _generate_po2_mipmap<4, true>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); + else + _generate_po2_mipmap<4, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); + break; default: {} } @@ -2217,7 +2244,7 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("crop", "width", "height"), &Image::crop); ClassDB::bind_method(D_METHOD("flip_x"), &Image::flip_x); ClassDB::bind_method(D_METHOD("flip_y"), &Image::flip_y); - ClassDB::bind_method(D_METHOD("generate_mipmaps"), &Image::generate_mipmaps); + ClassDB::bind_method(D_METHOD("generate_mipmaps", "renormalize"), &Image::generate_mipmaps, DEFVAL(false)); ClassDB::bind_method(D_METHOD("clear_mipmaps"), &Image::clear_mipmaps); ClassDB::bind_method(D_METHOD("create", "width", "height", "use_mipmaps", "format"), &Image::_create_empty); diff --git a/core/image.h b/core/image.h index 17477d88ea..3c43e49950 100644 --- a/core/image.h +++ b/core/image.h @@ -217,7 +217,7 @@ public: /** * Generate a mipmap to an image (creates an image 1/4 the size, with averaging of 4->1) */ - Error generate_mipmaps(); + Error generate_mipmaps(bool p_renormalize = false); void clear_mipmaps(); diff --git a/core/input_map.cpp b/core/input_map.cpp index ea724d2595..67c0e4eb04 100644 --- a/core/input_map.cpp +++ b/core/input_map.cpp @@ -41,9 +41,10 @@ void InputMap::_bind_methods() { ClassDB::bind_method(D_METHOD("has_action", "action"), &InputMap::has_action); ClassDB::bind_method(D_METHOD("get_actions"), &InputMap::_get_actions); - ClassDB::bind_method(D_METHOD("add_action", "action"), &InputMap::add_action); + ClassDB::bind_method(D_METHOD("add_action", "action", "deadzone"), &InputMap::add_action, DEFVAL(0.5f)); ClassDB::bind_method(D_METHOD("erase_action", "action"), &InputMap::erase_action); + ClassDB::bind_method(D_METHOD("action_set_deadzone", "deadzone"), &InputMap::action_set_deadzone); ClassDB::bind_method(D_METHOD("action_add_event", "action", "event"), &InputMap::action_add_event); ClassDB::bind_method(D_METHOD("action_has_event", "action", "event"), &InputMap::action_has_event); ClassDB::bind_method(D_METHOD("action_erase_event", "action", "event"), &InputMap::action_erase_event); @@ -52,12 +53,13 @@ void InputMap::_bind_methods() { ClassDB::bind_method(D_METHOD("load_from_globals"), &InputMap::load_from_globals); } -void InputMap::add_action(const StringName &p_action) { +void InputMap::add_action(const StringName &p_action, float p_deadzone) { ERR_FAIL_COND(input_map.has(p_action)); input_map[p_action] = Action(); static int last_id = 1; input_map[p_action].id = last_id; + input_map[p_action].deadzone = p_deadzone; last_id++; } @@ -96,9 +98,9 @@ List<StringName> InputMap::get_actions() const { return actions; } -List<Ref<InputEvent> >::Element *InputMap::_find_event(List<Ref<InputEvent> > &p_list, const Ref<InputEvent> &p_event, bool p_action_test) const { +List<Ref<InputEvent> >::Element *InputMap::_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength) const { - for (List<Ref<InputEvent> >::Element *E = p_list.front(); E; E = E->next()) { + for (List<Ref<InputEvent> >::Element *E = p_action.inputs.front(); E; E = E->next()) { const Ref<InputEvent> e = E->get(); @@ -106,9 +108,11 @@ List<Ref<InputEvent> >::Element *InputMap::_find_event(List<Ref<InputEvent> > &p // continue; int device = e->get_device(); - if (device == ALL_DEVICES || device == p_event->get_device()) - if (e->action_match(p_event)) + if (device == ALL_DEVICES || device == p_event->get_device()) { + if (e->action_match(p_event, p_pressed, p_strength, p_action.deadzone)) { return E; + } + } } return NULL; @@ -119,11 +123,18 @@ bool InputMap::has_action(const StringName &p_action) const { return input_map.has(p_action); } +void InputMap::action_set_deadzone(const StringName &p_action, float p_deadzone) { + + ERR_FAIL_COND(!input_map.has(p_action)); + + input_map[p_action].deadzone = p_deadzone; +} + void InputMap::action_add_event(const StringName &p_action, const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); ERR_FAIL_COND(!input_map.has(p_action)); - if (_find_event(input_map[p_action].inputs, p_event)) + if (_find_event(input_map[p_action], p_event)) return; //already gots input_map[p_action].inputs.push_back(p_event); @@ -132,14 +143,14 @@ void InputMap::action_add_event(const StringName &p_action, const Ref<InputEvent bool InputMap::action_has_event(const StringName &p_action, const Ref<InputEvent> &p_event) { ERR_FAIL_COND_V(!input_map.has(p_action), false); - return (_find_event(input_map[p_action].inputs, p_event) != NULL); + return (_find_event(input_map[p_action], p_event) != NULL); } void InputMap::action_erase_event(const StringName &p_action, const Ref<InputEvent> &p_event) { ERR_FAIL_COND(!input_map.has(p_action)); - List<Ref<InputEvent> >::Element *E = _find_event(input_map[p_action].inputs, p_event); + List<Ref<InputEvent> >::Element *E = _find_event(input_map[p_action], p_event); if (E) input_map[p_action].inputs.erase(E); } @@ -168,19 +179,33 @@ const List<Ref<InputEvent> > *InputMap::get_action_list(const StringName &p_acti } bool InputMap::event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action) const { + return event_get_action_status(p_event, p_action); +} +bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool *p_pressed, float *p_strength) const { Map<StringName, Action>::Element *E = input_map.find(p_action); if (!E) { ERR_EXPLAIN("Request for nonexistent InputMap action: " + String(p_action)); ERR_FAIL_COND_V(!E, false); } - Ref<InputEventAction> iea = p_event; - if (iea.is_valid()) { - return iea->get_action() == p_action; + Ref<InputEventAction> input_event_action = p_event; + if (input_event_action.is_valid()) { + return input_event_action->get_action() == p_action; } - return _find_event(E->get().inputs, p_event, true) != NULL; + bool pressed; + float strength; + List<Ref<InputEvent> >::Element *event = _find_event(E->get(), p_event, &pressed, &strength); + if (event != NULL) { + if (p_pressed != NULL) + *p_pressed = pressed; + if (p_strength != NULL) + *p_strength = strength; + return true; + } else { + return false; + } } const Map<StringName, InputMap::Action> &InputMap::get_action_map() const { @@ -202,16 +227,16 @@ void InputMap::load_from_globals() { String name = pi.name.substr(pi.name.find("/") + 1, pi.name.length()); - add_action(name); - - Array va = ProjectSettings::get_singleton()->get(pi.name); - - for (int i = 0; i < va.size(); i++) { + Dictionary action = ProjectSettings::get_singleton()->get(pi.name); + float deadzone = action.has("deadzone") ? (float)action["deadzone"] : 0.5f; + Array events = action["events"]; - Ref<InputEvent> ie = va[i]; - if (ie.is_null()) + add_action(name, deadzone); + for (int i = 0; i < events.size(); i++) { + Ref<InputEvent> event = events[i]; + if (event.is_null()) continue; - action_add_event(name, ie); + action_add_event(name, event); } } } diff --git a/core/input_map.h b/core/input_map.h index 9f3c13c2cf..f497a2b86e 100644 --- a/core/input_map.h +++ b/core/input_map.h @@ -46,6 +46,7 @@ public: struct Action { int id; + float deadzone; List<Ref<InputEvent> > inputs; }; @@ -54,7 +55,7 @@ private: mutable Map<StringName, Action> input_map; - List<Ref<InputEvent> >::Element *_find_event(List<Ref<InputEvent> > &p_list, const Ref<InputEvent> &p_event, bool p_action_test = false) const; + List<Ref<InputEvent> >::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool *p_pressed = NULL, float *p_strength = NULL) const; Array _get_action_list(const StringName &p_action); Array _get_actions(); @@ -67,15 +68,17 @@ public: bool has_action(const StringName &p_action) const; List<StringName> get_actions() const; - void add_action(const StringName &p_action); + void add_action(const StringName &p_action, float p_deadzone = 0.5); void erase_action(const StringName &p_action); + void action_set_deadzone(const StringName &p_action, float p_deadzone); void action_add_event(const StringName &p_action, const Ref<InputEvent> &p_event); bool action_has_event(const StringName &p_action, const Ref<InputEvent> &p_event); void action_erase_event(const StringName &p_action, const Ref<InputEvent> &p_event); const List<Ref<InputEvent> > *get_action_list(const StringName &p_action); bool event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action) const; + bool event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool *p_pressed = NULL, float *p_strength = NULL) const; const Map<StringName, Action> &get_action_map() const; void load_from_globals(); diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp index 596060221e..b6377662de 100644 --- a/core/io/pck_packer.cpp +++ b/core/io/pck_packer.cpp @@ -29,8 +29,8 @@ /*************************************************************************/ #include "pck_packer.h" - #include "core/os/file_access.h" +#include "version.h" static uint64_t _align(uint64_t p_n, int p_alignment) { @@ -70,9 +70,9 @@ Error PCKPacker::pck_start(const String &p_file, int p_alignment) { alignment = p_alignment; file->store_32(0x43504447); // MAGIC - file->store_32(0); // # version - file->store_32(0); // # major - file->store_32(0); // # minor + file->store_32(1); // # version + file->store_32(VERSION_MAJOR); // # major + file->store_32(VERSION_MINOR); // # minor file->store_32(0); // # revision for (int i = 0; i < 16; i++) { diff --git a/core/math/matrix3.cpp b/core/math/matrix3.cpp index 189b1ef9b3..b0b05d1ec8 100644 --- a/core/math/matrix3.cpp +++ b/core/math/matrix3.cpp @@ -254,7 +254,7 @@ void Basis::set_scale(const Vector3 &p_scale) { set_axis(2, get_axis(2).normalized() * p_scale.z); } -Vector3 Basis::get_scale() const { +Vector3 Basis::get_scale_abs() const { return Vector3( Vector3(elements[0][0], elements[1][0], elements[2][0]).length(), @@ -262,7 +262,13 @@ Vector3 Basis::get_scale() const { Vector3(elements[0][2], elements[1][2], elements[2][2]).length()); } -Vector3 Basis::get_signed_scale() const { +Vector3 Basis::get_scale_local() const { + real_t det_sign = determinant() > 0 ? 1 : -1; + return det_sign * Vector3(elements[0].length(), elements[1].length(), elements[2].length()); +} + +// get_scale works with get_rotation, use get_scale_abs if you need to enforce positive signature. +Vector3 Basis::get_scale() const { // FIXME: We are assuming M = R.S (R is rotation and S is scaling), and use polar decomposition to extract R and S. // A polar decomposition is M = O.P, where O is an orthogonal matrix (meaning rotation and reflection) and // P is a positive semi-definite matrix (meaning it contains absolute values of scaling along its diagonal). @@ -342,6 +348,14 @@ void Basis::rotate(const Vector3 &p_euler) { *this = rotated(p_euler); } +Basis Basis::rotated(const Quat &p_quat) const { + return Basis(p_quat) * (*this); +} + +void Basis::rotate(const Quat &p_quat) { + *this = rotated(p_quat); +} + // TODO: rename this to get_rotation_euler Vector3 Basis::get_rotation() const { // Assumes that the matrix can be decomposed into a proper rotation and scaling matrix as M = R.S, @@ -371,6 +385,22 @@ void Basis::get_rotation_axis_angle(Vector3 &p_axis, real_t &p_angle) const { m.get_axis_angle(p_axis, p_angle); } +void Basis::get_rotation_axis_angle_local(Vector3 &p_axis, real_t &p_angle) const { + // Assumes that the matrix can be decomposed into a proper rotation and scaling matrix as M = R.S, + // and returns the Euler angles corresponding to the rotation part, complementing get_scale(). + // See the comment in get_scale() for further information. + Basis m = transposed(); + m.orthonormalize(); + real_t det = m.determinant(); + if (det < 0) { + // Ensure that the determinant is 1, such that result is a proper rotation matrix which can be represented by Euler angles. + m.scale(Vector3(-1, -1, -1)); + } + + m.get_axis_angle(p_axis, p_angle); + p_angle = -p_angle; +} + // get_euler_xyz returns a vector containing the Euler angles in the format // (a1,a2,a3), where a3 is the angle of the first rotation, and a1 is the last // (following the convention they are commonly defined in the literature). @@ -767,3 +797,32 @@ void Basis::set_axis_angle(const Vector3 &p_axis, real_t p_phi) { elements[2][1] = p_axis.y * p_axis.z * (1.0 - cosine) + p_axis.x * sine; elements[2][2] = axis_sq.z + cosine * (1.0 - axis_sq.z); } + +void Basis::set_axis_angle_scale(const Vector3 &p_axis, real_t p_phi, const Vector3 &p_scale) { + set_diagonal(p_scale); + rotate(p_axis, p_phi); +} + +void Basis::set_euler_scale(const Vector3 &p_euler, const Vector3 &p_scale) { + set_diagonal(p_scale); + rotate(p_euler); +} + +void Basis::set_quat_scale(const Quat &p_quat, const Vector3 &p_scale) { + set_diagonal(p_scale); + rotate(p_quat); +} + +void Basis::set_diagonal(const Vector3 p_diag) { + elements[0][0] = p_diag.x; + elements[0][1] = 0; + elements[0][2] = 0; + + elements[1][0] = 0; + elements[1][1] = p_diag.y; + elements[1][2] = 0; + + elements[2][0] = 0; + elements[2][1] = 0; + elements[2][2] = p_diag.z; +} diff --git a/core/math/matrix3.h b/core/math/matrix3.h index c426435729..fd383fc673 100644 --- a/core/math/matrix3.h +++ b/core/math/matrix3.h @@ -81,8 +81,12 @@ public: void rotate(const Vector3 &p_euler); Basis rotated(const Vector3 &p_euler) const; + void rotate(const Quat &p_quat); + Basis rotated(const Quat &p_quat) const; + Vector3 get_rotation() const; void get_rotation_axis_angle(Vector3 &p_axis, real_t &p_angle) const; + void get_rotation_axis_angle_local(Vector3 &p_axis, real_t &p_angle) const; Vector3 rotref_posscale_decomposition(Basis &rotref) const; @@ -108,7 +112,12 @@ public: void set_scale(const Vector3 &p_scale); Vector3 get_scale() const; - Vector3 get_signed_scale() const; + Vector3 get_scale_abs() const; + Vector3 get_scale_local() const; + + void set_axis_angle_scale(const Vector3 &p_axis, real_t p_phi, const Vector3 &p_scale); + void set_euler_scale(const Vector3 &p_euler, const Vector3 &p_scale); + void set_quat_scale(const Quat &p_quat, const Vector3 &p_scale); // transposed dot products _FORCE_INLINE_ real_t tdotx(const Vector3 &v) const { @@ -140,6 +149,8 @@ public: int get_orthogonal_index() const; void set_orthogonal_index(int p_index); + void set_diagonal(const Vector3 p_diag); + bool is_orthogonal() const; bool is_diagonal() const; bool is_rotation() const; @@ -219,6 +230,8 @@ public: Basis(const Quat &p_quat) { set_quat(p_quat); }; Basis(const Vector3 &p_euler) { set_euler(p_euler); } Basis(const Vector3 &p_axis, real_t p_phi) { set_axis_angle(p_axis, p_phi); } + Basis(const Vector3 &p_axis, real_t p_phi, const Vector3 &p_scale) { set_axis_angle_scale(p_axis, p_phi, p_scale); } + Basis(const Quat &p_quat, const Vector3 &p_scale) { set_quat_scale(p_quat, p_scale); } _FORCE_INLINE_ Basis(const Vector3 &row0, const Vector3 &row1, const Vector3 &row2) { elements[0] = row0; diff --git a/core/math/transform.cpp b/core/math/transform.cpp index f727d00e30..7cd186ca60 100644 --- a/core/math/transform.cpp +++ b/core/math/transform.cpp @@ -119,11 +119,11 @@ Transform Transform::interpolate_with(const Transform &p_transform, real_t p_c) /* not sure if very "efficient" but good enough? */ - Vector3 src_scale = basis.get_signed_scale(); + Vector3 src_scale = basis.get_scale(); Quat src_rot = basis.orthonormalized(); Vector3 src_loc = origin; - Vector3 dst_scale = p_transform.basis.get_signed_scale(); + Vector3 dst_scale = p_transform.basis.get_scale(); Quat dst_rot = p_transform.basis; Vector3 dst_loc = p_transform.origin; diff --git a/core/node_path.cpp b/core/node_path.cpp index cd7ad77534..64983fc091 100644 --- a/core/node_path.cpp +++ b/core/node_path.cpp @@ -264,8 +264,9 @@ NodePath NodePath::get_as_property_path() const { Vector<StringName> new_path = data->subpath; String initial_subname = data->path[0]; + for (size_t i = 1; i < data->path.size(); i++) { - initial_subname += i == 0 ? data->path[i].operator String() : "/" + data->path[i]; + initial_subname += "/" + data->path[i]; } new_path.insert(0, initial_subname); diff --git a/core/os/input.cpp b/core/os/input.cpp index e8a635e1b5..a5b0f91e63 100644 --- a/core/os/input.cpp +++ b/core/os/input.cpp @@ -57,6 +57,7 @@ void Input::_bind_methods() { ClassDB::bind_method(D_METHOD("is_action_pressed", "action"), &Input::is_action_pressed); ClassDB::bind_method(D_METHOD("is_action_just_pressed", "action"), &Input::is_action_just_pressed); ClassDB::bind_method(D_METHOD("is_action_just_released", "action"), &Input::is_action_just_released); + ClassDB::bind_method(D_METHOD("get_action_strength", "action"), &Input::get_action_strength); ClassDB::bind_method(D_METHOD("add_joy_mapping", "mapping", "update_existing"), &Input::add_joy_mapping, DEFVAL(false)); ClassDB::bind_method(D_METHOD("remove_joy_mapping", "guid"), &Input::remove_joy_mapping); ClassDB::bind_method(D_METHOD("joy_connection_changed", "device", "connected", "name", "guid"), &Input::joy_connection_changed); @@ -119,7 +120,7 @@ void Input::get_argument_options(const StringName &p_function, int p_idx, List<S #ifdef TOOLS_ENABLED String pf = p_function; - if (p_idx == 0 && (pf == "is_action_pressed" || pf == "action_press" || pf == "action_release" || pf == "is_action_just_pressed" || pf == "is_action_just_released")) { + if (p_idx == 0 && (pf == "is_action_pressed" || pf == "action_press" || pf == "action_release" || pf == "is_action_just_pressed" || pf == "is_action_just_released" || pf == "get_action_strength")) { List<PropertyInfo> pinfo; ProjectSettings::get_singleton()->get_property_list(&pinfo); diff --git a/core/os/input.h b/core/os/input.h index fca68f27b7..027147b987 100644 --- a/core/os/input.h +++ b/core/os/input.h @@ -85,6 +85,7 @@ public: virtual bool is_action_pressed(const StringName &p_action) const = 0; virtual bool is_action_just_pressed(const StringName &p_action) const = 0; virtual bool is_action_just_released(const StringName &p_action) const = 0; + virtual float get_action_strength(const StringName &p_action) const = 0; virtual float get_joy_axis(int p_device, int p_axis) const = 0; virtual String get_joy_name(int p_idx) = 0; diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp index b9607632f7..4ebb821a2f 100644 --- a/core/os/input_event.cpp +++ b/core/os/input_event.cpp @@ -41,11 +41,6 @@ int InputEvent::get_device() const { return device; } -bool InputEvent::is_pressed() const { - - return false; -} - bool InputEvent::is_action(const StringName &p_action) const { return InputMap::get_singleton()->event_is_action(Ref<InputEvent>((InputEvent *)this), p_action); @@ -53,11 +48,29 @@ bool InputEvent::is_action(const StringName &p_action) const { bool InputEvent::is_action_pressed(const StringName &p_action) const { - return (is_pressed() && !is_echo() && is_action(p_action)); + bool pressed; + bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, &pressed); + return valid && pressed && !is_echo(); } + bool InputEvent::is_action_released(const StringName &p_action) const { - return (!is_pressed() && is_action(p_action)); + bool pressed; + bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, &pressed); + return valid && !pressed; +} + +float InputEvent::get_action_strength(const StringName &p_action) const { + + bool pressed; + float strength; + bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, &pressed, &strength); + return valid ? strength : 0.0f; +} + +bool InputEvent::is_pressed() const { + + return false; } bool InputEvent::is_echo() const { @@ -75,7 +88,7 @@ String InputEvent::as_text() const { return String(); } -bool InputEvent::action_match(const Ref<InputEvent> &p_event) const { +bool InputEvent::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const { return false; } @@ -95,15 +108,16 @@ void InputEvent::_bind_methods() { ClassDB::bind_method(D_METHOD("set_device", "device"), &InputEvent::set_device); ClassDB::bind_method(D_METHOD("get_device"), &InputEvent::get_device); - ClassDB::bind_method(D_METHOD("is_pressed"), &InputEvent::is_pressed); ClassDB::bind_method(D_METHOD("is_action", "action"), &InputEvent::is_action); ClassDB::bind_method(D_METHOD("is_action_pressed", "action"), &InputEvent::is_action_pressed); ClassDB::bind_method(D_METHOD("is_action_released", "action"), &InputEvent::is_action_released); + ClassDB::bind_method(D_METHOD("get_action_strength", "action"), &InputEvent::get_action_strength); + + ClassDB::bind_method(D_METHOD("is_pressed"), &InputEvent::is_pressed); ClassDB::bind_method(D_METHOD("is_echo"), &InputEvent::is_echo); ClassDB::bind_method(D_METHOD("as_text"), &InputEvent::as_text); - ClassDB::bind_method(D_METHOD("action_match", "event"), &InputEvent::action_match); ClassDB::bind_method(D_METHOD("shortcut_match", "event"), &InputEvent::shortcut_match); ClassDB::bind_method(D_METHOD("is_action_type"), &InputEvent::is_action_type); @@ -281,7 +295,7 @@ String InputEventKey::as_text() const { return kc; } -bool InputEventKey::action_match(const Ref<InputEvent> &p_event) const { +bool InputEventKey::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const { Ref<InputEventKey> key = p_event; if (key.is_null()) @@ -290,7 +304,14 @@ bool InputEventKey::action_match(const Ref<InputEvent> &p_event) const { uint32_t code = get_scancode_with_modifiers(); uint32_t event_code = key->get_scancode_with_modifiers(); - return get_scancode() == key->get_scancode() && (!key->is_pressed() || (code & event_code) == code); + bool match = get_scancode() == key->get_scancode() && (!key->is_pressed() || (code & event_code) == code); + if (match) { + if (p_pressed != NULL) + *p_pressed = key->is_pressed(); + if (p_strength != NULL) + *p_strength = (*p_pressed) ? 1.0f : 0.0f; + } + return match; } bool InputEventKey::shortcut_match(const Ref<InputEvent> &p_event) const { @@ -446,13 +467,21 @@ Ref<InputEvent> InputEventMouseButton::xformed_by(const Transform2D &p_xform, co return mb; } -bool InputEventMouseButton::action_match(const Ref<InputEvent> &p_event) const { +bool InputEventMouseButton::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const { Ref<InputEventMouseButton> mb = p_event; if (mb.is_null()) return false; - return mb->button_index == button_index; + bool match = mb->button_index == button_index; + if (match) { + if (p_pressed != NULL) + *p_pressed = mb->is_pressed(); + if (p_strength != NULL) + *p_strength = (*p_pressed) ? 1.0f : 0.0f; + } + + return match; } String InputEventMouseButton::as_text() const { @@ -610,6 +639,7 @@ void InputEventJoypadMotion::set_axis_value(float p_value) { axis_value = p_value; } + float InputEventJoypadMotion::get_axis_value() const { return axis_value; @@ -617,16 +647,25 @@ float InputEventJoypadMotion::get_axis_value() const { bool InputEventJoypadMotion::is_pressed() const { - return Math::abs(axis_value) > 0.5f; + return Math::abs(axis_value) >= 0.5f; } -bool InputEventJoypadMotion::action_match(const Ref<InputEvent> &p_event) const { +bool InputEventJoypadMotion::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const { Ref<InputEventJoypadMotion> jm = p_event; if (jm.is_null()) return false; - return (axis == jm->axis && ((axis_value < 0) == (jm->axis_value < 0) || jm->axis_value == 0)); + bool match = (axis == jm->axis); // Matches even if not in the same direction, but returns a "not pressed" event. + if (match) { + bool same_direction = (((axis_value < 0) == (jm->axis_value < 0)) || jm->axis_value == 0); + bool pressed = same_direction ? Math::abs(jm->get_axis_value()) >= p_deadzone : false; + if (p_pressed != NULL) + *p_pressed = pressed; + if (p_strength != NULL) + *p_strength = pressed ? CLAMP(Math::inverse_lerp(p_deadzone, 1.0f, Math::abs(jm->get_axis_value())), 0.0f, 1.0f) : 0.0f; + } + return match; } String InputEventJoypadMotion::as_text() const { @@ -681,13 +720,21 @@ float InputEventJoypadButton::get_pressure() const { return pressure; } -bool InputEventJoypadButton::action_match(const Ref<InputEvent> &p_event) const { +bool InputEventJoypadButton::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const { Ref<InputEventJoypadButton> jb = p_event; if (jb.is_null()) return false; - return button_index == jb->button_index; + bool match = button_index == jb->button_index; + if (match) { + if (p_pressed != NULL) + *p_pressed = jb->is_pressed(); + if (p_strength != NULL) + *p_strength = (*p_pressed) ? 1.0f : 0.0f; + } + + return match; } String InputEventJoypadButton::as_text() const { diff --git a/core/os/input_event.h b/core/os/input_event.h index 0a33ab18a7..037649ed60 100644 --- a/core/os/input_event.h +++ b/core/os/input_event.h @@ -154,16 +154,21 @@ public: void set_device(int p_device); int get_device() const; + bool is_action(const StringName &p_action) const; + bool is_action_pressed(const StringName &p_action) const; + bool is_action_released(const StringName &p_action) const; + float get_action_strength(const StringName &p_action) const; + + // To be removed someday, since they do not make sense for all events virtual bool is_pressed() const; - virtual bool is_action(const StringName &p_action) const; - virtual bool is_action_pressed(const StringName &p_action) const; - virtual bool is_action_released(const StringName &p_action) const; virtual bool is_echo() const; + // ...-. + virtual String as_text() const; virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const; - virtual bool action_match(const Ref<InputEvent> &p_event) const; + virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const; virtual bool shortcut_match(const Ref<InputEvent> &p_event) const; virtual bool is_action_type() const; @@ -244,7 +249,7 @@ public: uint32_t get_scancode_with_modifiers() const; - virtual bool action_match(const Ref<InputEvent> &p_event) const; + virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const; virtual bool shortcut_match(const Ref<InputEvent> &p_event) const; virtual bool is_action_type() const { return true; } @@ -305,7 +310,7 @@ public: bool is_doubleclick() const; virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const; - virtual bool action_match(const Ref<InputEvent> &p_event) const; + virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const; virtual bool is_action_type() const { return true; } virtual String as_text() const; @@ -352,7 +357,8 @@ public: float get_axis_value() const; virtual bool is_pressed() const; - virtual bool action_match(const Ref<InputEvent> &p_event) const; + + virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const; virtual bool is_action_type() const { return true; } virtual String as_text() const; @@ -379,7 +385,7 @@ public: void set_pressure(float p_pressure); float get_pressure() const; - virtual bool action_match(const Ref<InputEvent> &p_event) const; + virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const; virtual bool is_action_type() const { return true; } virtual String as_text() const; diff --git a/core/project_settings.cpp b/core/project_settings.cpp index 20d91e7940..ac4a4b7d15 100644 --- a/core/project_settings.cpp +++ b/core/project_settings.cpp @@ -42,7 +42,7 @@ #include "variant_parser.h" #include <zlib.h> -#define FORMAT_VERSION 3 +#define FORMAT_VERSION 4 ProjectSettings *ProjectSettings::singleton = NULL; @@ -262,6 +262,23 @@ bool ProjectSettings::_load_resource_pack(const String &p_pack) { return true; } +void ProjectSettings::_convert_to_last_version() { + if (!has_setting("config_version") || (int)get_setting("config_version") <= 3) { + + // Converts the actions from array to dictionary (array of events to dictionary with deadzone + events) + for (Map<StringName, ProjectSettings::VariantContainer>::Element *E = props.front(); E; E = E->next()) { + Variant value = E->get().variant; + if (String(E->key()).begins_with("input/") && value.get_type() == Variant::ARRAY) { + Array array = value; + Dictionary action; + action["deadzone"] = Variant(0.5f); + action["events"] = array; + E->get().variant = action; + } + } + } +} + Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bool p_upwards) { //If looking for files in network, just use network! @@ -390,6 +407,8 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bo if (resource_path.length() && resource_path[resource_path.length() - 1] == '/') resource_path = resource_path.substr(0, resource_path.length() - 1); // chop end + _convert_to_last_version(); + return OK; } @@ -797,12 +816,11 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default) { Variant ret; - if (ProjectSettings::get_singleton()->has_setting(p_var)) { - ret = ProjectSettings::get_singleton()->get(p_var); - } else { + if (!ProjectSettings::get_singleton()->has_setting(p_var)) { ProjectSettings::get_singleton()->set(p_var, p_default); - ret = p_default; } + ret = ProjectSettings::get_singleton()->get(p_var); + ProjectSettings::get_singleton()->set_initial_value(p_var, p_default); ProjectSettings::get_singleton()->set_builtin_order(p_var); return ret; diff --git a/core/project_settings.h b/core/project_settings.h index 9b51bc3ac3..b01e7855aa 100644 --- a/core/project_settings.h +++ b/core/project_settings.h @@ -102,6 +102,8 @@ protected: Error _save_custom_bnd(const String &p_file); + void _convert_to_last_version(); + bool _load_resource_pack(const String &p_pack); void _add_property_info_bind(const Dictionary &p_info); diff --git a/core/string_db.cpp b/core/string_db.cpp index 6e1f887754..2475cbe3e8 100644 --- a/core/string_db.cpp +++ b/core/string_db.cpp @@ -164,21 +164,14 @@ void StringName::operator=(const StringName &p_name) { _data = p_name._data; } } -/* was inlined -StringName::operator String() const { - if (_data) - return _data->get_name(); - - return ""; -} -*/ StringName::StringName(const StringName &p_name) { - ERR_FAIL_COND(!configured); _data = NULL; - if (p_name._data && p_name._data->refcount.ref()) { + ERR_FAIL_COND(!configured); + + if (p_name._data && p_name._data->refcount.ref()) { _data = p_name._data; } } diff --git a/core/string_db.h b/core/string_db.h index 28ca812a45..01d1ca4033 100644 --- a/core/string_db.h +++ b/core/string_db.h @@ -67,6 +67,7 @@ class StringName { _Data() { cname = NULL; next = prev = NULL; + idx = 0; hash = 0; } }; diff --git a/core/ustring.cpp b/core/ustring.cpp index 954f590218..b98e202175 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -1151,7 +1151,7 @@ String String::num_uint64(uint64_t p_num, int base, bool capitalize_hex) { c[chars] = 0; n = p_num; do { - int mod = ABS(n % base); + int mod = n % base; if (mod >= 10) { char a = (capitalize_hex ? 'A' : 'a'); c[--chars] = a + (mod - 10); @@ -1550,8 +1550,7 @@ String::String(const StrRange &p_range) { int String::hex_to_int(bool p_with_prefix) const { - int l = length(); - if (p_with_prefix && l < 3) + if (p_with_prefix && length() < 3) return 0; const CharType *s = ptr(); @@ -1560,17 +1559,13 @@ int String::hex_to_int(bool p_with_prefix) const { if (sign < 0) { s++; - l--; - if (p_with_prefix && l < 2) - return 0; } if (p_with_prefix) { if (s[0] != '0' || s[1] != 'x') return 0; s += 2; - l -= 2; - }; + } int hex = 0; @@ -1596,8 +1591,7 @@ int String::hex_to_int(bool p_with_prefix) const { int64_t String::hex_to_int64(bool p_with_prefix) const { - int l = length(); - if (p_with_prefix && l < 3) + if (p_with_prefix && length() < 3) return 0; const CharType *s = ptr(); @@ -1606,17 +1600,13 @@ int64_t String::hex_to_int64(bool p_with_prefix) const { if (sign < 0) { s++; - l--; - if (p_with_prefix && l < 2) - return 0; } if (p_with_prefix) { if (s[0] != '0' || s[1] != 'x') return 0; s += 2; - l -= 2; - }; + } int64_t hex = 0; @@ -2997,6 +2987,40 @@ String String::strip_escapes() const { return substr(beg, end - beg); } +String String::lstrip(const Vector<CharType> &p_chars) const { + + int len = length(); + int beg; + + for (beg = 0; beg < len; beg++) { + + if (p_chars.find(operator[](beg)) == -1) + break; + } + + if (beg == 0) + return *this; + + return substr(beg, len - beg); +} + +String String::rstrip(const Vector<CharType> &p_chars) const { + + int len = length(); + int end; + + for (end = len - 1; end >= 0; end--) { + + if (p_chars.find(operator[](end)) == -1) + break; + } + + if (end == len - 1) + return *this; + + return substr(0, end + 1); +} + String String::simplify_path() const { String s = *this; @@ -3448,6 +3472,24 @@ String String::pad_zeros(int p_digits) const { return s; } +String String::trim_prefix(const String &p_prefix) const { + + String s = *this; + if (s.begins_with(p_prefix)) { + return s.substr(p_prefix.length(), s.length() - p_prefix.length()); + } + return s; +} + +String String::trim_suffix(const String &p_suffix) const { + + String s = *this; + if (s.ends_with(p_suffix)) { + return s.substr(0, s.length() - p_suffix.length()); + } + return s; +} + bool String::is_valid_integer() const { int len = length(); @@ -3478,13 +3520,13 @@ bool String::is_valid_hex_number(bool p_with_prefix) const { if (p_with_prefix) { - if (len < 2) + if (len < 3) return false; if (operator[](from) != '0' || operator[](from + 1) != 'x') { return false; - }; + } from += 2; - }; + } for (int i = from; i < len; i++) { @@ -3492,7 +3534,7 @@ bool String::is_valid_hex_number(bool p_with_prefix) const { if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) continue; return false; - }; + } return true; }; diff --git a/core/ustring.h b/core/ustring.h index bb676ce623..1ed694bb80 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -137,6 +137,8 @@ public: String insert(int p_at_pos, const String &p_string) const; String pad_decimals(int p_digits) const; String pad_zeros(int p_digits) const; + String trim_prefix(const String &p_prefix) const; + String trim_suffix(const String &p_suffix) const; String lpad(int min_length, const String &character = " ") const; String rpad(int min_length, const String &character = " ") const; String sprintf(const Array &values, bool *error) const; @@ -188,6 +190,8 @@ public: String dedent() const; String strip_edges(bool left = true, bool right = true) const; String strip_escapes() const; + String lstrip(const Vector<CharType> &p_chars) const; + String rstrip(const Vector<CharType> &p_chars) const; String get_extension() const; String get_basename() const; String plus_file(const String &p_file) const; diff --git a/core/variant_call.cpp b/core/variant_call.cpp index c6e093010d..d05c7b174c 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -264,6 +264,8 @@ struct _VariantCall { VCALL_LOCALMEM1R(String, right); VCALL_LOCALMEM0R(String, dedent); VCALL_LOCALMEM2R(String, strip_edges); + VCALL_LOCALMEM1R(String, lstrip); + VCALL_LOCALMEM1R(String, rstrip); VCALL_LOCALMEM0R(String, get_extension); VCALL_LOCALMEM0R(String, get_basename); VCALL_LOCALMEM1R(String, plus_file); @@ -296,6 +298,8 @@ struct _VariantCall { VCALL_LOCALMEM0R(String, hex_to_int); VCALL_LOCALMEM1R(String, pad_decimals); VCALL_LOCALMEM1R(String, pad_zeros); + VCALL_LOCALMEM1R(String, trim_prefix); + VCALL_LOCALMEM1R(String, trim_suffix); static void _call_String_to_ascii(Variant &r_ret, Variant &p_self, const Variant **p_args) { @@ -1460,6 +1464,8 @@ void register_variant_methods() { ADDFUNC1R(STRING, STRING, String, left, INT, "position", varray()); ADDFUNC1R(STRING, STRING, String, right, INT, "position", varray()); ADDFUNC2R(STRING, STRING, String, strip_edges, BOOL, "left", BOOL, "right", varray(true, true)); + ADDFUNC1R(STRING, STRING, String, lstrip, STRING, "chars", varray()); + ADDFUNC1R(STRING, STRING, String, rstrip, STRING, "chars", varray()); ADDFUNC0R(STRING, STRING, String, get_extension, varray()); ADDFUNC0R(STRING, STRING, String, get_basename, varray()); ADDFUNC1R(STRING, STRING, String, plus_file, STRING, "file", varray()); @@ -1493,6 +1499,8 @@ void register_variant_methods() { ADDFUNC0R(STRING, INT, String, hex_to_int, varray()); ADDFUNC1R(STRING, STRING, String, pad_decimals, INT, "digits", varray()); ADDFUNC1R(STRING, STRING, String, pad_zeros, INT, "digits", varray()); + ADDFUNC1R(STRING, STRING, String, trim_prefix, STRING, "prefix", varray()); + ADDFUNC1R(STRING, STRING, String, trim_suffix, STRING, "suffix", varray()); ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, to_ascii, varray()); ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, to_utf8, varray()); diff --git a/core/variant_op.cpp b/core/variant_op.cpp index 8ad981ed0e..621af2dfb7 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -1459,13 +1459,13 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool v->a = p_value._data._int / 255.0; valid = true; } else if (p_index == CoreStringNames::singleton->h) { - v->set_hsv(p_value._data._int, v->get_s(), v->get_v()); + v->set_hsv(p_value._data._int, v->get_s(), v->get_v(), v->a); valid = true; } else if (p_index == CoreStringNames::singleton->s) { - v->set_hsv(v->get_h(), p_value._data._int, v->get_v()); + v->set_hsv(v->get_h(), p_value._data._int, v->get_v(), v->a); valid = true; } else if (p_index == CoreStringNames::singleton->v) { - v->set_hsv(v->get_h(), v->get_v(), p_value._data._int); + v->set_hsv(v->get_h(), v->get_v(), p_value._data._int, v->a); valid = true; } } else if (p_value.type == Variant::REAL) { @@ -1495,13 +1495,13 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool v->a = p_value._data._real / 255.0; valid = true; } else if (p_index == CoreStringNames::singleton->h) { - v->set_hsv(p_value._data._real, v->get_s(), v->get_v()); + v->set_hsv(p_value._data._real, v->get_s(), v->get_v(), v->a); valid = true; } else if (p_index == CoreStringNames::singleton->s) { - v->set_hsv(v->get_h(), p_value._data._real, v->get_v()); + v->set_hsv(v->get_h(), p_value._data._real, v->get_v(), v->a); valid = true; } else if (p_index == CoreStringNames::singleton->v) { - v->set_hsv(v->get_h(), v->get_s(), p_value._data._real); + v->set_hsv(v->get_h(), v->get_s(), p_value._data._real, v->a); valid = true; } } @@ -2117,15 +2117,15 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) return; } else if (*str == "h") { valid = true; - v->set_hsv(p_value, v->get_s(), v->get_v()); + v->set_hsv(p_value, v->get_s(), v->get_v(), v->a); return; } else if (*str == "s") { valid = true; - v->set_hsv(v->get_h(), p_value, v->get_v()); + v->set_hsv(v->get_h(), p_value, v->get_v(), v->a); return; } else if (*str == "v") { valid = true; - v->set_hsv(v->get_h(), v->get_s(), p_value); + v->set_hsv(v->get_h(), v->get_s(), p_value, v->a); return; } else if (*str == "r8") { valid = true; @@ -3728,8 +3728,9 @@ static const char *_op_names[Variant::OP_MAX] = { "*", "/", "- (negation)", + "+ (positive)", "%", - "..", + "+ (concatenation)", "<<", ">>", "&", |