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