mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-25 03:00:46 +00:00
- update of load/save menu to latest GZDoom code.
Input in save menu working.
This commit is contained in:
parent
94b4044d95
commit
e266044391
12 changed files with 1109 additions and 861 deletions
|
@ -830,6 +830,7 @@ set (PCH_SOURCES
|
||||||
common/menu/imagescroller.cpp
|
common/menu/imagescroller.cpp
|
||||||
common/menu/joystickmenu.cpp
|
common/menu/joystickmenu.cpp
|
||||||
common/menu/listmenu.cpp
|
common/menu/listmenu.cpp
|
||||||
|
common/menu/savegamemanager.cpp
|
||||||
common/menu/loadsavemenu.cpp
|
common/menu/loadsavemenu.cpp
|
||||||
common/menu/menu.cpp
|
common/menu/menu.cpp
|
||||||
common/menu/menudef.cpp
|
common/menu/menudef.cpp
|
||||||
|
|
|
@ -901,3 +901,4 @@ void ScaleWithAspect(int& w, int& h, int Width, int Height)
|
||||||
h = static_cast<int>(y);
|
h = static_cast<int>(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ void DrawTexture(F2DDrawer *drawer, FTexture* img, double x, double y, int tags_
|
||||||
void DrawChar (F2DDrawer* drawer, FFont *font, int normalcolor, double x, double y, int character, int tag_first, ...);
|
void DrawChar (F2DDrawer* drawer, FFont *font, int normalcolor, double x, double y, int character, int tag_first, ...);
|
||||||
void DrawText(F2DDrawer* drawer, FFont *font, int normalcolor, double x, double y, const char *string, int tag_first, ...);
|
void DrawText(F2DDrawer* drawer, FFont *font, int normalcolor, double x, double y, const char *string, int tag_first, ...);
|
||||||
void DrawText(F2DDrawer* drawer, FFont *font, int normalcolor, double x, double y, const char32_t *string, int tag_first, ...);
|
void DrawText(F2DDrawer* drawer, FFont *font, int normalcolor, double x, double y, const char32_t *string, int tag_first, ...);
|
||||||
|
void DrawFrame(F2DDrawer* twod, PalEntry color, int left, int top, int width, int height, int thickness);
|
||||||
|
|
||||||
EXTERN_CVAR(Int, con_scaletext) // Scale notify text at high resolutions?
|
EXTERN_CVAR(Int, con_scaletext) // Scale notify text at high resolutions?
|
||||||
EXTERN_CVAR(Int, con_scale)
|
EXTERN_CVAR(Int, con_scale)
|
||||||
|
|
|
@ -246,3 +246,25 @@ void DrawText(F2DDrawer* drawer, FFont *font, int normalcolor, double x, double
|
||||||
DrawTextCommon(drawer, font, normalcolor, x, y, string, parms);
|
DrawTextCommon(drawer, font, normalcolor, x, y, string, parms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// V_DrawFrame
|
||||||
|
//
|
||||||
|
// Draw a frame around the specified area using the view border
|
||||||
|
// frame graphics. The border is drawn outside the area, not in it.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void DrawFrame(F2DDrawer* twod, PalEntry color, int left, int top, int width, int height, int thickness)
|
||||||
|
{
|
||||||
|
// Sanity check for incomplete gameinfo
|
||||||
|
int offset = thickness == -1 ? screen->GetHeight() / 400 : thickness;
|
||||||
|
int right = left + width;
|
||||||
|
int bottom = top + height;
|
||||||
|
|
||||||
|
// Draw top and bottom sides.
|
||||||
|
twod->AddColorOnlyQuad(left, top - offset, width, offset, color);
|
||||||
|
twod->AddColorOnlyQuad(left - offset, top - offset, offset, height + 2 * offset, color);
|
||||||
|
twod->AddColorOnlyQuad(left, bottom, width, offset, color);
|
||||||
|
twod->AddColorOnlyQuad(right, top - offset, offset, height + 2 * offset, color);
|
||||||
|
}
|
||||||
|
|
|
@ -684,7 +684,7 @@ int FFont::StringWidth(const uint8_t *string) const
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
w += NewSmallFont->CharWidth(chr) + GlobalKerning;
|
w += CharWidth(chr) + GlobalKerning;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,12 +54,8 @@
|
||||||
class DLoadSaveMenu : public DListMenu
|
class DLoadSaveMenu : public DListMenu
|
||||||
{
|
{
|
||||||
using Super = DListMenu;
|
using Super = DListMenu;
|
||||||
friend void ClearSaveGames();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static TArray<FSaveGameNode*> SaveGames;
|
|
||||||
static int LastSaved;
|
|
||||||
static int LastAccessed;
|
|
||||||
|
|
||||||
int Selected;
|
int Selected;
|
||||||
int TopItem;
|
int TopItem;
|
||||||
|
@ -86,228 +82,13 @@ protected:
|
||||||
int commentHeight;
|
int commentHeight;
|
||||||
int commentRight;
|
int commentRight;
|
||||||
int commentBottom;
|
int commentBottom;
|
||||||
|
int commentRows;
|
||||||
|
|
||||||
|
double FontScale;
|
||||||
|
DTextEnterMenu *mInput = nullptr;
|
||||||
|
TArray<FBrokenLines> BrokenSaveComment;
|
||||||
|
bool mEntering = false;
|
||||||
|
|
||||||
static int InsertSaveNode (FSaveGameNode *node);
|
|
||||||
static void ReadSaveStrings ();
|
|
||||||
|
|
||||||
|
|
||||||
FTexture *SavePic = nullptr;
|
|
||||||
TArray<FBrokenLines> SaveComment;
|
|
||||||
bool mEntering;
|
|
||||||
FString savegamestring;
|
|
||||||
|
|
||||||
DLoadSaveMenu(DMenu *parent = NULL, FListMenuDescriptor *desc = NULL);
|
|
||||||
void Init(DMenu* parent, FListMenuDescriptor* desc) override;
|
|
||||||
void Destroy();
|
|
||||||
|
|
||||||
int RemoveSaveSlot (int index);
|
|
||||||
void UnloadSaveData ();
|
|
||||||
void ClearSaveStuff ();
|
|
||||||
void ExtractSaveData (int index);
|
|
||||||
void Drawer ();
|
|
||||||
bool MenuEvent (int mkey, bool fromcontroller);
|
|
||||||
bool MouseEvent(int type, int x, int y);
|
|
||||||
bool Responder(event_t *ev);
|
|
||||||
|
|
||||||
public:
|
|
||||||
static void NotifyNewSave (const char *file, const char *title, bool okForQuicksave);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
TArray<FSaveGameNode*> DLoadSaveMenu::SaveGames;
|
|
||||||
int DLoadSaveMenu::LastSaved = -1;
|
|
||||||
int DLoadSaveMenu::LastAccessed = -1;
|
|
||||||
|
|
||||||
FSaveGameNode *quickSaveSlot;
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
// Save data maintenance (stored statically)
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void ClearSaveGames()
|
|
||||||
{
|
|
||||||
for(unsigned i=0;i<DLoadSaveMenu::SaveGames.Size(); i++)
|
|
||||||
{
|
|
||||||
if(!DLoadSaveMenu::SaveGames[i]->bNoDelete)
|
|
||||||
delete DLoadSaveMenu::SaveGames[i];
|
|
||||||
}
|
|
||||||
DLoadSaveMenu::SaveGames.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
// Save data maintenance (stored statically)
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int DLoadSaveMenu::RemoveSaveSlot (int index)
|
|
||||||
{
|
|
||||||
FSaveGameNode *file = SaveGames[index];
|
|
||||||
|
|
||||||
if (quickSaveSlot == SaveGames[index])
|
|
||||||
{
|
|
||||||
quickSaveSlot = NULL;
|
|
||||||
}
|
|
||||||
if (Selected == index)
|
|
||||||
{
|
|
||||||
Selected = -1;
|
|
||||||
}
|
|
||||||
if (!file->bNoDelete) delete file;
|
|
||||||
SaveGames.Delete(index);
|
|
||||||
if ((unsigned)index >= SaveGames.Size()) index--;
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int DLoadSaveMenu::InsertSaveNode (FSaveGameNode *node)
|
|
||||||
{
|
|
||||||
if (SaveGames.Size() == 0)
|
|
||||||
{
|
|
||||||
return SaveGames.Push(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->bOldVersion)
|
|
||||||
{ // Add node at bottom of list
|
|
||||||
return SaveGames.Push(node);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // Add node at top of list
|
|
||||||
unsigned int i;
|
|
||||||
for(i = 0; i < SaveGames.Size(); i++)
|
|
||||||
{
|
|
||||||
if (SaveGames[i]->bOldVersion ||
|
|
||||||
stricmp (node->Title, SaveGames[i]->Title) <= 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SaveGames.Insert(i, node);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
// M_ReadSaveStrings
|
|
||||||
//
|
|
||||||
// Find savegames and read their titles
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void DLoadSaveMenu::ReadSaveStrings ()
|
|
||||||
{
|
|
||||||
if (SaveGames.Size() == 0)
|
|
||||||
{
|
|
||||||
void *filefirst;
|
|
||||||
findstate_t c_file;
|
|
||||||
FString filter;
|
|
||||||
|
|
||||||
LastSaved = LastAccessed = -1;
|
|
||||||
quickSaveSlot = NULL;
|
|
||||||
filter = G_BuildSaveName("*");
|
|
||||||
filefirst = I_FindFirst (filter.GetChars(), &c_file);
|
|
||||||
if (filefirst != ((void *)(-1)))
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// I_FindName only returns the file's name and not its full path
|
|
||||||
FString filepath = "";// G_BuildSaveName(I_FindName(&c_file), -1);
|
|
||||||
|
|
||||||
FResourceFile *savegame = FResourceFile::OpenResourceFile(filepath, true, true);
|
|
||||||
if (savegame != nullptr)
|
|
||||||
{
|
|
||||||
FResourceLump *info = savegame->FindLump("info.json");
|
|
||||||
if (info == nullptr)
|
|
||||||
{
|
|
||||||
// savegame info not found. This is not a savegame so leave it alone.
|
|
||||||
delete savegame;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto fr = info->NewReader();
|
|
||||||
FString title;
|
|
||||||
int check = G_ValidateSavegame(fr, &title);
|
|
||||||
delete savegame;
|
|
||||||
if (check != 0)
|
|
||||||
{
|
|
||||||
FSaveGameNode *node = new FSaveGameNode;
|
|
||||||
node->Filename = filepath;
|
|
||||||
node->bOldVersion = check == -1;
|
|
||||||
node->bMissingWads = check == -2;
|
|
||||||
node->Title = title;
|
|
||||||
InsertSaveNode(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (I_FindNext (filefirst, &c_file) == 0);
|
|
||||||
I_FindClose (filefirst);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void DLoadSaveMenu::NotifyNewSave (const char *file, const char *title, bool okForQuicksave)
|
|
||||||
{
|
|
||||||
FSaveGameNode *node;
|
|
||||||
|
|
||||||
if (file == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ReadSaveStrings ();
|
|
||||||
|
|
||||||
// See if the file is already in our list
|
|
||||||
for (unsigned i=0; i<SaveGames.Size(); i++)
|
|
||||||
{
|
|
||||||
FSaveGameNode *node = SaveGames[i];
|
|
||||||
#ifdef __unix__
|
|
||||||
if (node->Filename.Compare (file) == 0)
|
|
||||||
#else
|
|
||||||
if (node->Filename.CompareNoCase (file) == 0)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
node->Title = title;
|
|
||||||
node->bOldVersion = false;
|
|
||||||
node->bMissingWads = false;
|
|
||||||
if (okForQuicksave)
|
|
||||||
{
|
|
||||||
if (quickSaveSlot == NULL) quickSaveSlot = node;
|
|
||||||
LastAccessed = LastSaved = i;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
node = new FSaveGameNode;
|
|
||||||
node->Title = title;
|
|
||||||
node->Filename = file;
|
|
||||||
node->bOldVersion = false;
|
|
||||||
node->bMissingWads = false;
|
|
||||||
int index = InsertSaveNode (node);
|
|
||||||
|
|
||||||
if (okForQuicksave)
|
|
||||||
{
|
|
||||||
if (quickSaveSlot == NULL) quickSaveSlot = node;
|
|
||||||
LastAccessed = LastSaved = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void M_NotifyNewSave (const char *file, const char *title, bool okForQuicksave)
|
|
||||||
{
|
|
||||||
DLoadSaveMenu::NotifyNewSave(file, title, okForQuicksave);
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//
|
//
|
||||||
|
@ -315,13 +96,12 @@ void M_NotifyNewSave (const char *file, const char *title, bool okForQuicksave)
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
DLoadSaveMenu::DLoadSaveMenu(DMenu* parent, FListMenuDescriptor* desc)
|
DLoadSaveMenu()
|
||||||
: DListMenu(parent, desc)
|
|
||||||
{
|
{
|
||||||
ReadSaveStrings();
|
savegameManager.ReadSaveStrings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DLoadSaveMenu::Init(DMenu* parent, FListMenuDescriptor* desc)
|
void Init(DMenu* parent, FListMenuDescriptor* desc)
|
||||||
{
|
{
|
||||||
Super::Init(parent, desc);
|
Super::Init(parent, desc);
|
||||||
int Width43 = screen->GetHeight() * 4 / 3;
|
int Width43 = screen->GetHeight() * 4 / 3;
|
||||||
|
@ -332,11 +112,13 @@ void DLoadSaveMenu::Init(DMenu* parent, FListMenuDescriptor* desc)
|
||||||
savepicWidth = int(240 * wScale);
|
savepicWidth = int(240 * wScale);
|
||||||
savepicHeight = int(180 * wScale);
|
savepicHeight = int(180 * wScale);
|
||||||
|
|
||||||
rowHeight = (NewConsoleFont->GetHeight() + 1) * CleanYfac;
|
|
||||||
|
FontScale = max(screen->GetHeight() / 480, 1);
|
||||||
|
rowHeight = std::max(int((NewConsoleFont->GetHeight() + 1) * FontScale), 1);
|
||||||
listboxLeft = savepicLeft + savepicWidth + int(20 * wScale);
|
listboxLeft = savepicLeft + savepicWidth + int(20 * wScale);
|
||||||
listboxTop = savepicTop;
|
listboxTop = savepicTop;
|
||||||
listboxWidth = Width43 + Left43 - listboxLeft - int(30 * wScale);
|
listboxWidth = Width43 + Left43 - listboxLeft - int(30 * wScale);
|
||||||
int listboxHeight1 = screen->GetHeight() - listboxTop - 10;
|
int listboxHeight1 = screen->GetHeight() - listboxTop - int(20*wScale);
|
||||||
listboxRows = (listboxHeight1 - 1) / rowHeight;
|
listboxRows = (listboxHeight1 - 1) / rowHeight;
|
||||||
listboxHeight = listboxRows * rowHeight + 1;
|
listboxHeight = listboxRows * rowHeight + 1;
|
||||||
listboxRight = listboxLeft + listboxWidth;
|
listboxRight = listboxLeft + listboxWidth;
|
||||||
|
@ -345,14 +127,10 @@ void DLoadSaveMenu::Init(DMenu* parent, FListMenuDescriptor* desc)
|
||||||
commentLeft = savepicLeft;
|
commentLeft = savepicLeft;
|
||||||
commentTop = savepicTop + savepicHeight + int(16 * wScale);
|
commentTop = savepicTop + savepicHeight + int(16 * wScale);
|
||||||
commentWidth = savepicWidth;
|
commentWidth = savepicWidth;
|
||||||
commentHeight = (51+(screen->GetHeight()>200?10:0))*CleanYfac;
|
commentHeight = listboxHeight - savepicHeight - (16 * wScale);
|
||||||
commentRight = commentLeft + commentWidth;
|
commentRight = commentLeft + commentWidth;
|
||||||
commentBottom = commentTop + commentHeight;
|
commentBottom = commentTop + commentHeight;
|
||||||
}
|
commentRows = commentHeight / rowHeight;
|
||||||
|
|
||||||
void DLoadSaveMenu::Destroy()
|
|
||||||
{
|
|
||||||
ClearSaveStuff ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
@ -361,67 +139,10 @@ void DLoadSaveMenu::Destroy()
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
void DLoadSaveMenu::UnloadSaveData ()
|
void Drawer() override
|
||||||
{
|
|
||||||
if (SavePic != NULL)
|
|
||||||
{
|
|
||||||
delete SavePic;
|
|
||||||
}
|
|
||||||
SaveComment.Clear();
|
|
||||||
|
|
||||||
SavePic = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void DLoadSaveMenu::ClearSaveStuff ()
|
|
||||||
{
|
|
||||||
UnloadSaveData();
|
|
||||||
if (quickSaveSlot == (FSaveGameNode*)1)
|
|
||||||
{
|
|
||||||
quickSaveSlot = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void DLoadSaveMenu::ExtractSaveData (int index)
|
|
||||||
{
|
|
||||||
FILE *file;
|
|
||||||
//PNGHandle *png;
|
|
||||||
FSaveGameNode *node;
|
|
||||||
|
|
||||||
UnloadSaveData ();
|
|
||||||
|
|
||||||
if ((unsigned)index < SaveGames.Size() &&
|
|
||||||
(node = SaveGames[index]) &&
|
|
||||||
!node->Filename.IsEmpty() &&
|
|
||||||
!node->bOldVersion &&
|
|
||||||
(file = fopen (node->Filename.GetChars(), "rb")) != NULL)
|
|
||||||
{
|
|
||||||
// Todo.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void DLoadSaveMenu::Drawer ()
|
|
||||||
{
|
{
|
||||||
Super::Drawer();
|
Super::Drawer();
|
||||||
|
|
||||||
FSaveGameNode *node;
|
|
||||||
int i;
|
int i;
|
||||||
unsigned j;
|
unsigned j;
|
||||||
bool didSeeSelected = false;
|
bool didSeeSelected = false;
|
||||||
|
@ -434,115 +155,104 @@ void DLoadSaveMenu::Drawer ()
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//V_DrawFrame (savepicLeft, savepicTop, savepicWidth, savepicHeight);
|
PalEntry frameColor(255, 80, 80, 80); // todo: pick a proper color per game.
|
||||||
if (SavePic != NULL)
|
PalEntry fillColor(160, 0, 0, 0);
|
||||||
|
DrawFrame(&twod, frameColor, savepicLeft, savepicTop, savepicWidth, savepicHeight, -1);
|
||||||
|
if (!savegameManager.DrawSavePic(savepicLeft, savepicTop, savepicWidth, savepicHeight))
|
||||||
{
|
{
|
||||||
DrawTexture(&twod, SavePic, savepicLeft, savepicTop,
|
twod.AddColorOnlyQuad(savepicLeft, savepicTop, savepicWidth, savepicHeight, fillColor);
|
||||||
DTA_DestWidth, savepicWidth,
|
|
||||||
DTA_DestHeight, savepicHeight,
|
|
||||||
DTA_Masked, false,
|
|
||||||
TAG_DONE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
twod.AddColorOnlyQuad(savepicLeft, savepicTop, savepicWidth, savepicHeight, 0x80000000);
|
|
||||||
|
|
||||||
if (SaveGames.Size() > 0)
|
if (savegameManager.SavegameCount() > 0)
|
||||||
{
|
{
|
||||||
const char *text =
|
FString text = (Selected == -1 || !savegameManager.GetSavegame(Selected)->bOldVersion) ? GStrings("MNU_NOPICTURE") : GStrings("MNU_DIFFVERSION");
|
||||||
(Selected == -1 || !SaveGames[Selected]->bOldVersion)
|
int textlen = NewSmallFont->StringWidth(text) * CleanXfac;
|
||||||
? GStrings("MNU_NOPICTURE") : GStrings("MNU_DIFFVERSION");
|
|
||||||
const int textlen = NewConsoleFont->StringWidth (text)*CleanXfac;
|
|
||||||
|
|
||||||
DrawText (&twod, NewConsoleFont, CR_GOLD, savepicLeft+(savepicWidth-textlen)/2,
|
DrawText(&twod, NewSmallFont, CR_GOLD, savepicLeft + (savepicWidth - textlen) / 2,
|
||||||
savepicTop+(savepicHeight-rowHeight)/2, text,
|
savepicTop + (savepicHeight - rowHeight) / 2, text, DTA_CleanNoMove, true, TAG_DONE);
|
||||||
DTA_CleanNoMove, true, TAG_DONE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw comment area
|
// Draw comment area
|
||||||
//V_DrawFrame (commentLeft, commentTop, commentWidth, commentHeight);
|
DrawFrame(&twod, frameColor, commentLeft, commentTop, commentWidth, commentHeight, -1);
|
||||||
twod.AddColorOnlyQuad(commentLeft, commentTop, commentWidth, commentHeight, 0x80000000);
|
twod.AddColorOnlyQuad(commentLeft, commentTop, commentWidth, commentHeight, fillColor);
|
||||||
if (SaveComment.Size())
|
|
||||||
|
int numlinestoprint = std::min(commentRows, (int)BrokenSaveComment.Size());
|
||||||
|
for (int i = 0; i < numlinestoprint; i++)
|
||||||
{
|
{
|
||||||
// I'm not sure why SaveComment would go NULL in this loop, but I got
|
DrawText(&twod, NewConsoleFont, CR_ORANGE, commentLeft / FontScale, (commentTop + rowHeight * i) / FontScale, BrokenSaveComment[i].Text,
|
||||||
// a crash report where it was NULL when i reached 1, so now I check
|
DTA_VirtualWidthF, screen->GetWidth() / FontScale, DTA_VirtualHeightF, screen->GetHeight() / FontScale, DTA_KeepRatio, true, TAG_DONE);
|
||||||
// for that.
|
|
||||||
for (i = 0; i < SaveComment.Size() && SaveComment[i].Width >= 0 && i < 6; ++i)
|
|
||||||
{
|
|
||||||
DrawText (&twod, NewConsoleFont, CR_GOLD, commentLeft, commentTop
|
|
||||||
+ NewConsoleFont->GetHeight()*i*CleanYfac, SaveComment[i].Text,
|
|
||||||
DTA_CleanNoMove, true, TAG_DONE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Draw file area
|
// Draw file area
|
||||||
//V_DrawFrame (listboxLeft, listboxTop, listboxWidth, listboxHeight);
|
DrawFrame(&twod, frameColor, listboxLeft, listboxTop, listboxWidth, listboxHeight, -1);
|
||||||
twod.AddColorOnlyQuad(listboxLeft, listboxTop, listboxWidth, listboxHeight, 0x80000000);
|
twod.AddColorOnlyQuad(listboxLeft, listboxTop, listboxWidth, listboxHeight, fillColor);
|
||||||
|
|
||||||
if (SaveGames.Size() == 0)
|
if (savegameManager.SavegameCount() == 0)
|
||||||
{
|
{
|
||||||
const char * text = GStrings("MNU_NOFILES");
|
FString text = GStrings("MNU_NOFILES");
|
||||||
const int textlen = NewConsoleFont->StringWidth (text)*CleanXfac;
|
int textlen = int(NewConsoleFont->StringWidth(text) * FontScale);
|
||||||
|
|
||||||
DrawText (&twod, NewConsoleFont, CR_GOLD, listboxLeft+(listboxWidth-textlen)/2,
|
DrawText(&twod, NewConsoleFont, CR_GOLD, (listboxLeft + (listboxWidth - textlen) / 2) / FontScale, (listboxTop + (listboxHeight - rowHeight) / 2) / FontScale, text,
|
||||||
listboxTop+(listboxHeight-rowHeight)/2, text,
|
DTA_VirtualWidthF, screen->GetWidth() / FontScale, DTA_VirtualHeightF, screen->GetHeight() / FontScale, DTA_KeepRatio, true, TAG_DONE);
|
||||||
DTA_CleanNoMove, true, TAG_DONE);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0, j = TopItem; i < listboxRows && j < SaveGames.Size(); i++,j++)
|
j = TopItem;
|
||||||
|
for (i = 0; i < listboxRows && j < savegameManager.SavegameCount(); i++)
|
||||||
{
|
{
|
||||||
int color;
|
int colr;
|
||||||
node = SaveGames[j];
|
auto& node = *savegameManager.GetSavegame(j);
|
||||||
if (node->bOldVersion)
|
if (node.bOldVersion)
|
||||||
{
|
{
|
||||||
color = CR_BLUE;
|
colr = CR_RED;
|
||||||
}
|
}
|
||||||
else if (node->bMissingWads)
|
else if (node.bMissingWads)
|
||||||
{
|
{
|
||||||
color = CR_ORANGE;
|
colr = CR_YELLOW;
|
||||||
}
|
}
|
||||||
else if ((int)j == Selected)
|
else if (j == Selected)
|
||||||
{
|
{
|
||||||
color = CR_WHITE;
|
colr = CR_WHITE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
color = CR_TAN;
|
colr = CR_TAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//screen->SetClipRect(listboxLeft, listboxTop+rowHeight*i, listboxRight, listboxTop+rowHeight*(i+1));
|
||||||
|
|
||||||
if ((int)j == Selected)
|
if ((int)j == Selected)
|
||||||
{
|
{
|
||||||
twod.AddColorOnlyQuad(listboxLeft, listboxTop+rowHeight*i, listboxRight, listboxTop+rowHeight*(i+1), mEntering ? PalEntry(255,255,0,0) : PalEntry(255,0,0,255));
|
twod.AddColorOnlyQuad(listboxLeft, listboxTop + rowHeight * i, listboxWidth, rowHeight, mEntering ? PalEntry(255, 255, 0, 0) : PalEntry(255, 0, 0, 255));
|
||||||
didSeeSelected = true;
|
didSeeSelected = true;
|
||||||
if (!mEntering)
|
if (!mEntering)
|
||||||
{
|
{
|
||||||
DrawText(&twod, NewConsoleFont, color,
|
DrawText(&twod, NewConsoleFont, colr, (listboxLeft + 1) / FontScale, (listboxTop + rowHeight * i + FontScale) / FontScale, node.SaveTitle,
|
||||||
listboxLeft+1, listboxTop+rowHeight*i+CleanYfac, node->Title,
|
DTA_VirtualWidthF, screen->GetWidth() / FontScale, DTA_VirtualHeightF, screen->GetHeight() / FontScale, DTA_KeepRatio, true, TAG_DONE);
|
||||||
DTA_CleanNoMove, true, TAG_DONE);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DrawText(&twod, NewConsoleFont, CR_WHITE,
|
FStringf s("%s%c", mInput->GetText(), NewConsoleFont->GetCursor());
|
||||||
listboxLeft+1, listboxTop+rowHeight*i+CleanYfac, savegamestring,
|
int length = int(NewConsoleFont->StringWidth(s) * FontScale);
|
||||||
DTA_CleanNoMove, true, TAG_DONE);
|
int displacement = std::min(0, listboxWidth - 2 - length);
|
||||||
|
DrawText(&twod, NewConsoleFont, CR_WHITE, (listboxLeft + 1 + displacement) / FontScale, (listboxTop + rowHeight * i + FontScale) / FontScale, s,
|
||||||
|
DTA_VirtualWidthF, screen->GetWidth() / FontScale, DTA_VirtualHeightF, screen->GetHeight() / FontScale, DTA_KeepRatio, true, TAG_DONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DrawText(&twod, NewConsoleFont, colr, (listboxLeft + 1) / FontScale, (listboxTop + rowHeight * i + FontScale) / FontScale, node.SaveTitle,
|
||||||
|
DTA_VirtualWidthF, screen->GetWidth() / FontScale, DTA_VirtualHeightF, screen->GetHeight() / FontScale, DTA_KeepRatio, true, TAG_DONE);
|
||||||
|
}
|
||||||
|
//screen->ClearClipRect();
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char curs[2] = { NewConsoleFont->GetCursor(), 0 };
|
void UpdateSaveComment()
|
||||||
DrawText(&twod, NewConsoleFont, CR_WHITE,
|
|
||||||
listboxLeft+1+NewConsoleFont->StringWidth (savegamestring)*CleanXfac,
|
|
||||||
listboxTop+rowHeight*i+CleanYfac,
|
|
||||||
curs,
|
|
||||||
DTA_CleanNoMove, true, TAG_DONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
DrawText(&twod, NewConsoleFont, color,
|
//BrokenSaveComment = NewConsoleFont.BreakLines(manager.SaveCommentString, int(commentWidth / FontScale));
|
||||||
listboxLeft+1, listboxTop+rowHeight*i+CleanYfac, node->Title,
|
|
||||||
DTA_CleanNoMove, true, TAG_DONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
@ -551,73 +261,78 @@ void DLoadSaveMenu::Drawer ()
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
bool DLoadSaveMenu::MenuEvent (int mkey, bool fromcontroller)
|
bool MenuEvent(int mkey, bool fromcontroller) override
|
||||||
{
|
{
|
||||||
|
auto& manager = savegameManager;
|
||||||
switch (mkey)
|
switch (mkey)
|
||||||
{
|
{
|
||||||
case MKEY_Up:
|
case MKEY_Up:
|
||||||
if (SaveGames.Size() > 1)
|
if (manager.SavegameCount() > 1)
|
||||||
{
|
{
|
||||||
if (Selected == -1) Selected = TopItem;
|
if (Selected == -1) Selected = TopItem;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (--Selected < 0) Selected = SaveGames.Size()-1;
|
if (--Selected < 0) Selected = manager.SavegameCount() - 1;
|
||||||
if (Selected < TopItem) TopItem = Selected;
|
if (Selected < TopItem) TopItem = Selected;
|
||||||
else if (Selected >= TopItem + listboxRows) TopItem = std::max(0, Selected - listboxRows + 1);
|
else if (Selected >= TopItem + listboxRows) TopItem = std::max(0, Selected - listboxRows + 1);
|
||||||
}
|
}
|
||||||
UnloadSaveData ();
|
manager.UnloadSaveData();
|
||||||
ExtractSaveData (Selected);
|
manager.ExtractSaveData(Selected);
|
||||||
|
UpdateSaveComment();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case MKEY_Down:
|
case MKEY_Down:
|
||||||
if (SaveGames.Size() > 1)
|
if (manager.SavegameCount() > 1)
|
||||||
{
|
{
|
||||||
if (Selected == -1) Selected = TopItem;
|
if (Selected == -1) Selected = TopItem;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (unsigned(++Selected) >= SaveGames.Size()) Selected = 0;
|
if (++Selected >= manager.SavegameCount()) Selected = 0;
|
||||||
if (Selected < TopItem) TopItem = Selected;
|
if (Selected < TopItem) TopItem = Selected;
|
||||||
else if (Selected >= TopItem + listboxRows) TopItem = std::max(0, Selected - listboxRows + 1);
|
else if (Selected >= TopItem + listboxRows) TopItem = std::max(0, Selected - listboxRows + 1);
|
||||||
}
|
}
|
||||||
UnloadSaveData ();
|
manager.UnloadSaveData();
|
||||||
ExtractSaveData (Selected);
|
manager.ExtractSaveData(Selected);
|
||||||
|
UpdateSaveComment();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case MKEY_PageDown:
|
case MKEY_PageDown:
|
||||||
if (SaveGames.Size() > 1)
|
if (manager.SavegameCount() > 1)
|
||||||
{
|
{
|
||||||
if (TopItem >= (int)SaveGames.Size() - listboxRows)
|
if (TopItem >= manager.SavegameCount() - listboxRows)
|
||||||
{
|
{
|
||||||
TopItem = 0;
|
TopItem = 0;
|
||||||
if (Selected != -1) Selected = 0;
|
if (Selected != -1) Selected = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TopItem = std::min<int>(TopItem + listboxRows, SaveGames.Size() - listboxRows);
|
TopItem = std::min(TopItem + listboxRows, int(manager.SavegameCount()) - listboxRows);
|
||||||
if (TopItem > Selected&& Selected != -1) Selected = TopItem;
|
if (TopItem > Selected&& Selected != -1) Selected = TopItem;
|
||||||
}
|
}
|
||||||
UnloadSaveData ();
|
manager.UnloadSaveData();
|
||||||
ExtractSaveData (Selected);
|
manager.ExtractSaveData(Selected);
|
||||||
|
UpdateSaveComment();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case MKEY_PageUp:
|
case MKEY_PageUp:
|
||||||
if (SaveGames.Size() > 1)
|
if (manager.SavegameCount() > 1)
|
||||||
{
|
{
|
||||||
if (TopItem == 0)
|
if (TopItem == 0)
|
||||||
{
|
{
|
||||||
TopItem = SaveGames.Size() - listboxRows;
|
TopItem = std::max(0, int(manager.SavegameCount()) - listboxRows);
|
||||||
if (Selected != -1) Selected = TopItem;
|
if (Selected != -1) Selected = TopItem;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TopItem = std::max(TopItem - listboxRows, 0);
|
TopItem = std::max(int(TopItem - listboxRows), 0);
|
||||||
if (Selected >= TopItem + listboxRows) Selected = TopItem;
|
if (Selected >= TopItem + listboxRows) Selected = TopItem;
|
||||||
}
|
}
|
||||||
UnloadSaveData ();
|
manager.UnloadSaveData();
|
||||||
ExtractSaveData (Selected);
|
manager.ExtractSaveData(Selected);
|
||||||
|
UpdateSaveComment();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -626,18 +341,10 @@ bool DLoadSaveMenu::MenuEvent (int mkey, bool fromcontroller)
|
||||||
|
|
||||||
case MKEY_MBYes:
|
case MKEY_MBYes:
|
||||||
{
|
{
|
||||||
if ((unsigned)Selected < SaveGames.Size())
|
if (Selected < manager.SavegameCount())
|
||||||
{
|
{
|
||||||
int listindex = SaveGames[0]->bNoDelete? Selected-1 : Selected;
|
Selected = manager.RemoveSaveSlot(Selected);
|
||||||
remove (SaveGames[Selected]->Filename.GetChars());
|
UpdateSaveComment();
|
||||||
UnloadSaveData ();
|
|
||||||
Selected = RemoveSaveSlot (Selected);
|
|
||||||
ExtractSaveData (Selected);
|
|
||||||
|
|
||||||
if (LastSaved == listindex) LastSaved = -1;
|
|
||||||
else if (LastSaved > listindex) LastSaved--;
|
|
||||||
if (LastAccessed == listindex) LastAccessed = -1;
|
|
||||||
else if (LastAccessed > listindex) LastAccessed--;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -653,18 +360,20 @@ bool DLoadSaveMenu::MenuEvent (int mkey, bool fromcontroller)
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
bool DLoadSaveMenu::MouseEvent(int type, int x, int y)
|
bool MouseEvent(int type, int x, int y) override
|
||||||
{
|
{
|
||||||
|
auto& manager = savegameManager;
|
||||||
if (x >= listboxLeft && x < listboxLeft + listboxWidth &&
|
if (x >= listboxLeft && x < listboxLeft + listboxWidth &&
|
||||||
y >= listboxTop && y < listboxTop + listboxHeight)
|
y >= listboxTop && y < listboxTop + listboxHeight)
|
||||||
{
|
{
|
||||||
int lineno = (y - listboxTop) / rowHeight;
|
int lineno = (y - listboxTop) / rowHeight;
|
||||||
|
|
||||||
if (TopItem + lineno < (int)SaveGames.Size())
|
if (TopItem + lineno < manager.SavegameCount())
|
||||||
{
|
{
|
||||||
Selected = TopItem + lineno;
|
Selected = TopItem + lineno;
|
||||||
UnloadSaveData ();
|
manager.UnloadSaveData();
|
||||||
ExtractSaveData (Selected);
|
manager.ExtractSaveData(Selected);
|
||||||
|
UpdateSaveComment();
|
||||||
if (type == MOUSE_Release)
|
if (type == MOUSE_Release)
|
||||||
{
|
{
|
||||||
if (MenuEvent(MKEY_Enter, true))
|
if (MenuEvent(MKEY_Enter, true))
|
||||||
|
@ -686,22 +395,20 @@ bool DLoadSaveMenu::MouseEvent(int type, int x, int y)
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
bool DLoadSaveMenu::Responder (event_t *ev)
|
bool Responder(event_t * ev) override
|
||||||
{
|
{
|
||||||
|
auto& manager = savegameManager;
|
||||||
if (ev->type == EV_GUI_Event)
|
if (ev->type == EV_GUI_Event)
|
||||||
{
|
{
|
||||||
if (ev->subtype == EV_GUI_KeyDown)
|
if (ev->subtype == EV_GUI_KeyDown)
|
||||||
{
|
{
|
||||||
if ((unsigned)Selected < SaveGames.Size())
|
if ((unsigned)Selected < manager.SavegameCount())
|
||||||
{
|
{
|
||||||
switch (ev->data1)
|
switch (ev->data1)
|
||||||
{
|
{
|
||||||
case GK_F1:
|
case GK_F1:
|
||||||
if (!SaveGames[Selected]->Filename.IsEmpty())
|
manager.SetFileInfo(Selected);
|
||||||
{
|
UpdateSaveComment();
|
||||||
FStringf workbuf("File on disk:\n%s", SaveGames[Selected]->Filename.GetChars());
|
|
||||||
SaveComment = V_BreakLines (NewConsoleFont, 216*screen->GetWidth()/640/CleanXfac, workbuf);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case GK_DEL:
|
case GK_DEL:
|
||||||
|
@ -709,7 +416,7 @@ bool DLoadSaveMenu::Responder (event_t *ev)
|
||||||
{
|
{
|
||||||
FString EndString;
|
FString EndString;
|
||||||
EndString.Format("%s" TEXTCOLOR_WHITE "%s" TEXTCOLOR_NORMAL "?\n\n%s",
|
EndString.Format("%s" TEXTCOLOR_WHITE "%s" TEXTCOLOR_NORMAL "?\n\n%s",
|
||||||
GStrings("MNU_DELETESG"), SaveGames[Selected]->Title.GetChars(), GStrings("PRESSYN"));
|
GStrings("MNU_DELETESG"), manager.GetSavegame(Selected)->SaveTitle.GetChars(), GStrings("PRESSYN"));
|
||||||
M_StartMessage(EndString, 0);
|
M_StartMessage(EndString, 0);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -723,13 +430,13 @@ bool DLoadSaveMenu::Responder (event_t *ev)
|
||||||
}
|
}
|
||||||
else if (ev->subtype == EV_GUI_WheelDown)
|
else if (ev->subtype == EV_GUI_WheelDown)
|
||||||
{
|
{
|
||||||
if (TopItem < (int)SaveGames.Size() - listboxRows) TopItem++;
|
if (TopItem < manager.SavegameCount() - listboxRows) TopItem++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Super::Responder(ev);
|
return Super::Responder(ev);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//
|
//
|
||||||
|
@ -740,17 +447,9 @@ bool DLoadSaveMenu::Responder (event_t *ev)
|
||||||
class DSaveMenu : public DLoadSaveMenu
|
class DSaveMenu : public DLoadSaveMenu
|
||||||
{
|
{
|
||||||
using Super = DLoadSaveMenu;
|
using Super = DLoadSaveMenu;
|
||||||
FSaveGameNode NewSaveNode;
|
FString mSaveName;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DSaveMenu(DMenu *parent = NULL, FListMenuDescriptor *desc = NULL);
|
|
||||||
void Destroy();
|
|
||||||
void DoSave (FSaveGameNode *node);
|
|
||||||
bool Responder (event_t *ev);
|
|
||||||
bool MenuEvent (int mkey, bool fromcontroller);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//
|
//
|
||||||
|
@ -758,22 +457,12 @@ public:
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
DSaveMenu::DSaveMenu(DMenu *parent, FListMenuDescriptor *desc)
|
DSaveMenu()
|
||||||
: DLoadSaveMenu(parent, desc)
|
|
||||||
{
|
{
|
||||||
NewSaveNode.Title = GStrings["NEWSAVE"];
|
savegameManager.InsertNewSaveNode();
|
||||||
NewSaveNode.bNoDelete = true;
|
|
||||||
SaveGames.Insert(0, &NewSaveNode);
|
|
||||||
TopItem = 0;
|
TopItem = 0;
|
||||||
if (LastSaved == -1)
|
Selected = savegameManager.ExtractSaveData (-1);
|
||||||
{
|
UpdateSaveComment();
|
||||||
Selected = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Selected = LastSaved + 1;
|
|
||||||
}
|
|
||||||
ExtractSaveData (Selected);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
@ -782,57 +471,21 @@ DSaveMenu::DSaveMenu(DMenu *parent, FListMenuDescriptor *desc)
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
void DSaveMenu::Destroy()
|
void Destroy() override
|
||||||
{
|
{
|
||||||
if (SaveGames[0] == &NewSaveNode)
|
if (savegameManager.RemoveNewSaveNode())
|
||||||
{
|
{
|
||||||
SaveGames.Delete(0);
|
Selected--;
|
||||||
if (Selected == 0) Selected = -1;
|
|
||||||
else Selected--;
|
|
||||||
}
|
}
|
||||||
|
Super::Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
void DSaveMenu::DoSave (FSaveGameNode *node)
|
bool MenuEvent (int mkey, bool fromcontroller) override
|
||||||
{
|
|
||||||
if (node != &NewSaveNode)
|
|
||||||
{
|
|
||||||
//G_SaveGame (node->Filename.GetChars(), savegamestring);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Find an unused filename and save as that
|
|
||||||
FString filename;
|
|
||||||
int i;
|
|
||||||
FILE *test;
|
|
||||||
|
|
||||||
for (i = 0;; ++i)
|
|
||||||
{
|
|
||||||
filename = "";// G_BuildSaveName("save", i);
|
|
||||||
test = fopen (filename, "rb");
|
|
||||||
if (test == NULL)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fclose (test);
|
|
||||||
}
|
|
||||||
//G_SaveGame (filename, savegamestring);
|
|
||||||
}
|
|
||||||
M_ClearMenus();
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
bool DSaveMenu::MenuEvent (int mkey, bool fromcontroller)
|
|
||||||
{
|
{
|
||||||
if (Super::MenuEvent(mkey, fromcontroller))
|
if (Super::MenuEvent(mkey, fromcontroller))
|
||||||
{
|
{
|
||||||
|
@ -845,26 +498,21 @@ bool DSaveMenu::MenuEvent (int mkey, bool fromcontroller)
|
||||||
|
|
||||||
if (mkey == MKEY_Enter)
|
if (mkey == MKEY_Enter)
|
||||||
{
|
{
|
||||||
if (Selected != 0)
|
FString SavegameString = (Selected != 0)? savegameManager.GetSavegame(Selected)->SaveTitle : FString();
|
||||||
{
|
mInput = new DTextEnterMenu(this, NewConsoleFont, SavegameString, listboxWidth, false, false);
|
||||||
savegamestring = SaveGames[Selected]->Title;
|
M_ActivateMenu(mInput);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
savegamestring = "";
|
|
||||||
}
|
|
||||||
DMenu *input = new DTextEnterMenu(this, savegamestring, 1, fromcontroller);
|
|
||||||
M_ActivateMenu(input);
|
|
||||||
mEntering = true;
|
mEntering = true;
|
||||||
}
|
}
|
||||||
else if (mkey == MKEY_Input)
|
else if (mkey == MKEY_Input)
|
||||||
{
|
{
|
||||||
mEntering = false;
|
mEntering = false;
|
||||||
DoSave(SaveGames[Selected]);
|
mSaveName = mInput->GetText();
|
||||||
|
mInput = nullptr;
|
||||||
}
|
}
|
||||||
else if (mkey == MKEY_Abort)
|
else if (mkey == MKEY_Abort)
|
||||||
{
|
{
|
||||||
mEntering = false;
|
mEntering = false;
|
||||||
|
mInput = nullptr;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -875,7 +523,25 @@ bool DSaveMenu::MenuEvent (int mkey, bool fromcontroller)
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
bool DSaveMenu::Responder (event_t *ev)
|
bool MouseEvent(int type, int x, int y) override
|
||||||
|
{
|
||||||
|
if (mSaveName.Len() > 0)
|
||||||
|
{
|
||||||
|
// Do not process events when saving is in progress to avoid update of the current index,
|
||||||
|
// i.e. Selected member variable must remain unchanged
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Super::MouseEvent(type, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
bool Responder (event_t *ev) override
|
||||||
{
|
{
|
||||||
if (ev->subtype == EV_GUI_KeyDown)
|
if (ev->subtype == EV_GUI_KeyDown)
|
||||||
{
|
{
|
||||||
|
@ -891,7 +557,7 @@ bool DSaveMenu::Responder (event_t *ev)
|
||||||
|
|
||||||
case 'N':
|
case 'N':
|
||||||
Selected = TopItem = 0;
|
Selected = TopItem = 0;
|
||||||
UnloadSaveData ();
|
savegameManager.UnloadSaveData();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -905,15 +571,15 @@ bool DSaveMenu::Responder (event_t *ev)
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
class DLoadMenu : public DLoadSaveMenu
|
void Ticker() override
|
||||||
{
|
{
|
||||||
using Super = DLoadSaveMenu;
|
if (mSaveName.Len() > 0)
|
||||||
|
{
|
||||||
|
savegameManager.DoSave(Selected, mSaveName);
|
||||||
|
mSaveName = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
DLoadMenu(DMenu *parent = NULL, FListMenuDescriptor *desc = NULL);
|
|
||||||
|
|
||||||
bool MenuEvent (int mkey, bool fromcontroller);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
@ -922,16 +588,23 @@ public:
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
DLoadMenu::DLoadMenu(DMenu *parent, FListMenuDescriptor *desc)
|
class DLoadMenu : public DLoadSaveMenu
|
||||||
: DLoadSaveMenu(parent, desc)
|
{
|
||||||
|
using Super = DLoadSaveMenu;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
DLoadMenu()
|
||||||
{
|
{
|
||||||
TopItem = 0;
|
TopItem = 0;
|
||||||
if (LastAccessed != -1)
|
Selected = savegameManager.ExtractSaveData(-1);
|
||||||
{
|
UpdateSaveComment();
|
||||||
Selected = LastAccessed;
|
|
||||||
}
|
|
||||||
ExtractSaveData (Selected);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
@ -940,30 +613,25 @@ DLoadMenu::DLoadMenu(DMenu *parent, FListMenuDescriptor *desc)
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
bool DLoadMenu::MenuEvent (int mkey, bool fromcontroller)
|
bool MenuEvent(int mkey, bool fromcontroller) override
|
||||||
{
|
{
|
||||||
if (Super::MenuEvent(mkey, fromcontroller))
|
if (Super::MenuEvent(mkey, fromcontroller))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (Selected == -1 || SaveGames.Size() == 0)
|
if (Selected == -1 || savegameManager.SavegameCount() == 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mkey == MKEY_Enter)
|
if (mkey == MKEY_Enter)
|
||||||
{
|
{
|
||||||
//G_LoadGame (SaveGames[Selected]->Filename.GetChars(), true);
|
savegameManager.LoadSavegame(Selected);
|
||||||
if (quickSaveSlot == (FSaveGameNode*)1)
|
|
||||||
{
|
|
||||||
quickSaveSlot = SaveGames[Selected];
|
|
||||||
}
|
|
||||||
M_ClearMenus();
|
|
||||||
LastAccessed = Selected;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static TMenuClassDescriptor<DLoadMenu> _lm("LoadMenu");
|
static TMenuClassDescriptor<DLoadMenu> _lm("LoadMenu");
|
||||||
static TMenuClassDescriptor<DSaveMenu> _sm("SaveMenu");
|
static TMenuClassDescriptor<DSaveMenu> _sm("SaveMenu");
|
||||||
|
|
|
@ -569,6 +569,7 @@ bool M_SetMenu(FName menu, int param, FName caller)
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
Printf("Attempting to open menu of unknown type '%s'\n", menu.GetChars());
|
Printf("Attempting to open menu of unknown type '%s'\n", menu.GetChars());
|
||||||
|
M_ClearMenus();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -974,7 +975,7 @@ CCMD(opensavemenu)
|
||||||
{
|
{
|
||||||
gi->MenuOpened();
|
gi->MenuOpened();
|
||||||
M_StartControlPanel(false);
|
M_StartControlPanel(false);
|
||||||
M_SetMenu(NAME_SaveMenu);
|
M_SetMenu(NAME_SaveGameMenu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -982,5 +983,5 @@ CCMD(openloadmenu)
|
||||||
{
|
{
|
||||||
gi->MenuOpened();
|
gi->MenuOpened();
|
||||||
M_StartControlPanel(false);
|
M_StartControlPanel(false);
|
||||||
M_SetMenu(NAME_LoadMenu);
|
M_SetMenu(NAME_LoadGameMenu);
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,18 +138,6 @@ enum ENativeFontValues
|
||||||
};
|
};
|
||||||
|
|
||||||
extern FGameStartup GameStartupInfo;
|
extern FGameStartup GameStartupInfo;
|
||||||
|
|
||||||
struct FSaveGameNode
|
|
||||||
{
|
|
||||||
FString Title;
|
|
||||||
FString Filename;
|
|
||||||
bool bOldVersion;
|
|
||||||
bool bMissingWads;
|
|
||||||
bool bNoDelete;
|
|
||||||
|
|
||||||
FSaveGameNode() { bNoDelete = false; }
|
|
||||||
};
|
|
||||||
|
|
||||||
extern EMenuState menuactive;
|
extern EMenuState menuactive;
|
||||||
|
|
||||||
|
|
||||||
|
@ -682,29 +670,31 @@ public:
|
||||||
class DTextEnterMenu : public DMenu
|
class DTextEnterMenu : public DMenu
|
||||||
{
|
{
|
||||||
using Super = DMenu;
|
using Super = DMenu;
|
||||||
TArray<char> mEnterString;
|
|
||||||
FString* mOutString;
|
|
||||||
unsigned int mEnterSize;
|
|
||||||
unsigned int mEnterPos;
|
|
||||||
int mSizeMode; // 1: size is length in chars. 2: also check string width
|
|
||||||
bool mInputGridOkay;
|
|
||||||
|
|
||||||
|
FString mEnterString;
|
||||||
|
int mEnterSize;
|
||||||
|
int mEnterPos;
|
||||||
|
bool mInputGridOkay;
|
||||||
int InputGridX;
|
int InputGridX;
|
||||||
int InputGridY;
|
int InputGridY;
|
||||||
|
int CursorSize;
|
||||||
// [TP]
|
|
||||||
bool AllowColors;
|
bool AllowColors;
|
||||||
|
FFont *displayFont;
|
||||||
|
|
||||||
|
|
||||||
|
void AppendChar(int ch);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// [TP] Added allowcolors
|
// [TP] Added allowcolors
|
||||||
DTextEnterMenu(DMenu *parent, FString &textbuffer, int sizemode, bool showgrid, bool allowcolors = false);
|
DTextEnterMenu(DMenu *parent, FFont *dpf, FString textbuffer, int maxlen, bool showgrid, bool allowcolors = false);
|
||||||
|
|
||||||
void Drawer ();
|
void Drawer ();
|
||||||
bool MenuEvent (int mkey, bool fromcontroller);
|
bool MenuEvent (int mkey, bool fromcontroller);
|
||||||
bool Responder(event_t *ev);
|
bool Responder(event_t *ev);
|
||||||
bool TranslateKeyboardEvents();
|
bool TranslateKeyboardEvents();
|
||||||
bool MouseEvent(int type, int x, int y);
|
bool MouseEvent(int type, int x, int y);
|
||||||
|
const char* GetText() { return mEnterString.GetChars(); }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -757,4 +747,56 @@ template<class Menu> struct TMenuClassDescriptor : public MenuClassDescriptor
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct FSaveGameNode
|
||||||
|
{
|
||||||
|
FString SaveTitle;
|
||||||
|
FString Filename;
|
||||||
|
bool bOldVersion = false;
|
||||||
|
bool bMissingWads = false;
|
||||||
|
bool bNoDelete = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FSavegameManager
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
TArray<FSaveGameNode*> SaveGames;
|
||||||
|
FSaveGameNode NewSaveNode;
|
||||||
|
int LastSaved = -1;
|
||||||
|
int LastAccessed = -1;
|
||||||
|
TArray<char> SavePicData;
|
||||||
|
FTexture *SavePic = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
int WindowSize = 0;
|
||||||
|
FString SaveCommentString;
|
||||||
|
FSaveGameNode *quickSaveSlot = nullptr;
|
||||||
|
~FSavegameManager();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int InsertSaveNode(FSaveGameNode *node);
|
||||||
|
public:
|
||||||
|
void NotifyNewSave(const FString &file, const FString &title, bool okForQuicksave, bool forceQuicksave);
|
||||||
|
void ClearSaveGames();
|
||||||
|
|
||||||
|
void ReadSaveStrings();
|
||||||
|
void UnloadSaveData();
|
||||||
|
|
||||||
|
int RemoveSaveSlot(int index);
|
||||||
|
void LoadSavegame(int Selected);
|
||||||
|
void DoSave(int Selected, const char *savegamestring);
|
||||||
|
unsigned ExtractSaveData(int index);
|
||||||
|
void ClearSaveStuff();
|
||||||
|
bool DrawSavePic(int x, int y, int w, int h);
|
||||||
|
void DrawSaveComment(FFont *font, int cr, int x, int y, int scalefactor);
|
||||||
|
void SetFileInfo(int Selected);
|
||||||
|
unsigned SavegameCount();
|
||||||
|
FSaveGameNode *GetSavegame(int i);
|
||||||
|
void InsertNewSaveNode();
|
||||||
|
bool RemoveNewSaveNode();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
extern FSavegameManager savegameManager;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -47,8 +47,6 @@
|
||||||
|
|
||||||
#include "optionmenuitems.h"
|
#include "optionmenuitems.h"
|
||||||
|
|
||||||
void ClearSaveGames();
|
|
||||||
|
|
||||||
// Menu-relevant content that gets filled in by scripts. This will get processed after the game has loaded.
|
// Menu-relevant content that gets filled in by scripts. This will get processed after the game has loaded.
|
||||||
FString gSkillNames[MAXSKILLS];
|
FString gSkillNames[MAXSKILLS];
|
||||||
FString gVolumeNames[MAXVOLUMES];
|
FString gVolumeNames[MAXVOLUMES];
|
||||||
|
@ -94,7 +92,6 @@ static void DeinitMenus()
|
||||||
OptionValues.Clear();
|
OptionValues.Clear();
|
||||||
DMenu::CurrentMenu = NULL;
|
DMenu::CurrentMenu = NULL;
|
||||||
DefaultListMenuSettings.mItems.Clear();
|
DefaultListMenuSettings.mItems.Clear();
|
||||||
ClearSaveGames();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static FTexture* GetMenuTexture(const char* const name)
|
static FTexture* GetMenuTexture(const char* const name)
|
||||||
|
|
|
@ -63,16 +63,13 @@ CVAR(Bool, m_showinputgrid, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
// [TP] Added allowcolors
|
// [TP] Added allowcolors
|
||||||
DTextEnterMenu::DTextEnterMenu(DMenu *parent, FString &textbuffer, int sizemode, bool showgrid, bool allowcolors)
|
DTextEnterMenu::DTextEnterMenu(DMenu *parent, FFont *dpf, FString textbuffer, int maxlen, bool showgrid, bool allowcolors)
|
||||||
: DMenu(parent)
|
: DMenu(parent)
|
||||||
{
|
{
|
||||||
mOutString = &textbuffer;
|
mEnterString = textbuffer;
|
||||||
mEnterSize = 32; // this needs to calculate the size based on screen space (or scroll)
|
mEnterPos = maxlen;
|
||||||
mEnterString.Resize(mEnterSize + 1);
|
mInputGridOkay = (showgrid && (m_showinputgrid == 0)) || (m_showinputgrid >= 1);
|
||||||
mEnterPos = (unsigned)textbuffer.Len();
|
if (mEnterString.Len() > 0)
|
||||||
mSizeMode = sizemode;
|
|
||||||
mInputGridOkay = showgrid || m_showinputgrid;
|
|
||||||
if (mEnterPos > 0)
|
|
||||||
{
|
{
|
||||||
InputGridX = INPUTGRID_WIDTH - 1;
|
InputGridX = INPUTGRID_WIDTH - 1;
|
||||||
InputGridY = INPUTGRID_HEIGHT - 1;
|
InputGridY = INPUTGRID_HEIGHT - 1;
|
||||||
|
@ -84,6 +81,8 @@ DTextEnterMenu::DTextEnterMenu(DMenu *parent, FString &textbuffer, int sizemode,
|
||||||
InputGridY = 0;
|
InputGridY = 0;
|
||||||
}
|
}
|
||||||
AllowColors = allowcolors; // [TP]
|
AllowColors = allowcolors; // [TP]
|
||||||
|
displayFont = dpf;
|
||||||
|
CursorSize = displayFont->StringWidth(displayFont->GetCursor());
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
@ -111,12 +110,7 @@ bool DTextEnterMenu::Responder(event_t *ev)
|
||||||
if (ev->subtype == EV_GUI_Char)
|
if (ev->subtype == EV_GUI_Char)
|
||||||
{
|
{
|
||||||
mInputGridOkay = false;
|
mInputGridOkay = false;
|
||||||
if (mEnterPos < mEnterSize &&
|
AppendChar(ev->data1);
|
||||||
(mSizeMode == 2/*entering player name*/ || (size_t)SmallFont->StringWidth(mEnterString) < (mEnterSize-1)*8))
|
|
||||||
{
|
|
||||||
mEnterString[mEnterPos] = (char)ev->data1;
|
|
||||||
mEnterString[++mEnterPos] = 0;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
char ch = (char)ev->data1;
|
char ch = (char)ev->data1;
|
||||||
|
@ -124,8 +118,7 @@ bool DTextEnterMenu::Responder(event_t *ev)
|
||||||
{
|
{
|
||||||
if (mEnterPos > 0)
|
if (mEnterPos > 0)
|
||||||
{
|
{
|
||||||
mEnterPos--;
|
mEnterString.DeleteLastCharacter();
|
||||||
mEnterString[mEnterPos] = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ev->subtype == EV_GUI_KeyDown)
|
else if (ev->subtype == EV_GUI_KeyDown)
|
||||||
|
@ -133,17 +126,21 @@ bool DTextEnterMenu::Responder(event_t *ev)
|
||||||
if (ch == GK_ESCAPE)
|
if (ch == GK_ESCAPE)
|
||||||
{
|
{
|
||||||
DMenu *parent = mParentMenu;
|
DMenu *parent = mParentMenu;
|
||||||
Close();
|
|
||||||
parent->MenuEvent(MKEY_Abort, false);
|
parent->MenuEvent(MKEY_Abort, false);
|
||||||
|
Close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (ch == '\r')
|
else if (ch == '\r')
|
||||||
{
|
{
|
||||||
if (mEnterString[0])
|
if (mEnterString.Len() > 0)
|
||||||
{
|
{
|
||||||
|
// [TP] If we allow color codes, colorize the string now.
|
||||||
|
//if (AllowColors)
|
||||||
|
//mEnterString = mEnterString.Filter();
|
||||||
|
|
||||||
DMenu *parent = mParentMenu;
|
DMenu *parent = mParentMenu;
|
||||||
Close();
|
|
||||||
parent->MenuEvent(MKEY_Input, false);
|
parent->MenuEvent(MKEY_Input, false);
|
||||||
|
Close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,8 +161,8 @@ bool DTextEnterMenu::Responder(event_t *ev)
|
||||||
|
|
||||||
bool DTextEnterMenu::MouseEvent(int type, int x, int y)
|
bool DTextEnterMenu::MouseEvent(int type, int x, int y)
|
||||||
{
|
{
|
||||||
const int cell_width = 18 * CleanXfac;
|
const int cell_width = 18 * CleanXfac_1;
|
||||||
const int cell_height = 12 * CleanYfac;
|
const int cell_height = 16 * CleanYfac_1;
|
||||||
const int screen_y = screen->GetHeight() - INPUTGRID_HEIGHT * cell_height;
|
const int screen_y = screen->GetHeight() - INPUTGRID_HEIGHT * cell_height;
|
||||||
const int screen_x = (screen->GetWidth() - INPUTGRID_WIDTH * cell_width) / 2;
|
const int screen_x = (screen->GetWidth() - INPUTGRID_WIDTH * cell_width) / 2;
|
||||||
|
|
||||||
|
@ -177,12 +174,12 @@ bool DTextEnterMenu::MouseEvent(int type, int x, int y)
|
||||||
{
|
{
|
||||||
if (MenuEvent(MKEY_Enter, true))
|
if (MenuEvent(MKEY_Enter, true))
|
||||||
{
|
{
|
||||||
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
|
//M_MenuSound(CursorSound);
|
||||||
if (m_use_mouse == 2) InputGridX = InputGridY = -1;
|
if (m_use_mouse == 2) InputGridX = InputGridY = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
InputGridX = InputGridY = -1;
|
InputGridX = InputGridY = -1;
|
||||||
|
@ -190,7 +187,20 @@ bool DTextEnterMenu::MouseEvent(int type, int x, int y)
|
||||||
return Super::MouseEvent(type, x, y);
|
return Super::MouseEvent(type, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void DTextEnterMenu::AppendChar(int ch)
|
||||||
|
{
|
||||||
|
FStringf newstring("%s%c%c", mEnterString.GetChars(), ch, displayFont->GetCursor());
|
||||||
|
if (mEnterSize < 0 || displayFont->StringWidth(newstring) < mEnterSize)
|
||||||
|
{
|
||||||
|
mEnterString.AppendCharacter(ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//
|
//
|
||||||
|
@ -237,9 +247,9 @@ bool DTextEnterMenu::MenuEvent (int key, bool fromcontroller)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case MKEY_Clear:
|
case MKEY_Clear:
|
||||||
if (mEnterPos > 0)
|
if (mEnterString.Len() > 0)
|
||||||
{
|
{
|
||||||
mEnterString[--mEnterPos] = 0;
|
mEnterString.DeleteLastCharacter();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -250,26 +260,24 @@ bool DTextEnterMenu::MenuEvent (int key, bool fromcontroller)
|
||||||
ch = InputGridChars[InputGridX + InputGridY * INPUTGRID_WIDTH];
|
ch = InputGridChars[InputGridX + InputGridY * INPUTGRID_WIDTH];
|
||||||
if (ch == 0) // end
|
if (ch == 0) // end
|
||||||
{
|
{
|
||||||
if (mEnterString[0] != '\0')
|
if (mEnterString.Len() > 0)
|
||||||
{
|
{
|
||||||
DMenu *parent = mParentMenu;
|
DMenu *parent = mParentMenu;
|
||||||
Close();
|
|
||||||
parent->MenuEvent(MKEY_Input, false);
|
parent->MenuEvent(MKEY_Input, false);
|
||||||
|
Close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ch == '\b') // bs
|
else if (ch == '\b') // bs
|
||||||
{
|
{
|
||||||
if (mEnterPos > 0)
|
if (mEnterString.Len() > 0)
|
||||||
{
|
{
|
||||||
mEnterString[--mEnterPos] = 0;
|
mEnterString.DeleteLastCharacter();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mEnterPos < mEnterSize &&
|
else
|
||||||
(mSizeMode == 2/*entering player name*/ || (size_t)SmallFont->StringWidth(mEnterString) < (mEnterSize-1)*8))
|
|
||||||
{
|
{
|
||||||
mEnterString[mEnterPos] = ch;
|
AppendChar(ch);
|
||||||
mEnterString[++mEnterPos] = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -294,7 +302,7 @@ void DTextEnterMenu::Drawer ()
|
||||||
{
|
{
|
||||||
const int cell_width = 18 * CleanXfac;
|
const int cell_width = 18 * CleanXfac;
|
||||||
const int cell_height = 12 * CleanYfac;
|
const int cell_height = 12 * CleanYfac;
|
||||||
const int top_padding = cell_height / 2 - SmallFont->GetHeight() * CleanYfac / 2;
|
const int top_padding = cell_height / 2 - displayFont->GetHeight() * CleanYfac / 2;
|
||||||
|
|
||||||
// Darken the background behind the character grid.
|
// Darken the background behind the character grid.
|
||||||
// Unless we frame it with a border, I think it looks better to extend the
|
// Unless we frame it with a border, I think it looks better to extend the
|
||||||
|
@ -302,7 +310,7 @@ void DTextEnterMenu::Drawer ()
|
||||||
twod.AddColorOnlyQuad(0 /*screen->GetWidth()/2 - 13 * cell_width / 2*/,
|
twod.AddColorOnlyQuad(0 /*screen->GetWidth()/2 - 13 * cell_width / 2*/,
|
||||||
screen->GetHeight() - INPUTGRID_HEIGHT * cell_height,
|
screen->GetHeight() - INPUTGRID_HEIGHT * cell_height,
|
||||||
screen->GetWidth() /*13 * cell_width*/,
|
screen->GetWidth() /*13 * cell_width*/,
|
||||||
INPUTGRID_HEIGHT * cell_height, 0xff000000);
|
INPUTGRID_HEIGHT * cell_height, 0xc8000000);
|
||||||
|
|
||||||
if (InputGridX >= 0 && InputGridY >= 0)
|
if (InputGridX >= 0 && InputGridY >= 0)
|
||||||
{
|
{
|
||||||
|
@ -321,42 +329,42 @@ void DTextEnterMenu::Drawer ()
|
||||||
int width;
|
int width;
|
||||||
const int xx = x * cell_width - INPUTGRID_WIDTH * cell_width / 2 + screen->GetWidth() / 2;
|
const int xx = x * cell_width - INPUTGRID_WIDTH * cell_width / 2 + screen->GetWidth() / 2;
|
||||||
const int ch = InputGridChars[y * INPUTGRID_WIDTH + x];
|
const int ch = InputGridChars[y * INPUTGRID_WIDTH + x];
|
||||||
FTexture *pic = SmallFont->GetChar(ch, CR_DARKGRAY, &width);
|
FTexture *pic = displayFont->GetChar(ch, CR_DARKGRAY, &width);
|
||||||
EColorRange color;
|
EColorRange color;
|
||||||
int remap;
|
int remap;
|
||||||
|
|
||||||
// The highlighted character is yellow; the rest are dark gray.
|
// The highlighted character is yellow; the rest are dark gray.
|
||||||
color = (x == InputGridX && y == InputGridY) ? CR_YELLOW : CR_DARKGRAY;
|
color = (x == InputGridX && y == InputGridY) ? CR_YELLOW : CR_DARKGRAY;
|
||||||
remap = SmallFont->GetColorTranslation(color);
|
remap = displayFont->GetColorTranslation(color);
|
||||||
|
|
||||||
if (pic != NULL)
|
if (pic != NULL)
|
||||||
{
|
{
|
||||||
// Draw a normal character.
|
// Draw a normal character.
|
||||||
DrawTexture(&twod, pic, xx + cell_width/2 - width*CleanXfac/2, yy + top_padding,
|
DrawTexture(&twod, pic, xx + cell_width/2 - width*CleanXfac_1/2, yy + top_padding,
|
||||||
DTA_TranslationIndex, remap,
|
DTA_TranslationIndex, remap,
|
||||||
DTA_CleanNoMove, true,
|
DTA_CleanNoMove_1, true,
|
||||||
TAG_DONE);
|
TAG_DONE);
|
||||||
}
|
}
|
||||||
else if (ch == ' ')
|
else if (ch == ' ')
|
||||||
{
|
{
|
||||||
// Draw the space as a box outline. We also draw it 50% wider than it really is.
|
// Draw the space as a box outline. We also draw it 50% wider than it really is.
|
||||||
const int x1 = xx + cell_width/2 - width * CleanXfac * 3 / 4;
|
const int x1 = xx + cell_width/2 - width * CleanXfac_1 * 3 / 4;
|
||||||
const int x2 = x1 + width * 3 * CleanXfac / 2;
|
const int x2 = x1 + width * 3 * CleanXfac_1 / 2;
|
||||||
const int y1 = yy + top_padding;
|
const int y1 = yy + top_padding;
|
||||||
const int y2 = y1 + SmallFont->GetHeight() * CleanYfac;
|
const int y2 = y1 + displayFont->GetHeight() * CleanYfac_1;
|
||||||
auto palcolor = PalEntry(255, 160, 160, 160);
|
auto palcolor = PalEntry(255, 160, 160, 160);
|
||||||
twod.AddColorOnlyQuad(x1, y1, x2, y1+CleanYfac, palcolor); // top
|
twod.AddColorOnlyQuad(x1, y1, x2 - x1, CleanYfac_1, palcolor); // top
|
||||||
twod.AddColorOnlyQuad(x1, y2, x2, y2+CleanYfac, palcolor); // bottom
|
twod.AddColorOnlyQuad(x1, y2, x2 - x1, CleanYfac_1, palcolor); // bottom
|
||||||
twod.AddColorOnlyQuad(x1, y1+CleanYfac, x1+CleanXfac, y2, palcolor); // left
|
twod.AddColorOnlyQuad(x1, y1+CleanYfac_1, CleanXfac_1, y2 - y1, palcolor); // left
|
||||||
twod.AddColorOnlyQuad(x2-CleanXfac, y1+CleanYfac, x2, y2, palcolor); // right
|
twod.AddColorOnlyQuad(x2-CleanXfac_1, y1+CleanYfac_1, CleanXfac_1, CleanYfac_1, palcolor); // right
|
||||||
}
|
}
|
||||||
else if (ch == '\b' || ch == 0)
|
else if (ch == '\b' || ch == 0)
|
||||||
{
|
{
|
||||||
// Draw the backspace and end "characters".
|
// Draw the backspace and end "characters".
|
||||||
const char *const str = ch == '\b' ? "BS" : "ED";
|
const char *const str = ch == '\b' ? "BS" : "ED";
|
||||||
DrawText(&twod, SmallFont, color,
|
DrawText(&twod, NewSmallFont, color,
|
||||||
xx + cell_width/2 - SmallFont->StringWidth(str)*CleanXfac/2,
|
xx + cell_width/2 - displayFont->StringWidth(str)*CleanXfac_1/2,
|
||||||
yy + top_padding, str, DTA_CleanNoMove, true, TAG_DONE);
|
yy + top_padding, str, DTA_CleanNoMove_1, true, TAG_DONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
507
source/common/menu/savegamemanager.cpp
Normal file
507
source/common/menu/savegamemanager.cpp
Normal file
|
@ -0,0 +1,507 @@
|
||||||
|
/*
|
||||||
|
** loadsavemenu.cpp
|
||||||
|
** The load game and save game menus
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2001-2010 Randy Heit
|
||||||
|
** Copyright 2010 Christoph Oelckers
|
||||||
|
** All rights reserved.
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions
|
||||||
|
** are met:
|
||||||
|
**
|
||||||
|
** 1. Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** 3. The name of the author may not be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "menu/menu.h"
|
||||||
|
#include "version.h"
|
||||||
|
#include "m_png.h"
|
||||||
|
#include "filesystem.h"
|
||||||
|
#include "v_text.h"
|
||||||
|
#include "d_event.h"
|
||||||
|
#include "gstrings.h"
|
||||||
|
#include "d_gui.h"
|
||||||
|
#include "v_draw.h"
|
||||||
|
#include "files.h"
|
||||||
|
#include "resourcefile.h"
|
||||||
|
#include "sjson.h"
|
||||||
|
#include "cmdlib.h"
|
||||||
|
#include "files.h"
|
||||||
|
#include "savegamehelp.h"
|
||||||
|
#include "i_specialpaths.h"
|
||||||
|
#include "../../platform/win32/i_findfile.h" // This is a temporary direct path. Needs to be fixed when stuff gets cleaned up.
|
||||||
|
|
||||||
|
|
||||||
|
FSavegameManager savegameManager;
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// Save data maintenance
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void FSavegameManager::ClearSaveGames()
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i<SaveGames.Size(); i++)
|
||||||
|
{
|
||||||
|
if (!SaveGames[i]->bNoDelete)
|
||||||
|
delete SaveGames[i];
|
||||||
|
}
|
||||||
|
SaveGames.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
FSavegameManager::~FSavegameManager()
|
||||||
|
{
|
||||||
|
ClearSaveGames();
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// Save data maintenance
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
int FSavegameManager::RemoveSaveSlot(int index)
|
||||||
|
{
|
||||||
|
int listindex = SaveGames[0]->bNoDelete ? index - 1 : index;
|
||||||
|
if (listindex < 0) return index;
|
||||||
|
|
||||||
|
remove(SaveGames[index]->Filename.GetChars());
|
||||||
|
UnloadSaveData();
|
||||||
|
|
||||||
|
FSaveGameNode *file = SaveGames[index];
|
||||||
|
|
||||||
|
if (quickSaveSlot == SaveGames[index])
|
||||||
|
{
|
||||||
|
quickSaveSlot = nullptr;
|
||||||
|
}
|
||||||
|
if (!file->bNoDelete) delete file;
|
||||||
|
|
||||||
|
if (LastSaved == listindex) LastSaved = -1;
|
||||||
|
else if (LastSaved > listindex) LastSaved--;
|
||||||
|
if (LastAccessed == listindex) LastAccessed = -1;
|
||||||
|
else if (LastAccessed > listindex) LastAccessed--;
|
||||||
|
|
||||||
|
SaveGames.Delete(index);
|
||||||
|
if ((unsigned)index >= SaveGames.Size()) index--;
|
||||||
|
ExtractSaveData(index);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
int FSavegameManager::InsertSaveNode(FSaveGameNode *node)
|
||||||
|
{
|
||||||
|
if (SaveGames.Size() == 0)
|
||||||
|
{
|
||||||
|
return SaveGames.Push(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->bOldVersion)
|
||||||
|
{ // Add node at bottom of list
|
||||||
|
return SaveGames.Push(node);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Add node at top of list
|
||||||
|
unsigned int i;
|
||||||
|
for (i = 0; i < SaveGames.Size(); i++)
|
||||||
|
{
|
||||||
|
if (SaveGames[i]->bOldVersion || node->SaveTitle.CompareNoCase(SaveGames[i]->SaveTitle) <= 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SaveGames.Insert(i, node);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// M_ReadSaveStrings
|
||||||
|
//
|
||||||
|
// Find savegames and read their titles
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void FSavegameManager::ReadSaveStrings()
|
||||||
|
{
|
||||||
|
if (SaveGames.Size() == 0)
|
||||||
|
{
|
||||||
|
void *filefirst;
|
||||||
|
findstate_t c_file;
|
||||||
|
FString filter;
|
||||||
|
|
||||||
|
LastSaved = LastAccessed = -1;
|
||||||
|
quickSaveSlot = nullptr;
|
||||||
|
filter = G_BuildSaveName("*");
|
||||||
|
filefirst = I_FindFirst(filter.GetChars(), &c_file);
|
||||||
|
if (filefirst != ((void *)(-1)))
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// I_FindName only returns the file's name and not its full path
|
||||||
|
FString filepath = G_BuildSaveName(I_FindName(&c_file));
|
||||||
|
|
||||||
|
FResourceFile *savegame = FResourceFile::OpenResourceFile(filepath, true, true);
|
||||||
|
if (savegame != nullptr)
|
||||||
|
{
|
||||||
|
FResourceLump *info = savegame->FindLump("info.json");
|
||||||
|
if (info == nullptr)
|
||||||
|
{
|
||||||
|
// savegame info not found. This is not a savegame so leave it alone.
|
||||||
|
delete savegame;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto fr = info->NewReader();
|
||||||
|
FString title;
|
||||||
|
int check = G_ValidateSavegame(fr, &title);
|
||||||
|
delete savegame;
|
||||||
|
if (check != 0)
|
||||||
|
{
|
||||||
|
FSaveGameNode *node = new FSaveGameNode;
|
||||||
|
node->Filename = filepath;
|
||||||
|
node->bOldVersion = true;
|
||||||
|
node->bMissingWads = false;
|
||||||
|
node->SaveTitle = title;
|
||||||
|
InsertSaveNode(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (I_FindNext (filefirst, &c_file) == 0);
|
||||||
|
I_FindClose (filefirst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void FSavegameManager::NotifyNewSave(const FString &file, const FString &title, bool okForQuicksave, bool forceQuicksave)
|
||||||
|
{
|
||||||
|
FSaveGameNode *node;
|
||||||
|
|
||||||
|
if (file.IsEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ReadSaveStrings();
|
||||||
|
|
||||||
|
// See if the file is already in our list
|
||||||
|
for (unsigned i = 0; i<SaveGames.Size(); i++)
|
||||||
|
{
|
||||||
|
FSaveGameNode *node = SaveGames[i];
|
||||||
|
#ifdef __unix__
|
||||||
|
if (node->Filename.Compare(file) == 0)
|
||||||
|
#else
|
||||||
|
if (node->Filename.CompareNoCase(file) == 0)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
node->SaveTitle = title;
|
||||||
|
node->bOldVersion = false;
|
||||||
|
node->bMissingWads = false;
|
||||||
|
if (okForQuicksave)
|
||||||
|
{
|
||||||
|
if (quickSaveSlot == nullptr || quickSaveSlot == (FSaveGameNode*)1 || forceQuicksave) quickSaveSlot = node;
|
||||||
|
LastAccessed = LastSaved = i;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node = new FSaveGameNode;
|
||||||
|
node->SaveTitle = title;
|
||||||
|
node->Filename = file;
|
||||||
|
node->bOldVersion = false;
|
||||||
|
node->bMissingWads = false;
|
||||||
|
int index = InsertSaveNode(node);
|
||||||
|
|
||||||
|
if (okForQuicksave)
|
||||||
|
{
|
||||||
|
if (quickSaveSlot == nullptr || quickSaveSlot == (FSaveGameNode*)1 || forceQuicksave) quickSaveSlot = node;
|
||||||
|
LastAccessed = LastSaved = index;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LastAccessed = ++LastSaved;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// Loads the savegame
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void FSavegameManager::LoadSavegame(int Selected)
|
||||||
|
{
|
||||||
|
//G_LoadGame(SaveGames[Selected]->Filename.GetChars(), true);
|
||||||
|
if (quickSaveSlot == (FSaveGameNode*)1)
|
||||||
|
{
|
||||||
|
quickSaveSlot = SaveGames[Selected];
|
||||||
|
}
|
||||||
|
M_ClearMenus();
|
||||||
|
LastAccessed = Selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void FSavegameManager::DoSave(int Selected, const char *savegamestring)
|
||||||
|
{
|
||||||
|
if (Selected != 0)
|
||||||
|
{
|
||||||
|
auto node = SaveGames[Selected];
|
||||||
|
//G_SaveGame(node->Filename.GetChars(), savegamestring);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Find an unused filename and save as that
|
||||||
|
FString filename;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0;; ++i)
|
||||||
|
{
|
||||||
|
filename = G_BuildSaveName(FStringf("save%04d", i));
|
||||||
|
if (!FileExists(filename))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//G_SaveGame(filename, savegamestring);
|
||||||
|
}
|
||||||
|
M_ClearMenus();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
unsigned FSavegameManager::ExtractSaveData(int index)
|
||||||
|
{
|
||||||
|
FResourceFile *resf;
|
||||||
|
FSaveGameNode *node;
|
||||||
|
|
||||||
|
if (index == -1)
|
||||||
|
{
|
||||||
|
if (SaveGames.Size() > 0 && SaveGames[0]->bNoDelete)
|
||||||
|
{
|
||||||
|
index = LastSaved + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index = LastAccessed < 0? 0 : LastAccessed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UnloadSaveData();
|
||||||
|
|
||||||
|
if ((unsigned)index < SaveGames.Size() &&
|
||||||
|
(node = SaveGames[index]) &&
|
||||||
|
!node->Filename.IsEmpty() &&
|
||||||
|
!node->bOldVersion &&
|
||||||
|
(resf = FResourceFile::OpenResourceFile(node->Filename.GetChars(), true)) != nullptr)
|
||||||
|
{
|
||||||
|
FResourceLump *info = resf->FindLump("info.json");
|
||||||
|
if (info == nullptr)
|
||||||
|
{
|
||||||
|
// this should not happen because the file has already been verified.
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
auto fr = info->NewReader();
|
||||||
|
auto data = fr.ReadPadded(1);
|
||||||
|
sjson_context* ctx = sjson_create_context(0, 0, NULL);
|
||||||
|
if (ctx)
|
||||||
|
{
|
||||||
|
sjson_node* root = sjson_decode(ctx, (const char*)data.Data());
|
||||||
|
|
||||||
|
|
||||||
|
FString comment = sjson_get_string(root, "Creation Time", "");
|
||||||
|
FString pcomment = sjson_get_string(root, "Comment", "");
|
||||||
|
if (comment.Len() > 0) comment += "\n";
|
||||||
|
comment += pcomment;
|
||||||
|
SaveCommentString = comment;
|
||||||
|
|
||||||
|
// Extract pic (todo: let the renderer write a proper PNG file instead of a raw canvas dunp of the software renderer - and make it work for all games.)
|
||||||
|
FResourceLump *pic = resf->FindLump("savepic.png");
|
||||||
|
if (pic != nullptr)
|
||||||
|
{
|
||||||
|
FileReader picreader;
|
||||||
|
|
||||||
|
picreader.OpenMemoryArray([=](TArray<uint8_t> &array)
|
||||||
|
{
|
||||||
|
auto cache = pic->Lock();
|
||||||
|
array.Resize(pic->LumpSize);
|
||||||
|
memcpy(&array[0], cache, pic->LumpSize);
|
||||||
|
pic->Unlock();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
PNGHandle *png = M_VerifyPNG(picreader);
|
||||||
|
if (png != nullptr)
|
||||||
|
{
|
||||||
|
SavePic = nullptr; // not yet implemented: PNGTexture_CreateFromFile(png, node->Filename);
|
||||||
|
delete png;
|
||||||
|
if (SavePic && SavePic->GetWidth() == 1 && SavePic->GetHeight() == 1)
|
||||||
|
{
|
||||||
|
delete SavePic;
|
||||||
|
SavePic = nullptr;
|
||||||
|
SavePicData.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete resf;
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void FSavegameManager::UnloadSaveData()
|
||||||
|
{
|
||||||
|
if (SavePic != nullptr)
|
||||||
|
{
|
||||||
|
delete SavePic;
|
||||||
|
}
|
||||||
|
|
||||||
|
SaveCommentString = "";
|
||||||
|
SavePic = nullptr;
|
||||||
|
SavePicData.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void FSavegameManager::ClearSaveStuff()
|
||||||
|
{
|
||||||
|
UnloadSaveData();
|
||||||
|
if (quickSaveSlot == (FSaveGameNode*)1)
|
||||||
|
{
|
||||||
|
quickSaveSlot = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
bool FSavegameManager::DrawSavePic(int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
if (SavePic == nullptr) return false;
|
||||||
|
DrawTexture(&twod, SavePic, x, y, DTA_DestWidth, w, DTA_DestHeight, h, DTA_Masked, false, TAG_DONE);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void FSavegameManager::SetFileInfo(int Selected)
|
||||||
|
{
|
||||||
|
if (!SaveGames[Selected]->Filename.IsEmpty())
|
||||||
|
{
|
||||||
|
SaveCommentString.Format("File on disk:\n%s", SaveGames[Selected]->Filename.GetChars());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
unsigned FSavegameManager::SavegameCount()
|
||||||
|
{
|
||||||
|
return SaveGames.Size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
FSaveGameNode *FSavegameManager::GetSavegame(int i)
|
||||||
|
{
|
||||||
|
return SaveGames[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void FSavegameManager::InsertNewSaveNode()
|
||||||
|
{
|
||||||
|
NewSaveNode.SaveTitle = GStrings["NEWSAVE"];
|
||||||
|
NewSaveNode.bNoDelete = true;
|
||||||
|
SaveGames.Insert(0, &NewSaveNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
bool FSavegameManager::RemoveNewSaveNode()
|
||||||
|
{
|
||||||
|
if (SaveGames[0] == &NewSaveNode)
|
||||||
|
{
|
||||||
|
SaveGames.Delete(0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -20,8 +20,8 @@ xx(MainMenu)
|
||||||
xx(IngameMenu)
|
xx(IngameMenu)
|
||||||
xx(HelpMenu)
|
xx(HelpMenu)
|
||||||
xx(CreditsMenu)
|
xx(CreditsMenu)
|
||||||
xx(SaveMenu)
|
xx(SaveGameMenu)
|
||||||
xx(LoadMenu)
|
xx(LoadGameMenu)
|
||||||
xx(SoundMenu)
|
xx(SoundMenu)
|
||||||
xx(ConfirmPlayerReset)
|
xx(ConfirmPlayerReset)
|
||||||
xx(EpisodeMenu)
|
xx(EpisodeMenu)
|
||||||
|
|
Loading…
Reference in a new issue