diff --git a/src/Format.cpp b/src/Format.cpp index c9d455e85..121c2872b 100644 --- a/src/Format.cpp +++ b/src/Format.cpp @@ -8,7 +8,7 @@ #include #include #include "Format.h" -#include "graphics/Graphics.h" +#include "graphics/VideoBuffer.h" ByteString format::UnixtimeToDate(time_t unixtime, ByteString dateFormat, bool local) { diff --git a/src/PowderToyRenderer.cpp b/src/PowderToyRenderer.cpp index 6decd57bf..54b99c169 100644 --- a/src/PowderToyRenderer.cpp +++ b/src/PowderToyRenderer.cpp @@ -72,7 +72,6 @@ int main(int argc, char *argv[]) } ren->RenderSimulation(); - ren->RenderEnd(); if (auto data = ren->DumpFrame().ToPNG()) Platform::WriteFile(*data, outputFilename); diff --git a/src/WindowIcon.cpp b/src/WindowIcon.cpp index 37602f205..99c7c76a5 100644 --- a/src/WindowIcon.cpp +++ b/src/WindowIcon.cpp @@ -1,5 +1,5 @@ #include "Format.h" -#include "graphics/Graphics.h" +#include "graphics/VideoBuffer.h" #include "WindowIcon.h" #include "icon_exe.png.h" diff --git a/src/client/ThumbnailRendererTask.cpp b/src/client/ThumbnailRendererTask.cpp index fe40d5802..61c4d64f2 100644 --- a/src/client/ThumbnailRendererTask.cpp +++ b/src/client/ThumbnailRendererTask.cpp @@ -2,7 +2,7 @@ #include -#include "graphics/Graphics.h" +#include "graphics/VideoBuffer.h" #include "simulation/SaveRenderer.h" #include "client/GameSave.h" diff --git a/src/client/http/ImageRequest.cpp b/src/client/http/ImageRequest.cpp index d30a80300..fe1379057 100644 --- a/src/client/http/ImageRequest.cpp +++ b/src/client/http/ImageRequest.cpp @@ -1,5 +1,5 @@ #include "ImageRequest.h" -#include "graphics/Graphics.h" +#include "graphics/VideoBuffer.h" #include "client/Client.h" #include diff --git a/src/graphics/Graphics.cpp b/src/graphics/Graphics.cpp index 47165091b..8e3036508 100644 --- a/src/graphics/Graphics.cpp +++ b/src/graphics/Graphics.cpp @@ -457,34 +457,37 @@ void Graphics::SwapClipRect(Rect &rect) clipRect &= video.Size().OriginRect(); } -bool Graphics::GradientStop::operator <(const GradientStop &other) const +void Graphics::RenderZoom() { - return point < other.point; -} - -std::vector> Graphics::Gradient(std::vector stops, int resolution) -{ - std::vector> table(resolution, 0x000000_rgb); - if (stops.size() >= 2) + if(!zoomEnabled) + return; { - std::sort(stops.begin(), stops.end()); - auto stop = -1; - for (auto i = 0; i < resolution; ++i) + int x, y, i, j; + pixel pix; + + DrawFilledRect(RectSized(zoomWindowPosition, { zoomScopeSize * ZFACTOR, zoomScopeSize * ZFACTOR }), 0x000000_rgb); + DrawRect(RectSized(zoomWindowPosition - Vec2{ 2, 2 }, Vec2{ zoomScopeSize*ZFACTOR+3, zoomScopeSize*ZFACTOR+3 }), 0xC0C0C0_rgb); + DrawRect(RectSized(zoomWindowPosition - Vec2{ 1, 1 }, Vec2{ zoomScopeSize*ZFACTOR+1, zoomScopeSize*ZFACTOR+1 }), 0x000000_rgb); + for (j=0; j= (int)stops.size() - 1) + for (j=0; j -#include -#include -#include "common/Plane.h" -#include "common/String.h" -#include "Icons.h" -#include "Pixel.h" -#include "RasterDrawMethods.h" -#include "SimulationConfig.h" - -class VideoBuffer: public RasterDrawMethods -{ - PlaneAdapter> video; - - Rect GetClipRect() const - { - return video.Size().OriginRect(); - } - - friend struct RasterDrawMethods; - -public: - VideoBuffer(pixel const *data, Vec2 size); - VideoBuffer(pixel const *data, Vec2 size, size_t rowStride); - VideoBuffer(Vec2 size); - - Vec2 Size() const - { - return video.Size(); - } - - pixel *Data() - { - return video.data(); - } - - pixel const *Data() const - { - return video.data(); - } - - void Crop(Rect); - - void Resize(float factor, bool resample = false); - void Resize(Vec2 size, bool resample = false); - // Automatically choose a size to fit within the given box, keeping aspect ratio - void ResizeToFit(Vec2 bound, bool resample = false); - - static std::unique_ptr FromPNG(std::vector const &); - std::unique_ptr> ToPNG() const; - std::vector ToPPM() const; -}; +#include "VideoBuffer.h" class Graphics: public RasterDrawMethods { @@ -75,15 +24,6 @@ public: return video.data(); } - struct GradientStop - { - RGB color; - float point; - - bool operator <(const GradientStop &other) const; - }; - static std::vector> Gradient(std::vector stops, int resolution); - VideoBuffer DumpFrame(); void draw_icon(int x, int y, Icon icon, unsigned char alpha = 255, bool invert = false); @@ -98,4 +38,11 @@ public: { return clipRect; } + + ui::Point zoomWindowPosition = { 0, 0 }; + ui::Point zoomScopePosition = { 0, 0 }; + int zoomScopeSize = 32; + bool zoomEnabled = false; + int ZFACTOR = 8; + void RenderZoom(); }; diff --git a/src/graphics/RasterDrawMethodsImpl.h b/src/graphics/RasterDrawMethodsImpl.h index 1621cc096..5fe5b5492 100644 --- a/src/graphics/RasterDrawMethodsImpl.h +++ b/src/graphics/RasterDrawMethodsImpl.h @@ -2,7 +2,7 @@ #include #include "common/RasterGeometry.h" #include "FontReader.h" -#include "Graphics.h" +#include "VideoBuffer.h" #include "RasterDrawMethods.h" #define clipRect() (static_cast(*this).GetClipRect()) diff --git a/src/graphics/Renderer.h b/src/graphics/Renderer.h index 6b3552e41..870562189 100644 --- a/src/graphics/Renderer.h +++ b/src/graphics/Renderer.h @@ -1,5 +1,5 @@ #pragma once -#include "Graphics.h" +#include "VideoBuffer.h" #include "gui/game/RenderPreset.h" #include "gui/interface/Point.h" #include "common/tpt-rand.h" @@ -80,18 +80,9 @@ public: //Mouse position for debug information ui::Point mousePos; - //Zoom window - ui::Point zoomWindowPosition; - ui::Point zoomScopePosition; - int zoomScopeSize; - bool zoomEnabled; - int ZFACTOR; - //Renderers void RenderSimulation(); - void RenderEnd(); - void RenderZoom(); void DrawBlob(Vec2 pos, RGB colour); void DrawWalls(); void DrawSigns(); @@ -135,6 +126,15 @@ public: Renderer(); + struct GradientStop + { + RGB color; + float point; + + bool operator <(const GradientStop &other) const; + }; + static std::vector> Gradient(std::vector stops, int resolution); + #define RENDERER_TABLE(name) \ static std::vector> name; \ static inline RGB name ## At(int index) \ diff --git a/src/graphics/RendererBasic.cpp b/src/graphics/RendererBasic.cpp index 65ae89170..226662f53 100644 --- a/src/graphics/RendererBasic.cpp +++ b/src/graphics/RendererBasic.cpp @@ -5,11 +5,6 @@ #include "simulation/ElementClasses.h" #include "simulation/ElementGraphics.h" -void Renderer::RenderEnd() -{ - RenderZoom(); -} - void Renderer::SetSample(Vec2 pos) { sampleColor = GetPixel(pos); @@ -26,41 +21,6 @@ void Renderer::clearScreen() { } } -void Renderer::RenderZoom() -{ - if(!zoomEnabled) - return; - { - int x, y, i, j; - pixel pix; - - DrawFilledRect(RectSized(zoomWindowPosition, { zoomScopeSize * ZFACTOR, zoomScopeSize * ZFACTOR }), 0x000000_rgb); - DrawRect(RectSized(zoomWindowPosition - Vec2{ 2, 2 }, Vec2{ zoomScopeSize*ZFACTOR+3, zoomScopeSize*ZFACTOR+3 }), 0xC0C0C0_rgb); - DrawRect(RectSized(zoomWindowPosition - Vec2{ 1, 1 }, Vec2{ zoomScopeSize*ZFACTOR+1, zoomScopeSize*ZFACTOR+1 }), 0x000000_rgb); - for (j=0; j pos, RGB colour) { BlendPixel(pos + Vec2{ +1, 0 }, colour.WithAlpha(112)); @@ -116,20 +76,20 @@ void Renderer::PopulateTables() if (!tablesPopulated) { tablesPopulated = true; - flameTable = Graphics::Gradient({ + flameTable = Gradient({ { 0x000000_rgb, 0.00f }, { 0x60300F_rgb, 0.50f }, { 0xDFBF6F_rgb, 0.90f }, { 0xAF9F0F_rgb, 1.00f }, }, 200); - plasmaTable = Graphics::Gradient({ + plasmaTable = Gradient({ { 0x000000_rgb, 0.00f }, { 0x301040_rgb, 0.25f }, { 0x301060_rgb, 0.50f }, { 0xAFFFFF_rgb, 0.90f }, { 0xAFFFFF_rgb, 1.00f }, }, 200); - heatTable = Graphics::Gradient({ + heatTable = Gradient({ { 0x2B00FF_rgb, 0.00f }, { 0x003CFF_rgb, 0.01f }, { 0x00C0FF_rgb, 0.05f }, @@ -141,7 +101,7 @@ void Renderer::PopulateTables() { 0xFF0000_rgb, 0.71f }, { 0xFF00DC_rgb, 1.00f }, }, 1024); - clfmTable = Graphics::Gradient({ + clfmTable = Gradient({ { 0x000000_rgb, 0.00f }, { 0x0A0917_rgb, 0.10f }, { 0x19163C_rgb, 0.20f }, @@ -151,7 +111,7 @@ void Renderer::PopulateTables() { 0x57A0B4_rgb, 0.80f }, { 0x5EC4C6_rgb, 1.00f }, }, 200); - firwTable = Graphics::Gradient({ + firwTable = Gradient({ { 0xFF00FF_rgb, 0.00f }, { 0x0000FF_rgb, 0.20f }, { 0x00FFFF_rgb, 0.40f }, @@ -171,11 +131,6 @@ Renderer::Renderer(): sampleColor(0xFFFFFFFF), foundElements(0), mousePos(0, 0), - zoomWindowPosition(0, 0), - zoomScopePosition(0, 0), - zoomScopeSize(32), - zoomEnabled(false), - ZFACTOR(8), gridSize(0) { PopulateTables(); @@ -321,3 +276,35 @@ VideoBuffer Renderer::DumpFrame() } template struct RasterDrawMethods; + +bool Renderer::GradientStop::operator <(const GradientStop &other) const +{ + return point < other.point; +} + +std::vector> Renderer::Gradient(std::vector stops, int resolution) +{ + std::vector> table(resolution, 0x000000_rgb); + if (stops.size() >= 2) + { + std::sort(stops.begin(), stops.end()); + auto stop = -1; + for (auto i = 0; i < resolution; ++i) + { + auto point = i / (float)resolution; + while (stop < (int)stops.size() - 1 && stops[stop + 1].point <= point) + { + ++stop; + } + if (stop < 0 || stop >= (int)stops.size() - 1) + { + continue; + } + auto &left = stops[stop]; + auto &right = stops[stop + 1]; + auto f = (point - left.point) / (right.point - left.point); + table[i] = left.color.Blend(right.color.WithAlpha(uint8_t(f * 0xFF))); + } + } + return table; +} diff --git a/src/graphics/VideoBuffer.h b/src/graphics/VideoBuffer.h new file mode 100644 index 000000000..9b336516e --- /dev/null +++ b/src/graphics/VideoBuffer.h @@ -0,0 +1,54 @@ +#pragma once +#include +#include +#include +#include "common/Plane.h" +#include "common/String.h" +#include "gui/interface/Point.h" +#include "Icons.h" +#include "Pixel.h" +#include "RasterDrawMethods.h" +#include "SimulationConfig.h" + +class VideoBuffer: public RasterDrawMethods +{ + PlaneAdapter> video; + + Rect GetClipRect() const + { + return video.Size().OriginRect(); + } + + friend struct RasterDrawMethods; + +public: + VideoBuffer(pixel const *data, Vec2 size); + VideoBuffer(pixel const *data, Vec2 size, size_t rowStride); + VideoBuffer(Vec2 size); + + Vec2 Size() const + { + return video.Size(); + } + + pixel *Data() + { + return video.data(); + } + + pixel const *Data() const + { + return video.data(); + } + + void Crop(Rect); + + void Resize(float factor, bool resample = false); + void Resize(Vec2 size, bool resample = false); + // Automatically choose a size to fit within the given box, keeping aspect ratio + void ResizeToFit(Vec2 bound, bool resample = false); + + static std::unique_ptr FromPNG(std::vector const &); + std::unique_ptr> ToPNG() const; + std::vector ToPPM() const; +}; diff --git a/src/gui/game/GameController.cpp b/src/gui/game/GameController.cpp index 785ca45ea..baf9af652 100644 --- a/src/gui/game/GameController.cpp +++ b/src/gui/game/GameController.cpp @@ -87,6 +87,7 @@ GameController::GameController(): gameView->AttachController(this); gameModel->AddObserver(gameView); + gameModel->view = gameView; // mvc is a joke gameView->SetDebugHUD(GlobalPrefs::Ref().Get("Renderer.DebugMode", false)); diff --git a/src/gui/game/GameModel.cpp b/src/gui/game/GameModel.cpp index b8ab3487a..896a74dd8 100644 --- a/src/gui/game/GameModel.cpp +++ b/src/gui/game/GameModel.cpp @@ -1091,24 +1091,24 @@ void GameModel::SetLastTool(Tool * newTool) void GameModel::SetZoomEnabled(bool enabled) { - ren->zoomEnabled = enabled; + view->GetGraphics()->zoomEnabled = enabled; notifyZoomChanged(); } bool GameModel::GetZoomEnabled() { - return ren->zoomEnabled; + return view->GetGraphics()->zoomEnabled; } void GameModel::SetZoomPosition(ui::Point position) { - ren->zoomScopePosition = position; + view->GetGraphics()->zoomScopePosition = position; notifyZoomChanged(); } ui::Point GameModel::GetZoomPosition() { - return ren->zoomScopePosition; + return view->GetGraphics()->zoomScopePosition; } bool GameModel::MouseInZoom(ui::Point position) @@ -1141,35 +1141,35 @@ ui::Point GameModel::AdjustZoomCoords(ui::Point position) void GameModel::SetZoomWindowPosition(ui::Point position) { - ren->zoomWindowPosition = position; + view->GetGraphics()->zoomWindowPosition = position; notifyZoomChanged(); } ui::Point GameModel::GetZoomWindowPosition() { - return ren->zoomWindowPosition; + return view->GetGraphics()->zoomWindowPosition; } void GameModel::SetZoomSize(int size) { - ren->zoomScopeSize = size; + view->GetGraphics()->zoomScopeSize = size; notifyZoomChanged(); } int GameModel::GetZoomSize() { - return ren->zoomScopeSize; + return view->GetGraphics()->zoomScopeSize; } void GameModel::SetZoomFactor(int factor) { - ren->ZFACTOR = factor; + view->GetGraphics()->ZFACTOR = factor; notifyZoomChanged(); } int GameModel::GetZoomFactor() { - return ren->ZFACTOR; + return view->GetGraphics()->ZFACTOR; } void GameModel::SetActiveColourPreset(size_t preset) diff --git a/src/gui/game/GameModel.h b/src/gui/game/GameModel.h index abea540bf..2f2dcb0fb 100644 --- a/src/gui/game/GameModel.h +++ b/src/gui/game/GameModel.h @@ -273,4 +273,6 @@ public: void UpdateUpTo(int upTo); void BeforeSim(); void AfterSim(); + + GameView *view = nullptr; }; diff --git a/src/gui/game/GameView.cpp b/src/gui/game/GameView.cpp index de1ee6e4f..ecf4a85f4 100644 --- a/src/gui/game/GameView.cpp +++ b/src/gui/game/GameView.cpp @@ -2245,9 +2245,9 @@ void GameView::OnDraw() } c->AfterSimDraw(); - ren->RenderEnd(); std::copy_n(ren->Data(), ren->Size().X * ren->Size().Y, g->Data()); + g->RenderZoom(); if (doScreenshot) { diff --git a/src/gui/interface/Slider.cpp b/src/gui/interface/Slider.cpp index 1e42bcfa6..a4fa3228a 100644 --- a/src/gui/interface/Slider.cpp +++ b/src/gui/interface/Slider.cpp @@ -1,6 +1,6 @@ #include "Slider.h" - #include "graphics/Graphics.h" +#include "graphics/Renderer.h" namespace ui { @@ -70,7 +70,7 @@ void Slider::SetColour(Colour col1, Colour col2) { this->col1 = col1; this->col2 = col2; - bgGradient = Graphics::Gradient({ + bgGradient = Renderer::Gradient({ { col1.NoAlpha(), 0.f }, { col2.NoAlpha(), 1.f }, }, Size.X-7); diff --git a/src/gui/render/RenderView.cpp b/src/gui/render/RenderView.cpp index fbd9f90f9..d728a6413 100644 --- a/src/gui/render/RenderView.cpp +++ b/src/gui/render/RenderView.cpp @@ -190,7 +190,6 @@ void RenderView::OnDraw() ren->sim = sim; ren->clearScreen(); ren->RenderSimulation(); - ren->RenderEnd(); ren->sim = nullptr; for (auto y = 0; y < YRES; ++y) { diff --git a/src/lua/LuaRenderer.cpp b/src/lua/LuaRenderer.cpp index add5dd75c..5674c81d6 100644 --- a/src/lua/LuaRenderer.cpp +++ b/src/lua/LuaRenderer.cpp @@ -2,6 +2,7 @@ #include "gui/game/GameController.h" #include "gui/game/GameModel.h" #include "graphics/Renderer.h" +#include "graphics/Graphics.h" #include "simulation/ElementGraphics.h" static int renderMode(lua_State *L) @@ -148,13 +149,13 @@ static int zoomEnabled(lua_State *L) auto *lsi = GetLSI(); if (lua_gettop(L) == 0) { - lua_pushboolean(L, lsi->ren->zoomEnabled); + lua_pushboolean(L, lsi->g->zoomEnabled); return 1; } else { luaL_checktype(L, -1, LUA_TBOOLEAN); - lsi->ren->zoomEnabled = lua_toboolean(L, -1); + lsi->g->zoomEnabled = lua_toboolean(L, -1); return 0; } } @@ -162,14 +163,13 @@ static int zoomEnabled(lua_State *L) static int zoomWindow(lua_State *L) { auto *lsi = GetLSI(); - auto *ren = lsi->ren; if (lua_gettop(L) == 0) { - ui::Point location = ren->zoomWindowPosition; + ui::Point location = lsi->g->zoomWindowPosition; lua_pushnumber(L, location.X); lua_pushnumber(L, location.Y); - lua_pushnumber(L, ren->ZFACTOR); - lua_pushnumber(L, ren->zoomScopeSize * ren->ZFACTOR); + lua_pushnumber(L, lsi->g->ZFACTOR); + lua_pushnumber(L, lsi->g->zoomScopeSize * lsi->g->ZFACTOR); return 4; } int x = luaL_optint(L, 1, 0); @@ -179,24 +179,23 @@ static int zoomWindow(lua_State *L) return luaL_error(L, "Zoom factor must be greater than 0"); // To prevent crash when zoom window is outside screen - if (x < 0 || y < 0 || ren->zoomScopeSize * f + x > XRES || ren->zoomScopeSize * f + y > YRES) + if (x < 0 || y < 0 || lsi->g->zoomScopeSize * f + x > XRES || lsi->g->zoomScopeSize * f + y > YRES) return luaL_error(L, "Zoom window outside of bounds"); - ren->zoomWindowPosition = ui::Point(x, y); - ren->ZFACTOR = f; + lsi->g->zoomWindowPosition = ui::Point(x, y); + lsi->g->ZFACTOR = f; return 0; } static int zoomScope(lua_State *L) { auto *lsi = GetLSI(); - auto *ren = lsi->ren; if (lua_gettop(L) == 0) { - ui::Point location = ren->zoomScopePosition; + ui::Point location = lsi->g->zoomScopePosition; lua_pushnumber(L, location.X); lua_pushnumber(L, location.Y); - lua_pushnumber(L, ren->zoomScopeSize); + lua_pushnumber(L, lsi->g->zoomScopeSize); return 3; } int x = luaL_optint(L, 1, 0); @@ -206,15 +205,15 @@ static int zoomScope(lua_State *L) return luaL_error(L, "Zoom scope size must be greater than 0"); // To prevent crash when zoom or scope window is outside screen - int windowEdgeRight = ren->ZFACTOR * s + ren->zoomWindowPosition.X; - int windowEdgeBottom = ren->ZFACTOR * s + ren->zoomWindowPosition.Y; + int windowEdgeRight = lsi->g->ZFACTOR * s + lsi->g->zoomWindowPosition.X; + int windowEdgeBottom = lsi->g->ZFACTOR * s + lsi->g->zoomWindowPosition.Y; if (x < 0 || y < 0 || x + s > XRES || y + s > YRES) return luaL_error(L, "Zoom scope outside of bounds"); if (windowEdgeRight > XRES || windowEdgeBottom > YRES) return luaL_error(L, "Zoom window outside of bounds"); - ren->zoomScopePosition = ui::Point(x, y); - ren->zoomScopeSize = s; + lsi->g->zoomScopePosition = ui::Point(x, y); + lsi->g->zoomScopeSize = s; return 0; } diff --git a/src/simulation/SaveRenderer.cpp b/src/simulation/SaveRenderer.cpp index 98e810b07..b6814d0e4 100644 --- a/src/simulation/SaveRenderer.cpp +++ b/src/simulation/SaveRenderer.cpp @@ -2,7 +2,7 @@ #include "client/GameSave.h" -#include "graphics/Graphics.h" +#include "graphics/VideoBuffer.h" #include "graphics/Renderer.h" #include "Simulation.h" @@ -55,7 +55,6 @@ std::unique_ptr SaveRenderer::Render(const GameSave *save, bool dec } ren->RenderSimulation(); - ren->RenderEnd(); auto tempThumb = std::make_unique(save->blockSize * CELL); tempThumb->BlendImage(ren->Data(), 0xFF, ren->Size().OriginRect()); diff --git a/src/simulation/Sign.cpp b/src/simulation/Sign.cpp index d55718df0..6979a6ba7 100644 --- a/src/simulation/Sign.cpp +++ b/src/simulation/Sign.cpp @@ -1,6 +1,6 @@ #include "Sign.h" -#include "graphics/Graphics.h" +#include "graphics/Renderer.h" #include "Simulation.h" #include "SimulationData.h" @@ -136,7 +136,7 @@ String sign::getDisplayText(const RenderableSimulation *sim, int &x0, int &y0, i } } - w = Graphics::TextSize(drawable_text.c_str()).X + 4; + w = Renderer::TextSize(drawable_text.c_str()).X + 4; h = 15; x0 = (ju == Right) ? x - w : (ju == Left) ? x : x - w/2; y0 = (y > 18) ? y - 18 : y + 4;