diff options
Diffstat (limited to 'core/math/rect2.h')
| -rw-r--r-- | core/math/rect2.h | 149 | 
1 files changed, 119 insertions, 30 deletions
diff --git a/core/math/rect2.h b/core/math/rect2.h index 14393325ec..512499bdb2 100644 --- a/core/math/rect2.h +++ b/core/math/rect2.h @@ -5,8 +5,8 @@  /*                           GODOT ENGINE                                */  /*                      https://godotengine.org                          */  /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */  /*                                                                       */  /* Permission is hereby granted, free of charge, to any person obtaining */  /* a copy of this software and associated documentation files (the       */ @@ -123,8 +123,9 @@ struct Rect2 {  	_FORCE_INLINE_ bool has_no_area() const {  		return (size.x <= 0 || size.y <= 0);  	} -	inline Rect2 clip(const Rect2 &p_rect) const { /// return a clipped rect +	// Returns the instersection between two Rect2s or an empty Rect2 if there is no intersection +	inline Rect2 intersection(const Rect2 &p_rect) const {  		Rect2 new_rect = p_rect;  		if (!intersects(new_rect)) { @@ -179,24 +180,28 @@ struct Rect2 {  	bool operator==(const Rect2 &p_rect) const { return position == p_rect.position && size == p_rect.size; }  	bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; } -	inline Rect2 grow(real_t p_by) const { +	inline Rect2 grow(real_t p_amount) const {  		Rect2 g = *this; -		g.position.x -= p_by; -		g.position.y -= p_by; -		g.size.width += p_by * 2; -		g.size.height += p_by * 2; +		g.position.x -= p_amount; +		g.position.y -= p_amount; +		g.size.width += p_amount * 2; +		g.size.height += p_amount * 2;  		return g;  	} -	inline Rect2 grow_margin(Margin p_margin, real_t p_amount) const { +	inline Rect2 grow_side(Side p_side, real_t p_amount) const {  		Rect2 g = *this; -		g = g.grow_individual((MARGIN_LEFT == p_margin) ? p_amount : 0, -				(MARGIN_TOP == p_margin) ? p_amount : 0, -				(MARGIN_RIGHT == p_margin) ? p_amount : 0, -				(MARGIN_BOTTOM == p_margin) ? p_amount : 0); +		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_side_bind(uint32_t p_side, real_t p_amount) const { +		return grow_side(Side(p_side), p_amount); +	} +  	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; @@ -240,6 +245,77 @@ struct Rect2 {  		return Rect2(Point2(position.x + MIN(size.x, 0), position.y + MIN(size.y, 0)), size.abs());  	} +	Vector2 get_support(const Vector2 &p_normal) const { +		Vector2 half_extents = size * 0.5; +		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 = position + size * 0.5; +		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.0) { +				continue; +			} + +			//check inside +			Vector2 tg = r.orthogonal(); +			float s = tg.dot(center) - tg.dot(a); +			if (s < 0.0) { +				side_plus++; +			} else { +				side_minus++; +			} + +			//check ray box +			r /= l; +			Vector2 ir(1.0 / r.x, 1.0 / 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 { return String(position) + ", " + String(size); }  	Rect2() {} @@ -290,8 +366,9 @@ struct Rect2i {  	_FORCE_INLINE_ bool has_no_area() const {  		return (size.x <= 0 || size.y <= 0);  	} -	inline Rect2i clip(const Rect2i &p_rect) const { /// return a clipped rect +	// Returns the instersection between two Rect2is or an empty Rect2i if there is no intersection +	inline Rect2i intersection(const Rect2i &p_rect) const {  		Rect2i new_rect = p_rect;  		if (!intersects(new_rect)) { @@ -301,8 +378,8 @@ struct Rect2i {  		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; +		Point2i p_rect_end = p_rect.position + p_rect.size; +		Point2i end = position + size;  		new_rect.size.x = (int)(MIN(p_rect_end.x, end.x) - new_rect.position.x);  		new_rect.size.y = (int)(MIN(p_rect_end.y, end.y) - new_rect.position.y); @@ -324,7 +401,7 @@ struct Rect2i {  		return new_rect;  	} -	bool has_point(const Point2 &p_point) const { +	bool has_point(const Point2i &p_point) const {  		if (p_point.x < position.x) {  			return false;  		} @@ -345,24 +422,28 @@ struct Rect2i {  	bool operator==(const Rect2i &p_rect) const { return position == p_rect.position && size == p_rect.size; }  	bool operator!=(const Rect2i &p_rect) const { return position != p_rect.position || size != p_rect.size; } -	Rect2i grow(int p_by) const { +	Rect2i grow(int p_amount) const {  		Rect2i g = *this; -		g.position.x -= p_by; -		g.position.y -= p_by; -		g.size.width += p_by * 2; -		g.size.height += p_by * 2; +		g.position.x -= p_amount; +		g.position.y -= p_amount; +		g.size.width += p_amount * 2; +		g.size.height += p_amount * 2;  		return g;  	} -	inline Rect2i grow_margin(Margin p_margin, int p_amount) const { +	inline Rect2i grow_side(Side p_side, int p_amount) const {  		Rect2i g = *this; -		g = g.grow_individual((MARGIN_LEFT == p_margin) ? p_amount : 0, -				(MARGIN_TOP == p_margin) ? p_amount : 0, -				(MARGIN_RIGHT == p_margin) ? p_amount : 0, -				(MARGIN_BOTTOM == p_margin) ? p_amount : 0); +		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 Rect2i grow_side_bind(uint32_t p_side, int p_amount) const { +		return grow_side(Side(p_side), p_amount); +	} +  	inline Rect2i grow_individual(int p_left, int p_top, int p_right, int p_bottom) const {  		Rect2i g = *this;  		g.position.x -= p_left; @@ -405,6 +486,14 @@ struct Rect2i {  		return Rect2i(Point2i(position.x + MIN(size.x, 0), position.y + MIN(size.y, 0)), size.abs());  	} +	_FORCE_INLINE_ void set_end(const Vector2i &p_end) { +		size = p_end - position; +	} + +	_FORCE_INLINE_ Vector2i get_end() const { +		return position + size; +	} +  	operator String() const { return String(position) + ", " + String(size); }  	operator Rect2() const { return Rect2(position, size); } @@ -415,10 +504,10 @@ struct Rect2i {  			size(p_r2.size) {  	}  	Rect2i(int p_x, int p_y, int p_width, int p_height) : -			position(Point2(p_x, p_y)), -			size(Size2(p_width, p_height)) { +			position(Point2i(p_x, p_y)), +			size(Size2i(p_width, p_height)) {  	} -	Rect2i(const Point2 &p_pos, const Size2 &p_size) : +	Rect2i(const Point2i &p_pos, const Size2i &p_size) :  			position(p_pos),  			size(p_size) {  	}  |