diff --git a/cod4qol/commands.cpp b/cod4qol/commands.cpp index 1542d84..a478e3e 100644 --- a/cod4qol/commands.cpp +++ b/cod4qol/commands.cpp @@ -17,6 +17,9 @@ void commands::InitializeCommands() game::Cmd_AddCommand("loaddemos", LoadDemos); game::Cmd_AddCommand("playselecteddemo", PlaySelectedDemo); + game::Cmd_AddCommand("getdemoname", GetDemoName); + game::Cmd_AddCommand("deleteselecteddemo", DeleteSelectedDemo); + game::Cmd_AddCommand("renameselecteddemo", RenameSelectedDemo); game::Cmd_AddCommand("updatecod4qol", updater::Update); @@ -205,10 +208,7 @@ void commands::ToggleSteamAuthUpdate() void commands::LoadDemos() { - std::string relative_dir = game::fs_homepath->current.string; - relative_dir.append("\\"); - relative_dir.append(!strcmp(game::fs_game->current.string, "") ? "main" : game::fs_game->current.string); - relative_dir.append("\\demos"); + std::string relative_dir = getDemosFolder(); *game::modCount = 0; *game::modIndex = 0; @@ -225,6 +225,11 @@ void commands::LoadDemos() (*game::modCount)++; } + + if((*game::modCount) < 1) + game::Cmd_ExecuteSingleCommand(0, 0, "set qol_show_demos_buttons 0\n"); + else + game::Cmd_ExecuteSingleCommand(0, 0, "set qol_show_demos_buttons 1\n"); } void commands::PlaySelectedDemo() @@ -235,4 +240,73 @@ void commands::PlaySelectedDemo() std::string cmd = "demo " + std::string(game::modName[2 * (*game::modIndex)]); game::Cbuf_AddText(cmd.c_str(), 0); +} + +void commands::DeleteSelectedDemo() +{ + if (*game::modCount < 1) + return; + + std::string relative_dir = getDemosFolder(); + relative_dir.append("\\" + std::string(game::modName[2 * (*game::modIndex)]) + ".dm_1"); + + std::filesystem::remove(relative_dir); + + commands::LoadDemos(); +} + +void commands::RenameSelectedDemo() +{ + game::dvar_s* qol_rename_text = game::Find("qol_rename_text"); + + if(!qol_rename_text) + return; + + if (*game::modCount < 1) + return; + + std::string relative_dir = getDemosFolder(); + relative_dir.append("\\" + std::string(game::modName[2 * (*game::modIndex)]) + ".dm_1"); + + std::string new_name = relative_dir.substr(0, relative_dir.find_last_of("\\/")) + "\\" + std::string(qol_rename_text->current.string) + ".dm_1"; + + if (!isValidDestinationPath(new_name)) + return; + + std::filesystem::rename(relative_dir, new_name); +} + +void commands::GetDemoName() +{ + if (*game::modCount < 1) + return; + + std::string cmd = "set qol_rename_text " + std::string(game::modName[2 * (*game::modIndex)]) + "\n"; + + game::Cmd_ExecuteSingleCommand(0, 0, cmd.c_str()); +} + +std::string getDemosFolder() +{ + + std::string relative_dir = game::fs_homepath->current.string; + relative_dir.append("\\"); + relative_dir.append(!strcmp(game::fs_game->current.string, "") ? "main" : game::fs_game->current.string); + relative_dir.append("\\demos"); + + return relative_dir; +} + +bool isValidDestinationPath(const std::filesystem::path& destination) +{ + const std::string disallowedChars = "<>:\"/\\|?*"; + + for (char c : destination.filename().string()) + if (disallowedChars.find(c) != std::string::npos) + { + std::cout << "Invalid character '" << c << "' in the destination path." << std::endl; + return false; + } + + return true; } \ No newline at end of file diff --git a/cod4qol/commands.hpp b/cod4qol/commands.hpp index 91423af..0c28a85 100644 --- a/cod4qol/commands.hpp +++ b/cod4qol/commands.hpp @@ -17,6 +17,8 @@ namespace commands inline game::dvar_s* cg_gun_z; inline game::dvar_s* cg_draw2d; inline game::dvar_s* cg_drawgun; + + inline game::dvar_s* qol_rename_text; inline game::dvar_s* qol_check_updates; inline game::dvar_s* qol_getss; @@ -39,6 +41,14 @@ namespace commands void SetGun(game::GfxViewParms* view_parms); void ToggleLoadingInfoUpdate(); void ToggleSteamAuthUpdate(); + void LoadDemos(); void PlaySelectedDemo(); -} \ No newline at end of file + void DeleteSelectedDemo(); + void RenameSelectedDemo(); + void GetDemoName(); + +} + +std::string getDemosFolder(); +bool isValidDestinationPath(const std::filesystem::path& destination); \ No newline at end of file diff --git a/cod4qol/updater.cpp b/cod4qol/updater.cpp index 9fbe07b..23668db 100644 --- a/cod4qol/updater.cpp +++ b/cod4qol/updater.cpp @@ -42,7 +42,7 @@ bool updater::CheckForUpdates() download_url = parsed["assets"][0]["browser_download_url"]; std::cout << "A new version of " << COD4QOL_NAME << " is available: " << parsed["tag_name"] << std::endl; - game::Cmd_ExecuteSingleCommand(0, 0, "set qol_update_available 1\n"); + game::Cmd_ExecuteSingleCommand(0, 0, "set qol_dialog 1\n"); return true; } diff --git a/mod/cod4qol/mod.ff b/mod/cod4qol/mod.ff index 8e16e3c..c595e42 100644 Binary files a/mod/cod4qol/mod.ff and b/mod/cod4qol/mod.ff differ diff --git a/mod/cod4qol/ui/quit.menu b/mod/cod4qol/ui/quit.menu index d7dacb4..ab3a3d3 100644 --- a/mod/cod4qol/ui/quit.menu +++ b/mod/cod4qol/ui/quit.menu @@ -14,6 +14,8 @@ #undef CHOICE_SIZE_X #define CHOICE_SIZE_X 320 + +#define SIDE_MARGIN 40 #undef CHOICE_HORIZONTAL_ALIGN #define CHOICE_HORIZONTAL_ALIGN HORIZONTAL_ALIGN_CENTER @@ -35,17 +37,87 @@ decoration \ } +#define CENTER_POPUP_SETUP_RAW_EXTR( nameArg, itemCount, onEscArg, onOpenArg, extraArgs, shadow_visArg ) \ + name nameArg \ + fullscreen 0 \ + rect (0-(CHOICE_POPUP_WIDTH/2)) (0-(CHOICE_POPUP_HEIGHT( itemCount )/2)) CHOICE_POPUP_WIDTH CHOICE_POPUP_HEIGHT( itemCount ) HORIZONTAL_ALIGN_CENTER VERTICAL_ALIGN_CENTER \ + border 1 \ + backcolor 0 0 0 0 \ + bordersize CHOICE_POPUP_BORDER_WIDTH \ + bordercolor CHOICE_POPUP_BORDER_COLOR \ + focusColor COLOR_FOCUSED \ + style WINDOW_STYLE_FILLED \ + popup \ + extraArgs \ + onOpen \ + { \ + setLocalVarBool ui_centerPopup 1; \ + onOpenArg; \ + } \ + onClose \ + { \ + CENTER_POPUP_ON_CLOSE \ + setdvar qol_dialog 0; \ + setLocalVarBool ui_centerPopup 0; \ + } \ + onESC \ + { \ + setLocalVarBool ui_centerPopup 0; \ + close self; \ + onEscArg; \ + } \ + PREPROC_CANCEL_OVERLAY( shadow_visArg, itemCount ) \ + itemDef \ + { \ + style WINDOW_STYLE_SHADER \ + rect 0 0 (CHOICE_POPUP_WIDTH-(CHOICE_POPUP_BORDER_WIDTH*2)) (CHOICE_POPUP_HEIGHT( itemCount )-(CHOICE_POPUP_BORDER_WIDTH*2)) HORIZONTAL_ALIGN_CENTER VERTICAL_ALIGN_CENTER \ + background "white" \ + forecolor CHOICE_POPUP_BACKCOLOR \ + visible 1 \ + decoration \ + } + { menuDef { - CENTER_POPUP_SETUP( quit_popmenu, 4, ;, 1 ) + CENTER_POPUP_SETUP_RAW_EXTR( quit_popmenu, 4, ;, focusfirst, ;, 1 ); + + CHOICE_POPMENU_TITLE_VIS( "@MENU_ARE_YOU_SURE_QUIT", when(dvarInt("qol_dialog") == 0)) + CHOICE_BUTTON_VIS( 3, "@MENU_YES", uiScript quit, when(dvarInt("qol_dialog") == 0)) + CHOICE_BUTTON_VIS( 4, "@MENU_NO", close self, when(dvarInt("qol_dialog") == 0) ) - CHOICE_POPMENU_TITLE_VIS( "@MENU_ARE_YOU_SURE_QUIT", when(dvarInt("qol_update_available") == 0)) - CHOICE_BUTTON_VIS( 3, "@MENU_YES", uiScript quit, when(dvarInt("qol_update_available") == 0)) - CHOICE_BUTTON_VIS( 4, "@MENU_NO", close self, when(dvarInt("qol_update_available") == 0) ) + CHOICE_POPMENU_TITLE_VIS_EXTR( "A new version of CoD4QOL is available. Do you want to install it?", when(dvarInt("qol_dialog") == 1), 0.32) + CHOICE_BUTTON_VIS( 3, "@MENU_YES", exec "updatecod4qol";, when(dvarInt("qol_dialog") == 1)) + CHOICE_BUTTON_VIS( 4, "@MENU_NO", close self;, when(dvarInt("qol_dialog") == 1)) - CHOICE_POPMENU_TITLE_VIS_EXTR( "A new version of CoD4QOL is available. Do you want to install it?", when(dvarInt("qol_update_available") == 1), 0.32) - CHOICE_BUTTON_VIS( 3, "@MENU_YES", exec "updatecod4qol";, when(dvarInt("qol_update_available") == 1)) - CHOICE_BUTTON_VIS( 4, "@MENU_NO", close self; setdvar qol_update_available 0;, when(dvarInt("qol_update_available") == 1)) + CHOICE_POPMENU_TITLE_VIS_EXTR( "Are you sure you want to delete the selected demo?", when(dvarInt("qol_dialog") == 2), 0.32) + CHOICE_BUTTON_VIS( 3, "@MENU_YES", exec "deleteselecteddemo"; exec "loaddemos"; close self;, when(dvarInt("qol_dialog") == 2)) + CHOICE_BUTTON_VIS( 4, "@MENU_NO", close self;, when(dvarInt("qol_dialog") == 2)) + + CHOICE_POPMENU_TITLE_VIS_EXTR( "Type in the new name:", when(dvarInt("qol_dialog") == 3), 0.32) + itemDef + { + name renameEntry + group grpControls + TYPE 4 + text " " + dvar "qol_rename_text" + rect CHOICE_ORIGIN( 3 ) (CHOICE_SIZE_X-(SIDE_MARGIN*2)) 18 + origin SIDE_MARGIN -8 + textaligny -2 + maxchars 128 + maxpaintchars 128 + textalign ITEM_ALIGN_MIDDLE_LEFT + textfont UI_FONT_NORMAL + textscale TEXTSIZE_SMALL + forecolor .9 .9 .9 1 + style WINDOW_STYLE_FILLED + backcolor 0 0 0 .3 + visible when(dvarInt("qol_dialog") == 3) + mouseenter { show keyBindStatus; play "mouse_over"; } + mouseexit { hide keyBindStatus; setfocus ok_button; } + accept { exec "renameselecteddemo"; exec "loaddemos"; close self; } + } + CHOICE_BUTTON_VIS( 4, "@MENU_OK", exec "renameselecteddemo"; exec "loaddemos"; close self;, when(dvarInt("qol_dialog") == 3)) } } diff --git a/mod/cod4qol/ui_mp/main.menu b/mod/cod4qol/ui_mp/main.menu index 8bd0978..851307b 100644 --- a/mod/cod4qol/ui_mp/main.menu +++ b/mod/cod4qol/ui_mp/main.menu @@ -34,7 +34,7 @@ uiScript addPlayerProfiles; uiScript openMenuOnDvar com_playerProfile "" player_profile; uiScript openMenuOnDvarNot ui_playerProfileCount 1 player_profile; - uiScript openMenuOnDvar qol_update_available 1 quit_popmenu; + uiScript openMenuOnDvar qol_dialog 1 quit_popmenu; uiScript stopRefresh; setdvar ui_showEndOfGame "0"; } diff --git a/mod/cod4qol/ui_mp/mods.menu b/mod/cod4qol/ui_mp/mods.menu index a2e7b11..1ad76a3 100644 --- a/mod/cod4qol/ui_mp/mods.menu +++ b/mod/cod4qol/ui_mp/mods.menu @@ -104,15 +104,15 @@ bordercolor 1 1 1 0.15 outlinecolor BUTTON_BG_COLOR visible when( localVarInt ( ui_qol ) == 1 ); - action { show accept; } + action { } doubleClick { play "mouse_click"; exec "playselecteddemo"; } } CHOICE_BUTTON_VIS( 1, "@MENU_LAUNCH", uiScript RunMod;, when( localVarInt ( ui_qol ) == 0 ); ) CHOICE_BUTTON_VIS( 2, "@MENU_LAUNCH_WITHOUT_MODS", uiScript ClearMods;, when( dvarString( fs_game ) != "" && localVarInt ( ui_qol ) == 0 ); ) - CHOICE_BUTTON_VIS( 1, "Play", exec "playselecteddemo";, when( localVarInt ( ui_qol ) == 1 ); ) - CHOICE_BUTTON_VIS( 2, "Delete", ;, when( localVarInt ( ui_qol ) == 1 ); ) - CHOICE_BUTTON_VIS( 3, "Rename", ;, when( localVarInt ( ui_qol ) == 1 ); ) + CHOICE_BUTTON_VIS( 1, "Play", exec "playselecteddemo";, when( localVarInt ( ui_qol ) == 1 && dvarbool( qol_show_demos_buttons ) ); ) + CHOICE_BUTTON_VIS( 2, "Delete", setdvar qol_dialog 2; open quit_popmenu;, when( localVarInt ( ui_qol ) == 1 && dvarbool( qol_show_demos_buttons )); ) + CHOICE_BUTTON_VIS( 3, "Rename", setdvar qol_dialog 3; exec "getdemoname"; open quit_popmenu;, when( localVarInt ( ui_qol ) == 1 && dvarbool( qol_show_demos_buttons )); ) } } \ No newline at end of file