Complain about missing custom elements when opening online saves
The complaint manifests as a button in the bottom right corner of the half-size preview. Also convert the loading error popup to such a button.
This commit is contained in:
parent
374209eebe
commit
36800a76cd
@ -29,7 +29,7 @@ ThumbnailRendererTask::~ThumbnailRendererTask()
|
||||
|
||||
bool ThumbnailRendererTask::doWork()
|
||||
{
|
||||
thumbnail = std::unique_ptr<VideoBuffer>(SaveRenderer::Ref().Render(save.get(), decorations, fire));
|
||||
std::tie(thumbnail, std::ignore) = SaveRenderer::Ref().Render(save.get(), decorations, fire);
|
||||
if (thumbnail)
|
||||
{
|
||||
thumbnail->ResizeToFit(size, true);
|
||||
|
@ -1958,7 +1958,7 @@ void GameView::NotifyTransformedPlaceSaveChanged(GameModel *sender)
|
||||
{
|
||||
if (sender->GetTransformedPlaceSave())
|
||||
{
|
||||
placeSaveThumb = SaveRenderer::Ref().Render(sender->GetTransformedPlaceSave(), true, true, sender->GetRenderer());
|
||||
std::tie(placeSaveThumb, std::ignore) = SaveRenderer::Ref().Render(sender->GetTransformedPlaceSave(), true, true, sender->GetRenderer());
|
||||
selectMode = PlaceSave;
|
||||
selectPoint2 = mousePosition;
|
||||
}
|
||||
|
@ -93,6 +93,22 @@ PreviewView::PreviewView(std::unique_ptr<VideoBuffer> newSavePreview):
|
||||
browserOpenButton->SetActionCallback({ [this] { c->OpenInBrowser(); } });
|
||||
AddComponent(browserOpenButton);
|
||||
|
||||
loadErrorButton = new ui::Button({ 0, 0 }, ui::Point(148, 19), "Error loading save");
|
||||
loadErrorButton->Appearance.HorizontalAlign = ui::Appearance::AlignCentre;
|
||||
loadErrorButton->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
|
||||
loadErrorButton->SetIcon(IconDelete);
|
||||
loadErrorButton->SetActionCallback({ [this] { ShowLoadError(); } });
|
||||
loadErrorButton->Visible = false;
|
||||
AddComponent(loadErrorButton);
|
||||
|
||||
missingElementsButton = new ui::Button({ 0, 0 }, ui::Point(148, 19), "Missing custom elements");
|
||||
missingElementsButton->Appearance.HorizontalAlign = ui::Appearance::AlignCentre;
|
||||
missingElementsButton->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
|
||||
missingElementsButton->SetIcon(IconReport);
|
||||
missingElementsButton->SetActionCallback({ [this] { ShowMissingCustomElements(); } });
|
||||
missingElementsButton->Visible = false;
|
||||
AddComponent(missingElementsButton);
|
||||
|
||||
if(showAvatars)
|
||||
saveNameLabel = new ui::Label(ui::Point(39, (YRES/2)+4), ui::Point(100, 16), "");
|
||||
else
|
||||
@ -387,9 +403,9 @@ void PreviewView::OnTick(float dt)
|
||||
c->Update();
|
||||
if (doError)
|
||||
{
|
||||
new ErrorMessage("Error loading save", doErrorMessage, { [this]() {
|
||||
c->Exit();
|
||||
} });
|
||||
openButton->Enabled = false;
|
||||
loadErrorButton->Visible = true;
|
||||
UpdateLoadStatus();
|
||||
}
|
||||
|
||||
if (reportSaveRequest && reportSaveRequest->CheckDone())
|
||||
@ -464,6 +480,36 @@ void PreviewView::OnKeyPress(int key, int scan, bool repeat, bool shift, bool ct
|
||||
openButton->DoAction();
|
||||
}
|
||||
|
||||
void PreviewView::ShowLoadError()
|
||||
{
|
||||
new ErrorMessage("Error loading save", doErrorMessage, {});
|
||||
}
|
||||
|
||||
void PreviewView::ShowMissingCustomElements()
|
||||
{
|
||||
StringBuilder sb;
|
||||
sb << "This save uses custom elements that are not currently available. Make sure that you use the mod and/or have all the scripts the save requires to fully load. A list of identifiers of missing custom elements follows, which may help you determine how to fix this problem.\n";
|
||||
for (auto &identifier : missingElementTypes)
|
||||
{
|
||||
sb << "\n - " << identifier.FromUtf8();
|
||||
}
|
||||
new InformationMessage("Missing custom elements", sb.Build(), true);
|
||||
}
|
||||
|
||||
void PreviewView::UpdateLoadStatus()
|
||||
{
|
||||
auto y = YRES / 2 - 22;
|
||||
auto showButton = [&y](ui::Button *button) {
|
||||
if (button->Visible)
|
||||
{
|
||||
button->Position = { XRES / 2 - button->Size.X - 3, y };
|
||||
y -= button->Size.Y + 3;
|
||||
}
|
||||
};
|
||||
showButton(missingElementsButton);
|
||||
showButton(loadErrorButton);
|
||||
}
|
||||
|
||||
void PreviewView::NotifySaveChanged(PreviewModel * sender)
|
||||
{
|
||||
auto *save = sender->GetSaveInfo();
|
||||
@ -510,9 +556,11 @@ void PreviewView::NotifySaveChanged(PreviewModel * sender)
|
||||
|
||||
if(save->GetGameSave())
|
||||
{
|
||||
savePreview = SaveRenderer::Ref().Render(save->GetGameSave(), false, true);
|
||||
std::tie(savePreview, missingElementTypes) = SaveRenderer::Ref().Render(save->GetGameSave(), false, true);
|
||||
if (savePreview)
|
||||
savePreview->ResizeToFit(RES / 2, true);
|
||||
missingElementsButton->Visible = missingElementTypes.size();
|
||||
UpdateLoadStatus();
|
||||
}
|
||||
else if (!sender->GetCanOpen())
|
||||
openButton->Enabled = false;
|
||||
|
@ -26,25 +26,28 @@ class PreviewModel;
|
||||
class PreviewController;
|
||||
class PreviewView: public ui::Window
|
||||
{
|
||||
PreviewController * c;
|
||||
PreviewController *c{};
|
||||
std::vector<ByteString> missingElementTypes;
|
||||
std::unique_ptr<VideoBuffer> savePreview;
|
||||
ui::Button * openButton;
|
||||
ui::Button * browserOpenButton;
|
||||
ui::Button * favButton;
|
||||
ui::Button * reportButton;
|
||||
ui::Button * submitCommentButton;
|
||||
ui::Textbox * addCommentBox;
|
||||
ui::Label * commentWarningLabel;
|
||||
ui::Label * saveNameLabel;
|
||||
ui::Label * authorDateLabel;
|
||||
ui::AvatarButton * avatarButton;
|
||||
ui::Label * pageInfo;
|
||||
ui::Label * saveDescriptionLabel;
|
||||
ui::Label * viewsLabel;
|
||||
ui::Label * saveIDLabel;
|
||||
ui::Label * saveIDLabel2;
|
||||
ui::CopyTextButton * saveIDButton;
|
||||
ui::ScrollPanel * commentsPanel;
|
||||
ui::Button *openButton{};
|
||||
ui::Button *browserOpenButton{};
|
||||
ui::Button *favButton{};
|
||||
ui::Button *reportButton{};
|
||||
ui::Button *submitCommentButton{};
|
||||
ui::Button *loadErrorButton{};
|
||||
ui::Button *missingElementsButton{};
|
||||
ui::Textbox *addCommentBox{};
|
||||
ui::Label *commentWarningLabel{};
|
||||
ui::Label *saveNameLabel{};
|
||||
ui::Label *authorDateLabel{};
|
||||
ui::AvatarButton *avatarButton{};
|
||||
ui::Label *pageInfo{};
|
||||
ui::Label *saveDescriptionLabel{};
|
||||
ui::Label *viewsLabel{};
|
||||
ui::Label *saveIDLabel{};
|
||||
ui::Label *saveIDLabel2{};
|
||||
ui::CopyTextButton *saveIDButton{};
|
||||
ui::ScrollPanel *commentsPanel{};
|
||||
std::vector<ui::Component*> commentComponents;
|
||||
std::vector<ui::Component*> commentTextComponents;
|
||||
int votesUp;
|
||||
@ -70,6 +73,9 @@ class PreviewView: public ui::Window
|
||||
void submitComment();
|
||||
bool CheckSwearing(String text);
|
||||
void CheckComment();
|
||||
void ShowMissingCustomElements();
|
||||
void ShowLoadError();
|
||||
void UpdateLoadStatus();
|
||||
|
||||
std::unique_ptr<http::AddCommentRequest> addCommentRequest;
|
||||
std::unique_ptr<http::ReportSaveRequest> reportSaveRequest;
|
||||
|
@ -20,7 +20,7 @@ void SaveRenderer::Flush(int begin, int end)
|
||||
std::fill(ren->graphicscache + begin, ren->graphicscache + end, gcache_item());
|
||||
}
|
||||
|
||||
std::unique_ptr<VideoBuffer> SaveRenderer::Render(const GameSave *save, bool decorations, bool fire, Renderer *renderModeSource)
|
||||
std::pair<std::unique_ptr<VideoBuffer>, std::vector<ByteString>> SaveRenderer::Render(const GameSave *save, bool decorations, bool fire, Renderer *renderModeSource)
|
||||
{
|
||||
std::lock_guard<std::mutex> gx(renderMutex);
|
||||
|
||||
@ -32,11 +32,9 @@ std::unique_ptr<VideoBuffer> SaveRenderer::Render(const GameSave *save, bool dec
|
||||
ren->SetColourMode(renderModeSource->GetColourMode());
|
||||
}
|
||||
|
||||
std::unique_ptr<VideoBuffer> tempThumb;
|
||||
|
||||
sim->clear_sim();
|
||||
|
||||
sim->Load(save, true, { 0, 0 });
|
||||
auto missingElementTypes = sim->Load(save, true, { 0, 0 });
|
||||
ren->decorations_enable = true;
|
||||
ren->blackDecorations = !decorations;
|
||||
ren->ClearAccumulation();
|
||||
@ -57,10 +55,10 @@ std::unique_ptr<VideoBuffer> SaveRenderer::Render(const GameSave *save, bool dec
|
||||
ren->RenderBegin();
|
||||
ren->RenderEnd();
|
||||
|
||||
tempThumb = std::make_unique<VideoBuffer>(save->blockSize * CELL);
|
||||
auto tempThumb = std::make_unique<VideoBuffer>(save->blockSize * CELL);
|
||||
tempThumb->BlendImage(ren->Data(), 0xFF, ren->Size().OriginRect());
|
||||
|
||||
return tempThumb;
|
||||
return { std::move(tempThumb), missingElementTypes };
|
||||
}
|
||||
|
||||
SaveRenderer::~SaveRenderer()
|
||||
|
@ -1,7 +1,10 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "common/ExplicitSingleton.h"
|
||||
#include "common/String.h"
|
||||
|
||||
class GameSave;
|
||||
class VideoBuffer;
|
||||
@ -15,7 +18,7 @@ class SaveRenderer: public ExplicitSingleton<SaveRenderer> {
|
||||
std::mutex renderMutex;
|
||||
public:
|
||||
SaveRenderer();
|
||||
std::unique_ptr<VideoBuffer> Render(const GameSave *save, bool decorations = true, bool fire = true, Renderer *renderModeSource = nullptr);
|
||||
std::pair<std::unique_ptr<VideoBuffer>, std::vector<ByteString>> Render(const GameSave *save, bool decorations = true, bool fire = true, Renderer *renderModeSource = nullptr);
|
||||
void Flush(int begin, int end);
|
||||
virtual ~SaveRenderer();
|
||||
};
|
||||
|
@ -19,8 +19,9 @@ extern int Element_LOLZ_lolz[XRES/9][YRES/9];
|
||||
extern int Element_LOVE_RuleTable[9][9];
|
||||
extern int Element_LOVE_love[XRES/9][YRES/9];
|
||||
|
||||
void Simulation::Load(const GameSave *save, bool includePressure, Vec2<int> blockP) // block coordinates
|
||||
std::vector<ByteString> Simulation::Load(const GameSave *save, bool includePressure, Vec2<int> blockP) // block coordinates
|
||||
{
|
||||
std::vector<ByteString> missingElementTypes;
|
||||
auto partP = blockP * CELL;
|
||||
unsigned int pmapmask = (1<<save->pmapbits)-1;
|
||||
|
||||
@ -44,8 +45,15 @@ void Simulation::Load(const GameSave *save, bool includePressure, Vec2<int> bloc
|
||||
// if this is a custom element, set the ID to the ID we found when comparing identifiers in the palette map
|
||||
// set type to 0 if we couldn't find an element with that identifier present when loading,
|
||||
// unless this is a default element, in which case keep the current ID, because otherwise when an element is renamed it wouldn't show up anymore in older saves
|
||||
if (myId != 0 || !pi.first.BeginsWith("DEFAULT_PT_"))
|
||||
if (myId != 0)
|
||||
{
|
||||
partMap[pi.second] = myId;
|
||||
}
|
||||
else if (!pi.first.BeginsWith("DEFAULT_PT_"))
|
||||
{
|
||||
missingElementTypes.push_back(pi.first);
|
||||
partMap[pi.second] = myId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -318,6 +326,8 @@ void Simulation::Load(const GameSave *save, bool includePressure, Vec2<int> bloc
|
||||
{
|
||||
air->ApproximateBlockAirMaps();
|
||||
}
|
||||
|
||||
return missingElementTypes;
|
||||
}
|
||||
|
||||
std::unique_ptr<GameSave> Simulation::Save(bool includePressure, Rect<int> partR) // particle coordinates
|
||||
|
@ -121,7 +121,7 @@ public:
|
||||
uint64_t frameCount;
|
||||
bool ensureDeterminism;
|
||||
|
||||
void Load(const GameSave *save, bool includePressure, Vec2<int> blockP); // block coordinates
|
||||
std::vector<ByteString> Load(const GameSave *save, bool includePressure, Vec2<int> blockP); // block coordinates
|
||||
std::unique_ptr<GameSave> Save(bool includePressure, Rect<int> partR); // particle coordinates
|
||||
void SaveSimOptions(GameSave &gameSave);
|
||||
SimulationSample GetSample(int x, int y);
|
||||
|
Reference in New Issue
Block a user