From 65197d43503b9e7d71d994501f4eb161dfe2b310 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Tue, 5 Nov 2019 19:19:20 +1000 Subject: [PATCH] Common: Add Rectangle helper class --- src/common/CMakeLists.txt | 3 +- src/common/common.vcxproj | 1 + src/common/common.vcxproj.filters | 1 + src/common/rectangle.h | 132 ++++++++++++++++++++++++++++++ 4 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 src/common/rectangle.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 3c26c3615..31df1d34b 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -16,9 +16,10 @@ add_library(common gl/texture.h jit_code_buffer.cpp jit_code_buffer.h + rectangle.h state_wrapper.cpp state_wrapper.h - types.h + types.h ) target_include_directories(common PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/..") diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj index c6bd1dc88..9284532f7 100644 --- a/src/common/common.vcxproj +++ b/src/common/common.vcxproj @@ -48,6 +48,7 @@ + diff --git a/src/common/common.vcxproj.filters b/src/common/common.vcxproj.filters index c31b18e5d..7c6c099ac 100644 --- a/src/common/common.vcxproj.filters +++ b/src/common/common.vcxproj.filters @@ -31,6 +31,7 @@ d3d11 + diff --git a/src/common/rectangle.h b/src/common/rectangle.h new file mode 100644 index 000000000..e3fbdd2eb --- /dev/null +++ b/src/common/rectangle.h @@ -0,0 +1,132 @@ +#pragma once +#include +#include +#include + +namespace Common { + +/// Templated rectangle class. Assumes an upper-left origin, that is (0,0) is the top-left corner. +template +struct Rectangle +{ + enum : T + { + InvalidMinCoord = std::numeric_limits::max(), + InvalidMaxCoord = std::numeric_limits::min() + }; + + /// Default constructor - initializes to an invalid coordinate range suitable for including points. + constexpr Rectangle() : left(InvalidMinCoord), top(InvalidMinCoord), right(InvalidMaxCoord), bottom(InvalidMaxCoord) + { + } + + /// Construct with values. + constexpr Rectangle(T left_, T top_, T right_, T bottom_) : left(left_), top(top_), right(right_), bottom(bottom_) {} + + /// Copy constructor. + constexpr Rectangle(const Rectangle& copy) : left(copy.left), top(copy.top), right(copy.right), bottom(copy.bottom) {} + + /// Sets the rectangle using the specified values. + constexpr void Set(T left_, T top_, T right_, T bottom_) + { + left = left_; + top = top_; + right = right_; + bottom = bottom_; + } + + /// Sets the rectangle using the specified top-left position and extents. + constexpr void SetExtents(T x, T y, T width, T height) + { + left = x; + top = y; + left = x + width; + bottom = y + height; + } + + /// Returns a new rectangle from the specified position and size. + static Rectangle FromExtents(T x, T y, T width, T height) { return Rectangle(x, y, x + width, y + height); } + + /// Sets the rectangle to invalid coordinates (right < left, top < bottom). + constexpr void SetInvalid() { Set(InvalidMinCoord, InvalidMinCoord, InvalidMaxCoord, InvalidMaxCoord); } + + /// Returns the width of the rectangle. + constexpr T GetWidth() const { return right - left; } + + /// Returns the height of the rectangle. + constexpr T GetHeight() const { return bottom - top; } + + /// Returns true if the rectangles's width/height can be considered valid. + constexpr bool Valid() const { return left <= right && top <= bottom; } + + /// Returns false if the rectangle does not have any extents (zero size). + constexpr bool HasExtents() const { return left < right && top < bottom; } + + /// Assignment operator. + constexpr Rectangle& operator=(const Rectangle& rhs) + { + left = rhs.left; + top = rhs.top; + left = rhs.left; + bottom = rhs.bottom; + } + + // Relational operators. +#define RELATIONAL_OPERATOR(op) \ + constexpr bool operator op(const Rectangle& rhs) const \ + { \ + return std::tie(left, top, right, bottom) op std::tie(rhs.left, rhs.top, rhs.right, rhs.bottom); \ + } + + RELATIONAL_OPERATOR(==); + RELATIONAL_OPERATOR(!=); + RELATIONAL_OPERATOR(<); + RELATIONAL_OPERATOR(<=); + RELATIONAL_OPERATOR(>); + RELATIONAL_OPERATOR(>=); + +#undef RELATIONAL_OPERATOR + +#ifdef _WINDEF_ + /// Casts this rectangle to a Win32 RECT structure if compatible. + template && _>> + const RECT* AsRECT() const + { + return reinterpret_cast(this); + } +#endif + + /// Tests for intersection between two rectangles. + constexpr bool Intersects(const Rectangle& rhs) const + { + return !(left > rhs.right || rhs.left > right || top > rhs.bottom || rhs.top > bottom); + } + + /// Tests whether the specified point is contained in the rectangle. + constexpr bool Contains(T x, T y) const { return (x >= left && x < right && y >= top && y < bottom); } + + /// Expands the bounds of the rectangle to contain the specified point. + constexpr void Include(T x, T y) + { + left = std::min(left, x); + right = std::max(right, x + static_cast(1)); + top = std::min(top, y); + bottom = std::max(bottom, y + static_cast(1)); + } + + /// Expands the bounds of the rectangle to contain another rectangle. + constexpr void Include(const Rectangle& rhs) + { + left = std::min(left, rhs.left); + right = std::max(right, rhs.right); + top = std::min(top, rhs.top); + bottom = std::max(bottom, rhs.bottom); + } + + T left; + T top; + T right; + T bottom; +}; + +} // namespace Common \ No newline at end of file