-
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathViewport.mpp
More file actions
86 lines (70 loc) · 3 KB
/
Viewport.mpp
File metadata and controls
86 lines (70 loc) · 3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
export module CppUtils.Terminal.Area:Viewport;
import std;
import CppUtils.Container.Size;
import CppUtils.Math.Utility;
export namespace CppUtils::Terminal
{
class Viewport final
{
public:
inline constexpr Viewport(const Container::Size2& size = {0, 0}, const Container::Size2& position = {0, 0}):
m_size{size},
m_position{position}
{}
[[nodiscard]] friend constexpr auto operator==(const Viewport&, const Viewport&) noexcept -> bool = default;
[[nodiscard]] inline constexpr auto getSize() const noexcept -> Container::Size2
{
return m_size;
}
[[nodiscard]] inline constexpr auto getPosition() const noexcept -> Container::Size2
{
return m_position;
}
[[nodiscard]] inline constexpr auto getTopLeft() const noexcept -> Container::Size2
{
return m_position;
}
[[nodiscard]] inline constexpr auto getBottomRight() const noexcept -> Container::Size2
{
return {m_position.x() + m_size.width() - 1, m_position.y() + m_size.height() - 1};
}
[[nodiscard]] inline constexpr auto contains(const Container::Size2& point) const noexcept -> bool
{
auto topLeft = getTopLeft();
auto bottomRight = getBottomRight();
return Math::isBetween(point.x(), topLeft.x(), bottomRight.x()) and Math::isBetween(point.y(), topLeft.y(), bottomRight.y());
}
[[nodiscard]] inline constexpr auto contains(const Viewport& viewport) const noexcept -> bool
{
return contains(viewport.getTopLeft()) and contains(viewport.getBottomRight());
}
[[nodiscard]] static inline constexpr auto intersection(const Viewport& lhs, const Viewport& rhs) noexcept -> Viewport
{
const auto x1 = std::max(lhs.getPosition().x(), rhs.getPosition().x());
const auto y1 = std::max(lhs.getPosition().y(), rhs.getPosition().y());
const auto x2 = std::min(lhs.getPosition().x() + lhs.getSize().width(), rhs.getPosition().x() + rhs.getSize().width());
const auto y2 = std::min(lhs.getPosition().y() + lhs.getSize().height(), rhs.getPosition().y() + rhs.getSize().height());
if (x1 < x2 and y1 < y2)
return Viewport{{x2 - x1, y2 - y1}, {x1, y1}};
return Viewport{{0, 0}, {0, 0}};
}
inline auto forEach(auto&& function) const noexcept -> void
{
for (auto y = 0uz; y < m_size.height(); ++y)
for (auto x = 0uz; x < m_size.width(); ++x)
function(Container::Size2{m_position.x() + x, m_position.y() + y});
}
private:
Container::Size2 m_size, m_position;
};
static_assert(Viewport::intersection(Viewport{{10, 10}, {0, 0}}, Viewport{{10, 10}, {5, 5}}) == Viewport{{5, 5}, {5, 5}});
static_assert(Viewport::intersection(Viewport{{10, 10}, {0, 0}}, Viewport{{10, 10}, {10, 10}}) == Viewport{{0, 0}, {0, 0}});
[[nodiscard]] inline auto operator+(const Viewport& lhs, const Viewport& rhs) noexcept -> Viewport
{
return Viewport{lhs.getSize() + rhs.getSize(), lhs.getPosition() + rhs.getPosition()};
}
[[nodiscard]] inline auto operator-(const Viewport& lhs, const Viewport& rhs) noexcept -> Viewport
{
return Viewport{lhs.getSize() - rhs.getSize(), lhs.getPosition() - rhs.getPosition()};
}
}