2021-06-11 19:24:52 +02:00
|
|
|
#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 <https://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
#include <thread>
|
|
|
|
|
|
|
|
#include <Corrade/Containers/Pointer.h>
|
2021-07-23 14:17:42 +02:00
|
|
|
#include <Corrade/Utility/Configuration.h>
|
2021-06-11 19:24:52 +02:00
|
|
|
#include <Corrade/Utility/Resource.h>
|
|
|
|
|
|
|
|
#include <Magnum/Platform/Sdl2Application.h>
|
|
|
|
#include <Magnum/ImGuiIntegration/Context.h>
|
|
|
|
|
2021-09-10 16:15:27 +02:00
|
|
|
#include <SDL.h>
|
2021-06-11 19:24:52 +02:00
|
|
|
|
|
|
|
#include <imgui.h>
|
|
|
|
#include <imgui_internal.h>
|
|
|
|
|
|
|
|
#include <efsw/efsw.hpp>
|
|
|
|
|
|
|
|
#include "../ProfileManager/ProfileManager.h"
|
|
|
|
#include "../MassManager/MassManager.h"
|
2021-07-28 14:14:12 +02:00
|
|
|
#include "../ToastQueue/ToastQueue.h"
|
2021-06-11 19:24:52 +02:00
|
|
|
|
2021-09-27 20:51:48 +02:00
|
|
|
#ifdef SAVETOOL_DEBUG_BUILD
|
|
|
|
#include <Corrade/Utility/Tweakable.h>
|
|
|
|
|
|
|
|
#define tw CORRADE_TWEAKABLE
|
|
|
|
#endif
|
|
|
|
|
2021-06-11 19:24:52 +02:00
|
|
|
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;
|
|
|
|
|
2021-06-20 14:13:30 +02:00
|
|
|
enum InitStatus: Int {
|
2021-06-11 19:24:52 +02:00
|
|
|
InitSuccess,
|
|
|
|
ProfileManagerFailure
|
|
|
|
};
|
|
|
|
void initEvent(SDL_Event& event);
|
2021-07-22 11:39:53 +02:00
|
|
|
void updateCheckEvent(SDL_Event& event);
|
2021-06-11 19:24:52 +02:00
|
|
|
|
|
|
|
// Initialisation methods
|
2021-07-23 14:17:42 +02:00
|
|
|
void initialiseConfiguration();
|
2021-06-11 19:24:52 +02:00
|
|
|
void initialiseGui();
|
|
|
|
void initialiseManager();
|
2021-07-21 14:36:49 +02:00
|
|
|
auto findGameDataDirectory() -> bool;
|
2021-06-11 19:24:52 +02:00
|
|
|
void initialiseMassManager();
|
|
|
|
void initialiseFileWatcher();
|
|
|
|
|
|
|
|
// GUI-related methods
|
|
|
|
void drawImGui();
|
|
|
|
void drawGui();
|
|
|
|
void drawMainMenu();
|
|
|
|
void drawDisclaimer();
|
|
|
|
void drawInitialisation();
|
2021-08-28 20:57:06 +02:00
|
|
|
|
2021-06-11 19:24:52 +02:00
|
|
|
void drawProfileManager();
|
|
|
|
auto drawBackupListPopup() -> ImGuiID;
|
|
|
|
auto drawBackupProfilePopup(std::size_t profile_index) -> ImGuiID;
|
|
|
|
auto drawDeleteProfilePopup(std::size_t profile_index) -> ImGuiID;
|
2021-08-28 20:57:06 +02:00
|
|
|
|
2021-06-11 19:24:52 +02:00
|
|
|
void drawManager();
|
|
|
|
auto drawIntEditPopup(int* value_to_edit, int max) -> bool;
|
|
|
|
auto drawRenamePopup(Containers::ArrayView<char> name_view) -> bool;
|
|
|
|
void drawGeneralInfo();
|
|
|
|
void drawResearchInventory();
|
|
|
|
void drawMassManager();
|
|
|
|
auto drawDeleteMassPopup(int mass_index) -> ImGuiID;
|
|
|
|
auto drawDeleteStagedMassPopup(const std::string& filename) -> ImGuiID;
|
2021-08-28 20:57:06 +02:00
|
|
|
|
2021-08-19 20:35:00 +02:00
|
|
|
void drawMassViewer();
|
2021-09-10 16:16:21 +02:00
|
|
|
void drawFrameInfo();
|
2021-09-27 17:54:30 +02:00
|
|
|
void drawJointSliders();
|
2021-12-02 19:23:28 +01:00
|
|
|
void drawFrameStyles();
|
|
|
|
void drawEyeColourPicker();
|
|
|
|
void drawCustomFrameStyles();
|
|
|
|
void drawArmour();
|
|
|
|
void drawCustomArmourStyles();
|
|
|
|
void drawWeapons();
|
|
|
|
void drawWeaponEditor(Weapon& weapon);
|
|
|
|
void drawGlobalStyles();
|
|
|
|
void drawTuning();
|
|
|
|
void drawDecalEditor(Decal& decal);
|
|
|
|
void drawAccessoryEditor(Accessory& accessory, Containers::ArrayView<CustomStyle> style_view);
|
|
|
|
auto getStyleName(Int id, Containers::ArrayView<CustomStyle> view) -> const char*;
|
|
|
|
|
|
|
|
enum DCSResult {
|
|
|
|
DCS_Fail,
|
|
|
|
DCS_ResetStyle,
|
|
|
|
DCS_Save
|
|
|
|
};
|
|
|
|
auto drawCustomStyle(CustomStyle& style) -> DCSResult;
|
2021-08-28 20:57:06 +02:00
|
|
|
|
2021-06-11 19:24:52 +02:00
|
|
|
void drawAbout();
|
|
|
|
void drawGameState();
|
|
|
|
|
|
|
|
// Convenience wrappers over ImGui stuff
|
2021-06-20 14:13:30 +02:00
|
|
|
void drawHelpMarker(const char* text, Float wrap_pos = 0.0f);
|
|
|
|
void drawTooltip(const char* text, Float wrap_pos = 0.0f);
|
2021-06-11 19:24:52 +02:00
|
|
|
|
|
|
|
template<typename Functor, typename... Args>
|
|
|
|
auto drawUnsafeWidget(Functor func, Args... args) -> bool {
|
2021-07-21 14:36:49 +02:00
|
|
|
GameState game_state = _gameState; // Copying the value to reduce the risk of a data race.
|
2021-07-10 16:44:39 +02:00
|
|
|
if(!_unsafeMode && game_state != GameState::NotRunning) {
|
2021-06-11 19:24:52 +02:00
|
|
|
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
|
|
|
|
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.5f);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool result = func(std::forward<Args>(args)...);
|
|
|
|
|
2021-07-10 16:44:39 +02:00
|
|
|
if(!_unsafeMode && game_state != GameState::NotRunning) {
|
2021-06-11 19:24:52 +02:00
|
|
|
ImGui::PopItemFlag();
|
|
|
|
ImGui::PopStyleVar();
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
} // Obviously, should only be used with ImGui widgets that return a bool.
|
2021-07-10 16:44:39 +02:00
|
|
|
// Also, func should be a lambda if there are any default arguments, like ImGui::Button(), etc...
|
2021-06-11 19:24:52 +02:00
|
|
|
|
2021-07-21 13:40:55 +02:00
|
|
|
template<typename... Args>
|
|
|
|
void drawUnsafeText(const char* text, Args... args) { // Alternative to the above, for ImGui::Text*() variants.
|
2021-07-21 14:36:49 +02:00
|
|
|
if(!_unsafeMode && _gameState != GameState::NotRunning) {
|
2021-07-21 13:40:55 +02:00
|
|
|
ImGui::TextDisabled(text, std::forward<Args>(args)...);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ImGui::Text(text, std::forward<Args>(args)...);
|
|
|
|
}
|
|
|
|
}
|
2021-06-11 19:24:52 +02:00
|
|
|
|
|
|
|
void openUri(const std::string& uri);
|
|
|
|
|
2021-07-21 14:36:49 +02:00
|
|
|
void checkGameState();
|
|
|
|
|
2021-07-22 11:39:53 +02:00
|
|
|
void checkForUpdates();
|
|
|
|
|
2021-07-23 14:17:42 +02:00
|
|
|
Utility::Configuration _conf{"MassBuilderSaveTool.ini"};
|
2021-06-11 19:24:52 +02:00
|
|
|
Utility::Resource _rs{"assets"};
|
|
|
|
|
|
|
|
// GUI-related members
|
|
|
|
ImGuiIntegration::Context _imgui{NoCreate};
|
|
|
|
|
|
|
|
enum class UiState: uint8_t {
|
|
|
|
Disclaimer,
|
|
|
|
Initialising,
|
|
|
|
ProfileManager,
|
2021-08-19 20:35:00 +02:00
|
|
|
MainManager,
|
|
|
|
MassViewer
|
2021-07-21 14:36:49 +02:00
|
|
|
} _uiState{UiState::Disclaimer};
|
2021-06-11 19:24:52 +02:00
|
|
|
|
|
|
|
bool _aboutPopup{false};
|
2021-07-13 18:35:23 +02:00
|
|
|
#ifdef SAVETOOL_DEBUG_BUILD
|
2021-06-11 19:24:52 +02:00
|
|
|
bool _demoWindow{false};
|
|
|
|
bool _styleEditor{false};
|
|
|
|
bool _metricsWindow{false};
|
|
|
|
#endif
|
|
|
|
|
2021-07-28 14:14:12 +02:00
|
|
|
ToastQueue _queue;
|
|
|
|
|
2021-08-18 20:09:22 +02:00
|
|
|
std::thread _initThread;
|
|
|
|
std::thread _updateThread;
|
2021-07-22 11:39:53 +02:00
|
|
|
|
2021-06-20 14:13:30 +02:00
|
|
|
UnsignedInt _initEventId;
|
2021-07-22 11:39:53 +02:00
|
|
|
UnsignedInt _updateEventId;
|
2021-06-11 19:24:52 +02:00
|
|
|
|
2021-07-21 14:36:49 +02:00
|
|
|
std::string _lastError;
|
|
|
|
|
|
|
|
std::string _gameDataDir;
|
|
|
|
std::string _configDir;
|
|
|
|
std::string _saveDir;
|
|
|
|
std::string _screenshotsDir;
|
|
|
|
|
2021-07-21 20:38:33 +02:00
|
|
|
std::string _backupsDir;
|
2021-07-21 20:57:39 +02:00
|
|
|
std::string _stagingDir;
|
2021-07-21 20:38:33 +02:00
|
|
|
|
2021-07-21 14:36:49 +02:00
|
|
|
enum class GameState : UnsignedByte {
|
|
|
|
Unknown, NotRunning, Running
|
|
|
|
} _gameState{GameState::Unknown};
|
|
|
|
|
|
|
|
SDL_TimerID _gameCheckTimerId = 0;
|
2021-06-11 19:24:52 +02:00
|
|
|
|
|
|
|
Containers::Pointer<ProfileManager> _profileManager;
|
|
|
|
Profile* _currentProfile{nullptr};
|
|
|
|
|
|
|
|
Containers::Pointer<MassManager> _massManager;
|
2021-08-19 20:35:00 +02:00
|
|
|
Mass* _currentMass{nullptr};
|
2021-06-11 19:24:52 +02:00
|
|
|
|
|
|
|
Containers::Pointer<efsw::FileWatcher> _fileWatcher;
|
|
|
|
enum watchID {
|
|
|
|
SaveDir = 0,
|
|
|
|
StagingDir = 1
|
|
|
|
};
|
|
|
|
Containers::StaticArray<2, efsw::WatchID> _watchIDs;
|
|
|
|
|
2021-08-18 16:53:29 +02:00
|
|
|
enum class Framelimit: UnsignedByte {
|
|
|
|
Vsync,
|
|
|
|
HalfVsync,
|
|
|
|
FpsCap
|
|
|
|
} _framelimit{Framelimit::Vsync};
|
|
|
|
UnsignedInt _fpsCap{60};
|
|
|
|
|
2021-08-18 20:09:22 +02:00
|
|
|
bool _skipDisclaimer{false};
|
2021-07-23 14:17:42 +02:00
|
|
|
bool _checkUpdatesOnStartup{true};
|
2021-06-11 19:24:52 +02:00
|
|
|
bool _unsafeMode{false};
|
2021-07-28 14:18:39 +02:00
|
|
|
|
|
|
|
bool _updateAvailable{false};
|
|
|
|
std::string _latestVersion;
|
|
|
|
std::string _releaseLink;
|
|
|
|
std::string _downloadLink;
|
2021-07-28 15:00:15 +02:00
|
|
|
|
|
|
|
bool _cheatMode{false};
|
2021-06-11 19:24:52 +02:00
|
|
|
};
|