Improve sound reloading
Also some minor refactoring. Since realoding may take a lot of time, modman no longer reloads the whole app on entering/leaving the screen.pyro-refactor
parent
fd36ff3840
commit
9cb80daedf
|
@ -520,7 +520,9 @@ bool CApplication::Create()
|
|||
GetLogger()->Warn("Config could not be loaded. Default values will be used!\n");
|
||||
}
|
||||
|
||||
m_modManager->Init();
|
||||
m_modManager->FindMods();
|
||||
m_modManager->SaveMods();
|
||||
m_modManager->MountAllMods();
|
||||
|
||||
// Create the sound instance.
|
||||
#ifdef OPENAL_SOUND
|
||||
|
@ -1551,6 +1553,7 @@ void CApplication::StartLoadingMusic()
|
|||
SystemTimeStamp* musicLoadStart = m_systemUtils->CreateTimeStamp();
|
||||
m_systemUtils->GetCurrentTimeStamp(musicLoadStart);
|
||||
|
||||
m_sound->Reset();
|
||||
m_sound->CacheAll();
|
||||
|
||||
SystemTimeStamp* musicLoadEnd = m_systemUtils->CreateTimeStamp();
|
||||
|
|
|
@ -44,8 +44,11 @@ CModManager::CModManager(CApplication* app, CPathManager* pathManager)
|
|||
{
|
||||
}
|
||||
|
||||
void CModManager::Init()
|
||||
void CModManager::FindMods()
|
||||
{
|
||||
m_mods.clear();
|
||||
m_userChanges = false;
|
||||
|
||||
// Load names from the config file
|
||||
std::vector<std::string> savedModNames;
|
||||
GetConfigFile().GetArrayProperty("Mods", "Names", savedModNames);
|
||||
|
@ -103,9 +106,15 @@ void CModManager::Init()
|
|||
m_mods.push_back(mod);
|
||||
}
|
||||
|
||||
SaveMods();
|
||||
|
||||
// Load the metadata for each mod
|
||||
|
||||
// Unfortunately, the paths are distinguished by their real paths, not mount points
|
||||
// So we must unmount mods temporarily
|
||||
for (const auto& path : m_mountedModPaths)
|
||||
{
|
||||
UnmountMod(path);
|
||||
}
|
||||
|
||||
for (auto& mod : m_mods)
|
||||
{
|
||||
MountMod(mod, "/temp/mod");
|
||||
|
@ -113,28 +122,30 @@ void CModManager::Init()
|
|||
UnmountMod(mod);
|
||||
}
|
||||
|
||||
UpdatePaths();
|
||||
// Mount back
|
||||
for (const auto& path : m_mountedModPaths)
|
||||
{
|
||||
MountMod(path);
|
||||
}
|
||||
}
|
||||
|
||||
void CModManager::ReloadMods()
|
||||
{
|
||||
UnmountAllMods();
|
||||
m_mods.clear();
|
||||
|
||||
Init();
|
||||
|
||||
// Apply the configuration
|
||||
UnmountAllMountedMods();
|
||||
MountAllMods();
|
||||
ReloadResources();
|
||||
}
|
||||
|
||||
void CModManager::EnableMod(size_t i)
|
||||
{
|
||||
m_mods[i].enabled = true;
|
||||
m_userChanges = true;
|
||||
}
|
||||
|
||||
void CModManager::DisableMod(size_t i)
|
||||
{
|
||||
m_mods[i].enabled = false;
|
||||
m_userChanges = true;
|
||||
}
|
||||
|
||||
size_t CModManager::MoveUp(size_t i)
|
||||
|
@ -142,6 +153,7 @@ size_t CModManager::MoveUp(size_t i)
|
|||
if (i != 0)
|
||||
{
|
||||
std::swap(m_mods[i - 1], m_mods[i]);
|
||||
m_userChanges = true;
|
||||
return i - 1;
|
||||
}
|
||||
else
|
||||
|
@ -155,6 +167,7 @@ size_t CModManager::MoveDown(size_t i)
|
|||
if (i != m_mods.size() - 1)
|
||||
{
|
||||
std::swap(m_mods[i], m_mods[i + 1]);
|
||||
m_userChanges = true;
|
||||
return i + 1;
|
||||
}
|
||||
else
|
||||
|
@ -163,13 +176,27 @@ size_t CModManager::MoveDown(size_t i)
|
|||
}
|
||||
}
|
||||
|
||||
void CModManager::UpdatePaths()
|
||||
bool CModManager::Changes()
|
||||
{
|
||||
std::vector<std::string> paths;
|
||||
for (const auto& mod : m_mods)
|
||||
{
|
||||
if (mod.enabled)
|
||||
{
|
||||
paths.push_back(mod.path);
|
||||
}
|
||||
}
|
||||
return paths != m_mountedModPaths || m_userChanges;
|
||||
}
|
||||
|
||||
void CModManager::MountAllMods()
|
||||
{
|
||||
for (const auto& mod : m_mods)
|
||||
{
|
||||
if (mod.enabled)
|
||||
{
|
||||
MountMod(mod);
|
||||
m_mountedModPaths.push_back(mod.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -192,6 +219,8 @@ void CModManager::SaveMods()
|
|||
GetConfigFile().SetArrayProperty("Mods", "Enabled", savedEnabled);
|
||||
|
||||
GetConfigFile().Save();
|
||||
|
||||
m_userChanges = false;
|
||||
}
|
||||
|
||||
size_t CModManager::CountMods() const
|
||||
|
@ -296,23 +325,34 @@ void CModManager::LoadModData(Mod& mod)
|
|||
|
||||
void CModManager::MountMod(const Mod& mod, const std::string& mountPoint)
|
||||
{
|
||||
GetLogger()->Debug("Mounting mod: '%s' at path %s\n", mod.path.c_str(), mountPoint.c_str());
|
||||
CResourceManager::AddLocation(mod.path, true, mountPoint);
|
||||
MountMod(mod.path, mountPoint);
|
||||
}
|
||||
|
||||
void CModManager::MountMod(const std::string& path, const std::string& mountPoint)
|
||||
{
|
||||
GetLogger()->Debug("Mounting mod: '%s' at path %s\n", path.c_str(), mountPoint.c_str());
|
||||
CResourceManager::AddLocation(path, true, mountPoint);
|
||||
}
|
||||
|
||||
void CModManager::UnmountMod(const Mod& mod)
|
||||
{
|
||||
if (CResourceManager::LocationExists(mod.path))
|
||||
UnmountMod(mod.path);
|
||||
}
|
||||
|
||||
void CModManager::UnmountMod(const std::string& path)
|
||||
{
|
||||
if (CResourceManager::LocationExists(path))
|
||||
{
|
||||
GetLogger()->Debug("Unmounting mod: '%s'\n", mod.path.c_str());
|
||||
CResourceManager::RemoveLocation(mod.path);
|
||||
GetLogger()->Debug("Unmounting mod: '%s'\n", path.c_str());
|
||||
CResourceManager::RemoveLocation(path);
|
||||
}
|
||||
}
|
||||
|
||||
void CModManager::UnmountAllMods()
|
||||
void CModManager::UnmountAllMountedMods()
|
||||
{
|
||||
for (const auto& mod : m_mods)
|
||||
for (const auto& path : m_mountedModPaths)
|
||||
{
|
||||
UnmountMod(mod);
|
||||
UnmountMod(path);
|
||||
}
|
||||
m_mountedModPaths.clear();
|
||||
}
|
||||
|
|
|
@ -51,21 +51,17 @@ struct Mod
|
|||
* The order matters since the order in which files are loaded matters,
|
||||
* because some files can be overwritten.
|
||||
*
|
||||
* The changes in the list do not immediately apply
|
||||
* and will be lost after the \ref ReloadMods call if they were not
|
||||
* saved beforehand with \ref SaveMods.
|
||||
*
|
||||
* The changes are also lost to mods which are no longer found in the search paths.
|
||||
* The changes in the list do not immediately apply.
|
||||
*/
|
||||
class CModManager
|
||||
{
|
||||
public:
|
||||
CModManager(CApplication* app, CPathManager* pathManager);
|
||||
|
||||
//! Loads mods without resource reloading; should be called only once after creation
|
||||
void Init();
|
||||
|
||||
//! Finds all the mods along with their metadata
|
||||
void FindMods();
|
||||
|
||||
//! Applies the current configuration and reloads the application
|
||||
void ReloadMods();
|
||||
|
||||
//! Removes a mod from the list of loaded mods
|
||||
|
@ -80,6 +76,9 @@ public:
|
|||
//! Moves the selected mod down in the list so that it's loaded later than others, returns the new index
|
||||
size_t MoveDown(size_t i);
|
||||
|
||||
//! Checks if the list of currently used mods differs from the current configuration or there were changes made by the user
|
||||
bool Changes();
|
||||
|
||||
//! Saves the current configuration of mods to the config file
|
||||
void SaveMods();
|
||||
|
||||
|
@ -93,8 +92,8 @@ public:
|
|||
const std::vector<Mod>& GetMods() const;
|
||||
|
||||
private:
|
||||
//! Updates the paths in Path Manager according to the current mod configuration
|
||||
void UpdatePaths();
|
||||
// Allow access to MountAllMods() as CApplication doesn't want to reload itself during initialization
|
||||
friend CApplication;
|
||||
|
||||
//! Reloads application resources so the enabled mods are applied
|
||||
void ReloadResources();
|
||||
|
@ -102,13 +101,24 @@ private:
|
|||
//! Load mod data into mod
|
||||
void LoadModData(Mod& mod);
|
||||
|
||||
//! Updates the paths in Path Manager according to the current mod configuration
|
||||
void MountAllMods();
|
||||
|
||||
void MountMod(const Mod& mod, const std::string& mountPoint = "");
|
||||
void MountMod(const std::string& path, const std::string& mountPoint = "");
|
||||
void UnmountMod(const Mod& mod);
|
||||
void UnmountAllMods();
|
||||
void UnmountMod(const std::string& path);
|
||||
void UnmountAllMountedMods();
|
||||
|
||||
private:
|
||||
CApplication* m_app;
|
||||
CPathManager* m_pathManager;
|
||||
|
||||
//! Paths to mods already in the virtual filesystem
|
||||
std::vector<std::string> m_mountedModPaths;
|
||||
|
||||
//! List of mods
|
||||
std::vector<Mod> m_mods;
|
||||
|
||||
bool m_userChanges = false;
|
||||
};
|
||||
|
|
|
@ -47,22 +47,7 @@ void CALSound::CleanUp()
|
|||
if (m_enabled)
|
||||
{
|
||||
GetLogger()->Info("Unloading files and closing device...\n");
|
||||
StopAll();
|
||||
StopMusic();
|
||||
|
||||
m_channels.clear();
|
||||
|
||||
m_currentMusic.reset();
|
||||
|
||||
m_oldMusic.clear();
|
||||
|
||||
m_previousMusic.music.reset();
|
||||
|
||||
m_sounds.clear();
|
||||
|
||||
m_music.clear();
|
||||
|
||||
m_enabled = false;
|
||||
Reset();
|
||||
|
||||
alcDestroyContext(m_context);
|
||||
alcCloseDevice(m_device);
|
||||
|
@ -99,6 +84,24 @@ bool CALSound::Create()
|
|||
return true;
|
||||
}
|
||||
|
||||
void CALSound::Reset()
|
||||
{
|
||||
StopAll();
|
||||
StopMusic();
|
||||
|
||||
m_channels.clear();
|
||||
|
||||
m_currentMusic.reset();
|
||||
|
||||
m_oldMusic.clear();
|
||||
|
||||
m_previousMusic.music.reset();
|
||||
|
||||
m_sounds.clear();
|
||||
|
||||
m_music.clear();
|
||||
}
|
||||
|
||||
bool CALSound::GetEnable()
|
||||
{
|
||||
return m_enabled;
|
||||
|
|
|
@ -84,6 +84,7 @@ public:
|
|||
~CALSound();
|
||||
|
||||
bool Create() override;
|
||||
void Reset() override;
|
||||
bool Cache(SoundType, const std::string &) override;
|
||||
void CacheMusic(const std::string &) override;
|
||||
bool IsCached(SoundType) override;
|
||||
|
|
|
@ -52,6 +52,10 @@ void CSoundInterface::CacheAll()
|
|||
}
|
||||
}
|
||||
|
||||
void CSoundInterface::Reset()
|
||||
{
|
||||
}
|
||||
|
||||
bool CSoundInterface::Cache(SoundType sound, const std::string &file)
|
||||
{
|
||||
return true;
|
||||
|
|
|
@ -72,6 +72,10 @@ public:
|
|||
*/
|
||||
void CacheAll();
|
||||
|
||||
/** Stop all sounds and music and clean cache.
|
||||
*/
|
||||
virtual void Reset();
|
||||
|
||||
/** Function called to cache sound effect file.
|
||||
* This function is called by plugin interface for each file.
|
||||
* \param sound - id of a file, will be used to identify sound files
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
|
||||
#include "math/func.h"
|
||||
|
||||
#include "sound/sound.h"
|
||||
|
||||
#include "ui/controls/button.h"
|
||||
#include "ui/controls/edit.h"
|
||||
#include "ui/controls/interface.h"
|
||||
|
@ -64,9 +66,6 @@ void CScreenModList::CreateInterface()
|
|||
Math::Point pos, ddim;
|
||||
std::string name;
|
||||
|
||||
m_changes = false;
|
||||
ApplyChanges();
|
||||
|
||||
// Display the window
|
||||
pos.x = 0.10f;
|
||||
pos.y = 0.10f;
|
||||
|
@ -104,8 +103,6 @@ void CScreenModList::CreateInterface()
|
|||
pli->SetState(STATE_SHADOW);
|
||||
pli->SetState(STATE_EXTEND);
|
||||
|
||||
UpdateModList();
|
||||
|
||||
// Displays the mod details
|
||||
pos.x = ox+sx*9.5f;
|
||||
pos.y = oy+sy*10.5f;
|
||||
|
@ -124,8 +121,6 @@ void CScreenModList::CreateInterface()
|
|||
pe->SetEditCap(false); // just to see
|
||||
pe->SetHighlightCap(true);
|
||||
|
||||
UpdateModDetails();
|
||||
|
||||
pos = pli->GetPos();
|
||||
ddim = pli->GetDim();
|
||||
|
||||
|
@ -148,8 +143,6 @@ void CScreenModList::CreateInterface()
|
|||
pe->SetEditCap(false); // just to see
|
||||
pe->SetHighlightCap(true);
|
||||
|
||||
UpdateModSummary();
|
||||
|
||||
// Apply button
|
||||
pos.x = ox+sx*13.75f;
|
||||
pos.y = oy+sy*2;
|
||||
|
@ -158,16 +151,12 @@ void CScreenModList::CreateInterface()
|
|||
pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_MODS_APPLY);
|
||||
pb->SetState(STATE_SHADOW);
|
||||
|
||||
UpdateApplyButton();
|
||||
|
||||
// Display the enable/disable button
|
||||
pos.x -= dim.x*2.3f;
|
||||
ddim.x = dim.x*2.0f;
|
||||
pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_MOD_ENABLE_OR_DISABLE);
|
||||
pb->SetState(STATE_SHADOW);
|
||||
|
||||
UpdateEnableDisableButton();
|
||||
|
||||
// Display the move up button
|
||||
pos.x -= dim.x*0.8f;
|
||||
pos.y = oy+sy*2.48;
|
||||
|
@ -181,8 +170,6 @@ void CScreenModList::CreateInterface()
|
|||
pb = pw->CreateButton(pos, ddim, 50, EVENT_INTERFACE_MOD_MOVE_DOWN);
|
||||
pb->SetState(STATE_SHADOW);
|
||||
|
||||
UpdateUpDownButtons();
|
||||
|
||||
// Display the refresh button
|
||||
pos.x -= dim.x*1.3f;
|
||||
pos.y = oy+sy*2;
|
||||
|
@ -207,6 +194,9 @@ void CScreenModList::CreateInterface()
|
|||
pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_BACK);
|
||||
pb->SetState(STATE_SHADOW);
|
||||
|
||||
FindMods();
|
||||
UpdateAll();
|
||||
|
||||
// Background
|
||||
SetBackground("textures/interface/interface.png");
|
||||
CreateVersionDisplay();
|
||||
|
@ -231,7 +221,7 @@ bool CScreenModList::EventProcess(const Event &event)
|
|||
event.type == EVENT_INTERFACE_BACK ||
|
||||
(event.type == EVENT_KEY_DOWN && event.GetData<KeyEventData>()->key == KEY(ESCAPE)))
|
||||
{
|
||||
if (m_changes)
|
||||
if (m_modManager->Changes())
|
||||
{
|
||||
m_dialog->StartQuestion(RT_DIALOG_CHANGES_QUESTION, true, true, false,
|
||||
[this]()
|
||||
|
@ -241,14 +231,11 @@ bool CScreenModList::EventProcess(const Event &event)
|
|||
},
|
||||
[this]()
|
||||
{
|
||||
m_changes = false; // do not save changes on "No"
|
||||
ApplyChanges();
|
||||
CloseWindow();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplyChanges();
|
||||
CloseWindow();
|
||||
}
|
||||
return false;
|
||||
|
@ -278,7 +265,6 @@ bool CScreenModList::EventProcess(const Event &event)
|
|||
}
|
||||
UpdateModList();
|
||||
UpdateEnableDisableButton();
|
||||
m_changes = true;
|
||||
UpdateApplyButton();
|
||||
break;
|
||||
|
||||
|
@ -286,7 +272,6 @@ bool CScreenModList::EventProcess(const Event &event)
|
|||
m_modSelectedIndex = m_modManager->MoveUp(m_modSelectedIndex);
|
||||
UpdateModList();
|
||||
UpdateUpDownButtons();
|
||||
m_changes = true;
|
||||
UpdateApplyButton();
|
||||
break;
|
||||
|
||||
|
@ -294,20 +279,21 @@ bool CScreenModList::EventProcess(const Event &event)
|
|||
m_modSelectedIndex = m_modManager->MoveDown(m_modSelectedIndex);
|
||||
UpdateModList();
|
||||
UpdateUpDownButtons();
|
||||
m_changes = true;
|
||||
UpdateApplyButton();
|
||||
break;
|
||||
|
||||
case EVENT_INTERFACE_MODS_REFRESH:
|
||||
// Apply any changes before refresh so that the config file
|
||||
// is better synchronized with the state of the game
|
||||
case EVENT_INTERFACE_MODS_APPLY:
|
||||
ApplyChanges();
|
||||
// Update the whole UI
|
||||
UpdateModList();
|
||||
UpdateModSummary();
|
||||
UpdateModDetails();
|
||||
UpdateEnableDisableButton();
|
||||
UpdateApplyButton();
|
||||
UpdateUpDownButtons();
|
||||
UpdateAll();
|
||||
// Start playing the main menu music again
|
||||
if (!m_app->GetSound()->IsPlayingMusic())
|
||||
{
|
||||
m_app->GetSound()->PlayMusic("music/Intro1.ogg", false);
|
||||
m_app->GetSound()->CacheMusic("music/Intro2.ogg");
|
||||
}
|
||||
break;
|
||||
|
||||
case EVENT_INTERFACE_MODS_DIR:
|
||||
|
@ -341,19 +327,19 @@ bool CScreenModList::EventProcess(const Event &event)
|
|||
return false;
|
||||
}
|
||||
|
||||
void CScreenModList::FindMods()
|
||||
{
|
||||
m_modManager->FindMods();
|
||||
if (m_modManager->CountMods() != 0)
|
||||
{
|
||||
m_modSelectedIndex = Math::Clamp(m_modSelectedIndex, static_cast<size_t>(0), m_modManager->CountMods() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void CScreenModList::ApplyChanges()
|
||||
{
|
||||
if (m_changes)
|
||||
{
|
||||
m_changes = false;
|
||||
m_modManager->SaveMods();
|
||||
}
|
||||
|
||||
m_modManager->SaveMods();
|
||||
m_modManager->ReloadMods();
|
||||
|
||||
m_empty = (m_modManager->CountMods() == 0);
|
||||
|
||||
m_modSelectedIndex = Math::Clamp(m_modSelectedIndex, static_cast<size_t>(0), m_modManager->CountMods() - 1);
|
||||
}
|
||||
|
||||
void CScreenModList::CloseWindow()
|
||||
|
@ -361,6 +347,16 @@ void CScreenModList::CloseWindow()
|
|||
m_main->ChangePhase(PHASE_MAIN_MENU);
|
||||
}
|
||||
|
||||
void CScreenModList::UpdateAll()
|
||||
{
|
||||
UpdateModList();
|
||||
UpdateModDetails();
|
||||
UpdateModSummary();
|
||||
UpdateEnableDisableButton();
|
||||
UpdateApplyButton();
|
||||
UpdateUpDownButtons();
|
||||
}
|
||||
|
||||
void CScreenModList::UpdateModList()
|
||||
{
|
||||
CWindow* pw = static_cast<CWindow*>(m_interface->SearchControl(EVENT_WINDOW5));
|
||||
|
@ -371,16 +367,16 @@ void CScreenModList::UpdateModList()
|
|||
|
||||
pl->Flush();
|
||||
|
||||
if (m_empty)
|
||||
if (m_modManager->CountMods() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto mods = m_modManager->GetMods();
|
||||
const auto& mods = m_modManager->GetMods();
|
||||
for (size_t i = 0; i < mods.size(); ++i)
|
||||
{
|
||||
const auto& mod = mods[i];
|
||||
auto name = mod.data.displayName;
|
||||
const auto& name = mod.data.displayName;
|
||||
pl->SetItemName(i, name);
|
||||
pl->SetCheck(i, mod.enabled);
|
||||
pl->SetEnable(i, true);
|
||||
|
@ -398,7 +394,7 @@ void CScreenModList::UpdateModDetails()
|
|||
CEdit* pe = static_cast<CEdit*>(pw->SearchControl(EVENT_INTERFACE_MOD_DETAILS));
|
||||
if (pe == nullptr) return;
|
||||
|
||||
if (m_empty)
|
||||
if (m_modManager->CountMods() == 0)
|
||||
{
|
||||
pe->SetText("No information");
|
||||
return;
|
||||
|
@ -475,7 +471,7 @@ void CScreenModList::UpdateModSummary()
|
|||
std::string noSummary;
|
||||
GetResource(RES_TEXT, RT_MOD_NO_SUMMARY, noSummary);
|
||||
|
||||
if (m_empty)
|
||||
if (m_modManager->CountMods() == 0)
|
||||
{
|
||||
pe->SetText(noSummary);
|
||||
return;
|
||||
|
@ -503,7 +499,7 @@ void CScreenModList::UpdateEnableDisableButton()
|
|||
|
||||
std::string buttonName{};
|
||||
|
||||
if (m_empty)
|
||||
if (m_modManager->CountMods() == 0)
|
||||
{
|
||||
pb->ClearState(STATE_ENABLE);
|
||||
|
||||
|
@ -536,13 +532,7 @@ void CScreenModList::UpdateApplyButton()
|
|||
CButton* pb = static_cast<CButton*>(pw->SearchControl(EVENT_INTERFACE_MODS_APPLY));
|
||||
if (pb == nullptr) return;
|
||||
|
||||
if (m_empty)
|
||||
{
|
||||
pb->ClearState(STATE_ENABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_changes)
|
||||
if (m_modManager->Changes())
|
||||
{
|
||||
pb->SetState(STATE_ENABLE);
|
||||
}
|
||||
|
@ -563,7 +553,7 @@ void CScreenModList::UpdateUpDownButtons()
|
|||
CButton* pb_down = static_cast<CButton*>(pw->SearchControl(EVENT_INTERFACE_MOD_MOVE_DOWN));
|
||||
if (pb_down == nullptr) return;
|
||||
|
||||
if (m_empty)
|
||||
if (m_modManager->CountMods() == 0)
|
||||
{
|
||||
pb_up->ClearState(STATE_ENABLE);
|
||||
pb_down->ClearState(STATE_ENABLE);
|
||||
|
|
|
@ -33,34 +33,6 @@ namespace Ui
|
|||
/**
|
||||
* \class CScreenModList
|
||||
* \brief This class is the front-end for the \ref CModManager.
|
||||
*
|
||||
* \section Assumptions Assumptions
|
||||
*
|
||||
* It assumes the user is changing something in the mods folders while the screen is visible,
|
||||
* e.g. removing them or adding more. For this reason, the mods are always reloaded after the user
|
||||
* lefts the screen, possibly after asking the user if their changes should be saved. They are also reloaded
|
||||
* when the user opens the screen to avoid weird situations like "the mod is no longer there but in theory
|
||||
* it's still in the game's memory even if it's not visible on the list".
|
||||
*
|
||||
* Unsafe changes, like removing a mod which is still enabled, are a sole responsibility of the user and
|
||||
* we basically can't guarantee the game will behave properly in such cases even when they happen while
|
||||
* this screen is visible.
|
||||
*
|
||||
* \section Features UI Features
|
||||
*
|
||||
* The user can reorder mods with appropriate buttons and enable/disable them. To avoid reloading
|
||||
* the resources after every change, the changes are not immediate. The resources are reloaded in the
|
||||
* cases described above and also after using the Apply or Refresh buttons. The only technical
|
||||
* difference between them is that the Refresh button is always enabled, but Apply is only enabled
|
||||
* if the user made any changes in the list by using the UI. The reason is, again, to avoid dealing with
|
||||
* weird situations like described above.
|
||||
*
|
||||
* The UI also shows the selected mod metadata like description, version, etc.
|
||||
*
|
||||
* There is also a button which will try to open the default web browser with the Workshop website,
|
||||
* where the user can search for new mods.
|
||||
*
|
||||
* For convenience, also a button opening a saves/mods folder is provided.
|
||||
*/
|
||||
class CScreenModList : public CScreen
|
||||
{
|
||||
|
@ -71,9 +43,11 @@ public:
|
|||
bool EventProcess(const Event &event) override;
|
||||
|
||||
protected:
|
||||
void FindMods();
|
||||
void ApplyChanges();
|
||||
void CloseWindow();
|
||||
|
||||
void UpdateAll();
|
||||
void UpdateModList();
|
||||
void UpdateModDetails();
|
||||
void UpdateModSummary();
|
||||
|
@ -87,8 +61,6 @@ protected:
|
|||
CModManager* m_modManager;
|
||||
|
||||
size_t m_modSelectedIndex = 0;
|
||||
bool m_changes = false;
|
||||
bool m_empty = true;
|
||||
};
|
||||
|
||||
} // namespace Ui
|
||||
|
|
Loading…
Reference in New Issue