Skip to content

Commit

Permalink
Reworked addon folder management and logic.
Browse files Browse the repository at this point in the history
  • Loading branch information
Friendly0Fire committed Jan 31, 2022
1 parent 682c6cf commit 9722919
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 102 deletions.
6 changes: 2 additions & 4 deletions GW2Radial/include/ConfigurationFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,14 @@ class ConfigurationFile : public Singleton<ConfigurationFile>

CSimpleIniA& ini() { return ini_; }

const std::wstring& folder() const { return folder_; }
const auto& folder() const { return folder_; }

protected:
static std::tuple<bool /*exists*/, bool /*writable*/> CheckFolder(const std::filesystem::path& folder);
static void LoadImGuiSettings(const std::wstring& location);
static void SaveImGuiSettings(const std::wstring& location);

CSimpleIniA ini_;
std::wstring folder_;
std::wstring location_, imguiLocation_;
std::optional<std::filesystem::path> folder_;

bool lastSaveErrorChanged_ = false;
std::string lastSaveError_;
Expand Down
2 changes: 2 additions & 0 deletions GW2Radial/include/Main.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
#include <wrl.h>
#include <d3d9.h>
#include <fstream>
#include <filesystem>

#include <Resource.h>
#include <Log.h>

#define NULL_COALESCE(a, b) ((a) != nullptr ? (a) : (b))
#define OPT_COALESCE(a, b) ((a) ? (a) : (b))
#define SQUARE(x) ((x) * (x))

template <typename... Args>
Expand Down
33 changes: 3 additions & 30 deletions GW2Radial/include/Utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,36 +161,9 @@ constexpr uint operator "" _len(const char*, size_t len) {
return uint(len);
}

struct AddonFolders {
std::filesystem::path programFiles, myDocuments;
};

inline AddonFolders GetAddonFolders() {
wchar_t exeFullPath[MAX_PATH];
GetModuleFileNameW(nullptr, exeFullPath, MAX_PATH);
std::wstring exeFolder;
SplitFilename(exeFullPath, &exeFolder, nullptr);

wchar_t* myDocuments;
if(FAILED(SHGetKnownFolderPath(FOLDERID_Documents, KF_FLAG_CREATE, nullptr, &myDocuments)))
myDocuments = nullptr;

const auto programFilesLocation = std::filesystem::path(exeFolder + L"\\addons\\gw2radial\\");
const auto myDocumentsLocation = myDocuments ? std::filesystem::path(std::wstring(myDocuments) + L"\\GUILD WARS 2\\addons\\gw2radial\\") : std::filesystem::path();

return { programFilesLocation, myDocumentsLocation };
}

inline std::filesystem::path GetAddonFolder() {
auto folders = GetAddonFolders();

if(std::filesystem::exists(folders.programFiles))
return folders.programFiles;
else if(std::filesystem::exists(folders.myDocuments))
return folders.myDocuments;
else
return {};
}
std::filesystem::path GetGameFolder();
std::optional<std::filesystem::path> GetDocumentsFolder();
std::optional<std::filesystem::path> GetAddonFolder();

