... and everything built around them. A GameSave would hold at least one but sometimes two representations of a save: one serialized, and one "friendly", accessible for modification. Thus, a GameSave would have three states: - "Collapsed": only the serialized representation was present; this was the initial state of GameSaves loaded from files; - "Expanded With Data": both the serialized and the friendly representations were present; this was the state of GameSaves loaded from files after a call to Expand; - "Expanded Without Data": only the friendly representation was present; this was the initial state of GameSaves being prepared for being saved to files. A GameSave would be able to go from Collapsed to Expanded With Data with a call to Expand, and back with a call to Collapse. Of course, this latter transition would discard any changes made to the friendly representation, for example with Translate. A GameSave would however be unable to go from Expanded Without Data to any other state; a call to Collapse in this state would have been a no-op. There were two instances of Collapse being called, one in the GameSave constructor taking the serialized representation, immediately after a call to Expand, and another in SaveRenderer, which would Collapse a save "back down" if it had originally been Collapsed. Now, consider that there reasons for constructing a GameSave from the serialized representation are as follows: - loading an online save at startup from the command line; - loading a local save at startup from the command line; - loading a local save when it is dropped into the window; - loading a local save for placement of the most recently used stamp; - loading a local save for stamp placement via Lua; - loading an online save for preview generation while browsing; - loading a local save in the stamp browser for thumbnail generation; - loading a local save in the local save browser for thumbnail generation. In some cases, the friendly representation is needed for thumbnail generation by ThumbnailRendererTask. ThumbnailRendererTask operates on its own copy of the GameSave, because it runs SaveRenderer on a thread different from the main one and cannot be sure of the lifetime of the original GameSave. It destroys this copy when it is done rendering, so the call SaveRenderer makes to Collapse is pointless. In all other cases, the friendly representation is needed immediately. In some of these, SaveRenderer is used from the main thread, but since the friendly representation of the GameSave will be needed for pasting anyway, the call SaveRenderer makes to Collapse is pointless again. So, Collapse goes away. This also means that it is pointless for GameSaves to hold on to the serialized representation, since in all cases in which they have access to it, the friendly representation is needed immediately, and with Collapse gone, they will never need it again.
88 lines
1.7 KiB
C++
88 lines
1.7 KiB
C++
#include "SaveRenderer.h"
|
|
|
|
#include "client/GameSave.h"
|
|
|
|
#include "graphics/Graphics.h"
|
|
#include "graphics/Renderer.h"
|
|
|
|
#include "Simulation.h"
|
|
|
|
SaveRenderer::SaveRenderer(){
|
|
g = new Graphics();
|
|
sim = new Simulation();
|
|
ren = new Renderer(g, sim);
|
|
ren->decorations_enable = true;
|
|
ren->blackDecorations = true;
|
|
}
|
|
|
|
void SaveRenderer::Flush(int begin, int end)
|
|
{
|
|
std::lock_guard<std::mutex> gx(renderMutex);
|
|
std::fill(ren->graphicscache + begin, ren->graphicscache + end, gcache_item());
|
|
}
|
|
|
|
VideoBuffer * SaveRenderer::Render(GameSave * save, bool decorations, bool fire, Renderer *renderModeSource)
|
|
{
|
|
std::lock_guard<std::mutex> gx(renderMutex);
|
|
|
|
ren->ResetModes();
|
|
if (renderModeSource)
|
|
{
|
|
ren->SetRenderMode(renderModeSource->GetRenderMode());
|
|
ren->SetDisplayMode(renderModeSource->GetDisplayMode());
|
|
ren->SetColourMode(renderModeSource->GetColourMode());
|
|
}
|
|
|
|
int width, height;
|
|
VideoBuffer * tempThumb = NULL;
|
|
width = save->blockWidth;
|
|
height = save->blockHeight;
|
|
|
|
g->Clear();
|
|
sim->clear_sim();
|
|
|
|
if(!sim->Load(save, true))
|
|
{
|
|
ren->decorations_enable = true;
|
|
ren->blackDecorations = !decorations;
|
|
pixel * pData = NULL;
|
|
pixel * dst;
|
|
pixel * src = g->vid;
|
|
|
|
ren->ClearAccumulation();
|
|
|
|
if (fire)
|
|
{
|
|
int frame = 15;
|
|
while(frame)
|
|
{
|
|
frame--;
|
|
ren->render_parts();
|
|
ren->render_fire();
|
|
ren->clearScreen(1.0f);
|
|
}
|
|
}
|
|
|
|
ren->RenderBegin();
|
|
ren->RenderEnd();
|
|
|
|
|
|
pData = (pixel *)malloc(PIXELSIZE * ((width*CELL)*(height*CELL)));
|
|
dst = pData;
|
|
for(int i = 0; i < height*CELL; i++)
|
|
{
|
|
memcpy(dst, src, (width*CELL)*PIXELSIZE);
|
|
dst+=(width*CELL);///PIXELSIZE;
|
|
src+=WINDOWW;
|
|
}
|
|
tempThumb = new VideoBuffer(pData, width*CELL, height*CELL);
|
|
free(pData);
|
|
}
|
|
|
|
return tempThumb;
|
|
}
|
|
|
|
SaveRenderer::~SaveRenderer()
|
|
{
|
|
}
|