Skip to content

Commit

Permalink
#5231: Move PreferenceSystem to the core module. This required a few …
Browse files Browse the repository at this point in the history
…interfaces to be created along the way.

The GameManager is already prepared to be moved, which is the next step.
  • Loading branch information
codereader committed May 2, 2020
1 parent aa28109 commit 3dafa39
Show file tree
Hide file tree
Showing 24 changed files with 356 additions and 251 deletions.
27 changes: 27 additions & 0 deletions include/igame.h
Expand Up @@ -3,6 +3,7 @@
#include "xmlutil/Node.h"
#include "imodule.h"
#include <list>
#include <string>

// String identifier for the game manager module
const char* const MODULE_GAMEMANAGER("GameManager");
Expand Down Expand Up @@ -53,6 +54,28 @@ class IGame

typedef std::shared_ptr<IGame> IGamePtr;

/**
* Represents the game configuration as specified by the user
* in the Game Settings dialog, comprising Game name,
* engine path, mod path, etc.
*/
struct GameConfiguration
{
// The name of the current game, e.g. "Doom 3"
std::string gameType;

// The engine path (pointing to the game executable)
std::string enginePath;

// The "userengine" path (where the fs_game is stored)
// this is ~/.doom3/<fs_game> in linux, and <enginepath>/<fs_game> in Win32
std::string modBasePath;

// The "mod mod" path (where the fs_game_base is stored)
// this is ~/.doom3/<fs_game_base> in linux, and <enginepath>/<fs_game_base> in Win32
std::string modPath;
};

/**
* \brief
* Interface for the game management module.
Expand Down Expand Up @@ -98,6 +121,10 @@ class IGameManager :

// Returns the absolute path where prefabs are going to be saved to
virtual const std::string& getPrefabPath() = 0;

// Activates the given mod configuration
// Stores the given config, initialises VFS and constructs a few secondary paths
virtual void applyConfig(const GameConfiguration& config) = 0;
};
typedef std::shared_ptr<IGameManager> IGameManagerPtr;

Expand Down
99 changes: 99 additions & 0 deletions include/ipreferencesystem.h
Expand Up @@ -6,6 +6,86 @@
// A list containing possible values for a combo box widgets
typedef std::list<std::string> ComboBoxValueList;

// Common interface of all preference items (labels, combo boxes, etc.)
// All of them can carry a title and a registry key
class IPreferenceItemBase
{
public:
virtual ~IPreferenceItemBase() {}

typedef std::shared_ptr<IPreferenceItemBase> Ptr;

virtual const std::string& getLabel() const = 0;

virtual const std::string& getRegistryKey() const = 0;

virtual void setRegistryKey(const std::string& key) = 0;
};

class IPreferenceLabel :
public virtual IPreferenceItemBase
{
public:
virtual ~IPreferenceLabel() {}
};

class IPreferenceEntry :
public virtual IPreferenceItemBase
{
public:
virtual ~IPreferenceEntry() {}
};

class IPreferenceCheckbox :
public virtual IPreferenceItemBase
{
public:
virtual ~IPreferenceCheckbox() {}
};

class IPreferenceCombobox :
public virtual IPreferenceItemBase
{
public:
virtual ~IPreferenceCombobox() {}

virtual const ComboBoxValueList& getValues() const = 0;
virtual bool storeValueNotIndex() const = 0;
};

class IPreferencePathEntry :
public virtual IPreferenceItemBase
{
public:
virtual ~IPreferencePathEntry() {}

virtual bool browseDirectories() const = 0;
};

class IPreferenceSpinner :
public virtual IPreferenceItemBase
{
public:
virtual ~IPreferenceSpinner() {}

virtual double getLower() = 0;
virtual double getUpper() = 0;
virtual int getFraction() = 0;
};

class IPreferenceSlider :
public virtual IPreferenceItemBase
{
public:
virtual ~IPreferenceSlider() {}

virtual double getLower() = 0;
virtual double getUpper() = 0;
virtual double getStepIncrement() = 0;
virtual double getPageIncrement() = 0;
virtual int getFactor() = 0;
};

/* greebo: This is the interface the preference page has to provide for adding
* elements to the dialog page. */
class IPreferencePage
Expand All @@ -14,6 +94,9 @@ class IPreferencePage
// destructor
virtual ~IPreferencePage() {}

// Returns the title as displayed on top of the page's area
virtual const std::string& getTitle() const = 0;

/**
* greebo: Allows to set a custom title of this page. The default title
* upon construction is "guessed" by adding a " Settings" to
Expand All @@ -23,6 +106,17 @@ class IPreferencePage
*/
virtual void setTitle(const std::string& title) = 0;

// greebo: Returns the name (caption) of this Page (e.g. "Settings")
virtual const std::string& getName() const = 0;

// The preference path leading to this page
virtual const std::string& getPath() const = 0;

// Returns TRUE if this page doesn't hold any items
virtual bool isEmpty() const = 0;

virtual void foreachItem(const std::function<void(const IPreferenceItemBase::Ptr&)>& functor) const = 0;

