#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 #include #include #include #include #include #include #include #include #include "../ProfileManager/ProfileManager.h" #include "../MassManager/MassManager.h" using namespace Corrade; using namespace Magnum; class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener { public: explicit SaveTool(const Arguments& arguments); ~SaveTool() override; void handleFileAction(efsw::WatchID watch_id, const std::string& dir, const std::string& filename, efsw::Action action, std::string old_filename = "") override; private: // Events void drawEvent() override; void viewportEvent(ViewportEvent& event) override; void keyPressEvent(KeyEvent& event) override; void keyReleaseEvent(KeyEvent& event) override; void mousePressEvent(MouseEvent& event) override; void mouseReleaseEvent(MouseEvent& event) override; void mouseMoveEvent(MouseMoveEvent& event) override; void mouseScrollEvent(MouseScrollEvent& event) override; void textInputEvent(TextInputEvent& event) override; void anyEvent(SDL_Event& event) override; enum InitStatus: Int { InitSuccess, ProfileManagerFailure }; void initEvent(SDL_Event& event); void updateCheckEvent(SDL_Event& event); // Initialisation methods void initialiseConfiguration(); void initialiseGui(); void initialiseManager(); auto findGameDataDirectory() -> bool; void initialiseMassManager(); void initialiseFileWatcher(); // GUI-related methods void drawImGui(); void drawGui(); void drawMainMenu(); void drawDisclaimer(); void drawInitialisation(); void drawProfileManager(); auto drawBackupListPopup() -> ImGuiID; auto drawBackupProfilePopup(std::size_t profile_index) -> ImGuiID; auto drawDeleteProfilePopup(std::size_t profile_index) -> ImGuiID; void drawManager(); auto drawIntEditPopup(int* value_to_edit, int max) -> bool; auto drawRenamePopup(Containers::ArrayView name_view) -> bool; void drawGeneralInfo(); void drawResearchInventory(); void drawMassManager(); auto drawDeleteMassPopup(int mass_index) -> ImGuiID; auto drawDeleteStagedMassPopup(const std::string& filename) -> ImGuiID; void drawAbout(); void drawGameState(); // Convenience wrappers over ImGui stuff void drawHelpMarker(const char* text, Float wrap_pos = 0.0f); void drawTooltip(const char* text, Float wrap_pos = 0.0f); template auto drawUnsafeWidget(Functor func, Args... args) -> bool { 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); } bool result = func(std::forward(args)...); if(!_unsafeMode && game_state != GameState::NotRunning) { ImGui::PopItemFlag(); ImGui::PopStyleVar(); } return result; } // Obviously, should only be used with ImGui widgets that return a bool. // Also, func should be a lambda if there are any default arguments, like ImGui::Button(), etc... template void drawUnsafeText(const char* text, Args... args) { // Alternative to the above, for ImGui::Text*() variants. if(!_unsafeMode && _gameState != GameState::NotRunning) { ImGui::TextDisabled(text, std::forward(args)...); } else { ImGui::Text(text, std::forward(args)...); } } void openUri(const std::string& uri); void checkGameState(); void checkForUpdates(); Utility::Configuration _conf{"MassBuilderSaveTool.ini"}; Utility::Resource _rs{"assets"}; // GUI-related members ImGuiIntegration::Context _imgui{NoCreate}; enum class UiState: uint8_t { Disclaimer, Initialising, ProfileManager, MainManager } _uiState{UiState::Disclaimer}; bool _aboutPopup{false}; #ifdef SAVETOOL_DEBUG_BUILD bool _demoWindow{false}; bool _styleEditor{false}; bool _metricsWindow{false}; #endif std::thread _thread; // used for threaded operations such as profile manager init or update checking. UnsignedInt _initEventId; UnsignedInt _updateEventId; std::string _lastError; std::string _gameDataDir; std::string _configDir; std::string _saveDir; std::string _screenshotsDir; std::string _backupsDir; std::string _stagingDir; enum class GameState : UnsignedByte { Unknown, NotRunning, Running } _gameState{GameState::Unknown}; SDL_TimerID _gameCheckTimerId = 0; Containers::Pointer _profileManager; Profile* _currentProfile{nullptr}; Containers::Pointer _massManager; Containers::Pointer _fileWatcher; enum watchID { SaveDir = 0, StagingDir = 1 }; Containers::StaticArray<2, efsw::WatchID> _watchIDs; bool _checkUpdatesOnStartup{true}; bool _unsafeMode{false}; };