diff --git a/src/SimulationConfig.h b/src/SimulationConfig.h index 4c39bcc88..f432de36d 100644 --- a/src/SimulationConfig.h +++ b/src/SimulationConfig.h @@ -9,21 +9,23 @@ constexpr float M_GRAV = 6.67300e-1f; //CELL, the size of the pressure, gravity, and wall maps. Larger than 1 to prevent extreme lag constexpr int CELL = 4; -constexpr int XCELLS = 153; -constexpr int YCELLS = 96; + +constexpr auto CELLS = Vec2(153, 96); +constexpr int XCELLS = CELLS.X; +constexpr int YCELLS = CELLS.Y; constexpr int NCELL = XCELLS * YCELLS; -constexpr Rect CELLS = Rect(Vec2(0, 0), Vec2(XCELLS - 1, YCELLS - 1)); -constexpr int XRES = XCELLS * CELL; -constexpr int YRES = YCELLS * CELL; + +constexpr auto RES = CELLS * CELL; +constexpr int XRES = RES.X; +constexpr int YRES = RES.Y; constexpr int NPART = XRES * YRES; -constexpr Rect RES = Rect(Vec2(0, 0), Vec2(XRES - 1, YRES - 1)); constexpr int XCNTR = XRES / 2; constexpr int YCNTR = YRES / 2; -constexpr int WINDOWW = XRES + BARSIZE; -constexpr int WINDOWH = YRES + MENUSIZE; -constexpr Rect WINDOW = Rect(Vec2(0, 0), Vec2(WINDOWW - 1, WINDOWH - 1)); +constexpr auto WINDOW = RES + Vec2(BARSIZE, MENUSIZE); +constexpr int WINDOWW = WINDOW.X; +constexpr int WINDOWH = WINDOW.Y; constexpr int MAXSIGNS = 16; diff --git a/src/client/GameSave.cpp b/src/client/GameSave.cpp index 837562cb4..0b59b4042 100644 --- a/src/client/GameSave.cpp +++ b/src/client/GameSave.cpp @@ -122,16 +122,16 @@ inline Vec2 lroundNegInf(Vec2 v) Vec2 GameSave::Translate(Vec2 translate) { - auto bounds = Rect(Vec2::Zero); + auto bounds = RectAt(Vec2::Zero); // determine minimum and maximum position of all particles / signs for (auto &sign : signs) - bounds |= Rect(roundNegInf(Vec2(sign.x, sign.y) + translate)); + bounds |= RectAt(roundNegInf(Vec2(sign.x, sign.y) + translate)); for (int i = 0; i < particlesCount; i++) { if (!particles[i].type) continue; - bounds |= Rect(roundNegInf(Vec2(particles[i].x, particles[i].y) + translate)); + bounds |= RectAt(roundNegInf(Vec2(particles[i].x, particles[i].y) + translate)); } // determine whether corrections are needed. If moving in this direction would delete stuff, expand the save auto backCorrection = Vec2( @@ -171,12 +171,12 @@ void GameSave::Transform(Mat2 transform, Vec2 translate) Vec2(blockDimen.X * CELL - 1, blockDimen.Y * CELL - 1), }; // undo any translation caused by rotation - auto bounds = Rect(transform * cornerso[0]); + auto bounds = RectAt(transform * cornerso[0]); for (int i = 1; i < 4; i++) - bounds |= Rect(transform * cornerso[i]); + bounds |= RectAt(transform * cornerso[i]); Vec2 translateReal = translate; translate -= bounds.TopLeft; - auto newBounds = bounds.BottomRight - bounds.TopLeft + Vec2(1, 1); + auto newBounds = bounds.Size(); Transform(transform, translate, translateReal, newBounds); } @@ -204,7 +204,7 @@ void GameSave::Transform(Mat2 transform, Vec2 translate, Vec2 tra bool patchPipeV = transform == Mat2::MirrorY; // rotate and translate signs, parts, walls - auto bounds = Rect(Vec2::Zero, newDimen - Vec2(1, 1)); + auto bounds = newDimen.OriginRect(); for (auto &sign : signs) { auto pos = transform * Vec2(sign.x, sign.y) + translate; @@ -266,7 +266,7 @@ void GameSave::Transform(Mat2 transform, Vec2 translate, Vec2 tra || (translated.Y > 0 && (int)translated.Y%CELL == 0))) blockTranslate.Y = -CELL; - auto blockBounds = Rect(Vec2::Zero, newBlockDimen - Vec2(1, 1)); + auto blockBounds = newBlockDimen.OriginRect(); for (int y=0; y &rect) { - int newX = x; - int newY = y; - int newW = w; - int newH = h; - if (newX < 0) newX = 0; - if (newY < 0) newY = 0; - if (newW > WINDOWW - newX) newW = WINDOWW - newX; - if (newH > WINDOWH - newY) newH = WINDOWH - newY; - x = clipx1; - y = clipy1; - w = clipx2 - clipx1; - h = clipy2 - clipy1; - clipx1 = newX; - clipy1 = newY; - clipx2 = newX + newW; - clipy2 = newY + newH; + auto newRect = RectBetween(WINDOW.OriginRect().Clamp(rect.TopLeft), WINDOW.OriginRect().Clamp(rect.BottomRight)); + rect = clip; + clip = newRect; } bool VideoBuffer::WritePNG(const ByteString &path) const diff --git a/src/graphics/Graphics.h b/src/graphics/Graphics.h index d6db6380a..7610c050a 100644 --- a/src/graphics/Graphics.h +++ b/src/graphics/Graphics.h @@ -1,4 +1,5 @@ #pragma once +#include "common/Geometry.h" #include "common/String.h" #include "common/tpt-inline.h" #include "Pixel.h" @@ -68,10 +69,7 @@ public: class Graphics { - int clipx1; - int clipy1; - int clipx2; - int clipy2; + Rect clip; public: pixel *vid; @@ -131,7 +129,7 @@ public: Graphics(); ~Graphics(); - void SetClipRect(int &x, int &y, int &w, int &h); + void SetClipRect(Rect &); }; bool PngDataToPixels(std::vector &imageData, int &imgw, int &imgh, const char *pngData, size_t pngDataSize, bool addBackground); diff --git a/src/graphics/Pixel.h b/src/graphics/Pixel.h index fb78bafef..5224069e9 100644 --- a/src/graphics/Pixel.h +++ b/src/graphics/Pixel.h @@ -1,6 +1,9 @@ #pragma once +#include +#include +#include -typedef unsigned int pixel; +typedef uint32_t pixel; constexpr int PIXELCHANNELS = 3; constexpr int PIXELSIZE = 4; @@ -24,3 +27,30 @@ constexpr int PIXB(pixel x) { return x & 0xFF; } + +template, void>> +struct RGB +{ + T Red, Green, Blue; + + constexpr RGB(T r, T g, T b): + Red(r), + Green(g), + Blue(b) + { + } +}; + +template, void>> +struct RGBA +{ + T Red, Green, Blue, Alpha; + + constexpr RGBA(T r, T g, T b, T a = std::numeric_limits::max()): + Red(r), + Green(g), + Blue(b), + Alpha(a) + { + } +}; diff --git a/src/graphics/RasterDrawMethods.inl b/src/graphics/RasterDrawMethods.inl index c4f35154b..d57dc7df9 100644 --- a/src/graphics/RasterDrawMethods.inl +++ b/src/graphics/RasterDrawMethods.inl @@ -117,9 +117,9 @@ TPT_INLINE void PIXELMETHODS_CLASS::xor_pixel(int x, int y) { int c; #ifdef DO_CLIPCHECK - if (x=clipx2 || y>=clipy2) + if (!clip.Contains(Vec2(x, y))) #else - if (x<0 || y<0 || x>=VIDXRES || y>=VIDYRES) + if (!VIDRES.OriginRect().Contains(Vec2(x, y))) #endif return; c = vid[y*(VIDXRES)+x]; @@ -134,9 +134,9 @@ void PIXELMETHODS_CLASS::blendpixel(int x, int y, int r, int g, int b, int a) { pixel t; #ifdef DO_CLIPCHECK - if (x=clipx2 || y>=clipy2) + if (!clip.Contains(Vec2(x, y))) #else - if (x<0 || y<0 || x>=VIDXRES || y>=VIDYRES) + if (!VIDRES.OriginRect().Contains(Vec2(x, y))) #endif return; if (a!=255) @@ -153,9 +153,9 @@ void PIXELMETHODS_CLASS::addpixel(int x, int y, int r, int g, int b, int a) { pixel t; #ifdef DO_CLIPCHECK - if (x=clipx2 || y>=clipy2) + if (!clip.Contains(Vec2(x, y))) #else - if (x<0 || y<0 || x>=VIDXRES || y>=VIDYRES) + if (!VIDRES.OriginRect().Contains(Vec2(x, y))) #endif return; t = vid[y*(VIDXRES)+x]; @@ -401,32 +401,15 @@ void PIXELMETHODS_CLASS::clearrect(int x, int y, int w, int h) h -= 1; #ifdef DO_CLIPCHECK - if (x+w > clipx2) w = clipx2-x; - if (y+h > clipy2) h = clipy2-y; - if (x(x, y), Vec2(w, h))); #else - if (x+w > VIDXRES) w = VIDXRES-x; - if (y+h > VIDYRES) h = VIDYRES-y; - if (x<0) - { - w += x; - x = 0; - } - if (y<0) - { - h += y; - y = 0; - } + auto rect = VIDRES.OriginRect().Clamp(RectSized(Vec2(x, y), Vec2(w, h))); #endif + x = rect.TopLeft.X; + y = rect.TopLeft.Y; + w = rect.Size().X; + h = rect.Size().Y; + if (w<0 || h<0) return; @@ -468,9 +451,9 @@ void PIXELMETHODS_CLASS::draw_image(const pixel *img, int x, int y, int w, int h for (int i = startX; i < w; i++) { #ifdef DO_CLIPCHECK - if (!(x+i=clipx2 || y+j>=clipy2)) + if (clip.Contains(Vec2(x + i, y + j))) #endif - vid[(y+j)*(VIDXRES)+(x+i)] = *img; + vid[(y+j)*(VIDXRES)+(x+i)] = *img; img++; } } diff --git a/src/graphics/RasterGraphics.cpp b/src/graphics/RasterGraphics.cpp index 6bd8e6cc7..696f3677b 100644 --- a/src/graphics/RasterGraphics.cpp +++ b/src/graphics/RasterGraphics.cpp @@ -4,10 +4,7 @@ #include Graphics::Graphics(): - clipx1(0), - clipy1(0), - clipx2(WINDOWW), - clipy2(WINDOWH), + clip(WINDOW.OriginRect()), sdl_scale(1) { vid = (pixel *)malloc(PIXELSIZE * (WINDOWW * WINDOWH)); diff --git a/src/graphics/RendererBasic.cpp b/src/graphics/RendererBasic.cpp index bd9b535a2..efdc33801 100644 --- a/src/graphics/RendererBasic.cpp +++ b/src/graphics/RendererBasic.cpp @@ -5,8 +5,9 @@ #include "simulation/ElementClasses.h" #include -constexpr auto VIDXRES = WINDOWW; -constexpr auto VIDYRES = WINDOWH; +constexpr auto VIDRES = WINDOW; +constexpr auto VIDXRES = VIDRES.X; +constexpr auto VIDYRES = VIDRES.Y; void Renderer::RenderBegin() { diff --git a/src/gui/game/GOLTool.cpp b/src/gui/game/GOLTool.cpp index 81919a8e7..871c2c999 100644 --- a/src/gui/game/GOLTool.cpp +++ b/src/gui/game/GOLTool.cpp @@ -36,10 +36,12 @@ public: }; GOLWindow::GOLWindow(GameModel * gameModel_, Simulation *sim_, int toolSelection, int rule, int colour1, int colour2): -ui::Window(ui::Point(-1, -1), ui::Point(200, 108)), -gameModel(gameModel_), -sim(sim_), -toolSelection(toolSelection) + ui::Window(ui::Point(-1, -1), ui::Point(200, 108)), + highColour(0, 0, 0, 0), + lowColour(0, 0, 0, 0), + gameModel(gameModel_), + sim(sim_), + toolSelection(toolSelection) { ui::Label * messageLabel = new ui::Label(ui::Point(4, 5), ui::Point(Size.X-8, 14), "Edit custom GOL type"); messageLabel->SetTextColour(style::Colour::InformationTitle); diff --git a/src/gui/game/GameView.cpp b/src/gui/game/GameView.cpp index 134a6433e..dc38b8507 100644 --- a/src/gui/game/GameView.cpp +++ b/src/gui/game/GameView.cpp @@ -575,10 +575,7 @@ void GameView::NotifyToolListChanged(GameModel * sender) else tempButton = new ToolButton(ui::Point(currentX, YRES+1), ui::Point(30, 18), tool->GetName(), tool->GetIdentifier(), tool->GetDescription()); - tempButton->clipRectX = 1; - tempButton->clipRectY = YRES + 1; - tempButton->clipRectW = XRES - 1; - tempButton->clipRectH = 18; + tempButton->clip = RectBetween(Vec2(1, YRES + 1), Vec2(XRES - 1, YRES + 18)); //currentY -= 17; currentX -= 31; @@ -1859,11 +1856,8 @@ void GameView::DoDraw() c->Tick(); { - int x = 0; - int y = 0; - int w = WINDOWW; - int h = WINDOWH; - g->SetClipRect(x, y, w, h); // reset any nonsense cliprect Lua left configured + auto rect = WINDOW.OriginRect(); + g->SetClipRect(rect); // reset any nonsense cliprect Lua left configured } } diff --git a/src/gui/game/ToolButton.cpp b/src/gui/game/ToolButton.cpp index f7d12ea9c..2f5ba8614 100644 --- a/src/gui/game/ToolButton.cpp +++ b/src/gui/game/ToolButton.cpp @@ -45,13 +45,10 @@ void ToolButton::OnMouseUp(int x, int y, unsigned int button) void ToolButton::Draw(const ui::Point& screenPos) { Graphics * g = GetGraphics(); - int x = clipRectX; - int y = clipRectY; - int w = clipRectW; - int h = clipRectH; - if (clipRectW && clipRectH) + auto rect = clip; + if (rect) { - g->SetClipRect(x, y, w, h); // old cliprect is now in x, y, w, h + g->SetClipRect(*rect); // old cliprect is now in rect } int totalColour = Appearance.BackgroundInactive.Blue + (3*Appearance.BackgroundInactive.Green) + (2*Appearance.BackgroundInactive.Red); @@ -85,9 +82,9 @@ void ToolButton::Draw(const ui::Point& screenPos) { g->drawtext(screenPos.X+textPosition.X, screenPos.Y+textPosition.Y, buttonDisplayText, 0, 0, 0, 255); } - if (clipRectW && clipRectH) + if (rect) { - g->SetClipRect(x, y, w, h); // apply old clip rect + g->SetClipRect(*rect); // apply old clip rect } } diff --git a/src/gui/game/ToolButton.h b/src/gui/game/ToolButton.h index 84e1fa277..92c8f19d7 100644 --- a/src/gui/game/ToolButton.h +++ b/src/gui/game/ToolButton.h @@ -1,5 +1,6 @@ #pragma once #include "gui/interface/Button.h" +#include class Tool; @@ -16,8 +17,5 @@ public: void SetSelectionState(int state); int GetSelectionState(); Tool *tool; - int clipRectX = 0; - int clipRectY = 0; - int clipRectW = 0; - int clipRectH = 0; + std::optional> clip = std::nullopt; }; diff --git a/src/gui/interface/Appearance.cpp b/src/gui/interface/Appearance.cpp index d341b5258..0597d92b1 100644 --- a/src/gui/interface/Appearance.cpp +++ b/src/gui/interface/Appearance.cpp @@ -23,6 +23,7 @@ namespace ui BorderHover(255, 255, 255), BorderInactive(200, 200, 200), BorderActive(235, 235, 235), + BorderFavorite(255, 255, 0), BorderDisabled(100, 100, 100), Margin(1, 4), diff --git a/src/gui/interface/Colour.h b/src/gui/interface/Colour.h index 31a09460e..e9d2a6e65 100644 --- a/src/gui/interface/Colour.h +++ b/src/gui/interface/Colour.h @@ -1,21 +1,8 @@ #pragma once +#include "graphics/Pixel.h" +#include namespace ui { -class Colour -{ -public: - unsigned char Red, Green, Blue, Alpha; - Colour(unsigned char red, unsigned char green, unsigned char blue): - Red(red), Green(green), Blue(blue), Alpha(255) - { - } - Colour(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha): - Red(red), Green(green), Blue(blue), Alpha(alpha) - { - } - Colour() - { - } -}; + using Colour = RGBA; } diff --git a/src/gui/interface/Panel.cpp b/src/gui/interface/Panel.cpp index 4eb0828bf..bf2b33496 100644 --- a/src/gui/interface/Panel.cpp +++ b/src/gui/interface/Panel.cpp @@ -67,11 +67,8 @@ void Panel::Draw(const Point& screenPos) // draw ourself first XDraw(screenPos); - int x = screenPos.X; - int y = screenPos.Y; - int w = Size.X; - int h = Size.Y; - ui::Engine::Ref().g->SetClipRect(x, y, w, h); // old cliprect is now in x, y, w, h + auto rect = RectSized(screenPos, Size); + ui::Engine::Ref().g->SetClipRect(rect); // old cliprect is now in rect // attempt to draw all children for (size_t i = 0; i < children.size(); ++i) @@ -91,7 +88,7 @@ void Panel::Draw(const Point& screenPos) } } - ui::Engine::Ref().g->SetClipRect(x, y, w, h); // apply old cliprect + ui::Engine::Ref().g->SetClipRect(rect); // apply old cliprect } void Panel::Tick(float dt) diff --git a/src/lua/LuaScriptInterface.cpp b/src/lua/LuaScriptInterface.cpp index 31b86fb51..ab1866c83 100644 --- a/src/lua/LuaScriptInterface.cpp +++ b/src/lua/LuaScriptInterface.cpp @@ -3901,11 +3901,12 @@ int LuaScriptInterface::graphics_setClipRect(lua_State * l) int y = luaL_optinteger(l, 2, 0); int w = luaL_optinteger(l, 3, WINDOWW); int h = luaL_optinteger(l, 4, WINDOWH); - luacon_g->SetClipRect(x, y, w, h); - lua_pushinteger(l, x); - lua_pushinteger(l, y); - lua_pushinteger(l, w); - lua_pushinteger(l, h); + auto rect = RectSized(Vec2(x, y), Vec2(w, h)); + luacon_g->SetClipRect(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); return 4; }