diff options
107 files changed, 1877 insertions, 993 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 85793f127d..34d48b2b09 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++) { 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/input_map.cpp b/core/input_map.cpp index ea724d2595..973edcb5b5 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..a00be8c859 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/http_client.cpp b/core/io/http_client.cpp index c787b7ec4c..9e301ccac5 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -618,14 +618,14 @@ String HTTPClient::query_string_from_dict(const Dictionary &p_dict) { String query = ""; Array keys = p_dict.keys(); for (int i = 0; i < keys.size(); ++i) { - String encoded_key = String(keys[i]).percent_encode(); + String encoded_key = String(keys[i]).http_escape(); Variant value = p_dict[keys[i]]; switch (value.get_type()) { case Variant::ARRAY: { // Repeat the key with every values Array values = value; for (int j = 0; j < values.size(); ++j) { - query += "&" + encoded_key + "=" + String(values[j]).percent_encode(); + query += "&" + encoded_key + "=" + String(values[j]).http_escape(); } break; } @@ -636,7 +636,7 @@ String HTTPClient::query_string_from_dict(const Dictionary &p_dict) { } default: { // Add the key-value pair - query += "&" + encoded_key + "=" + String(value).percent_encode(); + query += "&" + encoded_key + "=" + String(value).http_escape(); } } } diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 26e87f009b..20001bb9a6 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -215,11 +215,11 @@ public: } static _ALWAYS_INLINE_ double wrapf(double value, double min, double max) { double rng = max - min; - return min + (value - min) - (rng * Math::floor((value - min) / rng)); + return value - (rng * Math::floor((value - min) / rng)); } static _ALWAYS_INLINE_ float wrapf(float value, float min, float max) { float rng = max - min; - return min + (value - min) - (rng * Math::floor((value - min) / rng)); + return value - (rng * Math::floor((value - min) / rng)); } // double only, as these functions are mainly used by the editor and not performance-critical, 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/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..bdb61cbfd9 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,23 @@ 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 && ((axis_value < 0) == (jm->axis_value < 0) || jm->axis_value == 0)); + if (match) { + if (p_pressed != NULL) + *p_pressed = Math::abs(jm->get_axis_value() >= p_deadzone); + if (p_strength != NULL) + *p_strength = (*p_pressed) ? Math::inverse_lerp(p_deadzone, 1.0f, Math::abs(jm->get_axis_value())) : 0.0f; + } + return match; } String InputEventJoypadMotion::as_text() const { @@ -681,13 +718,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..d3a62263ac 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; } 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/ustring.cpp b/core/ustring.cpp index d749146998..954f590218 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -3165,7 +3165,7 @@ String String::word_wrap(int p_chars_per_line) const { return ret; } -String String::percent_encode() const { +String String::http_escape() const { const CharString temp = utf8(); String res; for (int i = 0; i < temp.length(); ++i) { @@ -3189,7 +3189,7 @@ String String::percent_encode() const { return res; } -String String::percent_decode() const { +String String::http_unescape() const { String res; for (int i = 0; i < length(); ++i) { if (ord_at(i) == '%' && i + 2 < length()) { @@ -3727,6 +3727,68 @@ String String::plus_file(const String &p_file) const { return *this + "/" + p_file; } +String String::percent_encode() const { + + CharString cs = utf8(); + String encoded; + for (int i = 0; i < cs.length(); i++) { + uint8_t c = cs[i]; + if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '~' || c == '.') { + + char p[2] = { (char)c, 0 }; + encoded += p; + } else { + char p[4] = { '%', 0, 0, 0 }; + static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + + p[1] = hex[c >> 4]; + p[2] = hex[c & 0xF]; + encoded += p; + } + } + + return encoded; +} +String String::percent_decode() const { + + CharString pe; + + CharString cs = utf8(); + for (int i = 0; i < cs.length(); i++) { + + uint8_t c = cs[i]; + if (c == '%' && i < length() - 2) { + + uint8_t a = LOWERCASE(cs[i + 1]); + uint8_t b = LOWERCASE(cs[i + 2]); + + c = 0; + if (a >= '0' && a <= '9') + c = (a - '0') << 4; + else if (a >= 'a' && a <= 'f') + c = (a - 'a' + 10) << 4; + else + continue; + + uint8_t d = 0; + + if (b >= '0' && b <= '9') + d = (b - '0'); + else if (b >= 'a' && b <= 'f') + d = (b - 'a' + 10); + else + continue; + c += d; + i += 2; + } + pe.push_back(c); + } + + pe.push_back(0); + + return String::utf8(pe.ptr()); +} + String String::get_basename() const { int pos = find_last("."); diff --git a/core/ustring.h b/core/ustring.h index 8023c9b95d..bb676ce623 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -226,14 +226,17 @@ public: String xml_escape(bool p_escape_quotes = false) const; String xml_unescape() const; - String percent_encode() const; - String percent_decode() const; + String http_escape() const; + String http_unescape() const; String c_escape() const; String c_escape_multiline() const; String c_unescape() const; String json_escape() const; String word_wrap(int p_chars_per_line) const; + String percent_encode() const; + String percent_decode() const; + bool is_valid_identifier() const; bool is_valid_integer() const; bool is_valid_float() const; diff --git a/core/variant_op.cpp b/core/variant_op.cpp index 8ad981ed0e..4e37593915 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -3728,8 +3728,9 @@ static const char *_op_names[Variant::OP_MAX] = { "*", "/", "- (negation)", + "+ (positive)", "%", - "..", + "+ (concatenation)", "<<", ">>", "&", diff --git a/doc/classes/@GDScript.xml b/doc/classes/@GDScript.xml index 07e428faad..acece05510 100644 --- a/doc/classes/@GDScript.xml +++ b/doc/classes/@GDScript.xml @@ -326,7 +326,8 @@ <argument index="0" name="s" type="float"> </argument> <description> - Raises the Euler's constant [b]e[/b] to the power of [code]s[/code] and returns it. [b]e[/b] has an approximate value of 2.71828. + The natural exponential function. It raises the mathematical constant [b]e[/b] to the power of [code]s[/code] and returns it. + [b]e[/b] has an approximate value of 2.71828. [codeblock] a = exp(2) # approximately 7.39 [/codeblock] diff --git a/doc/classes/AnimationPlayer.xml b/doc/classes/AnimationPlayer.xml index f3280e7a27..673bbbea59 100644 --- a/doc/classes/AnimationPlayer.xml +++ b/doc/classes/AnimationPlayer.xml @@ -8,7 +8,7 @@ </description> <tutorials> http://docs.godotengine.org/en/3.0/getting_started/step_by_step/animations.html - http://docs.godotengine.org/en/3.0/tutorials/animation/index.html + http://docs.godotengine.org/en/3.0/tutorials/animation/index.html </tutorials> <demos> </demos> @@ -138,8 +138,7 @@ <argument index="3" name="from_end" type="bool" default="false"> </argument> <description> - Play the animation with key [code]name[/code]. Custom speed and blend times can be set. If custom speed is negative (-1), 'from_end' being true can play the - animation backwards. + Play the animation with key [code]name[/code]. Custom speed and blend times can be set. If custom speed is negative (-1), 'from_end' being true can play the animation backwards. </description> </method> <method name="play_backwards"> diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml index 8846616851..dec0cbbcc3 100644 --- a/doc/classes/SceneTree.xml +++ b/doc/classes/SceneTree.xml @@ -367,12 +367,16 @@ </signals> <constants> <constant name="GROUP_CALL_DEFAULT" value="0" enum="GroupCallFlags"> + Call a group with no flags (default). </constant> <constant name="GROUP_CALL_REVERSE" value="1" enum="GroupCallFlags"> + Call a group in reverse scene order. </constant> <constant name="GROUP_CALL_REALTIME" value="2" enum="GroupCallFlags"> + Call a group immediately (calls are normally made on idle). </constant> <constant name="GROUP_CALL_UNIQUE" value="4" enum="GroupCallFlags"> + Call a group only once even if the call is executed many times. </constant> <constant name="STRETCH_MODE_DISABLED" value="0" enum="StretchMode"> </constant> diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index 070c661c8a..1f3b76f5cd 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -795,7 +795,6 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_HEIGHT"] = "light_height"; actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_COLOR"] = "light_color"; actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_UV"] = "light_uv"; - //actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_SHADOW_COLOR"]="light_shadow_color"; actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT"] = "light"; actions[VS::SHADER_CANVAS_ITEM].renames["SHADOW_COLOR"] = "shadow_color"; @@ -805,9 +804,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_PIXEL_SIZE"] = "@SCREEN_UV"; actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMAL"] = "#define NORMAL_USED\n"; actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["SHADOW_COLOR"] = "#define SHADOW_COLOR_USED\n"; actions[VS::SHADER_CANVAS_ITEM].usage_defines["LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; - actions[VS::SHADER_CANVAS_ITEM].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; /** SPATIAL SHADER **/ diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index f436ef06f7..3bbeb1149d 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -285,7 +285,19 @@ MATERIAL_UNIFORMS FRAGMENT_SHADER_GLOBALS -void light_compute(inout vec4 light,vec2 light_vec,float light_height,vec4 light_color,vec2 light_uv,vec4 shadow,vec3 normal,vec2 uv,vec2 screen_uv,vec4 color) { +void light_compute( + inout vec4 light, + inout vec2 light_vec, + inout float light_height, + inout vec4 light_color, + vec2 light_uv, + inout vec4 shadow_color, + vec3 normal, + vec2 uv, +#if defined(SCREEN_UV_USED) + vec2 screen_uv, +#endif + vec4 color) { #if defined(USE_LIGHT_SHADER_CODE) @@ -462,39 +474,41 @@ FRAGMENT_SHADER_CODE float att=1.0; vec2 light_uv = light_uv_interp.xy; - vec4 light = texture(light_texture,light_uv) * light_color; -#if defined(SHADOW_COLOR_USED) - vec4 shadow_color=vec4(0.0,0.0,0.0,0.0); -#endif + vec4 light = texture(light_texture,light_uv); if (any(lessThan(light_uv_interp.xy,vec2(0.0,0.0))) || any(greaterThanEqual(light_uv_interp.xy,vec2(1.0,1.0)))) { color.a*=light_outside_alpha; //invisible } else { + float real_light_height = light_height; + vec4 real_light_color = light_color; + vec4 real_light_shadow_color = light_shadow_color; #if defined(USE_LIGHT_SHADER_CODE) //light is written by the light shader - light_compute(light,light_vec,light_height,light_color,light_uv,shadow,normal,uv,screen_uv,color); + light_compute( + light, + light_vec, + real_light_height, + real_light_color, + light_uv, + real_light_shadow_color, + normal, + uv, +#if defined(SCREEN_UV_USED) + screen_uv, +#endif + color); +#endif -#else + light *= real_light_color; if (normal_used) { - - vec3 light_normal = normalize(vec3(light_vec,-light_height)); + vec3 light_normal = normalize(vec3(light_vec,-real_light_height)); light*=max(dot(-light_normal,normal),0.0); } color*=light; -/* -#ifdef USE_NORMAL - color.xy=local_rot.xy;//normal.xy; - color.zw=vec2(0.0,1.0); -#endif -*/ - -//light shader code -#endif - #ifdef USE_SHADOWS @@ -634,13 +648,8 @@ FRAGMENT_SHADER_CODE #endif - -#if defined(SHADOW_COLOR_USED) - color=mix(shadow_color,color,shadow_attenuation); -#else //color*=shadow_attenuation; - color=mix(light_shadow_color,color,shadow_attenuation); -#endif + color=mix(real_light_shadow_color,color,shadow_attenuation); //use shadows #endif } diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp index fac73da44d..733c7cc80c 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp +++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp @@ -60,7 +60,7 @@ void AudioDriverPulseAudio::pa_sink_info_cb(pa_context *c, const pa_sink_info *l return; } - ad->pa_channels = l->channel_map.channels; + ad->pa_map = l->channel_map; ad->pa_status++; } @@ -73,7 +73,7 @@ void AudioDriverPulseAudio::pa_server_info_cb(pa_context *c, const pa_server_inf void AudioDriverPulseAudio::detect_channels() { - pa_channels = 2; + pa_channel_map_init_stereo(&pa_map); if (device_name == "Default") { // Get the default output device name @@ -129,60 +129,64 @@ Error AudioDriverPulseAudio::init_device() { } // Detect the amount of channels PulseAudio is using - // Note: If using an even amount of channels (2, 4, etc) channels and pa_channels will be equal, - // if not then pa_channels will have the real amount of channels PulseAudio is using and channels - // will have the amount of channels Godot is using (in this case it's pa_channels + 1) + // Note: If using an even amount of channels (2, 4, etc) channels and pa_map.channels will be equal, + // if not then pa_map.channels will have the real amount of channels PulseAudio is using and channels + // will have the amount of channels Godot is using (in this case it's pa_map.channels + 1) detect_channels(); - switch (pa_channels) { + switch (pa_map.channels) { case 1: // Mono case 3: // Surround 2.1 case 5: // Surround 5.0 case 7: // Surround 7.0 - channels = pa_channels + 1; + channels = pa_map.channels + 1; break; case 2: // Stereo case 4: // Surround 4.0 case 6: // Surround 5.1 case 8: // Surround 7.1 - channels = pa_channels; + channels = pa_map.channels; break; default: - WARN_PRINTS("PulseAudio: Unsupported number of channels: " + itos(pa_channels)); - pa_channels = 2; + WARN_PRINTS("PulseAudio: Unsupported number of channels: " + itos(pa_map.channels)); + pa_channel_map_init_stereo(&pa_map); channels = 2; break; } - pa_sample_spec spec; - spec.format = PA_SAMPLE_S16LE; - spec.channels = pa_channels; - spec.rate = mix_rate; - int latency = GLOBAL_DEF("audio/output_latency", DEFAULT_OUTPUT_LATENCY); buffer_frames = closest_power_of_2(latency * mix_rate / 1000); - pa_buffer_size = buffer_frames * pa_channels; + pa_buffer_size = buffer_frames * pa_map.channels; if (OS::get_singleton()->is_stdout_verbose()) { - print_line("PulseAudio: detected " + itos(pa_channels) + " channels"); + print_line("PulseAudio: detected " + itos(pa_map.channels) + " channels"); print_line("PulseAudio: audio buffer frames: " + itos(buffer_frames) + " calculated latency: " + itos(buffer_frames * 1000 / mix_rate) + "ms"); } + pa_sample_spec spec; + spec.format = PA_SAMPLE_S16LE; + spec.channels = pa_map.channels; + spec.rate = mix_rate; + + pa_str = pa_stream_new(pa_ctx, "Sound", &spec, &pa_map); + if (pa_str == NULL) { + ERR_PRINTS("PulseAudio: pa_stream_new error: " + String(pa_strerror(pa_context_errno(pa_ctx)))); + ERR_FAIL_V(ERR_CANT_OPEN); + } + pa_buffer_attr attr; // set to appropriate buffer length (in bytes) from global settings - attr.tlength = pa_buffer_size * sizeof(int16_t); + // Note: PulseAudio defaults to 4 fragments, which means that the actual + // latency is tlength / fragments. It seems that the PulseAudio has no way + // to get the fragments number so we're hardcoding this to the default of 4 + const int fragments = 4; + attr.tlength = pa_buffer_size * sizeof(int16_t) * fragments; // set them to be automatically chosen attr.prebuf = (uint32_t)-1; attr.maxlength = (uint32_t)-1; attr.minreq = (uint32_t)-1; - pa_str = pa_stream_new(pa_ctx, "Sound", &spec, NULL); - if (pa_str == NULL) { - ERR_PRINTS("PulseAudio: pa_stream_new error: " + String(pa_strerror(pa_context_errno(pa_ctx)))); - ERR_FAIL_V(ERR_CANT_OPEN); - } - const char *dev = device_name == "Default" ? NULL : device_name.utf8().get_data(); pa_stream_flags flags = pa_stream_flags(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE); int error_code = pa_stream_connect_playback(pa_str, dev, &attr, flags, NULL, NULL); @@ -297,7 +301,7 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { ad->unlock(); - if (ad->channels == ad->pa_channels) { + if (ad->channels == ad->pa_map.channels) { for (unsigned int i = 0; i < ad->pa_buffer_size; i++) { ad->samples_out[i] = ad->samples_in[i] >> 16; } @@ -307,7 +311,7 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { unsigned int out_idx = 0; for (unsigned int i = 0; i < ad->buffer_frames; i++) { - for (unsigned int j = 0; j < ad->pa_channels - 1; j++) { + for (unsigned int j = 0; j < ad->pa_map.channels - 1; j++) { ad->samples_out[out_idx++] = ad->samples_in[in_idx++] >> 16; } uint32_t l = ad->samples_in[in_idx++]; @@ -516,7 +520,6 @@ AudioDriverPulseAudio::AudioDriverPulseAudio() { buffer_frames = 0; pa_buffer_size = 0; channels = 0; - pa_channels = 0; pa_ready = 0; pa_status = 0; diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.h b/drivers/pulseaudio/audio_driver_pulseaudio.h index 934031e2a5..b471f5f9d5 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.h +++ b/drivers/pulseaudio/audio_driver_pulseaudio.h @@ -47,6 +47,7 @@ class AudioDriverPulseAudio : public AudioDriver { pa_mainloop *pa_ml; pa_context *pa_ctx; pa_stream *pa_str; + pa_channel_map pa_map; String device_name; String new_device; @@ -59,7 +60,6 @@ class AudioDriverPulseAudio : public AudioDriver { unsigned int buffer_frames; unsigned int pa_buffer_size; int channels; - int pa_channels; int pa_ready; int pa_status; Array pa_devices; diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index 23c8ea2ec7..d4b8a8c361 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -78,6 +78,7 @@ Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) { /* pretty much every implementation that uses fopen as primary backend supports utf8 encoding */ + struct _stat st; if (_wstat(path.c_str(), &st) == 0) { @@ -85,6 +86,23 @@ Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) { return ERR_FILE_CANT_OPEN; }; +#ifdef TOOLS_ENABLED + if (p_mode_flags==READ) { + WIN32_FIND_DATAW d = {0}; + HANDLE f = FindFirstFileW(filename.c_str(),&d); + if (f) { + String fname = d.cFileName; + if (fname!=String()) { + + String base_file = filename.get_file(); + if (base_file!=fname && base_file.findn(fname)==0) { + WARN_PRINTS("Case mismatch opening file '"+base_file+"', stored as '"+fname+"' in the filesystem. This file will not open when exported to other platforms."); + } + } + FindClose(f); + } + } +#endif if (is_backup_save_enabled() && p_mode_flags & WRITE && !(p_mode_flags & READ)) { save_path = path; path = path + ".tmp"; diff --git a/editor/icons/icon_editor_position.svg b/editor/icons/icon_editor_position.svg new file mode 100644 index 0000000000..7cbce07fab --- /dev/null +++ b/editor/icons/icon_editor_position.svg @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg919" + sodipodi:docname="icon_editor_position.svg" + inkscape:version="0.92.2 5c3e80d, 2017-08-06"> + <metadata + id="metadata925"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs923" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="2550" + inkscape:window-height="1414" + id="namedview921" + showgrid="false" + inkscape:zoom="64" + inkscape:cx="13.492036" + inkscape:cy="5.8518769" + inkscape:window-x="1370" + inkscape:window-y="20" + inkscape:window-maximized="0" + inkscape:current-layer="svg919" + inkscape:snap-page="true" /> + <g + id="g6479"> + <path + id="path913" + d="M 6 0 L 6 4.4199219 A 4.2661548 4.0576186 0 0 0 4.2910156 6 L 0 6 L 0 10 L 4.2949219 10 A 4.2661548 4.0576186 0 0 0 6 11.582031 L 6 16 L 10 16 L 10 11.580078 A 4.2661548 4.0576186 0 0 0 11.708984 10 L 16 10 L 16 6 L 11.705078 6 A 4.2661548 4.0576186 0 0 0 10 4.4179688 L 10 0 L 6 0 z " + style="fill:#ffffff;fill-opacity:0.70588237" /> + <path + id="path915" + d="M 7 1 L 7 4.0605469 A 4.2661548 4.0576186 0 0 1 8 3.9414062 A 4.2661548 4.0576186 0 0 1 9 4.0605469 L 9 1 L 7 1 z M 1 7 L 1 9 L 3.8691406 9 A 4.2661548 4.0576186 0 0 1 3.734375 8 A 4.2661548 4.0576186 0 0 1 3.8710938 7 L 1 7 z M 12.130859 7 A 4.2661548 4.0576186 0 0 1 12.265625 8 A 4.2661548 4.0576186 0 0 1 12.128906 9 L 15 9 L 15 7 L 12.130859 7 z M 7 11.939453 L 7 15 L 9 15 L 9 11.939453 A 4.2661548 4.0576186 0 0 1 8 12.058594 A 4.2661548 4.0576186 0 0 1 7 11.939453 z " + style="fill:#ff8484;stroke:none;fill-opacity:1" /> + <circle + id="circle1517" + r="2.9201488" + cy="8" + cx="8" + style="fill:#ff8484;fill-opacity:1;stroke-width:0.97338283" /> + </g> +</svg> diff --git a/editor/icons/icon_editor_position_previous.svg b/editor/icons/icon_editor_position_previous.svg new file mode 100644 index 0000000000..d9eb7d7ce2 --- /dev/null +++ b/editor/icons/icon_editor_position_previous.svg @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg919" + sodipodi:docname="icon_editor_position_previous.svg" + inkscape:version="0.92.2 5c3e80d, 2017-08-06"> + <metadata + id="metadata925"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs923" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1356" + inkscape:window-height="742" + id="namedview921" + showgrid="false" + inkscape:zoom="11.313709" + inkscape:cx="14.523034" + inkscape:cy="-5.7323703" + inkscape:window-x="4" + inkscape:window-y="20" + inkscape:window-maximized="0" + inkscape:current-layer="svg919" + inkscape:snap-page="true" /> + <path + style="fill:#6699ff;stroke:none;fill-opacity:0.69803923" + d="M 7 1 L 7 4.0605469 A 4.2661548 4.0576186 0 0 1 8 3.9414062 A 4.2661548 4.0576186 0 0 1 9 4.0605469 L 9 1 L 7 1 z M 1 7 L 1 9 L 3.8691406 9 A 4.2661548 4.0576186 0 0 1 3.734375 8 A 4.2661548 4.0576186 0 0 1 3.8710938 7 L 1 7 z M 12.130859 7 A 4.2661548 4.0576186 0 0 1 12.265625 8 A 4.2661548 4.0576186 0 0 1 12.128906 9 L 15 9 L 15 7 L 12.130859 7 z M 7 11.939453 L 7 15 L 9 15 L 9 11.939453 A 4.2661548 4.0576186 0 0 1 8 12.058594 A 4.2661548 4.0576186 0 0 1 7 11.939453 z " + id="path915" /> + <circle + style="fill:#6699ff;fill-opacity:0.69803923;stroke-width:0.97338283" + cx="8" + cy="8" + r="2.9201488" + id="circle1517" /> +</svg> diff --git a/editor/icons/icon_editor_position_unselected.svg b/editor/icons/icon_editor_position_unselected.svg new file mode 100644 index 0000000000..8f32c89f16 --- /dev/null +++ b/editor/icons/icon_editor_position_unselected.svg @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg919" + sodipodi:docname="icon_editor_position_unselected.svg" + inkscape:version="0.92.2 5c3e80d, 2017-08-06"> + <metadata + id="metadata925"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs923" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="2550" + inkscape:window-height="1414" + id="namedview921" + showgrid="false" + inkscape:zoom="64" + inkscape:cx="13.492036" + inkscape:cy="8.3518769" + inkscape:window-x="1370" + inkscape:window-y="20" + inkscape:window-maximized="0" + inkscape:current-layer="svg919" + inkscape:snap-page="true" /> + <path + style="fill:#000000;fill-opacity:0.41077441" + d="M 6 0 L 6 4.4199219 A 4.2661548 4.0576186 0 0 0 4.2910156 6 L 0 6 L 0 10 L 4.2949219 10 A 4.2661548 4.0576186 0 0 0 6 11.582031 L 6 16 L 10 16 L 10 11.580078 A 4.2661548 4.0576186 0 0 0 11.708984 10 L 16 10 L 16 6 L 11.705078 6 A 4.2661548 4.0576186 0 0 0 10 4.4179688 L 10 0 L 6 0 z " + id="path913" /> + <path + style="fill:#d9d9d9;stroke:none;fill-opacity:1" + d="M 7 1 L 7 4.0605469 A 4.2661548 4.0576186 0 0 1 8 3.9414062 A 4.2661548 4.0576186 0 0 1 9 4.0605469 L 9 1 L 7 1 z M 1 7 L 1 9 L 3.8691406 9 A 4.2661548 4.0576186 0 0 1 3.734375 8 A 4.2661548 4.0576186 0 0 1 3.8710938 7 L 1 7 z M 12.130859 7 A 4.2661548 4.0576186 0 0 1 12.265625 8 A 4.2661548 4.0576186 0 0 1 12.128906 9 L 15 9 L 15 7 L 12.130859 7 z M 7 11.939453 L 7 15 L 9 15 L 9 11.939453 A 4.2661548 4.0576186 0 0 1 8 12.058594 A 4.2661548 4.0576186 0 0 1 7 11.939453 z " + id="path915" /> + <circle + style="fill:#d9d9d9;fill-opacity:1;stroke-width:0.97338283" + cx="8" + cy="8" + r="2.9201488" + id="circle1517" /> +</svg> diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index b72c9b25be..c203b4b81e 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -902,7 +902,7 @@ void EditorAssetLibrary::_search(int p_page) { } if (filter->get_text() != String()) { - args += "&filter=" + filter->get_text().percent_encode(); + args += "&filter=" + filter->get_text().http_escape(); } if (p_page > 0) { diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index b8d0958c99..bb94aee462 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -196,11 +196,15 @@ void CanvasItemEditor::_snap_other_nodes(Point2 p_value, Point2 &r_current_snap, Transform2D ci_transform = canvas_item->get_global_transform_with_canvas(); Transform2D to_snap_transform = p_to_snap ? p_to_snap->get_global_transform_with_canvas() : Transform2D(); if (fmod(ci_transform.get_rotation() - to_snap_transform.get_rotation(), (real_t)360.0) == 0.0) { - Point2 begin = ci_transform.xform(canvas_item->_edit_get_rect().get_position()); - Point2 end = ci_transform.xform(canvas_item->_edit_get_rect().get_position() + canvas_item->_edit_get_rect().get_size()); - - _snap_if_closer_point(p_value, begin, r_current_snap, r_snapped, ci_transform.get_rotation()); - _snap_if_closer_point(p_value, end, r_current_snap, r_snapped, ci_transform.get_rotation()); + if (canvas_item->_edit_use_rect()) { + Point2 begin = ci_transform.xform(canvas_item->_edit_get_rect().get_position()); + Point2 end = ci_transform.xform(canvas_item->_edit_get_rect().get_position() + canvas_item->_edit_get_rect().get_size()); + _snap_if_closer_point(p_value, begin, r_current_snap, r_snapped, ci_transform.get_rotation()); + _snap_if_closer_point(p_value, end, r_current_snap, r_snapped, ci_transform.get_rotation()); + } else { + Point2 position = ci_transform.xform(Point2()); + _snap_if_closer_point(p_value, position, r_current_snap, r_snapped, ci_transform.get_rotation()); + } } } for (int i = 0; i < p_current->get_child_count(); i++) { @@ -221,23 +225,23 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const // Parent sides and center if ((is_snap_active && snap_node_parent && (p_modes & SNAP_NODE_PARENT)) || (p_forced_modes & SNAP_NODE_PARENT)) { - Point2 begin; - Point2 end; - bool can_snap = false; if (const Control *c = Object::cast_to<Control>(p_canvas_item)) { - begin = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(0, 0))); - end = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(1, 1))); - can_snap = true; - } else if (const CanvasItem *parent_ci = Object::cast_to<CanvasItem>(p_canvas_item->get_parent())) { - begin = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->_edit_get_rect().get_position()); - end = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->_edit_get_rect().get_position() + parent_ci->_edit_get_rect().get_size()); - can_snap = true; - } - - if (can_snap) { + Point2 begin = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(0, 0))); + Point2 end = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(1, 1))); _snap_if_closer_point(p_target, begin, output, snapped, rotation); _snap_if_closer_point(p_target, (begin + end) / 2.0, output, snapped, rotation); _snap_if_closer_point(p_target, end, output, snapped, rotation); + } else if (const CanvasItem *parent_ci = Object::cast_to<CanvasItem>(p_canvas_item->get_parent())) { + if (parent_ci->_edit_use_rect()) { + Point2 begin = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->_edit_get_rect().get_position()); + Point2 end = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->_edit_get_rect().get_position() + parent_ci->_edit_get_rect().get_size()); + _snap_if_closer_point(p_target, begin, output, snapped, rotation); + _snap_if_closer_point(p_target, (begin + end) / 2.0, output, snapped, rotation); + _snap_if_closer_point(p_target, end, output, snapped, rotation); + } else { + Point2 position = p_canvas_item->get_transform().affine_inverse().xform(Point2()); + _snap_if_closer_point(p_target, position, output, snapped, rotation); + } } } @@ -253,16 +257,23 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const // Self sides if ((is_snap_active && snap_node_sides && (p_modes & SNAP_NODE_SIDES)) || (p_forced_modes & SNAP_NODE_SIDES)) { - Point2 begin = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position()); - Point2 end = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position() + p_canvas_item->_edit_get_rect().get_size()); - _snap_if_closer_point(p_target, begin, output, snapped, rotation); - _snap_if_closer_point(p_target, end, output, snapped, rotation); + if (p_canvas_item->_edit_use_rect()) { + Point2 begin = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position()); + Point2 end = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position() + p_canvas_item->_edit_get_rect().get_size()); + _snap_if_closer_point(p_target, begin, output, snapped, rotation); + _snap_if_closer_point(p_target, end, output, snapped, rotation); + } } // Self center if ((is_snap_active && snap_node_center && (p_modes & SNAP_NODE_CENTER)) || (p_forced_modes & SNAP_NODE_CENTER)) { - Point2 center = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position() + p_canvas_item->_edit_get_rect().get_size() / 2.0); - _snap_if_closer_point(p_target, center, output, snapped, rotation); + if (p_canvas_item->_edit_use_rect()) { + Point2 center = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position() + p_canvas_item->_edit_get_rect().get_size() / 2.0); + _snap_if_closer_point(p_target, center, output, snapped, rotation); + } else { + Point2 position = p_canvas_item->get_global_transform_with_canvas().xform(Point2()); + _snap_if_closer_point(p_target, position, output, snapped, rotation); + } } } @@ -364,63 +375,85 @@ Rect2 CanvasItemEditor::_get_encompassing_rect_from_list(List<CanvasItem *> p_li // Handles the first element CanvasItem *canvas_item = p_list.front()->get(); - Rect2 rect = Rect2(canvas_item->get_global_transform_with_canvas().xform(canvas_item->_edit_get_rect().position + canvas_item->_edit_get_rect().size / 2), Size2()); + Rect2 rect; + if (canvas_item->_edit_use_rect()) { + rect = Rect2(canvas_item->get_global_transform_with_canvas().xform(canvas_item->_edit_get_rect().position + canvas_item->_edit_get_rect().size / 2), Size2()); + } else { + rect = Rect2(canvas_item->get_global_transform_with_canvas().xform(Point2()), Size2()); + } - // Handles the other ones + // Expand with the other ones for (List<CanvasItem *>::Element *E = p_list.front(); E; E = E->next()) { CanvasItem *canvas_item = E->get(); - Rect2 current_rect = canvas_item->_edit_get_rect(); Transform2D xform = canvas_item->get_global_transform_with_canvas(); - rect.expand_to(xform.xform(current_rect.position)); - rect.expand_to(xform.xform(current_rect.position + Vector2(current_rect.size.x, 0))); - rect.expand_to(xform.xform(current_rect.position + current_rect.size)); - rect.expand_to(xform.xform(current_rect.position + Vector2(0, current_rect.size.y))); + if (canvas_item->_edit_use_rect()) { + Rect2 current_rect = canvas_item->_edit_get_rect(); + + rect.expand_to(xform.xform(current_rect.position)); + rect.expand_to(xform.xform(current_rect.position + Vector2(current_rect.size.x, 0))); + rect.expand_to(xform.xform(current_rect.position + current_rect.size)); + rect.expand_to(xform.xform(current_rect.position + Vector2(0, current_rect.size.y))); + } else { + rect.expand_to(xform.xform(Point2())); + } } return rect; } -void CanvasItemEditor::_expand_encompassing_rect_using_children(Rect2 &r_rect, Node *p_node, bool &r_first, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) { +void CanvasItemEditor::_expand_encompassing_rect_using_children(Rect2 &r_rect, const Node *p_node, bool &r_first, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) { if (!p_node) return; if (Object::cast_to<Viewport>(p_node)) return; - CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node); + const CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node); - bool inherited = p_node != get_tree()->get_edited_scene_root() && p_node->get_filename() != ""; - bool editable = inherited && EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node); + /*bool inherited = p_node != get_tree()->get_edited_scene_root() && p_node->get_filename() != ""; + bool editable = !inherited || EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node); bool lock_children = p_node->has_meta("_edit_group_") && p_node->get_meta("_edit_group_"); - if (!lock_children && (!inherited || editable)) { - for (int i = p_node->get_child_count() - 1; i >= 0; i--) { - if (canvas_item && !canvas_item->is_set_as_toplevel()) { - _expand_encompassing_rect_using_children(r_rect, p_node->get_child(i), r_first, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); - } else { - CanvasLayer *canvas_layer = Object::cast_to<CanvasLayer>(p_node); - _expand_encompassing_rect_using_children(r_rect, p_node->get_child(i), r_first, Transform2D(), canvas_layer ? canvas_layer->get_transform() : p_canvas_xform); - } + if (!lock_children && editable) {}*/ + + for (int i = p_node->get_child_count() - 1; i >= 0; i--) { + if (canvas_item && !canvas_item->is_set_as_toplevel()) { + _expand_encompassing_rect_using_children(r_rect, p_node->get_child(i), r_first, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); + } else { + const CanvasLayer *canvas_layer = Object::cast_to<CanvasLayer>(p_node); + _expand_encompassing_rect_using_children(r_rect, p_node->get_child(i), r_first, Transform2D(), canvas_layer ? canvas_layer->get_transform() : p_canvas_xform); } } if (canvas_item && canvas_item->is_visible_in_tree() && !canvas_item->has_meta("_edit_lock_")) { - Rect2 rect = canvas_item->_edit_get_rect(); Transform2D xform = p_parent_xform * p_canvas_xform * canvas_item->get_transform(); - if (r_first) { - r_rect = Rect2(xform.xform(rect.position + rect.size / 2), Size2()); - r_first = false; + if (canvas_item->_edit_use_rect()) { + Rect2 rect = canvas_item->_edit_get_rect(); + if (r_first) { + r_rect = Rect2(xform.xform(rect.position + rect.size / 2), Size2()); + r_first = false; + } + if (r_rect.size != Size2()) { + r_rect.expand_to(xform.xform(rect.position)); + r_rect.expand_to(xform.xform(rect.position + Point2(rect.size.x, 0))); + r_rect.expand_to(xform.xform(rect.position + Point2(0, rect.size.y))); + r_rect.expand_to(xform.xform(rect.position + rect.size)); + } + } else { + if (r_first) { + r_rect = Rect2(xform.xform(Point2()), Size2()); + r_first = false; + } else { + r_rect.expand_to(xform.xform(Point2())); + } } - r_rect.expand_to(xform.xform(rect.position)); - r_rect.expand_to(xform.xform(rect.position + Point2(rect.size.x, 0))); - r_rect.expand_to(xform.xform(rect.position + Point2(0, rect.size.y))); - r_rect.expand_to(xform.xform(rect.position + rect.size)); } } -Rect2 CanvasItemEditor::_get_scene_encompassing_rect() { +Rect2 CanvasItemEditor::_get_encompassing_rect(const Node *p_node) { Rect2 rect; bool first = true; - _expand_encompassing_rect_using_children(rect, editor->get_edited_scene(), first); + _expand_encompassing_rect_using_children(rect, p_node, first); + return rect; } @@ -433,22 +466,23 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no const real_t grab_distance = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node); - for (int i = p_node->get_child_count() - 1; i >= 0; i--) { - if (canvas_item && !canvas_item->is_set_as_toplevel()) - _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, 0, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); - else { - CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node); - _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, 0, Transform2D(), cl ? cl->get_transform() : p_canvas_xform); //use base transform + Node *scene = editor->get_edited_scene(); + if (!(p_node != scene && p_node->get_owner() != scene && (!scene->is_editable_instance(p_node) || p_node->has_meta("_edit_lock_")))) { + for (int i = p_node->get_child_count() - 1; i >= 0; i--) { + if (canvas_item && !canvas_item->is_set_as_toplevel()) { + _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, limit, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); + } else { + CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node); + _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, limit, Transform2D(), cl ? cl->get_transform() : p_canvas_xform); + } + if (limit != 0 && r_items.size() >= limit) + return; } - if (limit != 0 && r_items.size() >= limit) - return; } - if (canvas_item && canvas_item->is_visible_in_tree() && !canvas_item->has_meta("_edit_lock_")) { - + if (canvas_item && canvas_item->is_visible_in_tree() && (canvas_item->get_owner() != editor->get_edited_scene() || !canvas_item->has_meta("_edit_lock_"))) { Transform2D xform = (p_parent_xform * p_canvas_xform * canvas_item->get_transform()).affine_inverse(); const real_t local_grab_distance = xform.basis_xform(Vector2(grab_distance, 0)).length(); - if (canvas_item->_edit_is_selected_on_click(xform.xform(p_pos), local_grab_distance)) { Node2D *node = Object::cast_to<Node2D>(canvas_item); @@ -463,7 +497,7 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no return; } -void CanvasItemEditor::_find_canvas_items_at_rect(const Rect2 &p_rect, Node *p_node, List<CanvasItem *> *r_items, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) { +void CanvasItemEditor::_find_canvas_items_in_rect(const Rect2 &p_rect, Node *p_node, List<CanvasItem *> *r_items, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) { if (!p_node) return; if (Object::cast_to<Viewport>(p_node)) @@ -472,31 +506,37 @@ void CanvasItemEditor::_find_canvas_items_at_rect(const Rect2 &p_rect, Node *p_n CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node); bool inherited = p_node != get_tree()->get_edited_scene_root() && p_node->get_filename() != ""; - bool editable = inherited && EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node); + bool editable = !inherited || EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node); bool lock_children = p_node->has_meta("_edit_group_") && p_node->get_meta("_edit_group_"); + bool locked = p_node->has_meta("_edit_lock_") && p_node->get_meta("_edit_lock_"); - if (!lock_children && (!inherited || editable)) { + if (!lock_children && !locked && editable) { for (int i = p_node->get_child_count() - 1; i >= 0; i--) { if (canvas_item && !canvas_item->is_set_as_toplevel()) { - _find_canvas_items_at_rect(p_rect, p_node->get_child(i), r_items, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); + _find_canvas_items_in_rect(p_rect, p_node->get_child(i), r_items, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); } else { CanvasLayer *canvas_layer = Object::cast_to<CanvasLayer>(p_node); - _find_canvas_items_at_rect(p_rect, p_node->get_child(i), r_items, Transform2D(), canvas_layer ? canvas_layer->get_transform() : p_canvas_xform); + _find_canvas_items_in_rect(p_rect, p_node->get_child(i), r_items, Transform2D(), canvas_layer ? canvas_layer->get_transform() : p_canvas_xform); } } } if (canvas_item && canvas_item->is_visible_in_tree() && !canvas_item->has_meta("_edit_lock_")) { - - Rect2 rect = canvas_item->_edit_get_rect(); Transform2D xform = p_parent_xform * p_canvas_xform * canvas_item->get_transform(); - if (p_rect.has_point(xform.xform(rect.position)) && - p_rect.has_point(xform.xform(rect.position + Vector2(rect.size.x, 0))) && - p_rect.has_point(xform.xform(rect.position + Vector2(rect.size.x, rect.size.y))) && - p_rect.has_point(xform.xform(rect.position + Vector2(0, rect.size.y)))) { + if (canvas_item->_edit_use_rect()) { + Rect2 rect = canvas_item->_edit_get_rect(); + if (p_rect.has_point(xform.xform(rect.position)) && + p_rect.has_point(xform.xform(rect.position + Vector2(rect.size.x, 0))) && + p_rect.has_point(xform.xform(rect.position + Vector2(rect.size.x, rect.size.y))) && + p_rect.has_point(xform.xform(rect.position + Vector2(0, rect.size.y)))) { - r_items->push_back(canvas_item); + r_items->push_back(canvas_item); + } + } else { + if (p_rect.has_point(xform.xform(Point2()))) { + r_items->push_back(canvas_item); + } } } } @@ -575,8 +615,11 @@ void CanvasItemEditor::_save_canvas_item_state(List<CanvasItem *> p_canvas_items if (se) { se->undo_state = canvas_item->_edit_get_state(); se->pre_drag_xform = canvas_item->get_global_transform_with_canvas(); - se->pre_drag_rect = canvas_item->_edit_get_rect(); - + if (canvas_item->_edit_use_rect()) { + se->pre_drag_rect = canvas_item->_edit_get_rect(); + } else { + se->pre_drag_rect = Rect2(); + } se->pre_drag_bones_length = List<float>(); se->pre_drag_bones_undo_state = List<Dictionary>(); @@ -1290,54 +1333,55 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) { List<CanvasItem *> selection = _get_edited_canvas_items(); if (selection.size() == 1) { CanvasItem *canvas_item = selection[0]; + if (canvas_item->_edit_use_rect()) { + Rect2 rect = canvas_item->_edit_get_rect(); + Transform2D xform = transform * canvas_item->get_global_transform_with_canvas(); + + Vector2 endpoints[4] = { + xform.xform(rect.position), + xform.xform(rect.position + Vector2(rect.size.x, 0)), + xform.xform(rect.position + rect.size), + xform.xform(rect.position + Vector2(0, rect.size.y)) + }; - Rect2 rect = canvas_item->_edit_get_rect(); - Transform2D xform = transform * canvas_item->get_global_transform_with_canvas(); - - Vector2 endpoints[4] = { - xform.xform(rect.position), - xform.xform(rect.position + Vector2(rect.size.x, 0)), - xform.xform(rect.position + rect.size), - xform.xform(rect.position + Vector2(0, rect.size.y)) - }; - - DragType dragger[] = { - DRAG_TOP_LEFT, - DRAG_TOP, - DRAG_TOP_RIGHT, - DRAG_RIGHT, - DRAG_BOTTOM_RIGHT, - DRAG_BOTTOM, - DRAG_BOTTOM_LEFT, - DRAG_LEFT - }; - - DragType resize_drag = DRAG_NONE; - float radius = (select_handle->get_size().width / 2) * 1.5; - - for (int i = 0; i < 4; i++) { - int prev = (i + 3) % 4; - int next = (i + 1) % 4; + DragType dragger[] = { + DRAG_TOP_LEFT, + DRAG_TOP, + DRAG_TOP_RIGHT, + DRAG_RIGHT, + DRAG_BOTTOM_RIGHT, + DRAG_BOTTOM, + DRAG_BOTTOM_LEFT, + DRAG_LEFT + }; - Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized(); - ofs *= (select_handle->get_size().width / 2); - ofs += endpoints[i]; - if (ofs.distance_to(b->get_position()) < radius) - resize_drag = dragger[i * 2]; + DragType resize_drag = DRAG_NONE; + float radius = (select_handle->get_size().width / 2) * 1.5; - ofs = (endpoints[i] + endpoints[next]) / 2; - ofs += (endpoints[next] - endpoints[i]).tangent().normalized() * (select_handle->get_size().width / 2); - if (ofs.distance_to(b->get_position()) < radius) - resize_drag = dragger[i * 2 + 1]; - } + for (int i = 0; i < 4; i++) { + int prev = (i + 3) % 4; + int next = (i + 1) % 4; + + Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized(); + ofs *= (select_handle->get_size().width / 2); + ofs += endpoints[i]; + if (ofs.distance_to(b->get_position()) < radius) + resize_drag = dragger[i * 2]; + + ofs = (endpoints[i] + endpoints[next]) / 2; + ofs += (endpoints[next] - endpoints[i]).tangent().normalized() * (select_handle->get_size().width / 2); + if (ofs.distance_to(b->get_position()) < radius) + resize_drag = dragger[i * 2 + 1]; + } - if (resize_drag != DRAG_NONE) { - drag_type = resize_drag; - drag_from = transform.affine_inverse().xform(b->get_position()); - drag_selection = List<CanvasItem *>(); - drag_selection.push_back(canvas_item); - _save_canvas_item_state(drag_selection); - return true; + if (resize_drag != DRAG_NONE) { + drag_type = resize_drag; + drag_from = transform.affine_inverse().xform(b->get_position()); + drag_selection = List<CanvasItem *>(); + drag_selection.push_back(canvas_item); + _save_canvas_item_state(drag_selection); + return true; + } } } } @@ -1535,61 +1579,64 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { _save_canvas_item_state(drag_selection, true); } - _restore_canvas_item_state(drag_selection, true); - - bool move_local_base = k->get_alt(); - bool move_local_base_rotated = k->get_control() || k->get_metakey(); - - Vector2 dir; - if (k->get_scancode() == KEY_UP) - dir += Vector2(0, -1); - else if (k->get_scancode() == KEY_DOWN) - dir += Vector2(0, 1); - else if (k->get_scancode() == KEY_LEFT) - dir += Vector2(-1, 0); - else if (k->get_scancode() == KEY_RIGHT) - dir += Vector2(1, 0); - if (k->get_shift()) - dir *= grid_step * Math::pow(2.0, grid_step_multiplier); - - drag_to += dir; - if (k->get_shift()) - drag_to = drag_to.snapped(grid_step * Math::pow(2.0, grid_step_multiplier)); - - Point2 previous_pos; - if (drag_selection.size() == 1) { - Transform2D xform = drag_selection[0]->get_global_transform_with_canvas() * drag_selection[0]->get_transform().affine_inverse(); - previous_pos = xform.xform(drag_selection[0]->_edit_get_position()); - } else { - previous_pos = _get_encompassing_rect_from_list(drag_selection).position; - } + if (drag_selection.size() > 0) { - Point2 new_pos; - if (drag_selection.size() == 1) { - Node2D *node_2d = Object::cast_to<Node2D>(drag_selection[0]); - if (node_2d && move_local_base_rotated) { - Transform2D m; - m.rotate(node_2d->get_rotation()); - new_pos += m.xform(drag_to); - } else if (move_local_base) { - new_pos += drag_to; + _restore_canvas_item_state(drag_selection, true); + + bool move_local_base = k->get_alt(); + bool move_local_base_rotated = k->get_control() || k->get_metakey(); + + Vector2 dir; + if (k->get_scancode() == KEY_UP) + dir += Vector2(0, -1); + else if (k->get_scancode() == KEY_DOWN) + dir += Vector2(0, 1); + else if (k->get_scancode() == KEY_LEFT) + dir += Vector2(-1, 0); + else if (k->get_scancode() == KEY_RIGHT) + dir += Vector2(1, 0); + if (k->get_shift()) + dir *= grid_step * Math::pow(2.0, grid_step_multiplier); + + drag_to += dir; + if (k->get_shift()) + drag_to = drag_to.snapped(grid_step * Math::pow(2.0, grid_step_multiplier)); + + Point2 previous_pos; + if (drag_selection.size() == 1) { + Transform2D xform = drag_selection[0]->get_global_transform_with_canvas() * drag_selection[0]->get_transform().affine_inverse(); + previous_pos = xform.xform(drag_selection[0]->_edit_get_position()); + } else { + previous_pos = _get_encompassing_rect_from_list(drag_selection).position; + } + + Point2 new_pos; + if (drag_selection.size() == 1) { + Node2D *node_2d = Object::cast_to<Node2D>(drag_selection[0]); + if (node_2d && move_local_base_rotated) { + Transform2D m; + m.rotate(node_2d->get_rotation()); + new_pos += m.xform(drag_to); + } else if (move_local_base) { + new_pos += drag_to; + } else { + new_pos = previous_pos + (drag_to - drag_from); + } } else { new_pos = previous_pos + (drag_to - drag_from); } - } else { - new_pos = previous_pos + (drag_to - drag_from); - } - for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { - CanvasItem *canvas_item = E->get(); - CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); - Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform(); + for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { + CanvasItem *canvas_item = E->get(); + CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); + Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform(); - Node2D *node2d = Object::cast_to<Node2D>(canvas_item); - if (node2d && se->pre_drag_bones_undo_state.size() > 0) { - _solve_IK(node2d, new_pos); - } else { - canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos)); + Node2D *node2d = Object::cast_to<Node2D>(canvas_item); + if (node2d && se->pre_drag_bones_undo_state.size() > 0) { + _solve_IK(node2d, new_pos); + } else { + canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos)); + } } } return true; @@ -1648,6 +1695,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { return true; } else if (!selection_results.empty()) { + // Sorts items according the their z-index selection_results.sort(); NodePath root_path = get_tree()->get_edited_scene_root()->get_path(); @@ -1707,16 +1755,17 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { canvas_item = selection[0].item; // Check if the canvas item is in a group, and select the group instead if it is the case - CanvasItem *canvas_item_tmp = canvas_item; - while (canvas_item_tmp) { - if (canvas_item->has_meta("_edit_group_")) { + Node *node = canvas_item; + while (node && node != scene) { + CanvasItem *canvas_item_tmp = Object::cast_to<CanvasItem>(node); + if (canvas_item_tmp && node->has_meta("_edit_group_")) { canvas_item = canvas_item_tmp; } - canvas_item_tmp = canvas_item_tmp->get_parent_item(); + node = node->get_parent(); } // Make sure the selected node is in the current scene - Node *node = canvas_item; + node = canvas_item; while (node && ((node != scene && node->get_owner() != scene) || !node->is_class("CanvasItem"))) { node = node->get_parent(); }; @@ -1766,7 +1815,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { if (bsfrom.y > bsto.y) SWAP(bsfrom.y, bsto.y); - _find_canvas_items_at_rect(Rect2(bsfrom, bsto - bsfrom), scene, &selitems); + _find_canvas_items_in_rect(Rect2(bsfrom, bsto - bsfrom), scene, &selitems); for (List<CanvasItem *>::Element *E = selitems.front(); E; E = E->next()) { editor_selection->add_node(E->get()); } @@ -1800,6 +1849,42 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { return false; } +bool CanvasItemEditor::_gui_input_hover(const Ref<InputEvent> &p_event) { + + Ref<InputEventMouseMotion> m = p_event; + if (m.is_valid()) { + if (drag_type == DRAG_NONE && tool == TOOL_SELECT) { + Point2 click = transform.affine_inverse().xform(m->get_position()); + Node *scene = editor->get_edited_scene(); + + //Checks if the hovered items changed, update the viewport if so + Vector<_SelectResult> hovering_results_tmp; + _find_canvas_items_at_pos(click, scene, hovering_results_tmp); + hovering_results_tmp.sort(); + bool changed = false; + if (hovering_results.size() == hovering_results_tmp.size()) { + for (int i = 0; i < hovering_results.size(); i++) { + if (hovering_results[i].item != hovering_results_tmp[i].item) { + changed = true; + break; + } + } + } else { + changed = true; + } + + if (changed) { + hovering_results = hovering_results_tmp; + viewport->update(); + } + + return true; + } + } + + return false; +} + void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) { bool accepted = false; if ((accepted = _gui_input_rulers_and_guides(p_event))) { @@ -1827,6 +1912,9 @@ void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) { if (accepted) accept_event(); + // Handles the mouse hovering + _gui_input_hover(p_event); + // Change the cursor CursorShape c = CURSOR_ARROW; switch (drag_type) { @@ -2093,6 +2181,9 @@ void CanvasItemEditor::_draw_grid() { void CanvasItemEditor::_draw_selection() { Ref<Texture> pivot_icon = get_icon("EditorPivot", "EditorIcons"); + Ref<Texture> position_icon = get_icon("EditorPosition", "EditorIcons"); + Ref<Texture> previous_position_icon = get_icon("EditorPositionPrevious", "EditorIcons"); + RID ci = viewport->get_canvas_item(); List<CanvasItem *> selection = _get_edited_canvas_items(false, false); @@ -2102,8 +2193,6 @@ void CanvasItemEditor::_draw_selection() { CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get()); CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); - Rect2 rect = canvas_item->_edit_get_rect(); - // Draw the previous position if we are dragging the node if (show_helpers && (drag_type == DRAG_ALL || drag_type == DRAG_ROTATE || @@ -2112,42 +2201,52 @@ void CanvasItemEditor::_draw_selection() { const Transform2D pre_drag_xform = transform * se->pre_drag_xform; const Color pre_drag_color = Color(0.4, 0.6, 1, 0.7); - Vector2 pre_drag_endpoints[4] = { + if (canvas_item->_edit_use_rect()) { + Vector2 pre_drag_endpoints[4] = { - pre_drag_xform.xform(se->pre_drag_rect.position), - pre_drag_xform.xform(se->pre_drag_rect.position + Vector2(se->pre_drag_rect.size.x, 0)), - pre_drag_xform.xform(se->pre_drag_rect.position + se->pre_drag_rect.size), - pre_drag_xform.xform(se->pre_drag_rect.position + Vector2(0, se->pre_drag_rect.size.y)) - }; + pre_drag_xform.xform(se->pre_drag_rect.position), + pre_drag_xform.xform(se->pre_drag_rect.position + Vector2(se->pre_drag_rect.size.x, 0)), + pre_drag_xform.xform(se->pre_drag_rect.position + se->pre_drag_rect.size), + pre_drag_xform.xform(se->pre_drag_rect.position + Vector2(0, se->pre_drag_rect.size.y)) + }; - for (int i = 0; i < 4; i++) { - viewport->draw_line(pre_drag_endpoints[i], pre_drag_endpoints[(i + 1) % 4], pre_drag_color, 2); + for (int i = 0; i < 4; i++) { + viewport->draw_line(pre_drag_endpoints[i], pre_drag_endpoints[(i + 1) % 4], pre_drag_color, 2); + } + } else { + viewport->draw_texture(previous_position_icon, (pre_drag_xform.xform(Point2()) - (previous_position_icon->get_size() / 2)).floor()); } } Transform2D xform = transform * canvas_item->get_global_transform_with_canvas(); - VisualServer::get_singleton()->canvas_item_add_set_transform(ci, xform); - - // Draw the selected items surrounding boxes - Vector2 endpoints[4] = { - xform.xform(rect.position), - xform.xform(rect.position + Vector2(rect.size.x, 0)), - xform.xform(rect.position + rect.size), - xform.xform(rect.position + Vector2(0, rect.size.y)) - }; - Color c = Color(1, 0.6, 0.4, 0.7); + // Draw the selected items position / surrounding boxes + if (canvas_item->_edit_use_rect()) { + Rect2 rect = canvas_item->_edit_get_rect(); + Vector2 endpoints[4] = { + xform.xform(rect.position), + xform.xform(rect.position + Vector2(rect.size.x, 0)), + xform.xform(rect.position + rect.size), + xform.xform(rect.position + Vector2(0, rect.size.y)) + }; + + Color c = Color(1, 0.6, 0.4, 0.7); - VisualServer::get_singleton()->canvas_item_add_set_transform(ci, Transform2D()); + for (int i = 0; i < 4; i++) { + viewport->draw_line(endpoints[i], endpoints[(i + 1) % 4], c, 2); + } + } else { - for (int i = 0; i < 4; i++) { - viewport->draw_line(endpoints[i], endpoints[(i + 1) % 4], c, 2); + Transform2D transform = Transform2D(xform.get_rotation(), xform.get_origin()); + viewport->draw_set_transform_matrix(transform); + viewport->draw_texture(position_icon, -(position_icon->get_size() / 2)); + viewport->draw_set_transform_matrix(Transform2D()); } if (single && (tool == TOOL_SELECT || tool == TOOL_MOVE || tool == TOOL_ROTATE || tool == TOOL_EDIT_PIVOT)) { //kind of sucks // Draw the pivot if (canvas_item->_edit_get_pivot() != Vector2() || drag_type == DRAG_PIVOT || tool == TOOL_EDIT_PIVOT) { // This is not really clean :/ - viewport->draw_texture(pivot_icon, xform.xform(canvas_item->_edit_get_pivot()) + (-pivot_icon->get_size() / 2).floor()); + viewport->draw_texture(pivot_icon, (xform.xform(canvas_item->_edit_get_pivot()) - (pivot_icon->get_size() / 2)).floor()); } Control *control = Object::cast_to<Control>(canvas_item); @@ -2329,7 +2428,14 @@ void CanvasItemEditor::_draw_selection() { } } - if (tool == TOOL_SELECT) { + if (tool == TOOL_SELECT && canvas_item->_edit_use_rect()) { + Rect2 rect = canvas_item->_edit_get_rect(); + Vector2 endpoints[4] = { + xform.xform(rect.position), + xform.xform(rect.position + Vector2(rect.size.x, 0)), + xform.xform(rect.position + rect.size), + xform.xform(rect.position + Vector2(0, rect.size.y)) + }; for (int i = 0; i < 4; i++) { // Draw the resize handles int prev = (i + 3) % 4; @@ -2506,32 +2612,121 @@ void CanvasItemEditor::_draw_bones() { } } -void CanvasItemEditor::_draw_locks_and_groups(Node *p_node, const Transform2D &p_xform) { +void CanvasItemEditor::_draw_invisible_nodes_positions(Node *p_node, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) { + ERR_FAIL_COND(!p_node); + + Node *scene = editor->get_edited_scene(); + if (p_node != scene && p_node->get_owner() != scene && !scene->is_editable_instance(p_node)) + return; + CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node); + if (canvas_item && !canvas_item->is_visible()) + return; + + Transform2D parent_xform = p_parent_xform; + Transform2D canvas_xform = p_canvas_xform; + + if (canvas_item && !canvas_item->is_set_as_toplevel()) { + parent_xform = parent_xform * canvas_item->get_transform(); + } else { + CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node); + parent_xform = Transform2D(); + canvas_xform = cl ? cl->get_transform() : p_canvas_xform; + } + + for (int i = p_node->get_child_count() - 1; i >= 0; i--) { + _draw_invisible_nodes_positions(p_node->get_child(i), parent_xform, canvas_xform); + } + + if (canvas_item && !canvas_item->_edit_use_rect() && !editor_selection->is_selected(canvas_item)) { + Transform2D xform = transform * canvas_xform * parent_xform; + + // Draw the node's position + Ref<Texture> position_icon = get_icon("EditorPositionUnselected", "EditorIcons"); + Transform2D transform = Transform2D(xform.get_rotation(), xform.get_origin()); + viewport->draw_set_transform_matrix(transform); + viewport->draw_texture(position_icon, -position_icon->get_size() / 2, Color(1.0, 1.0, 1.0, 0.5)); + viewport->draw_set_transform_matrix(Transform2D()); + } +} + +void CanvasItemEditor::_draw_hover() { + List<Rect2> previous_rects; + + for (int i = 0; i < hovering_results.size(); i++) { + // Draw the node's name and icon + CanvasItem *canvas_item = hovering_results[i].item; + + if (canvas_item->_edit_use_rect()) + continue; + + Transform2D xform = transform * canvas_item->get_global_transform_with_canvas(); + + // Get the resources + Ref<Texture> node_icon; + if (has_icon(canvas_item->get_class(), "EditorIcons")) + node_icon = get_icon(canvas_item->get_class(), "EditorIcons"); + else + node_icon = get_icon("Object", "EditorIcons"); + Ref<Font> font = get_font("font", "Label"); + String node_name = canvas_item->get_name(); + Size2 node_name_size = font->get_string_size(node_name); + Size2 item_size = Size2(node_icon->get_size().x + 4 + node_name_size.x, MAX(node_icon->get_size().y, node_name_size.y - 3)); + + Point2 pos = xform.get_origin() - Point2(0, item_size.y) + (Point2(node_icon->get_size().x, -node_icon->get_size().y) / 4); + // Rectify the position to avoid overlaping items + for (List<Rect2>::Element *E = previous_rects.front(); E; E = E->next()) { + if (E->get().intersects(Rect2(pos, item_size))) { + pos.y = E->get().get_position().y - item_size.y; + } + } + + previous_rects.push_back(Rect2(pos, item_size)); + + // Draw the node icon and name + viewport->draw_texture(node_icon, pos, Color(1.0, 1.0, 1.0, 0.5)); + viewport->draw_string(font, pos + Point2(node_icon->get_size().x + 4, item_size.y - 3), node_name, Color(1.0, 1.0, 1.0, 0.5)); + } +} + +void CanvasItemEditor::_draw_locks_and_groups(Node *p_node, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) { ERR_FAIL_COND(!p_node); - RID viewport_ci = viewport->get_canvas_item(); + Node *scene = editor->get_edited_scene(); + if (p_node != scene && p_node->get_owner() != scene && !scene->is_editable_instance(p_node->get_owner())) + return; + CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node); + if (canvas_item && !canvas_item->is_visible()) + return; + + Transform2D parent_xform = p_parent_xform; + Transform2D canvas_xform = p_canvas_xform; - Transform2D transform_ci = p_xform; - CanvasItem *ci = Object::cast_to<CanvasItem>(p_node); - if (ci) - transform_ci = transform_ci * ci->get_transform(); + if (canvas_item && !canvas_item->is_set_as_toplevel()) { + parent_xform = parent_xform * canvas_item->get_transform(); + } else { + CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node); + parent_xform = Transform2D(); + canvas_xform = cl ? cl->get_transform() : p_canvas_xform; + } for (int i = p_node->get_child_count() - 1; i >= 0; i--) { - _draw_locks_and_groups(p_node->get_child(i), transform_ci); + _draw_locks_and_groups(p_node->get_child(i), parent_xform, canvas_xform); } - if (ci) { + RID viewport_canvas_item = viewport->get_canvas_item(); + if (canvas_item) { + float offset = 0; + Ref<Texture> lock = get_icon("LockViewport", "EditorIcons"); if (p_node->has_meta("_edit_lock_")) { - lock->draw(viewport_ci, transform_ci.xform(Point2(0, 0))); + lock->draw(viewport_canvas_item, (transform * canvas_xform * parent_xform).xform(Point2(0, 0)) + Point2(offset, 0)); + offset += lock->get_size().x; } Ref<Texture> group = get_icon("GroupViewport", "EditorIcons"); - if (ci->has_meta("_edit_group_")) { - Vector2 ofs = transform_ci.xform(Point2(0, 0)); - if (ci->has_meta("_edit_lock_")) - ofs = Point2(ofs.x + lock->get_size().x, ofs.y); - group->draw(viewport_ci, ofs); + if (canvas_item->has_meta("_edit_group_")) { + group->draw(viewport_canvas_item, (transform * canvas_xform * parent_xform).xform(Point2(0, 0)) + Point2(offset, 0)); + //offset += group->get_size().x; } } } @@ -2597,8 +2792,10 @@ void CanvasItemEditor::_draw_viewport() { _draw_grid(); _draw_selection(); _draw_axis(); - if (editor->get_edited_scene()) - _draw_locks_and_groups(editor->get_edited_scene(), transform); + if (editor->get_edited_scene()) { + _draw_locks_and_groups(editor->get_edited_scene()); + _draw_invisible_nodes_positions(editor->get_edited_scene()); + } RID ci = viewport->get_canvas_item(); VisualServer::get_singleton()->canvas_item_add_set_transform(ci, Transform2D()); @@ -2618,6 +2815,7 @@ void CanvasItemEditor::_draw_viewport() { if (show_guides) _draw_guides(); _draw_focus(); + _draw_hover(); } void CanvasItemEditor::_notification(int p_what) { @@ -2633,12 +2831,17 @@ void CanvasItemEditor::_notification(int p_what) { CanvasItem *canvas_item = E->get(); CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); - Rect2 r = canvas_item->_edit_get_rect(); + Rect2 rect; + if (canvas_item->_edit_use_rect()) { + rect = canvas_item->_edit_get_rect(); + } else { + rect = Rect2(); + } Transform2D xform = canvas_item->get_transform(); - if (r != se->prev_rect || xform != se->prev_xform) { + if (rect != se->prev_rect || xform != se->prev_xform) { viewport->update(); - se->prev_rect = r; + se->prev_rect = rect; se->prev_xform = xform; } @@ -2840,7 +3043,7 @@ void CanvasItemEditor::_update_scrollbars() { // Calculate scrollable area Rect2 canvas_item_rect = Rect2(Point2(), screen_rect); if (editor->get_edited_scene()) { - Rect2 content_rect = _get_scene_encompassing_rect(); + Rect2 content_rect = _get_encompassing_rect(editor->get_edited_scene()); canvas_item_rect.expand_to(content_rect.position); canvas_item_rect.expand_to(content_rect.position + content_rect.size); } @@ -3539,7 +3742,12 @@ void CanvasItemEditor::_focus_selection(int p_op) { //if (!canvas_item->is_visible_in_tree()) continue; ++count; - Rect2 item_rect = canvas_item->_edit_get_rect(); + Rect2 item_rect; + if (canvas_item->_edit_use_rect()) { + item_rect = canvas_item->_edit_get_rect(); + } else { + item_rect = Rect2(); + } Vector2 pos = canvas_item->get_global_transform().get_origin(); Vector2 scale = canvas_item->get_global_transform().get_scale(); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index da7ce9172a..5ca8a37610 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -258,6 +258,7 @@ class CanvasItemEditor : public VBoxContainer { }; Vector<_SelectResult> selection_results; + Vector<_SelectResult> hovering_results; struct BoneList { @@ -336,7 +337,7 @@ class CanvasItemEditor : public VBoxContainer { Ref<ShortCut> divide_grid_step_shortcut; void _find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, Vector<_SelectResult> &r_items, int limit = 0, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); - void _find_canvas_items_at_rect(const Rect2 &p_rect, Node *p_node, List<CanvasItem *> *r_items, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); + void _find_canvas_items_in_rect(const Rect2 &p_rect, Node *p_node, List<CanvasItem *> *r_items, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); bool _select_click_on_item(CanvasItem *item, Point2 p_click_pos, bool p_append); ConfirmationDialog *snap_dialog; @@ -366,8 +367,8 @@ class CanvasItemEditor : public VBoxContainer { List<CanvasItem *> _get_edited_canvas_items(bool retreive_locked = false, bool remove_canvas_item_if_parent_in_selection = true); Rect2 _get_encompassing_rect_from_list(List<CanvasItem *> p_list); - void _expand_encompassing_rect_using_children(Rect2 &p_rect, Node *p_node, bool &r_first, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); - Rect2 _get_scene_encompassing_rect(); + void _expand_encompassing_rect_using_children(Rect2 &p_rect, const Node *p_node, bool &r_first, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); + Rect2 _get_encompassing_rect(const Node *p_node); Object *_get_editor_data(Object *p_what); @@ -387,7 +388,9 @@ class CanvasItemEditor : public VBoxContainer { void _draw_selection(); void _draw_axis(); void _draw_bones(); - void _draw_locks_and_groups(Node *p_node, const Transform2D &p_xform); + void _draw_invisible_nodes_positions(Node *p_node, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); + void _draw_locks_and_groups(Node *p_node, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); + void _draw_hover(); void _draw_viewport(); @@ -400,6 +403,7 @@ class CanvasItemEditor : public VBoxContainer { bool _gui_input_select(const Ref<InputEvent> &p_event); bool _gui_input_zoom_or_pan(const Ref<InputEvent> &p_event); bool _gui_input_rulers_and_guides(const Ref<InputEvent> &p_event); + bool _gui_input_hover(const Ref<InputEvent> &p_event); void _gui_input_viewport(const Ref<InputEvent> &p_event); diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index 6e3be343ba..8ae573baef 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -178,15 +178,15 @@ void ProjectSettingsEditor::_action_edited() { } int order = ProjectSettings::get_singleton()->get_order(add_at); - Array va = ProjectSettings::get_singleton()->get(add_at); + Dictionary action = ProjectSettings::get_singleton()->get(add_at); setting = true; undo_redo->create_action(TTR("Rename Input Action Event")); undo_redo->add_do_method(ProjectSettings::get_singleton(), "clear", add_at); - undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", action_prop, va); + undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", action_prop, action); undo_redo->add_do_method(ProjectSettings::get_singleton(), "set_order", action_prop, order); undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", action_prop); - undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", add_at, va); + undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", add_at, action); undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", add_at, order); undo_redo->add_do_method(this, "_update_actions"); undo_redo->add_undo_method(this, "_update_actions"); @@ -203,8 +203,9 @@ void ProjectSettingsEditor::_device_input_add() { Ref<InputEvent> ie; String name = add_at; int idx = edit_idx; - Array old_val = ProjectSettings::get_singleton()->get(name); - Array arr = old_val.duplicate(); + Dictionary old_val = ProjectSettings::get_singleton()->get(name); + Dictionary action = old_val.duplicate(); + Array events = action["events"]; switch (add_type) { @@ -215,9 +216,9 @@ void ProjectSettingsEditor::_device_input_add() { mb->set_button_index(device_index->get_selected() + 1); mb->set_device(_get_current_device()); - for (int i = 0; i < arr.size(); i++) { + for (int i = 0; i < events.size(); i++) { - Ref<InputEventMouseButton> aie = arr[i]; + Ref<InputEventMouseButton> aie = events[i]; if (aie.is_null()) continue; if (aie->get_device() == mb->get_device() && aie->get_button_index() == mb->get_button_index()) { @@ -233,20 +234,26 @@ void ProjectSettingsEditor::_device_input_add() { Ref<InputEventJoypadMotion> jm; jm.instance(); jm->set_axis(device_index->get_selected() >> 1); - jm->set_axis_value(device_index->get_selected() & 1 ? 1 : -1); jm->set_device(_get_current_device()); - for (int i = 0; i < arr.size(); i++) { + bool should_update_event = true; + Variant deadzone = device_special_value->get_value(); + for (int i = 0; i < events.size(); i++) { - Ref<InputEventJoypadMotion> aie = arr[i]; + Ref<InputEventJoypadMotion> aie = events[i]; if (aie.is_null()) continue; - if (aie->get_device() == jm->get_device() && aie->get_axis() == jm->get_axis() && aie->get_axis_value() == jm->get_axis_value()) { - return; + if (aie->get_device() == jm->get_device() && aie->get_axis() == jm->get_axis()) { + should_update_event = false; + break; } } + if (!should_update_event && deadzone == action["deadzone"]) + return; + ie = jm; + action["deadzone"] = deadzone; } break; case INPUT_JOY_BUTTON: { @@ -257,9 +264,9 @@ void ProjectSettingsEditor::_device_input_add() { jb->set_button_index(device_index->get_selected()); jb->set_device(_get_current_device()); - for (int i = 0; i < arr.size(); i++) { + for (int i = 0; i < events.size(); i++) { - Ref<InputEventJoypadButton> aie = arr[i]; + Ref<InputEventJoypadButton> aie = events[i]; if (aie.is_null()) continue; if (aie->get_device() == jb->get_device() && aie->get_button_index() == jb->get_button_index()) { @@ -272,14 +279,15 @@ void ProjectSettingsEditor::_device_input_add() { default: {} } - if (idx < 0 || idx >= arr.size()) { - arr.push_back(ie); + if (idx < 0 || idx >= events.size()) { + events.push_back(ie); } else { - arr[idx] = ie; + events[idx] = ie; } + action["events"] = events; undo_redo->create_action(TTR("Add Input Action Event")); - undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, arr); + undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, action); undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, old_val); undo_redo->add_do_method(this, "_update_actions"); undo_redo->add_undo_method(this, "_update_actions"); @@ -320,12 +328,13 @@ void ProjectSettingsEditor::_press_a_key_confirm() { String name = add_at; int idx = edit_idx; - Array old_val = ProjectSettings::get_singleton()->get(name); - Array arr = old_val.duplicate(); + Dictionary old_val = ProjectSettings::get_singleton()->get(name); + Dictionary action = old_val.duplicate(); + Array events = action["events"]; - for (int i = 0; i < arr.size(); i++) { + for (int i = 0; i < events.size(); i++) { - Ref<InputEventKey> aie = arr[i]; + Ref<InputEventKey> aie = events[i]; if (aie.is_null()) continue; if (aie->get_scancode_with_modifiers() == ie->get_scancode_with_modifiers()) { @@ -333,14 +342,15 @@ void ProjectSettingsEditor::_press_a_key_confirm() { } } - if (idx < 0 || idx >= arr.size()) { - arr.push_back(ie); + if (idx < 0 || idx >= events.size()) { + events.push_back(ie); } else { - arr[idx] = ie; + events[idx] = ie; } + action["events"] = events; undo_redo->create_action(TTR("Add Input Action Event")); - undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, arr); + undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, action); undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, old_val); undo_redo->add_do_method(this, "_update_actions"); undo_redo->add_undo_method(this, "_update_actions"); @@ -418,6 +428,9 @@ void ProjectSettingsEditor::_add_item(int p_item, Ref<InputEvent> p_exiting_even last_wait_for_key = Ref<InputEvent>(); press_a_key->popup_centered(Size2(250, 80) * EDSCALE); press_a_key->grab_focus(); + + device_special_value_label->hide(); + device_special_value->hide(); } break; case INPUT_MOUSE_BUTTON: { @@ -443,6 +456,9 @@ void ProjectSettingsEditor::_add_item(int p_item, Ref<InputEvent> p_exiting_even _set_current_device(0); device_input->get_ok()->set_text(TTR("Add")); } + + device_special_value_label->hide(); + device_special_value->hide(); } break; case INPUT_JOY_MOTION: { @@ -464,6 +480,15 @@ void ProjectSettingsEditor::_add_item(int p_item, Ref<InputEvent> p_exiting_even _set_current_device(0); device_input->get_ok()->set_text(TTR("Add")); } + + device_special_value_label->set_text(TTR("Deadzone (global to the action):")); + device_special_value_label->show(); + device_special_value->set_min(0.0f); + device_special_value->set_max(1.0f); + device_special_value->set_step(0.01f); + Dictionary action = ProjectSettings::get_singleton()->get(add_at); + device_special_value->set_value(action.has("deadzone") ? action["deadzone"] : Variant(0.5f)); + device_special_value->show(); } break; case INPUT_JOY_BUTTON: { @@ -486,6 +511,8 @@ void ProjectSettingsEditor::_add_item(int p_item, Ref<InputEvent> p_exiting_even device_input->get_ok()->set_text(TTR("Add")); } + device_special_value_label->hide(); + device_special_value->hide(); } break; default: {} } @@ -522,18 +549,17 @@ void ProjectSettingsEditor::_action_activated() { String name = "input/" + ti->get_parent()->get_text(0); int idx = ti->get_metadata(0); - Array va = ProjectSettings::get_singleton()->get(name); - - ERR_FAIL_INDEX(idx, va.size()); - - Ref<InputEvent> ie = va[idx]; + Dictionary action = ProjectSettings::get_singleton()->get(name); + Array events = action["events"]; - if (ie.is_null()) + ERR_FAIL_INDEX(idx, events.size()); + Ref<InputEvent> event = events[idx]; + if (event.is_null()) return; add_at = name; edit_idx = idx; - _edit_item(ie); + _edit_item(event); } void ProjectSettingsEditor::_action_button_pressed(Object *p_obj, int p_column, int p_id) { @@ -543,6 +569,7 @@ void ProjectSettingsEditor::_action_button_pressed(Object *p_obj, int p_column, ERR_FAIL_COND(!ti); if (p_id == 1) { + // Add action event Point2 ofs = input_editor->get_global_position(); Rect2 ir = input_editor->get_item_rect(ti); ir.position.y -= input_editor->get_scroll().y; @@ -554,14 +581,12 @@ void ProjectSettingsEditor::_action_button_pressed(Object *p_obj, int p_column, edit_idx = -1; } else if (p_id == 2) { - //remove + // Remove if (ti->get_parent() == input_editor->get_root()) { - - //remove main thing - + // Remove action String name = "input/" + ti->get_text(0); - Variant old_val = ProjectSettings::get_singleton()->get(name); + Dictionary old_val = ProjectSettings::get_singleton()->get(name); int order = ProjectSettings::get_singleton()->get_order(name); undo_redo->create_action(TTR("Erase Input Action")); @@ -575,24 +600,19 @@ void ProjectSettingsEditor::_action_button_pressed(Object *p_obj, int p_column, undo_redo->commit_action(); } else { - //remove action + // Remove action event String name = "input/" + ti->get_parent()->get_text(0); - Variant old_val = ProjectSettings::get_singleton()->get(name); + Dictionary old_val = ProjectSettings::get_singleton()->get(name); + Dictionary action = old_val.duplicate(); int idx = ti->get_metadata(0); - Array va = old_val; - - ERR_FAIL_INDEX(idx, va.size()); - - for (int i = idx; i < va.size() - 1; i++) { - - va[i] = va[i + 1]; - } - - va.resize(va.size() - 1); + Array events = action["events"]; + ERR_FAIL_INDEX(idx, events.size()); + events.remove(idx); + action["events"] = events; undo_redo->create_action(TTR("Erase Input Action Event")); - undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, va); + undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, action); undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, old_val); undo_redo->add_do_method(this, "_update_actions"); undo_redo->add_undo_method(this, "_update_actions"); @@ -601,30 +621,31 @@ void ProjectSettingsEditor::_action_button_pressed(Object *p_obj, int p_column, undo_redo->commit_action(); } } else if (p_id == 3) { - //edit + // Edit if (ti->get_parent() == input_editor->get_root()) { - + // Edit action name ti->set_as_cursor(0); input_editor->edit_selected(); } else { - //edit action + // Edit action event String name = "input/" + ti->get_parent()->get_text(0); int idx = ti->get_metadata(0); - Array va = ProjectSettings::get_singleton()->get(name); + Dictionary action = ProjectSettings::get_singleton()->get(name); - ERR_FAIL_INDEX(idx, va.size()); + Array events = action["events"]; + ERR_FAIL_INDEX(idx, events.size()); - Ref<InputEvent> ie = va[idx]; + Ref<InputEvent> event = events[idx]; - if (ie.is_null()) + if (event.is_null()) return; ti->set_as_cursor(0); add_at = name; edit_idx = idx; - _edit_item(ie); + _edit_item(event); } } } @@ -660,17 +681,18 @@ void ProjectSettingsEditor::_update_actions() { } item->set_custom_bg_color(0, get_color("prop_subsection", "Editor")); - Array actions = ProjectSettings::get_singleton()->get(pi.name); + Dictionary action = ProjectSettings::get_singleton()->get(pi.name); + Array events = action["events"]; - for (int i = 0; i < actions.size(); i++) { + for (int i = 0; i < events.size(); i++) { - Ref<InputEvent> ie = actions[i]; - if (ie.is_null()) + Ref<InputEvent> event = events[i]; + if (event.is_null()) continue; TreeItem *action = input_editor->create_item(item); - Ref<InputEventKey> k = ie; + Ref<InputEventKey> k = event; if (k.is_valid()) { String str = keycode_get_string(k->get_scancode()).capitalize(); @@ -687,7 +709,7 @@ void ProjectSettingsEditor::_update_actions() { action->set_icon(0, get_icon("Keyboard", "EditorIcons")); } - Ref<InputEventJoypadButton> jb = ie; + Ref<InputEventJoypadButton> jb = event; if (jb.is_valid()) { @@ -701,7 +723,7 @@ void ProjectSettingsEditor::_update_actions() { action->set_icon(0, get_icon("JoyButton", "EditorIcons")); } - Ref<InputEventMouseButton> mb = ie; + Ref<InputEventMouseButton> mb = event; if (mb.is_valid()) { String str = _get_device_string(mb->get_device()) + ", "; @@ -718,7 +740,7 @@ void ProjectSettingsEditor::_update_actions() { action->set_icon(0, get_icon("Mouse", "EditorIcons")); } - Ref<InputEventJoypadMotion> jm = ie; + Ref<InputEventJoypadMotion> jm = event; if (jm.is_valid()) { @@ -732,7 +754,7 @@ void ProjectSettingsEditor::_update_actions() { action->add_button(0, get_icon("Edit", "EditorIcons"), 3, false, TTR("Edit")); action->add_button(0, get_icon("Remove", "EditorIcons"), 2, false, TTR("Remove")); action->set_metadata(0, i); - action->set_meta("__input", ie); + action->set_meta("__input", event); } } @@ -892,10 +914,12 @@ void ProjectSettingsEditor::_action_adds(String) { void ProjectSettingsEditor::_action_add() { - Array va; + Dictionary action; + action["events"] = Array(); + action["deadzone"] = 0.5f; String name = "input/" + action_name->get_text(); undo_redo->create_action(TTR("Add Input Action")); - undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, va); + undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, action); undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", name); undo_redo->add_do_method(this, "_update_actions"); undo_redo->add_undo_method(this, "_update_actions"); @@ -1814,6 +1838,14 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { device_index = memnew(OptionButton); vbc_right->add_child(device_index); + l = memnew(Label); + l->set_text(TTR("Special value:")); + vbc_right->add_child(l); + device_special_value_label = l; + + device_special_value = memnew(SpinBox); + vbc_right->add_child(device_special_value); + setting = false; //translations diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h index 0ced88d7f6..b8bfdcd876 100644 --- a/editor/project_settings_editor.h +++ b/editor/project_settings_editor.h @@ -83,6 +83,8 @@ class ProjectSettingsEditor : public AcceptDialog { OptionButton *device_id; OptionButton *device_index; Label *device_index_label; + SpinBox *device_special_value; + Label *device_special_value_label; MenuButton *popup_copy_to_feature; LineEdit *action_name; diff --git a/main/input_default.cpp b/main/input_default.cpp index 1c73ecf2d2..3c40be5082 100644 --- a/main/input_default.cpp +++ b/main/input_default.cpp @@ -127,6 +127,14 @@ bool InputDefault::is_action_just_released(const StringName &p_action) const { } } +float InputDefault::get_action_strength(const StringName &p_action) const { + const Map<StringName, Action>::Element *E = action_state.find(p_action); + if (!E) + return 0.0f; + + return E->get().strength; +} + float InputDefault::get_joy_axis(int p_device, int p_axis) const { _THREAD_SAFE_METHOD_ @@ -330,16 +338,18 @@ void InputDefault::parse_input_event(const Ref<InputEvent> &p_event) { } } - if (!p_event->is_echo()) { - for (const Map<StringName, InputMap::Action>::Element *E = InputMap::get_singleton()->get_action_map().front(); E; E = E->next()) { + for (const Map<StringName, InputMap::Action>::Element *E = InputMap::get_singleton()->get_action_map().front(); E; E = E->next()) { + if (InputMap::get_singleton()->event_is_action(p_event, E->key())) { - if (InputMap::get_singleton()->event_is_action(p_event, E->key()) && is_action_pressed(E->key()) != p_event->is_pressed()) { + // Save the action's state + if (!p_event->is_echo() && is_action_pressed(E->key()) != p_event->is_action_pressed(E->key())) { Action action; action.physics_frame = Engine::get_singleton()->get_physics_frames(); action.idle_frame = Engine::get_singleton()->get_idle_frames(); - action.pressed = p_event->is_pressed(); + action.pressed = p_event->is_action_pressed(E->key()); action_state[E->key()] = action; } + action_state[E->key()].strength = p_event->get_action_strength(E->key()); } } diff --git a/main/input_default.h b/main/input_default.h index 384b04cf41..6dd88cd31e 100644 --- a/main/input_default.h +++ b/main/input_default.h @@ -55,6 +55,7 @@ class InputDefault : public Input { uint64_t physics_frame; uint64_t idle_frame; bool pressed; + float strength; }; Map<StringName, Action> action_state; @@ -182,6 +183,7 @@ public: virtual bool is_action_pressed(const StringName &p_action) const; virtual bool is_action_just_pressed(const StringName &p_action) const; virtual bool is_action_just_released(const StringName &p_action) const; + virtual float get_action_strength(const StringName &p_action) const; virtual float get_joy_axis(int p_device, int p_axis) const; String get_joy_name(int p_idx); diff --git a/modules/bullet/collision_object_bullet.cpp b/modules/bullet/collision_object_bullet.cpp index 05c0e653df..57e4db708e 100644 --- a/modules/bullet/collision_object_bullet.cpp +++ b/modules/bullet/collision_object_bullet.cpp @@ -49,7 +49,7 @@ CollisionObjectBullet::ShapeWrapper::~ShapeWrapper() {} void CollisionObjectBullet::ShapeWrapper::set_transform(const Transform &p_transform) { - G_TO_B(p_transform.get_basis().get_scale(), scale); + G_TO_B(p_transform.get_basis().get_scale_abs(), scale); G_TO_B(p_transform, transform); UNSCALE_BT_BASIS(transform); } @@ -158,7 +158,7 @@ int CollisionObjectBullet::get_godot_object_flags() const { void CollisionObjectBullet::set_transform(const Transform &p_global_transform) { - set_body_scale(p_global_transform.basis.get_scale()); + set_body_scale(p_global_transform.basis.get_scale_abs()); btTransform bt_transform; G_TO_B(p_global_transform, bt_transform); diff --git a/modules/bullet/godot_result_callbacks.cpp b/modules/bullet/godot_result_callbacks.cpp index caa3d677dd..1bf259da84 100644 --- a/modules/bullet/godot_result_callbacks.cpp +++ b/modules/bullet/godot_result_callbacks.cpp @@ -172,10 +172,7 @@ btScalar GodotAllContactResultCallback::addSingleResult(btManifoldPoint &cp, con result.shape = cp.m_index0; } - if (colObj) - result.collider_id = colObj->get_instance_id(); - else - result.collider_id = 0; + result.collider_id = colObj->get_instance_id(); result.collider = 0 == result.collider_id ? NULL : ObjectDB::get_instance(result.collider_id); result.rid = colObj->get_self(); ++m_count; @@ -250,10 +247,7 @@ btScalar GodotRestInfoContactResultCallback::addSingleResult(btManifoldPoint &cp m_rest_info_collision_object = colObj0Wrap->getCollisionObject(); } - if (colObj) - m_result->collider_id = colObj->get_instance_id(); - else - m_result->collider_id = 0; + m_result->collider_id = colObj->get_instance_id(); m_result->rid = colObj->get_self(); m_collided = true; diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index 8450a66f65..3a1f5d78dd 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -122,7 +122,7 @@ int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Tra ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->get(p_shape); - btCollisionShape *btShape = shape->create_bt_shape(p_xform.basis.get_scale(), p_margin); + btCollisionShape *btShape = shape->create_bt_shape(p_xform.basis.get_scale_abs(), p_margin); if (!btShape->isConvex()) { bulletdelete(btShape); ERR_PRINTS("The shape is not a convex shape, then is not supported: shape type: " + itos(shape->get_type())); @@ -202,7 +202,7 @@ bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform & ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->get(p_shape); - btCollisionShape *btShape = shape->create_bt_shape(p_shape_xform.basis.get_scale(), p_margin); + btCollisionShape *btShape = shape->create_bt_shape(p_shape_xform.basis.get_scale_abs(), p_margin); if (!btShape->isConvex()) { bulletdelete(btShape); ERR_PRINTS("The shape is not a convex shape, then is not supported: shape type: " + itos(shape->get_type())); @@ -234,7 +234,7 @@ bool BulletPhysicsDirectSpaceState::rest_info(RID p_shape, const Transform &p_sh ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->get(p_shape); - btCollisionShape *btShape = shape->create_bt_shape(p_shape_xform.basis.get_scale(), p_margin); + btCollisionShape *btShape = shape->create_bt_shape(p_shape_xform.basis.get_scale_abs(), p_margin); if (!btShape->isConvex()) { bulletdelete(btShape); ERR_PRINTS("The shape is not a convex shape, then is not supported: shape type: " + itos(shape->get_type())); diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp index 28b19224fb..95bb472c7b 100644 --- a/modules/enet/networked_multiplayer_enet.cpp +++ b/modules/enet/networked_multiplayer_enet.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "networked_multiplayer_enet.h" +#include "io/ip.h" #include "io/marshalls.h" #include "os/os.h" @@ -92,26 +93,39 @@ Error NetworkedMultiplayerENet::create_server(int p_port, int p_max_clients, int connection_status = CONNECTION_CONNECTED; return OK; } -Error NetworkedMultiplayerENet::create_client(const IP_Address &p_ip, int p_port, int p_in_bandwidth, int p_out_bandwidth) { +Error NetworkedMultiplayerENet::create_client(const String &p_address, int p_port, int p_in_bandwidth, int p_out_bandwidth) { ERR_FAIL_COND_V(active, ERR_ALREADY_IN_USE); host = enet_host_create(NULL /* create a client host */, 1 /* only allow 1 outgoing connection */, SYSCH_MAX /* allow up to SYSCH_MAX channels to be used */, - p_in_bandwidth /* 56K modem with 56 Kbps downstream bandwidth */, - p_out_bandwidth /* 56K modem with 14 Kbps upstream bandwidth */); + p_in_bandwidth /* limit incoming bandwith if > 0 */, + p_out_bandwidth /* limit outgoing bandwith if > 0 */); ERR_FAIL_COND_V(!host, ERR_CANT_CREATE); _setup_compressor(); + IP_Address ip; + if (p_address.is_valid_ip_address()) { + ip = p_address; + } else { +#ifdef GODOT_ENET + ip = IP::get_singleton()->resolve_hostname(p_address); +#else + ip = IP::get_singleton()->resolve_hostname(p_address, IP::TYPE_IPV4); +#endif + + ERR_FAIL_COND_V(!ip.is_valid(), ERR_CANT_RESOLVE); + } + ENetAddress address; #ifdef GODOT_ENET - enet_address_set_ip(&address, p_ip.get_ipv6(), 16); + enet_address_set_ip(&address, ip.get_ipv6(), 16); #else - ERR_FAIL_COND_V(!p_ip.is_ipv4(), ERR_INVALID_PARAMETER); - address.host = *(uint32_t *)p_ip.get_ipv4(); + ERR_FAIL_COND_V(!ip.is_ipv4(), ERR_INVALID_PARAMETER); + address.host = *(uint32_t *)ip.get_ipv4(); #endif address.port = p_port; @@ -708,7 +722,7 @@ int NetworkedMultiplayerENet::get_peer_port(int p_peer_id) const { void NetworkedMultiplayerENet::_bind_methods() { ClassDB::bind_method(D_METHOD("create_server", "port", "max_clients", "in_bandwidth", "out_bandwidth"), &NetworkedMultiplayerENet::create_server, DEFVAL(32), DEFVAL(0), DEFVAL(0)); - ClassDB::bind_method(D_METHOD("create_client", "ip", "port", "in_bandwidth", "out_bandwidth"), &NetworkedMultiplayerENet::create_client, DEFVAL(0), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("create_client", "address", "port", "in_bandwidth", "out_bandwidth"), &NetworkedMultiplayerENet::create_client, DEFVAL(0), DEFVAL(0)); ClassDB::bind_method(D_METHOD("close_connection"), &NetworkedMultiplayerENet::close_connection); ClassDB::bind_method(D_METHOD("disconnect_peer", "id", "now"), &NetworkedMultiplayerENet::disconnect_peer, DEFVAL(false)); ClassDB::bind_method(D_METHOD("set_compression_mode", "mode"), &NetworkedMultiplayerENet::set_compression_mode); diff --git a/modules/enet/networked_multiplayer_enet.h b/modules/enet/networked_multiplayer_enet.h index 0e8dd67160..678ae24135 100644 --- a/modules/enet/networked_multiplayer_enet.h +++ b/modules/enet/networked_multiplayer_enet.h @@ -119,7 +119,7 @@ public: virtual int get_peer_port(int p_peer_id) const; Error create_server(int p_port, int p_max_clients = 32, int p_in_bandwidth = 0, int p_out_bandwidth = 0); - Error create_client(const IP_Address &p_ip, int p_port, int p_in_bandwidth = 0, int p_out_bandwidth = 0); + Error create_client(const String &p_address, int p_port, int p_in_bandwidth = 0, int p_out_bandwidth = 0); void close_connection(); diff --git a/modules/gdnative/gdnative/string.cpp b/modules/gdnative/gdnative/string.cpp index ab0f0e0a50..7f5dbc12be 100644 --- a/modules/gdnative/gdnative/string.cpp +++ b/modules/gdnative/gdnative/string.cpp @@ -1168,6 +1168,24 @@ godot_string GDAPI godot_string_c_unescape(const godot_string *p_self) { return result; } +godot_string GDAPI godot_string_http_escape(const godot_string *p_self) { + const String *self = (const String *)p_self; + godot_string result; + String return_value = self->http_escape(); + memnew_placement(&result, String(return_value)); + + return result; +} + +godot_string GDAPI godot_string_http_unescape(const godot_string *p_self) { + const String *self = (const String *)p_self; + godot_string result; + String return_value = self->http_unescape(); + memnew_placement(&result, String(return_value)); + + return result; +} + godot_string GDAPI godot_string_json_escape(const godot_string *p_self) { const String *self = (const String *)p_self; godot_string result; diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json index 9da2a69360..f41c3859bd 100644 --- a/modules/gdnative/gdnative_api.json +++ b/modules/gdnative/gdnative_api.json @@ -5468,6 +5468,20 @@ ] }, { + "name": "godot_string_http_escape", + "return_type": "godot_string", + "arguments": [ + ["const godot_string *", "p_self"] + ] + }, + { + "name": "godot_string_http_unescape", + "return_type": "godot_string", + "arguments": [ + ["const godot_string *", "p_self"] + ] + }, + { "name": "godot_string_json_escape", "return_type": "godot_string", "arguments": [ diff --git a/modules/gdnative/include/gdnative/string.h b/modules/gdnative/include/gdnative/string.h index 8fc59e21da..73245160c1 100644 --- a/modules/gdnative/include/gdnative/string.h +++ b/modules/gdnative/include/gdnative/string.h @@ -228,14 +228,17 @@ godot_string GDAPI godot_string_simplify_path(const godot_string *p_self); godot_string GDAPI godot_string_c_escape(const godot_string *p_self); godot_string GDAPI godot_string_c_escape_multiline(const godot_string *p_self); godot_string GDAPI godot_string_c_unescape(const godot_string *p_self); -godot_string GDAPI godot_string_percent_decode(const godot_string *p_self); -godot_string GDAPI godot_string_percent_encode(const godot_string *p_self); +godot_string GDAPI godot_string_http_escape(const godot_string *p_self); +godot_string GDAPI godot_string_http_unescape(const godot_string *p_self); godot_string GDAPI godot_string_json_escape(const godot_string *p_self); godot_string GDAPI godot_string_word_wrap(const godot_string *p_self, godot_int p_chars_per_line); godot_string GDAPI godot_string_xml_escape(const godot_string *p_self); godot_string GDAPI godot_string_xml_escape_with_quotes(const godot_string *p_self); godot_string GDAPI godot_string_xml_unescape(const godot_string *p_self); +godot_string GDAPI godot_string_percent_decode(const godot_string *p_self); +godot_string GDAPI godot_string_percent_encode(const godot_string *p_self); + godot_bool GDAPI godot_string_is_valid_float(const godot_string *p_self); godot_bool GDAPI godot_string_is_valid_hex_number(const godot_string *p_self, godot_bool p_with_prefix); godot_bool GDAPI godot_string_is_valid_html_color(const godot_string *p_self); diff --git a/modules/mono/glue/cs_files/AABB.cs b/modules/mono/glue/cs_files/AABB.cs index 25458c93e1..39f2d2ed51 100644 --- a/modules/mono/glue/cs_files/AABB.cs +++ b/modules/mono/glue/cs_files/AABB.cs @@ -1,12 +1,10 @@ -using System; - // file: core/math/aabb.h // commit: 7ad14e7a3e6f87ddc450f7e34621eb5200808451 // file: core/math/aabb.cpp // commit: bd282ff43f23fe845f29a3e25c8efc01bd65ffb0 // file: core/variant_call.cpp // commit: 5ad9be4c24e9d7dc5672fdc42cea896622fe5685 - +using System; #if REAL_T_IS_DOUBLE using real_t = System.Double; #else @@ -51,12 +49,12 @@ namespace Godot Vector3 dst_min = with.position; Vector3 dst_max = with.position + with.size; - return ((src_min.x <= dst_min.x) && - (src_max.x > dst_max.x) && - (src_min.y <= dst_min.y) && - (src_max.y > dst_max.y) && - (src_min.z <= dst_min.z) && - (src_max.z > dst_max.z)); + return src_min.x <= dst_min.x && + src_max.x > dst_max.x && + src_min.y <= dst_min.y && + src_max.y > dst_max.y && + src_min.z <= dst_min.z && + src_max.z > dst_max.z; } public AABB Expand(Vector3 to_point) @@ -113,7 +111,7 @@ namespace Godot public Vector3 GetLongestAxis() { - Vector3 axis = new Vector3(1f, 0f, 0f); + var axis = new Vector3(1f, 0f, 0f); real_t max_size = size.x; if (size.y > max_size) @@ -125,7 +123,6 @@ namespace Godot if (size.z > max_size) { axis = new Vector3(0f, 0f, 1f); - max_size = size.z; } return axis; @@ -133,7 +130,7 @@ namespace Godot public Vector3.Axis GetLongestAxisIndex() { - Vector3.Axis axis = Vector3.Axis.X; + var axis = Vector3.Axis.X; real_t max_size = size.x; if (size.y > max_size) @@ -145,7 +142,6 @@ namespace Godot if (size.z > max_size) { axis = Vector3.Axis.Z; - max_size = size.z; } return axis; @@ -166,7 +162,7 @@ namespace Godot public Vector3 GetShortestAxis() { - Vector3 axis = new Vector3(1f, 0f, 0f); + var axis = new Vector3(1f, 0f, 0f); real_t max_size = size.x; if (size.y < max_size) @@ -178,7 +174,6 @@ namespace Godot if (size.z < max_size) { axis = new Vector3(0f, 0f, 1f); - max_size = size.z; } return axis; @@ -186,7 +181,7 @@ namespace Godot public Vector3.Axis GetShortestAxisIndex() { - Vector3.Axis axis = Vector3.Axis.X; + var axis = Vector3.Axis.X; real_t max_size = size.x; if (size.y < max_size) @@ -198,7 +193,6 @@ namespace Godot if (size.z < max_size) { axis = Vector3.Axis.Z; - max_size = size.z; } return axis; @@ -223,14 +217,14 @@ namespace Godot Vector3 ofs = position + half_extents; return ofs + new Vector3( - (dir.x > 0f) ? -half_extents.x : half_extents.x, - (dir.y > 0f) ? -half_extents.y : half_extents.y, - (dir.z > 0f) ? -half_extents.z : half_extents.z); + dir.x > 0f ? -half_extents.x : half_extents.x, + dir.y > 0f ? -half_extents.y : half_extents.y, + dir.z > 0f ? -half_extents.z : half_extents.z); } public AABB Grow(real_t by) { - AABB res = this; + var res = this; res.position.x -= by; res.position.y -= by; @@ -283,48 +277,42 @@ namespace Godot { return new AABB(); } - else - { - min.x = (src_min.x > dst_min.x) ? src_min.x : dst_min.x; - max.x = (src_max.x < dst_max.x) ? src_max.x : dst_max.x; - } + + min.x = src_min.x > dst_min.x ? src_min.x : dst_min.x; + max.x = src_max.x < dst_max.x ? src_max.x : dst_max.x; if (src_min.y > dst_max.y || src_max.y < dst_min.y) { return new AABB(); } - else - { - min.y = (src_min.y > dst_min.y) ? src_min.y : dst_min.y; - max.y = (src_max.y < dst_max.y) ? src_max.y : dst_max.y; - } + + min.y = src_min.y > dst_min.y ? src_min.y : dst_min.y; + max.y = src_max.y < dst_max.y ? src_max.y : dst_max.y; if (src_min.z > dst_max.z || src_max.z < dst_min.z) { return new AABB(); } - else - { - min.z = (src_min.z > dst_min.z) ? src_min.z : dst_min.z; - max.z = (src_max.z < dst_max.z) ? src_max.z : dst_max.z; - } + + min.z = src_min.z > dst_min.z ? src_min.z : dst_min.z; + max.z = src_max.z < dst_max.z ? src_max.z : dst_max.z; return new AABB(min, max - min); } public bool Intersects(AABB with) { - if (position.x >= (with.position.x + with.size.x)) + if (position.x >= with.position.x + with.size.x) return false; - if ((position.x + size.x) <= with.position.x) + if (position.x + size.x <= with.position.x) return false; - if (position.y >= (with.position.y + with.size.y)) + if (position.y >= with.position.y + with.size.y) return false; - if ((position.y + size.y) <= with.position.y) + if (position.y + size.y <= with.position.y) return false; - if (position.z >= (with.position.z + with.size.z)) + if (position.z >= with.position.z + with.size.z) return false; - if ((position.z + size.z) <= with.position.z) + if (position.z + size.z <= with.position.z) return false; return true; @@ -341,7 +329,7 @@ namespace Godot new Vector3(position.x + size.x, position.y, position.z), new Vector3(position.x + size.x, position.y, position.z + size.z), new Vector3(position.x + size.x, position.y + size.y, position.z), - new Vector3(position.x + size.x, position.y + size.y, position.z + size.z), + new Vector3(position.x + size.x, position.y + size.y, position.z + size.z) }; bool over = false; @@ -408,19 +396,19 @@ namespace Godot { Vector3 beg_1 = position; Vector3 beg_2 = with.position; - Vector3 end_1 = new Vector3(size.x, size.y, size.z) + beg_1; - Vector3 end_2 = new Vector3(with.size.x, with.size.y, with.size.z) + beg_2; + var end_1 = new Vector3(size.x, size.y, size.z) + beg_1; + var end_2 = new Vector3(with.size.x, with.size.y, with.size.z) + beg_2; - Vector3 min = new Vector3( - (beg_1.x < beg_2.x) ? beg_1.x : beg_2.x, - (beg_1.y < beg_2.y) ? beg_1.y : beg_2.y, - (beg_1.z < beg_2.z) ? beg_1.z : beg_2.z + var min = new Vector3( + beg_1.x < beg_2.x ? beg_1.x : beg_2.x, + beg_1.y < beg_2.y ? beg_1.y : beg_2.y, + beg_1.z < beg_2.z ? beg_1.z : beg_2.z ); - Vector3 max = new Vector3( - (end_1.x > end_2.x) ? end_1.x : end_2.x, - (end_1.y > end_2.y) ? end_1.y : end_2.y, - (end_1.z > end_2.z) ? end_1.z : end_2.z + var max = new Vector3( + end_1.x > end_2.x ? end_1.x : end_2.x, + end_1.y > end_2.y ? end_1.y : end_2.y, + end_1.z > end_2.z ? end_1.z : end_2.z ); return new AABB(min, max - min); @@ -467,8 +455,8 @@ namespace Godot { return String.Format("{0} - {1}", new object[] { - this.position.ToString(), - this.size.ToString() + position.ToString(), + size.ToString() }); } @@ -476,8 +464,8 @@ namespace Godot { return String.Format("{0} - {1}", new object[] { - this.position.ToString(format), - this.size.ToString(format) + position.ToString(format), + size.ToString(format) }); } } diff --git a/modules/mono/glue/cs_files/Basis.cs b/modules/mono/glue/cs_files/Basis.cs index 2e7e5404c4..929b13d70c 100644 --- a/modules/mono/glue/cs_files/Basis.cs +++ b/modules/mono/glue/cs_files/Basis.cs @@ -1,6 +1,5 @@ using System; using System.Runtime.InteropServices; - #if REAL_T_IS_DOUBLE using real_t = System.Double; #else @@ -19,8 +18,7 @@ namespace Godot new Vector3(0f, 0f, 1f) ); - private static readonly Basis[] orthoBases = new Basis[24] - { + private static readonly Basis[] orthoBases = { new Basis(1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f), new Basis(0f, -1f, 0f, 1f, 0f, 0f, 0f, 0f, 1f), new Basis(-1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, 1f), @@ -188,7 +186,7 @@ namespace Godot public Vector3 GetEuler() { - Basis m = this.Orthonormalized(); + Basis m = Orthonormalized(); Vector3 euler; euler.z = 0.0f; @@ -206,13 +204,13 @@ namespace Godot } else { - euler.x = Mathf.PI * 0.5f; + euler.x = Mathf.Pi * 0.5f; euler.y = -Mathf.Atan2(-m[0, 1], m[0, 0]); } } else { - euler.x = -Mathf.PI * 0.5f; + euler.x = -Mathf.Pi * 0.5f; euler.y = -Mathf.Atan2(-m[0, 1], m[0, 0]); } @@ -221,7 +219,7 @@ namespace Godot public int GetOrthogonalIndex() { - Basis orth = this; + var orth = this; for (int i = 0; i < 3; i++) { @@ -251,10 +249,9 @@ namespace Godot public Basis Inverse() { - Basis inv = this; + var inv = this; - real_t[] co = new real_t[3] - { + real_t[] co = { inv[1, 1] * inv[2, 2] - inv[1, 2] * inv[2, 1], inv[1, 2] * inv[2, 0] - inv[1, 0] * inv[2, 2], inv[1, 0] * inv[2, 1] - inv[1, 1] * inv[2, 0] @@ -297,12 +294,12 @@ namespace Godot Vector3 zAxis = GetAxis(2); xAxis.Normalize(); - yAxis = (yAxis - xAxis * (xAxis.Dot(yAxis))); + yAxis = yAxis - xAxis * xAxis.Dot(yAxis); yAxis.Normalize(); - zAxis = (zAxis - xAxis * (xAxis.Dot(zAxis)) - yAxis * (yAxis.Dot(zAxis))); + zAxis = zAxis - xAxis * xAxis.Dot(zAxis) - yAxis * yAxis.Dot(zAxis); zAxis.Normalize(); - return Basis.CreateFromAxes(xAxis, yAxis, zAxis); + return CreateFromAxes(xAxis, yAxis, zAxis); } public Basis Rotated(Vector3 axis, real_t phi) @@ -312,7 +309,7 @@ namespace Godot public Basis Scaled(Vector3 scale) { - Basis m = this; + var m = this; m[0, 0] *= scale.x; m[0, 1] *= scale.x; @@ -344,7 +341,7 @@ namespace Godot public Basis Transposed() { - Basis tr = this; + var tr = this; real_t temp = this[0, 1]; this[0, 1] = this[1, 0]; @@ -375,9 +372,9 @@ namespace Godot { return new Vector3 ( - (this[0, 0] * v.x) + (this[1, 0] * v.y) + (this[2, 0] * v.z), - (this[0, 1] * v.x) + (this[1, 1] * v.y) + (this[2, 1] * v.z), - (this[0, 2] * v.x) + (this[1, 2] * v.y) + (this[2, 2] * v.z) + this[0, 0] * v.x + this[1, 0] * v.y + this[2, 0] * v.z, + this[0, 1] * v.x + this[1, 1] * v.y + this[2, 1] * v.z, + this[0, 2] * v.x + this[1, 2] * v.y + this[2, 2] * v.z ); } @@ -393,34 +390,38 @@ namespace Godot (_y[0] - _x[1]) * inv_s, s * 0.25f ); - } else if (_x[0] > _y[1] && _x[0] > _z[2]) { - real_t s = Mathf.Sqrt(_x[0] - _y[1] - _z[2] + 1.0f) * 2f; - real_t inv_s = 1f / s; - return new Quat( - s * 0.25f, - (_x[1] + _y[0]) * inv_s, - (_x[2] + _z[0]) * inv_s, - (_z[1] - _y[2]) * inv_s - ); - } else if (_y[1] > _z[2]) { - real_t s = Mathf.Sqrt(-_x[0] + _y[1] - _z[2] + 1.0f) * 2f; - real_t inv_s = 1f / s; - return new Quat( - (_x[1] + _y[0]) * inv_s, - s * 0.25f, - (_y[2] + _z[1]) * inv_s, - (_x[2] - _z[0]) * inv_s - ); - } else { - real_t s = Mathf.Sqrt(-_x[0] - _y[1] + _z[2] + 1.0f) * 2f; - real_t inv_s = 1f / s; - return new Quat( - (_x[2] + _z[0]) * inv_s, - (_y[2] + _z[1]) * inv_s, - s * 0.25f, - (_y[0] - _x[1]) * inv_s - ); } + + if (_x[0] > _y[1] && _x[0] > _z[2]) { + real_t s = Mathf.Sqrt(_x[0] - _y[1] - _z[2] + 1.0f) * 2f; + real_t inv_s = 1f / s; + return new Quat( + s * 0.25f, + (_x[1] + _y[0]) * inv_s, + (_x[2] + _z[0]) * inv_s, + (_z[1] - _y[2]) * inv_s + ); + } + + if (_y[1] > _z[2]) { + real_t s = Mathf.Sqrt(-_x[0] + _y[1] - _z[2] + 1.0f) * 2f; + real_t inv_s = 1f / s; + return new Quat( + (_x[1] + _y[0]) * inv_s, + s * 0.25f, + (_y[2] + _z[1]) * inv_s, + (_x[2] - _z[0]) * inv_s + ); + } else { + real_t s = Mathf.Sqrt(-_x[0] - _y[1] + _z[2] + 1.0f) * 2f; + real_t inv_s = 1f / s; + return new Quat( + (_x[2] + _z[0]) * inv_s, + (_y[2] + _z[1]) * inv_s, + s * 0.25f, + (_y[0] - _x[1]) * inv_s + ); + } } public Basis(Quat quat) @@ -440,33 +441,33 @@ namespace Godot real_t yz = quat.y * zs; real_t zz = quat.z * zs; - this._x = new Vector3(1.0f - (yy + zz), xy - wz, xz + wy); - this._y = new Vector3(xy + wz, 1.0f - (xx + zz), yz - wx); - this._z = new Vector3(xz - wy, yz + wx, 1.0f - (xx + yy)); + _x = new Vector3(1.0f - (yy + zz), xy - wz, xz + wy); + _y = new Vector3(xy + wz, 1.0f - (xx + zz), yz - wx); + _z = new Vector3(xz - wy, yz + wx, 1.0f - (xx + yy)); } public Basis(Vector3 axis, real_t phi) { - Vector3 axis_sq = new Vector3(axis.x * axis.x, axis.y * axis.y, axis.z * axis.z); + var axis_sq = new Vector3(axis.x * axis.x, axis.y * axis.y, axis.z * axis.z); - real_t cosine = Mathf.Cos( (real_t)phi); - real_t sine = Mathf.Sin( (real_t)phi); + real_t cosine = Mathf.Cos( phi); + real_t sine = Mathf.Sin( phi); - this._x = new Vector3 + _x = new Vector3 ( axis_sq.x + cosine * (1.0f - axis_sq.x), axis.x * axis.y * (1.0f - cosine) - axis.z * sine, axis.z * axis.x * (1.0f - cosine) + axis.y * sine ); - this._y = new Vector3 + _y = new Vector3 ( axis.x * axis.y * (1.0f - cosine) + axis.z * sine, axis_sq.y + cosine * (1.0f - axis_sq.y), axis.y * axis.z * (1.0f - cosine) - axis.x * sine ); - this._z = new Vector3 + _z = new Vector3 ( axis.z * axis.x * (1.0f - cosine) - axis.y * sine, axis.y * axis.z * (1.0f - cosine) + axis.x * sine, @@ -476,16 +477,16 @@ namespace Godot public Basis(Vector3 xAxis, Vector3 yAxis, Vector3 zAxis) { - this._x = xAxis; - this._y = yAxis; - this._z = zAxis; + _x = xAxis; + _y = yAxis; + _z = zAxis; } public Basis(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz) { - this._x = new Vector3(xx, xy, xz); - this._y = new Vector3(yx, yy, yz); - this._z = new Vector3(zx, zy, zz); + _x = new Vector3(xx, xy, xz); + _y = new Vector3(yx, yy, yz); + _z = new Vector3(zx, zy, zz); } public static Basis operator *(Basis left, Basis right) @@ -532,9 +533,9 @@ namespace Godot { return String.Format("({0}, {1}, {2})", new object[] { - this._x.ToString(), - this._y.ToString(), - this._z.ToString() + _x.ToString(), + _y.ToString(), + _z.ToString() }); } @@ -542,9 +543,9 @@ namespace Godot { return String.Format("({0}, {1}, {2})", new object[] { - this._x.ToString(format), - this._y.ToString(format), - this._z.ToString(format) + _x.ToString(format), + _y.ToString(format), + _z.ToString(format) }); } } diff --git a/modules/mono/glue/cs_files/Color.cs b/modules/mono/glue/cs_files/Color.cs index aa42c487c8..af94bb616e 100644 --- a/modules/mono/glue/cs_files/Color.cs +++ b/modules/mono/glue/cs_files/Color.cs @@ -45,8 +45,8 @@ namespace Godot { get { - float max = (float) Mathf.Max(r, (float) Mathf.Max(g, b)); - float min = (float) Mathf.Min(r, (float) Mathf.Min(g, b)); + float max = Math.Max(r, Math.Max(g, b)); + float min = Math.Min(r, Math.Min(g, b)); float delta = max - min; @@ -79,8 +79,8 @@ namespace Godot { get { - float max = (float) Mathf.Max(r, (float) Mathf.Max(g, b)); - float min = (float) Mathf.Min(r, (float) Mathf.Min(g, b)); + float max = Math.Max(r, Math.Max(g, b)); + float min = Math.Min(r, Math.Min(g, b)); float delta = max - min; @@ -96,7 +96,7 @@ namespace Godot { get { - return (float) Mathf.Max(r, (float) Mathf.Max(g, b)); + return Math.Max(r, Math.Max(g, b)); } set { @@ -104,7 +104,7 @@ namespace Godot } } - private static readonly Color black = new Color(0f, 0f, 0f, 1.0f); + private static readonly Color black = new Color(0f, 0f, 0f); public Color Black { @@ -180,7 +180,7 @@ namespace Godot hue += 1.0f; } - saturation = (max == 0) ? 0 : 1f - (1f * min / max); + saturation = max == 0 ? 0 : 1f - 1f * min / max; value = max / 255f; } @@ -232,12 +232,10 @@ namespace Godot { return new Color(0, 0, 0, 0); } - else - { - res.r = (r * a * sa + over.r * over.a) / res.a; - res.g = (g * a * sa + over.g * over.a) / res.a; - res.b = (b * a * sa + over.b * over.a) / res.a; - } + + res.r = (r * a * sa + over.r * over.a) / res.a; + res.g = (g * a * sa + over.g * over.a) / res.a; + res.b = (b * a * sa + over.b * over.a) / res.a; return res; } @@ -265,14 +263,14 @@ namespace Godot ); } - public Color LinearInterpolate(Color b, float t) + public Color LinearInterpolate(Color c, float t) { - Color res = this; + var res = this; - res.r += (t * (b.r - this.r)); - res.g += (t * (b.g - this.g)); - res.b += (t * (b.b - this.b)); - res.a += (t * (b.a - this.a)); + res.r += t * (c.r - r); + res.g += t * (c.g - g); + res.b += t * (c.b - b); + res.a += t * (c.a - a); return res; } @@ -305,7 +303,7 @@ namespace Godot public string ToHtml(bool include_alpha = true) { - String txt = string.Empty; + var txt = string.Empty; txt += _to_hex(r); txt += _to_hex(g); @@ -328,13 +326,13 @@ namespace Godot public Color(int rgba) { - this.a = (rgba & 0xFF) / 255.0f; + a = (rgba & 0xFF) / 255.0f; rgba >>= 8; - this.b = (rgba & 0xFF) / 255.0f; + b = (rgba & 0xFF) / 255.0f; rgba >>= 8; - this.g = (rgba & 0xFF) / 255.0f; + g = (rgba & 0xFF) / 255.0f; rgba >>= 8; - this.r = (rgba & 0xFF) / 255.0f; + r = (rgba & 0xFF) / 255.0f; } private static int _parse_col(string str, int ofs) @@ -344,7 +342,7 @@ namespace Godot for (int i = 0; i < 2; i++) { int c = str[i + ofs]; - int v = 0; + int v; if (c >= '0' && c <= '9') { @@ -376,9 +374,9 @@ namespace Godot private String _to_hex(float val) { - int v = (int) Mathf.Clamp(val * 255.0f, 0, 255); + var v = (int) Mathf.Clamp(val * 255.0f, 0, 255); - string ret = string.Empty; + var ret = string.Empty; for (int i = 0; i < 2; i++) { @@ -405,7 +403,7 @@ namespace Godot if (color[0] == '#') color = color.Substring(1, color.Length - 1); - bool alpha = false; + bool alpha; if (color.Length == 8) alpha = true; @@ -434,7 +432,7 @@ namespace Godot public static Color Color8(byte r8, byte g8, byte b8, byte a8) { - return new Color((float)r8 / 255f, (float)g8 / 255f, (float)b8 / 255f, (float)a8 / 255f); + return new Color(r8 / 255f, g8 / 255f, b8 / 255f, a8 / 255f); } public Color(string rgba) @@ -451,7 +449,7 @@ namespace Godot if (rgba[0] == '#') rgba = rgba.Substring(1); - bool alpha = false; + bool alpha; if (rgba.Length == 8) { @@ -513,14 +511,11 @@ namespace Godot if (left.g == right.g) { if (left.b == right.b) - return (left.a < right.a); - else - return (left.b < right.b); - } - else - { - return left.g < right.g; + return left.a < right.a; + return left.b < right.b; } + + return left.g < right.g; } return left.r < right.r; @@ -533,14 +528,11 @@ namespace Godot if (left.g == right.g) { if (left.b == right.b) - return (left.a > right.a); - else - return (left.b > right.b); - } - else - { - return left.g > right.g; + return left.a > right.a; + return left.b > right.b; } + + return left.g > right.g; } return left.r > right.r; @@ -568,24 +560,12 @@ namespace Godot public override string ToString() { - return String.Format("{0},{1},{2},{3}", new object[] - { - this.r.ToString(), - this.g.ToString(), - this.b.ToString(), - this.a.ToString() - }); + return String.Format("{0},{1},{2},{3}", r.ToString(), g.ToString(), b.ToString(), a.ToString()); } public string ToString(string format) { - return String.Format("{0},{1},{2},{3}", new object[] - { - this.r.ToString(format), - this.g.ToString(format), - this.b.ToString(format), - this.a.ToString(format) - }); + return String.Format("{0},{1},{2},{3}", r.ToString(format), g.ToString(format), b.ToString(format), a.ToString(format)); } } } diff --git a/modules/mono/glue/cs_files/DebuggingUtils.cs b/modules/mono/glue/cs_files/DebuggingUtils.cs index ffaaf00837..b27816084e 100644 --- a/modules/mono/glue/cs_files/DebuggingUtils.cs +++ b/modules/mono/glue/cs_files/DebuggingUtils.cs @@ -14,7 +14,7 @@ namespace Godot else if (type == typeof(void)) sb.Append("void"); else - sb.Append(type.ToString()); + sb.Append(type); sb.Append(" "); } @@ -32,7 +32,7 @@ namespace Godot return; } - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); if (methodBase is MethodInfo) sb.AppendTypeName(((MethodInfo)methodBase).ReturnType); diff --git a/modules/mono/glue/cs_files/GD.cs b/modules/mono/glue/cs_files/GD.cs index 1ee7e7d21c..ec1534cb9a 100644 --- a/modules/mono/glue/cs_files/GD.cs +++ b/modules/mono/glue/cs_files/GD.cs @@ -91,7 +91,7 @@ namespace Godot public static int[] Range(int length) { - int[] ret = new int[length]; + var ret = new int[length]; for (int i = 0; i < length; i++) { @@ -106,7 +106,7 @@ namespace Godot if (to < from) return new int[0]; - int[] ret = new int[to - from]; + var ret = new int[to - from]; for (int i = from; i < to; i++) { @@ -124,14 +124,14 @@ namespace Godot return new int[0]; // Calculate count - int count = 0; + int count; if (increment > 0) - count = ((to - from - 1) / increment) + 1; + count = (to - from - 1) / increment + 1; else - count = ((from - to - 1) / -increment) + 1; + count = (from - to - 1) / -increment + 1; - int[] ret = new int[count]; + var ret = new int[count]; if (increment > 0) { diff --git a/modules/mono/glue/cs_files/GodotMethodAttribute.cs b/modules/mono/glue/cs_files/GodotMethodAttribute.cs index 21333c8dab..55848769d5 100644 --- a/modules/mono/glue/cs_files/GodotMethodAttribute.cs +++ b/modules/mono/glue/cs_files/GodotMethodAttribute.cs @@ -2,7 +2,7 @@ using System; namespace Godot { - [AttributeUsage(AttributeTargets.Method, Inherited = true)] + [AttributeUsage(AttributeTargets.Method)] internal class GodotMethodAttribute : Attribute { private string methodName; diff --git a/modules/mono/glue/cs_files/GodotSynchronizationContext.cs b/modules/mono/glue/cs_files/GodotSynchronizationContext.cs index eb4d0bed1c..da3c7bac83 100644 --- a/modules/mono/glue/cs_files/GodotSynchronizationContext.cs +++ b/modules/mono/glue/cs_files/GodotSynchronizationContext.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; diff --git a/modules/mono/glue/cs_files/GodotTaskScheduler.cs b/modules/mono/glue/cs_files/GodotTaskScheduler.cs index f587645a49..6bf25a89d2 100644 --- a/modules/mono/glue/cs_files/GodotTaskScheduler.cs +++ b/modules/mono/glue/cs_files/GodotTaskScheduler.cs @@ -36,7 +36,7 @@ namespace Godot TryDequeue(task); } - return base.TryExecuteTask(task); + return TryExecuteTask(task); } protected sealed override bool TryDequeue(Task task) diff --git a/modules/mono/glue/cs_files/IAwaiter.cs b/modules/mono/glue/cs_files/IAwaiter.cs index 73c71b5634..b5aa1a5389 100644 --- a/modules/mono/glue/cs_files/IAwaiter.cs +++ b/modules/mono/glue/cs_files/IAwaiter.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.CompilerServices; namespace Godot diff --git a/modules/mono/glue/cs_files/MarshalUtils.cs b/modules/mono/glue/cs_files/MarshalUtils.cs index 2bdfb95c51..ff4477cc6c 100644 --- a/modules/mono/glue/cs_files/MarshalUtils.cs +++ b/modules/mono/glue/cs_files/MarshalUtils.cs @@ -7,7 +7,7 @@ namespace Godot { private static Dictionary<object, object> ArraysToDictionary(object[] keys, object[] values) { - Dictionary<object, object> ret = new Dictionary<object, object>(); + var ret = new Dictionary<object, object>(); for (int i = 0; i < keys.Length; i++) { @@ -19,11 +19,11 @@ namespace Godot private static void DictionaryToArrays(Dictionary<object, object> from, out object[] keysTo, out object[] valuesTo) { - Dictionary<object, object>.KeyCollection keys = from.Keys; + var keys = from.Keys; keysTo = new object[keys.Count]; keys.CopyTo(keysTo, 0); - Dictionary<object, object>.ValueCollection values = from.Values; + var values = from.Values; valuesTo = new object[values.Count]; values.CopyTo(valuesTo, 0); } diff --git a/modules/mono/glue/cs_files/Mathf.cs b/modules/mono/glue/cs_files/Mathf.cs index adbcc855ef..0d20a12563 100644 --- a/modules/mono/glue/cs_files/Mathf.cs +++ b/modules/mono/glue/cs_files/Mathf.cs @@ -1,5 +1,4 @@ using System; - #if REAL_T_IS_DOUBLE using real_t = System.Double; #else @@ -8,16 +7,14 @@ using real_t = System.Single; namespace Godot { - public static class Mathf + public static partial class Mathf { - // Define constants with Decimal precision and cast down to double or float. - public const real_t PI = (real_t) 3.1415926535897932384626433833M; // 3.1415927f and 3.14159265358979 + // Define constants with Decimal precision and cast down to double or float. - #if REAL_T_IS_DOUBLE - public const real_t Epsilon = 1e-14; // Epsilon size should depend on the precision used. - #else - public const real_t Epsilon = 1e-06f; - #endif + public const real_t Tau = (real_t) 6.2831853071795864769252867666M; // 6.2831855f and 6.28318530717959 + public const real_t Pi = (real_t) 3.1415926535897932384626433833M; // 3.1415927f and 3.14159265358979 + public const real_t Inf = real_t.PositiveInfinity; + public const real_t NaN = real_t.NaN; private const real_t Deg2RadConst = (real_t) 0.0174532925199432957692369077M; // 0.0174532924f and 0.0174532925199433 private const real_t Rad2DegConst = (real_t) 57.295779513082320876798154814M; // 57.29578f and 57.2957795130823 @@ -27,6 +24,11 @@ namespace Godot return Math.Abs(s); } + public static int Abs(int s) + { + return Math.Abs(s); + } + public static real_t Acos(real_t s) { return (real_t)Math.Acos(s); @@ -57,18 +59,14 @@ namespace Godot return (real_t)Math.Ceiling(s); } - public static real_t Clamp(real_t val, real_t min, real_t max) + public static int Clamp(int value, int min, int max) { - if (val < min) - { - return min; - } - else if (val > max) - { - return max; - } + return value < min ? min : value > max ? max : value; + } - return val; + public static real_t Clamp(real_t value, real_t min, real_t max) + { + return value < min ? min : value > max ? max : value; } public static real_t Cos(real_t s) @@ -116,7 +114,8 @@ namespace Godot return Pow(s, curve); } - else if (curve < 0f) + + if (curve < 0f) { if (s < 0.5f) { @@ -145,10 +144,23 @@ namespace Godot { return x % y; } - else - { - return y - (-x % y); - } + + return y - -x % y; + } + + public static real_t InverseLerp(real_t from, real_t to, real_t weight) + { + return (Clamp(weight, 0f, 1f) - from) / (to - from); + } + + public static bool IsInf(real_t s) + { + return real_t.IsInfinity(s); + } + + public static bool IsNaN(real_t s) + { + return real_t.IsNaN(s); } public static real_t Lerp(real_t from, real_t to, real_t weight) @@ -163,34 +175,34 @@ namespace Godot public static int Max(int a, int b) { - return (a > b) ? a : b; + return a > b ? a : b; } public static real_t Max(real_t a, real_t b) { - return (a > b) ? a : b; + return a > b ? a : b; } public static int Min(int a, int b) { - return (a < b) ? a : b; + return a < b ? a : b; } public static real_t Min(real_t a, real_t b) { - return (a < b) ? a : b; + return a < b ? a : b; } - public static int NearestPo2(int val) + public static int NearestPo2(int value) { - val--; - val |= val >> 1; - val |= val >> 2; - val |= val >> 4; - val |= val >> 8; - val |= val >> 16; - val++; - return val; + value--; + value |= value >> 1; + value |= value >> 2; + value |= value >> 4; + value |= value >> 8; + value |= value >> 16; + value++; + return value; } public static Vector2 Polar2Cartesian(real_t r, real_t th) @@ -213,14 +225,14 @@ namespace Godot return (real_t)Math.Round(s); } - public static int RoundToInt(real_t s) + public static int Sign(int s) { - return (int)Math.Round(s); + return s < 0 ? -1 : 1; } public static real_t Sign(real_t s) { - return (s < 0f) ? -1f : 1f; + return s < 0f ? -1f : 1f; } public static real_t Sin(real_t s) @@ -258,16 +270,16 @@ namespace Godot return (real_t)Math.Tanh(s); } - public static int Wrap(int val, int min, int max) + public static int Wrap(int value, int min, int max) { int rng = max - min; - return min + ((((val - min) % rng) + rng) % rng); + return min + ((value - min) % rng + rng) % rng; } - public static real_t Wrap(real_t val, real_t min, real_t max) + public static real_t Wrap(real_t value, real_t min, real_t max) { real_t rng = max - min; - return min + (val - min) - (rng * Floor((val - min) / rng)); + return min + ((value - min) % rng + rng) % rng; } } } diff --git a/modules/mono/glue/cs_files/MathfEx.cs b/modules/mono/glue/cs_files/MathfEx.cs new file mode 100644 index 0000000000..739b7fb568 --- /dev/null +++ b/modules/mono/glue/cs_files/MathfEx.cs @@ -0,0 +1,39 @@ +using System; + +#if REAL_T_IS_DOUBLE +using real_t = System.Double; +#else +using real_t = System.Single; +#endif + +namespace Godot +{ + public static partial class Mathf + { + // Define constants with Decimal precision and cast down to double or float. + + public const real_t E = (real_t) 2.7182818284590452353602874714M; // 2.7182817f and 2.718281828459045 + public const real_t Sqrt2 = (real_t) 1.4142135623730950488016887242M; // 1.4142136f and 1.414213562373095 + +#if REAL_T_IS_DOUBLE + public const real_t Epsilon = 1e-14; // Epsilon size should depend on the precision used. +#else + public const real_t Epsilon = 1e-06f; +#endif + + public static int CeilToInt(real_t s) + { + return (int)Math.Ceiling(s); + } + + public static int FloorToInt(real_t s) + { + return (int)Math.Floor(s); + } + + public static int RoundToInt(real_t s) + { + return (int)Math.Round(s); + } + } +}
\ No newline at end of file diff --git a/modules/mono/glue/cs_files/Plane.cs b/modules/mono/glue/cs_files/Plane.cs index 0f74f3b66a..8b92522029 100644 --- a/modules/mono/glue/cs_files/Plane.cs +++ b/modules/mono/glue/cs_files/Plane.cs @@ -1,5 +1,4 @@ using System; - #if REAL_T_IS_DOUBLE using real_t = System.Double; #else @@ -81,9 +80,9 @@ namespace Godot if (Mathf.Abs(denom) <= Mathf.Epsilon) return new Vector3(); - Vector3 result = (b.normal.Cross(c.normal) * this.d) + - (c.normal.Cross(normal) * b.d) + - (normal.Cross(b.normal) * c.d); + Vector3 result = b.normal.Cross(c.normal) * d + + c.normal.Cross(normal) * b.d + + normal.Cross(b.normal) * c.d; return result / denom; } @@ -114,7 +113,7 @@ namespace Godot real_t dist = (normal.Dot(begin) - d) / den; - if (dist < -Mathf.Epsilon || dist > (1.0f + Mathf.Epsilon)) + if (dist < -Mathf.Epsilon || dist > 1.0f + Mathf.Epsilon) return new Vector3(); return begin + segment * -dist; @@ -198,8 +197,8 @@ namespace Godot { return String.Format("({0}, {1})", new object[] { - this.normal.ToString(), - this.d.ToString() + normal.ToString(), + d.ToString() }); } @@ -207,8 +206,8 @@ namespace Godot { return String.Format("({0}, {1})", new object[] { - this.normal.ToString(format), - this.d.ToString(format) + normal.ToString(format), + d.ToString(format) }); } } diff --git a/modules/mono/glue/cs_files/Quat.cs b/modules/mono/glue/cs_files/Quat.cs index 0cf3e00ddb..c69c55d997 100644 --- a/modules/mono/glue/cs_files/Quat.cs +++ b/modules/mono/glue/cs_files/Quat.cs @@ -1,6 +1,5 @@ using System; using System.Runtime.InteropServices; - #if REAL_T_IS_DOUBLE using real_t = System.Double; #else @@ -106,10 +105,10 @@ namespace Godot } public void Set(Quat q) { - this.x = q.x; - this.y = q.y; - this.z = q.z; - this.w = q.w; + x = q.x; + y = q.y; + z = q.z; + w = q.w; } public Quat Slerp(Quat b, real_t t) @@ -117,7 +116,7 @@ namespace Godot // Calculate cosine real_t cosom = x * b.x + y * b.y + z * b.z + w * b.w; - real_t[] to1 = new real_t[4]; + var to1 = new real_t[4]; // Adjust signs if necessary if (cosom < 0.0) @@ -138,7 +137,7 @@ namespace Godot real_t sinom, scale0, scale1; // Calculate coefficients - if ((1.0 - cosom) > Mathf.Epsilon) + if (1.0 - cosom > Mathf.Epsilon) { // Standard case (Slerp) real_t omega = Mathf.Acos(cosom); @@ -165,7 +164,7 @@ namespace Godot public Quat Slerpni(Quat b, real_t t) { - real_t dot = this.Dot(b); + real_t dot = Dot(b); if (Mathf.Abs(dot) > 0.9999f) { @@ -179,17 +178,17 @@ namespace Godot return new Quat ( - invFactor * this.x + newFactor * b.x, - invFactor * this.y + newFactor * b.y, - invFactor * this.z + newFactor * b.z, - invFactor * this.w + newFactor * b.w + invFactor * x + newFactor * b.x, + invFactor * y + newFactor * b.y, + invFactor * z + newFactor * b.z, + invFactor * w + newFactor * b.w ); } public Vector3 Xform(Vector3 v) { Quat q = this * v; - q *= this.Inverse(); + q *= Inverse(); return new Vector3(q.x, q.y, q.z); } @@ -203,10 +202,10 @@ namespace Godot } public Quat(Quat q) { - this.x = q.x; - this.y = q.y; - this.z = q.z; - this.w = q.w; + x = q.x; + y = q.y; + z = q.z; + w = q.w; } public Quat(Vector3 axis, real_t angle) @@ -327,24 +326,12 @@ namespace Godot public override string ToString() { - return String.Format("({0}, {1}, {2}, {3})", new object[] - { - this.x.ToString(), - this.y.ToString(), - this.z.ToString(), - this.w.ToString() - }); + return String.Format("({0}, {1}, {2}, {3})", x.ToString(), y.ToString(), z.ToString(), w.ToString()); } public string ToString(string format) { - return String.Format("({0}, {1}, {2}, {3})", new object[] - { - this.x.ToString(format), - this.y.ToString(format), - this.z.ToString(format), - this.w.ToString(format) - }); + return String.Format("({0}, {1}, {2}, {3})", x.ToString(format), y.ToString(format), z.ToString(format), w.ToString(format)); } } } diff --git a/modules/mono/glue/cs_files/Rect2.cs b/modules/mono/glue/cs_files/Rect2.cs index decee35f8c..6f16656573 100644 --- a/modules/mono/glue/cs_files/Rect2.cs +++ b/modules/mono/glue/cs_files/Rect2.cs @@ -1,6 +1,5 @@ using System; using System.Runtime.InteropServices; - #if REAL_T_IS_DOUBLE using real_t = System.Double; #else @@ -39,7 +38,7 @@ namespace Godot public Rect2 Clip(Rect2 b) { - Rect2 newRect = b; + var newRect = b; if (!Intersects(newRect)) return new Rect2(); @@ -58,14 +57,14 @@ namespace Godot public bool Encloses(Rect2 b) { - return (b.position.x >= position.x) && (b.position.y >= position.y) && - ((b.position.x + b.size.x) < (position.x + size.x)) && - ((b.position.y + b.size.y) < (position.y + size.y)); + return b.position.x >= position.x && b.position.y >= position.y && + b.position.x + b.size.x < position.x + size.x && + b.position.y + b.size.y < position.y + size.y; } public Rect2 Expand(Vector2 to) { - Rect2 expanded = this; + var expanded = this; Vector2 begin = expanded.position; Vector2 end = expanded.position + expanded.size; @@ -93,7 +92,7 @@ namespace Godot public Rect2 Grow(real_t by) { - Rect2 g = this; + var g = this; g.position.x -= by; g.position.y -= by; @@ -105,7 +104,7 @@ namespace Godot public Rect2 GrowIndividual(real_t left, real_t top, real_t right, real_t bottom) { - Rect2 g = this; + var g = this; g.position.x -= left; g.position.y -= top; @@ -117,12 +116,12 @@ namespace Godot public Rect2 GrowMargin(Margin margin, real_t by) { - Rect2 g = this; + var g = this; - g.GrowIndividual((Margin.Left == margin) ? by : 0, - (Margin.Top == margin) ? by : 0, - (Margin.Right == margin) ? by : 0, - (Margin.Bottom == margin) ? by : 0); + g.GrowIndividual(Margin.Left == margin ? by : 0, + Margin.Top == margin ? by : 0, + Margin.Right == margin ? by : 0, + Margin.Bottom == margin ? by : 0); return g; } @@ -139,9 +138,9 @@ namespace Godot if (point.y < position.y) return false; - if (point.x >= (position.x + size.x)) + if (point.x >= position.x + size.x) return false; - if (point.y >= (position.y + size.y)) + if (point.y >= position.y + size.y) return false; return true; @@ -149,13 +148,13 @@ namespace Godot public bool Intersects(Rect2 b) { - if (position.x > (b.position.x + b.size.x)) + if (position.x > b.position.x + b.size.x) return false; - if ((position.x + size.x) < b.position.x) + if (position.x + size.x < b.position.x) return false; - if (position.y > (b.position.y + b.size.y)) + if (position.y > b.position.y + b.size.y) return false; - if ((position.y + size.y) < b.position.y) + if (position.y + size.y < b.position.y) return false; return true; @@ -185,17 +184,17 @@ namespace Godot public Rect2(Vector2 position, real_t width, real_t height) { this.position = position; - this.size = new Vector2(width, height); + size = new Vector2(width, height); } public Rect2(real_t x, real_t y, Vector2 size) { - this.position = new Vector2(x, y); + position = new Vector2(x, y); this.size = size; } public Rect2(real_t x, real_t y, real_t width, real_t height) { - this.position = new Vector2(x, y); - this.size = new Vector2(width, height); + position = new Vector2(x, y); + size = new Vector2(width, height); } public static bool operator ==(Rect2 left, Rect2 right) @@ -232,8 +231,8 @@ namespace Godot { return String.Format("({0}, {1})", new object[] { - this.position.ToString(), - this.size.ToString() + position.ToString(), + size.ToString() }); } @@ -241,8 +240,8 @@ namespace Godot { return String.Format("({0}, {1})", new object[] { - this.position.ToString(format), - this.size.ToString(format) + position.ToString(format), + size.ToString(format) }); } } diff --git a/modules/mono/glue/cs_files/SignalAttribute.cs b/modules/mono/glue/cs_files/SignalAttribute.cs index d8a6cabb83..3957387be9 100644 --- a/modules/mono/glue/cs_files/SignalAttribute.cs +++ b/modules/mono/glue/cs_files/SignalAttribute.cs @@ -5,8 +5,5 @@ namespace Godot [AttributeUsage(AttributeTargets.Delegate)] public class SignalAttribute : Attribute { - public SignalAttribute() - { - } } } diff --git a/modules/mono/glue/cs_files/SignalAwaiter.cs b/modules/mono/glue/cs_files/SignalAwaiter.cs index 19ccc26e79..c06f6b05c9 100644 --- a/modules/mono/glue/cs_files/SignalAwaiter.cs +++ b/modules/mono/glue/cs_files/SignalAwaiter.cs @@ -4,15 +4,15 @@ namespace Godot { public class SignalAwaiter : IAwaiter<object[]>, IAwaitable<object[]> { - private bool completed = false; - private object[] result = null; - private Action action = null; + private bool completed; + private object[] result; + private Action action; - public SignalAwaiter(Godot.Object source, string signal, Godot.Object target) + public SignalAwaiter(Object source, string signal, Object target) { NativeCalls.godot_icall_Object_connect_signal_awaiter( - Godot.Object.GetPtr(source), - signal, Godot.Object.GetPtr(target), this + Object.GetPtr(source), + signal, Object.GetPtr(target), this ); } diff --git a/modules/mono/glue/cs_files/StringExtensions.cs b/modules/mono/glue/cs_files/StringExtensions.cs index cbc337ab19..21090fb68d 100644 --- a/modules/mono/glue/cs_files/StringExtensions.cs +++ b/modules/mono/glue/cs_files/StringExtensions.cs @@ -1,4 +1,5 @@ //using System; + using System; using System.Collections.Generic; using System.Globalization; @@ -43,11 +44,9 @@ namespace Godot { return instance.Substring(prev, i - prev); } - else - { - count++; - prev = i + 1; - } + + count++; + prev = i + 1; } i++; @@ -83,7 +82,7 @@ namespace Godot // </summary> public static string[] Bigrams(this string instance) { - string[] b = new string[instance.Length - 1]; + var b = new string[instance.Length - 1]; for (int i = 0; i < b.Length; i++) { @@ -98,7 +97,7 @@ namespace Godot // </summary> public static string CEscape(this string instance) { - StringBuilder sb = new StringBuilder(string.Copy(instance)); + var sb = new StringBuilder(string.Copy(instance)); sb.Replace("\\", "\\\\"); sb.Replace("\a", "\\a"); @@ -120,7 +119,7 @@ namespace Godot // </summary> public static string CUnescape(this string instance) { - StringBuilder sb = new StringBuilder(string.Copy(instance)); + var sb = new StringBuilder(string.Copy(instance)); sb.Replace("\\a", "\a"); sb.Replace("\\b", "\b"); @@ -143,7 +142,7 @@ namespace Godot public static string Capitalize(this string instance) { string aux = instance.Replace("_", " ").ToLower(); - string cap = string.Empty; + var cap = string.Empty; for (int i = 0; i < aux.GetSliceCount(" "); i++) { @@ -178,13 +177,13 @@ namespace Godot { if (to[to_idx] == 0 && instance[instance_idx] == 0) return 0; // We're equal - else if (instance[instance_idx] == 0) + if (instance[instance_idx] == 0) return -1; // If this is empty, and the other one is not, then we're less... I think? - else if (to[to_idx] == 0) + if (to[to_idx] == 0) return 1; // Otherwise the other one is smaller... - else if (instance[instance_idx] < to[to_idx]) // More than + if (instance[instance_idx] < to[to_idx]) // More than return -1; - else if (instance[instance_idx] > to[to_idx]) // Less than + if (instance[instance_idx] > to[to_idx]) // Less than return 1; instance_idx++; @@ -260,12 +259,12 @@ namespace Godot { int basepos = instance.Find("://"); - string rs = string.Empty; - string @base = string.Empty; + string rs; + var @base = string.Empty; if (basepos != -1) { - int end = basepos + 3; + var end = basepos + 3; rs = instance.Substring(end, instance.Length); @base = instance.Substring(0, end); } @@ -312,8 +311,8 @@ namespace Godot int hashv = 5381; int c; - while ((c = (int)instance[index++]) != 0) - hashv = ((hashv << 5) + hashv) + c; // hash * 33 + c + while ((c = instance[index++]) != 0) + hashv = (hashv << 5) + hashv + c; // hash * 33 + c return hashv; } @@ -379,7 +378,7 @@ namespace Godot while (instance[src] != 0 && text[tgt] != 0) { - bool match = false; + bool match; if (case_insensitive) { @@ -455,7 +454,10 @@ namespace Godot return false; // Don't start with number plz } - bool valid_char = (instance[i] >= '0' && instance[i] <= '9') || (instance[i] >= 'a' && instance[i] <= 'z') || (instance[i] >= 'A' && instance[i] <= 'Z') || instance[i] == '_'; + bool valid_char = instance[i] >= '0' && + instance[i] <= '9' || instance[i] >= 'a' && + instance[i] <= 'z' || instance[i] >= 'A' && + instance[i] <= 'Z' || instance[i] == '_'; if (!valid_char) return false; @@ -502,7 +504,7 @@ namespace Godot // </summary> public static string JsonEscape(this string instance) { - StringBuilder sb = new StringBuilder(string.Copy(instance)); + var sb = new StringBuilder(string.Copy(instance)); sb.Replace("\\", "\\\\"); sb.Replace("\b", "\\b"); @@ -551,7 +553,7 @@ namespace Godot case '\0': return instance[0] == 0; case '*': - return ExprMatch(expr + 1, instance, caseSensitive) || (instance[0] != 0 && ExprMatch(expr, instance + 1, caseSensitive)); + return ExprMatch(expr + 1, instance, caseSensitive) || instance[0] != 0 && ExprMatch(expr, instance + 1, caseSensitive); case '?': return instance[0] != 0 && instance[0] != '.' && ExprMatch(expr + 1, instance + 1, caseSensitive); default: @@ -610,13 +612,13 @@ namespace Godot { if (to[to_idx] == 0 && instance[instance_idx] == 0) return 0; // We're equal - else if (instance[instance_idx] == 0) + if (instance[instance_idx] == 0) return -1; // If this is empty, and the other one is not, then we're less... I think? - else if (to[to_idx] == 0) + if (to[to_idx] == 0) return 1; // Otherwise the other one is smaller.. - else if (char.ToUpper(instance[instance_idx]) < char.ToUpper(to[to_idx])) // More than + if (char.ToUpper(instance[instance_idx]) < char.ToUpper(to[to_idx])) // More than return -1; - else if (char.ToUpper(instance[instance_idx]) > char.ToUpper(to[to_idx])) // Less than + if (char.ToUpper(instance[instance_idx]) > char.ToUpper(to[to_idx])) // Less than return 1; instance_idx++; @@ -724,8 +726,7 @@ namespace Godot { if (instance.Length > 0 && instance[instance.Length - 1] == '/') return instance + file; - else - return instance + "/" + file; + return instance + "/" + file; } // <summary> @@ -771,7 +772,7 @@ namespace Godot if (pos < 0) return string.Empty; - return instance.Substring(pos, (instance.Length - pos)); + return instance.Substring(pos, instance.Length - pos); } public static byte[] Sha256Buffer(this string instance) @@ -824,7 +825,7 @@ namespace Godot } } - return (2.0f * inter) / sum; + return 2.0f * inter / sum; } // <summary> @@ -832,7 +833,7 @@ namespace Godot // </summary> public static string[] Split(this string instance, string divisor, bool allow_empty = true) { - return instance.Split(new string[] { divisor }, StringSplitOptions.RemoveEmptyEntries); + return instance.Split(new[] { divisor }, StringSplitOptions.RemoveEmptyEntries); } // <summary> @@ -840,7 +841,7 @@ namespace Godot // </summary> public static float[] SplitFloats(this string instance, string divisor, bool allow_empty = true) { - List<float> ret = new List<float>(); + var ret = new List<float>(); int from = 0; int len = instance.Length; @@ -849,7 +850,7 @@ namespace Godot int end = instance.Find(divisor, from); if (end < 0) end = len; - if (allow_empty || (end > from)) + if (allow_empty || end > from) ret.Add(float.Parse(instance.Substring(from))); if (end == len) break; @@ -878,13 +879,10 @@ namespace Godot { if (right) return instance.Trim(non_printable); - else - return instance.TrimStart(non_printable); - } - else - { - return instance.TrimEnd(non_printable); + return instance.TrimStart(non_printable); } + + return instance.TrimEnd(non_printable); } // <summary> diff --git a/modules/mono/glue/cs_files/Transform.cs b/modules/mono/glue/cs_files/Transform.cs index ce26c60706..d1b247a552 100644 --- a/modules/mono/glue/cs_files/Transform.cs +++ b/modules/mono/glue/cs_files/Transform.cs @@ -1,6 +1,5 @@ using System; using System.Runtime.InteropServices; - #if REAL_T_IS_DOUBLE using real_t = System.Double; #else @@ -29,7 +28,7 @@ namespace Godot public Transform LookingAt(Vector3 target, Vector3 up) { - Transform t = this; + var t = this; t.SetLookAt(origin, target, up); return t; } @@ -98,22 +97,22 @@ namespace Godot return new Vector3 ( - (basis[0, 0] * vInv.x) + (basis[1, 0] * vInv.y) + (basis[2, 0] * vInv.z), - (basis[0, 1] * vInv.x) + (basis[1, 1] * vInv.y) + (basis[2, 1] * vInv.z), - (basis[0, 2] * vInv.x) + (basis[1, 2] * vInv.y) + (basis[2, 2] * vInv.z) + basis[0, 0] * vInv.x + basis[1, 0] * vInv.y + basis[2, 0] * vInv.z, + basis[0, 1] * vInv.x + basis[1, 1] * vInv.y + basis[2, 1] * vInv.z, + basis[0, 2] * vInv.x + basis[1, 2] * vInv.y + basis[2, 2] * vInv.z ); } // Constructors public Transform(Vector3 xAxis, Vector3 yAxis, Vector3 zAxis, Vector3 origin) { - this.basis = Basis.CreateFromAxes(xAxis, yAxis, zAxis); + basis = Basis.CreateFromAxes(xAxis, yAxis, zAxis); this.origin = origin; } public Transform(Quat quat, Vector3 origin) { - this.basis = new Basis(quat); + basis = new Basis(quat); this.origin = origin; } @@ -164,8 +163,8 @@ namespace Godot { return String.Format("{0} - {1}", new object[] { - this.basis.ToString(), - this.origin.ToString() + basis.ToString(), + origin.ToString() }); } @@ -173,8 +172,8 @@ namespace Godot { return String.Format("{0} - {1}", new object[] { - this.basis.ToString(format), - this.origin.ToString(format) + basis.ToString(format), + origin.ToString(format) }); } } diff --git a/modules/mono/glue/cs_files/Transform2D.cs b/modules/mono/glue/cs_files/Transform2D.cs index 836cca129e..ff5259178b 100644 --- a/modules/mono/glue/cs_files/Transform2D.cs +++ b/modules/mono/glue/cs_files/Transform2D.cs @@ -1,6 +1,5 @@ using System; using System.Runtime.InteropServices; - #if REAL_T_IS_DOUBLE using real_t = System.Double; #else @@ -111,7 +110,7 @@ namespace Godot public Transform2D AffineInverse() { - Transform2D inv = this; + var inv = this; real_t det = this[0, 0] * this[1, 1] - this[1, 0] * this[0, 1]; @@ -158,15 +157,15 @@ namespace Godot Vector2 s2 = m.Scale; // Slerp rotation - Vector2 v1 = new Vector2(Mathf.Cos(r1), Mathf.Sin(r1)); - Vector2 v2 = new Vector2(Mathf.Cos(r2), Mathf.Sin(r2)); + var v1 = new Vector2(Mathf.Cos(r1), Mathf.Sin(r1)); + var v2 = new Vector2(Mathf.Cos(r2), Mathf.Sin(r2)); real_t dot = v1.Dot(v2); // Clamp dot to [-1, 1] - dot = (dot < -1.0f) ? -1.0f : ((dot > 1.0f) ? 1.0f : dot); + dot = dot < -1.0f ? -1.0f : (dot > 1.0f ? 1.0f : dot); - Vector2 v = new Vector2(); + Vector2 v; if (dot > 0.9995f) { @@ -185,7 +184,7 @@ namespace Godot Vector2 p2 = m.Origin; // Construct matrix - Transform2D res = new Transform2D(Mathf.Atan2(v.y, v.x), p1.LinearInterpolate(p2, c)); + var res = new Transform2D(Mathf.Atan2(v.y, v.x), p1.LinearInterpolate(p2, c)); Vector2 scale = s1.LinearInterpolate(s2, c); res.x *= scale; res.y *= scale; @@ -195,7 +194,7 @@ namespace Godot public Transform2D Inverse() { - Transform2D inv = this; + var inv = this; // Swap real_t temp = inv.x.y; @@ -209,13 +208,13 @@ namespace Godot public Transform2D Orthonormalized() { - Transform2D on = this; + var on = this; Vector2 onX = on.x; Vector2 onY = on.y; onX.Normalize(); - onY = onY - onX * (onX.Dot(onY)); + onY = onY - onX * onX.Dot(onY); onY.Normalize(); on.x = onX; @@ -231,7 +230,7 @@ namespace Godot public Transform2D Scaled(Vector2 scale) { - Transform2D copy = this; + var copy = this; copy.x *= scale; copy.y *= scale; copy.o *= scale; @@ -250,7 +249,7 @@ namespace Godot public Transform2D Translated(Vector2 offset) { - Transform2D copy = this; + var copy = this; copy.o += copy.BasisXform(offset); return copy; } @@ -269,22 +268,22 @@ namespace Godot // Constructors public Transform2D(Vector2 xAxis, Vector2 yAxis, Vector2 origin) { - this.x = xAxis; - this.y = yAxis; - this.o = origin; + x = xAxis; + y = yAxis; + o = origin; } public Transform2D(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy) { - this.x = new Vector2(xx, xy); - this.y = new Vector2(yx, yy); - this.o = new Vector2(ox, oy); + x = new Vector2(xx, xy); + y = new Vector2(yx, yy); + o = new Vector2(ox, oy); } public Transform2D(real_t rot, Vector2 pos) { - real_t cr = Mathf.Cos( (real_t)rot); - real_t sr = Mathf.Sin( (real_t)rot); + real_t cr = Mathf.Cos(rot); + real_t sr = Mathf.Sin(rot); x.x = cr; y.y = cr; x.y = -sr; @@ -345,9 +344,9 @@ namespace Godot { return String.Format("({0}, {1}, {2})", new object[] { - this.x.ToString(), - this.y.ToString(), - this.o.ToString() + x.ToString(), + y.ToString(), + o.ToString() }); } @@ -355,9 +354,9 @@ namespace Godot { return String.Format("({0}, {1}, {2})", new object[] { - this.x.ToString(format), - this.y.ToString(format), - this.o.ToString(format) + x.ToString(format), + y.ToString(format), + o.ToString(format) }); } } diff --git a/modules/mono/glue/cs_files/Vector2.cs b/modules/mono/glue/cs_files/Vector2.cs index 6fbe374611..cc2cda82fb 100644 --- a/modules/mono/glue/cs_files/Vector2.cs +++ b/modules/mono/glue/cs_files/Vector2.cs @@ -1,13 +1,11 @@ -using System; -using System.Runtime.InteropServices; - // file: core/math/math_2d.h // commit: 7ad14e7a3e6f87ddc450f7e34621eb5200808451 // file: core/math/math_2d.cpp // commit: 7ad14e7a3e6f87ddc450f7e34621eb5200808451 // file: core/variant_call.cpp // commit: 5ad9be4c24e9d7dc5672fdc42cea896622fe5685 - +using System; +using System.Runtime.InteropServices; #if REAL_T_IS_DOUBLE using real_t = System.Double; #else @@ -101,8 +99,8 @@ namespace Godot public Vector2 Clamped(real_t length) { - Vector2 v = this; - real_t l = this.Length(); + var v = this; + real_t l = Length(); if (l > 0 && length < l) { @@ -115,15 +113,15 @@ namespace Godot public Vector2 CubicInterpolate(Vector2 b, Vector2 preA, Vector2 postB, real_t t) { - Vector2 p0 = preA; - Vector2 p1 = this; - Vector2 p2 = b; - Vector2 p3 = postB; + var p0 = preA; + var p1 = this; + var p2 = b; + var p3 = postB; real_t t2 = t * t; real_t t3 = t2 * t; - return 0.5f * ((p1 * 2.0f) + + return 0.5f * (p1 * 2.0f + (-p0 + p2) * t + (2.0f * p0 - 5.0f * p1 + 4 * p2 - p3) * t2 + (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3); @@ -166,17 +164,17 @@ namespace Godot public Vector2 LinearInterpolate(Vector2 b, real_t t) { - Vector2 res = this; + var res = this; - res.x += (t * (b.x - x)); - res.y += (t * (b.y - y)); + res.x += t * (b.x - x); + res.y += t * (b.y - y); return res; } public Vector2 Normalized() { - Vector2 result = this; + var result = this; result.Normalize(); return result; } @@ -199,8 +197,8 @@ namespace Godot } public void Set(Vector2 v) { - this.x = v.x; - this.y = v.y; + x = v.x; + y = v.y; } public Vector2 Slide(Vector2 n) @@ -244,8 +242,8 @@ namespace Godot } public Vector2(Vector2 v) { - this.x = v.x; - this.y = v.y; + x = v.x; + y = v.y; } public static Vector2 operator +(Vector2 left, Vector2 right) @@ -320,10 +318,8 @@ namespace Godot { return left.y < right.y; } - else - { - return left.x < right.x; - } + + return left.x < right.x; } public static bool operator >(Vector2 left, Vector2 right) @@ -332,10 +328,8 @@ namespace Godot { return left.y > right.y; } - else - { - return left.x > right.x; - } + + return left.x > right.x; } public static bool operator <=(Vector2 left, Vector2 right) @@ -344,10 +338,8 @@ namespace Godot { return left.y <= right.y; } - else - { - return left.x <= right.x; - } + + return left.x <= right.x; } public static bool operator >=(Vector2 left, Vector2 right) @@ -356,10 +348,8 @@ namespace Godot { return left.y >= right.y; } - else - { - return left.x >= right.x; - } + + return left.x >= right.x; } public override bool Equals(object obj) @@ -386,8 +376,8 @@ namespace Godot { return String.Format("({0}, {1})", new object[] { - this.x.ToString(), - this.y.ToString() + x.ToString(), + y.ToString() }); } @@ -395,8 +385,8 @@ namespace Godot { return String.Format("({0}, {1})", new object[] { - this.x.ToString(format), - this.y.ToString(format) + x.ToString(format), + y.ToString(format) }); } } diff --git a/modules/mono/glue/cs_files/Vector3.cs b/modules/mono/glue/cs_files/Vector3.cs index 285736d7b8..0a71f3fa4d 100644 --- a/modules/mono/glue/cs_files/Vector3.cs +++ b/modules/mono/glue/cs_files/Vector3.cs @@ -1,13 +1,11 @@ -using System; -using System.Runtime.InteropServices; - // file: core/math/vector3.h // commit: bd282ff43f23fe845f29a3e25c8efc01bd65ffb0 // file: core/math/vector3.cpp // commit: 7ad14e7a3e6f87ddc450f7e34621eb5200808451 // file: core/variant_call.cpp // commit: 5ad9be4c24e9d7dc5672fdc42cea896622fe5685 - +using System; +using System.Runtime.InteropServices; #if REAL_T_IS_DOUBLE using real_t = System.Double; #else @@ -67,7 +65,7 @@ namespace Godot internal void Normalize() { - real_t length = this.Length(); + real_t length = Length(); if (length == 0f) { @@ -105,24 +103,24 @@ namespace Godot { return new Vector3 ( - (y * b.z) - (z * b.y), - (z * b.x) - (x * b.z), - (x * b.y) - (y * b.x) + y * b.z - z * b.y, + z * b.x - x * b.z, + x * b.y - y * b.x ); } public Vector3 CubicInterpolate(Vector3 b, Vector3 preA, Vector3 postB, real_t t) { - Vector3 p0 = preA; - Vector3 p1 = this; - Vector3 p2 = b; - Vector3 p3 = postB; + var p0 = preA; + var p1 = this; + var p2 = b; + var p3 = postB; real_t t2 = t * t; real_t t3 = t2 * t; return 0.5f * ( - (p1 * 2.0f) + (-p0 + p2) * t + + p1 * 2.0f + (-p0 + p2) * t + (2.0f * p0 - 5.0f * p1 + 4f * p2 - p3) * t2 + (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3 ); @@ -180,9 +178,9 @@ namespace Godot { return new Vector3 ( - x + (t * (b.x - x)), - y + (t * (b.y - y)), - z + (t * (b.z - z)) + x + t * (b.x - x), + y + t * (b.y - y), + z + t * (b.z - z) ); } @@ -198,7 +196,7 @@ namespace Godot public Vector3 Normalized() { - Vector3 v = this; + var v = this; v.Normalize(); return v; } @@ -234,9 +232,9 @@ namespace Godot } public void Set(Vector3 v) { - this.x = v.x; - this.y = v.y; - this.z = v.z; + x = v.x; + y = v.y; + z = v.z; } public Vector3 Slide(Vector3 n) @@ -294,9 +292,9 @@ namespace Godot } public Vector3(Vector3 v) { - this.x = v.x; - this.y = v.y; - this.z = v.z; + x = v.x; + y = v.y; + z = v.z; } public static Vector3 operator +(Vector3 left, Vector3 right) @@ -379,8 +377,7 @@ namespace Godot { if (left.y == right.y) return left.z < right.z; - else - return left.y < right.y; + return left.y < right.y; } return left.x < right.x; @@ -392,8 +389,7 @@ namespace Godot { if (left.y == right.y) return left.z > right.z; - else - return left.y > right.y; + return left.y > right.y; } return left.x > right.x; @@ -405,8 +401,7 @@ namespace Godot { if (left.y == right.y) return left.z <= right.z; - else - return left.y < right.y; + return left.y < right.y; } return left.x < right.x; @@ -418,8 +413,7 @@ namespace Godot { if (left.y == right.y) return left.z >= right.z; - else - return left.y > right.y; + return left.y > right.y; } return left.x > right.x; @@ -449,9 +443,9 @@ namespace Godot { return String.Format("({0}, {1}, {2})", new object[] { - this.x.ToString(), - this.y.ToString(), - this.z.ToString() + x.ToString(), + y.ToString(), + z.ToString() }); } @@ -459,9 +453,9 @@ namespace Godot { return String.Format("({0}, {1}, {2})", new object[] { - this.x.ToString(format), - this.y.ToString(format), - this.z.ToString(format) + x.ToString(format), + y.ToString(format), + z.ToString(format) }); } } diff --git a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml index 0929b227d0..399ba8ef5d 100644 --- a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml +++ b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml @@ -80,7 +80,7 @@ Return the natural logarithm of the input. Note that this is not the typical base-10 logarithm function calculators use. </constant> <constant name="MATH_EXP" value="20" enum="BuiltinFunc"> - Return [b]e[/b] raised to the power of the input. [b]e[/b] sometimes called "Euler's number" is a mathematical constant whose value is approximately 2.71828. + Return the mathematical constant [b]e[/b] raised to the specified power of the input. [b]e[/b] has an approximate value of 2.71828. </constant> <constant name="MATH_ISNAN" value="21" enum="BuiltinFunc"> Return whether the input is NaN (Not a Number) or not. NaN is usually produced by dividing 0 by 0, though other ways exist. diff --git a/modules/visual_script/doc_classes/VisualScriptMathConstant.xml b/modules/visual_script/doc_classes/VisualScriptMathConstant.xml index df439f8794..d456e880b7 100644 --- a/modules/visual_script/doc_classes/VisualScriptMathConstant.xml +++ b/modules/visual_script/doc_classes/VisualScriptMathConstant.xml @@ -4,7 +4,7 @@ Commonly used mathematical constants. </brief_description> <description> - Provides common math constants, such as Pi or Euler's constant, on an output Data port. + Provides common math constants, such as Pi, on an output Data port. [b]Input Ports:[/b] none [b]Output Ports:[/b] @@ -35,7 +35,7 @@ Tau: [code]6.283185[/code] </constant> <constant name="MATH_CONSTANT_E" value="4" enum="MathConstant"> - Natural log: [code]2.718282[/code] + Mathematical constant [code]e[/code], the natural log base: [code]2.718282[/code] </constant> <constant name="MATH_CONSTANT_SQRT2" value="5" enum="MathConstant"> Square root of two: [code]1.414214[/code] diff --git a/platform/android/java/src/org/godotengine/godot/GodotView.java b/platform/android/java/src/org/godotengine/godot/GodotView.java index 0222758c2b..23723c2696 100644 --- a/platform/android/java/src/org/godotengine/godot/GodotView.java +++ b/platform/android/java/src/org/godotengine/godot/GodotView.java @@ -261,7 +261,7 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener { }; int source = event.getSource(); - if ((source & InputDevice.SOURCE_JOYSTICK) != 0 || (source & InputDevice.SOURCE_DPAD) != 0 || (source & InputDevice.SOURCE_GAMEPAD) != 0) { + if ((source & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK || (source & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD || (source & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) { final int button = get_godot_button(keyCode); final int device = find_joy_device(event.getDeviceId()); @@ -302,7 +302,7 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener { int source = event.getSource(); //Log.e(TAG, String.format("Key down! source %d, device %d, joystick %d, %d, %d", event.getDeviceId(), source, (source & InputDevice.SOURCE_JOYSTICK), (source & InputDevice.SOURCE_DPAD), (source & InputDevice.SOURCE_GAMEPAD))); - if ((source & InputDevice.SOURCE_JOYSTICK) != 0 || (source & InputDevice.SOURCE_DPAD) != 0 || (source & InputDevice.SOURCE_GAMEPAD) != 0) { + if ((source & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK || (source & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD || (source & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) { if (event.getRepeatCount() > 0) // ignore key echo return true; diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp index 824f50495b..447bd9a090 100644 --- a/scene/2d/animated_sprite.cpp +++ b/scene/2d/animated_sprite.cpp @@ -80,6 +80,10 @@ Rect2 AnimatedSprite::_edit_get_rect() const { return Rect2(ofs, s); } +bool AnimatedSprite::_edit_use_rect() const { + return true; +} + void SpriteFrames::add_frame(const StringName &p_anim, const Ref<Texture> &p_frame, int p_at_pos) { Map<StringName, Anim>::Element *E = animations.find(p_anim); diff --git a/scene/2d/animated_sprite.h b/scene/2d/animated_sprite.h index a38adf792c..c7606d88aa 100644 --- a/scene/2d/animated_sprite.h +++ b/scene/2d/animated_sprite.h @@ -157,6 +157,7 @@ public: virtual Point2 _edit_get_pivot() const; virtual bool _edit_use_pivot() const; virtual Rect2 _edit_get_rect() const; + virtual bool _edit_use_rect() const; void set_sprite_frames(const Ref<SpriteFrames> &p_frames); Ref<SpriteFrames> get_sprite_frames() const; diff --git a/scene/2d/back_buffer_copy.cpp b/scene/2d/back_buffer_copy.cpp index 446b367be0..caa1adebdb 100644 --- a/scene/2d/back_buffer_copy.cpp +++ b/scene/2d/back_buffer_copy.cpp @@ -55,6 +55,10 @@ Rect2 BackBufferCopy::_edit_get_rect() const { return rect; } +bool BackBufferCopy::_edit_use_rect() const { + return true; +} + void BackBufferCopy::set_rect(const Rect2 &p_rect) { rect = p_rect; diff --git a/scene/2d/back_buffer_copy.h b/scene/2d/back_buffer_copy.h index b786c2b828..752d56de2b 100644 --- a/scene/2d/back_buffer_copy.h +++ b/scene/2d/back_buffer_copy.h @@ -54,6 +54,7 @@ protected: public: Rect2 _edit_get_rect() const; + virtual bool _edit_use_rect() const; void set_rect(const Rect2 &p_rect); Rect2 get_rect() const; diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index 2b89062181..60368816a9 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -245,6 +245,14 @@ CanvasItemMaterial::~CanvasItemMaterial() { /////////////////////////////////////////////////////////////////// +bool CanvasItem::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { + if (_edit_use_rect()) { + return _edit_get_rect().has_point(p_point); + } else { + return p_point.length() < p_tolerance; + } +} + bool CanvasItem::is_visible_in_tree() const { if (!is_inside_tree()) @@ -980,7 +988,8 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("_edit_set_position", "position"), &CanvasItem::_edit_set_position); ClassDB::bind_method(D_METHOD("_edit_get_position"), &CanvasItem::_edit_get_position); - ClassDB::bind_method(D_METHOD("_edit_use_position"), &CanvasItem::_edit_use_position); + ClassDB::bind_method(D_METHOD("_edit_set_scale", "scale"), &CanvasItem::_edit_set_scale); + ClassDB::bind_method(D_METHOD("_edit_get_scale"), &CanvasItem::_edit_get_scale); ClassDB::bind_method(D_METHOD("_edit_set_rect", "rect"), &CanvasItem::_edit_set_rect); ClassDB::bind_method(D_METHOD("_edit_get_rect"), &CanvasItem::_edit_get_rect); ClassDB::bind_method(D_METHOD("_edit_use_rect"), &CanvasItem::_edit_use_rect); diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index 980fcb4109..85de0d2796 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -220,30 +220,46 @@ public: /* EDITOR */ + // Save and restore a CanvasItem state virtual void _edit_set_state(const Dictionary &p_state){}; virtual Dictionary _edit_get_state() const { return Dictionary(); }; - // Used to move/select the node - virtual void _edit_set_position(const Point2 &p_position){}; - virtual Point2 _edit_get_position() const { return Point2(); }; - virtual bool _edit_use_position() const { return false; }; + // Used to move the node + virtual void _edit_set_position(const Point2 &p_position) = 0; + virtual Point2 _edit_get_position() const = 0; - // Used to resize/move/select the node + // Used to scale the node + virtual void _edit_set_scale(const Size2 &p_scale) = 0; + virtual Size2 _edit_get_scale() const = 0; + + // Used to resize/move the node virtual void _edit_set_rect(const Rect2 &p_rect){}; - virtual Rect2 _edit_get_rect() const { return Rect2(-32, -32, 64, 64); }; - virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { return _edit_get_rect().has_point(p_point); } - Rect2 _edit_get_item_and_children_rect() const; + virtual Rect2 _edit_get_rect() const { return Rect2(0, 0, 0, 0); }; virtual bool _edit_use_rect() const { return false; }; + Rect2 _edit_get_item_and_children_rect() const; + + // used to select the node + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; + // Used to rotate the node - virtual void _edit_set_rotation(float p_rotation){}; - virtual float _edit_get_rotation() const { return 0.0; }; - virtual bool _edit_use_rotation() const { return false; }; + virtual void + _edit_set_rotation(float p_rotation){}; + virtual float _edit_get_rotation() const { + return 0.0; + }; + virtual bool _edit_use_rotation() const { + return false; + }; // Used to set a pivot virtual void _edit_set_pivot(const Point2 &p_pivot){}; - virtual Point2 _edit_get_pivot() const { return Point2(); }; - virtual bool _edit_use_pivot() const { return false; }; + virtual Point2 _edit_get_pivot() const { + return Point2(); + }; + virtual bool _edit_use_pivot() const { + return false; + }; virtual Size2 _edit_get_minimum_size() const; @@ -308,7 +324,9 @@ public: virtual Transform2D get_global_transform_with_canvas() const; CanvasItem *get_toplevel() const; - _FORCE_INLINE_ RID get_canvas_item() const { return canvas_item; } + _FORCE_INLINE_ RID get_canvas_item() const { + return canvas_item; + } void set_block_transform_notify(bool p_enable); bool is_block_transform_notify_enabled() const; diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp index 7e2026d225..9d2a83fda7 100644 --- a/scene/2d/collision_polygon_2d.cpp +++ b/scene/2d/collision_polygon_2d.cpp @@ -264,6 +264,10 @@ Rect2 CollisionPolygon2D::_edit_get_rect() const { return aabb; } +bool CollisionPolygon2D::_edit_use_rect() const { + return true; +} + bool CollisionPolygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { return Geometry::is_point_in_polygon(p_point, Variant(polygon)); diff --git a/scene/2d/collision_polygon_2d.h b/scene/2d/collision_polygon_2d.h index 4dafe7d1da..412a923292 100644 --- a/scene/2d/collision_polygon_2d.h +++ b/scene/2d/collision_polygon_2d.h @@ -73,6 +73,7 @@ public: Vector<Point2> get_polygon() const; virtual Rect2 _edit_get_rect() const; + virtual bool _edit_use_rect() const; virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; virtual String get_configuration_warning() const; diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp index 0eeb6dafe5..83ef4df8f4 100644 --- a/scene/2d/collision_shape_2d.cpp +++ b/scene/2d/collision_shape_2d.cpp @@ -173,11 +173,6 @@ Ref<Shape2D> CollisionShape2D::get_shape() const { return shape; } -Rect2 CollisionShape2D::_edit_get_rect() const { - - return rect; -} - bool CollisionShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { if (!shape.is_valid()) diff --git a/scene/2d/collision_shape_2d.h b/scene/2d/collision_shape_2d.h index cdff595828..ed2c09d53d 100644 --- a/scene/2d/collision_shape_2d.h +++ b/scene/2d/collision_shape_2d.h @@ -54,7 +54,6 @@ protected: static void _bind_methods(); public: - virtual Rect2 _edit_get_rect() const; virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; void set_shape(const Ref<Shape2D> &p_shape); diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index 1220ff299c..9a44eb31bb 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -65,6 +65,10 @@ Rect2 Light2D::_edit_get_rect() const { return Rect2(texture_offset - s / 2.0, s); } +bool Light2D::_edit_use_rect() const { + return true; +} + void Light2D::_update_light_visibility() { if (!is_inside_tree()) diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h index 16d8c485d4..543805e329 100644 --- a/scene/2d/light_2d.h +++ b/scene/2d/light_2d.h @@ -92,6 +92,7 @@ public: virtual Point2 _edit_get_pivot() const; virtual bool _edit_use_pivot() const; virtual Rect2 _edit_get_rect() const; + virtual bool _edit_use_rect() const; void set_enabled(bool p_enabled); bool is_enabled() const; diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp index ba4a5c5571..229c2c6fe8 100644 --- a/scene/2d/line_2d.cpp +++ b/scene/2d/line_2d.cpp @@ -62,6 +62,10 @@ Rect2 Line2D::_edit_get_rect() const { return aabb; } +bool Line2D::_edit_use_rect() const { + return true; +} + bool Line2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { const real_t d = _width / 2 + p_tolerance; diff --git a/scene/2d/line_2d.h b/scene/2d/line_2d.h index 0eba024555..24c48982cd 100644 --- a/scene/2d/line_2d.h +++ b/scene/2d/line_2d.h @@ -59,6 +59,7 @@ public: Line2D(); virtual Rect2 _edit_get_rect() const; + virtual bool _edit_use_rect() const; virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; void set_points(const PoolVector<Vector2> &p_points); diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index 95e24505be..2a52ade01d 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -58,16 +58,39 @@ void Node2D::_edit_set_state(const Dictionary &p_state) { } void Node2D::_edit_set_position(const Point2 &p_position) { - pos = p_position; - _update_transform(); - _change_notify("position"); + set_position(p_position); } Point2 Node2D::_edit_get_position() const { return pos; } +void Node2D::_edit_set_scale(const Size2 &p_scale) { + set_scale(p_scale); +} + +Size2 Node2D::_edit_get_scale() const { + return _scale; +} + +void Node2D::_edit_set_rotation(float p_rotation) { + angle = p_rotation; + _update_transform(); + _change_notify("rotation"); + _change_notify("rotation_degrees"); +} + +float Node2D::_edit_get_rotation() const { + return angle; +} + +bool Node2D::_edit_use_rotation() const { + return true; +} + void Node2D::_edit_set_rect(const Rect2 &p_edit_rect) { + ERR_FAIL_COND(!_edit_use_rect()); + Rect2 r = _edit_get_rect(); Vector2 zero_offset; @@ -83,7 +106,7 @@ void Node2D::_edit_set_rect(const Rect2 &p_edit_rect) { if (r.size.y != 0) new_scale.y = p_edit_rect.size.y / r.size.y; - Point2 new_pos = p_edit_rect.position + p_edit_rect.size * zero_offset; //p_edit_rect.pos - r.pos; + Point2 new_pos = p_edit_rect.position + p_edit_rect.size * zero_offset; Transform2D postxf; postxf.set_rotation_and_scale(angle, _scale); @@ -97,25 +120,6 @@ void Node2D::_edit_set_rect(const Rect2 &p_edit_rect) { _change_notify("position"); } -bool Node2D::_edit_use_rect() const { - return true; -} - -void Node2D::_edit_set_rotation(float p_rotation) { - angle = p_rotation; - _update_transform(); - _change_notify("rotation"); - _change_notify("rotation_degrees"); -} - -float Node2D::_edit_get_rotation() const { - return angle; -} - -bool Node2D::_edit_use_rotation() const { - return true; -} - void Node2D::_update_xform_values() { pos = _mat.elements[2]; diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h index f817b214f8..725686cdf8 100644 --- a/scene/2d/node_2d.h +++ b/scene/2d/node_2d.h @@ -62,12 +62,16 @@ public: virtual void _edit_set_position(const Point2 &p_position); virtual Point2 _edit_get_position() const; - virtual void _edit_set_rect(const Rect2 &p_edit_rect); - virtual bool _edit_use_rect() const; + + virtual void _edit_set_scale(const Size2 &p_scale); + virtual Size2 _edit_get_scale() const; + virtual void _edit_set_rotation(float p_rotation); virtual float _edit_get_rotation() const; virtual bool _edit_use_rotation() const; + virtual void _edit_set_rect(const Rect2 &p_edit_rect); + void set_position(const Point2 &p_pos); void set_rotation(float p_radians); void set_rotation_degrees(float p_degrees); diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp index 052a0ac026..7377591f7d 100644 --- a/scene/2d/path_2d.cpp +++ b/scene/2d/path_2d.cpp @@ -57,6 +57,10 @@ Rect2 Path2D::_edit_get_rect() const { return aabb; } +bool Path2D::_edit_use_rect() const { + return true; +} + bool Path2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { for (int i = 0; i < curve->get_point_count(); i++) { @@ -92,7 +96,7 @@ void Path2D::_notification(int p_what) { #else const float line_width = 2; #endif - const Color color = Color(0.5, 0.6, 1.0, 0.7); + const Color color = Color(1.0, 1.0, 1.0, 1.0); for (int i = 0; i < curve->get_point_count(); i++) { @@ -147,6 +151,7 @@ void Path2D::_bind_methods() { Path2D::Path2D() { set_curve(Ref<Curve2D>(memnew(Curve2D))); //create one by default + set_self_modulate(Color(0.5, 0.6, 1.0, 0.7)); } ///////////////////////////////////////////////////////////////////////////////// diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h index 735d289d74..64696442c3 100644 --- a/scene/2d/path_2d.h +++ b/scene/2d/path_2d.h @@ -48,6 +48,7 @@ protected: public: virtual Rect2 _edit_get_rect() const; + virtual bool _edit_use_rect() const; virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; void set_curve(const Ref<Curve2D> &p_curve); diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp index 2cb1e86f51..bf5bf29b2e 100644 --- a/scene/2d/polygon_2d.cpp +++ b/scene/2d/polygon_2d.cpp @@ -73,6 +73,10 @@ Rect2 Polygon2D::_edit_get_rect() const { return item_rect; } +bool Polygon2D::_edit_use_rect() const { + return true; +} + bool Polygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { return Geometry::is_point_in_polygon(p_point - get_offset(), Variant(polygon)); diff --git a/scene/2d/polygon_2d.h b/scene/2d/polygon_2d.h index 3a24177548..262208f2f1 100644 --- a/scene/2d/polygon_2d.h +++ b/scene/2d/polygon_2d.h @@ -68,6 +68,7 @@ public: virtual Point2 _edit_get_pivot() const; virtual bool _edit_use_pivot() const; virtual Rect2 _edit_get_rect() const; + virtual bool _edit_use_rect() const; virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; diff --git a/scene/2d/position_2d.cpp b/scene/2d/position_2d.cpp index 37f6aaa2d6..64d23719e7 100644 --- a/scene/2d/position_2d.cpp +++ b/scene/2d/position_2d.cpp @@ -44,6 +44,10 @@ Rect2 Position2D::_edit_get_rect() const { return Rect2(Point2(-10, -10), Size2(20, 20)); } +bool Position2D::_edit_use_rect() const { + return false; +} + void Position2D::_notification(int p_what) { switch (p_what) { diff --git a/scene/2d/position_2d.h b/scene/2d/position_2d.h index 6f6a34c452..bff474cccd 100644 --- a/scene/2d/position_2d.h +++ b/scene/2d/position_2d.h @@ -44,6 +44,7 @@ protected: public: virtual Rect2 _edit_get_rect() const; + virtual bool _edit_use_rect() const; Position2D(); }; diff --git a/scene/2d/screen_button.cpp b/scene/2d/screen_button.cpp index b6cb734cee..9480f18176 100644 --- a/scene/2d/screen_button.cpp +++ b/scene/2d/screen_button.cpp @@ -335,6 +335,10 @@ Rect2 TouchScreenButton::_edit_get_rect() const { return Rect2(Size2(), texture->get_size()); } +bool TouchScreenButton::_edit_use_rect() const { + return true; +} + void TouchScreenButton::set_visibility_mode(VisibilityMode p_mode) { visibility = p_mode; update(); diff --git a/scene/2d/screen_button.h b/scene/2d/screen_button.h index e6f2a2f3cd..b2fafcc93d 100644 --- a/scene/2d/screen_button.h +++ b/scene/2d/screen_button.h @@ -104,6 +104,7 @@ public: bool is_pressed() const; Rect2 _edit_get_rect() const; + virtual bool _edit_use_rect() const; TouchScreenButton(); }; diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp index 67f016ae79..bc39368c88 100644 --- a/scene/2d/sprite.cpp +++ b/scene/2d/sprite.cpp @@ -58,6 +58,14 @@ bool Sprite::_edit_use_pivot() const { return true; } +Rect2 Sprite::_edit_get_rect() const { + return get_rect(); +} + +bool Sprite::_edit_use_rect() const { + return true; +} + void Sprite::_get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip) const { Size2 s; @@ -323,7 +331,31 @@ bool Sprite::_edit_is_selected_on_click(const Point2 &p_point, double p_toleranc } ERR_FAIL_COND_V(image.is_null(), false); + if (image->is_compressed()) { + return dst_rect.has_point(p_point); + } + bool is_repeat = texture->get_flags() & Texture::FLAG_REPEAT; + bool is_mirrored_repeat = texture->get_flags() & Texture::FLAG_MIRRORED_REPEAT; + if (is_repeat) { + int mirror_x = 0; + int mirror_y = 0; + if (is_mirrored_repeat) { + mirror_x = (int)(q.x / texture->get_size().width); + mirror_y = (int)(q.y / texture->get_size().height); + } + q.x = Math::fmod(q.x, texture->get_size().width); + q.y = Math::fmod(q.y, texture->get_size().height); + if (mirror_x % 2 == 1) { + q.x = texture->get_size().width - q.x - 1; + } + if (mirror_y % 2 == 1) { + q.y = texture->get_size().height - q.y - 1; + } + } else { + q.x = MIN(q.x, texture->get_size().width - 1); + q.y = MIN(q.y, texture->get_size().height - 1); + } image->lock(); const Color c = image->get_pixel((int)q.x, (int)q.y); image->unlock(); diff --git a/scene/2d/sprite.h b/scene/2d/sprite.h index abd04515ec..609ad8bb34 100644 --- a/scene/2d/sprite.h +++ b/scene/2d/sprite.h @@ -74,7 +74,9 @@ public: virtual Point2 _edit_get_pivot() const; virtual bool _edit_use_pivot() const; virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; - virtual Rect2 _edit_get_rect() const { return get_rect(); } + + virtual Rect2 _edit_get_rect() const; + virtual bool _edit_use_rect() const; void set_texture(const Ref<Texture> &p_texture); Ref<Texture> get_texture() const; diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index c126dd8f6b..14eb26b1ec 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -1119,6 +1119,10 @@ Rect2 TileMap::_edit_get_rect() const { return rect_cache; } +bool TileMap::_edit_use_rect() const { + return true; +} + void TileMap::set_collision_layer(uint32_t p_layer) { collision_layer = p_layer; diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index 587bd3b684..07947004b3 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -245,6 +245,7 @@ public: int get_cellv(const Vector2 &p_pos) const; Rect2 _edit_get_rect() const; + virtual bool _edit_use_rect() const; void make_bitmask_area_dirty(const Vector2 &p_pos); void update_bitmask_area(const Vector2 &p_pos); diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp index 4b38534d97..ddca97e60a 100644 --- a/scene/2d/visibility_notifier_2d.cpp +++ b/scene/2d/visibility_notifier_2d.cpp @@ -89,6 +89,10 @@ Rect2 VisibilityNotifier2D::_edit_get_rect() const { return rect; } +bool VisibilityNotifier2D::_edit_use_rect() const { + return true; +} + Rect2 VisibilityNotifier2D::get_rect() const { return rect; diff --git a/scene/2d/visibility_notifier_2d.h b/scene/2d/visibility_notifier_2d.h index 93a35a709e..c4e12dfa22 100644 --- a/scene/2d/visibility_notifier_2d.h +++ b/scene/2d/visibility_notifier_2d.h @@ -56,6 +56,7 @@ protected: public: virtual Rect2 _edit_get_rect() const; + virtual bool _edit_use_rect() const; void set_rect(const Rect2 &p_rect); Rect2 get_rect() const; diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp index f8a5c7f400..dab0e573d7 100644 --- a/scene/3d/spatial.cpp +++ b/scene/3d/spatial.cpp @@ -85,9 +85,7 @@ void Spatial::_notify_dirty() { } void Spatial::_update_local_transform() const { - data.local_transform.basis = Basis(); - data.local_transform.basis.scale(data.scale); - data.local_transform.basis.rotate(data.rotation); + data.local_transform.basis.set_euler_scale(data.rotation, data.scale); data.dirty &= ~DIRTY_LOCAL; } diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 63580bcae6..eca7caeaf0 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -590,9 +590,7 @@ void AnimationPlayer::_animation_update_transforms() { Transform t; t.origin = nc->loc_accum; - t.basis.scale(nc->scale_accum); - t.basis.rotate(nc->rot_accum.get_euler()); - + t.basis.set_quat_scale(nc->rot_accum, nc->scale_accum); if (nc->skeleton && nc->bone_idx >= 0) { nc->skeleton->set_bone_pose(nc->bone_idx, t); diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp index e811b7a7b3..42fa20068b 100644 --- a/scene/animation/animation_tree_player.cpp +++ b/scene/animation/animation_tree_player.cpp @@ -900,8 +900,7 @@ void AnimationTreePlayer::_process_animation(float p_delta) { t.scale.x += 1.0; t.scale.y += 1.0; t.scale.z += 1.0; - xform.basis.scale(t.scale); - xform.basis.rotate(t.rot.get_euler()); + xform.basis.set_quat_scale(t.rot, t.scale); if (t.bone_idx >= 0) { if (t.skeleton) diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 6ca6d82807..b7c1d35fd7 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -94,6 +94,14 @@ Point2 Control::_edit_get_position() const { return get_position(); }; +void Control::_edit_set_scale(const Size2 &p_scale) { + set_scale(p_scale); +} + +Size2 Control::_edit_get_scale() const { + return data.scale; +} + void Control::_edit_set_rect(const Rect2 &p_edit_rect) { set_position((get_position() + get_transform().basis_xform(p_edit_rect.position)).snapped(Vector2(1, 1))); set_size(p_edit_rect.size.snapped(Vector2(1, 1))); diff --git a/scene/gui/control.h b/scene/gui/control.h index a215490295..b5453e60f5 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -283,6 +283,9 @@ public: virtual void _edit_set_position(const Point2 &p_position); virtual Point2 _edit_get_position() const; + virtual void _edit_set_scale(const Size2 &p_scale); + virtual Size2 _edit_get_scale() const; + virtual void _edit_set_rect(const Rect2 &p_edit_rect); virtual Rect2 _edit_get_rect() const; virtual bool _edit_use_rect() const; diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index ecd98f054d..511dc248a0 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -678,7 +678,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) { search_string = ""; //any mousepress cancels - if (current % current_columns != (current_columns - 1)) { + if (current % current_columns != (current_columns - 1) && current + 1 < items.size()) { set_current(current + 1); ensure_current_is_visible(); if (select_mode == SELECT_SINGLE) { diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 37aeef8999..7aca497881 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -3008,7 +3008,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } if (next_op + 2 >= expression.size() || !expression[next_op + 2].is_op || expression[next_op + 2].op != OP_SELECT_ELSE) { - _set_error("Mising matching ':' for select operator"); + _set_error("Missing matching ':' for select operator"); return NULL; } @@ -3213,7 +3213,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui precision = get_token_precision(tk.type); tk = _get_token(); if (!is_token_nonvoid_datatype(tk.type)) { - _set_error("Expected datatype after precission"); + _set_error("Expected datatype after precision"); return ERR_PARSE_ERROR; } } @@ -3511,7 +3511,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui if (!p_can_break) { //all is good - _set_error("Contiuning is not allowed here"); + _set_error("Continuing is not allowed here"); } ControlFlowNode *flow = alloc_node<ControlFlowNode>(); diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp index 2ab52d13b8..a4053ad415 100644 --- a/servers/visual/shader_types.cpp +++ b/servers/visual/shader_types.cpp @@ -207,7 +207,7 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].can_discard = true; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["POSITION"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4); shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["NORMAL"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["COLOR"] = constt(ShaderLanguage::TYPE_VEC4); |