Ability to search for demos.

This commit is contained in:
furo 2023-08-26 01:55:30 +02:00
parent 5ba1834eed
commit 6781717983
3 changed files with 100 additions and 58 deletions

View file

@ -1215,7 +1215,7 @@ int CMenus::Render()
else if(m_Popup == POPUP_RENAME_DEMO)
{
dbg_assert(m_DemolistSelectedIndex >= 0, "m_DemolistSelectedIndex invalid for POPUP_RENAME_DEMO");
pTitle = m_vDemos[m_DemolistSelectedIndex].m_IsDir ? Localize("Rename folder") : Localize("Rename demo");
pTitle = m_vFilteredDemos[m_DemolistSelectedIndex].m_IsDir ? Localize("Rename folder") : Localize("Rename demo");
}
#if defined(CONF_VIDEORECORDER)
else if(m_Popup == POPUP_RENDER_DEMO)
@ -1519,31 +1519,31 @@ int CMenus::Render()
m_Popup = POPUP_NONE;
// rename demo
char aBufOld[IO_MAX_PATH_LENGTH];
str_format(aBufOld, sizeof(aBufOld), "%s/%s", m_aCurrentDemoFolder, m_vDemos[m_DemolistSelectedIndex].m_aFilename);
str_format(aBufOld, sizeof(aBufOld), "%s/%s", m_aCurrentDemoFolder, m_vFilteredDemos[m_DemolistSelectedIndex].m_aFilename);
char aBufNew[IO_MAX_PATH_LENGTH];
str_format(aBufNew, sizeof(aBufNew), "%s/%s", m_aCurrentDemoFolder, m_DemoRenameInput.GetString());
if(!m_vDemos[m_DemolistSelectedIndex].m_IsDir && !str_endswith(aBufNew, ".demo"))
if(!m_vFilteredDemos[m_DemolistSelectedIndex].m_IsDir && !str_endswith(aBufNew, ".demo"))
str_append(aBufNew, ".demo");
if(Storage()->FileExists(aBufNew, m_vDemos[m_DemolistSelectedIndex].m_StorageType))
if(Storage()->FileExists(aBufNew, m_vFilteredDemos[m_DemolistSelectedIndex].m_StorageType))
{
PopupMessage(Localize("Error"), Localize("A demo with this name already exists"), Localize("Ok"), POPUP_RENAME_DEMO);
}
else if(Storage()->FolderExists(aBufNew, m_vDemos[m_DemolistSelectedIndex].m_StorageType))
else if(Storage()->FolderExists(aBufNew, m_vFilteredDemos[m_DemolistSelectedIndex].m_StorageType))
{
PopupMessage(Localize("Error"), Localize("A folder with this name already exists"), Localize("Ok"), POPUP_RENAME_DEMO);
}
else if(Storage()->RenameFile(aBufOld, aBufNew, m_vDemos[m_DemolistSelectedIndex].m_StorageType))
else if(Storage()->RenameFile(aBufOld, aBufNew, m_vFilteredDemos[m_DemolistSelectedIndex].m_StorageType))
{
str_copy(m_aCurrentDemoSelectionName, m_DemoRenameInput.GetString());
if(!m_vDemos[m_DemolistSelectedIndex].m_IsDir)
if(!m_vFilteredDemos[m_DemolistSelectedIndex].m_IsDir)
fs_split_file_extension(m_DemoRenameInput.GetString(), m_aCurrentDemoSelectionName, sizeof(m_aCurrentDemoSelectionName));
DemolistPopulate();
DemolistOnUpdate(false);
}
else
{
PopupMessage(Localize("Error"), m_vDemos[m_DemolistSelectedIndex].m_IsDir ? Localize("Unable to rename the folder") : Localize("Unable to rename the demo"), Localize("Ok"), POPUP_RENAME_DEMO);
PopupMessage(Localize("Error"), m_vFilteredDemos[m_DemolistSelectedIndex].m_IsDir ? Localize("Unable to rename the folder") : Localize("Unable to rename the demo"), Localize("Ok"), POPUP_RENAME_DEMO);
}
}
@ -1560,7 +1560,7 @@ int CMenus::Render()
#if defined(CONF_VIDEORECORDER)
else if(m_Popup == POPUP_RENDER_DEMO)
{
dbg_assert(m_DemolistSelectedIndex >= 0 && !m_vDemos[m_DemolistSelectedIndex].m_IsDir, "m_DemolistSelectedIndex invalid for POPUP_RENDER_DEMO");
dbg_assert(m_DemolistSelectedIndex >= 0 && !m_vFilteredDemos[m_DemolistSelectedIndex].m_IsDir, "m_DemolistSelectedIndex invalid for POPUP_RENDER_DEMO");
CUIRect Label, TextBox, Ok, Abort, Button;
@ -1793,12 +1793,12 @@ int CMenus::Render()
void CMenus::PopupConfirmDemoReplaceVideo()
{
char aBuf[IO_MAX_PATH_LENGTH];
str_format(aBuf, sizeof(aBuf), "%s/%s", m_aCurrentDemoFolder, m_vDemos[m_DemolistSelectedIndex].m_aFilename);
str_format(aBuf, sizeof(aBuf), "%s/%s", m_aCurrentDemoFolder, m_vFilteredDemos[m_DemolistSelectedIndex].m_aFilename);
char aVideoName[IO_MAX_PATH_LENGTH];
str_copy(aVideoName, m_DemoRenderInput.GetString());
if(!str_endswith(aVideoName, ".mp4"))
str_append(aVideoName, ".mp4");
const char *pError = Client()->DemoPlayer_Render(aBuf, m_vDemos[m_DemolistSelectedIndex].m_StorageType, aVideoName, m_Speed, m_StartPaused);
const char *pError = Client()->DemoPlayer_Render(aBuf, m_vFilteredDemos[m_DemolistSelectedIndex].m_StorageType, aVideoName, m_Speed, m_StartPaused);
m_Speed = 4;
m_StartPaused = false;
m_LastPauseChange = -1.0f;

View file

@ -322,6 +322,7 @@ protected:
char m_aCurrentDemoSelectionName[IO_MAX_PATH_LENGTH];
CLineInputBuffered<IO_MAX_PATH_LENGTH> m_DemoRenameInput;
CLineInputBuffered<IO_MAX_PATH_LENGTH> m_DemoSliceInput;
CLineInputBuffered<IO_MAX_PATH_LENGTH> m_DemoSearchInput;
#if defined(CONF_VIDEORECORDER)
CLineInputBuffered<IO_MAX_PATH_LENGTH> m_DemoRenderInput;
#endif
@ -593,6 +594,7 @@ public:
// DDRace
int DoButton_CheckBox_Tristate(const void *pID, const char *pText, TRISTATE Checked, const CUIRect *pRect);
std::vector<CDemoItem> m_vDemos;
std::vector<CDemoItem> m_vFilteredDemos;
void DemolistPopulate();
void DemoSeekTick(IDemoPlayer::ETickOffset TickOffset);
bool m_Dummy;

View file

@ -901,7 +901,7 @@ void CMenus::DemolistOnUpdate(bool Reset)
bool Found = false;
int SelectedIndex = -1;
// search for selected index
for(auto &Item : m_vDemos)
for(auto &Item : m_vFilteredDemos)
{
SelectedIndex++;
@ -916,8 +916,8 @@ void CMenus::DemolistOnUpdate(bool Reset)
m_DemolistSelectedIndex = SelectedIndex;
}
m_DemolistSelectedIndex = Reset ? !m_vDemos.empty() ? 0 : -1 :
m_DemolistSelectedIndex >= (int)m_vDemos.size() ? m_vDemos.size() - 1 : m_DemolistSelectedIndex;
m_DemolistSelectedIndex = Reset ? !m_vFilteredDemos.empty() ? 0 : -1 :
m_DemolistSelectedIndex >= (int)m_vFilteredDemos.size() ? m_vFilteredDemos.size() - 1 : m_DemolistSelectedIndex;
m_DemolistSelectedReveal = true;
}
@ -952,15 +952,24 @@ void CMenus::RenderDemoList(CUIRect MainView)
s_Inited = 1;
}
m_vFilteredDemos.clear();
for(auto &Demo : m_vDemos)
{
if(str_find_nocase(Demo.m_aFilename, m_DemoSearchInput.GetString()))
{
m_vFilteredDemos.push_back(Demo);
}
}
char aFooterLabel[128] = {0};
if(m_DemolistSelectedIndex >= 0)
{
CDemoItem &Item = m_vDemos[m_DemolistSelectedIndex];
CDemoItem &Item = m_vFilteredDemos[m_DemolistSelectedIndex];
if(str_comp(Item.m_aFilename, "..") == 0)
str_copy(aFooterLabel, Localize("Parent Folder"));
else if(m_vDemos[m_DemolistSelectedIndex].m_IsLink)
else if(m_vFilteredDemos[m_DemolistSelectedIndex].m_IsLink)
str_copy(aFooterLabel, Localize("Folder Link"));
else if(m_vDemos[m_DemolistSelectedIndex].m_IsDir)
else if(m_vFilteredDemos[m_DemolistSelectedIndex].m_IsDir)
str_copy(aFooterLabel, Localize("Folder"));
else if(!FetchHeader(Item))
str_copy(aFooterLabel, Localize("Invalid Demo"));
@ -976,7 +985,7 @@ void CMenus::RenderDemoList(CUIRect MainView)
CUIRect RenderRect;
#endif
CUIRect ButtonBar, RefreshRect, FetchRect, PlayRect, DeleteRect, RenameRect, LabelRect, ListBox;
CUIRect ButtonBar2, DirectoryButton;
CUIRect ButtonBar2, DirectoryButton, DemoSearch;
MainView.HSplitBottom((ms_ButtonHeight + 5.0f) * 2.0f, &MainView, &ButtonBar2);
ButtonBar2.HSplitTop(5.0f, 0, &ButtonBar2);
@ -986,6 +995,8 @@ void CMenus::RenderDemoList(CUIRect MainView)
ButtonBar2.VSplitLeft(10.0f, 0, &ButtonBar2);
ButtonBar2.VSplitLeft(230.0f, &DirectoryButton, &ButtonBar2);
ButtonBar2.VSplitLeft(10.0f, 0, &ButtonBar2);
ButtonBar2.VSplitLeft(230.0f, &DemoSearch, &ButtonBar2);
ButtonBar2.VSplitLeft(10.0f, 0, &ButtonBar2);
ButtonBar.VSplitRight(110.0f, &ButtonBar, &PlayRect);
ButtonBar.VSplitLeft(110.0f, &RefreshRect, &ButtonBar);
ButtonBar.VSplitLeft(10.0f, 0, &ButtonBar);
@ -1004,7 +1015,7 @@ void CMenus::RenderDemoList(CUIRect MainView)
MainView.VMargin(5.0f, &MainView);
MainView.HSplitBottom(5.0f, &MainView, 0);
MainView.Draw(ColorRGBA(0, 0, 0, 0.15f), IGraphics::CORNER_B, 4.0f);
if(m_DemolistSelectedIndex >= 0 && !m_vDemos[m_DemolistSelectedIndex].m_IsDir && m_vDemos[m_DemolistSelectedIndex].m_Valid)
if(m_DemolistSelectedIndex >= 0 && !m_vFilteredDemos[m_DemolistSelectedIndex].m_IsDir && m_vFilteredDemos[m_DemolistSelectedIndex].m_Valid)
{
CUIRect Left, Right, Labels;
MainView.VMargin(20.0f, &MainView);
@ -1017,19 +1028,19 @@ void CMenus::RenderDemoList(CUIRect MainView)
UI()->DoLabel(&Left, Localize("Created:"), 14.0f, TEXTALIGN_ML);
char aTimestamp[256];
str_timestamp_ex(m_vDemos[m_DemolistSelectedIndex].m_Date, aTimestamp, sizeof(aTimestamp), FORMAT_SPACE);
str_timestamp_ex(m_vFilteredDemos[m_DemolistSelectedIndex].m_Date, aTimestamp, sizeof(aTimestamp), FORMAT_SPACE);
UI()->DoLabel(&Right, aTimestamp, 14.0f, TEXTALIGN_ML);
Labels.HSplitTop(5.0f, 0, &Labels);
Labels.HSplitTop(20.0f, &Left, &Labels);
Left.VSplitLeft(150.0f, &Left, &Right);
UI()->DoLabel(&Left, Localize("Type:"), 14.0f, TEXTALIGN_ML);
UI()->DoLabel(&Right, m_vDemos[m_DemolistSelectedIndex].m_Info.m_aType, 14.0f, TEXTALIGN_ML);
UI()->DoLabel(&Right, m_vFilteredDemos[m_DemolistSelectedIndex].m_Info.m_aType, 14.0f, TEXTALIGN_ML);
Labels.HSplitTop(5.0f, 0, &Labels);
Labels.HSplitTop(20.0f, &Left, &Labels);
Left.VSplitLeft(150.0f, &Left, &Right);
UI()->DoLabel(&Left, Localize("Length:"), 14.0f, TEXTALIGN_ML);
int Length = m_vDemos[m_DemolistSelectedIndex].Length();
int Length = m_vFilteredDemos[m_DemolistSelectedIndex].Length();
char aBuf[64];
str_time((int64_t)Length * 100, TIME_HOURS, aBuf, sizeof(aBuf));
UI()->DoLabel(&Right, aBuf, 14.0f, TEXTALIGN_ML);
@ -1037,13 +1048,13 @@ void CMenus::RenderDemoList(CUIRect MainView)
Labels.HSplitTop(20.0f, &Left, &Labels);
Left.VSplitLeft(150.0f, &Left, &Right);
UI()->DoLabel(&Left, Localize("Version:"), 14.0f, TEXTALIGN_ML);
str_from_int(m_vDemos[m_DemolistSelectedIndex].m_Info.m_Version, aBuf);
str_format(aBuf, sizeof(aBuf), "%d", m_vFilteredDemos[m_DemolistSelectedIndex].m_Info.m_Version);
UI()->DoLabel(&Right, aBuf, 14.0f, TEXTALIGN_ML);
Labels.HSplitTop(5.0f, 0, &Labels);
Labels.HSplitTop(20.0f, &Left, &Labels);
Left.VSplitLeft(150.0f, &Left, &Right);
UI()->DoLabel(&Left, Localize("Markers:"), 14.0f, TEXTALIGN_ML);
str_from_int(m_vDemos[m_DemolistSelectedIndex].NumMarkers(), aBuf);
str_format(aBuf, sizeof(aBuf), "%d", m_vFilteredDemos[m_DemolistSelectedIndex].NumMarkers());
UI()->DoLabel(&Right, aBuf, 14.0f, TEXTALIGN_ML);
// right side
@ -1051,12 +1062,12 @@ void CMenus::RenderDemoList(CUIRect MainView)
Labels.HSplitTop(20.0f, &Left, &Labels);
Left.VSplitLeft(150.0f, &Left, &Right);
UI()->DoLabel(&Left, Localize("Map:"), 14.0f, TEXTALIGN_ML);
UI()->DoLabel(&Right, m_vDemos[m_DemolistSelectedIndex].m_Info.m_aMapName, 14.0f, TEXTALIGN_ML);
UI()->DoLabel(&Right, m_vFilteredDemos[m_DemolistSelectedIndex].m_Info.m_aMapName, 14.0f, TEXTALIGN_ML);
Labels.HSplitTop(5.0f, 0, &Labels);
Labels.HSplitTop(20.0f, &Left, &Labels);
Left.VSplitLeft(150.0f, &Left, &Right);
UI()->DoLabel(&Left, Localize("Size:"), 14.0f, TEXTALIGN_ML);
const float Size = m_vDemos[m_DemolistSelectedIndex].Size() / 1024.0f;
const float Size = m_vFilteredDemos[m_DemolistSelectedIndex].Size() / 1024.0f;
if(Size > 1024)
str_format(aBuf, sizeof(aBuf), Localize("%.2f MiB"), Size / 1024.0f);
else
@ -1065,17 +1076,17 @@ void CMenus::RenderDemoList(CUIRect MainView)
Labels.HSplitTop(5.0f, 0, &Labels);
Labels.HSplitTop(20.0f, &Left, &Labels);
Left.VSplitLeft(150.0f, &Left, &Right);
if(m_vDemos[m_DemolistSelectedIndex].m_MapInfo.m_Sha256 != SHA256_ZEROED)
if(m_vFilteredDemos[m_DemolistSelectedIndex].m_MapInfo.m_Sha256 != SHA256_ZEROED)
{
UI()->DoLabel(&Left, "SHA256:", 14.0f, TEXTALIGN_ML);
char aSha[SHA256_MAXSTRSIZE];
sha256_str(m_vDemos[m_DemolistSelectedIndex].m_MapInfo.m_Sha256, aSha, sizeof(aSha) / 2);
sha256_str(m_vFilteredDemos[m_DemolistSelectedIndex].m_MapInfo.m_Sha256, aSha, sizeof(aSha) / 2);
UI()->DoLabel(&Right, aSha, Right.w > 235 ? 14.0f : 11.0f, TEXTALIGN_ML);
}
else
{
UI()->DoLabel(&Left, Localize("Crc:"), 14.0f, TEXTALIGN_ML);
str_format(aBuf, sizeof(aBuf), "%08x", m_vDemos[m_DemolistSelectedIndex].m_MapInfo.m_Crc);
str_format(aBuf, sizeof(aBuf), "%08x", m_vFilteredDemos[m_DemolistSelectedIndex].m_MapInfo.m_Crc);
UI()->DoLabel(&Right, aBuf, 14.0f, TEXTALIGN_ML);
}
Labels.HSplitTop(5.0f, 0, &Labels);
@ -1083,7 +1094,7 @@ void CMenus::RenderDemoList(CUIRect MainView)
Left.VSplitLeft(150.0f, &Left, &Right);
UI()->DoLabel(&Left, Localize("Netversion:"), 14.0f, TEXTALIGN_ML);
UI()->DoLabel(&Right, m_vDemos[m_DemolistSelectedIndex].m_Info.m_aNetversion, 14.0f, TEXTALIGN_ML);
UI()->DoLabel(&Right, m_vFilteredDemos[m_DemolistSelectedIndex].m_Info.m_aNetversion, 14.0f, TEXTALIGN_ML);
}
// demo list
@ -1166,7 +1177,7 @@ void CMenus::RenderDemoList(CUIRect MainView)
}
// Don't rescan in order to keep fetched headers, just resort
std::stable_sort(m_vDemos.begin(), m_vDemos.end());
std::stable_sort(m_vFilteredDemos.begin(), m_vFilteredDemos.end());
DemolistOnUpdate(false);
}
}
@ -1176,10 +1187,11 @@ void CMenus::RenderDemoList(CUIRect MainView)
s_ListBox.ScrollToSelected();
m_DemolistSelectedReveal = false;
}
s_ListBox.DoStart(ms_ListheaderHeight, m_vDemos.size(), 1, 3, m_DemolistSelectedIndex, &ListBox, false, IGraphics::CORNER_ALL, true);
s_ListBox.DoStart(ms_ListheaderHeight, m_vFilteredDemos.size(), 1, 3, m_DemolistSelectedIndex, &ListBox, false, IGraphics::CORNER_ALL, true);
int ItemIndex = -1;
for(auto &Item : m_vDemos)
for(auto &Item : m_vFilteredDemos)
{
ItemIndex++;
@ -1260,7 +1272,7 @@ void CMenus::RenderDemoList(CUIRect MainView)
{
m_DemolistSelectedIndex = NewSelected;
if(m_DemolistSelectedIndex >= 0)
str_copy(m_aCurrentDemoSelectionName, m_vDemos[m_DemolistSelectedIndex].m_aName);
str_copy(m_aCurrentDemoSelectionName, m_vFilteredDemos[m_DemolistSelectedIndex].m_aName);
DemolistOnUpdate(false);
}
@ -1279,13 +1291,14 @@ void CMenus::RenderDemoList(CUIRect MainView)
}
static CButtonContainer s_PlayButton;
if(DoButton_Menu(&s_PlayButton, (m_DemolistSelectedIndex >= 0 && m_vDemos[m_DemolistSelectedIndex].m_IsDir) ? Localize("Open") : Localize("Play", "Demo browser"), 0, &PlayRect) || s_ListBox.WasItemActivated() || UI()->ConsumeHotkey(CUI::HOTKEY_ENTER) || (Input()->KeyPress(KEY_P) && m_pClient->m_GameConsole.IsClosed()))
if(DoButton_Menu(&s_PlayButton, (m_DemolistSelectedIndex >= 0 && m_vFilteredDemos[m_DemolistSelectedIndex].m_IsDir) ? Localize("Open") : Localize("Play", "Demo browser"), 0, &PlayRect) || s_ListBox.WasItemActivated() || UI()->ConsumeHotkey(CUI::HOTKEY_ENTER) || (Input()->KeyPress(KEY_P) && m_pClient->m_GameConsole.IsClosed() && !m_DemoSearchInput.IsActive()))
{
if(m_DemolistSelectedIndex >= 0)
{
if(m_vDemos[m_DemolistSelectedIndex].m_IsDir) // folder
if(m_vFilteredDemos[m_DemolistSelectedIndex].m_IsDir) // folder
{
const bool ParentFolder = str_comp(m_vDemos[m_DemolistSelectedIndex].m_aFilename, "..") == 0;
m_DemoSearchInput.Clear();
const bool ParentFolder = str_comp(m_vFilteredDemos[m_DemolistSelectedIndex].m_aFilename, "..") == 0;
if(ParentFolder) // parent folder
{
str_copy(m_aCurrentDemoSelectionName, fs_filename(m_aCurrentDemoFolder));
@ -1309,8 +1322,8 @@ void CMenus::RenderDemoList(CUIRect MainView)
if(m_aCurrentDemoFolder[0] != '\0')
str_append(m_aCurrentDemoFolder, "/");
else
m_DemolistStorageType = m_vDemos[m_DemolistSelectedIndex].m_StorageType;
str_append(m_aCurrentDemoFolder, m_vDemos[m_DemolistSelectedIndex].m_aFilename);
m_DemolistStorageType = m_vFilteredDemos[m_DemolistSelectedIndex].m_StorageType;
str_append(m_aCurrentDemoFolder, m_vFilteredDemos[m_DemolistSelectedIndex].m_aFilename);
}
DemolistPopulate();
DemolistOnUpdate(!ParentFolder);
@ -1318,8 +1331,8 @@ void CMenus::RenderDemoList(CUIRect MainView)
else // file
{
char aBuf[IO_MAX_PATH_LENGTH];
str_format(aBuf, sizeof(aBuf), "%s/%s", m_aCurrentDemoFolder, m_vDemos[m_DemolistSelectedIndex].m_aFilename);
const char *pError = Client()->DemoPlayer_Play(aBuf, m_vDemos[m_DemolistSelectedIndex].m_StorageType);
str_format(aBuf, sizeof(aBuf), "%s/%s", m_aCurrentDemoFolder, m_vFilteredDemos[m_DemolistSelectedIndex].m_aFilename);
const char *pError = Client()->DemoPlayer_Play(aBuf, m_vFilteredDemos[m_DemolistSelectedIndex].m_StorageType);
m_LastPauseChange = -1.0f;
m_LastSpeedChange = -1.0f;
if(pError)
@ -1337,7 +1350,7 @@ void CMenus::RenderDemoList(CUIRect MainView)
if(DoButton_Menu(&s_DirectoryButtonID, Localize("Demos directory"), 0, &DirectoryButton))
{
char aBuf[IO_MAX_PATH_LENGTH];
Storage()->GetCompletePath(m_DemolistSelectedIndex >= 0 ? m_vDemos[m_DemolistSelectedIndex].m_StorageType : IStorage::TYPE_SAVE, m_aCurrentDemoFolder[0] == '\0' ? "demos" : m_aCurrentDemoFolder, aBuf, sizeof(aBuf));
Storage()->GetCompletePath(m_DemolistSelectedIndex >= 0 ? m_vFilteredDemos[m_DemolistSelectedIndex].m_StorageType : IStorage::TYPE_SAVE, m_aCurrentDemoFolder[0] == '\0' ? "demos" : m_aCurrentDemoFolder, aBuf, sizeof(aBuf));
if(!open_file(aBuf))
{
dbg_msg("menus", "couldn't open file '%s'", aBuf);
@ -1347,14 +1360,14 @@ void CMenus::RenderDemoList(CUIRect MainView)
if(m_DemolistSelectedIndex >= 0 && m_aCurrentDemoFolder[0] != '\0')
{
if(str_comp(m_vDemos[m_DemolistSelectedIndex].m_aFilename, "..") != 0 && m_vDemos[m_DemolistSelectedIndex].m_StorageType == IStorage::TYPE_SAVE)
if(str_comp(m_vFilteredDemos[m_DemolistSelectedIndex].m_aFilename, "..") != 0 && m_vFilteredDemos[m_DemolistSelectedIndex].m_StorageType == IStorage::TYPE_SAVE)
{
static CButtonContainer s_DeleteButton;
if(DoButton_Menu(&s_DeleteButton, Localize("Delete"), 0, &DeleteRect) || UI()->ConsumeHotkey(CUI::HOTKEY_DELETE) || (Input()->KeyPress(KEY_D) && m_pClient->m_GameConsole.IsClosed()))
if(DoButton_Menu(&s_DeleteButton, Localize("Delete"), 0, &DeleteRect) || UI()->ConsumeHotkey(CUI::HOTKEY_DELETE) || (Input()->KeyPress(KEY_D) && m_pClient->m_GameConsole.IsClosed() && !m_DemoSearchInput.IsActive()))
{
char aBuf[128 + IO_MAX_PATH_LENGTH];
str_format(aBuf, sizeof(aBuf), m_vDemos[m_DemolistSelectedIndex].m_IsDir ? Localize("Are you sure that you want to delete the folder '%s'?") : Localize("Are you sure that you want to delete the demo '%s'?"), m_vDemos[m_DemolistSelectedIndex].m_aFilename);
PopupConfirm(m_vDemos[m_DemolistSelectedIndex].m_IsDir ? Localize("Delete folder") : Localize("Delete demo"), aBuf, Localize("Yes"), Localize("No"), m_vDemos[m_DemolistSelectedIndex].m_IsDir ? &CMenus::PopupConfirmDeleteFolder : &CMenus::PopupConfirmDeleteDemo);
str_format(aBuf, sizeof(aBuf), m_vFilteredDemos[m_DemolistSelectedIndex].m_IsDir ? Localize("Are you sure that you want to delete the folder '%s'?") : Localize("Are you sure that you want to delete the demo '%s'?"), m_vFilteredDemos[m_DemolistSelectedIndex].m_aFilename);
PopupConfirm(m_vFilteredDemos[m_DemolistSelectedIndex].m_IsDir ? Localize("Delete folder") : Localize("Delete demo"), aBuf, Localize("Yes"), Localize("No"), m_vFilteredDemos[m_DemolistSelectedIndex].m_IsDir ? &CMenus::PopupConfirmDeleteFolder : &CMenus::PopupConfirmDeleteDemo);
return;
}
@ -1362,14 +1375,14 @@ void CMenus::RenderDemoList(CUIRect MainView)
if(DoButton_Menu(&s_RenameButton, Localize("Rename"), 0, &RenameRect))
{
m_Popup = POPUP_RENAME_DEMO;
if(m_vDemos[m_DemolistSelectedIndex].m_IsDir)
if(m_vFilteredDemos[m_DemolistSelectedIndex].m_IsDir)
{
m_DemoRenameInput.Set(m_vDemos[m_DemolistSelectedIndex].m_aFilename);
m_DemoRenameInput.Set(m_vFilteredDemos[m_DemolistSelectedIndex].m_aFilename);
}
else
{
char aNameWithoutExt[IO_MAX_PATH_LENGTH];
fs_split_file_extension(m_vDemos[m_DemolistSelectedIndex].m_aFilename, aNameWithoutExt, sizeof(aNameWithoutExt));
fs_split_file_extension(m_vFilteredDemos[m_DemolistSelectedIndex].m_aFilename, aNameWithoutExt, sizeof(aNameWithoutExt));
m_DemoRenameInput.Set(aNameWithoutExt);
}
UI()->SetActiveItem(&m_DemoRenameInput);
@ -1378,15 +1391,15 @@ void CMenus::RenderDemoList(CUIRect MainView)
}
#if defined(CONF_VIDEORECORDER)
if(!m_vDemos[m_DemolistSelectedIndex].m_IsDir)
if(!m_vFilteredDemos[m_DemolistSelectedIndex].m_IsDir)
{
static CButtonContainer s_RenderButton;
if(DoButton_Menu(&s_RenderButton, Localize("Render"), 0, &RenderRect) || (Input()->KeyPress(KEY_R) && m_pClient->m_GameConsole.IsClosed()))
if(DoButton_Menu(&s_RenderButton, Localize("Render"), 0, &RenderRect) || (Input()->KeyPress(KEY_R) && m_pClient->m_GameConsole.IsClosed() && !m_DemoSearchInput.IsActive()))
{
m_Popup = POPUP_RENDER_DEMO;
m_StartPaused = false;
char aNameWithoutExt[IO_MAX_PATH_LENGTH];
fs_split_file_extension(m_vDemos[m_DemolistSelectedIndex].m_aFilename, aNameWithoutExt, sizeof(aNameWithoutExt));
fs_split_file_extension(m_vFilteredDemos[m_DemolistSelectedIndex].m_aFilename, aNameWithoutExt, sizeof(aNameWithoutExt));
m_DemoRenderInput.Set(aNameWithoutExt);
UI()->SetActiveItem(&m_DemoRenderInput);
return;
@ -1396,13 +1409,40 @@ void CMenus::RenderDemoList(CUIRect MainView)
}
UI()->DoLabel(&LabelRect, aFooterLabel, 14.0f, TEXTALIGN_ML);
// render quick search
{
float SearchIconWidth = 0;
float ExcludeIconWidth = 0;
float ExcludeSearchIconMax = 0;
TextRender()->SetFontPreset(EFontPreset::ICON_FONT);
TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_PIXEL_ALIGMENT | ETextRenderFlags::TEXT_RENDER_FLAG_NO_OVERSIZE);
UI()->DoLabel(&DemoSearch, FONT_ICON_MAGNIFYING_GLASS, 16.0f, TEXTALIGN_ML);
SearchIconWidth = TextRender()->TextWidth(16.0f, FONT_ICON_MAGNIFYING_GLASS, -1, -1.0f);
ExcludeIconWidth = TextRender()->TextWidth(16.0f, FONT_ICON_BAN, -1, -1.0f);
ExcludeSearchIconMax = maximum(SearchIconWidth, ExcludeIconWidth);
TextRender()->SetRenderFlags(0);
TextRender()->SetFontPreset(EFontPreset::DEFAULT_FONT);
DemoSearch.VSplitLeft(ExcludeSearchIconMax, 0, &DemoSearch);
DemoSearch.VSplitLeft(5.0f, 0, &DemoSearch);
m_DemoSearchInput.SetEmptyText(Localize("Search"));
if(Input()->KeyPress(KEY_F) && Input()->ModifierIsPressed())
{
UI()->SetActiveItem(&m_DemoSearchInput);
m_DemoSearchInput.SelectAll();
}
UI()->DoClearableEditBox(&m_DemoSearchInput, &DemoSearch, 12.0f);
}
}
void CMenus::PopupConfirmDeleteDemo()
{
char aBuf[IO_MAX_PATH_LENGTH];
str_format(aBuf, sizeof(aBuf), "%s/%s", m_aCurrentDemoFolder, m_vDemos[m_DemolistSelectedIndex].m_aFilename);
if(Storage()->RemoveFile(aBuf, m_vDemos[m_DemolistSelectedIndex].m_StorageType))
str_format(aBuf, sizeof(aBuf), "%s/%s", m_aCurrentDemoFolder, m_vFilteredDemos[m_DemolistSelectedIndex].m_aFilename);
if(Storage()->RemoveFile(aBuf, m_vFilteredDemos[m_DemolistSelectedIndex].m_StorageType))
{
DemolistPopulate();
DemolistOnUpdate(false);
@ -1410,7 +1450,7 @@ void CMenus::PopupConfirmDeleteDemo()
else
{
char aError[128 + IO_MAX_PATH_LENGTH];
str_format(aError, sizeof(aError), Localize("Unable to delete the demo '%s'"), m_vDemos[m_DemolistSelectedIndex].m_aFilename);
str_format(aError, sizeof(aError), Localize("Unable to delete the demo '%s'"), m_vFilteredDemos[m_DemolistSelectedIndex].m_aFilename);
PopupMessage(Localize("Error"), aError, Localize("Ok"));
}
}
@ -1418,8 +1458,8 @@ void CMenus::PopupConfirmDeleteDemo()
void CMenus::PopupConfirmDeleteFolder()
{
char aBuf[IO_MAX_PATH_LENGTH];
str_format(aBuf, sizeof(aBuf), "%s/%s", m_aCurrentDemoFolder, m_vDemos[m_DemolistSelectedIndex].m_aFilename);
if(Storage()->RemoveFolder(aBuf, m_vDemos[m_DemolistSelectedIndex].m_StorageType))
str_format(aBuf, sizeof(aBuf), "%s/%s", m_aCurrentDemoFolder, m_vFilteredDemos[m_DemolistSelectedIndex].m_aFilename);
if(Storage()->RemoveFolder(aBuf, m_vFilteredDemos[m_DemolistSelectedIndex].m_StorageType))
{
DemolistPopulate();
DemolistOnUpdate(false);
@ -1427,7 +1467,7 @@ void CMenus::PopupConfirmDeleteFolder()
else
{
char aError[128 + IO_MAX_PATH_LENGTH];
str_format(aError, sizeof(aError), Localize("Unable to delete the folder '%s'. Make sure it's empty first."), m_vDemos[m_DemolistSelectedIndex].m_aFilename);
str_format(aError, sizeof(aError), Localize("Unable to delete the folder '%s'. Make sure it's empty first."), m_vFilteredDemos[m_DemolistSelectedIndex].m_aFilename);
PopupMessage(Localize("Error"), aError, Localize("Ok"));
}
}