godot.core.math.Rect2.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of godot-library-release Show documentation
Show all versions of godot-library-release Show documentation
Contains godot api as kotlin classes and jvm cpp interaction code.
@file:Suppress("PackageDirectoryMismatch", "unused")
package godot.core
import godot.Side
import godot.annotation.CoreTypeHelper
import godot.annotation.CoreTypeLocalCopy
import godot.util.RealT
import kotlin.math.max
import kotlin.math.min
private typealias Point2 = Vector2
private typealias Size2 = Vector2
class Rect2(
p_position: Point2,
p_size: Size2
) : CoreType {
@PublishedApi
internal var _position = Point2(p_position)
@PublishedApi
internal var _size = Size2(p_size)
//PROPERTIES
/** Return a copy of the position Vector2
* Warning: Writing position.x = 2 will only modify a copy, not the actual object.
* To modify it, use position().
* */
@CoreTypeLocalCopy
var position
get() = Point2(_position)
set(value) {
_position = Point2(value)
}
/**
* Apply modifications on actual [position] [Vector2].
*
*
* [position] var return a copy of actual position of this [Rect2]. This method purpose is to make changes to the
* actual position.
* See also: [position]
*/
@CoreTypeHelper
inline fun position(block: Point2.() -> T): T {
return _position.block()
}
/** Return a copy of the size Vector2
* Warning: Writing size.x = 2 will only modify a copy, not the actual object.
* To modify it, use size().
* */
@CoreTypeLocalCopy
var size
get() = Size2(_size)
set(value) {
_size = Size2(value)
}
/**
* Apply modifications on actual [size] [Vector2].
*
*
* [size] var return a copy of actual size of this [Rect2]. This method purpose is to make changes to the
* actual size.
* See also: [size]
*/
@CoreTypeHelper
inline fun size(block: Size2.() -> T): T {
return _size.block()
}
/** Return a copy of the end Vector2
* Warning: Writing end.x = 2 will only modify a copy, not the actual object.
* To modify it, use end().
* */
@CoreTypeLocalCopy
inline var end: Vector2
get() = _position + _size
set(value) {
_size = value - _position
}
@CoreTypeHelper
inline fun end(block: Vector2.() -> T): T {
val vec = end
val ret = vec.block()
end = vec
return ret
}
//CONSTANTS
enum class Margin(val value: Int) {
LEFT(0),
TOP(1),
RIGHT(2),
BOTTOM(3)
}
companion object {
val MARGIN_LEFT = Margin.LEFT.value
val MARGIN_TOP = Margin.TOP.value
val MARGIN_RIGHT = Margin.RIGHT.value
val MARGIN_BOTTOM = Margin.BOTTOM.value
}
//CONSTRUCTOR
constructor() :
this(Vector2(), Vector2())
constructor(other: Rect2) :
this(other._position, other._size)
constructor(other: Rect2i) : this(other._position.toVector2(), other._size.toVector2())
constructor(x: RealT, y: RealT, width: RealT, height: RealT) :
this(Vector2(x, y), Vector2(width, height))
//API
/**
*Returns a Rect2 with equivalent position and area, modified so that
* the top-left corner is the origin and width and height are positive.
*/
fun abs() = Rect2(position + size.min(Point2()), size.abs())
/**
* Returns true if this Rect2 completely encloses another one.
*/
fun encloses(b: Rect2): Boolean {
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))
}
/**
* Returns this Rect2 expanded to include a given point.
*/
fun expand(vector: Vector2): Rect2 {
val r = Rect2(this._position, this._size)
r.expandTo(vector)
return r
}
internal fun expandTo(vector: Vector2) {
val begin = Vector2(_position)
val end = _position + _size
if (vector.x < begin.x) {
begin.x = vector.x
}
if (vector.y < begin.y) {
begin.y = vector.y
}
if (vector.x > end.x) {
end.x = vector.x
}
if (vector.y > end.y) {
end.y = vector.y
}
_position = begin
_size = end - begin
}
/**
* Returns the area of the Rect2.
*/
fun getArea(): RealT {
return _size.x * _size.y
}
/**
* Returns the center of the Rect2, which is equal to [position] + ([size] / 2).
*/
fun getCenter() = position + (size * 0.5f)
/**
* Returns a copy of the Rect2 grown a given amount of units towards all the sides.
*/
fun grow(by: RealT): Rect2 {
val g = Rect2(this._position, this._size)
g._position.x -= by
g._position.y -= by
g._size.x += by * 2
g._size.y += by * 2
return g
}
/**
* Returns a copy of the Rect2 grown a given amount of units towards all the sides.
*/
fun growIndividual(left: RealT, top: RealT, right: RealT, bottom: RealT): Rect2 {
val g = Rect2(this._position, this._size)
g._position.x -= left
g._position.y -= top
g._size.x += left + right
g._size.y += top + bottom
return g
}
/**
* Returns a copy of the Rect2 grown a given [amount] of units towards all the sides.
*/
fun growSide(side: Side, amount: RealT): Rect2 {
var g = Rect2(this)
g = g.growIndividual(
if (Side.SIDE_LEFT == side) amount else 0.0,
if (Side.SIDE_TOP == side) amount else 0.0,
if (Side.SIDE_RIGHT == side) amount else 0.0,
if (Side.SIDE_BOTTOM == side) amount else 0.0,
)
return g
}
/**
* Returns true if the [Rect2] has area, and false if the Rect2 is linear, empty, or has a negative size. See also
* [getArea].
*/
fun hasArea() = size.x > 0.0f && size.y > 0.0f
/**
* Returns true if the Rect2 contains a point.
*/
fun hasPoint(point: Vector2): Boolean {
return when {
point.x < _position.x -> false
point.y < _position.y -> false
point.x >= (_position.x + _size.x) -> false
point.y >= (_position.y + _size.y) -> false
else -> true
}
}
/**
* Returns the intersection of this [Rect2] and [b].
*
* If the rectangles do not intersect, an empty [Rect2] is returned.
*/
fun intersection(rect: Rect2): Rect2 {
val ret = Rect2(rect)
if (!intersects(ret)) {
return Rect2()
}
ret._position.x = max(rect._position.x, _position.x)
ret._position.y = max(rect._position.y, _position.y)
val rectEnd: Point2 = rect._position + rect._size
val end = _position + _size
ret._size.x = min(rectEnd.x, end.x) - ret._position.x
ret._size.y = min(rectEnd.y, end.y) - ret._position.y
return ret
}
/**
* Returns true if the Rect2 overlaps with b (i.e. they have at least one point in common).
* If include_borders is true, they will also be considered overlapping if their borders touch, even without intersection.
*/
@JvmOverloads
fun intersects(b: Rect2, includeBorders: Boolean = false): Boolean {
if (includeBorders) {
return when {
_position.x > (b._position.x + b._size.x) -> false
(_position.x + _size.x) < b._position.x -> false
_position.y > (b._position.y + b._size.y) -> false
(_position.y + _size.y) < b._position.y -> false
else -> true
}
} else {
return when {
_position.x >= (b._position.x + b._size.x) -> false
(_position.x + _size.x) <= b._position.x -> false
_position.y >= (b._position.y + b._size.y) -> false
(_position.y + _size.y) <= b._position.y -> false
else -> true
}
}
}
/**
* Returns true if this Rect2 and rect are approximately equal, by calling is_equal_approx on each component.
*/
fun isEqualApprox(b: Rect2): Boolean {
return b._position.isEqualApprox(this._position) && b._size.isEqualApprox(this._size)
}
/**
* Returns true if this rectangle's values are finite, by calling Vector2.is_finite on the position and the size.
*/
fun isFinite(): Boolean {
return position.isFinite() && size.isFinite();
}
/**
* Returns a larger Rect2 that contains this Rect2 and b.
*/
fun merge(rect: Rect2): Rect2 {
val newRect = Rect2()
newRect._position.x = min(rect._position.x, _position.x)
newRect._position.y = min(rect._position.y, _position.y)
newRect._size.x = max(rect._position.x + rect._size.x, _position.x + _size.x)
newRect._size.y = max(rect._position.y + rect._size.y, _position.y + _size.y)
newRect._size = newRect._size - newRect._position // Make relative again.
return newRect
}
fun toRect2i() = Rect2i(this)
override fun equals(other: Any?): Boolean = when (other) {
is Rect2 -> _position == other._position && _size == other._size
else -> false
}
override fun toString(): String {
return "[P: $_position, S: $_size]"
}
override fun hashCode(): Int {
var result = _position.hashCode()
result = 31 * result + _size.hashCode()
return result
}
}