Skip to content

Commit

Permalink
WIP Path handling. Added code to derive some defaults, fs_game / fs_g…
Browse files Browse the repository at this point in the history
…ame_base, etc.
  • Loading branch information
codereader committed Nov 9, 2017
1 parent b23f9c1 commit dfea33d
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 34 deletions.
2 changes: 2 additions & 0 deletions include/igame.h
Expand Up @@ -11,6 +11,8 @@ const char* const RKEY_GAME_TYPE = "user/game/type";
const char* const RKEY_FS_GAME = "user/game/fs_game";
const char* const RKEY_FS_GAME_BASE = "user/game/fs_game_base";
const char* const RKEY_ENGINE_PATH = "user/paths/enginePath";
const char* const RKEY_MOD_PATH = "user/paths/modPath";
const char* const RKEY_MOD_BASE_PATH = "user/paths/modBasePath";

namespace game
{
Expand Down
88 changes: 66 additions & 22 deletions radiant/settings/GameManager.cpp
Expand Up @@ -13,6 +13,7 @@
#include "os/dir.h"
#include "os/path.h"
#include "os/fs.h"
#include "string/trim.h"
#include "string/convert.h"
#include "string/replace.h"
#include "string/predicate.h"
Expand Down Expand Up @@ -212,6 +213,7 @@ std::string Manager::getUserEnginePath()

void Manager::constructPaths()
{
#if 0
_enginePath = GlobalRegistry().get(RKEY_ENGINE_PATH);

// Make sure it's a well formatted path
Expand Down Expand Up @@ -248,10 +250,12 @@ void Manager::constructPaths()
// No fs_game, no modpath
_modPath = "";
}
#endif
}

bool Manager::userWantsToCorrectSettings() const
{
#if 0
std::stringstream msg("<b>Warning:</b>\n");

if (!os::fileOrDirExists(_enginePath))
Expand All @@ -273,69 +277,106 @@ bool Manager::userWantsToCorrectSettings() const

return wxutil::Messagebox::Show(_("Invalid Settings"),
msg.str(), ui::IDialog::MESSAGE_ASK, NULL) == ui::IDialog::RESULT_YES;
#endif
return false;
}

