| 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 | |
| 27 | class C4Rect |
| 28 | { |
| 29 | public: |
| 30 | int32_t x, y, Wdt, Hgt; |
| 31 | |
| 32 | public: |
| 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 | |
| 83 | class C4TargetRect : public C4Rect |
| 84 | { |
| 85 | public: |
| 86 | int32_t tx, ty; |
| 87 | |
| 88 | public: |
| 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 | |
| 99 | const C4Rect Rect0(0, 0, 0, 0); |
| 100 | const C4TargetRect TargetRect0(0, 0, 0, 0, 0, 0); |
| 101 | |
| 102 | // a bunch of rectangles |
| 103 | // rects NOT including pos+size-point |
| 104 | class C4RectList : public std::vector<C4Rect> |
| 105 | { |
| 106 | public: |
| 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 | |