// greebo: Use this to add a checkbox to the preference dialog that is connected to a registry value
virtual void appendCheckBox(const std::string& label, const std::string& registryKey) = 0;

Expand Down Expand Up @@ -92,6 +186,11 @@ class IPreferenceSystem :
* @returns: the IPreferencePage reference.
*/
virtual IPreferencePage& getPage(const std::string& path) = 0;

/**
* Visit each page, covering the whole tree
*/
virtual void foreachPage(const std::function<void(IPreferencePage&)>& functor) = 0;
};

inline IPreferenceSystem& GlobalPreferenceSystem()
Expand Down
75 changes: 75 additions & 0 deletions libs/GameConfigUtil.h
@@ -0,0 +1,75 @@
#pragma once

#include "igame.h"

#include "registry/registry.h"
#include "os/path.h"
#include "os/file.h"

namespace game
{

/**
* Some algorithms built around the GameConfiguration class.
*/
class GameConfigUtil
{
public:
// Loads the property values of this instance from the XMLRegistry
static GameConfiguration LoadFromRegistry()
{
GameConfiguration result;

result.gameType = registry::getValue<std::string>(RKEY_GAME_TYPE);
result.enginePath = os::standardPathWithSlash(registry::getValue<std::string>(RKEY_ENGINE_PATH));
result.modPath = os::standardPathWithSlash(registry::getValue<std::string>(RKEY_MOD_PATH));
result.modBasePath = os::standardPathWithSlash(registry::getValue<std::string>(RKEY_MOD_BASE_PATH));

return result;
}

// Persists the values of this instance to the XMLRegistry
static void SaveToRegistry(const GameConfiguration& config)
{
registry::setValue(RKEY_GAME_TYPE, config.gameType);
registry::setValue(RKEY_ENGINE_PATH, config.enginePath);
registry::setValue(RKEY_MOD_PATH, config.modPath);
registry::setValue(RKEY_MOD_BASE_PATH, config.modBasePath);
}

// Makes sure that all paths are normalised OS paths
static void EnsurePathsNormalised(GameConfiguration& config)
{
config.enginePath = os::standardPathWithSlash(config.enginePath);
config.modPath = os::standardPathWithSlash(config.modPath);
config.modBasePath = os::standardPathWithSlash(config.modBasePath);
}

// Returns true if the paths in this config are pointing to valid OS folders
static bool PathsValid(const GameConfiguration& config)
{
if (!os::fileOrDirExists(config.enginePath))
{
// Engine path doesn't exist
return false;
}

// Check the mod base path, if appropriate
if (!config.modBasePath.empty() && !os::fileOrDirExists(config.modBasePath))
{
// Mod base name is not empty, but folder doesnt' exist
return false;
}

// Check the mod path, if appropriate
if (!config.modPath.empty() && !os::fileOrDirExists(config.modPath))
{
// Mod name is not empty, but mod folder doesnt' exist
return false;
}

return true; // all paths ok
}
};

}
86 changes: 0 additions & 86 deletions radiant/settings/GameConfiguration.h

This file was deleted.

11 changes: 5 additions & 6 deletions radiant/settings/GameManager.cpp
Expand Up @@ -69,8 +69,7 @@ void Manager::initialiseModule(const ApplicationContext& ctx)
initialiseGameType();

// Try to retrieve a persisted game setup from the registry
GameConfiguration config;
config.loadFromRegistry();
GameConfiguration config = GameConfigUtil::LoadFromRegistry();

// Read command line parameters, these override any existing preference setting
// but only if we have a valid engine path
Expand Down Expand Up @@ -105,7 +104,7 @@ void Manager::initialiseModule(const ApplicationContext& ctx)

// Check validity of the saved game configuration
// and invoke the UI if it's not a valid one.
if (config.pathsValid())
if (GameConfigUtil::PathsValid(config))
{
applyConfig(config);
}
Expand Down Expand Up @@ -219,15 +218,15 @@ std::string Manager::getUserEnginePath()

void Manager::applyConfig(const GameConfiguration& config)
{
if (!config.pathsValid())
if (!GameConfigUtil::PathsValid(config))
{
rError() << "GameManager: Cannot apply invalid configuration, paths not valid" << std::endl;
return;
}

// Store the configuration, and persist it to the registry
_config = config;
_config.saveToRegistry();
GameConfigUtil::SaveToRegistry(_config);

// Extract the fs_game / fs_game_base settings from the mod path
std::string fsGame = os::getRelativePath(_config.modPath, _config.enginePath);
Expand Down Expand Up @@ -288,7 +287,7 @@ void Manager::setMapAndPrefabPaths(const std::string& baseGamePath)
void Manager::initialiseVfs()
{
// Ensure that all paths are normalised
_config.ensurePathsNormalised();
GameConfigUtil::EnsurePathsNormalised(_config);

// The list of paths which will be passed to the VFS init method
vfs::SearchPaths vfsSearchPaths;
Expand Down

0 comments on commit 3dafa39

Please sign in to comment.