mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-04-28 21:57:57 +03:00
372 lines
9.3 KiB
C++
372 lines
9.3 KiB
C++
/*
|
|
===========================================================================
|
|
Copyright (C) 2023 the OpenMoHAA team
|
|
|
|
This file is part of OpenMoHAA source code.
|
|
|
|
OpenMoHAA source code is free software; you can redistribute it
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the License,
|
|
or (at your option) any later version.
|
|
|
|
OpenMoHAA source code is distributed in the hope that it will be
|
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with OpenMoHAA source code; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
===========================================================================
|
|
*/
|
|
|
|
#include "cl_ui.h"
|
|
#include "../qcommon/localization.h"
|
|
|
|
class FAKKLoadGameItem : public UIListCtrlItem
|
|
{
|
|
str strings[4];
|
|
|
|
public:
|
|
FAKKLoadGameItem(const str& missionName, const str& elapsedTime, const str& dateTime, const str& fileName);
|
|
|
|
int getListItemValue(int which) const override;
|
|
griditemtype_t getListItemType(int which) const override;
|
|
str getListItemString(int which) const override;
|
|
void DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) override;
|
|
qboolean IsHeaderEntry() const override;
|
|
};
|
|
|
|
static UIFAKKLoadGameClass *loadgame_ui = NULL;
|
|
|
|
Event EV_FAKKLoadGame_LoadGame
|
|
(
|
|
"loadgame",
|
|
EV_DEFAULT,
|
|
NULL,
|
|
NULL,
|
|
"Load the currently selected game"
|
|
);
|
|
Event EV_FAKKLoadGame_RemoveGame
|
|
(
|
|
"removegame",
|
|
EV_DEFAULT,
|
|
NULL,
|
|
NULL,
|
|
"Delete the currently selected game"
|
|
);
|
|
Event EV_FAKKLoadGame_DeleteGame
|
|
(
|
|
"deletegame",
|
|
EV_DEFAULT,
|
|
NULL,
|
|
NULL,
|
|
"Delete the currently selected game... for real"
|
|
);
|
|
Event EV_FAKKLoadGame_NoDeleteGame
|
|
(
|
|
"nodeletegame",
|
|
EV_DEFAULT,
|
|
NULL,
|
|
NULL,
|
|
"Delete the currently selected game... for real"
|
|
);
|
|
Event EV_FAKKLoadGame_SaveGame
|
|
(
|
|
"savegame",
|
|
EV_DEFAULT,
|
|
NULL,
|
|
NULL,
|
|
"Save the currently selected game"
|
|
);
|
|
|
|
CLASS_DECLARATION(UIListCtrl, UIFAKKLoadGameClass, NULL) {
|
|
{&EV_UIListBase_ItemSelected, &UIFAKKLoadGameClass::SelectGame },
|
|
{&EV_UIListBase_ItemDoubleClicked, &UIFAKKLoadGameClass::LoadGame },
|
|
{&EV_FAKKLoadGame_RemoveGame, &UIFAKKLoadGameClass::RemoveGame },
|
|
{&EV_FAKKLoadGame_DeleteGame, &UIFAKKLoadGameClass::DeleteGame },
|
|
{&EV_FAKKLoadGame_NoDeleteGame, &UIFAKKLoadGameClass::NoDeleteGame},
|
|
{&EV_FAKKLoadGame_LoadGame, &UIFAKKLoadGameClass::LoadGame },
|
|
{&EV_FAKKLoadGame_SaveGame, &UIFAKKLoadGameClass::SaveGame },
|
|
{NULL, NULL }
|
|
};
|
|
|
|
UIFAKKLoadGameClass::UIFAKKLoadGameClass()
|
|
{
|
|
Connect(this, EV_UIListBase_ItemDoubleClicked, EV_UIListBase_ItemDoubleClicked);
|
|
Connect(this, EV_UIListBase_ItemSelected, EV_UIListBase_ItemSelected);
|
|
AllowActivate(false);
|
|
m_bRemovePending = false;
|
|
|
|
setHeaderFont("facfont-20");
|
|
loadgame_ui = this;
|
|
}
|
|
|
|
UIFAKKLoadGameClass::~UIFAKKLoadGameClass()
|
|
{
|
|
loadgame_ui = NULL;
|
|
}
|
|
|
|
void UIFAKKLoadGameClass::UpdateUIElement(void)
|
|
{
|
|
float width;
|
|
|
|
RemoveAllColumns();
|
|
|
|
width = getClientFrame().size.width;
|
|
AddColumn(Sys_LV_CL_ConvertString("Mission"), 0, width * 0.555, false, false);
|
|
AddColumn(Sys_LV_CL_ConvertString("Elapsed Time"), 1, width * 0.17f, true, true);
|
|
AddColumn(Sys_LV_CL_ConvertString("Date & Time Logged"), 2, width * 0.275f, true, true);
|
|
|
|
uWinMan.ActivateControl(this);
|
|
|
|
SetupFiles();
|
|
}
|
|
|
|
void UIFAKKLoadGameClass::SetupFiles(void)
|
|
{
|
|
char **filenames;
|
|
int numfiles;
|
|
int i;
|
|
const char *searchFolder = Com_GetArchiveFolder();
|
|
|
|
// cleanup
|
|
DeleteAllItems();
|
|
|
|
filenames = FS_ListFiles(searchFolder, "ssv", qfalse, &numfiles);
|
|
|
|
for (i = 0; i < numfiles; i++) {
|
|
const char *filename;
|
|
str work;
|
|
str gametime;
|
|
str date;
|
|
fileHandle_t f;
|
|
savegamestruct_t save;
|
|
|
|
filename = filenames[i];
|
|
work = searchFolder;
|
|
work += "/";
|
|
work += filename;
|
|
|
|
FS_FOpenFileRead(work, &f, qfalse, qtrue);
|
|
if (!f) {
|
|
continue;
|
|
}
|
|
|
|
FS_Read(&save, sizeof(savegamestruct_t), f);
|
|
FS_FCloseFile(f);
|
|
|
|
if (save.version != SAVEGAME_STRUCT_VERSION) {
|
|
// wrong save game version
|
|
continue;
|
|
}
|
|
|
|
gametime = (save.mapTime / 1000);
|
|
date = save.time;
|
|
|
|
AddItem(new FAKKLoadGameItem(save.comment, gametime, date, save.saveName));
|
|
}
|
|
|
|
FS_FreeFileList(filenames);
|
|
|
|
// sort by date
|
|
SortByColumn(2);
|
|
|
|
// select the first item
|
|
TrySelectItem(1);
|
|
SelectGame(NULL);
|
|
}
|
|
|
|
void UIFAKKLoadGameClass::SelectGame(Event *ev)
|
|
{
|
|
UIWidget *wid;
|
|
const char *shotName;
|
|
|
|
if (getCurrentItem() > 0) {
|
|
shotName = Com_GetArchiveFileName(GetItem(getCurrentItem())->getListItemString(3), "tga");
|
|
} else {
|
|
shotName = "textures/menu/no_saved_games.tga";
|
|
}
|
|
|
|
wid = findSibling("LoadSaveShot");
|
|
if (!wid) {
|
|
return;
|
|
}
|
|
|
|
wid->setMaterial(uWinMan.RefreshShader(shotName));
|
|
}
|
|
|
|
void UIFAKKLoadGameClass::RemoveGame(Event *ev)
|
|
{
|
|
if (m_bRemovePending || getCurrentItem() <= 0) {
|
|
return;
|
|
}
|
|
|
|
Cbuf_ExecuteText(
|
|
EXEC_NOW,
|
|
"dialog \"\" \"\" \"widgetcommand LoadSaveList deletegame\" \"widgetcommand LoadSaveList nodeletegame\" 256 64 "
|
|
"confirm_delete menu_button_trans menu_button_trans\n"
|
|
);
|
|
m_bRemovePending = true;
|
|
}
|
|
|
|
void UIFAKKLoadGameClass::NoDeleteGame(Event *ev)
|
|
{
|
|
m_bRemovePending = false;
|
|
}
|
|
|
|
void UIFAKKLoadGameClass::DeleteGame(Event *ev)
|
|
{
|
|
str name;
|
|
cvar_t *var;
|
|
m_bRemovePending = false;
|
|
|
|
if (getCurrentItem() <= 0) {
|
|
return;
|
|
}
|
|
|
|
name = GetItem(getCurrentItem())->getListItemString(3);
|
|
var = Cvar_Get("g_lastsave", "", 0);
|
|
|
|
if (!strcmp(name, var->string)) {
|
|
// Make sure the last save is not the save being deleted
|
|
Cvar_Set("g_lastsave", "");
|
|
}
|
|
|
|
Com_WipeSavegame(name);
|
|
SetupFiles();
|
|
}
|
|
|
|
void UIFAKKLoadGameClass::LoadGame(Event *ev)
|
|
{
|
|
char cmdString[266];
|
|
str name;
|
|
|
|
if (getCurrentItem() <= 0) {
|
|
return;
|
|
}
|
|
|
|
name = GetItem(getCurrentItem())->getListItemString(3);
|
|
// Execute the command
|
|
Com_sprintf(cmdString, sizeof(cmdString), "loadgame %s\n", name.c_str());
|
|
Cbuf_AddText(cmdString);
|
|
}
|
|
|
|
void UIFAKKLoadGameClass::SaveGame(Event *ev)
|
|
{
|
|
Cbuf_ExecuteText(EXEC_NOW, "savegame");
|
|
}
|
|
|
|
qboolean UIFAKKLoadGameClass::KeyEvent(int key, unsigned int time)
|
|
{
|
|
switch (key) {
|
|
case K_DEL:
|
|
RemoveGame(NULL);
|
|
return qtrue;
|
|
case K_ENTER:
|
|
case K_KP_ENTER:
|
|
LoadGame(NULL);
|
|
return qtrue;
|
|
case K_UPARROW:
|
|
if (getCurrentItem() > 1) {
|
|
TrySelectItem(getCurrentItem() - 1);
|
|
SelectGame(NULL);
|
|
return qtrue;
|
|
}
|
|
break;
|
|
case K_DOWNARROW:
|
|
if (getCurrentItem() < getNumItems()) {
|
|
TrySelectItem(getCurrentItem() + 1);
|
|
SelectGame(NULL);
|
|
return qtrue;
|
|
}
|
|
break;
|
|
default:
|
|
return UIListBase::KeyEvent(key, time);
|
|
}
|
|
|
|
return qfalse;
|
|
}
|
|
|
|
void UI_SetupFiles(void)
|
|
{
|
|
if (loadgame_ui && loadgame_ui->getShow()) {
|
|
loadgame_ui->SetupFiles();
|
|
}
|
|
}
|
|
|
|
FAKKLoadGameItem::FAKKLoadGameItem(
|
|
const str& missionName, const str& elapsedTime, const str& dateTime, const str& fileName
|
|
)
|
|
{
|
|
strings[0] = missionName;
|
|
strings[1] = elapsedTime;
|
|
strings[2] = dateTime;
|
|
strings[3] = fileName;
|
|
}
|
|
|
|
int FAKKLoadGameItem::getListItemValue(int which) const
|
|
{
|
|
return atoi(strings[which]);
|
|
}
|
|
|
|
griditemtype_t FAKKLoadGameItem::getListItemType(int which) const
|
|
{
|
|
return griditemtype_t::TYPE_STRING;
|
|
}
|
|
|
|
str FAKKLoadGameItem::getListItemString(int which) const
|
|
{
|
|
str itemstring;
|
|
|
|
switch (which) {
|
|
case 0:
|
|
case 3:
|
|
itemstring = strings[which];
|
|
break;
|
|
case 1:
|
|
{
|
|
int numseconds;
|
|
int numseconds_hours;
|
|
|
|
// hours
|
|
numseconds = atol(strings[1]);
|
|
itemstring += (numseconds / 3600);
|
|
itemstring += ":";
|
|
|
|
// minutes
|
|
numseconds_hours = numseconds % 3600;
|
|
if (numseconds_hours / 60 <= 9) {
|
|
itemstring += "0";
|
|
}
|
|
itemstring += (numseconds_hours / 60);
|
|
itemstring += ":";
|
|
|
|
// seconds
|
|
if (numseconds_hours / 60 <= 9) {
|
|
itemstring += "0";
|
|
}
|
|
itemstring += (numseconds_hours % 60);
|
|
}
|
|
break;
|
|
case 2:
|
|
{
|
|
time_t time;
|
|
char buffer[2048];
|
|
|
|
time = atol(strings[2]);
|
|
strftime(buffer, sizeof(buffer), "%a %b %d %H:%M:%S %Y", localtime(&time));
|
|
itemstring = buffer;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return itemstring;
|
|
}
|
|
|
|
void FAKKLoadGameItem::DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) {}
|
|
|
|
qboolean FAKKLoadGameItem::IsHeaderEntry() const
|
|
{
|
|
return qfalse;
|
|
}
|