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.
This commit is contained in:
Tamás Bálint Misius
2024-07-06 13:26:37 +02:00
parent c1a072f2e5
commit 6e01699a7f
17 changed files with 115 additions and 120 deletions

View File

@@ -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())

View File

@@ -10,6 +10,55 @@
#include "simulation/orbitalparts.h"
#include <cmath>
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<uint8_t>::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<uint8_t>::Unpack(video[p]);
auto s = RGB<uint8_t>::Unpack(source[rp]);
video[p] = RGB<uint8_t>(
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<VideoBuffer> Renderer::WallIcon(int wallID, Vec2<int> 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
{

View File

@@ -55,8 +55,7 @@ public:
}
RNG rng;
const RenderableSimulation *sim;
const RenderableSimulation *sim = nullptr;
std::vector<unsigned int> 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<VideoBuffer> WallIcon(int wallID, Vec2<int> size);
Renderer(RenderableSimulation *newSim);
Renderer();
#define RENDERER_TABLE(name) \
static std::vector<RGB<uint8_t>> name; \

View File

@@ -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<uint8_t>::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<uint8_t>::Unpack(video[p]);
auto s = RGB<uint8_t>::Unpack(source[rp]);
video[p] = RGB<uint8_t>(
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<int> pos, RGB<uint8_t> 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<int> 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),

View File

@@ -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()
{
}

View File

@@ -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

View File

@@ -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());
}

View File

@@ -59,7 +59,7 @@ GameModel::GameModel():
{
sim = new Simulation();
sim->useLuaCallbacks = true;
ren = new Renderer(sim);
ren = new Renderer();
activeTools = regularToolset.data();

View File

@@ -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)))
{

View File

@@ -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<ui::Button*> quickOptionButtons;

View File

@@ -5,7 +5,7 @@
#include "Controller.h"
RenderController::RenderController(Renderer * ren, std::function<void ()> onDone_):
RenderController::RenderController(Simulation *sim, Renderer * ren, std::function<void ()> onDone_):
HasExited(false)
{
renderView = new RenderView();
@@ -15,6 +15,7 @@ RenderController::RenderController(Renderer * ren, std::function<void ()> onDone
renderModel->AddObserver(renderView);
renderModel->SetRenderer(ren);
renderModel->SetSimulation(sim);
onDone = onDone_;
}

View File

@@ -4,6 +4,7 @@
class RenderView;
class RenderModel;
class Renderer;
class Simulation;
class RenderController
{
RenderView * renderView;
@@ -11,7 +12,7 @@ class RenderController
std::function<void ()> onDone;
public:
bool HasExited;
RenderController(Renderer * ren, std::function<void ()> onDone = nullptr);
RenderController(Simulation *sim, Renderer * ren, std::function<void ()> onDone = nullptr);
void Exit();
RenderView * GetView() { return renderView; }
virtual ~RenderController();

View File

@@ -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++)

View File

@@ -3,19 +3,24 @@
class RenderView;
class Renderer;
class Simulation;
class RenderModel
{
std::vector<RenderView*> 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();

View File

@@ -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);

View File

@@ -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<ModeCheckbox *> renderModes;
std::vector<ModeCheckbox *> displayModes;
std::vector<ModeCheckbox *> 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);

View File

@@ -11,7 +11,8 @@
SaveRenderer::SaveRenderer()
{
sim = std::make_unique<Simulation>();
ren = std::make_unique<Renderer>(sim.get());
ren = std::make_unique<Renderer>();
ren->sim = sim.get();
ren->decorations_enable = true;
ren->blackDecorations = true;
}
@@ -53,7 +54,7 @@ std::unique_ptr<VideoBuffer> SaveRenderer::Render(const GameSave *save, bool dec
}
}
ren->RenderBegin();
ren->RenderSimulation();
ren->RenderEnd();
auto tempThumb = std::make_unique<VideoBuffer>(save->blockSize * CELL);