void Manager::initEnginePath()
{
// Try to retrieve a saved value for the engine path
std::string enginePath = GlobalRegistry().get(RKEY_ENGINE_PATH);
_enginePath = registry::getValue<std::string>(RKEY_ENGINE_PATH);
_modPath = registry::getValue<std::string>(RKEY_MOD_PATH);
_modBasePath = registry::getValue<std::string>(RKEY_MOD_BASE_PATH);

xml::NodeList gameNodeList = GlobalRegistry().findXPath("game");

if (enginePath.empty() && gameNodeList.size() > 0) {
if (_enginePath.empty() && !gameNodeList.empty())
{
// No engine path known, but we have a valid game description
// Try to deduce the engine path from the Registry settings (Win32 only)
std::string regKey = gameNodeList[0].getAttributeValue("registryKey");
std::string regValue = gameNodeList[0].getAttributeValue("registryValue");

rMessage() << "GameManager: Querying Windows Registry for game path: "
<< "HKEY_LOCAL_MACHINE\\"
<< regKey << "\\" << regValue << std::endl;
<< "HKEY_LOCAL_MACHINE\\"
<< regKey << "\\" << regValue << std::endl;

// Query the Windows Registry for a default installation path
// This will return "" for non-Windows environments
enginePath = Win32Registry::getKeyValue(regKey, regValue);
_enginePath = Win32Registry::getKeyValue(regKey, regValue);

rMessage() << "GameManager: Windows Registry returned result: "
<< enginePath << std::endl;
<< _enginePath << std::endl;
}

// If the engine path is still empty, consult the .game file for a fallback value
if (enginePath.empty()) {
if (_enginePath.empty())
{
// No engine path set so far, search the game file for default values
const std::string ENGINEPATH_ATTRIBUTE =
#if defined(WIN32)
"enginepath_win32"
"enginepath_win32"
#elif defined(__linux__) || defined (__FreeBSD__)
"enginepath_linux"
"enginepath_linux"
#elif defined(__APPLE__)
"enginepath_macos"
"enginepath_macos"
#else
#error "unknown platform"
#endif
;
;

enginePath = os::standardPathWithSlash(
_enginePath = os::standardPathWithSlash(
currentGame()->getKeyValue(ENGINEPATH_ATTRIBUTE)
);
}

// Normalise the path in any case
enginePath = os::standardPathWithSlash(enginePath);
_enginePath = os::standardPathWithSlash(_enginePath);

// Take this path and store it into the Registry, it's expected to be there
GlobalRegistry().set(RKEY_ENGINE_PATH, enginePath);
registry::setValue(RKEY_ENGINE_PATH, _enginePath);

#if 0
// Try to do something with the information currently in the Registry
// It should be enough to know the engine path and the fs_game.
constructPaths();

#endif
#if 0
// Check loop, continue, till the user specifies a valid setting
while (!settingsValid())
{
// Engine path doesn't exist, ask the user
ui::GameSetupDialog::Show(cmd::ArgumentList());
//ui::PrefDialog::ShowDialog(_("Game"));
#endif
if (!settingsValid())
{
// Paths not valid, ask the user to select something
ui::GameSetupDialog::Result result = ui::GameSetupDialog::Show(cmd::ArgumentList());

if (!result.enginePath.empty())
{
_currentGameName = result.gameName;
_enginePath = result.enginePath;
_modBasePath = result.modBasePath;
_modPath = result.modPath;

// Persist the settings to the registry
registry::setValue(RKEY_GAME_TYPE, _currentGameName);
registry::setValue(RKEY_ENGINE_PATH, _enginePath);
registry::setValue(RKEY_MOD_PATH, _modPath);
registry::setValue(RKEY_MOD_BASE_PATH, _modBasePath);

// Extract the fs_game / fs_game_base settings from the mod path
std::string fsGame = os::getRelativePath(_modPath, _enginePath);
string::trim_right(fsGame, "/");

std::string fsGameBase = os::getRelativePath(_modBasePath, _enginePath);
string::trim_right(fsGameBase, "/");

registry::setValue(RKEY_FS_GAME, fsGame);
registry::setValue(RKEY_FS_GAME_BASE, fsGameBase);
}
}

#if 0
// After the dialog, the settings are located in the registry.
// Construct the paths with the settings found there
constructPaths();
Expand All @@ -345,6 +386,7 @@ void Manager::initEnginePath()
break;
}
}
#endif

// Register as observer, to get notified about future engine path changes
observeKey(RKEY_ENGINE_PATH);
Expand Down Expand Up @@ -385,16 +427,18 @@ void Manager::addVFSSearchPath(const std::string &path)

bool Manager::settingsValid() const
{
if (os::fileOrDirExists(_enginePath)) {

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

// Check the mod path, if appropriate
if (!_fsGame.empty() && !os::fileOrDirExists(_modPath)) {
if (!_modPath.empty() && !os::fileOrDirExists(_modPath))
{
// Mod name is not empty, but mod folder doesnt' exist
return false;
}
Expand Down
52 changes: 48 additions & 4 deletions radiant/ui/prefdialog/GameSetupDialog.cpp
Expand Up @@ -27,6 +27,8 @@ GameSetupDialog::GameSetupDialog(wxWindow* parent) :
GetSizer()->Add(mainVbox, 1, wxEXPAND | wxALL, 12);

_book = new wxChoicebook(this, wxID_ANY);
_book->Connect(wxEVT_CHOICEBOOK_PAGE_CHANGED, wxBookCtrlEventHandler(GameSetupDialog::onPageChanged), nullptr, this);

wxStaticText* label = new wxStaticText(this, wxID_ANY, _("Please select a Game Type:"));

mainVbox->Add(label);
Expand All @@ -40,7 +42,7 @@ GameSetupDialog::GameSetupDialog(wxWindow* parent) :

// Create the assign shortcut button
wxButton* cancelButton = new wxButton(this, wxID_CANCEL);
cancelButton->Connect(wxEVT_BUTTON, wxCommandEventHandler(GameSetupDialog::onCancel), NULL, this);
cancelButton->Connect(wxEVT_BUTTON, wxCommandEventHandler(GameSetupDialog::onCancel), nullptr, this);

buttonHBox->Add(saveButton, 0, wxRIGHT, 6);
buttonHBox->Add(cancelButton, 0, wxRIGHT, 6);
Expand Down Expand Up @@ -88,11 +90,40 @@ void GameSetupDialog::initialiseControls()

_book->AddPage(container, game->getKeyValue("name"));
}

// Select the currently active game type
setSelectedPage(registry::getValue<std::string>(RKEY_GAME_TYPE));
}

void GameSetupDialog::setSelectedPage(const std::string& name)
{
for (std::size_t i = 0; i < _book->GetPageCount(); ++i)
{
wxWindow* container = _book->GetPage(i);

GameSetupPage* page = dynamic_cast<GameSetupPage*>(wxWindow::FindWindowByName("GameSetupPage", container));

assert(page != nullptr);

wxStringClientData* data = static_cast<wxStringClientData*>(page->GetClientData());

if (data->GetData() == name)
{
_book->SetSelection(i);
page->onPageShown();
return;
}
}
}

GameSetupPage* GameSetupDialog::getSelectedPage()
{
// Extract the game type value from the current page and save it to the registry
return getPage(_book->GetSelection());
}

GameSetupPage* GameSetupDialog::getPage(int num)
{
// Find the actual GameSetupPage in the window hierarchy
wxWindow* container = _book->GetPage(_book->GetSelection());
return dynamic_cast<GameSetupPage*>(wxWindow::FindWindowByName("GameSetupPage", container));
}
Expand Down Expand Up @@ -146,6 +177,19 @@ void GameSetupDialog::onCancel(wxCommandEvent& ev)
EndModal(wxID_CANCEL);
}

void GameSetupDialog::onPageChanged(wxBookCtrlEvent& ev)
{
if (ev.GetSelection() != wxNOT_FOUND)
{
GameSetupPage* page = getPage(ev.GetSelection());

if (page != nullptr)
{
page->onPageShown();
}
}
}

GameSetupDialog::Result GameSetupDialog::Show(const cmd::ArgumentList& args)
{
GameSetupDialog::Result result;
Expand All @@ -159,9 +203,9 @@ GameSetupDialog::Result GameSetupDialog::Show(const cmd::ArgumentList& args)

if (dialog->ShowModal() == wxID_OK)
{
result.gameType = dialog->getSelectedGameType();
result.gameName = dialog->getSelectedGameType();

if (result.gameType.empty())
if (result.gameName.empty())
{
rError() << "Cannot save game paths, nothing selected" << std::endl;
return result;
Expand Down
6 changes: 5 additions & 1 deletion radiant/ui/prefdialog/GameSetupDialog.h
Expand Up @@ -5,6 +5,7 @@
#include "GameSetupPage.h"

class wxChoicebook;
class wxBookCtrlEvent;

namespace ui
{
Expand Down Expand Up @@ -35,7 +36,7 @@ class GameSetupDialog :
// The result after the user is done with the dialog
struct Result
{
std::string gameType; // Display name of the selected game
std::string gameName; // Display name of the selected game
std::string enginePath; // selected engine path
std::string modPath; // selected mod path
std::string modBasePath; // selected mod base path
Expand All @@ -47,11 +48,14 @@ class GameSetupDialog :

private:
GameSetupPage* getSelectedPage();
GameSetupPage* getPage(int num);
void setSelectedPage(const std::string& name);

void initialiseControls();

void onSave(wxCommandEvent& ev);
void onCancel(wxCommandEvent& ev);
void onPageChanged(wxBookCtrlEvent& ev);
};

}
3 changes: 3 additions & 0 deletions radiant/ui/prefdialog/GameSetupPage.h
Expand Up @@ -39,6 +39,9 @@ class GameSetupPage :
// GameSettingsInvalidException in case something is not correct.
virtual void validateSettings() = 0;

// Called by the owning GameSetupDialog when this page is selected
virtual void onPageShown() = 0;

// The following three path accessors are needed by the owning GameManager
// to continue setting up the VFS search order, map paths, etc.

Expand Down

0 comments on commit dfea33d

Please sign in to comment.