mirror of
https://github.com/The-Powder-Toy/The-Powder-Toy.git
synced 2025-08-08 01:16:33 +02:00
Do rendering on another thread when possible
"Possible" here means "when there are no particles with Lua graphics functions that haven't reported that they don't want to be called again and there are no beforesimdraw/aftersimdraw event handlers". I put my trust in Simulation::elementCount here; I sure hope it's always correct. If there is any of these, the renderer thread is paused and rendering happens on the main thread. To be clear, these are the situations in which Lua code is called with LuaScriptInterface::eventTraits having the eventTraitSimGraphics bit set. If the detection of this situation is somehow flawed, there will still be no crashes because when running on the renderer thread, Renderer is told to not call Lua functions, and GameController::BeforeSimDraw/AfterSimDraw is not called by GameView::RendererThread. The worst that can happen is that some particles are not rendered properly. Renderer settings (color and display modes, deco state, finding-element state, etc.) are managed by GameModel in the form of a RendererSettings and are passed to Renderer before each frame. The RenderableSimulation that Renderer works off of is also configured before each frame, either to point to a copy dedicated to the renderer thread, or directly to GameModel's Simulation, if the renderer thread is paused. Similarly, the result of the rendering is managed by GameView in the form of a RendererFrame, to enable e.g. sampling with deco tools without having to pause the renderer thread. Each time GameView::OnDraw is called, it checks whether rendering is allowed to happen on a different thread (see above for conditions). If it is, but the renderer thread is absent, GameView starts it and dispatches it (provides with settings and simulation data) right away. At this point, the renderer thread is definitely rendering a frame. GameView waits for this to finish and exchanges data with the renderer once it's done: it takes the result of the rendering and also dispatches the renderer thread again. This introduces a one-frame delay in rendering, which we can live with. If rendering is not allowed to happen on a different thread, GameView waits for the renderer thread to finish what it's currently doing and pauses it, then proceeds to render the frame by itself. Affecting this condition (whether rendering is allowed to happen on a different) by installing or removing event handlers, or clearing graphics cache (which, note, requires acquiring a unique lock on it), while the renderer thread is working, is not an issue because the renderer thread doesn't bother with event handlers, and because it acquires a shared lock on the graphics cache for rendering. The GameModel's Renderer is thus still primarily managed by GameView, potentially in two different threads, in a strictly non-overlapping manner. The exception to this is when RenderView butts in and starts doing renders of its own; in such cases, the renderer thread must be paused explicitly, as RenderView does by calling GameView::PauseRendererThread.
This commit is contained in:
@@ -52,8 +52,10 @@ int main(int argc, char *argv[])
|
|||||||
sim->Load(gameSave.get(), true, { 0, 0 });
|
sim->Load(gameSave.get(), true, { 0, 0 });
|
||||||
|
|
||||||
//Render save
|
//Render save
|
||||||
ren->decorations_enable = true;
|
RendererSettings rendererSettings;
|
||||||
ren->blackDecorations = true;
|
rendererSettings.decorations_enable = true;
|
||||||
|
rendererSettings.blackDecorations = true;
|
||||||
|
ren->ApplySettings(rendererSettings);
|
||||||
|
|
||||||
int frame = 15;
|
int frame = 15;
|
||||||
while(frame)
|
while(frame)
|
||||||
|
@@ -29,7 +29,7 @@ ThumbnailRendererTask::~ThumbnailRendererTask()
|
|||||||
|
|
||||||
bool ThumbnailRendererTask::doWork()
|
bool ThumbnailRendererTask::doWork()
|
||||||
{
|
{
|
||||||
thumbnail = SaveRenderer::Ref().Render(save.get(), decorations, fire);
|
thumbnail = SaveRenderer::Ref().Render(save.get(), decorations, fire, RendererSettings{});
|
||||||
if (thumbnail)
|
if (thumbnail)
|
||||||
{
|
{
|
||||||
thumbnail->ResizeToFit(size, true);
|
thumbnail->ResizeToFit(size, true);
|
||||||
|
@@ -2,10 +2,9 @@
|
|||||||
#include "Icons.h"
|
#include "Icons.h"
|
||||||
#include "RasterDrawMethods.h"
|
#include "RasterDrawMethods.h"
|
||||||
#include "gui/game/RenderPreset.h"
|
#include "gui/game/RenderPreset.h"
|
||||||
#include "gui/interface/Point.h"
|
#include "RendererSettings.h"
|
||||||
#include "common/tpt-rand.h"
|
#include "common/tpt-rand.h"
|
||||||
#include "RendererFrame.h"
|
#include "RendererFrame.h"
|
||||||
#include "FindingElement.h"
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -13,13 +12,13 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct RenderPreset;
|
struct RenderPreset;
|
||||||
struct RenderableSimulation;
|
|
||||||
class Renderer;
|
class Renderer;
|
||||||
|
struct RenderableSimulation;
|
||||||
struct Particle;
|
struct Particle;
|
||||||
|
|
||||||
struct GraphicsFuncContext
|
struct GraphicsFuncContext
|
||||||
{
|
{
|
||||||
const Renderer *ren;
|
const RendererSettings *ren;
|
||||||
const RenderableSimulation *sim;
|
const RenderableSimulation *sim;
|
||||||
RNG rng;
|
RNG rng;
|
||||||
const Particle *pipeSubcallCpart;
|
const Particle *pipeSubcallCpart;
|
||||||
@@ -28,7 +27,7 @@ struct GraphicsFuncContext
|
|||||||
|
|
||||||
int HeatToColour(float temp);
|
int HeatToColour(float temp);
|
||||||
|
|
||||||
class Renderer: public RasterDrawMethods<Renderer>
|
class Renderer : private RendererSettings, public RasterDrawMethods<Renderer>
|
||||||
{
|
{
|
||||||
RendererFrame video;
|
RendererFrame video;
|
||||||
std::array<pixel, WINDOW.X * RES.Y> persistentVideo;
|
std::array<pixel, WINDOW.X * RES.Y> persistentVideo;
|
||||||
@@ -41,39 +40,24 @@ class Renderer: public RasterDrawMethods<Renderer>
|
|||||||
|
|
||||||
friend struct RasterDrawMethods<Renderer>;
|
friend struct RasterDrawMethods<Renderer>;
|
||||||
|
|
||||||
float fireIntensity = 1;
|
RNG rng;
|
||||||
|
unsigned char fire_r[YCELLS][XCELLS];
|
||||||
|
unsigned char fire_g[YCELLS][XCELLS];
|
||||||
|
unsigned char fire_b[YCELLS][XCELLS];
|
||||||
|
unsigned int fire_alpha[CELL*3][CELL*3];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RNG rng;
|
|
||||||
const RenderableSimulation *sim = nullptr;
|
|
||||||
|
|
||||||
const RendererFrame &GetVideo() const
|
const RendererFrame &GetVideo() const
|
||||||
{
|
{
|
||||||
return video;
|
return video;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t renderMode = 0;
|
const RenderableSimulation *sim = nullptr;
|
||||||
uint32_t colorMode = 0;
|
|
||||||
uint32_t displayMode = 0;
|
void ApplySettings(const RendererSettings &newSettings);
|
||||||
|
|
||||||
static const std::vector<RenderPreset> renderModePresets;
|
static const std::vector<RenderPreset> renderModePresets;
|
||||||
//
|
|
||||||
unsigned char fire_r[YCELLS][XCELLS];
|
|
||||||
unsigned char fire_g[YCELLS][XCELLS];
|
|
||||||
unsigned char fire_b[YCELLS][XCELLS];
|
|
||||||
unsigned int fire_alpha[CELL*3][CELL*3];
|
|
||||||
//
|
|
||||||
bool gravityZonesEnabled;
|
|
||||||
bool gravityFieldEnabled;
|
|
||||||
int decorations_enable;
|
|
||||||
bool blackDecorations;
|
|
||||||
bool debugLines;
|
|
||||||
std::optional<FindingElement> findingElement;
|
|
||||||
int foundElements;
|
|
||||||
|
|
||||||
//Mouse position for debug information
|
|
||||||
ui::Point mousePos;
|
|
||||||
|
|
||||||
//Renderers
|
|
||||||
void RenderSimulation();
|
void RenderSimulation();
|
||||||
|
|
||||||
void DrawBlob(Vec2<int> pos, RGB<uint8_t> colour);
|
void DrawBlob(Vec2<int> pos, RGB<uint8_t> colour);
|
||||||
@@ -81,10 +65,6 @@ public:
|
|||||||
void DrawSigns();
|
void DrawSigns();
|
||||||
void render_gravlensing(const RendererFrame &source);
|
void render_gravlensing(const RendererFrame &source);
|
||||||
void render_fire();
|
void render_fire();
|
||||||
float GetFireIntensity() const
|
|
||||||
{
|
|
||||||
return fireIntensity;
|
|
||||||
}
|
|
||||||
void prepare_alpha(int size, float intensity);
|
void prepare_alpha(int size, float intensity);
|
||||||
void render_parts();
|
void render_parts();
|
||||||
void draw_grav_zones();
|
void draw_grav_zones();
|
||||||
@@ -95,22 +75,6 @@ public:
|
|||||||
void ClearAccumulation();
|
void ClearAccumulation();
|
||||||
void clearScreen();
|
void clearScreen();
|
||||||
|
|
||||||
void draw_icon(int x, int y, Icon icon);
|
|
||||||
|
|
||||||
//...
|
|
||||||
//Display mode modifiers
|
|
||||||
void SetRenderMode(uint32_t newRenderMode);
|
|
||||||
uint32_t GetRenderMode();
|
|
||||||
void SetDisplayMode(uint32_t newDisplayMode);
|
|
||||||
uint32_t GetDisplayMode();
|
|
||||||
void SetColorMode(uint32_t newColorMode);
|
|
||||||
uint32_t GetColorMode();
|
|
||||||
|
|
||||||
void ResetModes();
|
|
||||||
|
|
||||||
int GetGridSize() { return gridSize; }
|
|
||||||
void SetGridSize(int value) { gridSize = value; }
|
|
||||||
|
|
||||||
static std::unique_ptr<VideoBuffer> WallIcon(int wallID, Vec2<int> size);
|
static std::unique_ptr<VideoBuffer> WallIcon(int wallID, Vec2<int> size);
|
||||||
|
|
||||||
Renderer();
|
Renderer();
|
||||||
@@ -140,7 +104,4 @@ public:
|
|||||||
RENDERER_TABLE(firwTable)
|
RENDERER_TABLE(firwTable)
|
||||||
#undef RENDERER_TABLE
|
#undef RENDERER_TABLE
|
||||||
static void PopulateTables();
|
static void PopulateTables();
|
||||||
|
|
||||||
private:
|
|
||||||
int gridSize;
|
|
||||||
};
|
};
|
||||||
|
@@ -180,15 +180,7 @@ void Renderer::PopulateTables()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer::Renderer():
|
Renderer::Renderer()
|
||||||
gravityZonesEnabled(false),
|
|
||||||
gravityFieldEnabled(false),
|
|
||||||
decorations_enable(1),
|
|
||||||
blackDecorations(false),
|
|
||||||
debugLines(false),
|
|
||||||
foundElements(0),
|
|
||||||
mousePos(0, 0),
|
|
||||||
gridSize(0)
|
|
||||||
{
|
{
|
||||||
PopulateTables();
|
PopulateTables();
|
||||||
|
|
||||||
@@ -197,9 +189,8 @@ Renderer::Renderer():
|
|||||||
memset(fire_b, 0, sizeof(fire_b));
|
memset(fire_b, 0, sizeof(fire_b));
|
||||||
|
|
||||||
//Set defauly display modes
|
//Set defauly display modes
|
||||||
ResetModes();
|
|
||||||
|
|
||||||
prepare_alpha(CELL, 1.0f);
|
prepare_alpha(CELL, 1.0f);
|
||||||
|
ClearAccumulation();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::ClearAccumulation()
|
void Renderer::ClearAccumulation()
|
||||||
@@ -210,51 +201,17 @@ void Renderer::ClearAccumulation()
|
|||||||
std::fill(persistentVideo.begin(), persistentVideo.end(), 0);
|
std::fill(persistentVideo.begin(), persistentVideo.end(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::SetRenderMode(uint32_t newRenderMode)
|
void Renderer::ApplySettings(const RendererSettings &newSettings)
|
||||||
{
|
{
|
||||||
int oldRenderMode = renderMode;
|
if (!(newSettings.renderMode & FIREMODE) && (renderMode & FIREMODE))
|
||||||
renderMode = newRenderMode;
|
|
||||||
if (!(renderMode & FIREMODE) && (oldRenderMode & FIREMODE))
|
|
||||||
{
|
{
|
||||||
ClearAccumulation();
|
ClearAccumulation();
|
||||||
}
|
}
|
||||||
}
|
if (!(newSettings.displayMode & DISPLAY_PERS) && (displayMode & DISPLAY_PERS))
|
||||||
|
|
||||||
uint32_t Renderer::GetRenderMode()
|
|
||||||
{
|
|
||||||
return renderMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::SetDisplayMode(uint32_t newDisplayMode)
|
|
||||||
{
|
|
||||||
int oldDisplayMode = displayMode;
|
|
||||||
displayMode = newDisplayMode;
|
|
||||||
if (!(displayMode & DISPLAY_PERS) && (oldDisplayMode & DISPLAY_PERS))
|
|
||||||
{
|
{
|
||||||
ClearAccumulation();
|
ClearAccumulation();
|
||||||
}
|
}
|
||||||
}
|
static_cast<RendererSettings &>(*this) = newSettings;
|
||||||
|
|
||||||
uint32_t Renderer::GetDisplayMode()
|
|
||||||
{
|
|
||||||
return displayMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::SetColorMode(uint32_t newColorMode)
|
|
||||||
{
|
|
||||||
colorMode = newColorMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t Renderer::GetColorMode()
|
|
||||||
{
|
|
||||||
return colorMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::ResetModes()
|
|
||||||
{
|
|
||||||
SetRenderMode(RENDER_BASC | RENDER_FIRE | RENDER_SPRK | RENDER_EFFE);
|
|
||||||
SetDisplayMode(0);
|
|
||||||
SetColorMode(COLOUR_DEFAULT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template struct RasterDrawMethods<Renderer>;
|
template struct RasterDrawMethods<Renderer>;
|
||||||
|
23
src/graphics/RendererSettings.h
Normal file
23
src/graphics/RendererSettings.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "gui/interface/Point.h"
|
||||||
|
#include "simulation/ElementGraphics.h"
|
||||||
|
#include "FindingElement.h"
|
||||||
|
#include <cstdint>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
struct RendererSettings
|
||||||
|
{
|
||||||
|
uint32_t renderMode = RENDER_BASC | RENDER_FIRE | RENDER_SPRK | RENDER_EFFE;
|
||||||
|
uint32_t displayMode = 0;
|
||||||
|
uint32_t colorMode = COLOUR_DEFAULT;
|
||||||
|
std::optional<FindingElement> findingElement;
|
||||||
|
bool gravityZonesEnabled = false;
|
||||||
|
bool gravityFieldEnabled = false;
|
||||||
|
int decorations_enable = 1;
|
||||||
|
bool blackDecorations = false;
|
||||||
|
bool debugLines = false;
|
||||||
|
int foundElements = 0;
|
||||||
|
ui::Point mousePos = { 0, 0 };
|
||||||
|
int gridSize = 0;
|
||||||
|
float fireIntensity = 1;
|
||||||
|
};
|
@@ -271,9 +271,9 @@ void GameController::Install()
|
|||||||
void GameController::AdjustGridSize(int direction)
|
void GameController::AdjustGridSize(int direction)
|
||||||
{
|
{
|
||||||
if(direction > 0)
|
if(direction > 0)
|
||||||
gameModel->GetRenderer()->SetGridSize((gameModel->GetRenderer()->GetGridSize()+1)%10);
|
gameModel->GetRendererSettings().gridSize = (gameModel->GetRendererSettings().gridSize+1)%10;
|
||||||
else
|
else
|
||||||
gameModel->GetRenderer()->SetGridSize((gameModel->GetRenderer()->GetGridSize()+9)%10);
|
gameModel->GetRendererSettings().gridSize = (gameModel->GetRendererSettings().gridSize+9)%10;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameController::InvertAirSim()
|
void GameController::InvertAirSim()
|
||||||
@@ -851,19 +851,19 @@ void GameController::ToggleNewtonianGravity()
|
|||||||
|
|
||||||
void GameController::LoadRenderPreset(int presetNum)
|
void GameController::LoadRenderPreset(int presetNum)
|
||||||
{
|
{
|
||||||
Renderer * renderer = gameModel->GetRenderer();
|
auto &settings = gameModel->GetRendererSettings();
|
||||||
RenderPreset preset = Renderer::renderModePresets[presetNum];
|
RenderPreset preset = Renderer::renderModePresets[presetNum];
|
||||||
gameModel->SetInfoTip(preset.Name);
|
gameModel->SetInfoTip(preset.Name);
|
||||||
renderer->SetRenderMode(preset.renderMode);
|
settings.renderMode = preset.renderMode;
|
||||||
renderer->SetDisplayMode(preset.displayMode);
|
settings.displayMode = preset.displayMode;
|
||||||
renderer->SetColorMode(preset.colorMode);
|
settings.colorMode = preset.colorMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameController::Update()
|
void GameController::Update()
|
||||||
{
|
{
|
||||||
auto &sd = SimulationData::CRef();
|
auto &sd = SimulationData::CRef();
|
||||||
ui::Point pos = gameView->GetMousePosition();
|
ui::Point pos = gameView->GetMousePosition();
|
||||||
gameModel->GetRenderer()->mousePos = PointTranslate(pos);
|
gameModel->GetRendererSettings().mousePos = PointTranslate(pos);
|
||||||
if (pos.X < XRES && pos.Y < YRES)
|
if (pos.X < XRES && pos.Y < YRES)
|
||||||
gameView->SetSample(gameModel->GetSimulation()->GetSample(PointTranslate(pos).X, PointTranslate(pos).Y));
|
gameView->SetSample(gameModel->GetSimulation()->GetSample(PointTranslate(pos).X, PointTranslate(pos).Y));
|
||||||
else
|
else
|
||||||
@@ -1106,7 +1106,7 @@ void GameController::SetActiveTool(int toolSelection, Tool * tool)
|
|||||||
if (gameModel->GetActiveMenu() == SC_DECO && toolSelection == 2)
|
if (gameModel->GetActiveMenu() == SC_DECO && toolSelection == 2)
|
||||||
toolSelection = 0;
|
toolSelection = 0;
|
||||||
gameModel->SetActiveTool(toolSelection, tool);
|
gameModel->SetActiveTool(toolSelection, tool);
|
||||||
gameModel->GetRenderer()->gravityZonesEnabled = false;
|
gameModel->GetRendererSettings().gravityZonesEnabled = false;
|
||||||
if (toolSelection == 3)
|
if (toolSelection == 3)
|
||||||
gameModel->GetSimulation()->replaceModeSelected = tool->ToolID;
|
gameModel->GetSimulation()->replaceModeSelected = tool->ToolID;
|
||||||
gameModel->SetLastTool(tool);
|
gameModel->SetLastTool(tool);
|
||||||
@@ -1115,7 +1115,7 @@ void GameController::SetActiveTool(int toolSelection, Tool * tool)
|
|||||||
auto *activeTool = gameModel->GetActiveTool(i);
|
auto *activeTool = gameModel->GetActiveTool(i);
|
||||||
if (activeTool && activeTool->Identifier == "DEFAULT_WL_GRVTY")
|
if (activeTool && activeTool->Identifier == "DEFAULT_WL_GRVTY")
|
||||||
{
|
{
|
||||||
gameModel->GetRenderer()->gravityZonesEnabled = true;
|
gameModel->GetRendererSettings().gravityZonesEnabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tool->Identifier == "DEFAULT_UI_PROPERTY")
|
if (tool->Identifier == "DEFAULT_UI_PROPERTY")
|
||||||
@@ -1404,7 +1404,7 @@ void GameController::HideConsole()
|
|||||||
|
|
||||||
void GameController::OpenRenderOptions()
|
void GameController::OpenRenderOptions()
|
||||||
{
|
{
|
||||||
renderOptions = new RenderController(gameModel->GetSimulation(), gameModel->GetRenderer(), NULL);
|
renderOptions = new RenderController(gameModel->GetSimulation(), gameModel->GetRenderer(), &gameModel->GetRendererSettings(), NULL);
|
||||||
ui::Engine::Ref().ShowWindow(renderOptions->GetView());
|
ui::Engine::Ref().ShowWindow(renderOptions->GetView());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1727,3 +1727,8 @@ void GameController::AfterSimDraw()
|
|||||||
{
|
{
|
||||||
commandInterface->HandleEvent(AfterSimDrawEvent{});
|
commandInterface->HandleEvent(AfterSimDrawEvent{});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GameController::HaveSimGraphicsEventHandlers()
|
||||||
|
{
|
||||||
|
return commandInterface->HaveSimGraphicsEventHandlers();
|
||||||
|
}
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
#include "lua/CommandInterfacePtr.h"
|
#include "lua/CommandInterfacePtr.h"
|
||||||
#include "client/ClientListener.h"
|
#include "client/ClientListener.h"
|
||||||
#include "client/StartupInfo.h"
|
#include "client/StartupInfo.h"
|
||||||
|
#include "common/ExplicitSingleton.h"
|
||||||
#include "gui/interface/Point.h"
|
#include "gui/interface/Point.h"
|
||||||
#include "gui/interface/Colour.h"
|
#include "gui/interface/Colour.h"
|
||||||
#include "gui/SavePreviewType.h"
|
#include "gui/SavePreviewType.h"
|
||||||
@@ -37,7 +38,7 @@ class GameSave;
|
|||||||
class LoginController;
|
class LoginController;
|
||||||
class TagsController;
|
class TagsController;
|
||||||
class ConsoleController;
|
class ConsoleController;
|
||||||
class GameController: public ClientListener
|
class GameController : public ClientListener, public ExplicitSingleton<GameController>
|
||||||
{
|
{
|
||||||
CommandInterfacePtr commandInterface;
|
CommandInterfacePtr commandInterface;
|
||||||
|
|
||||||
@@ -204,4 +205,5 @@ public:
|
|||||||
|
|
||||||
void BeforeSimDraw();
|
void BeforeSimDraw();
|
||||||
void AfterSimDraw();
|
void AfterSimDraw();
|
||||||
|
bool HaveSimGraphicsEventHandlers();
|
||||||
};
|
};
|
||||||
|
@@ -91,15 +91,15 @@ GameModel::GameModel():
|
|||||||
setFunc(*pref);
|
setFunc(*pref);
|
||||||
};
|
};
|
||||||
handleOldModes("Renderer.RenderMode", "Renderer.RenderModes", RENDER_FIRE | RENDER_EFFE | RENDER_BASC, [this](uint32_t renderMode) {
|
handleOldModes("Renderer.RenderMode", "Renderer.RenderModes", RENDER_FIRE | RENDER_EFFE | RENDER_BASC, [this](uint32_t renderMode) {
|
||||||
ren->SetRenderMode(renderMode);
|
rendererSettings.renderMode = renderMode;
|
||||||
});
|
});
|
||||||
handleOldModes("Renderer.DisplayMode", "Renderer.DisplayModes", 0, [this](uint32_t displayMode) {
|
handleOldModes("Renderer.DisplayMode", "Renderer.DisplayModes", 0, [this](uint32_t displayMode) {
|
||||||
ren->SetDisplayMode(displayMode);
|
rendererSettings.displayMode = displayMode;
|
||||||
});
|
});
|
||||||
ren->SetColorMode(prefs.Get("Renderer.ColourMode", UINT32_C(0)));
|
rendererSettings.colorMode = prefs.Get("Renderer.ColourMode", UINT32_C(0));
|
||||||
|
|
||||||
ren->gravityFieldEnabled = prefs.Get("Renderer.GravityField", false);
|
rendererSettings.gravityFieldEnabled = prefs.Get("Renderer.GravityField", false);
|
||||||
ren->decorations_enable = prefs.Get("Renderer.Decorations", true);
|
rendererSettings.decorations_enable = prefs.Get("Renderer.Decorations", true);
|
||||||
|
|
||||||
//Load config into simulation
|
//Load config into simulation
|
||||||
edgeMode = prefs.Get("Simulation.EdgeMode", NUM_EDGEMODES, EDGE_VOID);
|
edgeMode = prefs.Get("Simulation.EdgeMode", NUM_EDGEMODES, EDGE_VOID);
|
||||||
@@ -170,12 +170,12 @@ GameModel::~GameModel()
|
|||||||
{
|
{
|
||||||
//Save to config:
|
//Save to config:
|
||||||
Prefs::DeferWrite dw(prefs);
|
Prefs::DeferWrite dw(prefs);
|
||||||
prefs.Set("Renderer.ColourMode", ren->GetColorMode());
|
prefs.Set("Renderer.ColourMode", rendererSettings.colorMode);
|
||||||
prefs.Set("Renderer.DisplayMode", ren->GetDisplayMode());
|
prefs.Set("Renderer.DisplayMode", rendererSettings.displayMode);
|
||||||
prefs.Set("Renderer.RenderMode", ren->GetRenderMode());
|
prefs.Set("Renderer.RenderMode", rendererSettings.renderMode);
|
||||||
prefs.Set("Renderer.GravityField", (bool)ren->gravityFieldEnabled);
|
prefs.Set("Renderer.GravityField", (bool)rendererSettings.gravityFieldEnabled);
|
||||||
prefs.Set("Renderer.Decorations", (bool)ren->decorations_enable);
|
prefs.Set("Renderer.Decorations", (bool)rendererSettings.decorations_enable);
|
||||||
prefs.Set("Renderer.DebugMode", ren->debugLines); //These two should always be equivalent, even though they are different things
|
prefs.Set("Renderer.DebugMode", rendererSettings.debugLines); //These two should always be equivalent, even though they are different things
|
||||||
prefs.Set("Simulation.NewtonianGravity", bool(sim->grav));
|
prefs.Set("Simulation.NewtonianGravity", bool(sim->grav));
|
||||||
prefs.Set("Simulation.AmbientHeat", sim->aheat_enable);
|
prefs.Set("Simulation.AmbientHeat", sim->aheat_enable);
|
||||||
prefs.Set("Simulation.PrettyPowder", sim->pretty_powder);
|
prefs.Set("Simulation.PrettyPowder", sim->pretty_powder);
|
||||||
@@ -1260,9 +1260,9 @@ bool GameModel::GetPaused()
|
|||||||
|
|
||||||
void GameModel::SetDecoration(bool decorationState)
|
void GameModel::SetDecoration(bool decorationState)
|
||||||
{
|
{
|
||||||
if (ren->decorations_enable != (decorationState?1:0))
|
if (rendererSettings.decorations_enable != (decorationState?1:0))
|
||||||
{
|
{
|
||||||
ren->decorations_enable = decorationState?1:0;
|
rendererSettings.decorations_enable = decorationState?1:0;
|
||||||
notifyDecorationChanged();
|
notifyDecorationChanged();
|
||||||
UpdateQuickOptions();
|
UpdateQuickOptions();
|
||||||
if (decorationState)
|
if (decorationState)
|
||||||
@@ -1274,7 +1274,7 @@ void GameModel::SetDecoration(bool decorationState)
|
|||||||
|
|
||||||
bool GameModel::GetDecoration()
|
bool GameModel::GetDecoration()
|
||||||
{
|
{
|
||||||
return ren->decorations_enable?true:false;
|
return rendererSettings.decorations_enable?true:false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameModel::SetAHeatEnable(bool aHeat)
|
void GameModel::SetAHeatEnable(bool aHeat)
|
||||||
@@ -1318,7 +1318,7 @@ bool GameModel::GetNewtonianGrvity()
|
|||||||
|
|
||||||
void GameModel::ShowGravityGrid(bool showGrid)
|
void GameModel::ShowGravityGrid(bool showGrid)
|
||||||
{
|
{
|
||||||
ren->gravityFieldEnabled = showGrid;
|
rendererSettings.gravityFieldEnabled = showGrid;
|
||||||
if (showGrid)
|
if (showGrid)
|
||||||
SetInfoTip("Gravity Grid: On");
|
SetInfoTip("Gravity Grid: On");
|
||||||
else
|
else
|
||||||
@@ -1327,7 +1327,7 @@ void GameModel::ShowGravityGrid(bool showGrid)
|
|||||||
|
|
||||||
bool GameModel::GetGravityGrid()
|
bool GameModel::GetGravityGrid()
|
||||||
{
|
{
|
||||||
return ren->gravityFieldEnabled;
|
return rendererSettings.gravityFieldEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameModel::FrameStep(int frames)
|
void GameModel::FrameStep(int frames)
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
#include "gui/interface/Colour.h"
|
#include "gui/interface/Colour.h"
|
||||||
#include "client/User.h"
|
#include "client/User.h"
|
||||||
#include "gui/interface/Point.h"
|
#include "gui/interface/Point.h"
|
||||||
|
#include "graphics/RendererSettings.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -66,6 +67,7 @@ private:
|
|||||||
|
|
||||||
Simulation * sim;
|
Simulation * sim;
|
||||||
Renderer * ren;
|
Renderer * ren;
|
||||||
|
RendererSettings rendererSettings;
|
||||||
std::vector<Menu*> menuList;
|
std::vector<Menu*> menuList;
|
||||||
std::vector<QuickOption*> quickOptions;
|
std::vector<QuickOption*> quickOptions;
|
||||||
int activeMenu;
|
int activeMenu;
|
||||||
@@ -231,6 +233,10 @@ public:
|
|||||||
void SetUser(User user);
|
void SetUser(User user);
|
||||||
Simulation * GetSimulation();
|
Simulation * GetSimulation();
|
||||||
Renderer * GetRenderer();
|
Renderer * GetRenderer();
|
||||||
|
RendererSettings &GetRendererSettings()
|
||||||
|
{
|
||||||
|
return rendererSettings;
|
||||||
|
}
|
||||||
void SetZoomEnabled(bool enabled);
|
void SetZoomEnabled(bool enabled);
|
||||||
bool GetZoomEnabled();
|
bool GetZoomEnabled();
|
||||||
void SetZoomSize(int size);
|
void SetZoomSize(int size);
|
||||||
|
@@ -203,7 +203,6 @@ GameView::GameView():
|
|||||||
recordingFolder(0),
|
recordingFolder(0),
|
||||||
currentPoint(ui::Point(0, 0)),
|
currentPoint(ui::Point(0, 0)),
|
||||||
lastPoint(ui::Point(0, 0)),
|
lastPoint(ui::Point(0, 0)),
|
||||||
ren(NULL),
|
|
||||||
activeBrush(NULL),
|
activeBrush(NULL),
|
||||||
saveSimulationButtonEnabled(false),
|
saveSimulationButtonEnabled(false),
|
||||||
saveReuploadAllowed(true),
|
saveReuploadAllowed(true),
|
||||||
@@ -332,6 +331,7 @@ GameView::GameView():
|
|||||||
|
|
||||||
GameView::~GameView()
|
GameView::~GameView()
|
||||||
{
|
{
|
||||||
|
StopRendererThread();
|
||||||
if(!colourPicker->GetParentWindow())
|
if(!colourPicker->GetParentWindow())
|
||||||
delete colourPicker;
|
delete colourPicker;
|
||||||
|
|
||||||
@@ -470,8 +470,7 @@ bool GameView::GetBrushEnable()
|
|||||||
void GameView::SetDebugHUD(bool mode)
|
void GameView::SetDebugHUD(bool mode)
|
||||||
{
|
{
|
||||||
showDebug = mode;
|
showDebug = mode;
|
||||||
if (ren)
|
rendererSettings->debugLines = showDebug;
|
||||||
ren->debugLines = showDebug;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameView::GetDebugHUD()
|
bool GameView::GetDebugHUD()
|
||||||
@@ -518,9 +517,10 @@ void GameView::NotifyActiveToolsChanged(GameModel * sender)
|
|||||||
|
|
||||||
decoBrush = sender->GetActiveTool(0)->Identifier.BeginsWith("DEFAULT_DECOR_");
|
decoBrush = sender->GetActiveTool(0)->Identifier.BeginsWith("DEFAULT_DECOR_");
|
||||||
|
|
||||||
if (sender->GetRenderer()->findingElement)
|
auto &settings = sender->GetRendererSettings();
|
||||||
|
if (settings.findingElement)
|
||||||
{
|
{
|
||||||
ren->findingElement = FindingElementCandidate();
|
settings.findingElement = FindingElementCandidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -734,6 +734,7 @@ void GameView::NotifyColourSelectorColourChanged(GameModel * sender)
|
|||||||
void GameView::NotifyRendererChanged(GameModel * sender)
|
void GameView::NotifyRendererChanged(GameModel * sender)
|
||||||
{
|
{
|
||||||
ren = sender->GetRenderer();
|
ren = sender->GetRenderer();
|
||||||
|
rendererSettings = &sender->GetRendererSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameView::NotifySimulationChanged(GameModel * sender)
|
void GameView::NotifySimulationChanged(GameModel * sender)
|
||||||
@@ -1443,13 +1444,13 @@ void GameView::OnKeyPress(int key, int scan, bool repeat, bool shift, bool ctrl,
|
|||||||
if (ctrl)
|
if (ctrl)
|
||||||
{
|
{
|
||||||
auto findingElementCandidate = FindingElementCandidate();
|
auto findingElementCandidate = FindingElementCandidate();
|
||||||
if (ren->findingElement == findingElementCandidate)
|
if (rendererSettings->findingElement == findingElementCandidate)
|
||||||
{
|
{
|
||||||
ren->findingElement = std::nullopt;
|
rendererSettings->findingElement = std::nullopt;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ren->findingElement = findingElementCandidate;
|
rendererSettings->findingElement = findingElementCandidate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1982,7 +1983,7 @@ void GameView::NotifyTransformedPlaceSaveChanged(GameModel *sender)
|
|||||||
{
|
{
|
||||||
if (sender->GetTransformedPlaceSave())
|
if (sender->GetTransformedPlaceSave())
|
||||||
{
|
{
|
||||||
placeSaveThumb = SaveRenderer::Ref().Render(sender->GetTransformedPlaceSave(), true, true, sender->GetRenderer());
|
placeSaveThumb = SaveRenderer::Ref().Render(sender->GetTransformedPlaceSave(), true, true, sender->GetRendererSettings());
|
||||||
selectMode = PlaceSave;
|
selectMode = PlaceSave;
|
||||||
selectPoint2 = mousePosition;
|
selectPoint2 = mousePosition;
|
||||||
}
|
}
|
||||||
@@ -2126,166 +2127,189 @@ void GameView::SetSaveButtonTooltips()
|
|||||||
saveSimulationButton->SetToolTips("Re-upload the current simulation", "Upload a new simulation. Hold Ctrl to save offline.");
|
saveSimulationButton->SetToolTips("Re-upload the current simulation", "Upload a new simulation. Hold Ctrl to save offline.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameView::RenderSimulation(const RenderableSimulation &sim, bool handleEvents)
|
||||||
|
{
|
||||||
|
ren->sim = ∼
|
||||||
|
ren->clearScreen();
|
||||||
|
ren->draw_air();
|
||||||
|
if (handleEvents)
|
||||||
|
{
|
||||||
|
c->BeforeSimDraw();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// we may write graphicscache here
|
||||||
|
auto &sd = SimulationData::Ref();
|
||||||
|
std::unique_lock lk(sd.elementGraphicsMx);
|
||||||
|
ren->RenderSimulation();
|
||||||
|
}
|
||||||
|
if (handleEvents)
|
||||||
|
{
|
||||||
|
c->AfterSimDraw();
|
||||||
|
}
|
||||||
|
ren->sim = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void GameView::OnDraw()
|
void GameView::OnDraw()
|
||||||
{
|
{
|
||||||
Graphics * g = GetGraphics();
|
Graphics * g = GetGraphics();
|
||||||
if (ren)
|
|
||||||
|
auto wantRendererThread = !c->HaveSimGraphicsEventHandlers();
|
||||||
|
if (wantRendererThread)
|
||||||
{
|
{
|
||||||
// we're the main thread, we may write graphicscache
|
StartRendererThread();
|
||||||
auto &sd = SimulationData::Ref();
|
WaitForRendererThread();
|
||||||
std::unique_lock lk(sd.elementGraphicsMx);
|
|
||||||
ren->sim = sim;
|
|
||||||
ren->clearScreen();
|
|
||||||
ren->draw_air();
|
|
||||||
c->BeforeSimDraw();
|
|
||||||
ren->RenderSimulation();
|
|
||||||
ren->sim = nullptr;
|
|
||||||
|
|
||||||
c->AfterSimDraw();
|
|
||||||
|
|
||||||
rendererFrame = ren->GetVideo();
|
rendererFrame = ren->GetVideo();
|
||||||
std::copy_n(rendererFrame.data(), rendererFrame.Size().X * rendererFrame.Size().Y, g->Data());
|
DispatchRendererThread();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PauseRendererThread();
|
||||||
|
ren->ApplySettings(*rendererSettings);
|
||||||
|
RenderSimulation(*sim, true);
|
||||||
|
rendererFrame = ren->GetVideo();
|
||||||
|
}
|
||||||
|
|
||||||
if (showBrush && selectMode == SelectNone && (!zoomEnabled || zoomCursorFixed) && activeBrush && (isMouseDown || (currentMouse.X >= 0 && currentMouse.X < XRES && currentMouse.Y >= 0 && currentMouse.Y < YRES)))
|
std::copy_n(rendererFrame.data(), rendererFrame.Size().X * rendererFrame.Size().Y, g->Data());
|
||||||
|
|
||||||
|
if (showBrush && selectMode == SelectNone && (!zoomEnabled || zoomCursorFixed) && activeBrush && (isMouseDown || (currentMouse.X >= 0 && currentMouse.X < XRES && currentMouse.Y >= 0 && currentMouse.Y < YRES)))
|
||||||
|
{
|
||||||
|
ui::Point finalCurrentMouse = windTool ? c->PointTranslateNoClamp(currentMouse) : c->PointTranslate(currentMouse);
|
||||||
|
ui::Point initialDrawPoint = drawPoint1;
|
||||||
|
|
||||||
|
if (wallBrush)
|
||||||
{
|
{
|
||||||
ui::Point finalCurrentMouse = windTool ? c->PointTranslateNoClamp(currentMouse) : c->PointTranslate(currentMouse);
|
finalCurrentMouse = c->NormaliseBlockCoord(finalCurrentMouse);
|
||||||
ui::Point initialDrawPoint = drawPoint1;
|
initialDrawPoint = c->NormaliseBlockCoord(initialDrawPoint);
|
||||||
|
|
||||||
if (wallBrush)
|
|
||||||
{
|
|
||||||
finalCurrentMouse = c->NormaliseBlockCoord(finalCurrentMouse);
|
|
||||||
initialDrawPoint = c->NormaliseBlockCoord(initialDrawPoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (drawMode == DrawRect && isMouseDown)
|
|
||||||
{
|
|
||||||
if (drawSnap)
|
|
||||||
{
|
|
||||||
finalCurrentMouse = rectSnapCoords(c->PointTranslate(initialDrawPoint), finalCurrentMouse);
|
|
||||||
}
|
|
||||||
if (wallBrush)
|
|
||||||
{
|
|
||||||
if (finalCurrentMouse.X > initialDrawPoint.X)
|
|
||||||
finalCurrentMouse.X += CELL-1;
|
|
||||||
else
|
|
||||||
initialDrawPoint.X += CELL-1;
|
|
||||||
|
|
||||||
if (finalCurrentMouse.Y > initialDrawPoint.Y)
|
|
||||||
finalCurrentMouse.Y += CELL-1;
|
|
||||||
else
|
|
||||||
initialDrawPoint.Y += CELL-1;
|
|
||||||
}
|
|
||||||
activeBrush->RenderRect(g, c->PointTranslate(initialDrawPoint), finalCurrentMouse);
|
|
||||||
}
|
|
||||||
else if (drawMode == DrawLine && isMouseDown)
|
|
||||||
{
|
|
||||||
if (drawSnap)
|
|
||||||
{
|
|
||||||
finalCurrentMouse = lineSnapCoords(c->PointTranslate(initialDrawPoint), finalCurrentMouse);
|
|
||||||
}
|
|
||||||
activeBrush->RenderLine(g, c->PointTranslate(initialDrawPoint), finalCurrentMouse);
|
|
||||||
}
|
|
||||||
else if (drawMode == DrawFill)// || altBehaviour)
|
|
||||||
{
|
|
||||||
if (!decoBrush)
|
|
||||||
activeBrush->RenderFill(g, finalCurrentMouse);
|
|
||||||
}
|
|
||||||
if (drawMode == DrawPoints || drawMode==DrawLine || (drawMode == DrawRect && !isMouseDown))
|
|
||||||
{
|
|
||||||
if (wallBrush)
|
|
||||||
{
|
|
||||||
ui::Point finalBrushRadius = c->NormaliseBlockCoord(activeBrush->GetRadius());
|
|
||||||
auto topLeft = finalCurrentMouse - finalBrushRadius;
|
|
||||||
auto bottomRight = finalCurrentMouse + finalBrushRadius + Vec2{ CELL - 1, CELL - 1 };
|
|
||||||
g->XorLine({ topLeft.X, topLeft.Y }, { bottomRight.X, topLeft.Y });
|
|
||||||
g->XorLine({ topLeft.X, bottomRight.Y }, { bottomRight.X, bottomRight.Y });
|
|
||||||
g->XorLine({ topLeft.X, topLeft.Y + 1 }, { topLeft.X, bottomRight.Y - 1 }); // offset by 1 so the corners don't get xor'd twice
|
|
||||||
g->XorLine({ bottomRight.X, topLeft.Y + 1 }, { bottomRight.X, bottomRight.Y - 1 }); // offset by 1 so the corners don't get xor'd twice
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
activeBrush->RenderPoint(g, finalCurrentMouse);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(selectMode!=SelectNone)
|
if (drawMode == DrawRect && isMouseDown)
|
||||||
{
|
{
|
||||||
if(selectMode==PlaceSave)
|
if (drawSnap)
|
||||||
{
|
{
|
||||||
if(placeSaveThumb && selectPoint2.X!=-1)
|
finalCurrentMouse = rectSnapCoords(c->PointTranslate(initialDrawPoint), finalCurrentMouse);
|
||||||
{
|
}
|
||||||
auto rect = RectSized(PlaceSavePos() * CELL, placeSaveThumb->Size());
|
if (wallBrush)
|
||||||
g->BlendImage(placeSaveThumb->Data(), 0x80, rect);
|
{
|
||||||
g->XorDottedRect(rect);
|
if (finalCurrentMouse.X > initialDrawPoint.X)
|
||||||
}
|
finalCurrentMouse.X += CELL-1;
|
||||||
|
else
|
||||||
|
initialDrawPoint.X += CELL-1;
|
||||||
|
|
||||||
|
if (finalCurrentMouse.Y > initialDrawPoint.Y)
|
||||||
|
finalCurrentMouse.Y += CELL-1;
|
||||||
|
else
|
||||||
|
initialDrawPoint.Y += CELL-1;
|
||||||
|
}
|
||||||
|
activeBrush->RenderRect(g, c->PointTranslate(initialDrawPoint), finalCurrentMouse);
|
||||||
|
}
|
||||||
|
else if (drawMode == DrawLine && isMouseDown)
|
||||||
|
{
|
||||||
|
if (drawSnap)
|
||||||
|
{
|
||||||
|
finalCurrentMouse = lineSnapCoords(c->PointTranslate(initialDrawPoint), finalCurrentMouse);
|
||||||
|
}
|
||||||
|
activeBrush->RenderLine(g, c->PointTranslate(initialDrawPoint), finalCurrentMouse);
|
||||||
|
}
|
||||||
|
else if (drawMode == DrawFill)// || altBehaviour)
|
||||||
|
{
|
||||||
|
if (!decoBrush)
|
||||||
|
activeBrush->RenderFill(g, finalCurrentMouse);
|
||||||
|
}
|
||||||
|
if (drawMode == DrawPoints || drawMode==DrawLine || (drawMode == DrawRect && !isMouseDown))
|
||||||
|
{
|
||||||
|
if (wallBrush)
|
||||||
|
{
|
||||||
|
ui::Point finalBrushRadius = c->NormaliseBlockCoord(activeBrush->GetRadius());
|
||||||
|
auto topLeft = finalCurrentMouse - finalBrushRadius;
|
||||||
|
auto bottomRight = finalCurrentMouse + finalBrushRadius + Vec2{ CELL - 1, CELL - 1 };
|
||||||
|
g->XorLine({ topLeft.X, topLeft.Y }, { bottomRight.X, topLeft.Y });
|
||||||
|
g->XorLine({ topLeft.X, bottomRight.Y }, { bottomRight.X, bottomRight.Y });
|
||||||
|
g->XorLine({ topLeft.X, topLeft.Y + 1 }, { topLeft.X, bottomRight.Y - 1 }); // offset by 1 so the corners don't get xor'd twice
|
||||||
|
g->XorLine({ bottomRight.X, topLeft.Y + 1 }, { bottomRight.X, bottomRight.Y - 1 }); // offset by 1 so the corners don't get xor'd twice
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(selectPoint1.X==-1)
|
activeBrush->RenderPoint(g, finalCurrentMouse);
|
||||||
{
|
|
||||||
g->BlendFilledRect(RectSized(Vec2{ 0, 0 }, Vec2{ XRES, YRES }), 0x000000_rgb .WithAlpha(100));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int x2 = (selectPoint1.X>selectPoint2.X)?selectPoint1.X:selectPoint2.X;
|
|
||||||
int y2 = (selectPoint1.Y>selectPoint2.Y)?selectPoint1.Y:selectPoint2.Y;
|
|
||||||
int x1 = (selectPoint2.X<selectPoint1.X)?selectPoint2.X:selectPoint1.X;
|
|
||||||
int y1 = (selectPoint2.Y<selectPoint1.Y)?selectPoint2.Y:selectPoint1.Y;
|
|
||||||
|
|
||||||
if(x2>XRES-1)
|
|
||||||
x2 = XRES-1;
|
|
||||||
if(y2>YRES-1)
|
|
||||||
y2 = YRES-1;
|
|
||||||
|
|
||||||
g->BlendFilledRect(RectSized(Vec2{ 0, 0 }, Vec2{ XRES, y1 }), 0x000000_rgb .WithAlpha(100));
|
|
||||||
g->BlendFilledRect(RectSized(Vec2{ 0, y2+1 }, Vec2{ XRES, YRES-y2-1 }), 0x000000_rgb .WithAlpha(100));
|
|
||||||
|
|
||||||
g->BlendFilledRect(RectSized(Vec2{ 0, y1 }, Vec2{ x1, (y2-y1)+1 }), 0x000000_rgb .WithAlpha(100));
|
|
||||||
g->BlendFilledRect(RectSized(Vec2{ x2+1, y1 }, Vec2{ XRES-x2-1, (y2-y1)+1 }), 0x000000_rgb .WithAlpha(100));
|
|
||||||
|
|
||||||
g->XorDottedRect(RectBetween(Vec2{ x1, y1 }, Vec2{ x2, y2 }));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
g->RenderZoom();
|
if(selectMode!=SelectNone)
|
||||||
|
{
|
||||||
if (doScreenshot)
|
if(selectMode==PlaceSave)
|
||||||
{
|
{
|
||||||
doScreenshot = false;
|
if(placeSaveThumb && selectPoint2.X!=-1)
|
||||||
TakeScreenshot(0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(recording)
|
|
||||||
{
|
|
||||||
std::vector<char> data = VideoBuffer(rendererFrame).ToPPM();
|
|
||||||
|
|
||||||
ByteString filename = ByteString::Build("recordings", PATH_SEP_CHAR, recordingFolder, PATH_SEP_CHAR, "frame_", Format::Width(recordingIndex++, 6), ".ppm");
|
|
||||||
|
|
||||||
Platform::WriteFile(data, filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (logEntries.size())
|
|
||||||
{
|
|
||||||
int startX = 20;
|
|
||||||
int startY = YRES-20;
|
|
||||||
std::deque<std::pair<String, int> >::iterator iter;
|
|
||||||
for(iter = logEntries.begin(); iter != logEntries.end(); iter++)
|
|
||||||
{
|
{
|
||||||
String message = (*iter).first;
|
auto rect = RectSized(PlaceSavePos() * CELL, placeSaveThumb->Size());
|
||||||
int alpha = std::min((*iter).second, 255);
|
g->BlendImage(placeSaveThumb->Data(), 0x80, rect);
|
||||||
if (alpha <= 0) //erase this and everything older
|
g->XorDottedRect(rect);
|
||||||
{
|
|
||||||
logEntries.erase(iter, logEntries.end());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
startY -= 14;
|
|
||||||
g->BlendFilledRect(RectSized(Vec2{ startX-3, startY-3 }, Vec2{ Graphics::TextSize(message).X + 5, 14 }), 0x000000_rgb .WithAlpha(std::min(100, alpha)));
|
|
||||||
g->BlendText({ startX, startY }, message, 0xFFFFFF_rgb .WithAlpha(alpha));
|
|
||||||
(*iter).second -= 3;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(selectPoint1.X==-1)
|
||||||
|
{
|
||||||
|
g->BlendFilledRect(RectSized(Vec2{ 0, 0 }, Vec2{ XRES, YRES }), 0x000000_rgb .WithAlpha(100));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int x2 = (selectPoint1.X>selectPoint2.X)?selectPoint1.X:selectPoint2.X;
|
||||||
|
int y2 = (selectPoint1.Y>selectPoint2.Y)?selectPoint1.Y:selectPoint2.Y;
|
||||||
|
int x1 = (selectPoint2.X<selectPoint1.X)?selectPoint2.X:selectPoint1.X;
|
||||||
|
int y1 = (selectPoint2.Y<selectPoint1.Y)?selectPoint2.Y:selectPoint1.Y;
|
||||||
|
|
||||||
|
if(x2>XRES-1)
|
||||||
|
x2 = XRES-1;
|
||||||
|
if(y2>YRES-1)
|
||||||
|
y2 = YRES-1;
|
||||||
|
|
||||||
|
g->BlendFilledRect(RectSized(Vec2{ 0, 0 }, Vec2{ XRES, y1 }), 0x000000_rgb .WithAlpha(100));
|
||||||
|
g->BlendFilledRect(RectSized(Vec2{ 0, y2+1 }, Vec2{ XRES, YRES-y2-1 }), 0x000000_rgb .WithAlpha(100));
|
||||||
|
|
||||||
|
g->BlendFilledRect(RectSized(Vec2{ 0, y1 }, Vec2{ x1, (y2-y1)+1 }), 0x000000_rgb .WithAlpha(100));
|
||||||
|
g->BlendFilledRect(RectSized(Vec2{ x2+1, y1 }, Vec2{ XRES-x2-1, (y2-y1)+1 }), 0x000000_rgb .WithAlpha(100));
|
||||||
|
|
||||||
|
g->XorDottedRect(RectBetween(Vec2{ x1, y1 }, Vec2{ x2, y2 }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g->RenderZoom();
|
||||||
|
|
||||||
|
if (doScreenshot)
|
||||||
|
{
|
||||||
|
doScreenshot = false;
|
||||||
|
TakeScreenshot(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(recording)
|
||||||
|
{
|
||||||
|
std::vector<char> data = VideoBuffer(rendererFrame).ToPPM();
|
||||||
|
|
||||||
|
ByteString filename = ByteString::Build("recordings", PATH_SEP_CHAR, recordingFolder, PATH_SEP_CHAR, "frame_", Format::Width(recordingIndex++, 6), ".ppm");
|
||||||
|
|
||||||
|
Platform::WriteFile(data, filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logEntries.size())
|
||||||
|
{
|
||||||
|
int startX = 20;
|
||||||
|
int startY = YRES-20;
|
||||||
|
std::deque<std::pair<String, int> >::iterator iter;
|
||||||
|
for(iter = logEntries.begin(); iter != logEntries.end(); iter++)
|
||||||
|
{
|
||||||
|
String message = (*iter).first;
|
||||||
|
int alpha = std::min((*iter).second, 255);
|
||||||
|
if (alpha <= 0) //erase this and everything older
|
||||||
|
{
|
||||||
|
logEntries.erase(iter, logEntries.end());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
startY -= 14;
|
||||||
|
g->BlendFilledRect(RectSized(Vec2{ startX-3, startY-3 }, Vec2{ Graphics::TextSize(message).X + 5, 14 }), 0x000000_rgb .WithAlpha(std::min(100, alpha)));
|
||||||
|
g->BlendText({ startX, startY }, message, 0xFFFFFF_rgb .WithAlpha(alpha));
|
||||||
|
(*iter).second -= 3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recording)
|
if (recording)
|
||||||
@@ -2487,8 +2511,8 @@ void GameView::OnDraw()
|
|||||||
|
|
||||||
if (showDebug)
|
if (showDebug)
|
||||||
{
|
{
|
||||||
if (ren->findingElement)
|
if (rendererSettings->findingElement)
|
||||||
fpsInfo << " Parts: " << ren->foundElements << "/" << sample.NumParts;
|
fpsInfo << " Parts: " << rendererSettings->foundElements << "/" << sample.NumParts;
|
||||||
else
|
else
|
||||||
fpsInfo << " Parts: " << sample.NumParts;
|
fpsInfo << " Parts: " << sample.NumParts;
|
||||||
}
|
}
|
||||||
@@ -2496,10 +2520,17 @@ void GameView::OnDraw()
|
|||||||
fpsInfo << " [REPLACE MODE]";
|
fpsInfo << " [REPLACE MODE]";
|
||||||
if (c->GetReplaceModeFlags()&SPECIFIC_DELETE)
|
if (c->GetReplaceModeFlags()&SPECIFIC_DELETE)
|
||||||
fpsInfo << " [SPECIFIC DELETE]";
|
fpsInfo << " [SPECIFIC DELETE]";
|
||||||
if (ren && ren->GetGridSize())
|
if (rendererSettings->gridSize)
|
||||||
fpsInfo << " [GRID: " << ren->GetGridSize() << "]";
|
fpsInfo << " [GRID: " << rendererSettings->gridSize << "]";
|
||||||
if (ren && ren->findingElement)
|
if (rendererSettings->findingElement)
|
||||||
fpsInfo << " [FIND]";
|
fpsInfo << " [FIND]";
|
||||||
|
if (showDebug)
|
||||||
|
{
|
||||||
|
if (wantRendererThread)
|
||||||
|
{
|
||||||
|
fpsInfo << " [SRT]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int textWidth = Graphics::TextSize(fpsInfo.Build()).X - 1;
|
int textWidth = Graphics::TextSize(fpsInfo.Build()).X - 1;
|
||||||
int alpha = 255-introText*5;
|
int alpha = 255-introText*5;
|
||||||
@@ -2584,3 +2615,106 @@ pixel GameView::GetPixelUnderMouse() const
|
|||||||
}
|
}
|
||||||
return rendererFrame[point];
|
return rendererFrame[point];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameView::RendererThread()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::unique_lock lk(rendererThreadMx);
|
||||||
|
rendererThreadOwnsRenderer = false;
|
||||||
|
rendererThreadCv.notify_one();
|
||||||
|
rendererThreadCv.wait(lk, [this]() {
|
||||||
|
return rendererThreadState == rendererThreadStopping || rendererThreadOwnsRenderer;
|
||||||
|
});
|
||||||
|
if (rendererThreadState == rendererThreadStopping)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RenderSimulation(*rendererThreadSim, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameView::StartRendererThread()
|
||||||
|
{
|
||||||
|
bool start = false;
|
||||||
|
bool notify = false;
|
||||||
|
{
|
||||||
|
std::lock_guard lk(rendererThreadMx);
|
||||||
|
if (rendererThreadState == rendererThreadAbsent)
|
||||||
|
{
|
||||||
|
rendererThreadSim = std::make_unique<RenderableSimulation>();
|
||||||
|
rendererThreadState = rendererThreadRunning;
|
||||||
|
start = true;
|
||||||
|
}
|
||||||
|
else if (rendererThreadState == rendererThreadPaused)
|
||||||
|
{
|
||||||
|
rendererThreadState = rendererThreadRunning;
|
||||||
|
notify = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (start)
|
||||||
|
{
|
||||||
|
rendererThread = std::thread([this]() {
|
||||||
|
RendererThread();
|
||||||
|
});
|
||||||
|
notify = true;
|
||||||
|
}
|
||||||
|
if (notify)
|
||||||
|
{
|
||||||
|
DispatchRendererThread();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameView::StopRendererThread()
|
||||||
|
{
|
||||||
|
bool join = false;
|
||||||
|
{
|
||||||
|
std::lock_guard lk(rendererThreadMx);
|
||||||
|
if (rendererThreadState != rendererThreadAbsent)
|
||||||
|
{
|
||||||
|
rendererThreadState = rendererThreadStopping;
|
||||||
|
join = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (join)
|
||||||
|
{
|
||||||
|
rendererThreadCv.notify_one();
|
||||||
|
rendererThread.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameView::PauseRendererThread()
|
||||||
|
{
|
||||||
|
std::unique_lock lk(rendererThreadMx);
|
||||||
|
if (rendererThreadState == rendererThreadRunning)
|
||||||
|
{
|
||||||
|
rendererThreadState = rendererThreadPaused;
|
||||||
|
rendererThreadCv.notify_one();
|
||||||
|
rendererThreadCv.wait(lk, [this]() {
|
||||||
|
return !rendererThreadOwnsRenderer;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameView::DispatchRendererThread()
|
||||||
|
{
|
||||||
|
ren->ApplySettings(*rendererSettings);
|
||||||
|
*rendererThreadSim = *sim;
|
||||||
|
rendererThreadSim->useLuaCallbacks = false;
|
||||||
|
rendererThreadOwnsRenderer = true;
|
||||||
|
{
|
||||||
|
std::lock_guard lk(rendererThreadMx);
|
||||||
|
rendererThreadOwnsRenderer = true;
|
||||||
|
}
|
||||||
|
rendererThreadCv.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameView::WaitForRendererThread()
|
||||||
|
{
|
||||||
|
std::unique_lock lk(rendererThreadMx);
|
||||||
|
rendererThreadCv.wait(lk, [this]() {
|
||||||
|
return !rendererThreadOwnsRenderer;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@@ -9,6 +9,9 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
|
|
||||||
enum DrawMode
|
enum DrawMode
|
||||||
{
|
{
|
||||||
@@ -29,9 +32,11 @@ namespace ui
|
|||||||
|
|
||||||
class SplitButton;
|
class SplitButton;
|
||||||
class Simulation;
|
class Simulation;
|
||||||
|
struct RenderableSimulation;
|
||||||
|
|
||||||
class MenuButton;
|
class MenuButton;
|
||||||
class Renderer;
|
class Renderer;
|
||||||
|
struct RendererSettings;
|
||||||
class VideoBuffer;
|
class VideoBuffer;
|
||||||
class ToolButton;
|
class ToolButton;
|
||||||
class GameController;
|
class GameController;
|
||||||
@@ -82,7 +87,8 @@ private:
|
|||||||
|
|
||||||
ui::Point currentPoint, lastPoint;
|
ui::Point currentPoint, lastPoint;
|
||||||
GameController * c;
|
GameController * c;
|
||||||
Renderer * ren;
|
Renderer *ren = nullptr;
|
||||||
|
RendererSettings *rendererSettings = nullptr;
|
||||||
Simulation *sim = nullptr;
|
Simulation *sim = nullptr;
|
||||||
Brush const *activeBrush;
|
Brush const *activeBrush;
|
||||||
//UI Elements
|
//UI Elements
|
||||||
@@ -147,10 +153,28 @@ private:
|
|||||||
Vec2<int> PlaceSavePos() const;
|
Vec2<int> PlaceSavePos() const;
|
||||||
|
|
||||||
std::optional<FindingElement> FindingElementCandidate() const;
|
std::optional<FindingElement> FindingElementCandidate() const;
|
||||||
|
enum RendererThreadState
|
||||||
|
{
|
||||||
|
rendererThreadAbsent,
|
||||||
|
rendererThreadRunning,
|
||||||
|
rendererThreadPaused,
|
||||||
|
rendererThreadStopping,
|
||||||
|
};
|
||||||
|
RendererThreadState rendererThreadState = rendererThreadAbsent;
|
||||||
|
std::thread rendererThread;
|
||||||
|
std::mutex rendererThreadMx;
|
||||||
|
std::condition_variable rendererThreadCv;
|
||||||
|
bool rendererThreadOwnsRenderer = false;
|
||||||
|
void StartRendererThread();
|
||||||
|
void StopRendererThread();
|
||||||
|
void RendererThread();
|
||||||
|
void WaitForRendererThread();
|
||||||
|
void DispatchRendererThread();
|
||||||
|
std::unique_ptr<RenderableSimulation> rendererThreadSim;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GameView();
|
GameView();
|
||||||
virtual ~GameView();
|
~GameView();
|
||||||
|
|
||||||
//Breaks MVC, but any other way is going to be more of a mess.
|
//Breaks MVC, but any other way is going to be more of a mess.
|
||||||
ui::Point GetMousePosition();
|
ui::Point GetMousePosition();
|
||||||
@@ -238,4 +262,12 @@ public:
|
|||||||
pixel GetPixelUnderMouse() const;
|
pixel GetPixelUnderMouse() const;
|
||||||
|
|
||||||
RendererFrame rendererFrame;
|
RendererFrame rendererFrame;
|
||||||
|
// Call this before accessing Renderer "out of turn", e.g. from RenderView. This *does not*
|
||||||
|
// include OptionsModel or Lua setting functions because they only access the RendererSettings
|
||||||
|
// in GameModel, or Lua drawing functions because they only access Renderer in eventTraitSimGraphics
|
||||||
|
// and *SimDraw events, and the renderer thread gets paused anyway if there are handlers
|
||||||
|
// installed for such events.
|
||||||
|
void PauseRendererThread();
|
||||||
|
|
||||||
|
void RenderSimulation(const RenderableSimulation &sim, bool handleEvents);
|
||||||
};
|
};
|
||||||
|
@@ -575,7 +575,7 @@ void PreviewView::NotifySaveChanged(PreviewModel * sender)
|
|||||||
if(save->GetGameSave())
|
if(save->GetGameSave())
|
||||||
{
|
{
|
||||||
missingElements = save->GetGameSave()->missingElements;
|
missingElements = save->GetGameSave()->missingElements;
|
||||||
savePreview = SaveRenderer::Ref().Render(save->GetGameSave(), false, true);
|
savePreview = SaveRenderer::Ref().Render(save->GetGameSave(), false, true, RendererSettings{});
|
||||||
if (savePreview)
|
if (savePreview)
|
||||||
savePreview->ResizeToFit(RES / 2, true);
|
savePreview->ResizeToFit(RES / 2, true);
|
||||||
missingElementsButton->Visible = missingElements;
|
missingElementsButton->Visible = missingElements;
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include "Controller.h"
|
#include "Controller.h"
|
||||||
|
|
||||||
RenderController::RenderController(Simulation *sim, Renderer * ren, std::function<void ()> onDone_):
|
RenderController::RenderController(Simulation *sim, Renderer * ren, RendererSettings *rendererSettings, std::function<void ()> onDone_):
|
||||||
HasExited(false)
|
HasExited(false)
|
||||||
{
|
{
|
||||||
renderView = new RenderView();
|
renderView = new RenderView();
|
||||||
@@ -14,7 +14,7 @@ RenderController::RenderController(Simulation *sim, Renderer * ren, std::functio
|
|||||||
renderView->AttachController(this);
|
renderView->AttachController(this);
|
||||||
renderModel->AddObserver(renderView);
|
renderModel->AddObserver(renderView);
|
||||||
|
|
||||||
renderModel->SetRenderer(ren);
|
renderModel->SetRenderer(ren, rendererSettings);
|
||||||
renderModel->SetSimulation(sim);
|
renderModel->SetSimulation(sim);
|
||||||
onDone = onDone_;
|
onDone = onDone_;
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
class RenderView;
|
class RenderView;
|
||||||
class RenderModel;
|
class RenderModel;
|
||||||
class Renderer;
|
class Renderer;
|
||||||
|
struct RendererSettings;
|
||||||
class Simulation;
|
class Simulation;
|
||||||
class RenderController
|
class RenderController
|
||||||
{
|
{
|
||||||
@@ -13,7 +14,7 @@ class RenderController
|
|||||||
std::function<void ()> onDone;
|
std::function<void ()> onDone;
|
||||||
public:
|
public:
|
||||||
bool HasExited;
|
bool HasExited;
|
||||||
RenderController(Simulation *sim, Renderer * ren, std::function<void ()> onDone = nullptr);
|
RenderController(Simulation *sim, Renderer * ren, RendererSettings *rendererSettings, std::function<void ()> onDone = nullptr);
|
||||||
void Exit();
|
void Exit();
|
||||||
RenderView * GetView() { return renderView; }
|
RenderView * GetView() { return renderView; }
|
||||||
virtual ~RenderController();
|
virtual ~RenderController();
|
||||||
|
@@ -1,17 +1,10 @@
|
|||||||
#include "RenderModel.h"
|
#include "RenderModel.h"
|
||||||
|
|
||||||
#include "RenderView.h"
|
#include "RenderView.h"
|
||||||
|
|
||||||
#include "gui/game/RenderPreset.h"
|
#include "gui/game/RenderPreset.h"
|
||||||
|
#include "gui/game/GameController.h"
|
||||||
|
#include "gui/game/GameView.h"
|
||||||
#include "graphics/Renderer.h"
|
#include "graphics/Renderer.h"
|
||||||
|
|
||||||
RenderModel::RenderModel():
|
|
||||||
renderer(NULL)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderModel::AddObserver(RenderView * observer)
|
void RenderModel::AddObserver(RenderView * observer)
|
||||||
{
|
{
|
||||||
observers.push_back(observer);
|
observers.push_back(observer);
|
||||||
@@ -23,44 +16,35 @@ void RenderModel::AddObserver(RenderView * observer)
|
|||||||
|
|
||||||
void RenderModel::SetRenderMode(uint32_t newRenderMode)
|
void RenderModel::SetRenderMode(uint32_t newRenderMode)
|
||||||
{
|
{
|
||||||
if (renderer)
|
rendererSettings->renderMode = newRenderMode;
|
||||||
{
|
|
||||||
renderer->SetRenderMode(newRenderMode);
|
|
||||||
}
|
|
||||||
notifyRenderChanged();
|
notifyRenderChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t RenderModel::GetRenderMode()
|
uint32_t RenderModel::GetRenderMode()
|
||||||
{
|
{
|
||||||
return renderer ? renderer->GetRenderMode() : 0;
|
return rendererSettings->renderMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderModel::SetDisplayMode(uint32_t newDisplayMode)
|
void RenderModel::SetDisplayMode(uint32_t newDisplayMode)
|
||||||
{
|
{
|
||||||
if (renderer)
|
rendererSettings->displayMode = newDisplayMode;
|
||||||
{
|
|
||||||
renderer->SetDisplayMode(newDisplayMode);
|
|
||||||
}
|
|
||||||
notifyDisplayChanged();
|
notifyDisplayChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t RenderModel::GetDisplayMode()
|
uint32_t RenderModel::GetDisplayMode()
|
||||||
{
|
{
|
||||||
return renderer ? renderer->GetDisplayMode() : 0;
|
return rendererSettings->displayMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderModel::SetColorMode(uint32_t newColorMode)
|
void RenderModel::SetColorMode(uint32_t newColorMode)
|
||||||
{
|
{
|
||||||
if (renderer)
|
rendererSettings->colorMode = newColorMode;
|
||||||
{
|
|
||||||
renderer->SetColorMode(newColorMode);
|
|
||||||
}
|
|
||||||
notifyColourChanged();
|
notifyColourChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t RenderModel::GetColorMode()
|
uint32_t RenderModel::GetColorMode()
|
||||||
{
|
{
|
||||||
return renderer ? renderer->GetColorMode() : 0;
|
return rendererSettings->colorMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderModel::LoadRenderPreset(int presetNum)
|
void RenderModel::LoadRenderPreset(int presetNum)
|
||||||
@@ -71,9 +55,10 @@ void RenderModel::LoadRenderPreset(int presetNum)
|
|||||||
SetColorMode(preset.colorMode);
|
SetColorMode(preset.colorMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderModel::SetRenderer(Renderer * ren)
|
void RenderModel::SetRenderer(Renderer * ren, RendererSettings *newRendererSettings)
|
||||||
{
|
{
|
||||||
renderer = ren;
|
renderer = ren;
|
||||||
|
rendererSettings = newRendererSettings;
|
||||||
notifyRendererChanged();
|
notifyRendererChanged();
|
||||||
notifyRenderChanged();
|
notifyRenderChanged();
|
||||||
notifyDisplayChanged();
|
notifyDisplayChanged();
|
||||||
@@ -94,6 +79,11 @@ Renderer * RenderModel::GetRenderer()
|
|||||||
return renderer;
|
return renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RendererSettings *RenderModel::GetRendererSettings()
|
||||||
|
{
|
||||||
|
return rendererSettings;
|
||||||
|
}
|
||||||
|
|
||||||
Simulation *RenderModel::GetSimulation()
|
Simulation *RenderModel::GetSimulation()
|
||||||
{
|
{
|
||||||
return sim;
|
return sim;
|
||||||
|
@@ -4,11 +4,13 @@
|
|||||||
|
|
||||||
class RenderView;
|
class RenderView;
|
||||||
class Renderer;
|
class Renderer;
|
||||||
|
struct RendererSettings;
|
||||||
class Simulation;
|
class Simulation;
|
||||||
class RenderModel
|
class RenderModel
|
||||||
{
|
{
|
||||||
std::vector<RenderView*> observers;
|
std::vector<RenderView*> observers;
|
||||||
Renderer * renderer;
|
Renderer * renderer = nullptr;
|
||||||
|
RendererSettings *rendererSettings = nullptr;
|
||||||
Simulation *sim = nullptr;
|
Simulation *sim = nullptr;
|
||||||
void notifyRendererChanged();
|
void notifyRendererChanged();
|
||||||
void notifySimulationChanged();
|
void notifySimulationChanged();
|
||||||
@@ -16,11 +18,11 @@ class RenderModel
|
|||||||
void notifyDisplayChanged();
|
void notifyDisplayChanged();
|
||||||
void notifyColourChanged();
|
void notifyColourChanged();
|
||||||
public:
|
public:
|
||||||
RenderModel();
|
|
||||||
Renderer * GetRenderer();
|
Renderer * GetRenderer();
|
||||||
|
RendererSettings *GetRendererSettings();
|
||||||
Simulation *GetSimulation();
|
Simulation *GetSimulation();
|
||||||
void AddObserver(RenderView * observer);
|
void AddObserver(RenderView * observer);
|
||||||
void SetRenderer(Renderer * ren);
|
void SetRenderer(Renderer * ren, RendererSettings *newRendererSettings);
|
||||||
void SetSimulation(Simulation *newSim);
|
void SetSimulation(Simulation *newSim);
|
||||||
void SetRenderMode(uint32_t newRenderMode);
|
void SetRenderMode(uint32_t newRenderMode);
|
||||||
uint32_t GetRenderMode();
|
uint32_t GetRenderMode();
|
||||||
|
@@ -1,18 +1,16 @@
|
|||||||
#include "RenderView.h"
|
#include "RenderView.h"
|
||||||
|
|
||||||
#include "simulation/ElementGraphics.h"
|
#include "simulation/ElementGraphics.h"
|
||||||
#include "simulation/SimulationData.h"
|
#include "simulation/SimulationData.h"
|
||||||
#include "simulation/Simulation.h"
|
#include "simulation/Simulation.h"
|
||||||
|
|
||||||
#include "graphics/Graphics.h"
|
#include "graphics/Graphics.h"
|
||||||
#include "graphics/Renderer.h"
|
#include "graphics/Renderer.h"
|
||||||
#include "graphics/VideoBuffer.h"
|
#include "graphics/VideoBuffer.h"
|
||||||
|
|
||||||
#include "RenderController.h"
|
#include "RenderController.h"
|
||||||
#include "RenderModel.h"
|
#include "RenderModel.h"
|
||||||
|
|
||||||
#include "gui/interface/Checkbox.h"
|
#include "gui/interface/Checkbox.h"
|
||||||
#include "gui/interface/Button.h"
|
#include "gui/interface/Button.h"
|
||||||
|
#include "gui/game/GameController.h"
|
||||||
|
#include "gui/game/GameView.h"
|
||||||
|
|
||||||
class ModeCheckbox : public ui::Checkbox
|
class ModeCheckbox : public ui::Checkbox
|
||||||
{
|
{
|
||||||
@@ -144,6 +142,7 @@ void RenderView::OnTryExit(ExitMethod method)
|
|||||||
void RenderView::NotifyRendererChanged(RenderModel * sender)
|
void RenderView::NotifyRendererChanged(RenderModel * sender)
|
||||||
{
|
{
|
||||||
ren = sender->GetRenderer();
|
ren = sender->GetRenderer();
|
||||||
|
rendererSettings = sender->GetRendererSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderView::NotifySimulationChanged(RenderModel * sender)
|
void RenderView::NotifySimulationChanged(RenderModel * sender)
|
||||||
@@ -183,20 +182,14 @@ void RenderView::OnDraw()
|
|||||||
{
|
{
|
||||||
Graphics * g = GetGraphics();
|
Graphics * g = GetGraphics();
|
||||||
g->DrawFilledRect(WINDOW.OriginRect(), 0x000000_rgb);
|
g->DrawFilledRect(WINDOW.OriginRect(), 0x000000_rgb);
|
||||||
if(ren)
|
auto *view = GameController::Ref().GetView();
|
||||||
|
view->PauseRendererThread();
|
||||||
|
ren->ApplySettings(*rendererSettings);
|
||||||
|
view->RenderSimulation(*sim, true);
|
||||||
|
for (auto y = 0; y < YRES; ++y)
|
||||||
{
|
{
|
||||||
// we're the main thread, we may write graphicscache
|
auto &video = ren->GetVideo();
|
||||||
auto &sd = SimulationData::Ref();
|
std::copy_n(video.data() + video.Size().X * y, video.Size().X, g->Data() + g->Size().X * y);
|
||||||
std::unique_lock lk(sd.elementGraphicsMx);
|
|
||||||
ren->sim = sim;
|
|
||||||
ren->clearScreen();
|
|
||||||
ren->RenderSimulation();
|
|
||||||
ren->sim = nullptr;
|
|
||||||
for (auto y = 0; y < YRES; ++y)
|
|
||||||
{
|
|
||||||
auto &video = ren->GetVideo();
|
|
||||||
std::copy_n(video.data() + video.Size().X * y, video.Size().X, g->Data() + g->Size().X * y);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
g->DrawLine({ 0, YRES }, { XRES-1, YRES }, 0xC8C8C8_rgb);
|
g->DrawLine({ 0, YRES }, { XRES-1, YRES }, 0xC8C8C8_rgb);
|
||||||
g->DrawLine({ line1, YRES }, { line1, WINDOWH }, 0xC8C8C8_rgb);
|
g->DrawLine({ line1, YRES }, { line1, WINDOWH }, 0xC8C8C8_rgb);
|
||||||
|
@@ -5,12 +5,14 @@
|
|||||||
class ModeCheckbox;
|
class ModeCheckbox;
|
||||||
|
|
||||||
class Renderer;
|
class Renderer;
|
||||||
|
struct RendererSettings;
|
||||||
class Simulation;
|
class Simulation;
|
||||||
class RenderController;
|
class RenderController;
|
||||||
class RenderModel;
|
class RenderModel;
|
||||||
class RenderView: public ui::Window {
|
class RenderView: public ui::Window {
|
||||||
RenderController * c;
|
RenderController * c;
|
||||||
Renderer * ren;
|
Renderer * ren;
|
||||||
|
RendererSettings *rendererSettings = nullptr;
|
||||||
Simulation *sim = nullptr;
|
Simulation *sim = nullptr;
|
||||||
std::vector<ModeCheckbox *> renderModes;
|
std::vector<ModeCheckbox *> renderModes;
|
||||||
std::vector<ModeCheckbox *> displayModes;
|
std::vector<ModeCheckbox *> displayModes;
|
||||||
|
@@ -34,6 +34,7 @@ public:
|
|||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
bool HandleEvent(const GameControllerEvent &event);
|
bool HandleEvent(const GameControllerEvent &event);
|
||||||
|
bool HaveSimGraphicsEventHandlers();
|
||||||
|
|
||||||
int Command(String command);
|
int Command(String command);
|
||||||
String FormatCommand(String command);
|
String FormatCommand(String command);
|
||||||
|
@@ -11,16 +11,6 @@ static int32_t int32Truncate(double n)
|
|||||||
return int32_t(n);
|
return int32_t(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::variant<Graphics *, Renderer *> currentGraphics()
|
|
||||||
{
|
|
||||||
auto *lsi = GetLSI();
|
|
||||||
if (lsi->eventTraits & eventTraitSimGraphics)
|
|
||||||
{
|
|
||||||
return lsi->ren;
|
|
||||||
}
|
|
||||||
return lsi->g;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int textSize(lua_State *L)
|
static int textSize(lua_State *L)
|
||||||
{
|
{
|
||||||
auto text = tpt_lua_optString(L, 1, "");
|
auto text = tpt_lua_optString(L, 1, "");
|
||||||
@@ -51,7 +41,7 @@ static int drawText(lua_State *L)
|
|||||||
|
|
||||||
std::visit([x, y, r, g, b, a, &text](auto p) {
|
std::visit([x, y, r, g, b, a, &text](auto p) {
|
||||||
p->BlendText({ x, y }, text, RGBA<uint8_t>(r, g, b, a));
|
p->BlendText({ x, y }, text, RGBA<uint8_t>(r, g, b, a));
|
||||||
}, currentGraphics());
|
}, GetLSI()->GetGraphics());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +63,7 @@ static int drawPixel(lua_State *L)
|
|||||||
else if (a > 255) a = 255;
|
else if (a > 255) a = 255;
|
||||||
std::visit([x, y, r, g, b, a](auto p) {
|
std::visit([x, y, r, g, b, a](auto p) {
|
||||||
p->BlendPixel({ x, y }, RGBA<uint8_t>(r, g, b, a));
|
p->BlendPixel({ x, y }, RGBA<uint8_t>(r, g, b, a));
|
||||||
}, currentGraphics());
|
}, GetLSI()->GetGraphics());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +96,7 @@ static int drawLine(lua_State *L)
|
|||||||
{
|
{
|
||||||
p->BlendLine({ x1, y1 }, { x2, y2 }, RGBA<uint8_t>(r, g, b, a));
|
p->BlendLine({ x1, y1 }, { x2, y2 }, RGBA<uint8_t>(r, g, b, a));
|
||||||
}
|
}
|
||||||
}, currentGraphics());
|
}, GetLSI()->GetGraphics());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,7 +129,7 @@ static int drawRect(lua_State *L)
|
|||||||
{
|
{
|
||||||
p->BlendRect(RectSized(Vec2{ x, y }, Vec2{ width, height }), RGBA<uint8_t>(r, g, b, a));
|
p->BlendRect(RectSized(Vec2{ x, y }, Vec2{ width, height }), RGBA<uint8_t>(r, g, b, a));
|
||||||
}
|
}
|
||||||
}, currentGraphics());
|
}, GetLSI()->GetGraphics());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,7 +162,7 @@ static int fillRect(lua_State *L)
|
|||||||
{
|
{
|
||||||
p->BlendFilledRect(RectSized(Vec2{ x, y }, Vec2{ width, height }), RGBA<uint8_t>(r, g, b, a));
|
p->BlendFilledRect(RectSized(Vec2{ x, y }, Vec2{ width, height }), RGBA<uint8_t>(r, g, b, a));
|
||||||
}
|
}
|
||||||
}, currentGraphics());
|
}, GetLSI()->GetGraphics());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,7 +188,7 @@ static int drawCircle(lua_State *L)
|
|||||||
|
|
||||||
std::visit([x, y, rx, ry, r, g, b, a](auto p) {
|
std::visit([x, y, rx, ry, r, g, b, a](auto p) {
|
||||||
p->BlendEllipse({ x, y }, { abs(rx), abs(ry) }, RGBA<uint8_t>(r, g, b, a));
|
p->BlendEllipse({ x, y }, { abs(rx), abs(ry) }, RGBA<uint8_t>(r, g, b, a));
|
||||||
}, currentGraphics());
|
}, GetLSI()->GetGraphics());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,7 +214,7 @@ static int fillCircle(lua_State *L)
|
|||||||
|
|
||||||
std::visit([x, y, rx, ry, r, g, b, a](auto p) {
|
std::visit([x, y, rx, ry, r, g, b, a](auto p) {
|
||||||
p->BlendFilledEllipse({ x, y }, { abs(rx), abs(ry) }, RGBA<uint8_t>(r, g, b, a));
|
p->BlendFilledEllipse({ x, y }, { abs(rx), abs(ry) }, RGBA<uint8_t>(r, g, b, a));
|
||||||
}, currentGraphics());
|
}, GetLSI()->GetGraphics());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,10 +10,10 @@ static int renderMode(lua_State *L)
|
|||||||
auto *lsi = GetLSI();
|
auto *lsi = GetLSI();
|
||||||
if (lua_gettop(L))
|
if (lua_gettop(L))
|
||||||
{
|
{
|
||||||
lsi->ren->SetRenderMode(luaL_checkinteger(L, 1));
|
lsi->gameModel->GetRendererSettings().renderMode = luaL_checkinteger(L, 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
lua_pushinteger(L, lsi->ren->GetRenderMode());
|
lua_pushinteger(L, lsi->gameModel->GetRendererSettings().renderMode);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,11 +63,10 @@ static int fireSize(lua_State *L)
|
|||||||
auto *lsi = GetLSI();
|
auto *lsi = GetLSI();
|
||||||
if (lua_gettop(L) < 1)
|
if (lua_gettop(L) < 1)
|
||||||
{
|
{
|
||||||
lua_pushnumber(L, lsi->gameModel->GetRenderer()->GetFireIntensity());
|
lua_pushnumber(L, lsi->gameModel->GetRendererSettings().fireIntensity);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
float fireintensity = float(luaL_checknumber(L, 1));
|
lsi->gameModel->GetRendererSettings().fireIntensity = float(luaL_checknumber(L, 1));
|
||||||
lsi->gameModel->GetRenderer()->prepare_alpha(CELL, fireintensity);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,10 +75,10 @@ static int displayMode(lua_State *L)
|
|||||||
auto *lsi = GetLSI();
|
auto *lsi = GetLSI();
|
||||||
if (lua_gettop(L))
|
if (lua_gettop(L))
|
||||||
{
|
{
|
||||||
lsi->ren->SetDisplayMode(luaL_checkinteger(L, 1));
|
lsi->gameModel->GetRendererSettings().displayMode = luaL_checkinteger(L, 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
lua_pushinteger(L, lsi->ren->GetDisplayMode());
|
lua_pushinteger(L, lsi->gameModel->GetRendererSettings().displayMode);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,10 +88,10 @@ static int colorMode(lua_State *L)
|
|||||||
auto *lsi = GetLSI();
|
auto *lsi = GetLSI();
|
||||||
if (lua_gettop(L))
|
if (lua_gettop(L))
|
||||||
{
|
{
|
||||||
lsi->ren->SetColorMode(luaL_checkinteger(L, 1));
|
lsi->gameModel->GetRendererSettings().colorMode = luaL_checkinteger(L, 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
lua_pushinteger(L, lsi->ren->GetColorMode());
|
lua_pushinteger(L, lsi->gameModel->GetRendererSettings().colorMode);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,11 +116,11 @@ static int grid(lua_State *L)
|
|||||||
int acount = lua_gettop(L);
|
int acount = lua_gettop(L);
|
||||||
if (acount == 0)
|
if (acount == 0)
|
||||||
{
|
{
|
||||||
lua_pushnumber(L, lsi->ren->GetGridSize());
|
lua_pushnumber(L, lsi->gameModel->GetRendererSettings().gridSize);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int grid = luaL_optint(L, 1, -1);
|
int grid = luaL_optint(L, 1, -1);
|
||||||
lsi->ren->SetGridSize(grid);
|
lsi->gameModel->GetRendererSettings().gridSize = grid;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -116,12 +116,12 @@ String LuaGetError()
|
|||||||
|
|
||||||
LuaScriptInterface::LuaScriptInterface(GameController *newGameController, GameModel *newGameModel) :
|
LuaScriptInterface::LuaScriptInterface(GameController *newGameController, GameModel *newGameModel) :
|
||||||
CommandInterface(newGameController, newGameModel),
|
CommandInterface(newGameController, newGameModel),
|
||||||
|
ren(newGameModel->GetRenderer()),
|
||||||
gameModel(newGameModel),
|
gameModel(newGameModel),
|
||||||
gameController(newGameController),
|
gameController(newGameController),
|
||||||
window(gameController->GetView()),
|
window(gameController->GetView()),
|
||||||
sim(gameModel->GetSimulation()),
|
sim(gameModel->GetSimulation()),
|
||||||
g(ui::Engine::Ref().g),
|
g(ui::Engine::Ref().g),
|
||||||
ren(gameModel->GetRenderer()),
|
|
||||||
customElements(PT_NUM),
|
customElements(PT_NUM),
|
||||||
gameControllerEventHandlers(std::variant_size_v<GameControllerEvent>)
|
gameControllerEventHandlers(std::variant_size_v<GameControllerEvent>)
|
||||||
{
|
{
|
||||||
@@ -417,6 +417,42 @@ bool CommandInterface::HandleEvent(const GameControllerEvent &event)
|
|||||||
return cont;
|
return cont;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<size_t Index>
|
||||||
|
std::enable_if_t<Index != std::variant_size_v<GameControllerEvent>, bool> HaveSimGraphicsEventHandlersHelper(lua_State *L, std::vector<LuaSmartRef> &gameControllerEventHandlers)
|
||||||
|
{
|
||||||
|
if (std::variant_alternative_t<Index, GameControllerEvent>::traits & eventTraitSimGraphics)
|
||||||
|
{
|
||||||
|
gameControllerEventHandlers[Index].Push(L);
|
||||||
|
auto have = lua_objlen(L, -1) > 0;
|
||||||
|
lua_pop(L, 1);
|
||||||
|
if (have)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return HaveSimGraphicsEventHandlersHelper<Index + 1>(L, gameControllerEventHandlers);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t Index>
|
||||||
|
std::enable_if_t<Index == std::variant_size_v<GameControllerEvent>, bool> HaveSimGraphicsEventHandlersHelper(lua_State *L, std::vector<LuaSmartRef> &gameControllerEventHandlers)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommandInterface::HaveSimGraphicsEventHandlers()
|
||||||
|
{
|
||||||
|
auto &sd = SimulationData::CRef();
|
||||||
|
auto *lsi = static_cast<LuaScriptInterface *>(this);
|
||||||
|
for (int i = 0; i < int(lsi->customElements.size()); ++i)
|
||||||
|
{
|
||||||
|
if (lsi->customElements[i].graphics && !sd.graphicscache[i].isready && lsi->sim->elementCount[i])
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return HaveSimGraphicsEventHandlersHelper<0>(lsi->L, lsi->gameControllerEventHandlers);
|
||||||
|
}
|
||||||
|
|
||||||
void CommandInterface::OnTick()
|
void CommandInterface::OnTick()
|
||||||
{
|
{
|
||||||
auto *lsi = static_cast<LuaScriptInterface *>(this);
|
auto *lsi = static_cast<LuaScriptInterface *>(this);
|
||||||
@@ -804,3 +840,4 @@ void CommandInterfaceDeleter::operator ()(CommandInterface *ptr) const
|
|||||||
{
|
{
|
||||||
delete static_cast<LuaScriptInterface *>(ptr);
|
delete static_cast<LuaScriptInterface *>(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -62,6 +62,8 @@ class LuaScriptInterface : public CommandInterface
|
|||||||
{
|
{
|
||||||
LuaStatePtr luaState;
|
LuaStatePtr luaState;
|
||||||
|
|
||||||
|
Renderer *ren;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
lua_State *L{};
|
lua_State *L{};
|
||||||
|
|
||||||
@@ -70,7 +72,18 @@ public:
|
|||||||
ui::Window *window;
|
ui::Window *window;
|
||||||
Simulation *sim;
|
Simulation *sim;
|
||||||
Graphics *g;
|
Graphics *g;
|
||||||
Renderer *ren;
|
|
||||||
|
std::variant<Graphics *, Renderer *> GetGraphics()
|
||||||
|
{
|
||||||
|
if (eventTraits & eventTraitSimGraphics)
|
||||||
|
{
|
||||||
|
// This is ok without calling gameModel->view->PauseRendererThread() because
|
||||||
|
// the renderer thread gets paused anyway if there are handlers
|
||||||
|
// installed for eventTraitSimGraphics and *SimDraw events.
|
||||||
|
return ren;
|
||||||
|
}
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<CustomElement> customElements; // must come after luaState
|
std::vector<CustomElement> customElements; // must come after luaState
|
||||||
|
|
||||||
|
@@ -23,6 +23,11 @@ bool CommandInterface::HandleEvent(const GameControllerEvent &event)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CommandInterface::HaveSimGraphicsEventHandlers()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int CommandInterface::Command(String command)
|
int CommandInterface::Command(String command)
|
||||||
{
|
{
|
||||||
return PlainCommand(command);
|
return PlainCommand(command);
|
||||||
|
@@ -13,32 +13,24 @@ SaveRenderer::SaveRenderer()
|
|||||||
sim = std::make_unique<Simulation>();
|
sim = std::make_unique<Simulation>();
|
||||||
ren = std::make_unique<Renderer>();
|
ren = std::make_unique<Renderer>();
|
||||||
ren->sim = sim.get();
|
ren->sim = sim.get();
|
||||||
ren->decorations_enable = true;
|
|
||||||
ren->blackDecorations = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SaveRenderer::~SaveRenderer() = default;
|
SaveRenderer::~SaveRenderer() = default;
|
||||||
|
|
||||||
std::unique_ptr<VideoBuffer> SaveRenderer::Render(const GameSave *save, bool decorations, bool fire, Renderer *renderModeSource)
|
std::unique_ptr<VideoBuffer> SaveRenderer::Render(const GameSave *save, bool decorations, bool fire, RendererSettings rendererSettings)
|
||||||
{
|
{
|
||||||
// this function usually runs on a thread different from where element info in SimulationData may be written, so we acquire a read-only lock on it
|
// this function usually runs on a thread different from where element info in SimulationData may be written, so we acquire a read-only lock on it
|
||||||
auto &sd = SimulationData::CRef();
|
auto &sd = SimulationData::CRef();
|
||||||
std::shared_lock lk(sd.elementGraphicsMx);
|
std::shared_lock lk(sd.elementGraphicsMx);
|
||||||
std::lock_guard<std::mutex> gx(renderMutex);
|
std::lock_guard<std::mutex> gx(renderMutex);
|
||||||
|
|
||||||
ren->ResetModes();
|
rendererSettings.decorations_enable = true;
|
||||||
if (renderModeSource)
|
rendererSettings.blackDecorations = !decorations;
|
||||||
{
|
ren->ApplySettings(rendererSettings);
|
||||||
ren->SetRenderMode(renderModeSource->GetRenderMode());
|
|
||||||
ren->SetDisplayMode(renderModeSource->GetDisplayMode());
|
|
||||||
ren->SetColorMode(renderModeSource->GetColorMode());
|
|
||||||
}
|
|
||||||
|
|
||||||
sim->clear_sim();
|
sim->clear_sim();
|
||||||
|
|
||||||
sim->Load(save, true, { 0, 0 });
|
sim->Load(save, true, { 0, 0 });
|
||||||
ren->decorations_enable = true;
|
|
||||||
ren->blackDecorations = !decorations;
|
|
||||||
ren->ClearAccumulation();
|
ren->ClearAccumulation();
|
||||||
ren->clearScreen();
|
ren->clearScreen();
|
||||||
|
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "common/ExplicitSingleton.h"
|
#include "common/ExplicitSingleton.h"
|
||||||
|
#include "graphics/RendererSettings.h"
|
||||||
#include "common/String.h"
|
#include "common/String.h"
|
||||||
|
|
||||||
class GameSave;
|
class GameSave;
|
||||||
@@ -20,5 +21,5 @@ class SaveRenderer: public ExplicitSingleton<SaveRenderer>
|
|||||||
public:
|
public:
|
||||||
SaveRenderer();
|
SaveRenderer();
|
||||||
~SaveRenderer();
|
~SaveRenderer();
|
||||||
std::unique_ptr<VideoBuffer> Render(const GameSave *save, bool decorations = true, bool fire = true, Renderer *renderModeSource = nullptr);
|
std::unique_ptr<VideoBuffer> Render(const GameSave *save, bool decorations, bool fire, RendererSettings rendererSettings);
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user