From 1b47cf76d3801676d6266fee960b31f3acf234fc Mon Sep 17 00:00:00 2001 From: DavivaD Date: Thu, 2 Aug 2018 07:38:32 +0200 Subject: [PATCH 1/6] Implement Mod Manager --- src/CMakeLists.txt | 2 + src/app/app.cpp | 20 ++ src/app/app.h | 2 + src/app/pathman.cpp | 23 ++- src/app/pathman.h | 1 + src/common/event.cpp | 8 + src/common/event.h | 8 + src/common/restext.cpp | 8 + src/common/restext.h | 3 + src/graphics/engine/engine.h | 8 +- src/graphics/engine/text.cpp | 2 + src/level/robotmain.cpp | 1 + src/level/robotmain.h | 1 + src/ui/mainui.cpp | 7 +- src/ui/mainui.h | 2 + src/ui/screen/screen_setup.cpp | 24 ++- src/ui/screen/screen_setup_mods.cpp | 281 ++++++++++++++++++++++++++++ src/ui/screen/screen_setup_mods.h | 50 +++++ 18 files changed, 444 insertions(+), 7 deletions(-) create mode 100644 src/ui/screen/screen_setup_mods.cpp create mode 100644 src/ui/screen/screen_setup_mods.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c58172bd..1dd6edb1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -570,6 +570,8 @@ set(BASE_SOURCES ui/screen/screen_setup_game.h ui/screen/screen_setup_graphics.cpp ui/screen/screen_setup_graphics.h + ui/screen/screen_setup_mods.cpp + ui/screen/screen_setup_mods.h ui/screen/screen_setup_sound.cpp ui/screen/screen_setup_sound.h ui/screen/screen_welcome.cpp diff --git a/src/app/app.cpp b/src/app/app.cpp index 3444481c..ff8df246 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -699,6 +699,26 @@ bool CApplication::Create() return true; } +void CApplication::Reload() +{ + m_sound->Create(); + m_engine->ReloadAllTextures(); + CThread musicLoadThread([this]() + { + SystemTimeStamp* musicLoadStart = m_systemUtils->CreateTimeStamp(); + m_systemUtils->GetCurrentTimeStamp(musicLoadStart); + m_sound->CacheAll(); + SystemTimeStamp* musicLoadEnd = m_systemUtils->CreateTimeStamp(); + m_systemUtils->GetCurrentTimeStamp(musicLoadEnd); + float musicLoadTime = m_systemUtils->TimeStampDiff(musicLoadStart, musicLoadEnd, STU_MSEC); + GetLogger()->Debug("Sound loading took %.2f ms\n", musicLoadTime); + }, + "Sound loading thread"); + musicLoadThread.Start(); + m_controller->GetRobotMain()->UpdateCustomLevelList(); +} + + bool CApplication::CreateVideoSurface() { Uint32 videoFlags = SDL_WINDOW_OPENGL; diff --git a/src/app/app.h b/src/app/app.h index ccae3a5c..2a7cc67d 100644 --- a/src/app/app.h +++ b/src/app/app.h @@ -168,6 +168,8 @@ public: ParseArgsStatus ParseArguments(int argc, char *argv[]); //! Initializes the application bool Create(); + //! Reloads the application + void Reload(); //! Main event loop int Run(); //! Returns the code to be returned at main() exit diff --git a/src/app/pathman.cpp b/src/app/pathman.cpp index 60715ac1..26eebdf8 100644 --- a/src/app/pathman.cpp +++ b/src/app/pathman.cpp @@ -72,7 +72,28 @@ void CPathManager::AddModAutoloadDir(const std::string &modAutoloadDirPath) void CPathManager::AddMod(const std::string &modPath) { - m_mods.push_back(modPath); + std::string::size_type ON; + ON = modPath.find('~'); + if (ON == std::string::npos) + { + GetLogger()->Info("Loading mod: '%s'\n", modPath.c_str()); + m_mods.push_back(modPath); + } + else + { + GetLogger()->Info("Found Excluded mod: '%s'\n", modPath.c_str()); + } +} + +void CPathManager::RemoveMod(const std::string &modPath) +{ + std::string::size_type ON; + ON = modPath.find('~'); + if (ON == std::string::npos) + { + GetLogger()->Info("Unloading mod: '%s'\n", modPath.c_str()); + CResourceManager::RemoveLocation(modPath); + } } const std::string& CPathManager::GetDataPath() diff --git a/src/app/pathman.h b/src/app/pathman.h index dd18d66e..66dcae59 100644 --- a/src/app/pathman.h +++ b/src/app/pathman.h @@ -39,6 +39,7 @@ public: void SetSavePath(const std::string &savePath); void AddModAutoloadDir(const std::string &modAutoloadDirPath); void AddMod(const std::string &modPath); + void RemoveMod(const std::string &modPath); const std::string& GetDataPath(); const std::string& GetLangPath(); diff --git a/src/common/event.cpp b/src/common/event.cpp index 8dded9e1..7ceea30e 100644 --- a/src/common/event.cpp +++ b/src/common/event.cpp @@ -196,6 +196,7 @@ void InitializeEventTypeTexts() EVENT_TYPE_TEXT[EVENT_INTERFACE_SETUPp] = "EVENT_INTERFACE_SETUPp"; EVENT_TYPE_TEXT[EVENT_INTERFACE_SETUPc] = "EVENT_INTERFACE_SETUPc"; EVENT_TYPE_TEXT[EVENT_INTERFACE_SETUPs] = "EVENT_INTERFACE_SETUPs"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_SETUPm] = "EVENT_INTERFACE_SETUPm"; EVENT_TYPE_TEXT[EVENT_INTERFACE_DEVICE] = "EVENT_INTERFACE_DEVICE"; EVENT_TYPE_TEXT[EVENT_INTERFACE_RESOL] = "EVENT_INTERFACE_RESOL"; @@ -265,6 +266,13 @@ void InitializeEventTypeTexts() EVENT_TYPE_TEXT[EVENT_INTERFACE_JOYSTICK_CAM_Y_INVERT]= "EVENT_INTERFACE_JOYSTICK_CAM_Y_INVERT"; EVENT_TYPE_TEXT[EVENT_INTERFACE_JOYSTICK_CAM_Z_INVERT]= "EVENT_INTERFACE_JOYSTICK_CAM_Z_INVERT"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_MODS_UNLOADED] = "EVENT_INTERFACE_MODS_UNLOADED"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_MODS_LOADED] = "EVENT_INTERFACE_MODS_LOADED"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_WORKSHOP] = "EVENT_INTERFACE_WORKSHOP"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_MODS_DIR] = "EVENT_INTERFACE_MODS_DIR"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_LOAD] = "EVENT_INTERFACE_LOAD"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_UNLOAD] = "EVENT_INTERFACE_UNLOAD"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_GLINTl] = "EVENT_INTERFACE_GLINTl"; EVENT_TYPE_TEXT[EVENT_INTERFACE_GLINTr] = "EVENT_INTERFACE_GLINTr"; EVENT_TYPE_TEXT[EVENT_INTERFACE_GLINTu] = "EVENT_INTERFACE_GLINTu"; diff --git a/src/common/event.h b/src/common/event.h index 64c52e41..faabfd9f 100644 --- a/src/common/event.h +++ b/src/common/event.h @@ -231,6 +231,7 @@ enum EventType EVENT_INTERFACE_SETUPp = 432, EVENT_INTERFACE_SETUPc = 433, EVENT_INTERFACE_SETUPs = 434, + EVENT_INTERFACE_SETUPm = 435, EVENT_INTERFACE_DEVICE = 440, EVENT_INTERFACE_RESOL = 441, @@ -304,6 +305,13 @@ enum EventType EVENT_INTERFACE_JOYSTICK_CAM_Y_INVERT = 573, EVENT_INTERFACE_JOYSTICK_CAM_Z_INVERT = 574, + EVENT_INTERFACE_MODS_UNLOADED = 580, + EVENT_INTERFACE_MODS_LOADED = 581, + EVENT_INTERFACE_WORKSHOP = 582, + EVENT_INTERFACE_MODS_DIR = 583, + EVENT_INTERFACE_LOAD = 584, + EVENT_INTERFACE_UNLOAD = 585, + EVENT_INTERFACE_GLINTl = 590, EVENT_INTERFACE_GLINTr = 591, EVENT_INTERFACE_GLINTu = 592, diff --git a/src/common/restext.cpp b/src/common/restext.cpp index 9bac8434..ac664d58 100644 --- a/src/common/restext.cpp +++ b/src/common/restext.cpp @@ -89,6 +89,9 @@ void InitializeRestext() stringsText[RT_SETUP_KEY1] = TR("1) First click on the key you want to redefine."); stringsText[RT_SETUP_KEY2] = TR("2) Then press the key you want to use instead."); + stringsText[RT_MODS_UNLOADED] = TR("Unloaded Mods:"); + stringsText[RT_MODS_LOADED] = TR("Loaded Mods:"); + stringsText[RT_PERSO_FACE] = TR("Face type:"); stringsText[RT_PERSO_GLASSES] = TR("Eyeglasses:"); stringsText[RT_PERSO_HAIR] = TR("Hair color:"); @@ -176,11 +179,16 @@ void InitializeRestext() stringsEvent[EVENT_INTERFACE_QUIT] = TR("Quit\\Quit Colobot: Gold Edition"); stringsEvent[EVENT_INTERFACE_BACK] = TR("<< Back \\Back to the previous screen"); stringsEvent[EVENT_INTERFACE_PLAY] = TR("Play\\Start mission!"); + stringsEvent[EVENT_INTERFACE_WORKSHOP] = TR("Workshop\\Open Workshop to search Mods"); + stringsEvent[EVENT_INTERFACE_MODS_DIR] = TR("Open Directory\\Open Mods directory"); + stringsEvent[EVENT_INTERFACE_LOAD] = TR("Load\\Load Mod"); + stringsEvent[EVENT_INTERFACE_UNLOAD] = TR("Unload\\Unload Mod"); stringsEvent[EVENT_INTERFACE_SETUPd] = TR("Device\\Driver and resolution settings"); stringsEvent[EVENT_INTERFACE_SETUPg] = TR("Graphics\\Graphics settings"); stringsEvent[EVENT_INTERFACE_SETUPp] = TR("Game\\Game settings"); stringsEvent[EVENT_INTERFACE_SETUPc] = TR("Controls\\Keyboard, joystick and mouse settings"); stringsEvent[EVENT_INTERFACE_SETUPs] = TR("Sound\\Music and game sound volume"); + stringsEvent[EVENT_INTERFACE_SETUPm] = TR("Mods\\Manage installed mods"); stringsEvent[EVENT_INTERFACE_DEVICE] = TR("Unit"); stringsEvent[EVENT_INTERFACE_RESOL] = TR("Resolution"); stringsEvent[EVENT_INTERFACE_FULL] = TR("Full screen\\Full screen or window mode"); diff --git a/src/common/restext.h b/src/common/restext.h index 6acfb610..81cff850 100644 --- a/src/common/restext.h +++ b/src/common/restext.h @@ -86,6 +86,9 @@ enum ResTextType RT_SETUP_KEY1 = 82, RT_SETUP_KEY2 = 83, + RT_MODS_UNLOADED = 85, + RT_MODS_LOADED = 86, + RT_PERSO_FACE = 90, RT_PERSO_GLASSES = 91, RT_PERSO_HAIR = 92, diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index 794bd9e8..10fa04f4 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -1182,6 +1182,10 @@ public: void EnablePauseBlur(); void DisablePauseBlur(); + //! Reloads all textures + /** This additionally sends EVENT_RELOAD_TEXTURES to reload all textures not maintained by CEngine **/ + void ReloadAllTextures(); + protected: //! Resets some states and flushes textures after device was changed (e.g. resoulution changed) /** Instead of calling this directly, send EVENT_RESOLUTION_CHANGED event **/ @@ -1280,10 +1284,6 @@ protected: }; static void WriteScreenShotThread(std::unique_ptr data); - //! Reloads all textures - /** This additionally sends EVENT_RELOAD_TEXTURES to reload all textures not maintained by CEngine **/ - void ReloadAllTextures(); - protected: CApplication* m_app; CSystemUtils* m_systemUtils; diff --git a/src/graphics/engine/text.cpp b/src/graphics/engine/text.cpp index a16439f4..c930db8e 100644 --- a/src/graphics/engine/text.cpp +++ b/src/graphics/engine/text.cpp @@ -261,6 +261,8 @@ void CText::FlushCache() m_lastCachedFont = nullptr; m_lastFontType = FONT_COMMON; m_lastFontSize = 0; + + Create(); } int CText::GetTabSize() diff --git a/src/level/robotmain.cpp b/src/level/robotmain.cpp index 3bf3e2d5..14e26f9e 100644 --- a/src/level/robotmain.cpp +++ b/src/level/robotmain.cpp @@ -321,6 +321,7 @@ std::string PhaseToString(Phase phase) if (phase == PHASE_SETUPp) return "PHASE_SETUPp"; if (phase == PHASE_SETUPc) return "PHASE_SETUPc"; if (phase == PHASE_SETUPs) return "PHASE_SETUPs"; + if (phase == PHASE_SETUPm) return "PHASE_SETUPm"; if (phase == PHASE_SETUPds) return "PHASE_SETUPds"; if (phase == PHASE_SETUPgs) return "PHASE_SETUPgs"; if (phase == PHASE_SETUPps) return "PHASE_SETUPps"; diff --git a/src/level/robotmain.h b/src/level/robotmain.h index 2614f2cc..68768beb 100644 --- a/src/level/robotmain.h +++ b/src/level/robotmain.h @@ -61,6 +61,7 @@ enum Phase PHASE_SETUPp, PHASE_SETUPc, PHASE_SETUPs, + PHASE_SETUPm, PHASE_SETUPds, PHASE_SETUPgs, PHASE_SETUPps, diff --git a/src/ui/mainui.cpp b/src/ui/mainui.cpp index 2ffb17fe..7e63a7db 100644 --- a/src/ui/mainui.cpp +++ b/src/ui/mainui.cpp @@ -53,6 +53,7 @@ #include "ui/screen/screen_setup_display.h" #include "ui/screen/screen_setup_game.h" #include "ui/screen/screen_setup_graphics.h" +#include "ui/screen/screen_setup_mods.h" #include "ui/screen/screen_setup_sound.h" #include "ui/screen/screen_welcome.h" @@ -82,6 +83,7 @@ CMainUserInterface::CMainUserInterface() m_screenSetupDisplay = MakeUnique(); m_screenSetupGame = MakeUnique(); m_screenSetupGraphics = MakeUnique(); + m_screenSetupMods = MakeUnique(); m_screenSetupSound = MakeUnique(); m_screenMainMenu = MakeUnique(); m_screenPlayerSelect = MakeUnique(m_dialog.get()); @@ -142,6 +144,7 @@ CScreenSetup* CMainUserInterface::GetSetupScreen(Phase phase) if(phase == PHASE_SETUPp) return m_screenSetupGame.get(); if(phase == PHASE_SETUPc) return m_screenSetupControls.get(); if(phase == PHASE_SETUPs) return m_screenSetupSound.get(); + if(phase == PHASE_SETUPm) return m_screenSetupMods.get(); assert(false); return nullptr; } @@ -182,7 +185,7 @@ void CMainUserInterface::ChangePhase(Phase phase) m_screenLevelList->SetLevelCategory(m_main->GetLevelCategory()); m_currentScreen = m_screenLevelList.get(); } - if (m_phase >= PHASE_SETUPd && m_phase <= PHASE_SETUPs) + if (m_phase >= PHASE_SETUPd && m_phase <= PHASE_SETUPm) { CScreenSetup* screenSetup = GetSetupScreen(m_phase); screenSetup->SetInSimulation(false); @@ -345,6 +348,7 @@ void CMainUserInterface::GlintMove() m_phase == PHASE_SETUPp || m_phase == PHASE_SETUPc || m_phase == PHASE_SETUPs || + m_phase == PHASE_SETUPm || m_phase == PHASE_SETUPds || m_phase == PHASE_SETUPgs || m_phase == PHASE_SETUPps || @@ -534,6 +538,7 @@ void CMainUserInterface::FrameParticle(float rTime) m_phase == PHASE_SETUPp || m_phase == PHASE_SETUPc || m_phase == PHASE_SETUPs || + m_phase == PHASE_SETUPm || m_phase == PHASE_READ ) { pParti = partiPosBig; diff --git a/src/ui/mainui.h b/src/ui/mainui.h index 77074492..0d3ce91e 100644 --- a/src/ui/mainui.h +++ b/src/ui/mainui.h @@ -55,6 +55,7 @@ class CScreenSetupControls; class CScreenSetupDisplay; class CScreenSetupGame; class CScreenSetupGraphics; +class CScreenSetupMods; class CScreenSetupSound; class CScreenWelcome; @@ -119,6 +120,7 @@ protected: std::unique_ptr m_screenSetupDisplay; std::unique_ptr m_screenSetupGame; std::unique_ptr m_screenSetupGraphics; + std::unique_ptr m_screenSetupMods; std::unique_ptr m_screenSetupSound; std::unique_ptr m_screenWelcome; diff --git a/src/ui/screen/screen_setup.cpp b/src/ui/screen/screen_setup.cpp index 823207af..e9c36a71 100644 --- a/src/ui/screen/screen_setup.cpp +++ b/src/ui/screen/screen_setup.cpp @@ -83,7 +83,7 @@ void CScreenSetup::CreateInterface() ddim.y = 0.05f; pw->CreateGroup(pos, ddim, 3, EVENT_NULL); // transparent -> gray - ddim.x = 0.78f/5-0.01f; + ddim.x = 0.65f/5-0.01f; ddim.y = 0.06f; pos.x = 0.115f; pos.y = 0.76f; @@ -116,6 +116,12 @@ void CScreenSetup::CreateInterface() pb->SetState(STATE_CARD); pb->SetState(STATE_CHECK, (m_tab == PHASE_SETUPs)); + pos.x += ddim.x+0.01f; + pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_SETUPm); + pb->SetState(STATE_SHADOW); + pb->SetState(STATE_CARD); + pb->SetState(STATE_CHECK, (m_tab == PHASE_SETUPm)); + pos.x = 0.10f; ddim.x = 0.80f; pos.y = 0.34f; @@ -148,6 +154,10 @@ bool CScreenSetup::EventProcess(const Event &event) CWindow* pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); if ( pw == nullptr ) return false; + CButton* pb = static_cast(pw->SearchControl(EVENT_INTERFACE_SETUPm)); + if ( pb == nullptr ) return false; + pb->SetState(STATE_ENABLE); + if ( event.type == pw->GetEventTypeClose() || event.type == EVENT_INTERFACE_BACK || (event.type == EVENT_KEY_DOWN && event.GetData()->key == KEY(ESCAPE)) ) @@ -179,6 +189,10 @@ bool CScreenSetup::EventProcess(const Event &event) m_main->ChangePhase(PHASE_SETUPs); return false; + case EVENT_INTERFACE_SETUPm: + m_main->ChangePhase(PHASE_SETUPm); + return false; + default: break; } @@ -188,6 +202,10 @@ bool CScreenSetup::EventProcess(const Event &event) CWindow* pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); if ( pw == nullptr ) return false; + CButton* pb = static_cast(pw->SearchControl(EVENT_INTERFACE_SETUPm)); + if ( pb == nullptr ) return false; + pb->ClearState(STATE_ENABLE); + if ( event.type == pw->GetEventTypeClose() || event.type == EVENT_INTERFACE_BACK || (event.type == EVENT_KEY_DOWN && event.GetData()->key == KEY(ESCAPE)) ) @@ -221,6 +239,10 @@ bool CScreenSetup::EventProcess(const Event &event) m_main->ChangePhase(PHASE_SETUPss); return false; + case EVENT_INTERFACE_SETUPm: + m_main->ChangePhase(PHASE_SETUPm); + return false; + default: break; } diff --git a/src/ui/screen/screen_setup_mods.cpp b/src/ui/screen/screen_setup_mods.cpp new file mode 100644 index 00000000..960d7e21 --- /dev/null +++ b/src/ui/screen/screen_setup_mods.cpp @@ -0,0 +1,281 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 this program. If not, see http://gnu.org/licenses + */ + +#include "ui/screen/screen_setup_mods.h" + +#include "app/app.h" +#include "app/pathman.h" + +#include "common/restext.h" +#include "common/config.h" +#include "common/logger.h" +#include "common/settings.h" + +#include "common/resources/resourcemanager.h" +#include "level/parser/parser.h" + +#include "ui/controls/button.h" +#include "ui/controls/edit.h" +#include "ui/controls/interface.h" +#include "ui/controls/label.h" +#include "ui/controls/list.h" +#include "ui/controls/window.h" + +#include +#include + +namespace Ui +{ + +CScreenSetupMods::CScreenSetupMods() +{ +} + +void CScreenSetupMods::SetActive() +{ + m_tab = PHASE_SETUPm; +} + +void CScreenSetupMods::CreateInterface() +{ + CWindow* pw; + CLabel* pl; + CButton* pb; + CList* pli; + Math::Point pos, ddim; + std::string name; + + CScreenSetup::CreateInterface(); + pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); + if ( pw == nullptr ) return; + + // Displays a list of unloaded mods: + pos.x = ox+sx*3; + pos.y = oy+sy*9; + ddim.x = dim.x*6; + ddim.y = dim.y*1; + GetResource(RES_TEXT, RT_MODS_UNLOADED, name); + pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL11, name); + pl->SetTextAlign(Gfx::TEXT_ALIGN_LEFT); + + pos.y = oy+sy*3.75f; + ddim.x = dim.x*6.5f; + ddim.y = dim.y*6.05f; + pli = pw->CreateList(pos, ddim, 0, EVENT_INTERFACE_MODS_UNLOADED); + pli->SetState(STATE_SHADOW); + UpdateUnloadedModList(); + + // Displays a list of loaded mods: + pos.x = ox+sx*9.5f; + pos.y = oy+sy*9; + ddim.x = dim.x*6; + ddim.y = dim.y*1; + GetResource(RES_TEXT, RT_MODS_LOADED, name); + pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL12, name); + pl->SetTextAlign(Gfx::TEXT_ALIGN_LEFT); + + pos.y = oy+sy*3.75f; + ddim.x = dim.x*6.5f; + ddim.y = dim.y*6.05f; + pli = pw->CreateList(pos, ddim, 0, EVENT_INTERFACE_MODS_LOADED); + pli->SetState(STATE_SHADOW); + UpdateLoadedModList(); + + pos = pli->GetPos(); + ddim = pli->GetDim(); + pos.x = ox+sx*8.2f; + pos.y = oy+sy*2; + ddim.x = dim.x*1; + ddim.y = dim.y*1; + pb = pw->CreateButton(pos, ddim, 40, EVENT_INTERFACE_WORKSHOP); + pb->SetState(STATE_SHADOW); + + pos.x += dim.x*1.3f; + pb = pw->CreateButton(pos, ddim, 57, EVENT_INTERFACE_MODS_DIR); + pb->SetState(STATE_SHADOW); + + pos.x += dim.x*1.3f; + ddim.x = dim.x*2.5f; + pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_LOAD); + pb->SetState(STATE_SHADOW); + pb->ClearState(STATE_ENABLE); + + pos.x += dim.x*2.8f; + pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_UNLOAD); + pb->SetState(STATE_SHADOW); + pb->ClearState(STATE_ENABLE); +} +bool CScreenSetupMods::EventProcess(const Event &event) +{ + CWindow* pw; + CButton* pb; + CList* pl; + int result; + std::string modName, modPath, modPathRaw, OFF = "~"; + + if (!CScreenSetup::EventProcess(event)) return false; + + pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); + if ( pw == nullptr ) return false; + + if (event.type == EVENT_INTERFACE_LOAD) + { + pl = static_cast(pw->SearchControl(EVENT_INTERFACE_MODS_UNLOADED)); + if ( pl == nullptr ) return false; + modName = pl->GetItemName(pl->GetSelect()); + + modPathRaw = CResourceManager::GetSaveLocation() + "/" + "mods" + "/"; + modPath = modPathRaw.c_str(); + boost::filesystem::rename(modPath+OFF+modName, modPath+modName); + m_pathManager->AddMod(modPath+modName); + m_app->Reload(); + m_main->ChangePhase(PHASE_SETUPm); + } + if (event.type == EVENT_INTERFACE_UNLOAD) + { + pl = static_cast(pw->SearchControl(EVENT_INTERFACE_MODS_LOADED)); + if ( pl == nullptr ) return false; + modName = pl->GetItemName(pl->GetSelect()); + + modPathRaw = CResourceManager::GetSaveLocation() + "/" + "mods" + "/"; + modPath = modPathRaw.c_str(); + m_pathManager->RemoveMod(modPath+modName); + boost::filesystem::rename(modPath+modName, modPath+OFF+modName); + m_app->Reload(); + m_main->ChangePhase(PHASE_SETUPm); + } + if (event.type == EVENT_INTERFACE_MODS_DIR) + { + modPathRaw = CResourceManager::GetSaveLocation() + "/" + "mods"; + #if defined(PLATFORM_WINDOWS) + result = system(("start \""+modPathRaw+"\"").c_str()); + #elif defined(PLATFORM_LINUX) + result = system(("xdg-open \""+modPathRaw+"\"").c_str()); + #elif defined(PLATFORM_MACOSX) + result = system(("open \""+modPathRaw+"\"").c_str()); + #endif + if (result == -1) + { + GetLogger()->Error("Failed to open Mods directory! Does directory exists?\n"); + } + } + switch (event.type) + { + case EVENT_INTERFACE_MODS_UNLOADED: + pl = static_cast(pw->SearchControl(EVENT_INTERFACE_MODS_LOADED)); + if ( pl == nullptr ) break; + + pb = static_cast(pw->SearchControl(EVENT_INTERFACE_UNLOAD)); + if ( pb == nullptr ) break; + pl->SetSelect(-1); + pb->ClearState(STATE_ENABLE); + + pb = static_cast(pw->SearchControl(EVENT_INTERFACE_LOAD)); + if ( pb == nullptr ) break; + pb->SetState(STATE_ENABLE); + break; + + case EVENT_INTERFACE_MODS_LOADED: + pl = static_cast(pw->SearchControl(EVENT_INTERFACE_MODS_UNLOADED)); + if ( pl == nullptr ) break; + + pb = static_cast(pw->SearchControl(EVENT_INTERFACE_LOAD)); + if ( pb == nullptr ) break; + pl->SetSelect(-1); + pb->ClearState(STATE_ENABLE); + + pb = static_cast(pw->SearchControl(EVENT_INTERFACE_UNLOAD)); + if ( pb == nullptr ) break; + pb->SetState(STATE_ENABLE); + break; + + case EVENT_INTERFACE_WORKSHOP: + #if defined(PLATFORM_WINDOWS) + result = system("start \"https://colobot.info/forum/forumdisplay.php?fid=60\""); + #elif defined(PLATFORM_LINUX) + result = system("xdg-open \"https://colobot.info/forum/forumdisplay.php?fid=60\""); + #elif defined(PLATFORM_MACOSX) + result = system("open \"https://colobot.info/forum/forumdisplay.php?fid=60\""); + #endif + if (result == -1) + { + GetLogger()->Error("Failed to open Workshop page! Is any Web Broswer installed?\n"); + } + break; + default: + return true; + } + return false; +} +void CScreenSetupMods::UpdateUnloadedModList() +{ + CWindow* pw; + CList* pl; + int i = 0; + std::string modName; + + pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); + if ( pw == nullptr ) return; + + pl = static_cast(pw->SearchControl(EVENT_INTERFACE_MODS_UNLOADED)); + if ( pl == nullptr ) return; + pl->Flush(); + + auto modsDir = CResourceManager::ListDirectories("mods/"); + std::sort(modsDir.begin(), modsDir.end()); + + for(auto const& modNameRaw : modsDir) + { + modName = modNameRaw; + std::string::size_type ON; + ON = modName.find('~'); + if (ON != std::string::npos) + { + modName.erase(0,1); + pl->SetItemName(i++, modName); + } + } + pl->ShowSelect(false); // shows the selected columns +} +void CScreenSetupMods::UpdateLoadedModList() +{ + CWindow* pw; + CList* pl; + int i = 0; + + pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); + if ( pw == nullptr ) return; + + pl = static_cast(pw->SearchControl(EVENT_INTERFACE_MODS_LOADED)); + if ( pl == nullptr ) return; + pl->Flush(); + + auto modsDir = CResourceManager::ListDirectories("mods/"); + std::sort(modsDir.begin(), modsDir.end()); + + for(auto const &modName : modsDir) + { + std::string::size_type ON; + ON = modName.find('~'); + if (ON == std::string::npos) + pl->SetItemName(i++, modName); + } + pl->ShowSelect(false); // shows the selected columns +} +} // namespace Ui diff --git a/src/ui/screen/screen_setup_mods.h b/src/ui/screen/screen_setup_mods.h new file mode 100644 index 00000000..0d54502f --- /dev/null +++ b/src/ui/screen/screen_setup_mods.h @@ -0,0 +1,50 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 this program. If not, see http://gnu.org/licenses + */ + +#pragma once + +#include "ui/screen/screen_setup.h" + +#include + +class CPathManager; + +namespace Ui +{ + +class CScreenSetupMods : public CScreenSetup +{ +public: + CScreenSetupMods(); + void SetActive() override; + + void CreateInterface() override; + bool EventProcess(const Event &event) override; + +protected: + void UpdateUnloadedModList(); + void UpdateLoadedModList(); + +protected: + CPathManager* m_pathManager; + std::vector m_unloadedModList; + std::vector m_loadedModList; +}; + +} // namespace Ui From e823c209faf2084dca8aacc73d8b223b955f27f9 Mon Sep 17 00:00:00 2001 From: DavivaD Date: Thu, 2 Aug 2018 17:21:31 +0200 Subject: [PATCH 2/6] Fix crash while loading mod and blank settings menu while paused game --- src/app/pathman.cpp | 30 ++++++++++++++++++++++++------ src/level/robotmain.cpp | 4 +++- src/level/robotmain.h | 1 + src/ui/maindialog.cpp | 1 + src/ui/mainui.cpp | 2 +- src/ui/screen/screen_setup.cpp | 1 - 6 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/app/pathman.cpp b/src/app/pathman.cpp index 26eebdf8..9656d3eb 100644 --- a/src/app/pathman.cpp +++ b/src/app/pathman.cpp @@ -77,11 +77,11 @@ void CPathManager::AddMod(const std::string &modPath) if (ON == std::string::npos) { GetLogger()->Info("Loading mod: '%s'\n", modPath.c_str()); - m_mods.push_back(modPath); + CResourceManager::AddLocation(modPath, true); } else { - GetLogger()->Info("Found Excluded mod: '%s'\n", modPath.c_str()); + GetLogger()->Info("Found excluded mod: '%s'\n", modPath.c_str()); } } @@ -171,15 +171,33 @@ void CPathManager::InitPaths() GetLogger()->Trace("Searching for mods in '%s'...\n", modAutoloadDir.c_str()); for (const std::string& modPath : FindModsInDir(modAutoloadDir)) { - GetLogger()->Info("Autoloading mod: '%s'\n", modPath.c_str()); - CResourceManager::AddLocation(modPath); + std::string::size_type ON; + ON = modPath.find('~'); + if (ON == std::string::npos) + { + GetLogger()->Info("Autoloading mod: '%s'\n", modPath.c_str()); + CResourceManager::AddLocation(modPath); + } + else + { + GetLogger()->Info("Found excluded mod: '%s'\n", modPath.c_str()); + } } } for (const std::string& modPath : m_mods) { - GetLogger()->Info("Loading mod: '%s'\n", modPath.c_str()); - CResourceManager::AddLocation(modPath); + std::string::size_type ON; + ON = modPath.find('~'); + if (ON == std::string::npos) + { + GetLogger()->Info("Loading mod: '%s'\n", modPath.c_str()); + CResourceManager::AddLocation(modPath); + } + else + { + GetLogger()->Info("Found excluded mod: '%s'\n", modPath.c_str()); + } } CResourceManager::SetSaveLocation(m_savePath); diff --git a/src/level/robotmain.cpp b/src/level/robotmain.cpp index 14e26f9e..14397feb 100644 --- a/src/level/robotmain.cpp +++ b/src/level/robotmain.cpp @@ -327,6 +327,7 @@ std::string PhaseToString(Phase phase) if (phase == PHASE_SETUPps) return "PHASE_SETUPps"; if (phase == PHASE_SETUPcs) return "PHASE_SETUPcs"; if (phase == PHASE_SETUPss) return "PHASE_SETUPss"; + if (phase == PHASE_SETUPms) return "PHASE_SETUPms"; if (phase == PHASE_WRITEs) return "PHASE_WRITEs"; if (phase == PHASE_READ) return "PHASE_READ"; if (phase == PHASE_READs) return "PHASE_READs"; @@ -339,7 +340,7 @@ std::string PhaseToString(Phase phase) bool IsInSimulationConfigPhase(Phase phase) { - return (phase >= PHASE_SETUPds && phase <= PHASE_SETUPss) || phase == PHASE_READs || phase == PHASE_WRITEs; + return (phase >= PHASE_SETUPds && phase <= PHASE_SETUPms) || phase == PHASE_READs || phase == PHASE_WRITEs; } bool IsPhaseWithWorld(Phase phase) @@ -3865,6 +3866,7 @@ void CRobotMain::ChangeColor() m_phase != PHASE_SETUPps && m_phase != PHASE_SETUPcs && m_phase != PHASE_SETUPss && + m_phase != PHASE_SETUPms && m_phase != PHASE_WIN && m_phase != PHASE_LOST && m_phase != PHASE_APPERANCE ) return; diff --git a/src/level/robotmain.h b/src/level/robotmain.h index 68768beb..cd3345e4 100644 --- a/src/level/robotmain.h +++ b/src/level/robotmain.h @@ -67,6 +67,7 @@ enum Phase PHASE_SETUPps, PHASE_SETUPcs, PHASE_SETUPss, + PHASE_SETUPms, PHASE_WRITEs, PHASE_READ, PHASE_READs, diff --git a/src/ui/maindialog.cpp b/src/ui/maindialog.cpp index 01d87dc2..395a875e 100644 --- a/src/ui/maindialog.cpp +++ b/src/ui/maindialog.cpp @@ -107,6 +107,7 @@ bool CMainDialog::EventProcess(const Event &event) if ( CScreenSetup::GetTab() == PHASE_SETUPp ) m_main->ChangePhase(PHASE_SETUPps); if ( CScreenSetup::GetTab() == PHASE_SETUPc ) m_main->ChangePhase(PHASE_SETUPcs); if ( CScreenSetup::GetTab() == PHASE_SETUPs ) m_main->ChangePhase(PHASE_SETUPss); + if ( CScreenSetup::GetTab() == PHASE_SETUPm ) m_main->ChangePhase(PHASE_SETUPss); } if ( pressedButton == EVENT_INTERFACE_WRITE ) diff --git a/src/ui/mainui.cpp b/src/ui/mainui.cpp index 7e63a7db..1ca364bc 100644 --- a/src/ui/mainui.cpp +++ b/src/ui/mainui.cpp @@ -192,7 +192,7 @@ void CMainUserInterface::ChangePhase(Phase phase) screenSetup->SetActive(); m_currentScreen = screenSetup; } - if (m_phase >= PHASE_SETUPds && m_phase <= PHASE_SETUPss) + if (m_phase >= PHASE_SETUPds && m_phase <= PHASE_SETUPms) { CScreenSetup* screenSetup = GetSetupScreen(static_cast(m_phase - PHASE_SETUPds + PHASE_SETUPd)); screenSetup->SetInSimulation(true); diff --git a/src/ui/screen/screen_setup.cpp b/src/ui/screen/screen_setup.cpp index e9c36a71..3dbc0836 100644 --- a/src/ui/screen/screen_setup.cpp +++ b/src/ui/screen/screen_setup.cpp @@ -240,7 +240,6 @@ bool CScreenSetup::EventProcess(const Event &event) return false; case EVENT_INTERFACE_SETUPm: - m_main->ChangePhase(PHASE_SETUPm); return false; default: From cd140f13841f468ff375cf23c54ae6447d8f2aaa Mon Sep 17 00:00:00 2001 From: DavivaD Date: Sat, 27 Jul 2019 03:36:03 +0200 Subject: [PATCH 3/6] Move mod loading/unloading stuff to a new class + fix some derps --- src/app/pathman.cpp | 40 +++++++++--------- src/ui/screen/screen_setup.cpp | 2 +- src/ui/screen/screen_setup_mods.cpp | 64 ++++++++++++++++++----------- src/ui/screen/screen_setup_mods.h | 4 +- 4 files changed, 65 insertions(+), 45 deletions(-) diff --git a/src/app/pathman.cpp b/src/app/pathman.cpp index 9656d3eb..11776d19 100644 --- a/src/app/pathman.cpp +++ b/src/app/pathman.cpp @@ -72,9 +72,9 @@ void CPathManager::AddModAutoloadDir(const std::string &modAutoloadDirPath) void CPathManager::AddMod(const std::string &modPath) { - std::string::size_type ON; - ON = modPath.find('~'); - if (ON == std::string::npos) + std::string::size_type enabled; + enabled = modPath.find('~'); + if (enabled == std::string::npos) { GetLogger()->Info("Loading mod: '%s'\n", modPath.c_str()); CResourceManager::AddLocation(modPath, true); @@ -87,9 +87,9 @@ void CPathManager::AddMod(const std::string &modPath) void CPathManager::RemoveMod(const std::string &modPath) { - std::string::size_type ON; - ON = modPath.find('~'); - if (ON == std::string::npos) + std::string::size_type enabled; + enabled = modPath.find('~'); + if (enabled == std::string::npos) { GetLogger()->Info("Unloading mod: '%s'\n", modPath.c_str()); CResourceManager::RemoveLocation(modPath); @@ -171,9 +171,9 @@ void CPathManager::InitPaths() GetLogger()->Trace("Searching for mods in '%s'...\n", modAutoloadDir.c_str()); for (const std::string& modPath : FindModsInDir(modAutoloadDir)) { - std::string::size_type ON; - ON = modPath.find('~'); - if (ON == std::string::npos) + std::string::size_type enabled; + enabled = modPath.find('~'); + if (enabled == std::string::npos) { GetLogger()->Info("Autoloading mod: '%s'\n", modPath.c_str()); CResourceManager::AddLocation(modPath); @@ -187,17 +187,17 @@ void CPathManager::InitPaths() for (const std::string& modPath : m_mods) { - std::string::size_type ON; - ON = modPath.find('~'); - if (ON == std::string::npos) - { - GetLogger()->Info("Loading mod: '%s'\n", modPath.c_str()); - CResourceManager::AddLocation(modPath); - } - else - { - GetLogger()->Info("Found excluded mod: '%s'\n", modPath.c_str()); - } + std::string::size_type enabled; + enabled = modPath.find('~'); + if (enabled == std::string::npos) + { + GetLogger()->Info("Loading mod: '%s'\n", modPath.c_str()); + CResourceManager::AddLocation(modPath); + } + else + { + GetLogger()->Info("Found excluded mod: '%s'\n", modPath.c_str()); + } } CResourceManager::SetSaveLocation(m_savePath); diff --git a/src/ui/screen/screen_setup.cpp b/src/ui/screen/screen_setup.cpp index 3dbc0836..66bdac20 100644 --- a/src/ui/screen/screen_setup.cpp +++ b/src/ui/screen/screen_setup.cpp @@ -240,7 +240,7 @@ bool CScreenSetup::EventProcess(const Event &event) return false; case EVENT_INTERFACE_SETUPm: - return false; + assert(false); // should never get here default: break; diff --git a/src/ui/screen/screen_setup_mods.cpp b/src/ui/screen/screen_setup_mods.cpp index 960d7e21..696e6a02 100644 --- a/src/ui/screen/screen_setup_mods.cpp +++ b/src/ui/screen/screen_setup_mods.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2019, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -127,7 +127,7 @@ bool CScreenSetupMods::EventProcess(const Event &event) CButton* pb; CList* pl; int result; - std::string modName, modPath, modPathRaw, OFF = "~"; + std::string modName, modPath; if (!CScreenSetup::EventProcess(event)) return false; @@ -139,11 +139,8 @@ bool CScreenSetupMods::EventProcess(const Event &event) pl = static_cast(pw->SearchControl(EVENT_INTERFACE_MODS_UNLOADED)); if ( pl == nullptr ) return false; modName = pl->GetItemName(pl->GetSelect()); + LoadMod(modName); - modPathRaw = CResourceManager::GetSaveLocation() + "/" + "mods" + "/"; - modPath = modPathRaw.c_str(); - boost::filesystem::rename(modPath+OFF+modName, modPath+modName); - m_pathManager->AddMod(modPath+modName); m_app->Reload(); m_main->ChangePhase(PHASE_SETUPm); } @@ -152,23 +149,21 @@ bool CScreenSetupMods::EventProcess(const Event &event) pl = static_cast(pw->SearchControl(EVENT_INTERFACE_MODS_LOADED)); if ( pl == nullptr ) return false; modName = pl->GetItemName(pl->GetSelect()); + UnloadMod(modName); - modPathRaw = CResourceManager::GetSaveLocation() + "/" + "mods" + "/"; - modPath = modPathRaw.c_str(); - m_pathManager->RemoveMod(modPath+modName); - boost::filesystem::rename(modPath+modName, modPath+OFF+modName); m_app->Reload(); m_main->ChangePhase(PHASE_SETUPm); } if (event.type == EVENT_INTERFACE_MODS_DIR) { - modPathRaw = CResourceManager::GetSaveLocation() + "/" + "mods"; + modPath = CResourceManager::GetSaveLocation() + "/" + "mods"; #if defined(PLATFORM_WINDOWS) - result = system(("start \""+modPathRaw+"\"").c_str()); + std::replace(modPath.begin(), modPath.end(), '/', '\\'); + result = system(("explorer \""+modPath+"\"").c_str()); #elif defined(PLATFORM_LINUX) - result = system(("xdg-open \""+modPathRaw+"\"").c_str()); + result = system(("xdg-open \""+modPath+"\"").c_str()); #elif defined(PLATFORM_MACOSX) - result = system(("open \""+modPathRaw+"\"").c_str()); + result = system(("open \""+modPath+"\"").c_str()); //TODO: Test on macOS #endif if (result == -1) { @@ -207,11 +202,11 @@ bool CScreenSetupMods::EventProcess(const Event &event) case EVENT_INTERFACE_WORKSHOP: #if defined(PLATFORM_WINDOWS) - result = system("start \"https://colobot.info/forum/forumdisplay.php?fid=60\""); + result = system("rundll32 url.dll,FileProtocolHandler \"https://www.moddb.com/games/colobot-gold-edition\""); #elif defined(PLATFORM_LINUX) - result = system("xdg-open \"https://colobot.info/forum/forumdisplay.php?fid=60\""); + result = system("xdg-open \"https://www.moddb.com/games/colobot-gold-edition\""); #elif defined(PLATFORM_MACOSX) - result = system("open \"https://colobot.info/forum/forumdisplay.php?fid=60\""); + result = system("open \"https://www.moddb.com/games/colobot-gold-edition\""); //TODO: Test on macOS #endif if (result == -1) { @@ -223,6 +218,29 @@ bool CScreenSetupMods::EventProcess(const Event &event) } return false; } + +void CScreenSetupMods::UnloadMod(std::string modName) +{ + std::string modPath, modPathRaw, disabled = "~"; + + modPathRaw = CResourceManager::GetSaveLocation() + "/" + "mods" + "/"; + modPath = modPathRaw.c_str(); + + m_pathManager->RemoveMod(modPath+modName); + boost::filesystem::rename(modPath+modName, modPath+disabled+modName); +} + +void CScreenSetupMods::LoadMod(std::string modName) +{ + std::string modPath, modPathRaw, disabled = "~"; + + modPathRaw = CResourceManager::GetSaveLocation() + "/" + "mods" + "/"; + modPath = modPathRaw.c_str(); + + boost::filesystem::rename(modPath+disabled+modName, modPath+modName); + m_pathManager->AddMod(modPath+modName); +} + void CScreenSetupMods::UpdateUnloadedModList() { CWindow* pw; @@ -243,9 +261,9 @@ void CScreenSetupMods::UpdateUnloadedModList() for(auto const& modNameRaw : modsDir) { modName = modNameRaw; - std::string::size_type ON; - ON = modName.find('~'); - if (ON != std::string::npos) + std::string::size_type enabled; + enabled = modName.find('~'); + if (enabled != std::string::npos) { modName.erase(0,1); pl->SetItemName(i++, modName); @@ -271,9 +289,9 @@ void CScreenSetupMods::UpdateLoadedModList() for(auto const &modName : modsDir) { - std::string::size_type ON; - ON = modName.find('~'); - if (ON == std::string::npos) + std::string::size_type enabled; + enabled = modName.find('~'); + if (enabled == std::string::npos) pl->SetItemName(i++, modName); } pl->ShowSelect(false); // shows the selected columns diff --git a/src/ui/screen/screen_setup_mods.h b/src/ui/screen/screen_setup_mods.h index 0d54502f..e61d75bc 100644 --- a/src/ui/screen/screen_setup_mods.h +++ b/src/ui/screen/screen_setup_mods.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2019, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -38,6 +38,8 @@ public: bool EventProcess(const Event &event) override; protected: + void UnloadMod(std::string ModName); + void LoadMod(std::string ModName); void UpdateUnloadedModList(); void UpdateLoadedModList(); From 7d30a827477d1611bea5a2b8f60523e58d6df7b0 Mon Sep 17 00:00:00 2001 From: DavivaD Date: Sat, 27 Jul 2019 16:59:51 +0200 Subject: [PATCH 4/6] Move platform-dependent code to system_*.cpp --- src/common/system/system.cpp | 10 +++++++++ src/common/system/system.h | 6 ++++++ src/common/system/system_linux.cpp | 22 ++++++++++++++++++++ src/common/system/system_linux.h | 3 +++ src/common/system/system_macosx.cpp | 22 ++++++++++++++++++++ src/common/system/system_macosx.h | 3 +++ src/common/system/system_other.cpp | 10 +++++++++ src/common/system/system_other.h | 3 +++ src/common/system/system_windows.cpp | 22 ++++++++++++++++++++ src/common/system/system_windows.h | 3 +++ src/ui/screen/screen_setup_mods.cpp | 31 ++++++---------------------- 11 files changed, 110 insertions(+), 25 deletions(-) diff --git a/src/common/system/system.cpp b/src/common/system/system.cpp index 44064556..3c306ac0 100644 --- a/src/common/system/system.cpp +++ b/src/common/system/system.cpp @@ -192,3 +192,13 @@ std::string CSystemUtils::GetSaveDir() { return "./saves"; } + +void CSystemUtils::OpenPath(std::string path) +{ + assert(false); +} + +void CSystemUtils::OpenWebsite(std::string website) +{ + assert(false); +} diff --git a/src/common/system/system.h b/src/common/system/system.h index aaf54954..2ef0b5cb 100644 --- a/src/common/system/system.h +++ b/src/common/system/system.h @@ -134,6 +134,12 @@ public: //! Returns the save dir location virtual std::string GetSaveDir(); + //! Opens a path with default file browser + virtual void OpenPath(std::string path); + + //! Opens a website with default web browser + virtual void OpenWebsite(std::string website); + //! Sleep for given amount of microseconds virtual void Usleep(int usecs) = 0; diff --git a/src/common/system/system_linux.cpp b/src/common/system/system_linux.cpp index 6578830d..2dda1c00 100644 --- a/src/common/system/system_linux.cpp +++ b/src/common/system/system_linux.cpp @@ -126,6 +126,28 @@ std::string CSystemUtilsLinux::GetSaveDir() #endif } +void CSystemUtilsLinux::OpenPath(std::string path) +{ + int result; + + result = system(("xdg-open \""+path+"\"").c_str()); + if (result == -1) + { + GetLogger()->Error("Failed to open path: %s\n", path.c_str()); + } +} + +void CSystemUtilsLinux::OpenWebsite(std::string website) +{ + int result; + + result = system(("xdg-open \""+website+"\"").c_str()); + if (result == -1) + { + GetLogger()->Error("Failed to open website: %s\n", website.c_str()); + } +} + void CSystemUtilsLinux::Usleep(int usec) { usleep(usec); diff --git a/src/common/system/system_linux.h b/src/common/system/system_linux.h index f1576f31..c41c30d4 100644 --- a/src/common/system/system_linux.h +++ b/src/common/system/system_linux.h @@ -45,6 +45,9 @@ public: std::string GetSaveDir() override; + void OpenPath(std::string path) override; + void OpenWebsite(std::string website) override; + void Usleep(int usec) override; private: diff --git a/src/common/system/system_macosx.cpp b/src/common/system/system_macosx.cpp index 9ef7ce1d..129037aa 100644 --- a/src/common/system/system_macosx.cpp +++ b/src/common/system/system_macosx.cpp @@ -113,6 +113,28 @@ std::string CSystemUtilsMacOSX::GetSaveDir() #endif } +void CSystemUtilsLinux::OpenPath(std::string path) +{ + int result; + + result = system(("open \""+path+"\"").c_str()); // TODO: Test on macOS + if (result == -1) + { + GetLogger()->Error("Failed to open path: %s\n", path.c_str()); + } +} + +void CSystemUtilsLinux::OpenWebsite(std::string website) +{ + int result; + + result = system(("open \""+website+"\"").c_str()); // TODO: Test on macOS + if (result == -1) + { + GetLogger()->Error("Failed to open website: %s\n", website.c_str()); + } +} + void CSystemUtilsMacOSX::Usleep(int usec) { usleep(usec); diff --git a/src/common/system/system_macosx.h b/src/common/system/system_macosx.h index 5b572ec4..dc4d2733 100644 --- a/src/common/system/system_macosx.h +++ b/src/common/system/system_macosx.h @@ -36,6 +36,9 @@ public: std::string GetLangPath() override; std::string GetSaveDir() override; + void OpenPath(std::string path) override; + void OpenWebsite(std::string website) override; + void Usleep(int usec) override; private: diff --git a/src/common/system/system_other.cpp b/src/common/system/system_other.cpp index a3311a74..7d439868 100644 --- a/src/common/system/system_other.cpp +++ b/src/common/system/system_other.cpp @@ -39,6 +39,16 @@ long long int CSystemUtilsOther::TimeStampExactDiff(SystemTimeStamp* before, Sys return (after->sdlTicks - before->sdlTicks) * 1000000ll; } +void CSystemUtilsOther::OpenPath(std::string path) +{ + // TODO +} + +void CSystemUtilsOther::OpenWebsite(std::string website) +{ + // TODO +} + void CSystemUtilsOther::Usleep(int usec) { SDL_Delay(usec / 1000); // close enough diff --git a/src/common/system/system_other.h b/src/common/system/system_other.h index ac80701b..d457b1e6 100644 --- a/src/common/system/system_other.h +++ b/src/common/system/system_other.h @@ -49,6 +49,9 @@ public: void GetCurrentTimeStamp(SystemTimeStamp *stamp) override; long long TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after) override; + void OpenPath(std::string path) override; + void OpenWebsite(std::string website) override; + void Usleep(int usec) override; }; diff --git a/src/common/system/system_windows.cpp b/src/common/system/system_windows.cpp index a20bfcf1..3400817d 100644 --- a/src/common/system/system_windows.cpp +++ b/src/common/system/system_windows.cpp @@ -131,6 +131,28 @@ std::string CSystemUtilsWindows::GetSaveDir() #endif } +void CSystemUtilsWindows::OpenPath(std::string path) +{ + int result; + + result = system(("explorer \""+path+"\"").c_str()); // TODO: Test on macOS + if (result == -1) + { + GetLogger()->Error("Failed to open path: %s\n", path.c_str()); + } +} + +void CSystemUtilsWindows::OpenWebsite(std::string website) +{ + int result; + + result = system(("rundll32 url.dll,FileProtocolHandler \""+website+"\"").c_str()); // TODO: Test on macOS + if (result == -1) + { + GetLogger()->Error("Failed to open website: %s\n", website.c_str()); + } +} + void CSystemUtilsWindows::Usleep(int usec) { LARGE_INTEGER ft; diff --git a/src/common/system/system_windows.h b/src/common/system/system_windows.h index 74f02455..54c8611e 100644 --- a/src/common/system/system_windows.h +++ b/src/common/system/system_windows.h @@ -43,6 +43,9 @@ public: std::string GetSaveDir() override; + void OpenPath(std::string path) override; + void OpenWebsite(std::string website) override; + void Usleep(int usec) override; public: diff --git a/src/ui/screen/screen_setup_mods.cpp b/src/ui/screen/screen_setup_mods.cpp index 696e6a02..d3266e2d 100644 --- a/src/ui/screen/screen_setup_mods.cpp +++ b/src/ui/screen/screen_setup_mods.cpp @@ -22,6 +22,8 @@ #include "app/app.h" #include "app/pathman.h" +#include "common/system/system.h" + #include "common/restext.h" #include "common/config.h" #include "common/logger.h" @@ -126,8 +128,8 @@ bool CScreenSetupMods::EventProcess(const Event &event) CWindow* pw; CButton* pb; CList* pl; - int result; - std::string modName, modPath; + std::string modName, modPath, website = "https://www.moddb.com/games/colobot-gold-edition"; + auto systemUtils = CSystemUtils::Create(); // platform-specific utils if (!CScreenSetup::EventProcess(event)) return false; @@ -157,18 +159,7 @@ bool CScreenSetupMods::EventProcess(const Event &event) if (event.type == EVENT_INTERFACE_MODS_DIR) { modPath = CResourceManager::GetSaveLocation() + "/" + "mods"; - #if defined(PLATFORM_WINDOWS) - std::replace(modPath.begin(), modPath.end(), '/', '\\'); - result = system(("explorer \""+modPath+"\"").c_str()); - #elif defined(PLATFORM_LINUX) - result = system(("xdg-open \""+modPath+"\"").c_str()); - #elif defined(PLATFORM_MACOSX) - result = system(("open \""+modPath+"\"").c_str()); //TODO: Test on macOS - #endif - if (result == -1) - { - GetLogger()->Error("Failed to open Mods directory! Does directory exists?\n"); - } + systemUtils->OpenPath(modPath); } switch (event.type) { @@ -201,17 +192,7 @@ bool CScreenSetupMods::EventProcess(const Event &event) break; case EVENT_INTERFACE_WORKSHOP: - #if defined(PLATFORM_WINDOWS) - result = system("rundll32 url.dll,FileProtocolHandler \"https://www.moddb.com/games/colobot-gold-edition\""); - #elif defined(PLATFORM_LINUX) - result = system("xdg-open \"https://www.moddb.com/games/colobot-gold-edition\""); - #elif defined(PLATFORM_MACOSX) - result = system("open \"https://www.moddb.com/games/colobot-gold-edition\""); //TODO: Test on macOS - #endif - if (result == -1) - { - GetLogger()->Error("Failed to open Workshop page! Is any Web Broswer installed?\n"); - } + systemUtils->OpenWebsite(website); break; default: return true; From 6f3b14202ec33ce697adc67bc5d10ab672833cab Mon Sep 17 00:00:00 2001 From: DavivaD Date: Sat, 27 Jul 2019 17:03:33 +0200 Subject: [PATCH 5/6] Mod Manager i18n --- po/colobot.pot | 21 +++++++++++++++++++++ po/cs.po | 21 +++++++++++++++++++++ po/de.po | 21 +++++++++++++++++++++ po/fr.po | 21 +++++++++++++++++++++ po/pl.po | 21 +++++++++++++++++++++ po/ru.po | 21 +++++++++++++++++++++ 6 files changed, 126 insertions(+) diff --git a/po/colobot.pot b/po/colobot.pot index 5d71af8c..675932b8 100644 --- a/po/colobot.pot +++ b/po/colobot.pot @@ -120,6 +120,12 @@ msgstr "" msgid "2) Then press the key you want to use instead." msgstr "" +msgid "Unloaded Mods:" +msgstr "" + +msgid "Loaded Mods:" +msgstr "" + msgid "Face type:" msgstr "" @@ -334,6 +340,18 @@ msgstr "" msgid "Play\\Start mission!" msgstr "" +msgid "Workshop\\Open Workshop to search Mods" +msgstr "" + +msgid "Open Directory\\Open Mods directory" +msgstr "" + +msgid "Load\\Load Mod" +msgstr "" + +msgid "Unload\\Unload Mod" +msgstr "" + msgid "Device\\Driver and resolution settings" msgstr "" @@ -349,6 +367,9 @@ msgstr "" msgid "Sound\\Music and game sound volume" msgstr "" +msgid "Mods\\Manage installed mods" +msgstr "" + msgid "Unit" msgstr "" diff --git a/po/cs.po b/po/cs.po index 555df720..cee89994 100644 --- a/po/cs.po +++ b/po/cs.po @@ -817,12 +817,18 @@ msgstr "Seznam uložených misí" msgid "Load a saved mission" msgstr "Nahrát uloženou misi" +msgid "Load\\Load Mod" +msgstr "" + msgid "Load\\Load a saved mission" msgstr "Nahrát\\Nahrát uloženou misi" msgid "Load\\Loads the selected mission" msgstr "Nahrát\\Nahraje vybranou misi" +msgid "Loaded Mods:" +msgstr "" + msgid "Loading basic level settings" msgstr "Načítám základní nastavení mapy" @@ -877,6 +883,9 @@ msgstr "Mise na této planetě:" msgid "Missions\\Select mission" msgstr "Mise\\Vyberte misi" +msgid "Mods\\Manage installed mods" +msgstr "" + msgid "Mouse inversion X\\Inversion of the scrolling direction on the X axis" msgstr "Vodorovné převrácení posunu\\Při vodorovném posunu kamery myší pousouvat opačným směrem" @@ -1039,6 +1048,9 @@ msgstr "Otevřít" msgid "Open (Ctrl+O)" msgstr "Otevřít (Ctrl+O)" +msgid "Open Directory\\Open Mods directory" +msgstr "" + msgid "Opening brace missing" msgstr "Chybí levá složená závorka" @@ -1640,6 +1652,12 @@ msgstr "Neznámá zástupná sekvence" msgid "Unknown function" msgstr "Neznámá funkce" +msgid "Unload\\Unload Mod" +msgstr "" + +msgid "Unloaded Mods:" +msgstr "" + msgid "Up (\\key gup;)" msgstr "Vzhůru (\\key gup;)" @@ -1706,6 +1724,9 @@ msgstr "Létající detektor" msgid "Withdraw shield (\\key action;)" msgstr "Vypnout štít (\\key action;)" +msgid "Workshop\\Open Workshop to search Mods" +msgstr "" + msgid "Worm" msgstr "Červ" diff --git a/po/de.po b/po/de.po index 553ead83..ca53d3cb 100644 --- a/po/de.po +++ b/po/de.po @@ -819,12 +819,18 @@ msgstr "Liste der gespeicherten Missionen" msgid "Load a saved mission" msgstr "Gespeicherte Mission laden" +msgid "Load\\Load Mod" +msgstr "" + msgid "Load\\Load a saved mission" msgstr "Laden\\Eine gespeicherte Mission öffnen" msgid "Load\\Loads the selected mission" msgstr "Laden\\Öffnet eine gespeicherte Mission" +msgid "Loaded Mods:" +msgstr "" + msgid "Loading basic level settings" msgstr "Lade Level-Grundeinstellungen" @@ -893,6 +899,9 @@ msgstr "Liste der Missionen des Planeten:" msgid "Missions\\Select mission" msgstr "Missionen\\Aufbruch ins Weltall" +msgid "Mods\\Manage installed mods" +msgstr "" + msgid "Mouse inversion X\\Inversion of the scrolling direction on the X axis" msgstr "Umkehr X\\Umkehr der Kameradrehung X-Achse" @@ -1055,6 +1064,9 @@ msgstr "Öffnen" msgid "Open (Ctrl+O)" msgstr "Öffnen (Ctrl+O)" +msgid "Open Directory\\Open Mods directory" +msgstr "" + msgid "Opening brace missing" msgstr "Es fehlt eine offene geschweifte Klammer\"{\"" @@ -1657,6 +1669,12 @@ msgstr "" msgid "Unknown function" msgstr "Unbekannte Funktion" +msgid "Unload\\Unload Mod" +msgstr "" + +msgid "Unloaded Mods:" +msgstr "" + msgid "Up (\\key gup;)" msgstr "Steigt (\\key gup;)" @@ -1723,6 +1741,9 @@ msgstr "Schnüffler" msgid "Withdraw shield (\\key action;)" msgstr "Schutzschild einholen (\\key action;)" +msgid "Workshop\\Open Workshop to search Mods" +msgstr "" + msgid "Worm" msgstr "Wurm" diff --git a/po/fr.po b/po/fr.po index ce3f5fdf..76afb80c 100644 --- a/po/fr.po +++ b/po/fr.po @@ -821,12 +821,18 @@ msgstr "Liste des missions enregistrées" msgid "Load a saved mission" msgstr "Chargement d'une mission enregistrée" +msgid "Load\\Load Mod" +msgstr "" + msgid "Load\\Load a saved mission" msgstr "Charger\\Charger une mission enregistrée" msgid "Load\\Loads the selected mission" msgstr "Charger\\Charger la mission sélectionnée" +msgid "Loaded Mods:" +msgstr "" + msgid "Loading basic level settings" msgstr "Chargement des configurations de base du niveau" @@ -895,6 +901,9 @@ msgstr "Liste des missions du chapitre :" msgid "Missions\\Select mission" msgstr "Missions\\La grande aventure" +msgid "Mods\\Manage installed mods" +msgstr "" + msgid "Mouse inversion X\\Inversion of the scrolling direction on the X axis" msgstr "Inversion souris X\\Inversion de la rotation lorsque la souris touche un bord" @@ -1057,6 +1066,9 @@ msgstr "Ouvrir" msgid "Open (Ctrl+O)" msgstr "Ouvrir (Ctrl+O)" +msgid "Open Directory\\Open Mods directory" +msgstr "" + msgid "Opening brace missing" msgstr "Début d'un bloc attendu" @@ -1660,6 +1672,12 @@ msgstr "" msgid "Unknown function" msgstr "Routine inconnue" +msgid "Unload\\Unload Mod" +msgstr "" + +msgid "Unloaded Mods:" +msgstr "" + msgid "Up (\\key gup;)" msgstr "Monte (\\key gup;)" @@ -1726,6 +1744,9 @@ msgstr "Robot renifleur volant" msgid "Withdraw shield (\\key action;)" msgstr "Refermer le bouclier (\\key action;)" +msgid "Workshop\\Open Workshop to search Mods" +msgstr "" + msgid "Worm" msgstr "Ver" diff --git a/po/pl.po b/po/pl.po index f9f76de8..4dd75cc4 100644 --- a/po/pl.po +++ b/po/pl.po @@ -816,12 +816,18 @@ msgstr "Lista zapisanych misji" msgid "Load a saved mission" msgstr "Wczytaj zapisaną misję" +msgid "Load\\Load Mod" +msgstr "" + msgid "Load\\Load a saved mission" msgstr "Wczytaj\\Wczytuje zapisaną misję" msgid "Load\\Loads the selected mission" msgstr "Wczytaj\\Wczytuje zaznaczoną misję" +msgid "Loaded Mods:" +msgstr "" + msgid "Loading basic level settings" msgstr "Wczytywanie ustawień poziomu" @@ -876,6 +882,9 @@ msgstr "Misje na tej planecie:" msgid "Missions\\Select mission" msgstr "Misje\\Wybierz misję" +msgid "Mods\\Manage installed mods" +msgstr "" + msgid "Mouse inversion X\\Inversion of the scrolling direction on the X axis" msgstr "Odwrócenie myszy X\\Odwrócenie kierunków przewijania w poziomie" @@ -1038,6 +1047,9 @@ msgstr "Otwórz" msgid "Open (Ctrl+O)" msgstr "Otwórz (Ctrl+O)" +msgid "Open Directory\\Open Mods directory" +msgstr "" + msgid "Opening brace missing" msgstr "Brak klamry otwierającej" @@ -1639,6 +1651,12 @@ msgstr "" msgid "Unknown function" msgstr "Funkcja nieznana" +msgid "Unload\\Unload Mod" +msgstr "" + +msgid "Unloaded Mods:" +msgstr "" + msgid "Up (\\key gup;)" msgstr "Góra (\\key gup;)" @@ -1705,6 +1723,9 @@ msgstr "Szperacz latający" msgid "Withdraw shield (\\key action;)" msgstr "Wyłącz osłonę (\\key action;)" +msgid "Workshop\\Open Workshop to search Mods" +msgstr "" + msgid "Worm" msgstr "Robal" diff --git a/po/ru.po b/po/ru.po index 0763e742..21266749 100644 --- a/po/ru.po +++ b/po/ru.po @@ -825,12 +825,18 @@ msgstr "Список сохраненных миссий" msgid "Load a saved mission" msgstr "Загрузить" +msgid "Load\\Load Mod" +msgstr "" + msgid "Load\\Load a saved mission" msgstr "Загрузить\\Загрузить сохраненную миссию" msgid "Load\\Loads the selected mission" msgstr "Загрузить\\Загрузить выбранную миссию" +msgid "Loaded Mods:" +msgstr "" + msgid "Loading basic level settings" msgstr "Загрузка основных настроек уровня" @@ -899,6 +905,9 @@ msgstr "Миссии на этой планете:" msgid "Missions\\Select mission" msgstr "Миссии\\Выбор миссии" +msgid "Mods\\Manage installed mods" +msgstr "" + msgid "Mouse inversion X\\Inversion of the scrolling direction on the X axis" msgstr "Инверсия мыши по оси X\\Инверсия прокрутки по оси Х" @@ -1063,6 +1072,9 @@ msgstr "Открыть" msgid "Open (Ctrl+O)" msgstr "Открыть (Ctrl+O)" +msgid "Open Directory\\Open Mods directory" +msgstr "" + msgid "Opening brace missing" msgstr "Открывающая скобка отсутствует" @@ -1670,6 +1682,12 @@ msgstr "" msgid "Unknown function" msgstr "Неизвестная функция" +msgid "Unload\\Unload Mod" +msgstr "" + +msgid "Unloaded Mods:" +msgstr "" + msgid "Up (\\key gup;)" msgstr "Вверх (\\key gup;)" @@ -1736,6 +1754,9 @@ msgstr "Летающий искатель" msgid "Withdraw shield (\\key action;)" msgstr "Снять щит (\\key action;)" +msgid "Workshop\\Open Workshop to search Mods" +msgstr "" + msgid "Worm" msgstr "Червь" From 50c3c45ef8d536c594cbe5fa65b615ea2397de47 Mon Sep 17 00:00:00 2001 From: DavivaD Date: Sat, 27 Jul 2019 17:58:12 +0200 Subject: [PATCH 6/6] Show only local mods on the list --- src/ui/screen/screen_setup_mods.cpp | 39 ++++++++++++++++++----------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/src/ui/screen/screen_setup_mods.cpp b/src/ui/screen/screen_setup_mods.cpp index d3266e2d..3779ee32 100644 --- a/src/ui/screen/screen_setup_mods.cpp +++ b/src/ui/screen/screen_setup_mods.cpp @@ -41,6 +41,9 @@ #include #include +#include + +using namespace boost::filesystem; namespace Ui { @@ -224,10 +227,11 @@ void CScreenSetupMods::LoadMod(std::string modName) void CScreenSetupMods::UpdateUnloadedModList() { - CWindow* pw; - CList* pl; - int i = 0; - std::string modName; + CWindow* pw; + CList* pl; + int i = 0; + std::string modPath, modPathRaw; + directory_iterator end_itr; pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); if ( pw == nullptr ) return; @@ -236,12 +240,13 @@ void CScreenSetupMods::UpdateUnloadedModList() if ( pl == nullptr ) return; pl->Flush(); - auto modsDir = CResourceManager::ListDirectories("mods/"); - std::sort(modsDir.begin(), modsDir.end()); + modPathRaw = CResourceManager::GetSaveLocation() + "/" + "mods" + "/"; + modPath = modPathRaw.c_str(); - for(auto const& modNameRaw : modsDir) + for (directory_iterator itr(modPath); itr != end_itr; ++itr) { - modName = modNameRaw; + std::string modName = itr->path().string(); + boost::erase_all(modName, modPath); std::string::size_type enabled; enabled = modName.find('~'); if (enabled != std::string::npos) @@ -250,13 +255,16 @@ void CScreenSetupMods::UpdateUnloadedModList() pl->SetItemName(i++, modName); } } + pl->ShowSelect(false); // shows the selected columns } void CScreenSetupMods::UpdateLoadedModList() { - CWindow* pw; - CList* pl; - int i = 0; + CWindow* pw; + CList* pl; + int i = 0; + std::string modPath, modPathRaw; + directory_iterator end_itr; pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); if ( pw == nullptr ) return; @@ -265,16 +273,19 @@ void CScreenSetupMods::UpdateLoadedModList() if ( pl == nullptr ) return; pl->Flush(); - auto modsDir = CResourceManager::ListDirectories("mods/"); - std::sort(modsDir.begin(), modsDir.end()); + modPathRaw = CResourceManager::GetSaveLocation() + "/" + "mods" + "/"; + modPath = modPathRaw.c_str(); - for(auto const &modName : modsDir) + for (directory_iterator itr(modPath); itr != end_itr; ++itr) { + std::string modName = itr->path().string(); + boost::erase_all(modName, modPath); std::string::size_type enabled; enabled = modName.find('~'); if (enabled == std::string::npos) pl->SetItemName(i++, modName); } + pl->ShowSelect(false); // shows the selected columns } } // namespace Ui