diff --git a/core/math/color.cpp b/core/math/color.cpp index 64abd6dd088e..52f029ef4b79 100644 --- a/core/math/color.cpp +++ b/core/math/color.cpp @@ -211,6 +211,14 @@ bool Color::is_equal_approx(const Color &p_color) const { return Math::is_equal_approx(r, p_color.r) && Math::is_equal_approx(g, p_color.g) && Math::is_equal_approx(b, p_color.b) && Math::is_equal_approx(a, p_color.a); } +Color Color::clamp(const Color &p_min, const Color &p_max) const { + return Color( + CLAMP(r, p_min.r, p_max.r), + CLAMP(g, p_min.g, p_max.g), + CLAMP(b, p_min.b, p_max.b), + CLAMP(a, p_min.a, p_max.a)); +} + void Color::invert() { r = 1.0 - r; g = 1.0 - g; diff --git a/core/math/color.h b/core/math/color.h index e404d80c8a00..a95dbf4f6003 100644 --- a/core/math/color.h +++ b/core/math/color.h @@ -89,6 +89,7 @@ struct Color { bool is_equal_approx(const Color &p_color) const; + Color clamp(const Color &p_min = Color(0, 0, 0, 0), const Color &p_max = Color(1, 1, 1, 1)) const; void invert(); Color inverted() const; diff --git a/core/math/vector2.cpp b/core/math/vector2.cpp index 46a08b53ab9c..ea430b15c448 100644 --- a/core/math/vector2.cpp +++ b/core/math/vector2.cpp @@ -122,14 +122,20 @@ Vector2 Vector2::project(const Vector2 &p_to) const { return p_to * (dot(p_to) / p_to.length_squared()); } +Vector2 Vector2::clamp(const Vector2 &p_min, const Vector2 &p_max) const { + return Vector2( + CLAMP(x, p_min.x, p_max.x), + CLAMP(y, p_min.y, p_max.y)); +} + Vector2 Vector2::snapped(const Vector2 &p_step) const { return Vector2( Math::snapped(x, p_step.x), Math::snapped(y, p_step.y)); } -Vector2 Vector2::clamped(real_t p_len) const { - real_t l = length(); +Vector2 Vector2::limit_length(const real_t p_len) const { + const real_t l = length(); Vector2 v = *this; if (l > 0 && p_len < l) { v /= l; @@ -189,6 +195,12 @@ bool Vector2::is_equal_approx(const Vector2 &p_v) const { /* Vector2i */ +Vector2i Vector2i::clamp(const Vector2i &p_min, const Vector2i &p_max) const { + return Vector2i( + CLAMP(x, p_min.x, p_max.x), + CLAMP(y, p_min.y, p_max.y)); +} + Vector2i Vector2i::operator+(const Vector2i &p_v) const { return Vector2i(x + p_v.x, y + p_v.y); } diff --git a/core/math/vector2.h b/core/math/vector2.h index 6abe0f5ea99d..b0d2049f55a2 100644 --- a/core/math/vector2.h +++ b/core/math/vector2.h @@ -84,6 +84,7 @@ struct Vector2 { real_t length() const; real_t length_squared() const; + Vector2 limit_length(const real_t p_len = 1.0) const; Vector2 min(const Vector2 &p_vector2) const { return Vector2(MIN(x, p_vector2.x), MIN(y, p_vector2.y)); @@ -107,8 +108,6 @@ struct Vector2 { Vector2 plane_project(real_t p_d, const Vector2 &p_vec) const; - Vector2 clamped(real_t p_len) const; - _FORCE_INLINE_ Vector2 lerp(const Vector2 &p_to, real_t p_weight) const; _FORCE_INLINE_ Vector2 slerp(const Vector2 &p_to, real_t p_weight) const; Vector2 cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_weight) const; @@ -163,6 +162,7 @@ struct Vector2 { Vector2 ceil() const; Vector2 round() const; Vector2 snapped(const Vector2 &p_by) const; + Vector2 clamp(const Vector2 &p_min, const Vector2 &p_max) const; real_t aspect() const { return width / height; } operator String() const { return String::num(x) + ", " + String::num(y); } @@ -338,6 +338,7 @@ struct Vector2i { real_t aspect() const { return width / (real_t)height; } Vector2i sign() const { return Vector2i(SGN(x), SGN(y)); } Vector2i abs() const { return Vector2i(ABS(x), ABS(y)); } + Vector2i clamp(const Vector2i &p_min, const Vector2i &p_max) const; operator String() const { return String::num(x) + ", " + String::num(y); } diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp index d4317d506c66..d5ca98524426 100644 --- a/core/math/vector3.cpp +++ b/core/math/vector3.cpp @@ -52,6 +52,13 @@ real_t Vector3::get_axis(int p_axis) const { return operator[](p_axis); } +Vector3 Vector3::clamp(const Vector3 &p_min, const Vector3 &p_max) const { + return Vector3( + CLAMP(x, p_min.x, p_max.x), + CLAMP(y, p_min.y, p_max.y), + CLAMP(z, p_min.z, p_max.z)); +} + void Vector3::snap(Vector3 p_step) { x = Math::snapped(x, p_step.x); y = Math::snapped(y, p_step.y); @@ -64,6 +71,17 @@ Vector3 Vector3::snapped(Vector3 p_step) const { return v; } +Vector3 Vector3::limit_length(const real_t p_len) const { + const real_t l = length(); + Vector3 v = *this; + if (l > 0 && p_len < l) { + v /= l; + v *= p_len; + } + + return v; +} + Vector3 Vector3::cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_weight) const { Vector3 p0 = p_pre_a; Vector3 p1 = *this; diff --git a/core/math/vector3.h b/core/math/vector3.h index adfc52566f19..d8d3cd3cc07c 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -86,6 +86,7 @@ struct Vector3 { _FORCE_INLINE_ Vector3 normalized() const; _FORCE_INLINE_ bool is_normalized() const; _FORCE_INLINE_ Vector3 inverse() const; + Vector3 limit_length(const real_t p_len = 1.0) const; _FORCE_INLINE_ void zero(); @@ -112,6 +113,7 @@ struct Vector3 { _FORCE_INLINE_ Vector3 sign() const; _FORCE_INLINE_ Vector3 ceil() const; _FORCE_INLINE_ Vector3 round() const; + Vector3 clamp(const Vector3 &p_min, const Vector3 &p_max) const; _FORCE_INLINE_ real_t distance_to(const Vector3 &p_to) const; _FORCE_INLINE_ real_t distance_squared_to(const Vector3 &p_to) const; diff --git a/core/math/vector3i.cpp b/core/math/vector3i.cpp index 167fa3221d44..a82db7f7fc66 100644 --- a/core/math/vector3i.cpp +++ b/core/math/vector3i.cpp @@ -48,6 +48,13 @@ int Vector3i::max_axis() const { return x < y ? (y < z ? 2 : 1) : (x < z ? 2 : 0); } +Vector3i Vector3i::clamp(const Vector3i &p_min, const Vector3i &p_max) const { + return Vector3i( + CLAMP(x, p_min.x, p_max.x), + CLAMP(y, p_min.y, p_max.y), + CLAMP(z, p_min.z, p_max.z)); +} + Vector3i::operator String() const { return (itos(x) + ", " + itos(y) + ", " + itos(z)); } diff --git a/core/math/vector3i.h b/core/math/vector3i.h index b0411fb62e8e..37c7c1c368aa 100644 --- a/core/math/vector3i.h +++ b/core/math/vector3i.h @@ -69,6 +69,7 @@ struct Vector3i { _FORCE_INLINE_ Vector3i abs() const; _FORCE_INLINE_ Vector3i sign() const; + Vector3i clamp(const Vector3i &p_min, const Vector3i &p_max) const; /* Operators */ diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 063611d415ed..d9cc97154de4 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -1419,6 +1419,7 @@ static void _register_variant_builtin_methods() { bind_method(Vector2, distance_squared_to, sarray("to"), varray()); bind_method(Vector2, length, sarray(), varray()); bind_method(Vector2, length_squared, sarray(), varray()); + bind_method(Vector2, limit_length, sarray("length"), varray(1.0)); bind_method(Vector2, normalized, sarray(), varray()); bind_method(Vector2, is_normalized, sarray(), varray()); bind_method(Vector2, is_equal_approx, sarray("to"), varray()); @@ -1442,14 +1443,15 @@ static void _register_variant_builtin_methods() { bind_method(Vector2, cross, sarray("with"), varray()); bind_method(Vector2, abs, sarray(), varray()); bind_method(Vector2, sign, sarray(), varray()); + bind_method(Vector2, clamp, sarray("min", "max"), varray()); bind_method(Vector2, snapped, sarray("step"), varray()); - bind_method(Vector2, clamped, sarray("length"), varray()); /* Vector2i */ bind_method(Vector2i, aspect, sarray(), varray()); bind_method(Vector2i, sign, sarray(), varray()); bind_method(Vector2i, abs, sarray(), varray()); + bind_method(Vector2i, clamp, sarray("min", "max"), varray()); /* Rect2 */ @@ -1493,10 +1495,12 @@ static void _register_variant_builtin_methods() { bind_method(Vector3, distance_squared_to, sarray("b"), varray()); bind_method(Vector3, length, sarray(), varray()); bind_method(Vector3, length_squared, sarray(), varray()); + bind_method(Vector3, limit_length, sarray("length"), varray(1.0)); bind_method(Vector3, normalized, sarray(), varray()); bind_method(Vector3, is_normalized, sarray(), varray()); bind_method(Vector3, is_equal_approx, sarray("to"), varray()); bind_method(Vector3, inverse, sarray(), varray()); + bind_method(Vector3, clamp, sarray("min", "max"), varray()); bind_method(Vector3, snapped, sarray("step"), varray()); bind_method(Vector3, rotated, sarray("by_axis", "phi"), varray()); bind_method(Vector3, lerp, sarray("to", "weight"), varray()); @@ -1525,6 +1529,7 @@ static void _register_variant_builtin_methods() { bind_method(Vector3i, max_axis, sarray(), varray()); bind_method(Vector3i, sign, sarray(), varray()); bind_method(Vector3i, abs, sarray(), varray()); + bind_method(Vector3i, clamp, sarray("min", "max"), varray()); /* Plane */ @@ -1562,6 +1567,7 @@ static void _register_variant_builtin_methods() { bind_method(Color, to_abgr64, sarray(), varray()); bind_method(Color, to_rgba64, sarray(), varray()); + bind_method(Color, clamp, sarray("min", "max"), varray(Color(0, 0, 0, 0), Color(1, 1, 1, 1))); bind_method(Color, inverted, sarray(), varray()); bind_method(Color, lerp, sarray("to", "weight"), varray()); bind_method(Color, lightened, sarray("amount"), varray()); diff --git a/doc/classes/Color.xml b/doc/classes/Color.xml index 6133bb8d8c0a..ddff92e6fc0a 100644 --- a/doc/classes/Color.xml +++ b/doc/classes/Color.xml @@ -136,6 +136,17 @@ [/codeblocks] + + + + + + + + + Returns a new color with all components clamped between the components of [code]min[/code] and [code]max[/code], by running [method @GlobalScope.clamp] on each component. + + diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml index 94d4b1a90343..1390a5e45b90 100644 --- a/doc/classes/Vector2.xml +++ b/doc/classes/Vector2.xml @@ -110,13 +110,15 @@ Returns the vector with all components rounded up (towards positive infinity). - + - + + + - Returns the vector with a maximum length by limiting its length to [code]length[/code]. + Returns a new vector with all components clamped between the components of [code]min[/code] and [code]max[/code], by running [method @GlobalScope.clamp] on each component. @@ -232,6 +234,15 @@ Returns the result of the linear interpolation between this vector and [code]to[/code] by amount [code]weight[/code]. [code]weight[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation. + + + + + + + Returns the vector with a maximum length by limiting its length to [code]length[/code]. + + diff --git a/doc/classes/Vector2i.xml b/doc/classes/Vector2i.xml index b38b968ba338..6efb52b7123d 100644 --- a/doc/classes/Vector2i.xml +++ b/doc/classes/Vector2i.xml @@ -64,6 +64,17 @@ Returns the ratio of [member x] to [member y]. + + + + + + + + + Returns a new vector with all components clamped between the components of [code]min[/code] and [code]max[/code], by running [method @GlobalScope.clamp] on each component. + + diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml index 0a86369506e7..170bd78067b0 100644 --- a/doc/classes/Vector3.xml +++ b/doc/classes/Vector3.xml @@ -87,6 +87,17 @@ Returns a new vector with all components rounded up (towards positive infinity). + + + + + + + + + Returns a new vector with all components clamped between the components of [code]min[/code] and [code]max[/code], by running [method @GlobalScope.clamp] on each component. + + @@ -207,6 +218,15 @@ Returns the result of the linear interpolation between this vector and [code]to[/code] by amount [code]weight[/code]. [code]weight[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation. + + + + + + + Returns the vector with a maximum length by limiting its length to [code]length[/code]. + + diff --git a/doc/classes/Vector3i.xml b/doc/classes/Vector3i.xml index ea5945f5b739..6e8a34b692fa 100644 --- a/doc/classes/Vector3i.xml +++ b/doc/classes/Vector3i.xml @@ -58,6 +58,17 @@ + + + + + + + + + Returns a new vector with all components clamped between the components of [code]min[/code] and [code]max[/code], by running [method @GlobalScope.clamp] on each component. + + diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs index 2a9f834aac31..24b921819701 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs @@ -256,6 +256,27 @@ public Color Blend(Color over) return res; } + /// + /// Returns a new color with all components clamped between the + /// components of `min` and `max` using + /// . + /// + /// The color with minimum allowed values. + /// The color with maximum allowed values. + /// The color with all components clamped. + public Color Clamp(Color? min = null, Color? max = null) + { + Color minimum = min ?? new Color(0, 0, 0, 0); + Color maximum = max ?? new Color(1, 1, 1, 1); + return new Color + ( + (float)Mathf.Clamp(r, minimum.r, maximum.r), + (float)Mathf.Clamp(g, minimum.g, maximum.g), + (float)Mathf.Clamp(b, minimum.b, maximum.b), + (float)Mathf.Clamp(a, minimum.a, maximum.a) + ); + } + /// /// Returns a new color resulting from making this color darker /// by the specified ratio (on the range of 0 to 1). diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs index ebfe70aa8205..334c7cd510d4 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs @@ -160,22 +160,20 @@ public Vector2 Ceil() } /// - /// Returns the vector with a maximum length by limiting its length to `length`. + /// Returns a new vector with all components clamped between the + /// components of `min` and `max` using + /// . /// - /// The length to limit to. - /// The vector with its length limited. - public Vector2 Clamped(real_t length) + /// The vector with minimum allowed values. + /// The vector with maximum allowed values. + /// The vector with all components clamped. + public Vector2 Clamp(Vector2 min, Vector2 max) { - var v = this; - real_t l = Length(); - - if (l > 0 && length < l) - { - v /= l; - v *= length; - } - - return v; + return new Vector2 + ( + Mathf.Clamp(x, min.x, max.x), + Mathf.Clamp(y, min.y, max.y) + ); } /// @@ -334,6 +332,25 @@ public Vector2 Lerp(Vector2 to, Vector2 weight) ); } + /// + /// Returns the vector with a maximum length by limiting its length to `length`. + /// + /// The length to limit to. + /// The vector with its length limited. + public Vector2 LimitLength(real_t length = 1.0f) + { + Vector2 v = this; + real_t l = Length(); + + if (l > 0 && length < l) + { + v /= l; + v *= length; + } + + return v; + } + /// /// Returns the axis of the vector's largest value. See . /// If both components are equal, this method returns . diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs index f605ba8fd080..9068593fd8f7 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs @@ -119,6 +119,23 @@ public real_t Aspect() return x / (real_t)y; } + /// + /// Returns a new vector with all components clamped between the + /// components of `min` and `max` using + /// . + /// + /// The vector with minimum allowed values. + /// The vector with maximum allowed values. + /// The vector with all components clamped. + public Vector2i Clamp(Vector2i min, Vector2i max) + { + return new Vector2i + ( + Mathf.Clamp(x, min.x, max.x), + Mathf.Clamp(y, min.y, max.y) + ); + } + /// /// Returns the cross product of this vector and `b`. /// diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs index 3b895bbbf664..fe1b3ad3c0f1 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs @@ -139,6 +139,24 @@ public Vector3 Ceil() return new Vector3(Mathf.Ceil(x), Mathf.Ceil(y), Mathf.Ceil(z)); } + /// + /// Returns a new vector with all components clamped between the + /// components of `min` and `max` using + /// . + /// + /// The vector with minimum allowed values. + /// The vector with maximum allowed values. + /// The vector with all components clamped. + public Vector3 Clamp(Vector3 min, Vector3 max) + { + return new Vector3 + ( + Mathf.Clamp(x, min.x, max.x), + Mathf.Clamp(y, min.y, max.y), + Mathf.Clamp(z, min.z, max.z) + ); + } + /// /// Returns the cross product of this vector and `b`. /// @@ -312,6 +330,25 @@ public Vector3 Lerp(Vector3 to, Vector3 weight) ); } + /// + /// Returns the vector with a maximum length by limiting its length to `length`. + /// + /// The length to limit to. + /// The vector with its length limited. + public Vector3 LimitLength(real_t length = 1.0f) + { + Vector3 v = this; + real_t l = Length(); + + if (l > 0 && length < l) + { + v /= l; + v *= length; + } + + return v; + } + /// /// Returns the axis of the vector's largest value. See . /// If all components are equal, this method returns . diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs index bf25ba9cb39a..e727afa3ff4a 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs @@ -88,6 +88,24 @@ public Vector3i Abs() return new Vector3i(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z)); } + /// + /// Returns a new vector with all components clamped between the + /// components of `min` and `max` using + /// . + /// + /// The vector with minimum allowed values. + /// The vector with maximum allowed values. + /// The vector with all components clamped. + public Vector3i Clamp(Vector3i min, Vector3i max) + { + return new Vector3i + ( + Mathf.Clamp(x, min.x, max.x), + Mathf.Clamp(y, min.y, max.y), + Mathf.Clamp(z, min.z, max.z) + ); + } + /// /// Returns the squared distance between this vector and `b`. /// This method runs faster than , so prefer it if diff --git a/servers/physics_2d/joints_2d_sw.cpp b/servers/physics_2d/joints_2d_sw.cpp index eaec582f9ba3..5a0a628fbc5a 100644 --- a/servers/physics_2d/joints_2d_sw.cpp +++ b/servers/physics_2d/joints_2d_sw.cpp @@ -322,7 +322,7 @@ bool GrooveJoint2DSW::setup(real_t p_step) { Vector2 delta = (B->get_transform().get_origin() + rB) - (A->get_transform().get_origin() + rA); real_t _b = get_bias(); - gbias = (delta * -(_b == 0 ? space->get_constraint_bias() : _b) * (1.0 / p_step)).clamped(get_max_bias()); + gbias = (delta * -(_b == 0 ? space->get_constraint_bias() : _b) * (1.0 / p_step)).limit_length(get_max_bias()); correct = true; return true; @@ -348,7 +348,7 @@ void GrooveJoint2DSW::solve(real_t p_step) { Vector2 jOld = jn_acc; j += jOld; - jn_acc = (((clamp * j.cross(xf_normal)) > 0) ? j : j.project(xf_normal)).clamped(jn_max); + jn_acc = (((clamp * j.cross(xf_normal)) > 0) ? j : j.project(xf_normal)).limit_length(jn_max); j = jn_acc - jOld;