template<typename T>
T safe_toupper(T c) {
Expand Down
73 changes: 29 additions & 44 deletions GW2Radial/src/ConfigurationFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,34 +19,42 @@ ConfigurationFile::ConfigurationFile()

void ConfigurationFile::Reload()
{
auto folders = GetAddonFolders();
auto [pfExists, pfWritable] = CheckFolder(folders.programFiles);
auto [mdExists, mdWritable] = CheckFolder(folders.myDocuments);

ini_.SetUnicode();
if(pfExists)
auto folder = GetAddonFolder();
if (!folder)
{
ini_.LoadFile((folders.programFiles / g_configName).c_str());
LoadImGuiSettings(folders.programFiles / g_imguiConfigName);
folder_ = std::nullopt;
return;
}
else if(mdExists)

FILE* fp = nullptr;
if (_wfopen_s(&fp, (*folder / g_configName).c_str(), L"ab") != 0)
{
ini_.LoadFile((folders.myDocuments / g_configName).c_str());
LoadImGuiSettings(folders.myDocuments / g_imguiConfigName);
Log::i().Print(Severity::Error, L"Could write to config file '{}'.", (*folder / g_configName).wstring());
folder_ = std::nullopt;
return;
}

if(pfWritable)
folder_ = folders.programFiles;
else
folder_ = folders.myDocuments;
else if (fp)
fclose(fp);

location_ = folder_ + g_configName;
imguiLocation_ = folder_ + g_imguiConfigName;
ini_.SetUnicode();
ini_.LoadFile((*folder / g_configName).c_str());
LoadImGuiSettings(*folder / g_imguiConfigName);
folder_ = folder;

Log::i().Print(Severity::Info, L"Config folder is now '{}'.", folder_->wstring());
}

void ConfigurationFile::Save()
{
const auto r = ini_.SaveFile(location_.c_str());
if (!folder_)
{
const auto prevSaveError = lastSaveError_;
lastSaveError_ = "No configuration folder could be located.";
lastSaveErrorChanged_ |= prevSaveError != lastSaveError_;
return;
}

const auto r = ini_.SaveFile((*folder_ / g_configName).c_str());

if (r < 0)
{
Expand Down Expand Up @@ -82,31 +90,8 @@ void ConfigurationFile::Save()

void ConfigurationFile::OnUpdate() const
{
SaveImGuiSettings(imguiLocation_);
}

std::tuple<bool /*exists*/, bool /*writable*/> ConfigurationFile::CheckFolder(const std::filesystem::path& folder)
{
const auto filepath = folder / g_configName;

bool exists = true, writable = true;

if (filepath.empty() || !std::filesystem::exists(filepath))
writable = exists = false;

if(exists && SHCreateDirectoryExW(nullptr, folder.c_str(), nullptr) == ERROR_ACCESS_DENIED)
writable = false;

if(writable)
{
FILE *fp = nullptr;
if(_wfopen_s(&fp, filepath.c_str(), L"ab") != 0)
writable = false;
else if(fp)
fclose(fp);
}

return { exists, writable };
if(folder_)
SaveImGuiSettings(*folder_ / g_imguiConfigName);
}

void ConfigurationFile::LoadImGuiSettings(const std::wstring & location)
Expand Down
53 changes: 29 additions & 24 deletions GW2Radial/src/CustomWheel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,38 +271,43 @@ void CustomWheelsManager::Reload(IDirect3DDevice9* dev)
customWheels_.clear();
}

cref folderBase = ConfigurationFile::i().folder() + L"custom\\";
if(std::filesystem::exists(folderBase))
auto folderBaseOpt = ConfigurationFile::i().folder();
if (folderBaseOpt)
{
auto addWheel = [&](const std::filesystem::path& configFile)
auto folderBase = *folderBaseOpt / L"custom";

if (std::filesystem::exists(folderBase))
{
auto wheel = BuildWheel(configFile, dev);
if (wheel)
auto addWheel = [&](const std::filesystem::path& configFile)
{
wheels_.push_back(std::move(wheel));
customWheels_.push_back(wheels_.back().get());
}
};

for(cref entry : std::filesystem::directory_iterator(folderBase))
{
if(!entry.is_directory() && entry.path().extension() != L".zip")
continue;
auto wheel = BuildWheel(configFile, dev);
if (wheel)
{
wheels_.push_back(std::move(wheel));
customWheels_.push_back(wheels_.back().get());
}
};

std::filesystem::path configFile = entry.path() / L"config.ini";
if (FileSystem::Exists(configFile))
addWheel(configFile);
else if (auto dirs = FileSystem::IterateZipFolders(entry.path()); !dirs.empty())
for (cref entry : std::filesystem::directory_iterator(folderBase))
{
for (cref subdir : dirs)
if (!entry.is_directory() && entry.path().extension() != L".zip")
continue;

std::filesystem::path configFile = entry.path() / L"config.ini";
if (FileSystem::Exists(configFile))
addWheel(configFile);
else if (auto dirs = FileSystem::IterateZipFolders(entry.path()); !dirs.empty())
{
std::filesystem::path subdirCfgFile = subdir / L"config.ini";
if (FileSystem::Exists(subdirCfgFile))
addWheel(subdirCfgFile);
for (cref subdir : dirs)
{
std::filesystem::path subdirCfgFile = subdir / L"config.ini";
if (FileSystem::Exists(subdirCfgFile))
addWheel(subdirCfgFile);
}
}

}

}
}
}

loaded_ = true;
Expand Down
56 changes: 56 additions & 0 deletions GW2Radial/src/Utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,62 @@ void DumpSurfaceToDiskTGA(IDirect3DDevice9* dev, IDirect3DSurface9* surf, uint b
surf2->UnlockRect();
}

std::filesystem::path GetGameFolder()
{
wchar_t exeFullPath[MAX_PATH];
GetModuleFileNameW(nullptr, exeFullPath, MAX_PATH);
std::wstring exeFolder;
SplitFilename(exeFullPath, &exeFolder, nullptr);

return exeFolder;
}

std::optional<std::filesystem::path> GetDocumentsFolder()
{
wchar_t* myDocuments;
if (FAILED(SHGetKnownFolderPath(FOLDERID_Documents, KF_FLAG_CREATE, nullptr, &myDocuments)))
return std::nullopt;

std::filesystem::path documentsGW2 = myDocuments;
documentsGW2 /= L"GUILD WARS 2";

if (std::filesystem::is_directory(documentsGW2))
return documentsGW2;

return std::nullopt;
}

std::optional<std::filesystem::path> GetAddonFolder()
{
auto folder = (GetGameFolder() / "addons/gw2radial").make_preferred();

if (std::filesystem::is_directory(folder))
return folder;

if (SUCCEEDED(SHCreateDirectoryExW(nullptr, folder.c_str(), nullptr)))
return folder;

Log::i().Print(Severity::Warn, L"Could not open or create configuration folder '{}'.", folder.wstring());

auto docs = GetDocumentsFolder();
if (!docs) {
Log::i().Print(Severity::Error, L"Could not locate Documents folder (fallback).");
return std::nullopt;
}

folder = (*docs / "addons/gw2radial").make_preferred();

if (std::filesystem::is_directory(folder))
return folder;

if (SUCCEEDED(SHCreateDirectoryExW(nullptr, folder.c_str(), nullptr)))
return folder;

Log::i().Print(Severity::Error, L"Could not open or create configuration folder '{}'.", folder.wstring());

return std::nullopt;
}

std::span<const wchar_t*> GetCommandLineArgs() {
auto cmdLine = GetCommandLineW();
int num = 0;
Expand Down

0 comments on commit 9722919

Please sign in to comment.