From 6e01699a7fcdf1ae03441e3c1d4ba9f39a77c9dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20B=C3=A1lint=20Misius?= Date: Sat, 6 Jul 2024 13:26:37 +0200 Subject: [PATCH] Separate Simulation-specific Renderer code Also decouple Simulation lifetime from Renderer lifetime. This also let me get rid of the hack that was RendererFont.cpp. --- src/PowderToyRenderer.cpp | 5 ++- src/graphics/Renderer.cpp | 51 +++++++++++++++++++++- src/graphics/Renderer.h | 8 ++-- src/graphics/RendererBasic.cpp | 66 ++--------------------------- src/graphics/RendererFont.cpp | 33 --------------- src/graphics/meson.build | 8 +--- src/gui/game/GameController.cpp | 2 +- src/gui/game/GameModel.cpp | 2 +- src/gui/game/GameView.cpp | 7 ++- src/gui/game/GameView.h | 2 + src/gui/render/RenderController.cpp | 3 +- src/gui/render/RenderController.h | 3 +- src/gui/render/RenderModel.cpp | 22 ++++++++++ src/gui/render/RenderModel.h | 5 +++ src/gui/render/RenderView.cpp | 10 ++++- src/gui/render/RenderView.h | 3 ++ src/simulation/SaveRenderer.cpp | 5 ++- 17 files changed, 115 insertions(+), 120 deletions(-) delete mode 100644 src/graphics/RendererFont.cpp diff --git a/src/PowderToyRenderer.cpp b/src/PowderToyRenderer.cpp index 0eee7ef6c..6decd57bf 100644 --- a/src/PowderToyRenderer.cpp +++ b/src/PowderToyRenderer.cpp @@ -43,7 +43,8 @@ int main(int argc, char *argv[]) } Simulation * sim = new Simulation(); - Renderer * ren = new Renderer(sim); + Renderer * ren = new Renderer(); + ren->sim = sim; if (gameSave) { @@ -70,7 +71,7 @@ int main(int argc, char *argv[]) ren->BlendText({ x+8, y+8 }, "Save file invalid", 0xC0C0F0_rgb .WithAlpha(255)); } - ren->RenderBegin(); + ren->RenderSimulation(); ren->RenderEnd(); if (auto data = ren->DumpFrame().ToPNG()) diff --git a/src/graphics/Renderer.cpp b/src/graphics/Renderer.cpp index 2b1c491af..3048b09ab 100644 --- a/src/graphics/Renderer.cpp +++ b/src/graphics/Renderer.cpp @@ -10,6 +10,55 @@ #include "simulation/orbitalparts.h" #include +void Renderer::RenderSimulation() +{ + draw_grav(); + DrawWalls(); + render_parts(); + + if (display_mode & DISPLAY_PERS) + { + std::transform(video.RowIterator({ 0, 0 }), video.RowIterator({ 0, YRES }), persistentVideo.begin(), [](pixel p) { + return RGB::Unpack(p).Decay().Pack(); + }); + } + + render_fire(); + draw_other(); + draw_grav_zones(); + DrawSigns(); + + if (display_mode & DISPLAY_WARP) + { + warpVideo = video; + std::fill_n(video.data(), WINDOWW * YRES, 0); + render_gravlensing(warpVideo); + } +} + +void Renderer::render_gravlensing(const Video &source) +{ + for (auto p : RES.OriginRect()) + { + auto cp = p / CELL; + auto rp = Vec2{ int(p.X - sim->gravOut.forceX[cp] * 0.75f + 0.5f), int(p.Y - sim->gravOut.forceY[cp] * 0.75f + 0.5f) }; + auto gp = Vec2{ int(p.X - sim->gravOut.forceX[cp] * 0.875f + 0.5f), int(p.Y - sim->gravOut.forceY[cp] * 0.875f + 0.5f) }; + auto bp = Vec2{ int(p.X - sim->gravOut.forceX[cp] + 0.5f), int(p.Y - sim->gravOut.forceY[cp] + 0.5f) }; + if (RES.OriginRect().Contains(rp) && + RES.OriginRect().Contains(gp) && + RES.OriginRect().Contains(bp)) + { + auto v = RGB::Unpack(video[p]); + auto s = RGB::Unpack(source[rp]); + video[p] = RGB( + std::min(0xFF, s.Red + v.Red ), + std::min(0xFF, s.Green + v.Green), + std::min(0xFF, s.Blue + v.Blue ) + ).Pack(); + } + } +} + std::unique_ptr Renderer::WallIcon(int wallID, Vec2 size) { auto &sd = SimulationData::CRef(); @@ -185,8 +234,6 @@ void Renderer::render_parts() int orbd[4] = {0, 0, 0, 0}, orbl[4] = {0, 0, 0, 0}; int drawing_budget = 1000000; //Serves as an upper bound for costly effects such as SPARK, FLARE and LFLARE - if(!sim) - return; auto *parts = sim->parts; if (gridSize)//draws the grid { diff --git a/src/graphics/Renderer.h b/src/graphics/Renderer.h index f2b46f8bf..cb185c20e 100644 --- a/src/graphics/Renderer.h +++ b/src/graphics/Renderer.h @@ -55,8 +55,7 @@ public: } RNG rng; - - const RenderableSimulation *sim; + const RenderableSimulation *sim = nullptr; std::vector render_modes; unsigned int render_mode; @@ -90,7 +89,7 @@ public: int ZFACTOR; //Renderers - void RenderBegin(); + void RenderSimulation(); void RenderEnd(); void RenderZoom(); @@ -109,7 +108,6 @@ public: void draw_air(); void draw_grav(); void draw_other(); - void FinaliseParts(); void ClearAccumulation(); void clearScreen(); @@ -142,7 +140,7 @@ public: static std::unique_ptr WallIcon(int wallID, Vec2 size); - Renderer(RenderableSimulation *newSim); + Renderer(); #define RENDERER_TABLE(name) \ static std::vector> name; \ diff --git a/src/graphics/RendererBasic.cpp b/src/graphics/RendererBasic.cpp index cde788778..63b7bb284 100644 --- a/src/graphics/RendererBasic.cpp +++ b/src/graphics/RendererBasic.cpp @@ -4,31 +4,6 @@ #include "Renderer.h" #include "simulation/ElementClasses.h" #include "simulation/ElementGraphics.h" -#include "simulation/Simulation.h" - -constexpr auto VIDXRES = WINDOWW; -constexpr auto VIDYRES = WINDOWH; - -void Renderer::RenderBegin() -{ - draw_grav(); - DrawWalls(); - render_parts(); - - if(display_mode & DISPLAY_PERS) - { - std::transform(video.RowIterator({ 0, 0 }), video.RowIterator({ 0, YRES }), persistentVideo.begin(), [](pixel p) { - return RGB::Unpack(p).Decay().Pack(); - }); - } - - render_fire(); - draw_other(); - draw_grav_zones(); - DrawSigns(); - - FinaliseParts(); -} void Renderer::RenderEnd() { @@ -47,17 +22,7 @@ void Renderer::clearScreen() { } else { - std::fill_n(video.data(), VIDXRES * YRES, 0); - } -} - -void Renderer::FinaliseParts() -{ - if(display_mode & DISPLAY_WARP) - { - warpVideo = video; - std::fill_n(video.data(), VIDXRES * YRES, 0); - render_gravlensing(warpVideo); + std::fill_n(video.data(), WINDOWW * YRES, 0); } } @@ -96,30 +61,6 @@ void Renderer::RenderZoom() } } - -void Renderer::render_gravlensing(const Video &source) -{ - for (auto p : RES.OriginRect()) - { - auto cp = p / CELL; - auto rp = Vec2{ int(p.X - sim->gravOut.forceX[cp] * 0.75f + 0.5f), int(p.Y - sim->gravOut.forceY[cp] * 0.75f + 0.5f) }; - auto gp = Vec2{ int(p.X - sim->gravOut.forceX[cp] * 0.875f + 0.5f), int(p.Y - sim->gravOut.forceY[cp] * 0.875f + 0.5f) }; - auto bp = Vec2{ int(p.X - sim->gravOut.forceX[cp] + 0.5f), int(p.Y - sim->gravOut.forceY[cp] + 0.5f) }; - if (RES.OriginRect().Contains(rp) && - RES.OriginRect().Contains(gp) && - RES.OriginRect().Contains(bp)) - { - auto v = RGB::Unpack(video[p]); - auto s = RGB::Unpack(source[rp]); - video[p] = RGB( - std::min(0xFF, s.Red + v.Red ), - std::min(0xFF, s.Green + v.Green), - std::min(0xFF, s.Blue + v.Blue ) - ).Pack(); - } - } -} - void Renderer::DrawBlob(Vec2 pos, RGB colour) { BlendPixel(pos + Vec2{ +1, 0 }, colour.WithAlpha(112)); @@ -157,7 +98,7 @@ void Renderer::prepare_alpha(int size, float intensity) pixel Renderer::GetPixel(Vec2 pos) const { - if (pos.X<0 || pos.Y<0 || pos.X>=VIDXRES || pos.Y>=VIDYRES) + if (pos.X<0 || pos.Y<0 || pos.X>=WINDOWW || pos.Y>=WINDOWH) return 0; return video[pos]; } @@ -221,8 +162,7 @@ void Renderer::PopulateTables() } } -Renderer::Renderer(RenderableSimulation *newSim): - sim(newSim), +Renderer::Renderer(): render_mode(0), colour_mode(0), display_mode(0), diff --git a/src/graphics/RendererFont.cpp b/src/graphics/RendererFont.cpp deleted file mode 100644 index 9671d36d3..000000000 --- a/src/graphics/RendererFont.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "Renderer.h" - -void Renderer::draw_air() -{ -} - -void Renderer::draw_grav() -{ -} - -void Renderer::DrawWalls() -{ -} - -void Renderer::render_parts() -{ -} - -void Renderer::render_fire() -{ -} - -void Renderer::draw_other() -{ -} - -void Renderer::draw_grav_zones() -{ -} - -void Renderer::DrawSigns() -{ -} diff --git a/src/graphics/meson.build b/src/graphics/meson.build index 5c01cffc6..8334e066e 100644 --- a/src/graphics/meson.build +++ b/src/graphics/meson.build @@ -2,16 +2,12 @@ graphics_files = files( 'Graphics.cpp', 'RasterGraphics.cpp', 'FontReader.cpp', + 'RendererBasic.cpp', ) powder_graphics_files = files( - 'RendererBasic.cpp', 'Renderer.cpp', ) -font_graphics_files = files( - 'RendererBasic.cpp', - 'RendererFont.cpp', -) powder_files += graphics_files + powder_graphics_files render_files += graphics_files + powder_graphics_files -font_files += graphics_files + font_graphics_files +font_files += graphics_files diff --git a/src/gui/game/GameController.cpp b/src/gui/game/GameController.cpp index a7fbb126a..d48e260b8 100644 --- a/src/gui/game/GameController.cpp +++ b/src/gui/game/GameController.cpp @@ -1403,7 +1403,7 @@ void GameController::HideConsole() void GameController::OpenRenderOptions() { - renderOptions = new RenderController(gameModel->GetRenderer(), NULL); + renderOptions = new RenderController(gameModel->GetSimulation(), gameModel->GetRenderer(), NULL); ui::Engine::Ref().ShowWindow(renderOptions->GetView()); } diff --git a/src/gui/game/GameModel.cpp b/src/gui/game/GameModel.cpp index 7660b9199..86fcc45ee 100644 --- a/src/gui/game/GameModel.cpp +++ b/src/gui/game/GameModel.cpp @@ -59,7 +59,7 @@ GameModel::GameModel(): { sim = new Simulation(); sim->useLuaCallbacks = true; - ren = new Renderer(sim); + ren = new Renderer(); activeTools = regularToolset.data(); diff --git a/src/gui/game/GameView.cpp b/src/gui/game/GameView.cpp index d457e11b8..de1ee6e4f 100644 --- a/src/gui/game/GameView.cpp +++ b/src/gui/game/GameView.cpp @@ -26,6 +26,7 @@ #include "simulation/ElementDefs.h" #include "simulation/SaveRenderer.h" #include "simulation/SimulationData.h" +#include "simulation/Simulation.h" #include "gui/dialogues/ConfirmPrompt.h" #include "gui/dialogues/ErrorMessage.h" @@ -737,7 +738,7 @@ void GameView::NotifyRendererChanged(GameModel * sender) void GameView::NotifySimulationChanged(GameModel * sender) { - + sim = sender->GetSimulation(); } void GameView::NotifyUserChanged(GameModel * sender) { @@ -2133,10 +2134,12 @@ void GameView::OnDraw() // we're the main thread, we may write graphicscache auto &sd = SimulationData::Ref(); std::unique_lock lk(sd.elementGraphicsMx); + ren->sim = sim; ren->clearScreen(); ren->draw_air(); c->BeforeSimDraw(); - ren->RenderBegin(); + ren->RenderSimulation(); + ren->sim = nullptr; ren->SetSample(c->PointTranslate(currentMouse)); if (showBrush && selectMode == SelectNone && (!zoomEnabled || zoomCursorFixed) && activeBrush && (isMouseDown || (currentMouse.X >= 0 && currentMouse.X < XRES && currentMouse.Y >= 0 && currentMouse.Y < YRES))) { diff --git a/src/gui/game/GameView.h b/src/gui/game/GameView.h index a7fd8c8ef..d4fd54266 100644 --- a/src/gui/game/GameView.h +++ b/src/gui/game/GameView.h @@ -27,6 +27,7 @@ namespace ui } class SplitButton; +class Simulation; class MenuButton; class Renderer; @@ -81,6 +82,7 @@ private: ui::Point currentPoint, lastPoint; GameController * c; Renderer * ren; + Simulation *sim = nullptr; Brush const *activeBrush; //UI Elements std::vector quickOptionButtons; diff --git a/src/gui/render/RenderController.cpp b/src/gui/render/RenderController.cpp index 9c2842dbe..e817442b3 100644 --- a/src/gui/render/RenderController.cpp +++ b/src/gui/render/RenderController.cpp @@ -5,7 +5,7 @@ #include "Controller.h" -RenderController::RenderController(Renderer * ren, std::function onDone_): +RenderController::RenderController(Simulation *sim, Renderer * ren, std::function onDone_): HasExited(false) { renderView = new RenderView(); @@ -15,6 +15,7 @@ RenderController::RenderController(Renderer * ren, std::function onDone renderModel->AddObserver(renderView); renderModel->SetRenderer(ren); + renderModel->SetSimulation(sim); onDone = onDone_; } diff --git a/src/gui/render/RenderController.h b/src/gui/render/RenderController.h index 06ab6dc3d..e4e5c817a 100644 --- a/src/gui/render/RenderController.h +++ b/src/gui/render/RenderController.h @@ -4,6 +4,7 @@ class RenderView; class RenderModel; class Renderer; +class Simulation; class RenderController { RenderView * renderView; @@ -11,7 +12,7 @@ class RenderController std::function onDone; public: bool HasExited; - RenderController(Renderer * ren, std::function onDone = nullptr); + RenderController(Simulation *sim, Renderer * ren, std::function onDone = nullptr); void Exit(); RenderView * GetView() { return renderView; } virtual ~RenderController(); diff --git a/src/gui/render/RenderModel.cpp b/src/gui/render/RenderModel.cpp index a4a949b9d..517c6b8fa 100644 --- a/src/gui/render/RenderModel.cpp +++ b/src/gui/render/RenderModel.cpp @@ -100,11 +100,25 @@ void RenderModel::SetRenderer(Renderer * ren) notifyColourChanged(); } +void RenderModel::SetSimulation(Simulation *newSim) +{ + sim = newSim; + notifySimulationChanged(); + notifyRenderChanged(); + notifyDisplayChanged(); + notifyColourChanged(); +} + Renderer * RenderModel::GetRenderer() { return renderer; } +Simulation *RenderModel::GetSimulation() +{ + return sim; +} + void RenderModel::notifyRendererChanged() { for (size_t i = 0; i < observers.size(); i++) @@ -113,6 +127,14 @@ void RenderModel::notifyRendererChanged() } } +void RenderModel::notifySimulationChanged() +{ + for (size_t i = 0; i < observers.size(); i++) + { + observers[i]->NotifySimulationChanged(this); + } +} + void RenderModel::notifyRenderChanged() { for (size_t i = 0; i < observers.size(); i++) diff --git a/src/gui/render/RenderModel.h b/src/gui/render/RenderModel.h index ca41c2e9e..8449c4d8e 100644 --- a/src/gui/render/RenderModel.h +++ b/src/gui/render/RenderModel.h @@ -3,19 +3,24 @@ class RenderView; class Renderer; +class Simulation; class RenderModel { std::vector observers; Renderer * renderer; + Simulation *sim = nullptr; void notifyRendererChanged(); + void notifySimulationChanged(); void notifyRenderChanged(); void notifyDisplayChanged(); void notifyColourChanged(); public: RenderModel(); Renderer * GetRenderer(); + Simulation *GetSimulation(); void AddObserver(RenderView * observer); void SetRenderer(Renderer * ren); + void SetSimulation(Simulation *newSim); void SetRenderMode(unsigned int renderMode); void UnsetRenderMode(unsigned int renderMode); unsigned int GetRenderMode(); diff --git a/src/gui/render/RenderView.cpp b/src/gui/render/RenderView.cpp index 2fbb19e3f..8e72ca5b8 100644 --- a/src/gui/render/RenderView.cpp +++ b/src/gui/render/RenderView.cpp @@ -2,6 +2,7 @@ #include "simulation/ElementGraphics.h" #include "simulation/SimulationData.h" +#include "simulation/Simulation.h" #include "graphics/Graphics.h" #include "graphics/Renderer.h" @@ -125,6 +126,11 @@ void RenderView::NotifyRendererChanged(RenderModel * sender) ren = sender->GetRenderer(); } +void RenderView::NotifySimulationChanged(RenderModel * sender) +{ + sim = sender->GetSimulation(); +} + void RenderView::NotifyRenderChanged(RenderModel * sender) { for (size_t i = 0; i < renderModes.size(); i++) @@ -162,9 +168,11 @@ void RenderView::OnDraw() // we're the main thread, we may write graphicscache auto &sd = SimulationData::Ref(); std::unique_lock lk(sd.elementGraphicsMx); + ren->sim = sim; ren->clearScreen(); - ren->RenderBegin(); + ren->RenderSimulation(); ren->RenderEnd(); + ren->sim = nullptr; for (auto y = 0; y < YRES; ++y) { std::copy_n(ren->Data() + ren->Size().X * y, ren->Size().X, g->Data() + g->Size().X * y); diff --git a/src/gui/render/RenderView.h b/src/gui/render/RenderView.h index fb7478dec..2de166324 100644 --- a/src/gui/render/RenderView.h +++ b/src/gui/render/RenderView.h @@ -5,11 +5,13 @@ class ModeCheckbox; class Renderer; +class Simulation; class RenderController; class RenderModel; class RenderView: public ui::Window { RenderController * c; Renderer * ren; + Simulation *sim = nullptr; std::vector renderModes; std::vector displayModes; std::vector colourModes; @@ -20,6 +22,7 @@ class RenderView: public ui::Window { public: RenderView(); void NotifyRendererChanged(RenderModel * sender); + void NotifySimulationChanged(RenderModel * sender); void NotifyRenderChanged(RenderModel * sender); void NotifyDisplayChanged(RenderModel * sender); void NotifyColourChanged(RenderModel * sender); diff --git a/src/simulation/SaveRenderer.cpp b/src/simulation/SaveRenderer.cpp index 733409f76..6e4e2b692 100644 --- a/src/simulation/SaveRenderer.cpp +++ b/src/simulation/SaveRenderer.cpp @@ -11,7 +11,8 @@ SaveRenderer::SaveRenderer() { sim = std::make_unique(); - ren = std::make_unique(sim.get()); + ren = std::make_unique(); + ren->sim = sim.get(); ren->decorations_enable = true; ren->blackDecorations = true; } @@ -53,7 +54,7 @@ std::unique_ptr SaveRenderer::Render(const GameSave *save, bool dec } } - ren->RenderBegin(); + ren->RenderSimulation(); ren->RenderEnd(); auto tempThumb = std::make_unique(save->blockSize * CELL);