Compare commits
No commits in common. "master" and "v1.6.0" have entirely different histories.
15 changed files with 285 additions and 37 deletions
4
.gitmodules
vendored
4
.gitmodules
vendored
|
@ -22,6 +22,10 @@
|
||||||
path = third-party/libzip
|
path = third-party/libzip
|
||||||
url = https://github.com/nih-at/libzip
|
url = https://github.com/nih-at/libzip
|
||||||
branch = main
|
branch = main
|
||||||
|
[submodule "efsw"]
|
||||||
|
path = third-party/efsw
|
||||||
|
url = https://github.com/SpartanJ/efsw
|
||||||
|
branch = master
|
||||||
[submodule "libcurl"]
|
[submodule "libcurl"]
|
||||||
path = third-party/curl
|
path = third-party/curl
|
||||||
url = https://github.com/curl/curl
|
url = https://github.com/curl/curl
|
||||||
|
|
|
@ -27,6 +27,7 @@ include(CMakeDependentOption)
|
||||||
cmake_dependent_option(SAVETOOL_USE_SYSTEM_CORRADE_MAGNUM "Use system-wide versions of Corrade and Magnum." ON "SAVETOOL_USE_SYSTEM_LIBS" OFF)
|
cmake_dependent_option(SAVETOOL_USE_SYSTEM_CORRADE_MAGNUM "Use system-wide versions of Corrade and Magnum." ON "SAVETOOL_USE_SYSTEM_LIBS" OFF)
|
||||||
cmake_dependent_option(SAVETOOL_USE_SYSTEM_SDL2 "Use a system-wide version of SDL2." ON "SAVETOOL_USE_SYSTEM_LIBS" OFF)
|
cmake_dependent_option(SAVETOOL_USE_SYSTEM_SDL2 "Use a system-wide version of SDL2." ON "SAVETOOL_USE_SYSTEM_LIBS" OFF)
|
||||||
cmake_dependent_option(SAVETOOL_USE_SYSTEM_LIBZIP "Use a system-wide version of libzip." ON "SAVETOOL_USE_SYSTEM_LIBS" OFF)
|
cmake_dependent_option(SAVETOOL_USE_SYSTEM_LIBZIP "Use a system-wide version of libzip." ON "SAVETOOL_USE_SYSTEM_LIBS" OFF)
|
||||||
|
cmake_dependent_option(SAVETOOL_USE_SYSTEM_EFSW "Use a system-wide version of EFSW." ON "SAVETOOL_USE_SYSTEM_LIBS" OFF)
|
||||||
cmake_dependent_option(SAVETOOL_USE_SYSTEM_LIBCURL "Use a system-wide version of libcurl." ON "SAVETOOL_USE_SYSTEM_LIBS" OFF)
|
cmake_dependent_option(SAVETOOL_USE_SYSTEM_LIBCURL "Use a system-wide version of libcurl." ON "SAVETOOL_USE_SYSTEM_LIBS" OFF)
|
||||||
|
|
||||||
if(NOT SAVETOOL_USE_SYSTEM_LIBS OR NOT (SAVETOOL_USE_SYSTEM_CORRADE_MAGNUM AND SAVETOOL_USE_SYSTEM_SDL2 AND SAVETOOL_USE_SYSTEM_LIBZIP AND SAVETOOL_USE_SYSTEM_EFSW AND SAVETOOL_USE_SYSTEM_LIBCURL))
|
if(NOT SAVETOOL_USE_SYSTEM_LIBS OR NOT (SAVETOOL_USE_SYSTEM_CORRADE_MAGNUM AND SAVETOOL_USE_SYSTEM_SDL2 AND SAVETOOL_USE_SYSTEM_LIBZIP AND SAVETOOL_USE_SYSTEM_EFSW AND SAVETOOL_USE_SYSTEM_LIBCURL))
|
||||||
|
@ -113,6 +114,13 @@ if(NOT SAVETOOL_USE_SYSTEM_LIBZIP)
|
||||||
add_subdirectory(third-party/libzip EXCLUDE_FROM_ALL)
|
add_subdirectory(third-party/libzip EXCLUDE_FROM_ALL)
|
||||||
endif(NOT SAVETOOL_USE_SYSTEM_LIBZIP)
|
endif(NOT SAVETOOL_USE_SYSTEM_LIBZIP)
|
||||||
|
|
||||||
|
if(NOT SAVETOOL_USE_SYSTEM_EFSW)
|
||||||
|
set(VERBOSE OFF CACHE BOOL "" FORCE)
|
||||||
|
set(BUILD_TEST_APP OFF CACHE BOOL "" FORCE)
|
||||||
|
set(EFSW_INSTALL OFF CACHE BOOL "" FORCE)
|
||||||
|
add_subdirectory(third-party/efsw EXCLUDE_FROM_ALL)
|
||||||
|
endif(NOT SAVETOOL_USE_SYSTEM_EFSW)
|
||||||
|
|
||||||
if(NOT SAVETOOL_USE_SYSTEM_LIBCURL)
|
if(NOT SAVETOOL_USE_SYSTEM_LIBCURL)
|
||||||
set(BUILD_CURL_EXE OFF CACHE BOOL "" FORCE)
|
set(BUILD_CURL_EXE OFF CACHE BOOL "" FORCE)
|
||||||
set(ENABLE_UNICODE ON CACHE BOOL "" FORCE)
|
set(ENABLE_UNICODE ON CACHE BOOL "" FORCE)
|
||||||
|
|
|
@ -92,6 +92,7 @@ Application::Application(const Arguments& arguments):
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateEventId = _initEventId + 1;
|
_updateEventId = _initEventId + 1;
|
||||||
|
_fileEventId = _initEventId + 2;
|
||||||
|
|
||||||
LOG_INFO("Initialising the timer subsystem.");
|
LOG_INFO("Initialising the timer subsystem.");
|
||||||
if(SDL_InitSubSystem(SDL_INIT_TIMER) != 0) {
|
if(SDL_InitSubSystem(SDL_INIT_TIMER) != 0) {
|
||||||
|
@ -225,6 +226,9 @@ Application::anyEvent(SDL_Event& event) {
|
||||||
else if(event.type == _updateEventId) {
|
else if(event.type == _updateEventId) {
|
||||||
updateCheckEvent(event);
|
updateCheckEvent(event);
|
||||||
}
|
}
|
||||||
|
else if(event.type == _fileEventId) {
|
||||||
|
fileUpdateEvent(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include <Corrade/Containers/Pointer.h>
|
#include <Corrade/Containers/Pointer.h>
|
||||||
|
@ -34,6 +35,8 @@
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
|
#include <efsw/efsw.hpp>
|
||||||
|
|
||||||
#include "../Managers/BackupManager.h"
|
#include "../Managers/BackupManager.h"
|
||||||
#include "../Managers/MassManager.h"
|
#include "../Managers/MassManager.h"
|
||||||
#include "../Managers/ProfileManager.h"
|
#include "../Managers/ProfileManager.h"
|
||||||
|
@ -51,11 +54,17 @@ using namespace Magnum;
|
||||||
|
|
||||||
namespace mbst {
|
namespace mbst {
|
||||||
|
|
||||||
class Application: public Platform::Sdl2Application {
|
class Application: public Platform::Sdl2Application, public efsw::FileWatchListener {
|
||||||
public:
|
public:
|
||||||
explicit Application(const Arguments& arguments);
|
explicit Application(const Arguments& arguments);
|
||||||
|
|
||||||
virtual ~Application();
|
~Application() override;
|
||||||
|
|
||||||
|
void handleFileAction(efsw::WatchID watch_id,
|
||||||
|
const std::string& dir,
|
||||||
|
const std::string& filename,
|
||||||
|
efsw::Action action,
|
||||||
|
std::string old_filename) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Events
|
// Events
|
||||||
|
@ -81,11 +90,21 @@ class Application: public Platform::Sdl2Application {
|
||||||
|
|
||||||
void updateCheckEvent(SDL_Event& event);
|
void updateCheckEvent(SDL_Event& event);
|
||||||
|
|
||||||
|
enum FileEventType: std::int32_t {
|
||||||
|
FileAdded = efsw::Action::Add,
|
||||||
|
FileDeleted = efsw::Action::Delete,
|
||||||
|
FileModified = efsw::Action::Modified,
|
||||||
|
FileMoved = efsw::Action::Moved,
|
||||||
|
StagedUpdate = 1 << 3
|
||||||
|
};
|
||||||
|
void fileUpdateEvent(SDL_Event& event);
|
||||||
|
|
||||||
// Initialisation methods
|
// Initialisation methods
|
||||||
void initialiseConfiguration();
|
void initialiseConfiguration();
|
||||||
void initialiseGui();
|
void initialiseGui();
|
||||||
void initialiseManager();
|
void initialiseManager();
|
||||||
void initialiseMassManager();
|
void initialiseMassManager();
|
||||||
|
void initialiseFileWatcher();
|
||||||
|
|
||||||
// GUI-related methods
|
// GUI-related methods
|
||||||
void drawImGui();
|
void drawImGui();
|
||||||
|
@ -225,6 +244,7 @@ class Application: public Platform::Sdl2Application {
|
||||||
|
|
||||||
std::uint32_t _initEventId;
|
std::uint32_t _initEventId;
|
||||||
std::uint32_t _updateEventId;
|
std::uint32_t _updateEventId;
|
||||||
|
std::uint32_t _fileEventId;
|
||||||
|
|
||||||
Containers::String _lastError;
|
Containers::String _lastError;
|
||||||
|
|
||||||
|
@ -246,9 +266,17 @@ class Application: public Platform::Sdl2Application {
|
||||||
|
|
||||||
GameObjects::Weapon* _currentWeapon = nullptr;
|
GameObjects::Weapon* _currentWeapon = nullptr;
|
||||||
|
|
||||||
|
Containers::Pointer<efsw::FileWatcher> _fileWatcher;
|
||||||
|
enum watchID {
|
||||||
|
SaveDir = 0,
|
||||||
|
StagingDir = 1
|
||||||
|
};
|
||||||
|
Containers::StaticArray<2, efsw::WatchID> _watchIDs;
|
||||||
|
|
||||||
Containers::Optional<UpdateChecker> _checker{Containers::NullOpt};
|
Containers::Optional<UpdateChecker> _checker{Containers::NullOpt};
|
||||||
std::mutex _checkerMutex;
|
std::mutex _checkerMutex;
|
||||||
|
|
||||||
|
bool _modifiedBySaveTool = false;
|
||||||
bool _jointsDirty = false;
|
bool _jointsDirty = false;
|
||||||
bool _stylesDirty = false;
|
bool _stylesDirty = false;
|
||||||
bool _eyeFlareDirty = false;
|
bool _eyeFlareDirty = false;
|
||||||
|
|
158
src/Application/Application_FileWatcher.cpp
Normal file
158
src/Application/Application_FileWatcher.cpp
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2024 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 <cstring>
|
||||||
|
|
||||||
|
#include <Corrade/Utility/Format.h>
|
||||||
|
#include <Corrade/Utility/String.h>
|
||||||
|
#include <Corrade/Utility/Unicode.h>
|
||||||
|
|
||||||
|
#include <SDL_events.h>
|
||||||
|
#include <SDL_messagebox.h>
|
||||||
|
|
||||||
|
#include <fileapi.h>
|
||||||
|
#include <handleapi.h>
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
|
|
||||||
|
namespace mbst {
|
||||||
|
|
||||||
|
void
|
||||||
|
Application::handleFileAction(efsw::WatchID watch_id, const std::string&, const std::string& filename,
|
||||||
|
efsw::Action action, std::string old_filename)
|
||||||
|
{
|
||||||
|
SDL_Event event;
|
||||||
|
SDL_zero(event);
|
||||||
|
event.type = _fileEventId;
|
||||||
|
|
||||||
|
event.user.data1 = Containers::String{Containers::AllocatedInit, filename.c_str()}.release();
|
||||||
|
|
||||||
|
if(watch_id == _watchIDs[StagingDir] && Utility::String::endsWith(filename, ".sav")) {
|
||||||
|
event.user.code = StagedUpdate | action;
|
||||||
|
SDL_PushEvent(&event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Utility::String::endsWith(filename, "Config.sav")) {
|
||||||
|
return;
|
||||||
|
} // TODO: actually do something when config files will finally be handled
|
||||||
|
|
||||||
|
if(!Utility::String::endsWith(filename, Utility::format("Profile{}.sav", _currentProfile->account()).data()) &&
|
||||||
|
filename.find("Unit") == std::string::npos)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.user.code = action;
|
||||||
|
if(action == efsw::Actions::Moved) {
|
||||||
|
event.user.data2 = Containers::String{Containers::AllocatedInit, old_filename.c_str()}.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_PushEvent(&event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Application::fileUpdateEvent(SDL_Event& event) {
|
||||||
|
Containers::String filename{static_cast<char*>(event.user.data1),
|
||||||
|
std::strlen(static_cast<char*>(event.user.data1)), nullptr};
|
||||||
|
|
||||||
|
if((event.user.code & StagedUpdate) == StagedUpdate) {
|
||||||
|
_stagedMassManager->refreshMass(filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Containers::String old_filename;
|
||||||
|
|
||||||
|
std::int32_t index = 0;
|
||||||
|
std::int32_t old_index = 0;
|
||||||
|
bool is_current_profile = filename == _currentProfile->filename();
|
||||||
|
bool is_unit = filename.hasPrefix(_currentProfile->isDemo() ? "DemoUnit"_s : "Unit"_s);
|
||||||
|
if(is_unit) {
|
||||||
|
index = ((filename[_currentProfile->isDemo() ? 8 : 4] - 0x30) * 10) +
|
||||||
|
(filename[_currentProfile->isDemo() ? 9 : 5] - 0x30);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(event.user.code == FileMoved) {
|
||||||
|
old_filename = Containers::String{static_cast<char*>(event.user.data2),
|
||||||
|
std::strlen(static_cast<char*>(event.user.data2)), nullptr};
|
||||||
|
old_index = ((old_filename[_currentProfile->isDemo() ? 8 : 4] - 0x30) * 10) +
|
||||||
|
(old_filename[_currentProfile->isDemo() ? 9 : 5] - 0x30);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(event.user.code) {
|
||||||
|
case FileAdded:
|
||||||
|
if(is_unit) {
|
||||||
|
if(!_currentMass || _currentMass != &(_massManager->hangar(index))) {
|
||||||
|
_massManager->refreshHangar(index);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_currentMass->setDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FileDeleted:
|
||||||
|
if(is_current_profile) {
|
||||||
|
_currentProfile = nullptr;
|
||||||
|
_uiState = UiState::ProfileManager;
|
||||||
|
if(!_profileManager->refreshProfiles()) {
|
||||||
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",
|
||||||
|
_profileManager->lastError().data(), window());
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(is_unit) {
|
||||||
|
if(!_currentMass || _currentMass != &(_massManager->hangar(index))) {
|
||||||
|
_massManager->refreshHangar(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FileModified:
|
||||||
|
if(is_current_profile) {
|
||||||
|
_currentProfile->refreshValues();
|
||||||
|
}
|
||||||
|
else if(is_unit) {
|
||||||
|
if(!_currentMass || _currentMass != &(_massManager->hangar(index))) {
|
||||||
|
_massManager->refreshHangar(index);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(_modifiedBySaveTool && _currentMass->filename() == filename) {
|
||||||
|
auto handle = CreateFileW(Utility::Unicode::widen(Containers::StringView{filename}),
|
||||||
|
GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||||
|
if(handle && handle != INVALID_HANDLE_VALUE) {
|
||||||
|
CloseHandle(handle);
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_currentMass->setDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FileMoved:
|
||||||
|
if(is_unit) {
|
||||||
|
if(old_filename.hasSuffix(".sav"_s)) {
|
||||||
|
_massManager->refreshHangar(index);
|
||||||
|
_massManager->refreshHangar(old_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_queue.addToast(Toast::Type::Warning, "Unknown file action type"_s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -122,6 +122,8 @@ Application::initialiseManager() {
|
||||||
|
|
||||||
_backupManager.emplace();
|
_backupManager.emplace();
|
||||||
|
|
||||||
|
_stagedMassManager.emplace();
|
||||||
|
|
||||||
event.user.code = InitSuccess;
|
event.user.code = InitSuccess;
|
||||||
SDL_PushEvent(&event);
|
SDL_PushEvent(&event);
|
||||||
}
|
}
|
||||||
|
@ -130,8 +132,15 @@ void
|
||||||
Application::initialiseMassManager() {
|
Application::initialiseMassManager() {
|
||||||
LOG_INFO("Initialising the M.A.S.S. manager.");
|
LOG_INFO("Initialising the M.A.S.S. manager.");
|
||||||
_massManager.emplace(_currentProfile->account(), _currentProfile->isDemo());
|
_massManager.emplace(_currentProfile->account(), _currentProfile->isDemo());
|
||||||
LOG_INFO("Initialising the staged M.A.S.S. manager.");
|
}
|
||||||
_stagedMassManager.emplace();
|
|
||||||
|
void
|
||||||
|
Application::initialiseFileWatcher() {
|
||||||
|
LOG_INFO("Initialising the file watcher.");
|
||||||
|
_fileWatcher.emplace();
|
||||||
|
_watchIDs[SaveDir] = _fileWatcher->addWatch(conf().directories().gameSaves, this, false);
|
||||||
|
_watchIDs[StagingDir] = _fileWatcher->addWatch(conf().directories().staging, this, false);
|
||||||
|
_fileWatcher->watch();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,20 +55,9 @@ Application::drawManager() {
|
||||||
if(ImGui::Button(ICON_FA_ARROW_LEFT " Back to profile manager")) {
|
if(ImGui::Button(ICON_FA_ARROW_LEFT " Back to profile manager")) {
|
||||||
_currentProfile = nullptr;
|
_currentProfile = nullptr;
|
||||||
_massManager.reset();
|
_massManager.reset();
|
||||||
_stagedMassManager.reset();
|
_fileWatcher.reset();
|
||||||
_uiState = UiState::ProfileManager;
|
_uiState = UiState::ProfileManager;
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
|
||||||
if(ImGui::Button(ICON_FA_SYNC_ALT " Refresh external changes")) {
|
|
||||||
_currentProfile->refreshValues();
|
|
||||||
if(!_currentProfile->valid()) {
|
|
||||||
_currentProfile = nullptr;
|
|
||||||
_profileManager->refreshProfiles();
|
|
||||||
_queue.addToast(Toast::Type::Error, "The current profile isn't valid anymore."_s);
|
|
||||||
ImGui::End();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ImGui::BeginChild("##ProfileInfo",
|
if(ImGui::BeginChild("##ProfileInfo",
|
||||||
{ImGui::GetContentRegionAvail().x * 0.60f, 0.0f},
|
{ImGui::GetContentRegionAvail().x * 0.60f, 0.0f},
|
||||||
|
@ -104,11 +93,6 @@ Application::drawManager() {
|
||||||
if(ImGui::BeginMenuBar()) {
|
if(ImGui::BeginMenuBar()) {
|
||||||
ImGui::TextUnformatted("M.A.S.S. management");
|
ImGui::TextUnformatted("M.A.S.S. management");
|
||||||
drawHelpMarker("To move, import, or export builds, drag-and-drop them.");
|
drawHelpMarker("To move, import, or export builds, drag-and-drop them.");
|
||||||
if(ImGui::SmallButton(ICON_FA_SYNC_ALT " Refresh")) {
|
|
||||||
for(int i = 0; i < 32 ; i++) {
|
|
||||||
_massManager->refreshHangar(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::EndMenuBar();
|
ImGui::EndMenuBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -543,13 +527,10 @@ Application::drawMassManager() {
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(0);
|
ImGui::TableSetColumnIndex(0);
|
||||||
ImGui::TextUnformatted("Staging area");
|
ImGui::TextUnformatted("Staging area");
|
||||||
|
ImGui::SameLine();
|
||||||
if(ImGui::SmallButton(ICON_FA_FOLDER_OPEN " Open staging folder")) {
|
if(ImGui::SmallButton(ICON_FA_FOLDER_OPEN " Open staging folder")) {
|
||||||
openUri(Utility::Path::toNativeSeparators(conf().directories().staging));
|
openUri(Utility::Path::toNativeSeparators(conf().directories().staging));
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
|
||||||
if(ImGui::SmallButton(ICON_FA_SYNC_ALT " Refresh")) {
|
|
||||||
_stagedMassManager->refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
for(const auto& mass : _stagedMassManager->stagedMasses()) {
|
for(const auto& mass : _stagedMassManager->stagedMasses()) {
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
|
@ -594,7 +575,6 @@ Application::drawMassManager() {
|
||||||
if(!_massManager->exportMass(index)) {
|
if(!_massManager->exportMass(index)) {
|
||||||
_queue.addToast(Toast::Type::Error, _massManager->lastError());
|
_queue.addToast(Toast::Type::Error, _massManager->lastError());
|
||||||
}
|
}
|
||||||
_stagedMassManager->refresh();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndDragDropTarget();
|
ImGui::EndDragDropTarget();
|
||||||
|
|
|
@ -72,12 +72,16 @@ Application::drawMassViewer() {
|
||||||
drawTooltip(_currentMass->filename());
|
drawTooltip(_currentMass->filename());
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(2);
|
ImGui::TableSetColumnIndex(2);
|
||||||
if(ImGui::SmallButton(ICON_FA_SYNC_ALT " Refresh external changes")) {
|
if(_currentMass->dirty()) {
|
||||||
_currentMass->refreshValues();
|
ImGui::TextUnformatted("External changes detected");
|
||||||
_currentMass->setDirty(false);
|
ImGui::SameLine();
|
||||||
_jointsDirty = false;
|
if(ImGui::SmallButton(ICON_FA_SYNC_ALT " Refresh")) {
|
||||||
_stylesDirty = false;
|
_currentMass->refreshValues();
|
||||||
_eyeFlareDirty = false;
|
_currentMass->setDirty(false);
|
||||||
|
_jointsDirty = false;
|
||||||
|
_stylesDirty = false;
|
||||||
|
_eyeFlareDirty = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(3);
|
ImGui::TableSetColumnIndex(3);
|
||||||
|
@ -186,7 +190,9 @@ Application::drawGlobalStyles() {
|
||||||
_currentMass->getGlobalStyles();
|
_currentMass->getGlobalStyles();
|
||||||
break;
|
break;
|
||||||
case DCS_Save:
|
case DCS_Save:
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
if(!_currentMass->writeGlobalStyle(i)) {
|
if(!_currentMass->writeGlobalStyle(i)) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -14,8 +14,6 @@
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <imgui_internal.h>
|
#include <imgui_internal.h>
|
||||||
|
|
||||||
#include "../FontAwesome/IconsFontAwesome5.h"
|
#include "../FontAwesome/IconsFontAwesome5.h"
|
||||||
|
@ -199,7 +197,9 @@ Application::drawArmour() {
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
|
|
||||||
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
if(!_currentMass->writeArmourPart(part.slot)) {
|
if(!_currentMass->writeArmourPart(part.slot)) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -357,8 +357,11 @@ Application::drawBLAttachment() {
|
||||||
ImGui::EndGroup();
|
ImGui::EndGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
if(!_currentMass->writeBulletLauncherAttachments()) {
|
if(!_currentMass->writeBulletLauncherAttachments()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -385,7 +388,9 @@ Application::drawCustomArmourStyles() {
|
||||||
_currentMass->getArmourCustomStyles();
|
_currentMass->getArmourCustomStyles();
|
||||||
break;
|
break;
|
||||||
case DCS_Save:
|
case DCS_Save:
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
if(!_currentMass->writeArmourCustomStyle(i)) {
|
if(!_currentMass->writeArmourCustomStyle(i)) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -149,7 +149,9 @@ Application::drawJointSliders() {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
if(!_currentMass->writeJointSliders()) {
|
if(!_currentMass->writeJointSliders()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
_jointsDirty = false;
|
_jointsDirty = false;
|
||||||
|
@ -204,7 +206,9 @@ Application::drawFrameStyles() {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
if(!_currentMass->writeFrameStyles()) {
|
if(!_currentMass->writeFrameStyles()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
_stylesDirty = false;
|
_stylesDirty = false;
|
||||||
|
@ -236,7 +240,9 @@ Application::drawEyeColourPicker() {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
if(!_currentMass->writeEyeFlareColour()) {
|
if(!_currentMass->writeEyeFlareColour()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
_eyeFlareDirty = false;
|
_eyeFlareDirty = false;
|
||||||
|
@ -270,7 +276,9 @@ Application::drawCustomFrameStyles() {
|
||||||
_currentMass->getFrameCustomStyles();
|
_currentMass->getFrameCustomStyles();
|
||||||
break;
|
break;
|
||||||
case DCS_Save:
|
case DCS_Save:
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
if(!_currentMass->writeFrameCustomStyle(i)) {
|
if(!_currentMass->writeFrameCustomStyle(i)) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -94,39 +94,47 @@ Application::drawWeaponCategory(Containers::StringView name, GameObjects::Weapon
|
||||||
ImGui::PushID(name.cbegin());
|
ImGui::PushID(name.cbegin());
|
||||||
|
|
||||||
if(drawUnsafeWidget(ImGui::SmallButton, ICON_FA_SAVE " Save")) {
|
if(drawUnsafeWidget(ImGui::SmallButton, ICON_FA_SAVE " Save")) {
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
switch(category) {
|
switch(category) {
|
||||||
case GameObjects::Weapon::Type::Melee:
|
case GameObjects::Weapon::Type::Melee:
|
||||||
if(!_currentMass->writeMeleeWeapons()) {
|
if(!_currentMass->writeMeleeWeapons()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GameObjects::Weapon::Type::Shield:
|
case GameObjects::Weapon::Type::Shield:
|
||||||
if(!_currentMass->writeShields()) {
|
if(!_currentMass->writeShields()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GameObjects::Weapon::Type::BulletShooter:
|
case GameObjects::Weapon::Type::BulletShooter:
|
||||||
if(!_currentMass->writeBulletShooters()) {
|
if(!_currentMass->writeBulletShooters()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GameObjects::Weapon::Type::EnergyShooter:
|
case GameObjects::Weapon::Type::EnergyShooter:
|
||||||
if(!_currentMass->writeEnergyShooters()) {
|
if(!_currentMass->writeEnergyShooters()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GameObjects::Weapon::Type::BulletLauncher:
|
case GameObjects::Weapon::Type::BulletLauncher:
|
||||||
if(!_currentMass->writeBulletLaunchers()) {
|
if(!_currentMass->writeBulletLaunchers()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GameObjects::Weapon::Type::EnergyLauncher:
|
case GameObjects::Weapon::Type::EnergyLauncher:
|
||||||
if(!_currentMass->writeEnergyLaunchers()) {
|
if(!_currentMass->writeEnergyLaunchers()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
_queue.addToast(Toast::Type::Error, "Unknown weapon type");
|
_modifiedBySaveTool = false;
|
||||||
|
_queue.addToast(Toast::Type::Error, "Unknown weapon type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,6 +91,7 @@ Application::drawProfileManager() {
|
||||||
{
|
{
|
||||||
_currentProfile = _profileManager->getProfile(i);
|
_currentProfile = _profileManager->getProfile(i);
|
||||||
initialiseMassManager();
|
initialiseMassManager();
|
||||||
|
initialiseFileWatcher();
|
||||||
_uiState = UiState::MainManager;
|
_uiState = UiState::MainManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -193,6 +193,23 @@ Application::drawAbout() {
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(ImGui::TreeNodeEx("Entropia File System Watcher (efsw)", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
||||||
|
auto efsw_repo = "https://github.com/SpartanJ/efsw";
|
||||||
|
drawAlignedText(ICON_FA_GITHUB " %s", efsw_repo);
|
||||||
|
ImGui::SameLine();
|
||||||
|
if(ImGui::Button("Copy to clipboard")) {
|
||||||
|
ImGui::SetClipboardText(efsw_repo);
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if(ImGui::Button("Open in browser")) {
|
||||||
|
openUri(efsw_repo);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TextUnformatted("Licence: MIT");
|
||||||
|
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
|
||||||
if(ImGui::TreeNodeEx("libcurl", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
if(ImGui::TreeNodeEx("libcurl", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
||||||
ImGui::Text("Version used: %s", LIBCURL_VERSION);
|
ImGui::Text("Version used: %s", LIBCURL_VERSION);
|
||||||
auto curl_website = "https://curl.se/libcurl";
|
auto curl_website = "https://curl.se/libcurl";
|
||||||
|
|
|
@ -18,7 +18,7 @@ set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
set(SAVETOOL_PROJECT_VERSION 1.6.1)
|
set(SAVETOOL_PROJECT_VERSION 1.6.0)
|
||||||
|
|
||||||
find_package(Corrade REQUIRED Containers Utility)
|
find_package(Corrade REQUIRED Containers Utility)
|
||||||
if(CORRADE_TARGET_WINDOWS)
|
if(CORRADE_TARGET_WINDOWS)
|
||||||
|
@ -31,6 +31,10 @@ if(SAVETOOL_USE_SYSTEM_LIBZIP)
|
||||||
find_package(libzip REQUIRED)
|
find_package(libzip REQUIRED)
|
||||||
endif(SAVETOOL_USE_SYSTEM_LIBZIP)
|
endif(SAVETOOL_USE_SYSTEM_LIBZIP)
|
||||||
|
|
||||||
|
if(SAVETOOL_USE_SYSTEM_EFSW)
|
||||||
|
find_package(efsw REQUIRED)
|
||||||
|
endif(SAVETOOL_USE_SYSTEM_EFSW)
|
||||||
|
|
||||||
if(SAVETOOL_USE_SYSTEM_LIBCURL)
|
if(SAVETOOL_USE_SYSTEM_LIBCURL)
|
||||||
find_package(CURL REQUIRED HTTPS)
|
find_package(CURL REQUIRED HTTPS)
|
||||||
endif(SAVETOOL_USE_SYSTEM_LIBCURL)
|
endif(SAVETOOL_USE_SYSTEM_LIBCURL)
|
||||||
|
@ -141,6 +145,7 @@ add_executable(MassBuilderSaveTool
|
||||||
Application/Application.cpp
|
Application/Application.cpp
|
||||||
Application/Application_drawAbout.cpp
|
Application/Application_drawAbout.cpp
|
||||||
Application/Application_drawMainMenu.cpp
|
Application/Application_drawMainMenu.cpp
|
||||||
|
Application/Application_FileWatcher.cpp
|
||||||
Application/Application_Initialisation.cpp
|
Application/Application_Initialisation.cpp
|
||||||
Application/Application_MainManager.cpp
|
Application/Application_MainManager.cpp
|
||||||
Application/Application_MassViewer.cpp
|
Application/Application_MassViewer.cpp
|
||||||
|
@ -221,7 +226,7 @@ target_compile_definitions(MassBuilderSaveTool PRIVATE
|
||||||
SAVETOOL_VERSION_STRING="${SAVETOOL_PROJECT_VERSION}"
|
SAVETOOL_VERSION_STRING="${SAVETOOL_PROJECT_VERSION}"
|
||||||
SAVETOOL_VERSION_MAJOR=1
|
SAVETOOL_VERSION_MAJOR=1
|
||||||
SAVETOOL_VERSION_MINOR=6
|
SAVETOOL_VERSION_MINOR=6
|
||||||
SAVETOOL_VERSION_PATCH=1
|
SAVETOOL_VERSION_PATCH=0
|
||||||
SAVETOOL_VERSION_PRERELEASE=false
|
SAVETOOL_VERSION_PRERELEASE=false
|
||||||
SAVETOOL_CODENAME="Glorious Fuckery"
|
SAVETOOL_CODENAME="Glorious Fuckery"
|
||||||
SAVETOOL_SUPPORTED_GAME_VERSION="0.12.x"
|
SAVETOOL_SUPPORTED_GAME_VERSION="0.12.x"
|
||||||
|
@ -257,6 +262,12 @@ else()
|
||||||
target_link_libraries(MassBuilderSaveTool PRIVATE zip)
|
target_link_libraries(MassBuilderSaveTool PRIVATE zip)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(SAVETOOL_USE_SYSTEM_EFSW)
|
||||||
|
target_link_libraries(MassBuilderSaveTool PRIVATE efsw::efsw)
|
||||||
|
else()
|
||||||
|
target_link_libraries(MassBuilderSaveTool PRIVATE efsw)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(CORRADE_TARGET_WINDOWS)
|
if(CORRADE_TARGET_WINDOWS)
|
||||||
target_link_libraries(MassBuilderSaveTool PRIVATE
|
target_link_libraries(MassBuilderSaveTool PRIVATE
|
||||||
Corrade::Main
|
Corrade::Main
|
||||||
|
|
1
third-party/efsw
vendored
Submodule
1
third-party/efsw
vendored
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 87abe599995d5646f5d83cf2e3a225bd73148b3a
|
Loading…
Reference in a new issue