HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
aarect.hpp
1// Copyright 2020 Pokitec
2// All rights reserved.
3
4#pragma once
5
6#include "TTauri/Foundation/vec.hpp"
7#include "TTauri/Foundation/attributes.hpp"
8
9namespace tt {
10
13class aarect {
14private:
15 friend class R32G32B32A32SFloat;
16
22 vec v;
23
24public:
25 tt_force_inline aarect() noexcept : v() {}
26 tt_force_inline aarect(aarect const &rhs) noexcept = default;
27 tt_force_inline aarect &operator=(aarect const &rhs) noexcept = default;
28 tt_force_inline aarect(aarect &&rhs) noexcept = default;
29 tt_force_inline aarect &operator=(aarect &&rhs) noexcept = default;
30
31
39 template<typename X, typename Y, typename W=float, typename H=float,
40 std::enable_if_t<std::is_arithmetic_v<X> && std::is_arithmetic_v<Y> && std::is_arithmetic_v<W> && std::is_arithmetic_v<H>,int> = 0>
41 tt_force_inline aarect(X x, Y y, W width, H height) noexcept :
42 v(vec(
43 numeric_cast<float>(x),
44 numeric_cast<float>(y),
45 numeric_cast<float>(x) + numeric_cast<float>(width),
46 numeric_cast<float>(y) + numeric_cast<float>(height)
47 )) {}
48
54 tt_force_inline aarect(vec const &position, vec const &extent) noexcept :
55 v(position.xyxy() + extent._00xy()) {
56 tt_assume(position.is_point());
57 tt_assume(position.z() == 0.0);
58 tt_assume(extent.is_vector());
59 tt_assume(extent.z() == 0.0);
60 }
61
66 tt_force_inline aarect(vec const &extent) noexcept :
67 v(extent._00xy()) {
68 tt_assume(extent.is_vector());
69 tt_assume(extent.z() == 0.0);
70 }
71
75 [[nodiscard]] tt_force_inline static aarect p0p3(vec const &v) noexcept {
76 aarect r;
77 r.v = v;
78 return r;
79 }
80
81 [[nodiscard]] tt_force_inline static aarect p0p3(vec const &p0, vec const &p3) noexcept {
82 tt_assume(p0.is_point());
83 tt_assume(p3.is_point());
84 return aarect::p0p3(p0.xy00() + p3._00xy());
85 }
86
87 operator bool () const noexcept {
88 return v.xyxy() != v.zwzw();
89 }
90
96 aarect &operator|=(aarect const &rhs) noexcept {
97 return *this = *this | rhs;
98 }
99
105 aarect &operator|=(vec const &rhs) noexcept {
106 return *this = *this | rhs;
107 }
108
109
114 aarect &operator+=(vec const &rhs) noexcept {
115 return *this = *this + rhs;
116 }
117
122 aarect &operator-=(vec const &rhs) noexcept {
123 return *this = *this - rhs;
124 }
125
130 aarect &operator*=(float rhs) noexcept {
131 return *this = *this * rhs;
132 }
133
139 template<size_t I>
140 [[nodiscard]] tt_force_inline vec corner() const noexcept {
141 static_assert(I <= 3);
142 if constexpr (I == 0) {
143 return v.xy01();
144 } else if constexpr (I == 1) {
145 return v.zy01();
146 } else if constexpr (I == 2) {
147 return v.xw01();
148 } else {
149 return v.zw01();
150 }
151 }
152
159 //template<size_t I, typename Z, std::enable_if_t<std::is_arithmetic_v<Z>,int> = 0>
160 //[[nodiscard]] tt_force_inline vec corner(Z z) const noexcept {
161 // return corner<I>().z(numeric_cast<float>(z));
162 //}
163
164 [[nodiscard]] tt_force_inline vec p0() const noexcept {
165 return corner<0>();
166 }
167
168 [[nodiscard]] tt_force_inline vec p3() const noexcept {
169 return corner<3>();
170 }
171
172
177 [[nodiscard]] tt_force_inline vec offset() const noexcept {
178 return v.xy00();
179 }
180
185 [[nodiscard]] vec extent() const noexcept {
186 return (v.zwzw() - v).xy00();
187 }
188
189 [[nodiscard]] tt_force_inline float x() const noexcept {
190 return v.x();
191 }
192
193 [[nodiscard]] tt_force_inline float y() const noexcept {
194 return v.y();
195 }
196
197 [[nodiscard]] tt_force_inline float width() const noexcept {
198 return (v.zwzw() - v).x();
199 }
200
201 [[nodiscard]] tt_force_inline float height() const noexcept {
202 return (v.zwzw() - v).y();
203 }
204
205 template<typename T, std::enable_if_t<std::is_arithmetic_v<T>,int> = 0>
206 tt_force_inline aarect &width(T newWidth) noexcept {
207 v = v.xyxw() + vec::make_z(newWidth);
208 return *this;
209 }
210
211 template<typename T, std::enable_if_t<std::is_arithmetic_v<T>,int> = 0>
212 tt_force_inline aarect &height(T newHeight) noexcept {
213 v = v.xyzy() + vec::make_w(newHeight);
214 return *this;
215 }
216
221 [[nodiscard]] bool contains(vec const &rhs) const noexcept {
222 return (rhs.xyxy() >= v) == 0b0011;
223 }
224
231 [[nodiscard]] friend aarect align(aarect haystack, aarect needle, Alignment alignment) noexcept {
232 float x;
233 if (alignment == HorizontalAlignment::Left) {
234 x = haystack.p0().x();
235
236 } else if (alignment == HorizontalAlignment::Right) {
237 x = haystack.p3().x() - needle.width();
238
239 } else if (alignment == HorizontalAlignment::Center) {
240 x = (haystack.p0().x() + (haystack.width() * 0.5f)) - (needle.width() * 0.5f);
241
242 } else {
243 tt_no_default;
244 }
245
246 float y;
247 if (alignment == VerticalAlignment::Bottom) {
248 y = haystack.p0().y();
249
250 } else if (alignment == VerticalAlignment::Top) {
251 y = haystack.p3().y() - needle.height();
252
253 } else if (alignment == VerticalAlignment::Middle) {
254 y = (haystack.p0().y() + (haystack.height() * 0.5f)) - (needle.height() * 0.5f);
255
256 } else {
257 tt_no_default;
258 }
259
260 return {vec::point(x, y), needle.extent()};
261 }
262
265 [[nodiscard]] static aarect _align(aarect outside, aarect inside, Alignment alignment) noexcept {
266 return align(outside, inside, alignment);
267 }
268
269 [[nodiscard]] friend bool operator==(aarect const &lhs, aarect const &rhs) noexcept {
270 return lhs.v == rhs.v;
271 }
272
273 [[nodiscard]] friend bool operator!=(aarect const &lhs, aarect const &rhs) noexcept {
274 return !(lhs == rhs);
275 }
276
277 [[nodiscard]] friend bool overlaps(aarect const &lhs, aarect const &rhs) noexcept {
278 ttlet rhs_swap = rhs.v.zwxy();
279 if (((lhs.v > rhs_swap) & 0x0011) != 0) {
280 return false;
281 }
282 if (((lhs.v < rhs_swap) & 0x1100) != 0) {
283 return false;
284 }
285 return true;
286 }
287
288 [[nodiscard]] friend aarect operator|(aarect const &lhs, aarect const &rhs) noexcept {
289 return aarect::p0p3(min(lhs.p0(), rhs.p0()), max(lhs.p3(), rhs.p3()));
290 }
291
292 [[nodiscard]] friend aarect operator|(aarect const &lhs, vec const &rhs) noexcept {
293 tt_assume(rhs.is_point());
294 return aarect::p0p3(min(lhs.p0(), rhs), max(lhs.p3(), rhs));
295 }
296
297 [[nodiscard]] friend aarect operator+(aarect const &lhs, vec const &rhs) noexcept {
298 return aarect::p0p3(lhs.v + rhs.xyxy());
299 }
300
301 [[nodiscard]] friend aarect operator-(aarect const &lhs, vec const &rhs) noexcept {
302 return aarect::p0p3(lhs.v - rhs.xyxy());
303 }
304
305 [[nodiscard]] friend aarect operator*(aarect const &lhs, float rhs) noexcept {
306 return aarect::p0p3(lhs.v * vec{rhs});
307 }
308
314 [[nodiscard]] friend aarect scale(aarect const &lhs, float rhs) noexcept {
315 ttlet extent = lhs.extent();
316 ttlet scaled_extent = extent * rhs;
317 ttlet diff_extent = scaled_extent - extent;
318 ttlet half_diff_extent = diff_extent * 0.5f;
319
320 ttlet p1 = lhs.p0() - half_diff_extent;
321 ttlet p2 = lhs.p3() + half_diff_extent;
322 return aarect::p0p3(p1, p2);
323 }
324
325
332 [[nodiscard]] friend aarect expand(aarect const &lhs, float rhs) noexcept {
333 return aarect::p0p3(lhs.v + neg<1,1,0,0>(vec{rhs}));
334 }
335
342 [[nodiscard]] friend aarect shrink(aarect const &lhs, float rhs) noexcept {
343 return expand(lhs, -rhs);
344 }
345
346 [[nodiscard]] friend aarect round(aarect const &rhs) noexcept {
347 return aarect::p0p3(round(rhs.v));
348 }
349};
350
351}
352
Class which represents an axis-aligned rectangle.
Definition aarect.hpp:13
aarect & operator*=(float rhs) noexcept
Scale the box by moving the positions (scaling the vectors).
Definition aarect.hpp:130
tt_force_inline vec corner() const noexcept
Get coordinate of a corner.
Definition aarect.hpp:140
friend aarect align(aarect haystack, aarect needle, Alignment alignment) noexcept
Align a rectangle within another rectangle.
Definition aarect.hpp:231
tt_force_inline vec p0() const noexcept
Get coordinate of a corner.
Definition aarect.hpp:164
aarect & operator-=(vec const &rhs) noexcept
Translate the box to a new position.
Definition aarect.hpp:122
aarect & operator|=(aarect const &rhs) noexcept
Expand the current rectangle to include the new rectangle.
Definition aarect.hpp:96
aarect & operator|=(vec const &rhs) noexcept
Expand the current rectangle to include the new point.
Definition aarect.hpp:105
tt_force_inline vec offset() const noexcept
Get vector from origin to the bottom-left corner.
Definition aarect.hpp:177
friend aarect scale(aarect const &lhs, float rhs) noexcept
Expand the rectangle for the same amount in all directions.
Definition aarect.hpp:314
friend aarect expand(aarect const &lhs, float rhs) noexcept
Expand the rectangle for the same amount in all directions.
Definition aarect.hpp:332
bool contains(vec const &rhs) const noexcept
Check if a 2D coordinate is inside the rectangle.
Definition aarect.hpp:221
tt_force_inline aarect(X x, Y y, W width, H height) noexcept
Create a box from the position and size.
Definition aarect.hpp:41
vec extent() const noexcept
Get size of the rectangle.
Definition aarect.hpp:185
aarect & operator+=(vec const &rhs) noexcept
Translate the box to a new position.
Definition aarect.hpp:114
tt_force_inline aarect(vec const &position, vec const &extent) noexcept
Create a rectangle from the position and size.
Definition aarect.hpp:54
static aarect _align(aarect outside, aarect inside, Alignment alignment) noexcept
Need to call the hiden friend function from within another class.
Definition aarect.hpp:265
friend aarect shrink(aarect const &lhs, float rhs) noexcept
Shrink the rectangle for the same amount in all directions.
Definition aarect.hpp:342
tt_force_inline aarect(vec const &extent) noexcept
Create a rectangle from the size.
Definition aarect.hpp:66
static tt_force_inline aarect p0p3(vec const &v) noexcept
Create aarect from packed p0p3 coordinates.
Definition aarect.hpp:75
Definition R32G32B32A32SFloat.hpp:13
A 4D vector.
Definition vec.hpp:37
static tt_force_inline vec point(float x=0.0f, float y=0.0f, float z=0.0f) noexcept
Create a point out of 2 to 4 values.
Definition vec.hpp:180
T max(T... args)
T min(T... args)