mirror of
https://github.com/The-Powder-Toy/The-Powder-Toy.git
synced 2025-07-31 13:40:12 +02:00
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:
@@ -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())
|
||||
|
@@ -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
|
||||
{
|
||||
|
@@ -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; \
|
||||
|
@@ -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),
|
||||
|
@@ -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()
|
||||
{
|
||||
}
|
@@ -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
|
||||
|
@@ -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());
|
||||
}
|
||||
|
||||
|
@@ -59,7 +59,7 @@ GameModel::GameModel():
|
||||
{
|
||||
sim = new Simulation();
|
||||
sim->useLuaCallbacks = true;
|
||||
ren = new Renderer(sim);
|
||||
ren = new Renderer();
|
||||
|
||||
activeTools = regularToolset.data();
|
||||
|
||||
|
@@ -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)))
|
||||
{
|
||||
|
@@ -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;
|
||||
|
@@ -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_;
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
|
@@ -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++)
|
||||
|
@@ -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();
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user