diff --git a/src/common/RasterGeometry.h b/src/common/RasterGeometry.h index b2cee21d1..1916ee75f 100644 --- a/src/common/RasterGeometry.h +++ b/src/common/RasterGeometry.h @@ -121,44 +121,44 @@ void RasterizeEllipseRows(Vec2 radiusSquared, F f) } // Call f for every point on the boundary of the indicated rectangle (so that -// TopLeft and BottomRight are both corners). +// pos and BottomRight are both corners). template void RasterizeRect(Rect rect, F f) { - for (int x = rect.TopLeft.X; x <= rect.BottomRight.X; x++) - f(Vec2(x, rect.TopLeft.Y)); + for (int x = rect.pos.X; x < rect.pos.X + rect.size.X; x++) + f(Vec2(x, rect.pos.Y)); - if (rect.TopLeft.Y != rect.BottomRight.Y) - for (int x = rect.TopLeft.X; x <= rect.BottomRight.X; x++) - f(Vec2(x, rect.BottomRight.Y)); + if (rect.pos.Y != rect.pos.Y + rect.size.Y - 1) + for (int x = rect.pos.X; x < rect.pos.X + rect.size.X; x++) + f(Vec2(x, rect.pos.Y + rect.size.Y - 1)); // corners already drawn - for (int y = rect.TopLeft.Y + 1; y <= rect.BottomRight.Y - 1; y++) - f(Vec2(rect.TopLeft.X, y)); + for (int y = rect.pos.Y + 1; y < rect.pos.Y + rect.size.Y - 1; y++) + f(Vec2(rect.pos.X, y)); - if (rect.TopLeft.X != rect.BottomRight.X) - for (int y = rect.TopLeft.Y + 1; y <= rect.BottomRight.Y - 1; y++) - f(Vec2(rect.BottomRight.X, y)); + if (rect.pos.X != rect.pos.X + rect.size.X - 1) + for (int y = rect.pos.Y + 1; y < rect.pos.Y + rect.size.Y - 1; y++) + f(Vec2(rect.pos.X + rect.size.X - 1, y)); } // Call f for every point on the dotted boundary of the indicated rectangle. template void RasterizeDottedRect(Rect rect, F f) { - for (int x = rect.TopLeft.X; x <= rect.BottomRight.X; x += 2) - f(Vec2(x, rect.TopLeft.Y)); + for (int x = rect.pos.X; x < rect.pos.X + rect.size.X; x += 2) + f(Vec2(x, rect.pos.Y)); - int bottomOff = (rect.BottomRight.Y - rect.TopLeft.Y) % 2; - if (rect.TopLeft.Y != rect.BottomRight.Y) - for (int x = rect.TopLeft.X + bottomOff; x <= rect.BottomRight.X; x += 2) - f(Vec2(x, rect.BottomRight.Y)); + int bottomOff = (rect.pos.Y + rect.size.Y - 1 - rect.pos.Y) % 2; + if (rect.pos.Y != rect.pos.Y + rect.size.Y - 1) + for (int x = rect.pos.X + bottomOff; x < rect.pos.X + rect.size.X; x += 2) + f(Vec2(x, rect.pos.Y + rect.size.Y - 1)); // corners already drawn - for (int y = rect.TopLeft.Y + 1 + 1; y <= rect.BottomRight.Y - 1; y += 2) - f(Vec2(rect.TopLeft.X, y)); + for (int y = rect.pos.Y + 1 + 1; y < rect.pos.Y + rect.size.Y - 1; y += 2) + f(Vec2(rect.pos.X, y)); - int leftOff = (rect.BottomRight.X - rect.TopLeft.X + 1) % 2; - if (rect.TopLeft.X != rect.BottomRight.X) - for (int y = rect.TopLeft.Y + 1 + leftOff; y <= rect.BottomRight.Y - 1; y += 2) - f(Vec2(rect.BottomRight.X, y)); + int leftOff = (rect.pos.X + rect.size.X - 1 - rect.pos.X + 1) % 2; + if (rect.pos.X != rect.pos.X + rect.size.X - 1) + for (int y = rect.pos.Y + 1 + leftOff; y < rect.pos.Y + rect.size.Y - 1; y += 2) + f(Vec2(rect.pos.X + rect.size.X - 1, y)); } diff --git a/src/common/Vec2.h b/src/common/Vec2.h index aee87b7c6..34133f785 100644 --- a/src/common/Vec2.h +++ b/src/common/Vec2.h @@ -107,8 +107,8 @@ struct Vec2 Vec2 Clamp(Rect rect) const { return Vec2( - std::clamp(X, rect.TopLeft.X, rect.BottomRight.X), - std::clamp(Y, rect.TopLeft.Y, rect.BottomRight.Y) + std::clamp(X, rect.pos.X, rect.pos.X + rect.size.X - T(1)), + std::clamp(Y, rect.pos.Y, rect.pos.Y + rect.size.Y - T(1)) ); } @@ -185,8 +185,8 @@ Mat2 const Mat2::MirrorY = Mat2(1, 0, 0, -1); template Mat2 const Mat2::CCW = Mat2(0, 1, -1, 0); // reminder: the Y axis points down -template>> -constexpr static inline Rect RectBetween(Vec2, Vec2); +template>> +constexpr static inline Rect RectSized(Vec2, Vec2); enum IterationDirection { @@ -200,16 +200,15 @@ template struct Rect { // Inclusive - Vec2 TopLeft, BottomRight; + Vec2 pos, size; -private: - constexpr Rect(Vec2 topLeft, Vec2 bottomRight): - TopLeft(topLeft), - BottomRight(bottomRight) + constexpr Rect(Vec2 newPos, Vec2 newSize): + pos(newPos), + size(newSize) { } - friend constexpr Rect RectBetween(Vec2, Vec2); +private: struct end_sentinel {}; @@ -350,48 +349,25 @@ private: public: constexpr bool operator==(Rect other) const { - return TopLeft == other.TopLeft && BottomRight == other.BottomRight; + return pos == other.pos && size == other.size; } constexpr bool operator!=(Rect other) const { - return TopLeft != other.TopLeft || BottomRight != other.BottomRight; + return pos != other.pos || size != other.size; } constexpr explicit operator bool() const { - return BottomRight.X >= TopLeft.X && BottomRight.Y >= TopLeft.Y; - } - - // Return the smallest rectangle that contains both input rectangles, - // **assuming neither are empty** - Rect operator|(Rect other) const - { - return Rect( - Vec2(std::min(TopLeft.X, other.TopLeft.X), std::min(TopLeft.Y, other.TopLeft.Y)), - Vec2(std::max(BottomRight.X, other.BottomRight.X), std::max(BottomRight.Y, other.BottomRight.Y)) - ); + return size.X > 0 && size.Y > 0; } // Return the intersection of two rectangles (possibly empty) Rect operator&(Rect other) const { - auto rect = Rect( - Vec2(std::max(TopLeft.X, other.TopLeft.X), std::max(TopLeft.Y, other.TopLeft.Y)), - Vec2(std::min(BottomRight.X, other.BottomRight.X), std::min(BottomRight.Y, other.BottomRight.Y)) - ); - return Rect( - rect.TopLeft, - Vec2( - std::max(rect.TopLeft.X - 1, rect.BottomRight.X), - std::max(rect.TopLeft.Y - 1, rect.BottomRight.Y) - ) - ); - } - - inline Rect &operator|=(Rect other) - { - return *this = *this | other; + auto tl = Vec2(std::max(pos.X , other.pos.X ), std::max(pos.Y , other.pos.Y )); + auto br1 = Vec2(std::min(pos.X + size.X, other.pos.X + other.size.X), std::min(pos.Y + size.Y, other.pos.Y + other.size.Y)); + return Rect(tl, br1 - tl); } inline Rect &operator&=(Rect other) @@ -401,19 +377,13 @@ public: constexpr bool Contains(Vec2 point) const { - return point.X >= TopLeft.X && point.X <= BottomRight.X && point.Y >= TopLeft.Y && point.Y <= BottomRight.Y; - } - - template>> - inline Vec2 Size() const - { - return BottomRight - TopLeft + Vec2(1, 1); + return point.X >= pos.X && point.X < pos.X + size.X && point.Y >= pos.Y && point.Y < pos.Y + size.Y; } template Rect() + std::declval())> Inset(S delta) const { - return Rect() + std::declval())>(TopLeft + Vec2(delta, delta), BottomRight - Vec2(delta, delta)); + return Rect() + std::declval())>(pos + Vec2(delta, delta), size - Vec2(delta, delta) * S(2)); } template>> @@ -426,10 +396,10 @@ public: ); if constexpr (D1 == TOP_TO_BOTTOM || D1 == BOTTOM_TO_TOP) { - return range_row_major{TopLeft.X, TopLeft.Y, BottomRight.X, BottomRight.Y}; + return range_row_major{pos.X, pos.Y, pos.X + size.X - T(1), pos.Y + size.Y - T(1)}; } else - return range_column_major{TopLeft.X, TopLeft.Y, BottomRight.X, BottomRight.Y}; + return range_column_major{pos.X, pos.Y, pos.X + size.X - T(1), pos.Y + size.Y - T(1)}; } // Use when the order isn't important @@ -445,19 +415,19 @@ public: }; template +constexpr inline Rect RectSized(Vec2 pos, Vec2 size) +{ + return Rect(pos, size); +} + +template>> constexpr inline Rect RectBetween(Vec2 topLeft, Vec2 bottomRight) { - return Rect(topLeft, bottomRight); + return RectSized(topLeft, bottomRight - topLeft + Vec2(1, 1)); } template>> constexpr inline Rect RectAt(Vec2 pos) { - return RectBetween(pos, pos); -} - -template>> -constexpr inline Rect RectSized(Vec2 topLeft, Vec2 dimen) -{ - return RectBetween(topLeft, topLeft + dimen - Vec2(1, 1)); + return RectSized(pos, Vec2(1, 1)); } diff --git a/src/graphics/Graphics.cpp b/src/graphics/Graphics.cpp index 8e3036508..aa8ff287f 100644 --- a/src/graphics/Graphics.cpp +++ b/src/graphics/Graphics.cpp @@ -36,10 +36,10 @@ void VideoBuffer::Crop(Rect rect) if (rect == Size().OriginRect()) return; - PlaneAdapter &> newVideo(rect.Size(), std::in_place, video.Base); + PlaneAdapter &> newVideo(rect.size, std::in_place, video.Base); for (auto y = 0; y < newVideo.Size().Y; y++) std::copy_n( - video.RowIterator(rect.TopLeft + Vec2(0, y)), + video.RowIterator(rect.pos + Vec2(0, y)), newVideo.Size().X, newVideo.RowIterator(Vec2(0, y)) ); diff --git a/src/graphics/RasterDrawMethodsImpl.h b/src/graphics/RasterDrawMethodsImpl.h index 5fe5b5492..509f9d596 100644 --- a/src/graphics/RasterDrawMethodsImpl.h +++ b/src/graphics/RasterDrawMethodsImpl.h @@ -135,8 +135,8 @@ void RasterDrawMethods::DrawFilledRect(Rect rect, RGB col pixel packed = colour.Pack(); auto &video = static_cast(*this).video; if (rect) - for (int y = rect.TopLeft.Y; y <= rect.BottomRight.Y; y++) - std::fill_n(video.RowIterator(Vec2(rect.TopLeft.X, y)), rect.Size().X, packed); + for (int y = rect.pos.Y; y < rect.pos.Y + rect.size.Y; y++) + std::fill_n(video.RowIterator(Vec2(rect.pos.X, y)), rect.size.X, packed); } template @@ -166,22 +166,22 @@ void RasterDrawMethods::BlendFilledEllipse(Vec2 center, Vec2 template void RasterDrawMethods::BlendImage(pixel const *data, uint8_t alpha, Rect rect) { - BlendImage(data, alpha, rect, rect.Size().X); + BlendImage(data, alpha, rect, rect.size.X); } template void RasterDrawMethods::BlendImage(pixel const *data, uint8_t alpha, Rect rect, size_t rowStride) { - auto origin = rect.TopLeft; + auto origin = rect.pos; rect &= clipRect(); if (alpha == 0xFF) { auto &video = static_cast(*this).video; - for (int y = rect.TopLeft.Y; y <= rect.BottomRight.Y; y++) + for (int y = rect.pos.Y; y < rect.pos.Y + rect.size.Y; y++) std::copy_n( - data + (rect.TopLeft.X - origin.X) + (y - origin.Y) * rowStride, - rect.Size().X, - video.RowIterator(Vec2(rect.TopLeft.X, y)) + data + (rect.pos.X - origin.X) + (y - origin.Y) * rowStride, + rect.size.X, + video.RowIterator(Vec2(rect.pos.X, y)) ); } else @@ -197,13 +197,13 @@ void RasterDrawMethods::BlendImage(pixel const *data, uint8_t alpha, Re template void RasterDrawMethods::XorImage(unsigned char const *data, Rect rect) { - XorImage(data, rect, rect.Size().X); + XorImage(data, rect, rect.size.X); } template void RasterDrawMethods::XorImage(unsigned char const *data, Rect rect, size_t rowStride) { - auto origin = rect.TopLeft; + auto origin = rect.pos; rect &= clipRect(); for (auto pos : rect) if (data[(pos.X - origin.X) + (pos.Y - origin.Y) * rowStride]) @@ -213,13 +213,13 @@ void RasterDrawMethods::XorImage(unsigned char const *data, Rect r template void RasterDrawMethods::BlendRGBAImage(pixel_rgba const *data, Rect rect) { - BlendRGBAImage(data, rect, rect.Size().X); + BlendRGBAImage(data, rect, rect.size.X); } template void RasterDrawMethods::BlendRGBAImage(pixel_rgba const *data, Rect rect, size_t rowStride) { - auto origin = rect.TopLeft; + auto origin = rect.pos; rect &= clipRect(); for (auto pos : rect) { diff --git a/src/gui/game/ToolButton.cpp b/src/gui/game/ToolButton.cpp index 1e703f231..0b24349d9 100644 --- a/src/gui/game/ToolButton.cpp +++ b/src/gui/game/ToolButton.cpp @@ -50,7 +50,7 @@ void ToolButton::Draw(const ui::Point& screenPos) { Graphics * g = GetGraphics(); auto rect = ClipRect; - if (ClipRect.Size().X && ClipRect.Size().Y) + if (ClipRect.size.X && ClipRect.size.Y) g->SwapClipRect(rect); // old cliprect is now in rect int totalColour = Appearance.BackgroundInactive.Blue + (3*Appearance.BackgroundInactive.Green) + (2*Appearance.BackgroundInactive.Red); @@ -87,7 +87,7 @@ void ToolButton::Draw(const ui::Point& screenPos) g->BlendText(screenPos + textPosition, buttonDisplayText, 0x000000_rgb .WithAlpha(255)); } - if (ClipRect.Size().X && ClipRect.Size().Y) + if (ClipRect.size.X && ClipRect.size.Y) g->SwapClipRect(rect); // apply old clip rect } diff --git a/src/gui/interface/Panel.cpp b/src/gui/interface/Panel.cpp index 36e26f342..f49e29a30 100644 --- a/src/gui/interface/Panel.cpp +++ b/src/gui/interface/Panel.cpp @@ -80,7 +80,7 @@ void Panel::Draw(const Point& screenPos) //check if the component is in the screen, draw if it is if (rect & Size.OriginRect()) { - child->Draw(screenPos + rect.TopLeft); + child->Draw(screenPos + rect.pos); } } diff --git a/src/gui/interface/ProgressBar.cpp b/src/gui/interface/ProgressBar.cpp index e9c1b1052..c29c30cd6 100644 --- a/src/gui/interface/ProgressBar.cpp +++ b/src/gui/interface/ProgressBar.cpp @@ -46,7 +46,7 @@ void ProgressBar::Draw(const Point &screenPos) g->DrawRect(RectSized(screenPos, Size), 0xFFFFFF_rgb); auto inner = RectSized(screenPos + Vec2{ 2, 2 }, Size - Vec2{ 4, 4 }); auto drawContent = [this, screenPos, g, inner](int beginX, int endX, ui::Colour bgColour, ui::Colour textColour) { - auto clip = RectSized(inner.TopLeft + Vec2{ beginX, 0 }, Vec2{ endX - beginX, inner.Size().Y }) & g->GetClipRect(); + auto clip = RectSized(inner.pos + Vec2{ beginX, 0 }, Vec2{ endX - beginX, inner.size.Y }) & g->GetClipRect(); g->SwapClipRect(clip); if (bgColour.Alpha) { @@ -58,18 +58,18 @@ void ProgressBar::Draw(const Point &screenPos) }, progressStatus, textColour); g->SwapClipRect(clip); }; - drawContent(0, inner.Size().X, 0x000000_rgb .WithAlpha(0), 0xFFFFFF_rgb .WithAlpha(255)); + drawContent(0, inner.size.X, 0x000000_rgb .WithAlpha(0), 0xFFFFFF_rgb .WithAlpha(255)); if (progress == -1) { constexpr auto size = 40; - auto pos = int(inner.Size().X * intermediatePos / 100); + auto pos = int(inner.size.X * intermediatePos / 100); drawContent(pos, pos + size, style::Colour::WarningTitle, 0x000000_rgb .WithAlpha(255)); - pos -= inner.Size().X; + pos -= inner.size.X; drawContent(pos, pos + size, style::Colour::WarningTitle, 0x000000_rgb .WithAlpha(255)); } else { - drawContent(0, inner.Size().X * progress / 100, style::Colour::WarningTitle, 0x000000_rgb .WithAlpha(255)); + drawContent(0, inner.size.X * progress / 100, style::Colour::WarningTitle, 0x000000_rgb .WithAlpha(255)); } } diff --git a/src/gui/interface/Window.cpp b/src/gui/interface/Window.cpp index cb8534986..8de1a0e24 100644 --- a/src/gui/interface/Window.cpp +++ b/src/gui/interface/Window.cpp @@ -189,7 +189,7 @@ void Window::DoDraw() { auto rect = RectSized(Position + child->Position, child->Size); if (AllowExclusiveDrawing || bool(rect & GetGraphics()->Size().OriginRect())) - child->Draw(rect.TopLeft); + child->Draw(rect.pos); } }; for (auto child : Components) diff --git a/src/lua/LuaGraphics.cpp b/src/lua/LuaGraphics.cpp index f6c746824..aaf2f0a21 100644 --- a/src/lua/LuaGraphics.cpp +++ b/src/lua/LuaGraphics.cpp @@ -261,10 +261,10 @@ static int setClipRect(lua_State *L) int h = luaL_optinteger(L, 4, WINDOWH); auto rect = RectSized(Vec2(x, y), Vec2(w, h)); lsi->g->SwapClipRect(rect); - lua_pushinteger(L, rect.TopLeft.X); - lua_pushinteger(L, rect.TopLeft.Y); - lua_pushinteger(L, rect.Size().X); - lua_pushinteger(L, rect.Size().Y); + lua_pushinteger(L, rect.pos.X); + lua_pushinteger(L, rect.pos.Y); + lua_pushinteger(L, rect.size.X); + lua_pushinteger(L, rect.size.Y); return 4; } diff --git a/src/simulation/Editing.cpp b/src/simulation/Editing.cpp index 1bd8d4ccd..e2ea0ceda 100644 --- a/src/simulation/Editing.cpp +++ b/src/simulation/Editing.cpp @@ -85,10 +85,10 @@ void Simulation::Restore(const Snapshot &snap) void Simulation::clear_area(int area_x, int area_y, int area_w, int area_h) { auto intersection = RES.OriginRect() & RectSized(Vec2{ area_x, area_y }, Vec2{ area_w, area_h }); - area_x = intersection.TopLeft.X; - area_y = intersection.TopLeft.Y; - area_w = intersection.Size().X; - area_h = intersection.Size().Y; + area_x = intersection.pos.X; + area_y = intersection.pos.Y; + area_w = intersection.size.X; + area_h = intersection.size.Y; float fx = area_x-.5f, fy = area_y-.5f; for (int i = 0; i <= parts_lastActiveIndex; i++) { diff --git a/src/simulation/Simulation.cpp b/src/simulation/Simulation.cpp index c3507daaa..2b9b43444 100644 --- a/src/simulation/Simulation.cpp +++ b/src/simulation/Simulation.cpp @@ -53,20 +53,20 @@ void Simulation::Load(const GameSave *save, bool includePressure, Vec2 bloc std::sort(existingParticles.begin(), existingParticles.end(), [](const auto &lhs, const auto &rhs) { return std::tie(lhs.pos.Y, lhs.pos.X) < std::tie(rhs.pos.Y, rhs.pos.X); }); - PlaneAdapter> existingParticleIndices(pasteArea.Size(), existingParticles.size()); + PlaneAdapter> existingParticleIndices(pasteArea.size, existingParticles.size()); { auto lastPos = Vec2{ -1, -1 }; // not a valid pos in existingParticles for (auto it = existingParticles.begin(); it != existingParticles.end(); ++it) { if (lastPos != it->pos) { - existingParticleIndices[it->pos - pasteArea.TopLeft] = it - existingParticles.begin(); + existingParticleIndices[it->pos - pasteArea.pos] = it - existingParticles.begin(); lastPos = it->pos; } } } auto removeExistingParticles = [this, pasteArea, &existingParticles, &existingParticleIndices](Vec2 p) { - auto rp = p - pasteArea.TopLeft; + auto rp = p - pasteArea.pos; if (existingParticleIndices.Size().OriginRect().Contains(rp)) { auto index = existingParticleIndices[rp]; @@ -312,10 +312,10 @@ void Simulation::Load(const GameSave *save, bool includePressure, Vec2 bloc std::unique_ptr Simulation::Save(bool includePressure, Rect partR) // particle coordinates { - auto blockR = RectBetween(partR.TopLeft / CELL, partR.BottomRight / CELL); - auto blockP = blockR.TopLeft; + auto blockR = RectSized(partR.pos / CELL, partR.size / CELL); + auto blockP = blockR.pos; - auto newSave = std::make_unique(blockR.Size()); + auto newSave = std::make_unique(blockR.size); newSave->frameCount = frameCount; newSave->rngState = rng.state();