- reintegrate savegame menu changes back into trunk

SVN r2816 (trunk)
This commit is contained in:
Christoph Oelckers 2010-09-17 22:48:55 +00:00
parent 46b3bb8e41
commit eeab5ba0e4
2 changed files with 246 additions and 334 deletions

View file

@ -56,46 +56,66 @@ class DLoadSaveMenu : public DListMenu
DECLARE_CLASS(DLoadSaveMenu, DListMenu) DECLARE_CLASS(DLoadSaveMenu, DListMenu)
protected: protected:
static List SaveGames; static TDeletingArray<FSaveGameNode*> SaveGames;
static FSaveGameNode *TopSaveGame; static int LastSaved;
static FSaveGameNode *lastSaveSlot;
static FSaveGameNode *SelSaveGame; int Selected;
int TopItem;
friend void M_NotifyNewSave (const char *file, const char *title, bool okForQuicksave); int savepicLeft;
int savepicTop;
int savepicWidth;
int savepicHeight;
static FSaveGameNode *RemoveSaveSlot (FSaveGameNode *file); int rowHeight;
static void UnloadSaveStrings(); int listboxLeft;
static void InsertSaveNode (FSaveGameNode *node); int listboxTop;
int listboxWidth;
int listboxRows;
int listboxHeight;
int listboxRight;
int listboxBottom;
int commentLeft;
int commentTop;
int commentWidth;
int commentHeight;
int commentRight;
int commentBottom;
static int InsertSaveNode (FSaveGameNode *node);
static void ReadSaveStrings (); static void ReadSaveStrings ();
static void NotifyNewSave (const char *file, const char *title, bool okForQuicksave);
FTexture *SavePic; FTexture *SavePic;
FBrokenLines *SaveComment; FBrokenLines *SaveComment;
bool mEntering; bool mEntering;
char savegamestring[SAVESTRINGSIZE]; char savegamestring[SAVESTRINGSIZE];
bool mWheelScrolled;
DLoadSaveMenu(DMenu *parent = NULL, FListMenuDescriptor *desc = NULL); DLoadSaveMenu(DMenu *parent = NULL, FListMenuDescriptor *desc = NULL);
void Destroy(); void Destroy();
int RemoveSaveSlot (int index);
void UnloadSaveData (); void UnloadSaveData ();
void ClearSaveStuff (); void ClearSaveStuff ();
void ExtractSaveData (const FSaveGameNode *node); void ExtractSaveData (int index);
void Drawer (); void Drawer ();
bool MenuEvent (int mkey, bool fromcontroller); bool MenuEvent (int mkey, bool fromcontroller);
bool MouseEvent(int type, int x, int y); bool MouseEvent(int type, int x, int y);
bool Responder(event_t *ev); bool Responder(event_t *ev);
public:
static void NotifyNewSave (const char *file, const char *title, bool okForQuicksave);
}; };
IMPLEMENT_CLASS(DLoadSaveMenu) IMPLEMENT_CLASS(DLoadSaveMenu)
List DLoadSaveMenu::SaveGames; TDeletingArray<FSaveGameNode*> DLoadSaveMenu::SaveGames;
FSaveGameNode *DLoadSaveMenu::TopSaveGame; int DLoadSaveMenu::LastSaved = -1;
FSaveGameNode *DLoadSaveMenu::lastSaveSlot;
FSaveGameNode *DLoadSaveMenu::SelSaveGame;
FSaveGameNode *quickSaveSlot; FSaveGameNode *quickSaveSlot;
@ -105,78 +125,54 @@ FSaveGameNode *quickSaveSlot;
// //
//============================================================================= //=============================================================================
FSaveGameNode *DLoadSaveMenu::RemoveSaveSlot (FSaveGameNode *file) int DLoadSaveMenu::RemoveSaveSlot (int index)
{ {
FSaveGameNode *next = static_cast<FSaveGameNode *>(file->Succ); FSaveGameNode *file = SaveGames[index];
if (file == TopSaveGame) if (quickSaveSlot == SaveGames[index])
{
TopSaveGame = next;
}
if (quickSaveSlot == file)
{ {
quickSaveSlot = NULL; quickSaveSlot = NULL;
} }
if (lastSaveSlot == file) if (Selected == index)
{ {
lastSaveSlot = NULL; Selected = -1;
} }
file->Remove ();
if (!file->bNoDelete) delete file; if (!file->bNoDelete) delete file;
return next; SaveGames.Delete(index);
if ((unsigned)index >= SaveGames.Size()) index--;
return index;
} }
//============================================================================= //=============================================================================
// //
// //
// //
//============================================================================= //=============================================================================
void DLoadSaveMenu::UnloadSaveStrings() int DLoadSaveMenu::InsertSaveNode (FSaveGameNode *node)
{ {
while (!SaveGames.IsEmpty()) if (SaveGames.Size() == 0)
{ {
RemoveSaveSlot (static_cast<FSaveGameNode *>(SaveGames.Head)); return SaveGames.Push(node);
}
}
//=============================================================================
//
//
//
//=============================================================================
void DLoadSaveMenu::InsertSaveNode (FSaveGameNode *node)
{
FSaveGameNode *probe;
if (SaveGames.IsEmpty ())
{
SaveGames.AddHead (node);
return;
} }
if (node->bOldVersion) if (node->bOldVersion)
{ // Add node at bottom of list { // Add node at bottom of list
probe = static_cast<FSaveGameNode *>(SaveGames.TailPred); return SaveGames.Push(node);
while (probe->Pred != NULL && probe->bOldVersion &&
stricmp (node->Title, probe->Title) < 0)
{
probe = static_cast<FSaveGameNode *>(probe->Pred);
}
node->Insert (probe);
} }
else else
{ // Add node at top of list { // Add node at top of list
probe = static_cast<FSaveGameNode *>(SaveGames.Head); unsigned int i;
while (probe->Succ != NULL && !probe->bOldVersion && for(i = 0; i < SaveGames.Size(); i++)
stricmp (node->Title, probe->Title) > 0)
{ {
probe = static_cast<FSaveGameNode *>(probe->Succ); if (SaveGames[i]->bOldVersion ||
stricmp (node->Title, SaveGames[i]->Title) <= 0)
{
break;
}
} }
node->InsertBefore (probe); SaveGames.Insert(i, node);
return i;
} }
} }
@ -191,14 +187,12 @@ void DLoadSaveMenu::InsertSaveNode (FSaveGameNode *node)
void DLoadSaveMenu::ReadSaveStrings () void DLoadSaveMenu::ReadSaveStrings ()
{ {
if (SaveGames.IsEmpty ()) if (SaveGames.Size() == 0)
{ {
void *filefirst; void *filefirst;
findstate_t c_file; findstate_t c_file;
FString filter; FString filter;
atterm (UnloadSaveStrings);
filter = G_BuildSaveName ("*.zds", -1); filter = G_BuildSaveName ("*.zds", -1);
filefirst = I_FindFirst (filter.GetChars(), &c_file); filefirst = I_FindFirst (filter.GetChars(), &c_file);
if (filefirst != ((void *)(-1))) if (filefirst != ((void *)(-1)))
@ -309,10 +303,6 @@ void DLoadSaveMenu::ReadSaveStrings ()
I_FindClose (filefirst); I_FindClose (filefirst);
} }
} }
if (SelSaveGame == NULL || SelSaveGame->Succ == NULL)
{
SelSaveGame = static_cast<FSaveGameNode *>(SaveGames.Head);
}
} }
@ -332,10 +322,9 @@ void DLoadSaveMenu::NotifyNewSave (const char *file, const char *title, bool okF
ReadSaveStrings (); ReadSaveStrings ();
// See if the file is already in our list // See if the file is already in our list
for (node = static_cast<FSaveGameNode *>(SaveGames.Head); for (unsigned i=0; i<SaveGames.Size(); i++)
node->Succ != NULL;
node = static_cast<FSaveGameNode *>(node->Succ))
{ {
FSaveGameNode *node = SaveGames[i];
#ifdef unix #ifdef unix
if (node->Filename.Compare (file) == 0) if (node->Filename.Compare (file) == 0)
#else #else
@ -345,25 +334,26 @@ void DLoadSaveMenu::NotifyNewSave (const char *file, const char *title, bool okF
strcpy (node->Title, title); strcpy (node->Title, title);
node->bOldVersion = false; node->bOldVersion = false;
node->bMissingWads = false; node->bMissingWads = false;
break; if (okForQuicksave)
{
if (quickSaveSlot == NULL) quickSaveSlot = node;
LastSaved = i;
}
return;
} }
} }
if (node->Succ == NULL) node = new FSaveGameNode;
{ strcpy (node->Title, title);
node = new FSaveGameNode; node->Filename = file;
strcpy (node->Title, title); node->bOldVersion = false;
node->Filename = file; node->bMissingWads = false;
node->bOldVersion = false; int index = InsertSaveNode (node);
node->bMissingWads = false;
InsertSaveNode (node);
SelSaveGame = node;
}
if (okForQuicksave) if (okForQuicksave)
{ {
if (quickSaveSlot == NULL) quickSaveSlot = node; if (quickSaveSlot == NULL) quickSaveSlot = node;
lastSaveSlot = node; LastSaved = index;
} }
} }
@ -382,7 +372,28 @@ DLoadSaveMenu::DLoadSaveMenu(DMenu *parent, FListMenuDescriptor *desc)
: DListMenu(parent, desc) : DListMenu(parent, desc)
{ {
ReadSaveStrings(); ReadSaveStrings();
mWheelScrolled = false;
savepicLeft = 10;
savepicTop = 54*CleanYfac;
savepicWidth = 216*screen->GetWidth()/640;
savepicHeight = 135*screen->GetHeight()/400;
rowHeight = (SmallFont->GetHeight() + 1) * CleanYfac;
listboxLeft = savepicLeft + savepicWidth + 14;
listboxTop = savepicTop;
listboxWidth = screen->GetWidth() - listboxLeft - 10;
int listboxHeight1 = screen->GetHeight() - listboxTop - 10;
listboxRows = (listboxHeight1 - 1) / rowHeight;
listboxHeight = listboxRows * rowHeight + 1;
listboxRight = listboxLeft + listboxWidth;
listboxBottom = listboxTop + listboxHeight;
commentLeft = savepicLeft;
commentTop = savepicTop + savepicHeight + 16;
commentWidth = savepicWidth;
commentHeight = (51+(screen->GetHeight()>200?10:0))*CleanYfac;
commentRight = commentLeft + commentWidth;
commentBottom = commentTop + commentHeight;
} }
void DLoadSaveMenu::Destroy() void DLoadSaveMenu::Destroy()
@ -420,7 +431,7 @@ void DLoadSaveMenu::UnloadSaveData ()
void DLoadSaveMenu::ClearSaveStuff () void DLoadSaveMenu::ClearSaveStuff ()
{ {
UnloadSaveData(); UnloadSaveData();
if (quickSaveSlot == (FSaveGameNode *)1) if (quickSaveSlot == (FSaveGameNode*)1)
{ {
quickSaveSlot = NULL; quickSaveSlot = NULL;
} }
@ -432,15 +443,16 @@ void DLoadSaveMenu::ClearSaveStuff ()
// //
//============================================================================= //=============================================================================
void DLoadSaveMenu::ExtractSaveData (const FSaveGameNode *node) void DLoadSaveMenu::ExtractSaveData (int index)
{ {
FILE *file; FILE *file;
PNGHandle *png; PNGHandle *png;
FSaveGameNode *node;
UnloadSaveData (); UnloadSaveData ();
if (node != NULL && if ((unsigned)index < SaveGames.Size() &&
node->Succ != NULL && (node = SaveGames[index]) &&
!node->Filename.IsEmpty() && !node->Filename.IsEmpty() &&
!node->bOldVersion && !node->bOldVersion &&
(file = fopen (node->Filename.GetChars(), "rb")) != NULL) (file = fopen (node->Filename.GetChars(), "rb")) != NULL)
@ -512,30 +524,9 @@ void DLoadSaveMenu::Drawer ()
{ {
Super::Drawer(); Super::Drawer();
const int savepicLeft = 10;
const int savepicTop = 54*CleanYfac;
const int savepicWidth = 216*screen->GetWidth()/640;
const int savepicHeight = 135*screen->GetHeight()/400;
const int rowHeight = (SmallFont->GetHeight() + 1) * CleanYfac;
const int listboxLeft = savepicLeft + savepicWidth + 14;
const int listboxTop = savepicTop;
const int listboxWidth = screen->GetWidth() - listboxLeft - 10;
const int listboxHeight1 = screen->GetHeight() - listboxTop - 10;
const int listboxRows = (listboxHeight1 - 1) / rowHeight;
const int listboxHeight = listboxRows * rowHeight + 1;
const int listboxRight = listboxLeft + listboxWidth;
const int listboxBottom = listboxTop + listboxHeight;
const int commentLeft = savepicLeft;
const int commentTop = savepicTop + savepicHeight + 16;
const int commentWidth = savepicWidth;
const int commentHeight = (51+(screen->GetHeight()>200?10:0))*CleanYfac;
const int commentRight = commentLeft + commentWidth;
const int commentBottom = commentTop + commentHeight;
FSaveGameNode *node; FSaveGameNode *node;
int i; int i;
unsigned j;
bool didSeeSelected = false; bool didSeeSelected = false;
// Draw picture area // Draw picture area
@ -558,10 +549,10 @@ void DLoadSaveMenu::Drawer ()
screen->Clear (savepicLeft, savepicTop, screen->Clear (savepicLeft, savepicTop,
savepicLeft+savepicWidth, savepicTop+savepicHeight, 0, 0); savepicLeft+savepicWidth, savepicTop+savepicHeight, 0, 0);
if (!SaveGames.IsEmpty ()) if (SaveGames.Size() > 0)
{ {
const char *text = const char *text =
(SelSaveGame == NULL || !SelSaveGame->bOldVersion) (Selected == -1 || SaveGames[Selected]->bOldVersion)
? GStrings("MNU_NOPICTURE") : GStrings("MNU_DIFFVERSION"); ? GStrings("MNU_NOPICTURE") : GStrings("MNU_DIFFVERSION");
const int textlen = SmallFont->StringWidth (text)*CleanXfac; const int textlen = SmallFont->StringWidth (text)*CleanXfac;
@ -588,110 +579,73 @@ void DLoadSaveMenu::Drawer ()
} }
// Draw file area // Draw file area
do V_DrawFrame (listboxLeft, listboxTop, listboxWidth, listboxHeight);
screen->Clear (listboxLeft, listboxTop, listboxRight, listboxBottom, 0, 0);
if (SaveGames.Size() == 0)
{ {
V_DrawFrame (listboxLeft, listboxTop, listboxWidth, listboxHeight); const char * text = GStrings("MNU_NOFILES");
screen->Clear (listboxLeft, listboxTop, listboxRight, listboxBottom, 0, 0); const int textlen = SmallFont->StringWidth (text)*CleanXfac;
if (SaveGames.IsEmpty ()) screen->DrawText (SmallFont, CR_GOLD, listboxLeft+(listboxWidth-textlen)/2,
listboxTop+(listboxHeight-rowHeight)/2, text,
DTA_CleanNoMove, true, TAG_DONE);
return;
}
for (i = 0, j = TopItem; i < listboxRows && j < SaveGames.Size(); i++,j++)
{
int color;
node = SaveGames[j];
if (node->bOldVersion)
{ {
const char * text = GStrings("MNU_NOFILES"); color = CR_BLUE;
const int textlen = SmallFont->StringWidth (text)*CleanXfac;
screen->DrawText (SmallFont, CR_GOLD, listboxLeft+(listboxWidth-textlen)/2,
listboxTop+(listboxHeight-rowHeight)/2, text,
DTA_CleanNoMove, true, TAG_DONE);
return;
} }
else if (node->bMissingWads)
for (i = 0, node = TopSaveGame;
i < listboxRows && node->Succ != NULL;
++i, node = static_cast<FSaveGameNode *>(node->Succ))
{ {
int color; color = CR_ORANGE;
if (node->bOldVersion) }
{ else if (j == Selected)
color = CR_BLUE; {
} color = CR_WHITE;
else if (node->bMissingWads) }
{ else
color = CR_ORANGE; {
} color = CR_TAN;
else if (node == SelSaveGame) }
{ if (j == Selected)
color = CR_WHITE; {
} screen->Clear (listboxLeft, listboxTop+rowHeight*i,
else listboxRight, listboxTop+rowHeight*(i+1), -1,
{ mEntering ? MAKEARGB(255,255,0,0) : MAKEARGB(255,0,0,255));
color = CR_TAN; didSeeSelected = true;
} if (!mEntering)
if (node == SelSaveGame)
{
screen->Clear (listboxLeft, listboxTop+rowHeight*i,
listboxRight, listboxTop+rowHeight*(i+1), -1,
mEntering ? MAKEARGB(255,255,0,0) : MAKEARGB(255,0,0,255));
didSeeSelected = true;
if (!mEntering)
{
screen->DrawText (SmallFont, color,
listboxLeft+1, listboxTop+rowHeight*i+CleanYfac, node->Title,
DTA_CleanNoMove, true, TAG_DONE);
}
else
{
screen->DrawText (SmallFont, CR_WHITE,
listboxLeft+1, listboxTop+rowHeight*i+CleanYfac, savegamestring,
DTA_CleanNoMove, true, TAG_DONE);
screen->DrawText (SmallFont, CR_WHITE,
listboxLeft+1+SmallFont->StringWidth (savegamestring)*CleanXfac,
listboxTop+rowHeight*i+CleanYfac,
(gameinfo.gametype & (GAME_DoomStrifeChex)) ? "_" : "[",
DTA_CleanNoMove, true, TAG_DONE);
}
}
else
{ {
screen->DrawText (SmallFont, color, screen->DrawText (SmallFont, color,
listboxLeft+1, listboxTop+rowHeight*i+CleanYfac, node->Title, listboxLeft+1, listboxTop+rowHeight*i+CleanYfac, node->Title,
DTA_CleanNoMove, true, TAG_DONE); DTA_CleanNoMove, true, TAG_DONE);
} }
}
// This is dumb: If the selected node was not visible,
// scroll down and redraw. M_SaveLoadResponder()
// guarantees that if the node is not visible, it will
// always be below the visible list instead of above it.
// This should not really be done here, but I don't care.
if (!didSeeSelected)
{
// no, this shouldn't be here - and that's why there's now another hack in here
// so that the mouse scrolling does not get screwed by this code...
if (mWheelScrolled)
{
didSeeSelected = true;
SelSaveGame = NULL;
mWheelScrolled = false;
}
for (i = 1; node->Succ != NULL && node != SelSaveGame; ++i)
{
node = static_cast<FSaveGameNode *>(node->Succ);
}
if (node->Succ == NULL)
{ // SelSaveGame is invalid
didSeeSelected = true;
}
else else
{ {
do screen->DrawText (SmallFont, CR_WHITE,
{ listboxLeft+1, listboxTop+rowHeight*i+CleanYfac, savegamestring,
TopSaveGame = static_cast<FSaveGameNode *>(TopSaveGame->Succ); DTA_CleanNoMove, true, TAG_DONE);
} while (--i);
screen->DrawText (SmallFont, CR_WHITE,
listboxLeft+1+SmallFont->StringWidth (savegamestring)*CleanXfac,
listboxTop+rowHeight*i+CleanYfac,
(gameinfo.gametype & (GAME_DoomStrifeChex)) ? "_" : "[",
DTA_CleanNoMove, true, TAG_DONE);
} }
} }
} while (!didSeeSelected); else
} {
screen->DrawText (SmallFont, color,
listboxLeft+1, listboxTop+rowHeight*i+CleanYfac, node->Title,
DTA_CleanNoMove, true, TAG_DONE);
}
}
}
//============================================================================= //=============================================================================
// //
@ -704,47 +658,68 @@ bool DLoadSaveMenu::MenuEvent (int mkey, bool fromcontroller)
switch (mkey) switch (mkey)
{ {
case MKEY_Up: case MKEY_Up:
if (SelSaveGame == NULL) if (SaveGames.Size() > 1)
{ {
SelSaveGame = TopSaveGame; if (Selected == -1) Selected = TopItem;
}
else if (SelSaveGame->Succ != NULL)
{
if (SelSaveGame != SaveGames.Head)
{
if (SelSaveGame == TopSaveGame)
{
TopSaveGame = static_cast<FSaveGameNode *>(TopSaveGame->Pred);
}
SelSaveGame = static_cast<FSaveGameNode *>(SelSaveGame->Pred);
}
else else
{ {
SelSaveGame = static_cast<FSaveGameNode *>(SaveGames.TailPred); if (--Selected < 0) Selected = SaveGames.Size()-1;
if (Selected < TopItem) TopItem = Selected;
else if (Selected >= TopItem + listboxRows) TopItem = MAX(0, Selected - listboxRows + 1);
} }
UnloadSaveData (); UnloadSaveData ();
ExtractSaveData (SelSaveGame); ExtractSaveData (Selected);
} }
return true; return true;
case MKEY_Down: case MKEY_Down:
if (SelSaveGame == NULL) if (SaveGames.Size() > 1)
{ {
SelSaveGame = TopSaveGame; if (Selected == -1) Selected = TopItem;
} else
else if (SelSaveGame->Succ != NULL)
{
if (SelSaveGame != SaveGames.TailPred)
{ {
SelSaveGame = static_cast<FSaveGameNode *>(SelSaveGame->Succ); if (unsigned(++Selected) >= SaveGames.Size()) Selected = 0;
if (Selected < TopItem) TopItem = Selected;
else if (Selected >= TopItem + listboxRows) TopItem = MAX(0, Selected - listboxRows + 1);
}
UnloadSaveData ();
ExtractSaveData (Selected);
}
return true;
case MKEY_PageDown:
if (SaveGames.Size() > 1)
{
if (TopItem >= (int)SaveGames.Size() - listboxRows)
{
TopItem = 0;
if (Selected != -1) Selected = 0;
} }
else else
{ {
SelSaveGame = TopSaveGame = TopItem = MIN<int>(TopItem + listboxRows, SaveGames.Size() - listboxRows);
static_cast<FSaveGameNode *>(SaveGames.Head); if (TopItem > Selected && Selected != -1) Selected = TopItem;
} }
UnloadSaveData (); UnloadSaveData ();
ExtractSaveData (SelSaveGame); ExtractSaveData (Selected);
}
return true;
case MKEY_PageUp:
if (SaveGames.Size() > 1)
{
if (TopItem == 0)
{
TopItem = SaveGames.Size() - listboxRows;
if (Selected != -1) Selected = TopItem;
}
else
{
TopItem = MAX(TopItem - listboxRows, 0);
if (Selected >= TopItem + listboxRows) Selected = TopItem;
}
UnloadSaveData ();
ExtractSaveData (Selected);
} }
return true; return true;
@ -753,22 +728,12 @@ bool DLoadSaveMenu::MenuEvent (int mkey, bool fromcontroller)
case MKEY_MBYes: case MKEY_MBYes:
{ {
if (SelSaveGame != NULL && SelSaveGame->Succ != NULL) if (Selected != -1)
{ {
FSaveGameNode *next = static_cast<FSaveGameNode *>(SelSaveGame->Succ); remove (SaveGames[Selected]->Filename.GetChars());
if (next->Succ == NULL)
{
next = static_cast<FSaveGameNode *>(SelSaveGame->Pred);
if (next->Pred == NULL)
{
next = NULL;
}
}
remove (SelSaveGame->Filename.GetChars());
UnloadSaveData (); UnloadSaveData ();
SelSaveGame = RemoveSaveSlot (SelSaveGame); Selected = RemoveSaveSlot (Selected);
ExtractSaveData (SelSaveGame); ExtractSaveData (Selected);
} }
return true; return true;
} }
@ -786,39 +751,16 @@ bool DLoadSaveMenu::MenuEvent (int mkey, bool fromcontroller)
bool DLoadSaveMenu::MouseEvent(int type, int x, int y) bool DLoadSaveMenu::MouseEvent(int type, int x, int y)
{ {
const int savepicLeft = 10;
const int savepicTop = 54*CleanYfac;
const int savepicWidth = 216*screen->GetWidth()/640;
const int rowHeight = (SmallFont->GetHeight() + 1) * CleanYfac;
const int listboxLeft = savepicLeft + savepicWidth + 14;
const int listboxTop = savepicTop;
const int listboxWidth = screen->GetWidth() - listboxLeft - 10;
const int listboxHeight1 = screen->GetHeight() - listboxTop - 10;
const int listboxRows = (listboxHeight1 - 1) / rowHeight;
const int listboxHeight = listboxRows * rowHeight + 1;
const int listboxRight = listboxLeft + listboxWidth;
const int listboxBottom = listboxTop + listboxHeight;
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;
FSaveGameNode *top = TopSaveGame;
while (lineno > 0 && top->Succ != NULL) if (TopItem + lineno < (int)SaveGames.Size())
{ {
lineno--; Selected = TopItem + lineno;
top = (FSaveGameNode *)top->Succ; UnloadSaveData ();
} ExtractSaveData (Selected);
if (lineno == 0)
{
if (SelSaveGame != top)
{
SelSaveGame = top;
UnloadSaveData ();
ExtractSaveData (SelSaveGame);
// Sound?
}
if (type == MOUSE_Release) if (type == MOUSE_Release)
{ {
if (MenuEvent(MKEY_Enter, true)) if (MenuEvent(MKEY_Enter, true))
@ -827,12 +769,10 @@ bool DLoadSaveMenu::MouseEvent(int type, int x, int y)
} }
} }
} }
else SelSaveGame = NULL; else Selected = -1;
}
else
{
SelSaveGame = NULL;
} }
else Selected = -1;
return Super::MouseEvent(type, x, y); return Super::MouseEvent(type, x, y);
} }
@ -848,16 +788,16 @@ bool DLoadSaveMenu::Responder (event_t *ev)
{ {
if (ev->subtype == EV_GUI_KeyDown) if (ev->subtype == EV_GUI_KeyDown)
{ {
if (SelSaveGame != NULL && SelSaveGame->Succ != NULL) if (Selected != -1)
{ {
switch (ev->data1) switch (ev->data1)
{ {
case GK_F1: case GK_F1:
if (!SelSaveGame->Filename.IsEmpty()) if (!SaveGames[Selected]->Filename.IsEmpty())
{ {
char workbuf[512]; char workbuf[512];
mysnprintf (workbuf, countof(workbuf), "File on disk:\n%s", SelSaveGame->Filename.GetChars()); mysnprintf (workbuf, countof(workbuf), "File on disk:\n%s", SaveGames[Selected]->Filename.GetChars());
if (SaveComment != NULL) if (SaveComment != NULL)
{ {
V_FreeBrokenLines (SaveComment); V_FreeBrokenLines (SaveComment);
@ -871,7 +811,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"), SelSaveGame->Title, GStrings("PRESSYN")); GStrings("MNU_DELETESG"), SaveGames[Selected]->Title, GStrings("PRESSYN"));
M_StartMessage (EndString, 0); M_StartMessage (EndString, 0);
} }
return true; return true;
@ -880,36 +820,13 @@ bool DLoadSaveMenu::Responder (event_t *ev)
} }
else if (ev->subtype == EV_GUI_WheelUp) else if (ev->subtype == EV_GUI_WheelUp)
{ {
if (TopSaveGame != SaveGames.Head && TopSaveGame != NULL) if (TopItem > 0) TopItem--;
{
TopSaveGame = static_cast<FSaveGameNode *>(TopSaveGame->Pred);
mWheelScrolled = true;
}
return true; return true;
} }
else if (ev->subtype == EV_GUI_WheelDown) else if (ev->subtype == EV_GUI_WheelDown)
{ {
const int savepicTop = 54*CleanYfac; if (TopItem < (int)SaveGames.Size() - listboxRows) TopItem++;
const int listboxTop = savepicTop; return true;
const int rowHeight = (SmallFont->GetHeight() + 1) * CleanYfac;
const int listboxHeight1 = screen->GetHeight() - listboxTop - 10;
const int listboxRows = (listboxHeight1 - 1) / rowHeight;
FSaveGameNode *node = TopSaveGame;
if (node != NULL)
{
int count = 1;
while (node != NULL && node != SaveGames.TailPred)
{
node = (FSaveGameNode*)node->Succ;
count++;
}
if (count > listboxRows)
{
TopSaveGame = (FSaveGameNode*)TopSaveGame->Succ;
mWheelScrolled = true;
}
}
} }
} }
return Super::Responder(ev); return Super::Responder(ev);
@ -952,17 +869,17 @@ DSaveMenu::DSaveMenu(DMenu *parent, FListMenuDescriptor *desc)
{ {
strcpy (NewSaveNode.Title, "<New Save Game>"); strcpy (NewSaveNode.Title, "<New Save Game>");
NewSaveNode.bNoDelete = true; NewSaveNode.bNoDelete = true;
SaveGames.AddHead (&NewSaveNode); SaveGames.Insert(0, &NewSaveNode);
TopSaveGame = static_cast<FSaveGameNode *>(SaveGames.Head); TopItem = 0;
if (lastSaveSlot == NULL) if (LastSaved == -1)
{ {
SelSaveGame = &NewSaveNode; Selected = 0;
} }
else else
{ {
SelSaveGame = lastSaveSlot; Selected = LastSaved + 1;
} }
ExtractSaveData (SelSaveGame); ExtractSaveData (Selected);
} }
//============================================================================= //=============================================================================
@ -973,17 +890,11 @@ DSaveMenu::DSaveMenu(DMenu *parent, FListMenuDescriptor *desc)
void DSaveMenu::Destroy() void DSaveMenu::Destroy()
{ {
if (SaveGames.Head == &NewSaveNode) if (SaveGames[0] == &NewSaveNode)
{ {
SaveGames.RemHead (); SaveGames.Delete(0);
if (SelSaveGame == &NewSaveNode) if (Selected == 0) Selected = -1;
{ else Selected--;
SelSaveGame = static_cast<FSaveGameNode *>(SaveGames.Head);
}
if (TopSaveGame == &NewSaveNode)
{
TopSaveGame = static_cast<FSaveGameNode *>(SaveGames.Head);
}
} }
} }
@ -1034,16 +945,16 @@ bool DSaveMenu::MenuEvent (int mkey, bool fromcontroller)
{ {
return true; return true;
} }
if (SelSaveGame == NULL || SelSaveGame->Succ == NULL) if (Selected == -1)
{ {
return false; return false;
} }
if (mkey == MKEY_Enter) if (mkey == MKEY_Enter)
{ {
if (SelSaveGame != &NewSaveNode) if (Selected != 0)
{ {
strcpy (savegamestring, SelSaveGame->Title); strcpy (savegamestring, SaveGames[Selected]->Title);
} }
else else
{ {
@ -1056,7 +967,7 @@ bool DSaveMenu::MenuEvent (int mkey, bool fromcontroller)
else if (mkey == MKEY_Input) else if (mkey == MKEY_Input)
{ {
mEntering = false; mEntering = false;
DoSave(SelSaveGame); DoSave(SaveGames[Selected]);
} }
else if (mkey == MKEY_Abort) else if (mkey == MKEY_Abort)
{ {
@ -1075,18 +986,18 @@ bool DSaveMenu::Responder (event_t *ev)
{ {
if (ev->subtype == EV_GUI_KeyDown) if (ev->subtype == EV_GUI_KeyDown)
{ {
if (SelSaveGame != NULL && SelSaveGame->Succ != NULL) if (Selected != -1)
{ {
switch (ev->data1) switch (ev->data1)
{ {
case GK_DEL: case GK_DEL:
case '\b': case '\b':
// cannot delete 'new save game' item // cannot delete 'new save game' item
if (SelSaveGame == &NewSaveNode) return true; if (Selected == 0) return true;
break; break;
case 'N': case 'N':
SelSaveGame = TopSaveGame = &NewSaveNode; Selected = TopItem = 0;
UnloadSaveData (); UnloadSaveData ();
return true; return true;
} }
@ -1124,8 +1035,9 @@ IMPLEMENT_CLASS(DLoadMenu)
DLoadMenu::DLoadMenu(DMenu *parent, FListMenuDescriptor *desc) DLoadMenu::DLoadMenu(DMenu *parent, FListMenuDescriptor *desc)
: DLoadSaveMenu(parent, desc) : DLoadSaveMenu(parent, desc)
{ {
TopSaveGame = static_cast<FSaveGameNode *>(SaveGames.Head); TopItem = 0;
ExtractSaveData (SelSaveGame); ExtractSaveData (Selected);
} }
//============================================================================= //=============================================================================
@ -1140,21 +1052,21 @@ bool DLoadMenu::MenuEvent (int mkey, bool fromcontroller)
{ {
return true; return true;
} }
if (SelSaveGame == NULL || SelSaveGame->Succ == NULL) if (Selected == -1)
{ {
return false; return false;
} }
if (mkey == MKEY_Enter) if (mkey == MKEY_Enter)
{ {
G_LoadGame (SelSaveGame->Filename.GetChars()); G_LoadGame (SaveGames[Selected]->Filename.GetChars());
if (gamestate == GS_FULLCONSOLE) if (gamestate == GS_FULLCONSOLE)
{ {
gamestate = GS_HIDECONSOLE; gamestate = GS_HIDECONSOLE;
} }
if (quickSaveSlot == (FSaveGameNode *)1) if (quickSaveSlot == (FSaveGameNode*)1)
{ {
quickSaveSlot = SelSaveGame; quickSaveSlot = SaveGames[Selected];
} }
M_ClearMenus(); M_ClearMenus();
BorderNeedRefresh = screen->GetPageCount (); BorderNeedRefresh = screen->GetPageCount ();

View file

@ -56,7 +56,7 @@ struct FGameStartup
extern FGameStartup GameStartupInfo; extern FGameStartup GameStartupInfo;
struct FSaveGameNode : public Node struct FSaveGameNode
{ {
char Title[SAVESTRINGSIZE]; char Title[SAVESTRINGSIZE];
FString Filename; FString Filename;