From 2a617b335901d07f6090aa22a596f3f7221d7f6c Mon Sep 17 00:00:00 2001 From: William JCM Date: Wed, 21 Jul 2021 14:36:49 +0200 Subject: [PATCH] MassBuilderManager: move functionality to SaveTool. And also improve the main menu too. --- src/CMakeLists.txt | 2 - src/MassBuilderManager/MassBuilderManager.cpp | 87 --------------- src/MassBuilderManager/MassBuilderManager.h | 51 --------- src/SaveTool/SaveTool.cpp | 104 +++++++++++++----- src/SaveTool/SaveTool.h | 26 +++-- src/SaveTool/SaveTool_MainManager.cpp | 12 +- src/SaveTool/SaveTool_drawMainMenu.cpp | 17 ++- 7 files changed, 108 insertions(+), 191 deletions(-) delete mode 100644 src/MassBuilderManager/MassBuilderManager.cpp delete mode 100644 src/MassBuilderManager/MassBuilderManager.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a88d0ae..a4d41a1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -36,8 +36,6 @@ add_executable(MassBuilderSaveTool WIN32 SaveTool/SaveTool_drawMainMenu.cpp SaveTool/SaveTool_MainManager.cpp SaveTool/SaveTool_ProfileManager.cpp - MassBuilderManager/MassBuilderManager.h - MassBuilderManager/MassBuilderManager.cpp ProfileManager/ProfileManager.h ProfileManager/ProfileManager.cpp Profile/Profile.h diff --git a/src/MassBuilderManager/MassBuilderManager.cpp b/src/MassBuilderManager/MassBuilderManager.cpp deleted file mode 100644 index 2ac969a..0000000 --- a/src/MassBuilderManager/MassBuilderManager.cpp +++ /dev/null @@ -1,87 +0,0 @@ -// MassBuilderSaveTool -// Copyright (C) 2021 Guillaume Jacquemin -// -// 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 . - -#include "MassBuilderManager.h" - -#include -#include -#include - -#include -#include - -using namespace Corrade; - -MassBuilderManager::MassBuilderManager() { - _ready = findSaveDirectory(); -} - -auto MassBuilderManager::ready() const -> bool { - return _ready; -} - -auto MassBuilderManager::lastError() -> std::string const& { - return _lastError; -} - -auto MassBuilderManager::saveDirectory() -> std::string const& { - return _saveDirectory; -} - -void MassBuilderManager::checkGameState() { - WTS_PROCESS_INFOW* process_infos = nullptr; - unsigned long process_count = 0; - - if(WTSEnumerateProcessesW(WTS_CURRENT_SERVER_HANDLE, 0, 1, &process_infos, &process_count)) { - Containers::ScopeGuard guard{process_infos, WTSFreeMemory}; - - for(unsigned long i = 0; i < process_count; ++i) { - if(std::wcscmp(process_infos[i].pProcessName, L"MASS_Builder-Win64-Shipping.exe") == 0) { - _gameState = GameState::Running; - break; - } - else { - _gameState = GameState::NotRunning; - } - } - } - else { - _gameState = GameState::Unknown; - } -} - -auto MassBuilderManager::gameState() -> GameState { - return _gameState; -} - -auto MassBuilderManager::findSaveDirectory() -> bool { - wchar_t* localappdata_path; - Containers::ScopeGuard guard{localappdata_path, CoTaskMemFree}; - if(SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_NO_APPCONTAINER_REDIRECTION, nullptr, &localappdata_path) != S_OK) - { - _lastError = "SHGetKnownFolderPath() failed in MassBuilderManager::findSaveDirectory()"; - return false; - } - - _saveDirectory = Utility::Directory::join(Utility::Directory::fromNativeSeparators(Utility::Unicode::narrow(localappdata_path)), "MASS_Builder"); - - if(!Utility::Directory::exists(_saveDirectory)) { - _lastError = _saveDirectory + " wasn't found."; - return false; - } - - return true; -} diff --git a/src/MassBuilderManager/MassBuilderManager.h b/src/MassBuilderManager/MassBuilderManager.h deleted file mode 100644 index 82a902c..0000000 --- a/src/MassBuilderManager/MassBuilderManager.h +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -// MassBuilderSaveTool -// Copyright (C) 2021 Guillaume Jacquemin -// -// 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 . - -#include - -#include - -using namespace Magnum; - -enum class GameState : UnsignedByte { - Unknown, NotRunning, Running -}; - -class MassBuilderManager { - public: - MassBuilderManager(); - - auto ready() const -> bool; - auto lastError() -> std::string const&; - - auto saveDirectory() -> std::string const&; - - void checkGameState(); - auto gameState() -> GameState; - - private: - auto findSaveDirectory() -> bool; - - bool _ready = false; - - std::string _lastError = ""; - - std::string _saveDirectory = ""; - - GameState _gameState = GameState::Unknown; -}; diff --git a/src/SaveTool/SaveTool.cpp b/src/SaveTool/SaveTool.cpp index ebf3cd1..5f01873 100644 --- a/src/SaveTool/SaveTool.cpp +++ b/src/SaveTool/SaveTool.cpp @@ -18,6 +18,8 @@ #include +#include +#include #include #include #include @@ -32,6 +34,8 @@ #include #include #include +#include +#include #include "../FontAwesome/IconsFontAwesome5.h" #include "../FontAwesome/IconsFontAwesome5Brands.h" @@ -59,11 +63,11 @@ SaveTool::SaveTool(const Arguments& arguments): Utility::Debug{} << "Clickthrough is available."; } else { - Utility::Debug{} << "Clickthrough is not available (hint couldn't be set)."; + Utility::Warning{} << "Clickthrough is not available (hint couldn't be set)."; } } else { - Utility::Debug{} << "Clickthrough is not available (SDL2 is too old)."; + Utility::Warning{} << "Clickthrough is not available (SDL2 is too old)."; } GL::Renderer::enable(GL::Renderer::Feature::Blending); @@ -79,7 +83,33 @@ SaveTool::SaveTool(const Arguments& arguments): if((_initEventId = SDL_RegisterEvents(1)) == UnsignedInt(-1)) { SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", - "SDL_RegisterEvents failed in SaveTool::SaveTool(). Exiting...", nullptr); + "SDL_RegisterEvents failed in SaveTool::SaveTool(). Exiting...", window()); + exit(EXIT_FAILURE); + } + + if(!findGameDataDirectory()) { + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error initialising the app", _lastError.c_str(), window()); + exit(EXIT_FAILURE); + } + + _configDir = Utility::Directory::join(_gameDataDir, "Saved/Config/WindowsNoEditor"); + _saveDir = Utility::Directory::join(_gameDataDir, "Saved/SaveGames"); + _screenshotsDir = Utility::Directory::join(_gameDataDir, "Saved/Screenshots/WindowsNoEditor"); + + if(SDL_InitSubSystem(SDL_INIT_TIMER) != 0) { + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error initialising the app", SDL_GetError(), window()); + exit(EXIT_FAILURE); + } + + checkGameState(); + _gameCheckTimerId = SDL_AddTimer(2000, + [](UnsignedInt interval, void* param)->UnsignedInt{ + static_cast(param)->checkGameState(); + return interval; + }, + this); + if(_gameCheckTimerId == 0) { + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", SDL_GetError(), window()); exit(EXIT_FAILURE); } } @@ -215,22 +245,6 @@ void SaveTool::initEvent(SDL_Event& event) { case InitSuccess: _uiState = UiState::ProfileManager; ImGui::CloseCurrentPopup(); - SDL_InitSubSystem(SDL_INIT_TIMER); - _mbManager->checkGameState(); - _gameCheckTimerId = SDL_AddTimer(2000, - [](UnsignedInt interval, void* param)->UnsignedInt{ - static_cast(param)->checkGameState(); - return interval; - }, - _mbManager.get()); - if(_gameCheckTimerId == 0) { - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", SDL_GetError(), window()); - exit(EXIT_FAILURE); - } - break; - case MbManagerFailure: - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error initialising MassBuilderManager", _mbManager->lastError().c_str(), window()); - exit(EXIT_FAILURE); break; case ProfileManagerFailure: SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error initialising ProfileManager", _profileManager->lastError().c_str(), window()); @@ -290,14 +304,7 @@ void SaveTool::initialiseManager() { SDL_zero(event); event.type = _initEventId; - _mbManager.emplace(); - if(!_mbManager->ready()) { - event.user.code = MbManagerFailure; - SDL_PushEvent(&event); - return; - } - - _profileManager.emplace(_mbManager->saveDirectory()); + _profileManager.emplace(_gameDataDir); if(!_profileManager->ready()) { event.user.code = ProfileManagerFailure; SDL_PushEvent(&event); @@ -308,6 +315,25 @@ void SaveTool::initialiseManager() { SDL_PushEvent(&event); } +auto SaveTool::findGameDataDirectory() -> bool { + wchar_t* localappdata_path = nullptr; + Containers::ScopeGuard guard{localappdata_path, CoTaskMemFree}; + if(SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_NO_APPCONTAINER_REDIRECTION, nullptr, &localappdata_path) != S_OK) + { + _lastError = "SHGetKnownFolderPath() failed in SaveTool::findGameDataDirectory()"; + return false; + } + + _gameDataDir = Utility::Directory::join(Utility::Directory::fromNativeSeparators(Utility::Unicode::narrow(localappdata_path)), "MASS_Builder"); + + if(!Utility::Directory::exists(_gameDataDir)) { + _lastError = _gameDataDir + " wasn't found. Make sure to play the game at least once."; + return false; + } + + return true; +} + void SaveTool::initialiseMassManager() { _currentProfile->refreshValues(); @@ -450,7 +476,7 @@ void SaveTool::drawGameState() { ImGui::TextUnformatted("Game state:"); ImGui::SameLine(); { - switch(_mbManager->gameState()) { + switch(_gameState) { case GameState::Unknown: ImGui::TextColored(ImColor{0xff00a5ff}, ICON_FA_CIRCLE); drawTooltip("unknown"); @@ -489,3 +515,25 @@ void SaveTool::drawTooltip(const char* text, Float wrap_pos) { void SaveTool::openUri(const std::string& uri) { ShellExecuteW(nullptr, nullptr, Utility::Unicode::widen(uri).c_str(), nullptr, nullptr, SW_SHOW); } + +void SaveTool::checkGameState() { + WTS_PROCESS_INFOW* process_infos = nullptr; + unsigned long process_count = 0; + + if(WTSEnumerateProcessesW(WTS_CURRENT_SERVER_HANDLE, 0, 1, &process_infos, &process_count)) { + Containers::ScopeGuard guard{process_infos, WTSFreeMemory}; + + for(unsigned long i = 0; i < process_count; ++i) { + if(std::wcscmp(process_infos[i].pProcessName, L"MASS_Builder-Win64-Shipping.exe") == 0) { + _gameState = GameState::Running; + break; + } + else { + _gameState = GameState::NotRunning; + } + } + } + else { + _gameState = GameState::Unknown; + } +} diff --git a/src/SaveTool/SaveTool.h b/src/SaveTool/SaveTool.h index b03eea0..2d89d47 100644 --- a/src/SaveTool/SaveTool.h +++ b/src/SaveTool/SaveTool.h @@ -31,7 +31,6 @@ #include -#include "../MassBuilderManager/MassBuilderManager.h" #include "../ProfileManager/ProfileManager.h" #include "../MassManager/MassManager.h" @@ -68,7 +67,6 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener enum InitStatus: Int { InitSuccess, - MbManagerFailure, ProfileManagerFailure }; void initEvent(SDL_Event& event); @@ -76,6 +74,7 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener // Initialisation methods void initialiseGui(); void initialiseManager(); + auto findGameDataDirectory() -> bool; void initialiseMassManager(); void initialiseFileWatcher(); @@ -106,7 +105,7 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener template auto drawUnsafeWidget(Functor func, Args... args) -> bool { - GameState game_state = _mbManager->gameState(); + GameState game_state = _gameState; // Copying the value to reduce the risk of a data race. if(!_unsafeMode && game_state != GameState::NotRunning) { ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.5f); @@ -125,7 +124,7 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener template void drawUnsafeText(const char* text, Args... args) { // Alternative to the above, for ImGui::Text*() variants. - if(!_unsafeMode && _mbManager->gameState() != GameState::NotRunning) { + if(!_unsafeMode && _gameState != GameState::NotRunning) { ImGui::TextDisabled(text, std::forward(args)...); } else { @@ -135,6 +134,8 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener void openUri(const std::string& uri); + void checkGameState(); + Utility::Resource _rs{"assets"}; // GUI-related members @@ -145,8 +146,7 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener Initialising, ProfileManager, MainManager - }; - UiState _uiState{UiState::Disclaimer}; + } _uiState{UiState::Disclaimer}; bool _aboutPopup{false}; #ifdef SAVETOOL_DEBUG_BUILD @@ -158,8 +158,18 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener std::thread _thread; UnsignedInt _initEventId; - Containers::Pointer _mbManager; - SDL_TimerID _gameCheckTimerId; + std::string _lastError; + + std::string _gameDataDir; + std::string _configDir; + std::string _saveDir; + std::string _screenshotsDir; + + enum class GameState : UnsignedByte { + Unknown, NotRunning, Running + } _gameState{GameState::Unknown}; + + SDL_TimerID _gameCheckTimerId = 0; Containers::Pointer _profileManager; Profile* _currentProfile{nullptr}; diff --git a/src/SaveTool/SaveTool_MainManager.cpp b/src/SaveTool/SaveTool_MainManager.cpp index e1c4d10..22f1f9b 100644 --- a/src/SaveTool/SaveTool_MainManager.cpp +++ b/src/SaveTool/SaveTool_MainManager.cpp @@ -161,9 +161,9 @@ auto SaveTool::drawRenamePopup(Containers::ArrayView name_view) -> bool { ImGuiInputTextFlags_CallbackCharFilter, callback, nullptr); ImGui::SameLine(); - GameState game_state = _mbManager->gameState(); + GameState game_state = _gameState; if((!_unsafeMode && game_state != GameState::NotRunning) || - !(len >= 6 && len <= 32) || + !(len >= 6 && len <= 32) || !(name_view[0] != ' ' && name_view[len - 1] != ' ')) { ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); @@ -176,7 +176,7 @@ auto SaveTool::drawRenamePopup(Containers::ArrayView name_view) -> bool { } if((!_unsafeMode && game_state != GameState::NotRunning) || - !(len >= 6 && len <= 32) || + !(len >= 6 && len <= 32) || !(name_view[0] != ' ' && name_view[len - 1] != ' ')) { ImGui::PopItemFlag(); @@ -265,7 +265,7 @@ void SaveTool::drawGeneralInfo() { } drawTooltip("Story progress directly affects unlocked levels."); if(ImGui::BeginPopup("StoryProgressMenu")) { - if(!_unsafeMode && _mbManager->gameState() != GameState::NotRunning) { + if(!_unsafeMode && _gameState != GameState::NotRunning) { ImGui::CloseCurrentPopup(); } for(const auto& sp : story_progress) { @@ -441,7 +441,7 @@ void SaveTool::drawMassManager() { ImGui::EndDragDropSource(); } - if((!_unsafeMode && _mbManager->gameState() == GameState::NotRunning) && ImGui::BeginDragDropTarget()) { + if((!_unsafeMode && _gameState == GameState::NotRunning) && ImGui::BeginDragDropTarget()) { if(const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("StagedMass")) { if(payload->DataSize != sizeof(std::string)) { SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal error", @@ -595,7 +595,7 @@ auto SaveTool::drawDeleteMassPopup(int mass_index) -> ImGuiID { return 0; } - if(_mbManager->gameState() != GameState::NotRunning) { + if(_gameState != GameState::NotRunning) { ImGui::CloseCurrentPopup(); ImGui::EndPopup(); return 0; diff --git a/src/SaveTool/SaveTool_drawMainMenu.cpp b/src/SaveTool/SaveTool_drawMainMenu.cpp index 709396b..94876e0 100644 --- a/src/SaveTool/SaveTool_drawMainMenu.cpp +++ b/src/SaveTool/SaveTool_drawMainMenu.cpp @@ -24,18 +24,17 @@ void SaveTool::drawMainMenu() { if(ImGui::BeginMainMenuBar()) { if(ImGui::BeginMenu("Save Tool##SaveToolMenu")) { - if(ImGui::BeginMenu(ICON_FA_FOLDER_OPEN " Open game data directory", _mbManager != nullptr)) { - if(ImGui::MenuItem(ICON_FA_COG " Configuration", nullptr, false, _mbManager != nullptr)) { - openUri(Utility::Directory::toNativeSeparators(_mbManager->saveDirectory() + "/Saved/Config/WindowsNoEditor")); + if(ImGui::BeginMenu(ICON_FA_FOLDER_OPEN " Open game data directory", Utility::Directory::exists(_gameDataDir))) { + if(ImGui::MenuItem(ICON_FA_COG " Configuration", nullptr, false, Utility::Directory::exists(_configDir))) { + openUri(Utility::Directory::toNativeSeparators(_configDir)); } - if(ImGui::MenuItem(ICON_FA_SAVE " Saves", nullptr, false, _profileManager != nullptr)) { - openUri(Utility::Directory::toNativeSeparators(_profileManager->saveDirectory())); + if(ImGui::MenuItem(ICON_FA_SAVE " Saves", nullptr, false, Utility::Directory::exists(_saveDir))) { + openUri(Utility::Directory::toNativeSeparators(_saveDir)); } - static bool _screenshotsAvailable = Utility::Directory::exists(_mbManager->saveDirectory() + "/Saved/Screenshots/WindowsNoEditor"); - if(ImGui::MenuItem(ICON_FA_IMAGE " Screenshots", nullptr, false, _screenshotsAvailable)) { - openUri(Utility::Directory::toNativeSeparators(_mbManager->saveDirectory() + "/Screenshots/WindowsNoEditor")); + if(ImGui::MenuItem(ICON_FA_IMAGE " Screenshots", nullptr, false, Utility::Directory::exists(_screenshotsDir))) { + openUri(Utility::Directory::toNativeSeparators(_screenshotsDir)); } ImGui::EndMenu(); @@ -105,7 +104,7 @@ void SaveTool::drawMainMenu() { ImGui::EndMenu(); } - if(_mbManager != nullptr) { + if(_gameCheckTimerId != 0) { if(ImGui::BeginTable("##MainMenuLayout", 2)) { ImGui::TableSetupColumn("##Dummy", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("##GameState", ImGuiTableColumnFlags_WidthFixed);