Backported some improvements to Rect2 from Godot4. Also bound all eligible methods.

This commit is contained in:
Relintai 2022-08-14 13:15:22 +02:00
parent 7650103ce7
commit 899ac5cbd8
9 changed files with 168 additions and 13 deletions

View File

@ -118,6 +118,11 @@ void register_global_constants() {
BIND_GLOBAL_ENUM_CONSTANT(MARGIN_RIGHT);
BIND_GLOBAL_ENUM_CONSTANT(MARGIN_BOTTOM);
BIND_GLOBAL_ENUM_CONSTANT(SIDE_LEFT);
BIND_GLOBAL_ENUM_CONSTANT(SIDE_TOP);
BIND_GLOBAL_ENUM_CONSTANT(SIDE_RIGHT);
BIND_GLOBAL_ENUM_CONSTANT(SIDE_BOTTOM);
BIND_GLOBAL_ENUM_CONSTANT(CORNER_TOP_LEFT);
BIND_GLOBAL_ENUM_CONSTANT(CORNER_TOP_RIGHT);
BIND_GLOBAL_ENUM_CONSTANT(CORNER_BOTTOM_RIGHT);

View File

@ -92,6 +92,13 @@ enum Margin {
MARGIN_BOTTOM
};
enum Side {
SIDE_LEFT,
SIDE_TOP,
SIDE_RIGHT,
SIDE_BOTTOM
};
enum Corner {
CORNER_TOP_LEFT,

View File

@ -30,6 +30,8 @@
#include "core/math/transform_2d.h" // Includes rect2.h but Rect2 needs Transform2D
#include "core/math/rect2i.h"
bool Rect2::is_equal_approx(const Rect2 &p_rect) const {
return position.is_equal_approx(p_rect.position) && size.is_equal_approx(p_rect.size);
}
@ -263,3 +265,7 @@ next4:
return true;
}
Rect2::operator String() const {
return "[P: " + position.operator String() + ", S: " + size + "]";
}

View File

@ -35,6 +35,7 @@
#include "core/math/vector2i.h"
struct Transform2D;
struct Rect2i;
struct _NO_DISCARD_CLASS_ Rect2 {
Point2 position;
@ -146,6 +147,25 @@ struct _NO_DISCARD_CLASS_ Rect2 {
return new_rect;
}
inline Rect2 intersection(const Rect2 &p_rect) const {
Rect2 new_rect = p_rect;
if (!intersects(new_rect)) {
return Rect2();
}
new_rect.position.x = MAX(p_rect.position.x, position.x);
new_rect.position.y = MAX(p_rect.position.y, position.y);
Point2 p_rect_end = p_rect.position + p_rect.size;
Point2 end = position + size;
new_rect.size.x = MIN(p_rect_end.x, end.x) - new_rect.position.x;
new_rect.size.y = MIN(p_rect_end.y, end.y) - new_rect.position.y;
return new_rect;
}
inline Rect2 merge(const Rect2 &p_rect) const { ///< return a merged rect
Rect2 new_rect;
@ -204,6 +224,15 @@ struct _NO_DISCARD_CLASS_ Rect2 {
return g;
}
inline Rect2 grow_side(Side p_side, real_t p_amount) const {
Rect2 g = *this;
g = g.grow_individual((SIDE_LEFT == p_side) ? p_amount : 0,
(SIDE_TOP == p_side) ? p_amount : 0,
(SIDE_RIGHT == p_side) ? p_amount : 0,
(SIDE_BOTTOM == p_side) ? p_amount : 0);
return g;
}
inline Rect2 grow_individual(real_t p_left, real_t p_top, real_t p_right, real_t p_bottom) const {
Rect2 g = *this;
g.position.x -= p_left;
@ -247,7 +276,78 @@ struct _NO_DISCARD_CLASS_ Rect2 {
return Rect2(Point2(position.x + MIN(size.x, 0), position.y + MIN(size.y, 0)), size.abs());
}
operator String() const { return String(position) + ", " + String(size); }
Vector2 get_support(const Vector2 &p_normal) const {
Vector2 half_extents = size * 0.5f;
Vector2 ofs = position + half_extents;
return Vector2(
(p_normal.x > 0) ? -half_extents.x : half_extents.x,
(p_normal.y > 0) ? -half_extents.y : half_extents.y) +
ofs;
}
_FORCE_INLINE_ bool intersects_filled_polygon(const Vector2 *p_points, int p_point_count) const {
Vector2 center = get_center();
int side_plus = 0;
int side_minus = 0;
Vector2 end = position + size;
int i_f = p_point_count - 1;
for (int i = 0; i < p_point_count; i++) {
const Vector2 &a = p_points[i_f];
const Vector2 &b = p_points[i];
i_f = i;
Vector2 r = (b - a);
float l = r.length();
if (l == 0.0f) {
continue;
}
//check inside
Vector2 tg = r.orthogonal();
float s = tg.dot(center) - tg.dot(a);
if (s < 0.0f) {
side_plus++;
} else {
side_minus++;
}
//check ray box
r /= l;
Vector2 ir(1.0f / r.x, 1.0f / r.y);
// lb is the corner of AABB with minimal coordinates - left bottom, rt is maximal corner
// r.org is origin of ray
Vector2 t13 = (position - a) * ir;
Vector2 t24 = (end - a) * ir;
float tmin = MAX(MIN(t13.x, t24.x), MIN(t13.y, t24.y));
float tmax = MIN(MAX(t13.x, t24.x), MAX(t13.y, t24.y));
// if tmax < 0, ray (line) is intersecting AABB, but the whole AABB is behind us
if (tmax < 0 || tmin > tmax || tmin >= l) {
continue;
}
return true;
}
if (side_plus * side_minus == 0) {
return true; //all inside
} else {
return false;
}
}
_FORCE_INLINE_ void set_end(const Vector2 &p_end) {
size = p_end - position;
}
_FORCE_INLINE_ Vector2 get_end() const {
return position + size;
}
operator String() const;
Rect2() {}
Rect2(real_t p_x, real_t p_y, real_t p_width, real_t p_height) :
@ -260,5 +360,4 @@ struct _NO_DISCARD_CLASS_ Rect2 {
}
};
#endif // RECT2_H

View File

@ -164,6 +164,9 @@ struct _NO_DISCARD_CLASS_ Vector2 {
Vector2 snapped(const Vector2 &p_by) const;
real_t aspect() const { return width / height; }
//TODO
Vector2 orthogonal() { return Vector2(); }
operator String() const { return String::num(x) + ", " + String::num(y); }
_FORCE_INLINE_ Vector2(real_t p_x, real_t p_y) {

View File

@ -171,6 +171,7 @@ VARIANT_ENUM_CAST(Vector2i::Axis);
VARIANT_ENUM_CAST(Error);
VARIANT_ENUM_CAST(Margin);
VARIANT_ENUM_CAST(Side);
VARIANT_ENUM_CAST(Corner);
VARIANT_ENUM_CAST(Orientation);
VARIANT_ENUM_CAST(HAlign);

View File

@ -2362,6 +2362,9 @@ Variant::operator Vector<Color>() const {
Variant::operator Margin() const {
return (Margin) operator int();
}
Variant::operator Side() const {
return (Side) operator int();
}
Variant::operator Orientation() const {
return (Orientation) operator int();
}

View File

@ -264,6 +264,7 @@ public:
// some core type enums to convert to
operator Margin() const;
operator Side() const;
operator Orientation() const;
operator IP_Address() const;

View File

@ -457,18 +457,39 @@ struct _VariantCall {
VCALL_LOCALMEM0R(Rect2, get_area);
VCALL_LOCALMEM0R(Rect2, get_center);
VCALL_LOCALMEM2R(Rect2, intersects);
VCALL_LOCALMEM1R(Rect2, distance_to);
VCALL_LOCALMEM2R(Rect2, intersects_transformed);
static void _call_Rect2_intersects_segment(Variant &r_ret, Variant &p_self, const Variant **p_args) {
Point2 pos;
Point2 normal;
if (reinterpret_cast<Rect2 *>(p_self._data._mem)->intersects_segment(*p_args[0], *p_args[1], &pos, &normal)) {
Array arr;
arr.push_back(pos);
arr.push_back(normal);
r_ret = arr;
} else {
r_ret = Variant();
}
}
VCALL_LOCALMEM1R(Rect2, encloses);
VCALL_LOCALMEM0R(Rect2, has_no_area);
VCALL_LOCALMEM1R(Rect2, clip);
VCALL_LOCALMEM1R(Rect2, intersection);
VCALL_LOCALMEM1R(Rect2, merge);
VCALL_LOCALMEM1R(Rect2, has_point);
VCALL_LOCALMEM1R(Rect2, is_equal_approx);
VCALL_LOCALMEM2R(Rect2, intersects);
VCALL_LOCALMEM1R(Rect2, encloses);
VCALL_LOCALMEM1R(Rect2, clip);
VCALL_LOCALMEM1R(Rect2, merge);
VCALL_LOCALMEM1R(Rect2, expand);
VCALL_LOCALMEM1R(Rect2, grow);
VCALL_LOCALMEM1(Rect2, grow_by);
VCALL_LOCALMEM2R(Rect2, grow_margin);
VCALL_LOCALMEM2R(Rect2, grow_side);
VCALL_LOCALMEM4R(Rect2, grow_individual);
VCALL_LOCALMEM1R(Rect2, expand);
VCALL_LOCALMEM1(Rect2, expand_to);
VCALL_LOCALMEM0R(Rect2, abs);
VCALL_LOCALMEM1R(Rect2, get_support);
VCALL_LOCALMEM1(Rect2, set_end);
VCALL_LOCALMEM0R(Rect2, get_end);
VCALL_LOCALMEM0R(Rect2i, get_area);
VCALL_LOCALMEM0R(Rect2i, get_center);
@ -2172,18 +2193,28 @@ void register_variant_methods() {
ADDFUNC0R(RECT2, REAL, Rect2, get_area, varray());
ADDFUNC0R(RECT2, VECTOR2, Rect2, get_center, varray());
ADDFUNC2R(RECT2, BOOL, Rect2, intersects, RECT2, "b", BOOL, "include_borders", varray(false));
ADDFUNC1R(RECT2, REAL, Rect2, distance_to, VECTOR2, "point", varray());
ADDFUNC2R(RECT2, BOOL, Rect2, intersects_transformed, TRANSFORM2D, "xform", RECT2, "rect", varray());
ADDFUNC2R(RECT2, NIL, Rect2, intersects_segment, VECTOR2, "from", VECTOR2, "to", varray());
ADDFUNC1R(RECT2, BOOL, Rect2, encloses, RECT2, "b", varray());
ADDFUNC0R(RECT2, BOOL, Rect2, has_no_area, varray());
ADDFUNC1R(RECT2, RECT2, Rect2, clip, RECT2, "b", varray());
ADDFUNC1R(RECT2, RECT2, Rect2, intersection, RECT2, "rect", varray());
ADDFUNC1R(RECT2, RECT2, Rect2, merge, RECT2, "b", varray());
ADDFUNC1R(RECT2, BOOL, Rect2, has_point, VECTOR2, "point", varray());
ADDFUNC1R(RECT2, BOOL, Rect2, is_equal_approx, RECT2, "rect", varray());
ADDFUNC2R(RECT2, BOOL, Rect2, intersects, RECT2, "b", BOOL, "include_borders", varray(false));
ADDFUNC1R(RECT2, BOOL, Rect2, encloses, RECT2, "b", varray());
ADDFUNC1R(RECT2, RECT2, Rect2, clip, RECT2, "b", varray());
ADDFUNC1R(RECT2, RECT2, Rect2, merge, RECT2, "b", varray());
ADDFUNC1R(RECT2, RECT2, Rect2, expand, VECTOR2, "to", varray());
ADDFUNC1R(RECT2, RECT2, Rect2, grow, REAL, "by", varray());
ADDFUNC1(RECT2, NIL, Rect2, grow_by, REAL, "by", varray());
ADDFUNC2R(RECT2, RECT2, Rect2, grow_margin, INT, "margin", REAL, "by", varray());
ADDFUNC2R(RECT2, RECT2, Rect2, grow_side, INT, "side", REAL, "by", varray());
ADDFUNC4R(RECT2, RECT2, Rect2, grow_individual, REAL, "left", REAL, "top", REAL, "right", REAL, " bottom", varray());
ADDFUNC1R(RECT2, RECT2, Rect2, expand, VECTOR2, "to", varray());
ADDFUNC1R(RECT2, RECT2, Rect2, expand_to, VECTOR2, "to", varray());
ADDFUNC0R(RECT2, RECT2, Rect2, abs, varray());
ADDFUNC1R(RECT2, VECTOR2, Rect2, get_support, VECTOR2, "normal", varray());
ADDFUNC1(RECT2, NIL, Rect2, set_end, VECTOR2, "end", varray());
ADDFUNC0R(RECT2, VECTOR2, Rect2, get_end, varray());
ADDFUNC0R(RECT2I, INT, Rect2i, get_area, varray());
ADDFUNC0R(RECT2I, VECTOR2I, Rect2i, get_center, varray());
@ -2280,7 +2311,6 @@ void register_variant_methods() {
ADDFUNC0R(COLOR, INT, Color, to_argb64, varray());
ADDFUNC0R(COLOR, INT, Color, to_abgr64, varray());
ADDFUNC0R(COLOR, REAL, Color, gray, varray());
ADDFUNC0R(COLOR, REAL, Color, get_h, varray());
ADDFUNC0R(COLOR, REAL, Color, get_s, varray());
ADDFUNC0R(COLOR, REAL, Color, get_v, varray());