1/*
2 * LegacyClonk
3 *
4 * Copyright (c) 1998-2000, Matthes Bender (RedWolf Design)
5 * Copyright (c) 2017-2020, The LegacyClonk Team and contributors
6 *
7 * Distributed under the terms of the ISC license; see accompanying file
8 * "COPYING" for details.
9 *
10 * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11 * See accompanying file "TRADEMARK" for details.
12 *
13 * To redistribute this file separately, substitute the full license texts
14 * for the above references.
15 */
16
17/* Basic classes for rectangles */
18
19#pragma once
20
21#include "C4ForwardDeclarations.h"
22
23#include <cstddef>
24#include <cstdint>
25#include <vector>
26
27class C4Rect
28{
29public:
30 int32_t x, y, Wdt, Hgt;
31
32public:
33 void Set(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt);
34 void Default();
35 bool Overlap(C4Rect &rTarget);
36 void Intersect(const C4Rect &r2);
37 void Add(const C4Rect &r2);
38 bool operator==(const C4Rect &r2) const { return !((x - r2.x) | (y - r2.y) | (Wdt - r2.Wdt) | (Hgt - r2.Hgt)); }
39
40 bool Contains(int32_t iX, int32_t iY)
41 {
42 return iX >= x && iX < x + Wdt && iY >= y && iY < y + Hgt;
43 }
44
45 bool Contains(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt)
46 {
47 return iX >= x && iX + iWdt < x + Wdt && iY >= y && iY + iHgt < y + Hgt;
48 }
49
50 bool Contains(const C4Rect &rect)
51 {
52 return Contains(iX: rect.x, iY: rect.y, iWdt: rect.Wdt, iHgt: rect.Hgt);
53 }
54
55 bool IntersectsLine(int32_t iX, int32_t iY, int32_t iX2, int32_t iY2);
56
57 void Normalize()
58 {
59 if (Wdt < 0) { x += Wdt + 1; Wdt = -Wdt; } if (Hgt < 0) { y += Hgt + 1; Hgt = -Hgt; }
60 }
61
62 void Enlarge(int32_t iBy)
63 {
64 x -= iBy; y -= iBy; Wdt += 2 * iBy; Hgt += 2 * iBy;
65 }
66
67 int32_t GetMiddleX() { return x + Wdt / 2; }
68 int32_t GetMiddleY() { return y + Hgt / 2; }
69 int32_t GetBottom() { return y + Hgt; }
70
71 constexpr C4Rect(int32_t tx, int32_t ty, int32_t twdt, int32_t thgt)
72 {
73 x = tx; y = ty; Wdt = twdt; Hgt = thgt;
74 }
75
76 constexpr C4Rect() = default; // default ctor; doesn't initialize
77
78 C4Rect Scaled(float scale) const noexcept;
79
80 void CompileFunc(StdCompiler *pComp);
81};
82
83class C4TargetRect : public C4Rect
84{
85public:
86 int32_t tx, ty;
87
88public:
89 C4TargetRect(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, int32_t iTX, int32_t iTY)
90 : C4Rect(iX, iY, iWdt, iHgt), tx(iTX), ty(iTY) {}
91 C4TargetRect() {} // default ctor; doesn't initialize
92 void Set(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, int32_t iTX, int32_t iTY);
93 void Default();
94 bool ClipBy(C4TargetRect &rClip); // clip this rectangle by the given one (adding target positions) - return false if they don't overlap
95
96 void CompileFunc(StdCompiler *pComp);
97};
98
99const C4Rect Rect0(0, 0, 0, 0);
100const C4TargetRect TargetRect0(0, 0, 0, 0, 0, 0);
101
102// a bunch of rectangles
103// rects NOT including pos+size-point
104class C4RectList : public std::vector<C4Rect>
105{
106public:
107 void AddRect(const C4Rect &rNewRect)
108 {
109 push_back(x: rNewRect);
110 }
111
112 void RemoveIndexedRect(size_t idx)
113 {
114 if (idx < GetCount() - 1) Get(idx) = Get(idx: GetCount() - 1); pop_back();
115 }
116
117 void Clear() { clear(); }
118 size_t GetCount() const { return size(); }
119 C4Rect &Get(size_t idx) { return (*this)[idx]; } // access w/o range check
120
121 void ClipByRect(const C4Rect &rClip); // split up rectangles
122};
123