summaryrefslogtreecommitdiff
path: root/Runtime/Math/Rect.h
diff options
context:
space:
mode:
Diffstat (limited to 'Runtime/Math/Rect.h')
-rw-r--r--Runtime/Math/Rect.h184
1 files changed, 184 insertions, 0 deletions
diff --git a/Runtime/Math/Rect.h b/Runtime/Math/Rect.h
new file mode 100644
index 0000000..4801988
--- /dev/null
+++ b/Runtime/Math/Rect.h
@@ -0,0 +1,184 @@
+#ifndef RECT_H
+#define RECT_H
+
+#include "Vector2.h"
+#include "Runtime/Modules/ExportModules.h"
+
+/// A rectangle.
+template <typename T>
+class EXPORT_COREMODULE RectT
+{
+public:
+ typedef RectT<T> RectType;
+ typedef float BaseType;
+
+ T x; ///< Rectangle x coordinate.
+ T y; ///< Rectangle y coordinate.
+ T width; ///< Rectangle width.
+ T height; ///< Rectangle height.
+
+ //DECLARE_SERIALIZE_OPTIMIZE_TRANSFER (Rectf)
+ inline static const char* GetTypeString ();
+ inline static bool IsAnimationChannel () { return false; }
+ inline static bool MightContainPPtr () { return false; }
+ inline static bool AllowTransferOptimization () { return true; }
+ template <class TransferFunction>
+ void Transfer (TransferFunction& transfer)
+ {
+ TRANSFER (x);
+ TRANSFER (y);
+ TRANSFER (width);
+ TRANSFER (height);
+ }
+
+ /// Create a empty rectangle.
+ RectT ()
+ {
+ Reset ();
+ }
+
+ /// Create a new rectangle.
+ RectT (T inX, T inY, T iWidth, T iHeight)
+ {
+ x = inX; width = iWidth;
+ y = inY; height = iHeight;
+ }
+
+ T GetRight() const { return x + width; }
+ T GetBottom() const { return y + height; }
+ void SetLeft(T l) { T oldXMax = GetXMax(); x = l; width = oldXMax - x; }
+ void SetTop(T t) { T oldYMax = GetYMax(); y = t; height = oldYMax - y; }
+ void SetRight(T r) { width = r - x; }
+ void SetBottom(T b) { height = b - y; }
+
+
+ T GetXMax() const { return x + width; }
+ T GetYMax() const { return y + height; }
+
+ /// Return true if rectangle is empty.
+ inline bool IsEmpty () const { return width <= 0 || height <= 0; }
+
+ inline void SetPosition(const Vector2f& position) { x = position.x; y = position.y; }
+ inline Vector2f GetPosition() const { return Vector2f(x, y); }
+
+ inline void SetSize(const Vector2f& size) { width = size.x; height = size.y; }
+ inline Vector2f GetSize() const { return Vector2f(width, height); }
+ /// Resets the rectangle
+ inline void Reset() { x = y = width = height = 0; }
+
+ /// Sets the rectangle
+ inline void Set(T inX, T inY, T iWidth, T iHeight)
+ {
+ x = inX; width = iWidth;
+ y = inY; height = iHeight;
+ }
+
+ inline void Scale (T dx, T dy) { x *= dx; width *= dx; y *= dy; height *= dy;}
+
+ /// Set Center position of rectangle (size stays the same)
+ void SetCenterPos (T cx, T cy) { x = cx - width / 2; y = cy - height / 2; }
+ Vector2f GetCenterPos() const { return Vector2f(x + (BaseType)width / 2, y + (BaseType)height / 2); }
+
+ /// Ensure this is inside the rect r.
+ void Clamp (const RectType &r)
+ {
+ T x2 = x + width;
+ T y2 = y + height;
+ T rx2 = r.x + r.width;
+ T ry2 = r.y + r.height;
+
+ if (x < r.x) x = r.x;
+ if (x2 > rx2) x2 = rx2;
+ if (y < r.y) y = r.y;
+ if (y2 > ry2) y2 = ry2;
+
+ width = x2 - x;
+ if (width < 0) width = 0;
+
+ height = y2 - y;
+ if (height < 0) height = 0;
+ }
+
+ /// Move rectangle by deltaX, deltaY.
+ inline void Move (T dX, T dY) { x += dX; y += dY; }
+
+ /// Return the width of rectangle.
+ inline T Width () const { return width; }
+
+ /// Return the height of rectangle.
+ inline T Height () const { return height; }
+
+ /// Return true if a point lies within rectangle bounds.
+ inline bool Contains (T px, T py) const { return (px >= x) && (px < x + width) && (py >= y) && (py < y + height); }
+ inline bool Contains (const Vector2f& p) const { return Contains(p.x, p.y); }
+ /// Return true if a relative point lies within rectangle bounds.
+ inline bool ContainsRel (T x, T y) const
+ { return (x >= 0) && (x < Width ()) && (y >= 0) && (y < Height ()); }
+
+ inline bool Intersects(const RectType& r) const
+ {
+ // Rects are disjoint if there's at least one separating axis
+ bool disjoint = x + width < r.x;
+ disjoint |= r.x + r.width < x;
+ disjoint |= y + height < r.y;
+ disjoint |= r.y + r.height < y;
+ return !disjoint;
+ }
+
+ /// Normalize a rectangle such that xmin <= xmax and ymin <= ymax.
+ inline void Normalize ()
+ {
+ width = std::max<T>(width, 0);
+ height = std::max<T>(height, 0);
+ }
+
+ bool operator == (const RectType& r)const { return x == r.x && y == r.y && width == r.width && height == r.height; }
+ bool operator != (const RectType& r)const { return x != r.x || y != r.y || width != r.width || height != r.height; }
+};
+
+typedef RectT<float> Rectf;
+typedef RectT<int> RectInt;
+
+template<> inline const char* Rectf::GetTypeString () { return "Rectf"; }
+template<> inline const char* RectInt::GetTypeString () { return "RectInt"; }
+
+inline bool CompareApproximately (const Rectf& lhs, const Rectf& rhs)
+{
+ return CompareApproximately (lhs.x, rhs.x) && CompareApproximately (lhs.y, rhs.y) &&
+ CompareApproximately (lhs.width, rhs.width) && CompareApproximately (lhs.height, rhs.height);
+}
+
+/// Make a rect with width & height
+template<typename T>
+inline RectT<T> MinMaxRect (T minx, T miny, T maxx, T maxy) { return RectT<T> (minx, miny, maxx - minx, maxy - miny); }
+
+// RectT<float> specialization
+template<>
+inline bool Rectf::IsEmpty () const { return width <= 0.00001F || height <= 0.00001F; }
+
+template<>
+template<class TransferFunction> inline
+void Rectf::Transfer (TransferFunction& transfer)
+{
+ transfer.SetVersion(2);
+
+ TRANSFER (x);
+ TRANSFER (y);
+ TRANSFER (width);
+ TRANSFER (height);
+
+ #if UNITY_EDITOR
+ if (transfer.IsOldVersion(1))
+ {
+ float xmax=0.0F, ymax=0.0F, ymin=0.0F, xmin=0.0F;
+ TRANSFER (xmin);
+ TRANSFER (ymin);
+ TRANSFER (xmax);
+ TRANSFER (ymax);
+
+ *this = MinMaxRect(xmin, ymin, xmax, ymax);
+ }
+ #endif
+}
+
+#endif