1.5: Fuckin' UE5... #38

Manually merged
williamjcm merged 126 commits from one-point-five into master 2024-07-22 11:06:13 +02:00
135 changed files with 2727 additions and 2094 deletions
Showing only changes of commit 819e144410 - Show all commits

View file

@ -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 "SaveTool.h"
#include <Corrade/Containers/ScopeGuard.h> #include <Corrade/Containers/ScopeGuard.h>
#include <Corrade/Utility/Unicode.h> #include <Corrade/Utility/Unicode.h>
@ -37,6 +35,8 @@
#include "../Configuration/Configuration.h" #include "../Configuration/Configuration.h"
#include "../Logger/Logger.h" #include "../Logger/Logger.h"
#include "Application.h"
using namespace Containers::Literals; using namespace Containers::Literals;
extern const ImVec2 center_pivot = {0.5f, 0.5f}; extern const ImVec2 center_pivot = {0.5f, 0.5f};
@ -45,7 +45,9 @@ extern const ImVec2 center_pivot = {0.5f, 0.5f};
Utility::Tweakable tweak; Utility::Tweakable tweak;
#endif #endif
SaveTool::SaveTool(const Arguments& arguments): namespace mbst {
Application::Application(const Arguments& arguments):
Platform::Sdl2Application{arguments, Platform::Sdl2Application{arguments,
Configuration{}.setTitle("M.A.S.S. Builder Save Tool " SAVETOOL_VERSION_STRING " (\"" SAVETOOL_CODENAME "\")") Configuration{}.setTitle("M.A.S.S. Builder Save Tool " SAVETOOL_VERSION_STRING " (\"" SAVETOOL_CODENAME "\")")
.setSize({960, 720})} .setSize({960, 720})}
@ -82,7 +84,7 @@ SaveTool::SaveTool(const Arguments& arguments):
LOG_INFO("Registering custom events."); LOG_INFO("Registering custom events.");
if((_initEventId = SDL_RegisterEvents(3)) == std::uint32_t(-1)) { if((_initEventId = SDL_RegisterEvents(3)) == std::uint32_t(-1)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",
"SDL_RegisterEvents() failed in SaveTool::SaveTool(). Exiting...", window()); "SDL_RegisterEvents() failed in Application::SaveTool(). Exiting...", window());
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
return; return;
} }
@ -118,7 +120,7 @@ SaveTool::SaveTool(const Arguments& arguments):
checkGameState(); checkGameState();
_gameCheckTimerId = SDL_AddTimer(2000, _gameCheckTimerId = SDL_AddTimer(2000,
[](std::uint32_t interval, void* param)->std::uint32_t{ [](std::uint32_t interval, void* param)->std::uint32_t{
static_cast<SaveTool*>(param)->checkGameState(); static_cast<Application*>(param)->checkGameState();
return interval; return interval;
}, this); }, this);
if(_gameCheckTimerId == 0) { if(_gameCheckTimerId == 0) {
@ -149,7 +151,7 @@ SaveTool::SaveTool(const Arguments& arguments):
_timeline.start(); _timeline.start();
} }
SaveTool::~SaveTool() { Application::~Application() {
LOG_INFO("Cleaning up."); LOG_INFO("Cleaning up.");
SDL_RemoveTimer(_gameCheckTimerId); SDL_RemoveTimer(_gameCheckTimerId);
@ -162,7 +164,7 @@ SaveTool::~SaveTool() {
} }
void void
SaveTool::drawEvent() { Application::drawEvent() {
#ifdef SAVETOOL_DEBUG_BUILD #ifdef SAVETOOL_DEBUG_BUILD
tweak.update(); tweak.update();
#endif #endif
@ -183,7 +185,7 @@ SaveTool::drawEvent() {
} }
void void
SaveTool::viewportEvent(ViewportEvent& event) { Application::viewportEvent(ViewportEvent& event) {
GL::defaultFramebuffer.setViewport({{}, event.framebufferSize()}); GL::defaultFramebuffer.setViewport({{}, event.framebufferSize()});
const Vector2 size = Vector2{windowSize()}/dpiScaling(); const Vector2 size = Vector2{windowSize()}/dpiScaling();
@ -191,32 +193,32 @@ SaveTool::viewportEvent(ViewportEvent& event) {
} }
void void
SaveTool::keyPressEvent(KeyEvent& event) { Application::keyPressEvent(KeyEvent& event) {
if(_imgui.handleKeyPressEvent(event)) return; if(_imgui.handleKeyPressEvent(event)) return;
} }
void void
SaveTool::keyReleaseEvent(KeyEvent& event) { Application::keyReleaseEvent(KeyEvent& event) {
if(_imgui.handleKeyReleaseEvent(event)) return; if(_imgui.handleKeyReleaseEvent(event)) return;
} }
void void
SaveTool::mousePressEvent(MouseEvent& event) { Application::mousePressEvent(MouseEvent& event) {
if(_imgui.handleMousePressEvent(event)) return; if(_imgui.handleMousePressEvent(event)) return;
} }
void void
SaveTool::mouseReleaseEvent(MouseEvent& event) { Application::mouseReleaseEvent(MouseEvent& event) {
if(_imgui.handleMouseReleaseEvent(event)) return; if(_imgui.handleMouseReleaseEvent(event)) return;
} }
void void
SaveTool::mouseMoveEvent(MouseMoveEvent& event) { Application::mouseMoveEvent(MouseMoveEvent& event) {
if(_imgui.handleMouseMoveEvent(event)) return; if(_imgui.handleMouseMoveEvent(event)) return;
} }
void void
SaveTool::mouseScrollEvent(MouseScrollEvent& event) { Application::mouseScrollEvent(MouseScrollEvent& event) {
if(_imgui.handleMouseScrollEvent(event)) { if(_imgui.handleMouseScrollEvent(event)) {
event.setAccepted(); event.setAccepted();
return; return;
@ -224,12 +226,12 @@ SaveTool::mouseScrollEvent(MouseScrollEvent& event) {
} }
void void
SaveTool::textInputEvent(TextInputEvent& event) { Application::textInputEvent(TextInputEvent& event) {
if(_imgui.handleTextInputEvent(event)) return; if(_imgui.handleTextInputEvent(event)) return;
} }
void void
SaveTool::anyEvent(SDL_Event& event) { Application::anyEvent(SDL_Event& event) {
if(event.type == _initEventId) { if(event.type == _initEventId) {
initEvent(event); initEvent(event);
} }
@ -242,7 +244,7 @@ SaveTool::anyEvent(SDL_Event& event) {
} }
void void
SaveTool::drawImGui() { Application::drawImGui() {
_imgui.newFrame(); _imgui.newFrame();
if(ImGui::GetIO().WantTextInput && !isTextInputActive()) { if(ImGui::GetIO().WantTextInput && !isTextInputActive()) {
@ -260,7 +262,7 @@ SaveTool::drawImGui() {
} }
void void
SaveTool::drawGui() { Application::drawGui() {
drawMainMenu(); drawMainMenu();
switch(_uiState) { switch(_uiState) {
@ -303,7 +305,7 @@ SaveTool::drawGui() {
} }
void void
SaveTool::drawDisclaimer() { Application::drawDisclaimer() {
ImGui::SetNextWindowPos(ImVec2{Vector2{windowSize() / 2.0f} / dpiScaling()}, ImGuiCond_Always, center_pivot); ImGui::SetNextWindowPos(ImVec2{Vector2{windowSize() / 2.0f} / dpiScaling()}, ImGuiCond_Always, center_pivot);
if(ImGui::Begin("Disclaimer##DisclaimerWindow", nullptr, if(ImGui::Begin("Disclaimer##DisclaimerWindow", nullptr,
@ -371,7 +373,7 @@ SaveTool::drawDisclaimer() {
} }
void void
SaveTool::drawInitialisation() { Application::drawInitialisation() {
ImGui::SetNextWindowPos(ImVec2{Vector2{windowSize() / 2.0f} / dpiScaling()}, ImGuiCond_Always, center_pivot); ImGui::SetNextWindowPos(ImVec2{Vector2{windowSize() / 2.0f} / dpiScaling()}, ImGuiCond_Always, center_pivot);
if(ImGui::BeginPopupModal("##InitPopup", nullptr, if(ImGui::BeginPopupModal("##InitPopup", nullptr,
@ -385,7 +387,7 @@ SaveTool::drawInitialisation() {
} }
void void
SaveTool::drawGameState() { Application::drawGameState() {
ImGui::TextUnformatted("Game state:"); ImGui::TextUnformatted("Game state:");
ImGui::SameLine(); ImGui::SameLine();
{ {
@ -407,13 +409,13 @@ SaveTool::drawGameState() {
} }
void void
SaveTool::drawHelpMarker(Containers::StringView text, float wrap_pos) { Application::drawHelpMarker(Containers::StringView text, float wrap_pos) {
ImGui::TextUnformatted(ICON_FA_QUESTION_CIRCLE); ImGui::TextUnformatted(ICON_FA_QUESTION_CIRCLE);
drawTooltip(text, wrap_pos); drawTooltip(text, wrap_pos);
} }
void void
SaveTool::drawTooltip(Containers::StringView text, float wrap_pos) { Application::drawTooltip(Containers::StringView text, float wrap_pos) {
if(ImGui::IsItemHovered()){ if(ImGui::IsItemHovered()){
ImGui::BeginTooltip(); ImGui::BeginTooltip();
if(wrap_pos > 0.0f) { if(wrap_pos > 0.0f) {
@ -428,12 +430,12 @@ SaveTool::drawTooltip(Containers::StringView text, float wrap_pos) {
} }
bool bool
SaveTool::drawCheckbox(Containers::StringView label, bool value) { Application::drawCheckbox(Containers::StringView label, bool value) {
return ImGui::Checkbox(label.data(), &value); return ImGui::Checkbox(label.data(), &value);
} }
void void
SaveTool::openUri(Containers::StringView uri) { Application::openUri(Containers::StringView uri) {
if(!conf().isRunningInWine()) { if(!conf().isRunningInWine()) {
ShellExecuteA(nullptr, nullptr, uri.data(), nullptr, nullptr, SW_SHOWDEFAULT); ShellExecuteA(nullptr, nullptr, uri.data(), nullptr, nullptr, SW_SHOWDEFAULT);
} }
@ -443,7 +445,7 @@ SaveTool::openUri(Containers::StringView uri) {
} }
void void
SaveTool::checkGameState() { Application::checkGameState() {
WTS_PROCESS_INFOW* process_infos = nullptr; WTS_PROCESS_INFOW* process_infos = nullptr;
unsigned long process_count = 0; unsigned long process_count = 0;
@ -464,3 +466,5 @@ SaveTool::checkGameState() {
_gameState = GameState::Unknown; _gameState = GameState::Unknown;
} }
} }
}

View file

@ -51,11 +51,13 @@ using namespace Corrade;
using namespace Containers::Literals; using namespace Containers::Literals;
using namespace Magnum; using namespace Magnum;
class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener { namespace mbst {
public:
explicit SaveTool(const Arguments& arguments);
~SaveTool() override; class Application: public Platform::Sdl2Application, public efsw::FileWatchListener {
public:
explicit Application(const Arguments& arguments);
~Application() override;
void handleFileAction(efsw::WatchID watch_id, void handleFileAction(efsw::WatchID watch_id,
const std::string& dir, const std::string& dir,
@ -113,20 +115,20 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener
void drawInitialisation(); void drawInitialisation();
void drawProfileManager(); void drawProfileManager();
ImGuiID drawBackupListPopup(); auto drawBackupListPopup() -> ImGuiID;
ImGuiID drawBackupProfilePopup(std::size_t profile_index); auto drawBackupProfilePopup(std::size_t profile_index) -> ImGuiID;
ImGuiID drawDeleteProfilePopup(std::size_t profile_index); auto drawDeleteProfilePopup(std::size_t profile_index) -> ImGuiID;
void drawManager(); void drawManager();
bool drawIntEditPopup(int* value_to_edit, int max); bool drawIntEditPopup(int* value_to_edit, int max);
bool drawRenamePopup(Containers::ArrayView<char> name_view); bool drawRenamePopup(Containers::ArrayView<char> name_view);
void drawGeneralInfo(); void drawGeneralInfo();
void drawResearchInventory(); void drawResearchInventory();
void drawMaterialRow(Containers::StringView name, std::int32_t tier, MaterialID id); void drawMaterialRow(Containers::StringView name, std::int32_t tier, GameData::MaterialID id);
void drawUnavailableMaterialRow(Containers::StringView name, std::int32_t tier); void drawUnavailableMaterialRow(Containers::StringView name, std::int32_t tier);
void drawMassManager(); void drawMassManager();
ImGuiID drawDeleteMassPopup(int mass_index); auto drawDeleteMassPopup(int mass_index) -> ImGuiID;
ImGuiID drawDeleteStagedMassPopup(Containers::StringView filename); auto drawDeleteStagedMassPopup(Containers::StringView filename) -> ImGuiID;
void drawMassViewer(); void drawMassViewer();
void drawFrameInfo(); void drawFrameInfo();
@ -137,21 +139,24 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener
void drawArmour(); void drawArmour();
void drawCustomArmourStyles(); void drawCustomArmourStyles();
void drawWeapons(); void drawWeapons();
void drawWeaponCategory(Containers::StringView name, Containers::ArrayView<Weapon> weapons_view, bool& dirty, void drawWeaponCategory(Containers::StringView name, Containers::ArrayView<GameObjects::Weapon> weapons_view,
Containers::StringView payload_type, Containers::StringView payload_tooltip); bool& dirty, Containers::StringView payload_type,
void drawWeaponEditor(Weapon& weapon); Containers::StringView payload_tooltip);
void drawWeaponEditor(GameObjects::Weapon& weapon);
void drawGlobalStyles(); void drawGlobalStyles();
void drawTuning(); void drawTuning();
void drawDecalEditor(Decal& decal); void drawDecalEditor(GameObjects::Decal& decal);
void drawAccessoryEditor(Accessory& accessory, Containers::ArrayView<CustomStyle> style_view); void drawAccessoryEditor(GameObjects::Accessory& accessory,
Containers::StringView getStyleName(std::int32_t id, Containers::ArrayView<CustomStyle> view); Containers::ArrayView<GameObjects::CustomStyle> style_view);
auto getStyleName(std::int32_t id, Containers::ArrayView<GameObjects::CustomStyle> view)
-> Containers::StringView;
enum DCSResult { enum DCSResult {
DCS_Fail, DCS_Fail,
DCS_ResetStyle, DCS_ResetStyle,
DCS_Save DCS_Save
}; };
DCSResult drawCustomStyle(CustomStyle& style); auto drawCustomStyle(GameObjects::CustomStyle& style) -> DCSResult;
void drawAbout(); void drawAbout();
void drawGameState(); void drawGameState();
@ -206,11 +211,11 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener
MassViewer MassViewer
} _uiState{UiState::Disclaimer}; } _uiState{UiState::Disclaimer};
bool _aboutPopup{false}; bool _aboutPopup = false;
#ifdef SAVETOOL_DEBUG_BUILD #ifdef SAVETOOL_DEBUG_BUILD
bool _demoWindow{false}; bool _demoWindow = false;
bool _styleEditor{false}; bool _styleEditor = false;
bool _metricsWindow{false}; bool _metricsWindow = false;
#endif #endif
ToastQueue _queue; ToastQueue _queue;
@ -243,12 +248,12 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener
SDL_TimerID _gameCheckTimerId = 0; SDL_TimerID _gameCheckTimerId = 0;
Containers::Pointer<ProfileManager> _profileManager; Containers::Pointer<ProfileManager> _profileManager;
Profile* _currentProfile{nullptr}; GameObjects::Profile* _currentProfile = nullptr;
Containers::Pointer<MassManager> _massManager; Containers::Pointer<MassManager> _massManager;
Mass* _currentMass{nullptr}; GameObjects::Mass* _currentMass = nullptr;
Weapon* _currentWeapon = nullptr; GameObjects::Weapon* _currentWeapon = nullptr;
Containers::Pointer<efsw::FileWatcher> _fileWatcher; Containers::Pointer<efsw::FileWatcher> _fileWatcher;
enum watchID { enum watchID {
@ -260,22 +265,25 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener
Containers::Optional<UpdateChecker> _checker{Containers::NullOpt}; Containers::Optional<UpdateChecker> _checker{Containers::NullOpt};
std::mutex _checkerMutex; std::mutex _checkerMutex;
bool _modifiedBySaveTool{false}; bool _modifiedBySaveTool = false;
bool _jointsDirty{false}; bool _jointsDirty = false;
bool _stylesDirty{false}; bool _stylesDirty = false;
bool _eyeFlareDirty{false}; bool _eyeFlareDirty = false;
bool _meleeDirty = false;
bool _shieldsDirty = false;
bool _bShootersDirty = false;
bool _eShootersDirty = false;
bool _bLaunchersDirty = false;
bool _eLaunchersDirty = false;
Containers::StaticArray<38, std::int32_t> _selectedArmourDecals{ValueInit}; Containers::StaticArray<38, std::int32_t> _selectedArmourDecals{ValueInit};
Containers::StaticArray<38, std::int32_t> _selectedArmourAccessories{ValueInit}; Containers::StaticArray<38, std::int32_t> _selectedArmourAccessories{ValueInit};
std::int32_t _selectedBLPlacement{0}; std::int32_t _selectedBLPlacement = 0;
std::int32_t _selectedWeaponPart{0}; std::int32_t _selectedWeaponPart = 0;
std::int32_t _selectedWeaponDecal{0}; std::int32_t _selectedWeaponDecal = 0;
std::int32_t _selectedWeaponAccessory{0}; std::int32_t _selectedWeaponAccessory = 0;
bool _meleeDirty{false};
bool _shieldsDirty{false};
bool _bShootersDirty{false};
bool _eShootersDirty{false};
bool _bLaunchersDirty{false};
bool _eLaunchersDirty{false};
Timeline _timeline; Timeline _timeline;
}; };
}

View file

@ -24,10 +24,12 @@
#include <fileapi.h> #include <fileapi.h>
#include <handleapi.h> #include <handleapi.h>
#include "SaveTool.h" #include "Application.h"
namespace mbst {
void void
SaveTool::handleFileAction(efsw::WatchID watch_id, Application::handleFileAction(efsw::WatchID watch_id,
const std::string&, const std::string&,
const std::string& filename, const std::string& filename,
efsw::Action action, efsw::Action action,
@ -64,7 +66,7 @@ SaveTool::handleFileAction(efsw::WatchID watch_id,
} }
void void
SaveTool::fileUpdateEvent(SDL_Event& event) { Application::fileUpdateEvent(SDL_Event& event) {
Containers::String filename{static_cast<char*>(event.user.data1), Containers::String filename{static_cast<char*>(event.user.data1),
std::strlen(static_cast<char*>(event.user.data1)), nullptr}; std::strlen(static_cast<char*>(event.user.data1)), nullptr};
@ -153,3 +155,5 @@ SaveTool::fileUpdateEvent(SDL_Event& event) {
_queue.addToast(Toast::Type::Warning, "Unknown file action type"_s); _queue.addToast(Toast::Type::Warning, "Unknown file action type"_s);
} }
} }
}

View file

@ -14,7 +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 <Corrade/Containers/Pair.h>
#include <Corrade/Containers/ScopeGuard.h> #include <Corrade/Containers/ScopeGuard.h>
#include <Corrade/Utility/Path.h> #include <Corrade/Utility/Path.h>
#include <Corrade/Utility/Unicode.h> #include <Corrade/Utility/Unicode.h>
@ -29,10 +28,12 @@
#include "../FontAwesome/IconsFontAwesome5Brands.h" #include "../FontAwesome/IconsFontAwesome5Brands.h"
#include "../Logger/Logger.h" #include "../Logger/Logger.h"
#include "SaveTool.h" #include "Application.h"
namespace mbst {
void void
SaveTool::initEvent(SDL_Event& event) { Application::initEvent(SDL_Event& event) {
_initThread.join(); _initThread.join();
switch(event.user.code) { switch(event.user.code) {
@ -51,7 +52,7 @@ SaveTool::initEvent(SDL_Event& event) {
} }
void void
SaveTool::initialiseConfiguration() { Application::initialiseConfiguration() {
LOG_INFO("Reading configuration file."); LOG_INFO("Reading configuration file.");
setSwapInterval(conf().swapInterval()); setSwapInterval(conf().swapInterval());
@ -59,7 +60,7 @@ SaveTool::initialiseConfiguration() {
} }
void void
SaveTool::initialiseGui() { Application::initialiseGui() {
LOG_INFO("Initialising Dear ImGui."); LOG_INFO("Initialising Dear ImGui.");
auto ctx = ImGui::CreateContext(); auto ctx = ImGui::CreateContext();
@ -107,7 +108,7 @@ SaveTool::initialiseGui() {
} }
void void
SaveTool::initialiseManager() { Application::initialiseManager() {
LOG_INFO("Initialising the profile manager."); LOG_INFO("Initialising the profile manager.");
SDL_Event event; SDL_Event event;
@ -126,7 +127,7 @@ SaveTool::initialiseManager() {
} }
auto auto
SaveTool::initialiseToolDirectories() -> bool { Application::initialiseToolDirectories() -> bool {
LOG_INFO("Initialising Save Tool directories."); LOG_INFO("Initialising Save Tool directories.");
_backupsDir = Utility::Path::join(Utility::Path::split(*Utility::Path::executableLocation()).first(), "backups"); _backupsDir = Utility::Path::join(Utility::Path::split(*Utility::Path::executableLocation()).first(), "backups");
@ -188,7 +189,7 @@ SaveTool::initialiseToolDirectories() -> bool {
} }
auto auto
SaveTool::findGameDataDirectory() -> bool { Application::findGameDataDirectory() -> bool {
LOG_INFO("Searching for the game's save directory."); LOG_INFO("Searching for the game's save directory.");
wchar_t* localappdata_path = nullptr; wchar_t* localappdata_path = nullptr;
@ -223,16 +224,18 @@ SaveTool::findGameDataDirectory() -> bool {
} }
void void
SaveTool::initialiseMassManager() { Application::initialiseMassManager() {
LOG_INFO("Initialising the M.A.S.S. manager."); LOG_INFO("Initialising the M.A.S.S. manager.");
_massManager.emplace(_saveDir, _currentProfile->account(), _currentProfile->isDemo(), _stagingDir); _massManager.emplace(_saveDir, _currentProfile->account(), _currentProfile->isDemo(), _stagingDir);
} }
void void
SaveTool::initialiseFileWatcher() { Application::initialiseFileWatcher() {
LOG_INFO("Initialising the file watcher."); LOG_INFO("Initialising the file watcher.");
_fileWatcher.emplace(); _fileWatcher.emplace();
_watchIDs[SaveDir] = _fileWatcher->addWatch(_saveDir, this, false); _watchIDs[SaveDir] = _fileWatcher->addWatch(_saveDir, this, false);
_watchIDs[StagingDir] = _fileWatcher->addWatch(_stagingDir, this, false); _watchIDs[StagingDir] = _fileWatcher->addWatch(_stagingDir, this, false);
_fileWatcher->watch(); _fileWatcher->watch();
} }
}

View file

@ -28,10 +28,12 @@
#include "../Maps/LastMissionId.h" #include "../Maps/LastMissionId.h"
#include "../Maps/StoryProgress.h" #include "../Maps/StoryProgress.h"
#include "SaveTool.h" #include "Application.h"
namespace mbst {
void void
SaveTool::drawManager() { Application::drawManager() {
ImGui::SetNextWindowPos({0.0f, ImGui::GetItemRectSize().y}, ImGuiCond_Always); ImGui::SetNextWindowPos({0.0f, ImGui::GetItemRectSize().y}, ImGuiCond_Always);
ImGui::SetNextWindowSize(ImVec2{Vector2{float(windowSize().x()), float(windowSize().y()) - ImGui::GetItemRectSize().y} / dpiScaling()}, ImGui::SetNextWindowSize(ImVec2{Vector2{float(windowSize().x()), float(windowSize().y()) - ImGui::GetItemRectSize().y} / dpiScaling()},
ImGuiCond_Always); ImGuiCond_Always);
@ -99,7 +101,7 @@ SaveTool::drawManager() {
} }
bool bool
SaveTool::drawIntEditPopup(int* value_to_edit, int max) { Application::drawIntEditPopup(int* value_to_edit, int max) {
bool apply = false; bool apply = false;
if(ImGui::BeginPopup("int_edit")) { if(ImGui::BeginPopup("int_edit")) {
ImGui::Text("Please enter a value between 0 and %i:", max); ImGui::Text("Please enter a value between 0 and %i:", max);
@ -123,7 +125,7 @@ SaveTool::drawIntEditPopup(int* value_to_edit, int max) {
} }
bool bool
SaveTool::drawRenamePopup(Containers::ArrayView<char> name_view) { Application::drawRenamePopup(Containers::ArrayView<char> name_view) {
bool apply = false; bool apply = false;
if(ImGui::BeginPopup("name_edit")) { if(ImGui::BeginPopup("name_edit")) {
ImGui::TextUnformatted("Please enter a new name. Conditions:"); ImGui::TextUnformatted("Please enter a new name. Conditions:");
@ -178,16 +180,16 @@ SaveTool::drawRenamePopup(Containers::ArrayView<char> name_view) {
} }
void void
SaveTool::drawGeneralInfo() { Application::drawGeneralInfo() {
if(!_currentProfile) { if(!_currentProfile) {
return; return;
} }
ImGui::Text("Credits: %i", _currentProfile->credits()); ImGui::Text("Credits: %i", _currentProfile->credits());
auto it = std::find_if(story_progress.begin(), story_progress.end(), auto it = std::find_if(GameData::story_progress.begin(), GameData::story_progress.end(),
[this](const StoryProgressPoint& p){ return p.id == _currentProfile->storyProgress(); }); [this](const GameData::StoryProgressPoint& p){ return p.id == _currentProfile->storyProgress(); });
if(it != story_progress.end()) if(it != GameData::story_progress.end())
{ {
ImGui::TextUnformatted("Story progress:"); ImGui::TextUnformatted("Story progress:");
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.x / 4.0f); ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.x / 4.0f);
@ -202,8 +204,8 @@ SaveTool::drawGeneralInfo() {
ImGui::Text("Story progress: 0x%x", _currentProfile->storyProgress()); ImGui::Text("Story progress: 0x%x", _currentProfile->storyProgress());
} }
if(mission_id_map.find(_currentProfile->lastMissionId()) != mission_id_map.cend()) { if(GameData::mission_id_map.find(_currentProfile->lastMissionId()) != GameData::mission_id_map.cend()) {
ImGui::Text("Last mission: %s", mission_id_map.at(_currentProfile->lastMissionId()).data()); ImGui::Text("Last mission: %s", GameData::mission_id_map.at(_currentProfile->lastMissionId()).data());
} }
else if(_currentProfile->lastMissionId() == -1) { else if(_currentProfile->lastMissionId() == -1) {
ImGui::TextUnformatted("Last mission: none"); ImGui::TextUnformatted("Last mission: none");
@ -260,7 +262,7 @@ SaveTool::drawGeneralInfo() {
if(_gameState != GameState::NotRunning) { if(_gameState != GameState::NotRunning) {
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
for(const auto& sp : story_progress) { for(const auto& sp : GameData::story_progress) {
if(ImGui::BeginMenu(sp.chapter.data())) { if(ImGui::BeginMenu(sp.chapter.data())) {
if(!sp.after) { if(!sp.after) {
if(ImGui::MenuItem(sp.point.data())) { if(ImGui::MenuItem(sp.point.data())) {
@ -287,7 +289,7 @@ SaveTool::drawGeneralInfo() {
} }
void void
SaveTool::drawResearchInventory() { Application::drawResearchInventory() {
if(!_currentProfile) { if(!_currentProfile) {
return; return;
} }
@ -304,48 +306,48 @@ SaveTool::drawResearchInventory() {
ImGui::TableSetColumnIndex(1); ImGui::TableSetColumnIndex(1);
ImGui::TextUnformatted("Engine materials"); ImGui::TextUnformatted("Engine materials");
drawMaterialRow("Verse steel", 1, VerseSteel); drawMaterialRow("Verse steel", 1, GameData::MaterialID::VerseSteel);
drawMaterialRow("Undinium", 2, Undinium); drawMaterialRow("Undinium", 2, GameData::MaterialID::Undinium);
drawMaterialRow("Necrium alloy", 3, NecriumAlloy); drawMaterialRow("Necrium alloy", 3, GameData::MaterialID::NecriumAlloy);
drawMaterialRow("Lunarite", 4, Lunarite); drawMaterialRow("Lunarite", 4, GameData::MaterialID::Lunarite);
drawMaterialRow("Asterite", 5, Asterite); drawMaterialRow("Asterite", 5, GameData::MaterialID::Asterite);
drawMaterialRow("Hallite fragma", 6, HalliteFragma); drawMaterialRow("Hallite fragma", 6, GameData::MaterialID::HalliteFragma);
drawUnavailableMaterialRow("Unnoctinium", 7); drawUnavailableMaterialRow("Unnoctinium", 7);
ImGui::TableNextRow(ImGuiTableRowFlags_Headers); ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
ImGui::TableSetColumnIndex(1); ImGui::TableSetColumnIndex(1);
ImGui::TextUnformatted("OS materials"); ImGui::TextUnformatted("OS materials");
drawMaterialRow("Ednil", 1, Ednil); drawMaterialRow("Ednil", 1, GameData::MaterialID::Ednil);
drawMaterialRow("Nuflalt", 2, Nuflalt); drawMaterialRow("Nuflalt", 2, GameData::MaterialID::Nuflalt);
drawMaterialRow("Aurelene", 3, Aurelene); drawMaterialRow("Aurelene", 3, GameData::MaterialID::Aurelene);
drawMaterialRow("Soldus", 4, Soldus); drawMaterialRow("Soldus", 4, GameData::MaterialID::Soldus);
drawMaterialRow("Synthesized N", 5, SynthesisedN); drawMaterialRow("Synthesized N", 5, GameData::MaterialID::SynthesisedN);
drawMaterialRow("Nanoc", 6, Nanoc); drawMaterialRow("Nanoc", 6, GameData::MaterialID::Nanoc);
drawUnavailableMaterialRow("Abyssillite", 7); drawUnavailableMaterialRow("Abyssillite", 7);
ImGui::TableNextRow(ImGuiTableRowFlags_Headers); ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
ImGui::TableSetColumnIndex(1); ImGui::TableSetColumnIndex(1);
ImGui::TextUnformatted("Architect materials"); ImGui::TextUnformatted("Architect materials");
drawMaterialRow("Alcarbonite", 1, Alcarbonite); drawMaterialRow("Alcarbonite", 1, GameData::MaterialID::Alcarbonite);
drawMaterialRow("Keriphene", 2, Keriphene); drawMaterialRow("Keriphene", 2, GameData::MaterialID::Keriphene);
drawMaterialRow("Nitinol-CM", 3, NitinolCM); drawMaterialRow("Nitinol-CM", 3, GameData::MaterialID::NitinolCM);
drawMaterialRow("Quarkium", 4, Quarkium); drawMaterialRow("Quarkium", 4, GameData::MaterialID::Quarkium);
drawMaterialRow("Alterene", 5, Alterene); drawMaterialRow("Alterene", 5, GameData::MaterialID::Alterene);
drawMaterialRow("Cosmium", 6, Cosmium); drawMaterialRow("Cosmium", 6, GameData::MaterialID::Cosmium);
drawUnavailableMaterialRow("Purified quarkium", 7); drawUnavailableMaterialRow("Purified quarkium", 7);
ImGui::TableNextRow(ImGuiTableRowFlags_Headers); ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
ImGui::TableSetColumnIndex(1); ImGui::TableSetColumnIndex(1);
ImGui::TextUnformatted("Quark data"); ImGui::TextUnformatted("Quark data");
drawMaterialRow("Mixed composition", 1, MixedComposition); drawMaterialRow("Mixed composition", 1, GameData::MaterialID::MixedComposition);
drawMaterialRow("Void residue", 2, VoidResidue); drawMaterialRow("Void residue", 2, GameData::MaterialID::VoidResidue);
drawMaterialRow("Muscular construction", 3, MuscularConstruction); drawMaterialRow("Muscular construction", 3, GameData::MaterialID::MuscularConstruction);
drawMaterialRow("Mineral exoskeletology", 4, MineralExoskeletology); drawMaterialRow("Mineral exoskeletology", 4, GameData::MaterialID::MineralExoskeletology);
drawMaterialRow("Carbonized skin", 5, CarbonisedSkin); drawMaterialRow("Carbonized skin", 5, GameData::MaterialID::CarbonisedSkin);
drawMaterialRow("Isolated void particle", 6, IsolatedVoidParticle); drawMaterialRow("Isolated void particle", 6, GameData::MaterialID::IsolatedVoidParticle);
drawUnavailableMaterialRow("Weaponised physiology", 7); drawUnavailableMaterialRow("Weaponised physiology", 7);
ImGui::EndTable(); ImGui::EndTable();
@ -353,7 +355,7 @@ SaveTool::drawResearchInventory() {
} }
void void
SaveTool::drawMaterialRow(Containers::StringView name, std::int32_t tier, MaterialID id) { Application::drawMaterialRow(Containers::StringView name, std::int32_t tier, GameData::MaterialID id) {
ImGui::TableNextRow(); ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0); ImGui::TableSetColumnIndex(0);
ImGui::Text("T%i", tier); ImGui::Text("T%i", tier);
@ -380,7 +382,7 @@ SaveTool::drawMaterialRow(Containers::StringView name, std::int32_t tier, Materi
} }
void void
SaveTool::drawUnavailableMaterialRow(Containers::StringView name, std::int32_t tier) { Application::drawUnavailableMaterialRow(Containers::StringView name, std::int32_t tier) {
ImGui::TableNextRow(); ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0); ImGui::TableSetColumnIndex(0);
ImGui::Text("T%i", tier); ImGui::Text("T%i", tier);
@ -391,7 +393,7 @@ SaveTool::drawUnavailableMaterialRow(Containers::StringView name, std::int32_t t
} }
void void
SaveTool::drawMassManager() { Application::drawMassManager() {
if(!_massManager) { if(!_massManager) {
return; return;
} }
@ -426,7 +428,7 @@ SaveTool::drawMassManager() {
ImGui::TableSetColumnIndex(0); ImGui::TableSetColumnIndex(0);
ImGui::Selectable(Utility::format("{:.2d}", i + 1).data(), ImGui::Selectable(Utility::format("{:.2d}", i + 1).data(),
false, ImGuiSelectableFlags_SpanAllColumns|ImGuiSelectableFlags_AllowItemOverlap); false, ImGuiSelectableFlags_SpanAllColumns|ImGuiSelectableFlags_AllowItemOverlap);
if(_massManager->hangar(i).state() == Mass::State::Valid && if(_massManager->hangar(i).state() == GameObjects::Mass::State::Valid &&
ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceNoHoldToOpenOthers)) ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceNoHoldToOpenOthers))
{ {
drag_drop_index = i; drag_drop_index = i;
@ -440,7 +442,7 @@ SaveTool::drawMassManager() {
if(const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("StagedMass")) { if(const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("StagedMass")) {
if(payload->DataSize != sizeof(Containers::String)) { if(payload->DataSize != sizeof(Containers::String)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal error", SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal error",
"payload->DataSize != sizeof(Containers::String) in SaveTool::drawMassManager()", "payload->DataSize != sizeof(Containers::String) in Application::drawMassManager()",
window()); window());
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -454,7 +456,7 @@ SaveTool::drawMassManager() {
else if((payload = ImGui::AcceptDragDropPayload("Mass"))) { else if((payload = ImGui::AcceptDragDropPayload("Mass"))) {
if(payload->DataSize != sizeof(int)) { if(payload->DataSize != sizeof(int)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal error", SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal error",
"payload->DataSize != sizeof(int) in SaveTool::drawMassManager()", "payload->DataSize != sizeof(int) in Application::drawMassManager()",
window()); window());
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -471,13 +473,13 @@ SaveTool::drawMassManager() {
ImGui::TableSetColumnIndex(1); ImGui::TableSetColumnIndex(1);
switch(_massManager->hangar(i).state()) { switch(_massManager->hangar(i).state()) {
case Mass::State::Empty: case GameObjects::Mass::State::Empty:
ImGui::TextDisabled("<empty>"); ImGui::TextDisabled("<empty>");
break; break;
case Mass::State::Invalid: case GameObjects::Mass::State::Invalid:
ImGui::TextDisabled("<invalid>"); ImGui::TextDisabled("<invalid>");
break; break;
case Mass::State::Valid: case GameObjects::Mass::State::Valid:
ImGui::TextUnformatted(_massManager->hangar(i).name().data()); ImGui::TextUnformatted(_massManager->hangar(i).name().data());
break; break;
} }
@ -488,10 +490,10 @@ SaveTool::drawMassManager() {
drawTooltip("This is the currently active frame slot."); drawTooltip("This is the currently active frame slot.");
} }
if(_massManager->hangar(i).state() != Mass::State::Empty) { if(_massManager->hangar(i).state() != GameObjects::Mass::State::Empty) {
ImGui::TableSetColumnIndex(3); ImGui::TableSetColumnIndex(3);
ImGui::PushID(i); ImGui::PushID(i);
if(_massManager->hangar(i).state() == Mass::State::Valid) { if(_massManager->hangar(i).state() == GameObjects::Mass::State::Valid) {
if(ImGui::SmallButton(ICON_FA_SEARCH)) { if(ImGui::SmallButton(ICON_FA_SEARCH)) {
_currentMass = &_massManager->hangar(i); _currentMass = &_massManager->hangar(i);
_uiState = UiState::MassViewer; _uiState = UiState::MassViewer;
@ -570,7 +572,7 @@ SaveTool::drawMassManager() {
if(const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("Mass")) { if(const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("Mass")) {
if(payload->DataSize != sizeof(int)) { if(payload->DataSize != sizeof(int)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal error", SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal error",
"payload->DataSize != sizeof(int) in SaveTool::drawMassManager()", "payload->DataSize != sizeof(int) in Application::drawMassManager()",
window()); window());
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -589,14 +591,14 @@ SaveTool::drawMassManager() {
} }
ImGuiID ImGuiID
SaveTool::drawDeleteMassPopup(int mass_index) { Application::drawDeleteMassPopup(int mass_index) {
if(!ImGui::BeginPopupModal("Confirmation##DeleteMassConfirmation", nullptr, if(!ImGui::BeginPopupModal("Confirmation##DeleteMassConfirmation", nullptr,
ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoMove)) ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoMove))
{ {
return ImGui::GetID("Confirmation##DeleteMassConfirmation"); return ImGui::GetID("Confirmation##DeleteMassConfirmation");
} }
if(_massManager->hangar(mass_index).state() == Mass::State::Empty) { if(_massManager->hangar(mass_index).state() == GameObjects::Mass::State::Empty) {
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
ImGui::EndPopup(); ImGui::EndPopup();
return 0; return 0;
@ -609,7 +611,7 @@ SaveTool::drawDeleteMassPopup(int mass_index) {
} }
ImGui::PushTextWrapPos(float(windowSize().x()) * 0.40f); ImGui::PushTextWrapPos(float(windowSize().x()) * 0.40f);
if(_massManager->hangar(mass_index).state() == Mass::State::Invalid) { if(_massManager->hangar(mass_index).state() == GameObjects::Mass::State::Invalid) {
ImGui::Text("Are you sure you want to delete the invalid M.A.S.S. data in hangar %.2i ? This operation is irreversible.", ImGui::Text("Are you sure you want to delete the invalid M.A.S.S. data in hangar %.2i ? This operation is irreversible.",
mass_index + 1); mass_index + 1);
} }
@ -646,7 +648,7 @@ SaveTool::drawDeleteMassPopup(int mass_index) {
} }
ImGuiID ImGuiID
SaveTool::drawDeleteStagedMassPopup(Containers::StringView filename) { Application::drawDeleteStagedMassPopup(Containers::StringView filename) {
if(!ImGui::BeginPopupModal("Confirmation##DeleteStagedMassConfirmation", nullptr, if(!ImGui::BeginPopupModal("Confirmation##DeleteStagedMassConfirmation", nullptr,
ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoMove)) ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoMove))
{ {
@ -683,3 +685,5 @@ SaveTool::drawDeleteStagedMassPopup(Containers::StringView filename) {
return 0; return 0;
} }
}

View file

@ -25,11 +25,13 @@
#define STYLENAMES_DEFINITION #define STYLENAMES_DEFINITION
#include "../Maps/StyleNames.h" #include "../Maps/StyleNames.h"
#include "SaveTool.h" #include "Application.h"
namespace mbst {
void void
SaveTool::drawMassViewer() { Application::drawMassViewer() {
if(!_currentMass || _currentMass->state() != Mass::State::Valid) { if(!_currentMass || _currentMass->state() != GameObjects::Mass::State::Valid) {
_currentMass = nullptr; _currentMass = nullptr;
_currentWeapon = nullptr; _currentWeapon = nullptr;
_uiState = UiState::MainManager; _uiState = UiState::MainManager;
@ -156,8 +158,8 @@ SaveTool::drawMassViewer() {
} }
void void
SaveTool::drawGlobalStyles() { Application::drawGlobalStyles() {
if(!_currentMass || _currentMass->state() != Mass::State::Valid) { if(!_currentMass || _currentMass->state() != GameObjects::Mass::State::Valid) {
return; return;
} }
@ -193,8 +195,8 @@ SaveTool::drawGlobalStyles() {
} }
void void
SaveTool::drawTuning() { Application::drawTuning() {
if(!_currentMass || _currentMass->state() != Mass::State::Valid) { if(!_currentMass || _currentMass->state() != GameObjects::Mass::State::Valid) {
return; return;
} }
@ -289,9 +291,9 @@ SaveTool::drawTuning() {
ImGui::EndTable(); ImGui::EndTable();
} }
SaveTool::DCSResult Application::DCSResult
SaveTool::drawCustomStyle(CustomStyle& style) { Application::drawCustomStyle(GameObjects::CustomStyle& style) {
if(!_currentMass || _currentMass->state() != Mass::State::Valid) { if(!_currentMass || _currentMass->state() != GameObjects::Mass::State::Valid) {
return DCS_Fail; return DCS_Fail;
} }
@ -396,7 +398,7 @@ SaveTool::drawCustomStyle(CustomStyle& style) {
} }
void void
SaveTool::drawDecalEditor(Decal& decal) { Application::drawDecalEditor(GameObjects::Decal& decal) {
ImGui::Text("ID: %i", decal.id); ImGui::Text("ID: %i", decal.id);
if(ImGui::BeginTable("##DecalTable", conf().advancedMode() ? 2 : 1, ImGuiTableFlags_BordersInnerV)) { if(ImGui::BeginTable("##DecalTable", conf().advancedMode() ? 2 : 1, ImGuiTableFlags_BordersInnerV)) {
@ -501,12 +503,12 @@ SaveTool::drawDecalEditor(Decal& decal) {
} }
void void
SaveTool::drawAccessoryEditor(Accessory& accessory, Containers::ArrayView<CustomStyle> style_view) { Application::drawAccessoryEditor(GameObjects::Accessory& accessory, Containers::ArrayView<GameObjects::CustomStyle> style_view) {
if(accessory.id < 1) { if(accessory.id < 1) {
ImGui::TextUnformatted("Accessory: <none>"); ImGui::TextUnformatted("Accessory: <none>");
} }
else if(accessories.find(accessory.id) != accessories.cend()) { else if(GameData::accessories.find(accessory.id) != GameData::accessories.cend()) {
ImGui::Text("Accessory #%.4i - %s", accessory.id, accessories.at(accessory.id).name.data()); ImGui::Text("Accessory #%.4i - %s", accessory.id, GameData::accessories.at(accessory.id).name.data());
} }
else { else {
ImGui::Text("Accessory #%i", accessory.id); ImGui::Text("Accessory #%i", accessory.id);
@ -516,7 +518,7 @@ SaveTool::drawAccessoryEditor(Accessory& accessory, Containers::ArrayView<Custom
ImGui::SameLine(); ImGui::SameLine();
static std::int32_t tab = 0; static std::int32_t tab = 0;
static Containers::Optional<AccessorySize> size = Containers::NullOpt; static Containers::Optional<GameData::Accessory::Size> size = Containers::NullOpt;
if(ImGui::SmallButton("Change")) { if(ImGui::SmallButton("Change")) {
ImGui::OpenPopup("##AccessoryPopup"); ImGui::OpenPopup("##AccessoryPopup");
if(accessory.id >= 3000) { if(accessory.id >= 3000) {
@ -574,45 +576,45 @@ SaveTool::drawAccessoryEditor(Accessory& accessory, Containers::ArrayView<Custom
ImGui::SameLine(); ImGui::SameLine();
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical); ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
ImGui::SameLine(); ImGui::SameLine();
if(ImGui::Selectable("S", size && *size == AccessorySize::S, ImGuiSelectableFlags_DontClosePopups, {70.0f, 0.0f})) { if(ImGui::Selectable("S", size && *size == GameData::Accessory::Size::S, ImGuiSelectableFlags_DontClosePopups, {70.0f, 0.0f})) {
if(!size) { if(!size) {
size.emplace(); size.emplace();
} }
*size = AccessorySize::S; *size = GameData::Accessory::Size::S;
} }
ImGui::SameLine(); ImGui::SameLine();
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical); ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
ImGui::SameLine(); ImGui::SameLine();
if(ImGui::Selectable("M", size && *size == AccessorySize::M, ImGuiSelectableFlags_DontClosePopups, {70.0f, 0.0f})) { if(ImGui::Selectable("M", size && *size == GameData::Accessory::Size::M, ImGuiSelectableFlags_DontClosePopups, {70.0f, 0.0f})) {
if(!size) { if(!size) {
size.emplace(); size.emplace();
} }
*size = AccessorySize::M; *size = GameData::Accessory::Size::M;
} }
ImGui::SameLine(); ImGui::SameLine();
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical); ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
ImGui::SameLine(); ImGui::SameLine();
if(ImGui::Selectable("L", size && *size == AccessorySize::L, ImGuiSelectableFlags_DontClosePopups, {70.0f, 0.0f})) { if(ImGui::Selectable("L", size && *size == GameData::Accessory::Size::L, ImGuiSelectableFlags_DontClosePopups, {70.0f, 0.0f})) {
if(!size) { if(!size) {
size.emplace(); size.emplace();
} }
*size = AccessorySize::L; *size = GameData::Accessory::Size::L;
} }
ImGui::SameLine(); ImGui::SameLine();
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical); ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
ImGui::SameLine(); ImGui::SameLine();
if(ImGui::Selectable("XL", size && *size == AccessorySize::XL, ImGuiSelectableFlags_DontClosePopups, {70.0f, 0.0f})) { if(ImGui::Selectable("XL", size && *size == GameData::Accessory::Size::XL, ImGuiSelectableFlags_DontClosePopups, {70.0f, 0.0f})) {
if(!size) { if(!size) {
size.emplace(); size.emplace();
} }
*size = AccessorySize::XL; *size = GameData::Accessory::Size::XL;
} }
ImGui::PopStyleVar(); ImGui::PopStyleVar();
ImGui::Separator(); ImGui::Separator();
if(ImGui::BeginListBox("##AccessoryListbox", {-1.0f, 0.0f})) { if(ImGui::BeginListBox("##AccessoryListbox", {-1.0f, 0.0f})) {
for(const auto& acc : accessories) { for(const auto& acc : GameData::accessories) {
if(acc.first >= tab * 1000 && acc.first < ((tab + 1) * 1000) && (!size || *size == acc.second.size)) { if(acc.first >= tab * 1000 && acc.first < ((tab + 1) * 1000) && (!size || *size == acc.second.size)) {
if(ImGui::Selectable(Utility::format("#{:.4d} - {} ({})", acc.first, acc.second.name, size_labels[acc.second.size]).data(), if(ImGui::Selectable(Utility::format("#{:.4d} - {} ({})", acc.first, acc.second.name, size_labels[acc.second.size]).data(),
acc.first == accessory.id)) acc.first == accessory.id))
@ -658,7 +660,7 @@ SaveTool::drawAccessoryEditor(Accessory& accessory, Containers::ArrayView<Custom
ImGui::BeginGroup(); ImGui::BeginGroup();
ImGui::PushMultiItemsWidths(2, ImGui::CalcItemWidth()); ImGui::PushMultiItemsWidths(2, ImGui::CalcItemWidth());
if(ImGui::BeginCombo("##Style1", getStyleName(accessory.styles[0], style_view).data())) { if(ImGui::BeginCombo("##Style1", getStyleName(accessory.styles[0], style_view).data())) {
for(const auto& style : style_names) { for(const auto& style : GameData::style_names) {
if(ImGui::Selectable(getStyleName(style.first, style_view).data(), accessory.styles[0] == style.first)) { if(ImGui::Selectable(getStyleName(style.first, style_view).data(), accessory.styles[0] == style.first)) {
accessory.styles[0] = style.first; accessory.styles[0] = style.first;
} }
@ -669,7 +671,7 @@ SaveTool::drawAccessoryEditor(Accessory& accessory, Containers::ArrayView<Custom
ImGui::PopItemWidth(); ImGui::PopItemWidth();
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
if(ImGui::BeginCombo("##Style2", getStyleName(accessory.styles[1], style_view).data())) { if(ImGui::BeginCombo("##Style2", getStyleName(accessory.styles[1], style_view).data())) {
for(const auto& style : style_names) { for(const auto& style : GameData::style_names) {
if(ImGui::Selectable(getStyleName(style.first, style_view).data(), accessory.styles[1] == style.first)) { if(ImGui::Selectable(getStyleName(style.first, style_view).data(), accessory.styles[1] == style.first)) {
accessory.styles[1] = style.first; accessory.styles[1] = style.first;
} }
@ -740,7 +742,7 @@ SaveTool::drawAccessoryEditor(Accessory& accessory, Containers::ArrayView<Custom
} }
Containers::StringView Containers::StringView
SaveTool::getStyleName(std::int32_t id, Containers::ArrayView<CustomStyle> view) { Application::getStyleName(std::int32_t id, Containers::ArrayView<GameObjects::CustomStyle> view) {
if(id >= 0 && id <= 15) { if(id >= 0 && id <= 15) {
return view[id].name; return view[id].name;
} }
@ -748,6 +750,8 @@ SaveTool::getStyleName(std::int32_t id, Containers::ArrayView<CustomStyle> view)
return _currentMass->globalStyles()[id - 50].name; return _currentMass->globalStyles()[id - 50].name;
} }
else { else {
return style_names.at(id); return GameData::style_names.at(id);
} }
} }
}

View file

@ -19,11 +19,13 @@
#include "../Maps/ArmourSets.h" #include "../Maps/ArmourSets.h"
#include "../Maps/StyleNames.h" #include "../Maps/StyleNames.h"
#include "SaveTool.h" #include "Application.h"
namespace mbst {
void void
SaveTool::drawArmour() { Application::drawArmour() {
if(!_currentMass || _currentMass->state() != Mass::State::Valid) { if(!_currentMass || _currentMass->state() != GameObjects::Mass::State::Valid) {
return; return;
} }
@ -52,11 +54,17 @@ SaveTool::drawArmour() {
std::memset(header, '\0', 129); std::memset(header, '\0', 129);
if(armour_sets.find(part.id) != armour_sets.cend()) { if(GameData::armour_sets.find(part.id) != GameData::armour_sets.cend()) {
std::snprintf(header, 128, "%s: %s###%u", slot_labels[std::uint32_t(part.slot)].data(), armour_sets.at(part.id).name.data(), std::uint32_t(part.slot)); std::snprintf(header, 128, "%s: %s###%u",
slot_labels[std::uint32_t(part.slot)].data(),
GameData::armour_sets.at(part.id).name.data(),
std::uint32_t(part.slot));
} }
else { else {
std::snprintf(header, 128, "%s: %i###%u", slot_labels[std::uint32_t(part.slot)].data(), part.id, std::uint32_t(part.slot)); std::snprintf(header, 128, "%s: %i###%u",
slot_labels[std::uint32_t(part.slot)].data(),
part.id,
std::uint32_t(part.slot));
} }
if(ImGui::CollapsingHeader(header)) { if(ImGui::CollapsingHeader(header)) {
@ -65,14 +73,14 @@ SaveTool::drawArmour() {
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x * 0.491f); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x * 0.491f);
if(ImGui::BeginListBox("##ChangePart")) { if(ImGui::BeginListBox("##ChangePart")) {
if(std::strncmp("Neck", slot_labels[std::uint32_t(part.slot)].data(), 4) != 0) { if(std::strncmp("Neck", slot_labels[std::uint32_t(part.slot)].data(), 4) != 0) {
for(auto& set : armour_sets) { for(auto& set : GameData::armour_sets) {
if(ImGui::Selectable(set.second.name.data(), set.first == part.id, ImGuiSelectableFlags_SpanAvailWidth)) { if(ImGui::Selectable(set.second.name.data(), set.first == part.id, ImGuiSelectableFlags_SpanAvailWidth)) {
part.id = set.first; part.id = set.first;
} }
} }
} }
else { else {
for(auto& set : armour_sets) { for(auto& set : GameData::armour_sets) {
if(!set.second.neck_compatible) { if(!set.second.neck_compatible) {
continue; continue;
} }
@ -106,7 +114,7 @@ SaveTool::drawArmour() {
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - 2.0f); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - 2.0f);
if(ImGui::BeginCombo("##Style", getStyleName(part.styles[j], _currentMass->armourCustomStyles()).data())) { if(ImGui::BeginCombo("##Style", getStyleName(part.styles[j], _currentMass->armourCustomStyles()).data())) {
for(const auto& style : style_names) { for(const auto& style : GameData::style_names) {
if(ImGui::Selectable(getStyleName(style.first, _currentMass->armourCustomStyles()).data(), part.styles[j] == style.first)) { if(ImGui::Selectable(getStyleName(style.first, _currentMass->armourCustomStyles()).data(), part.styles[j] == style.first)) {
part.styles[j] = style.first; part.styles[j] = style.first;
} }
@ -164,19 +172,19 @@ SaveTool::drawArmour() {
ImGui::PopID(); ImGui::PopID();
} }
if(_currentMass->bulletLauncherAttachmentStyle() != BulletLauncherAttachmentStyle::NotFound && if(_currentMass->bulletLauncherAttachmentStyle() != GameObjects::BulletLauncherAttachmentStyle::NotFound &&
ImGui::CollapsingHeader("Bullet launcher placement")) ImGui::CollapsingHeader("Bullet launcher placement"))
{ {
drawAlignedText("Attachment style:"_s); drawAlignedText("Attachment style:"_s);
ImGui::SameLine(); ImGui::SameLine();
ImGui::RadioButton("Active one", ImGui::RadioButton("Active one",
_currentMass->bulletLauncherAttachmentStyle() == BulletLauncherAttachmentStyle::ActiveOne); _currentMass->bulletLauncherAttachmentStyle() == GameObjects::BulletLauncherAttachmentStyle::ActiveOne);
ImGui::SameLine(); ImGui::SameLine();
ImGui::RadioButton("Active one per slot", ImGui::RadioButton("Active one per slot",
_currentMass->bulletLauncherAttachmentStyle() == BulletLauncherAttachmentStyle::ActiveOnePerSlot); _currentMass->bulletLauncherAttachmentStyle() == GameObjects::BulletLauncherAttachmentStyle::ActiveOnePerSlot);
ImGui::SameLine(); ImGui::SameLine();
ImGui::RadioButton("All equipped", ImGui::RadioButton("All equipped",
_currentMass->bulletLauncherAttachmentStyle() == BulletLauncherAttachmentStyle::AllEquipped); _currentMass->bulletLauncherAttachmentStyle() == GameObjects::BulletLauncherAttachmentStyle::AllEquipped);
ImGui::Separator(); ImGui::Separator();
@ -203,13 +211,13 @@ SaveTool::drawArmour() {
if(ImGui::BeginCombo("##Socket", socket_labels[std::uint32_t(placement.socket)].data())) { if(ImGui::BeginCombo("##Socket", socket_labels[std::uint32_t(placement.socket)].data())) {
for(std::uint32_t i = 0; i < (sizeof(socket_labels) / sizeof(socket_labels[0])); i++) { for(std::uint32_t i = 0; i < (sizeof(socket_labels) / sizeof(socket_labels[0])); i++) {
if(ImGui::Selectable(socket_labels[i].data(), i == std::uint32_t(placement.socket), ImGuiSelectableFlags_SpanAvailWidth)) { if(ImGui::Selectable(socket_labels[i].data(), i == std::uint32_t(placement.socket), ImGuiSelectableFlags_SpanAvailWidth)) {
placement.socket = static_cast<BulletLauncherSocket>(i); placement.socket = static_cast<GameObjects::BulletLauncherAttachment::Socket>(i);
} }
} }
ImGui::EndCombo(); ImGui::EndCombo();
} }
if(placement.socket != BulletLauncherSocket::Auto) { if(placement.socket != GameObjects::BulletLauncherAttachment::Socket::Auto) {
ImGui::BeginGroup(); ImGui::BeginGroup();
drawAlignedText("Relative position:"); drawAlignedText("Relative position:");
drawAlignedText("Offset position:"); drawAlignedText("Offset position:");
@ -290,8 +298,8 @@ SaveTool::drawArmour() {
} }
void void
SaveTool::drawCustomArmourStyles() { Application::drawCustomArmourStyles() {
if(!_currentMass || _currentMass->state() != Mass::State::Valid) { if(!_currentMass || _currentMass->state() != GameObjects::Mass::State::Valid) {
return; return;
} }
@ -325,3 +333,5 @@ SaveTool::drawCustomArmourStyles() {
ImGui::EndChild(); ImGui::EndChild();
} }
}

View file

@ -17,11 +17,13 @@
#include "../FontAwesome/IconsFontAwesome5.h" #include "../FontAwesome/IconsFontAwesome5.h"
#include "../Maps/StyleNames.h" #include "../Maps/StyleNames.h"
#include "SaveTool.h" #include "Application.h"
namespace mbst {
void void
SaveTool::drawFrameInfo() { Application::drawFrameInfo() {
if(!_currentMass || _currentMass->state() != Mass::State::Valid) { if(!_currentMass || _currentMass->state() != GameObjects::Mass::State::Valid) {
return; return;
} }
@ -81,8 +83,8 @@ SaveTool::drawFrameInfo() {
} }
void void
SaveTool::drawJointSliders() { Application::drawJointSliders() {
if(!_currentMass || _currentMass->state() != Mass::State::Valid) { if(!_currentMass || _currentMass->state() != GameObjects::Mass::State::Valid) {
return; return;
} }
@ -204,8 +206,8 @@ SaveTool::drawJointSliders() {
} }
void void
SaveTool::drawFrameStyles() { Application::drawFrameStyles() {
if(!_currentMass || _currentMass->state() != Mass::State::Valid) { if(!_currentMass || _currentMass->state() != GameObjects::Mass::State::Valid) {
return; return;
} }
@ -217,7 +219,7 @@ SaveTool::drawFrameStyles() {
ImGui::PushID(i); ImGui::PushID(i);
if(ImGui::BeginCombo("##Style", getStyleName(_currentMass->frameStyles()[i], _currentMass->frameCustomStyles()).data())) { if(ImGui::BeginCombo("##Style", getStyleName(_currentMass->frameStyles()[i], _currentMass->frameCustomStyles()).data())) {
for(const auto& style : style_names) { for(const auto& style : GameData::style_names) {
if(ImGui::Selectable(getStyleName(style.first, _currentMass->frameCustomStyles()).data(), _currentMass->frameStyles()[i] == style.first)) { if(ImGui::Selectable(getStyleName(style.first, _currentMass->frameCustomStyles()).data(), _currentMass->frameStyles()[i] == style.first)) {
_currentMass->frameStyles()[i] = style.first; _currentMass->frameStyles()[i] = style.first;
_stylesDirty = true; _stylesDirty = true;
@ -255,8 +257,8 @@ SaveTool::drawFrameStyles() {
} }
void void
SaveTool::drawEyeColourPicker() { Application::drawEyeColourPicker() {
if(!_currentMass || _currentMass->state() != Mass::State::Valid) { if(!_currentMass || _currentMass->state() != GameObjects::Mass::State::Valid) {
return; return;
} }
@ -289,8 +291,8 @@ SaveTool::drawEyeColourPicker() {
} }
void void
SaveTool::drawCustomFrameStyles() { Application::drawCustomFrameStyles() {
if(!_currentMass || _currentMass->state() != Mass::State::Valid) { if(!_currentMass || _currentMass->state() != GameObjects::Mass::State::Valid) {
return; return;
} }
@ -324,3 +326,5 @@ SaveTool::drawCustomFrameStyles() {
ImGui::EndChild(); ImGui::EndChild();
} }
}

View file

@ -19,11 +19,13 @@
#include "../Maps/StyleNames.h" #include "../Maps/StyleNames.h"
#include "../Maps/WeaponParts.h" #include "../Maps/WeaponParts.h"
#include "SaveTool.h" #include "Application.h"
namespace mbst {
void void
SaveTool::drawWeapons() { Application::drawWeapons() {
if(!_currentMass || _currentMass->state() != Mass::State::Valid) { if(!_currentMass || _currentMass->state() != GameObjects::Mass::State::Valid) {
_currentWeapon = nullptr; _currentWeapon = nullptr;
return; return;
} }
@ -179,37 +181,37 @@ SaveTool::drawWeapons() {
if(drawUnsafeWidget([](){ return ImGui::Button(ICON_FA_SAVE " Save changes to weapon category"); })) { if(drawUnsafeWidget([](){ return ImGui::Button(ICON_FA_SAVE " Save changes to weapon category"); })) {
_modifiedBySaveTool = true; _modifiedBySaveTool = true;
switch(_currentWeapon->type) { switch(_currentWeapon->type) {
case WeaponType::Melee: case GameObjects::Weapon::Type::Melee:
if(!_currentMass->writeMeleeWeapons()) { if(!_currentMass->writeMeleeWeapons()) {
_modifiedBySaveTool = false; _modifiedBySaveTool = false;
_queue.addToast(Toast::Type::Error, _currentMass->lastError()); _queue.addToast(Toast::Type::Error, _currentMass->lastError());
} }
break; break;
case WeaponType::Shield: case GameObjects::Weapon::Type::Shield:
if(!_currentMass->writeShields()) { if(!_currentMass->writeShields()) {
_modifiedBySaveTool = false; _modifiedBySaveTool = false;
_queue.addToast(Toast::Type::Error, _currentMass->lastError()); _queue.addToast(Toast::Type::Error, _currentMass->lastError());
} }
break; break;
case WeaponType::BulletShooter: case GameObjects::Weapon::Type::BulletShooter:
if(!_currentMass->writeBulletShooters()) { if(!_currentMass->writeBulletShooters()) {
_modifiedBySaveTool = false; _modifiedBySaveTool = false;
_queue.addToast(Toast::Type::Error, _currentMass->lastError()); _queue.addToast(Toast::Type::Error, _currentMass->lastError());
} }
break; break;
case WeaponType::EnergyShooter: case GameObjects::Weapon::Type::EnergyShooter:
if(!_currentMass->writeEnergyShooters()) { if(!_currentMass->writeEnergyShooters()) {
_modifiedBySaveTool = false; _modifiedBySaveTool = false;
_queue.addToast(Toast::Type::Error, _currentMass->lastError()); _queue.addToast(Toast::Type::Error, _currentMass->lastError());
} }
break; break;
case WeaponType::BulletLauncher: case GameObjects::Weapon::Type::BulletLauncher:
if(!_currentMass->writeBulletLaunchers()) { if(!_currentMass->writeBulletLaunchers()) {
_modifiedBySaveTool = false; _modifiedBySaveTool = false;
_queue.addToast(Toast::Type::Error, _currentMass->lastError()); _queue.addToast(Toast::Type::Error, _currentMass->lastError());
} }
break; break;
case WeaponType::EnergyLauncher: case GameObjects::Weapon::Type::EnergyLauncher:
if(!_currentMass->writeEnergyLaunchers()) { if(!_currentMass->writeEnergyLaunchers()) {
_modifiedBySaveTool = false; _modifiedBySaveTool = false;
_queue.addToast(Toast::Type::Error, _currentMass->lastError()); _queue.addToast(Toast::Type::Error, _currentMass->lastError());
@ -225,22 +227,22 @@ SaveTool::drawWeapons() {
if(ImGui::Button(ICON_FA_UNDO_ALT " Reset weapon category")) { if(ImGui::Button(ICON_FA_UNDO_ALT " Reset weapon category")) {
switch(_currentWeapon->type) { switch(_currentWeapon->type) {
case WeaponType::Melee: case GameObjects::Weapon::Type::Melee:
_currentMass->getMeleeWeapons(); _currentMass->getMeleeWeapons();
break; break;
case WeaponType::Shield: case GameObjects::Weapon::Type::Shield:
_currentMass->getShields(); _currentMass->getShields();
break; break;
case WeaponType::BulletShooter: case GameObjects::Weapon::Type::BulletShooter:
_currentMass->getBulletShooters(); _currentMass->getBulletShooters();
break; break;
case WeaponType::EnergyShooter: case GameObjects::Weapon::Type::EnergyShooter:
_currentMass->getEnergyShooters(); _currentMass->getEnergyShooters();
break; break;
case WeaponType::BulletLauncher: case GameObjects::Weapon::Type::BulletLauncher:
_currentMass->getBulletLaunchers(); _currentMass->getBulletLaunchers();
break; break;
case WeaponType::EnergyLauncher: case GameObjects::Weapon::Type::EnergyLauncher:
_currentMass->getEnergyLaunchers(); _currentMass->getEnergyLaunchers();
break; break;
default: default:
@ -252,7 +254,7 @@ SaveTool::drawWeapons() {
} }
void void
SaveTool::drawWeaponCategory(Containers::StringView name, Containers::ArrayView<Weapon> weapons_view, bool& dirty, Application::drawWeaponCategory(Containers::StringView name, Containers::ArrayView<GameObjects::Weapon> weapons_view, bool& dirty,
Containers::StringView payload_type, Containers::StringView payload_tooltip) Containers::StringView payload_type, Containers::StringView payload_tooltip)
{ {
ImGui::TableNextRow(ImGuiTableRowFlags_Headers); ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
@ -316,8 +318,8 @@ SaveTool::drawWeaponCategory(Containers::StringView name, Containers::ArrayView<
} }
void void
SaveTool::drawWeaponEditor(Weapon& weapon) { Application::drawWeaponEditor(GameObjects::Weapon& weapon) {
if(!_currentMass || _currentMass->state() != Mass::State::Valid || !_currentWeapon) { if(!_currentMass || _currentMass->state() != GameObjects::Mass::State::Valid || !_currentWeapon) {
return; return;
} }
@ -346,11 +348,11 @@ SaveTool::drawWeaponEditor(Weapon& weapon) {
ImGui::BeginGroup(); ImGui::BeginGroup();
drawAlignedText("Equipped:"); drawAlignedText("Equipped:");
if(weapon.type != WeaponType::Shield) { if(weapon.type != GameObjects::Weapon::Type::Shield) {
drawAlignedText("Damage type:"); drawAlignedText("Damage type:");
} }
if(weapon.type == WeaponType::Melee) { if(weapon.type == GameObjects::Weapon::Type::Melee) {
drawAlignedText("Dual-wield:"); drawAlignedText("Dual-wield:");
drawAlignedText("Custom effect mode:"); drawAlignedText("Custom effect mode:");
@ -364,48 +366,48 @@ SaveTool::drawWeaponEditor(Weapon& weapon) {
ImGui::BeginGroup(); ImGui::BeginGroup();
ImGui::Checkbox("##EquippedCheckbox", &weapon.attached); ImGui::Checkbox("##EquippedCheckbox", &weapon.attached);
if(weapon.type != WeaponType::Shield) { if(weapon.type != GameObjects::Weapon::Type::Shield) {
if(weapon.type == WeaponType::Melee && if(weapon.type == GameObjects::Weapon::Type::Melee &&
ImGui::RadioButton("Physical##NoElement", weapon.damageType == DamageType::Physical)) ImGui::RadioButton("Physical##NoElement", weapon.damageType == GameObjects::Weapon::DamageType::Physical))
{ {
weapon.damageType = DamageType::Physical; weapon.damageType = GameObjects::Weapon::DamageType::Physical;
} }
else if((weapon.type == WeaponType::BulletShooter || weapon.type == WeaponType::BulletLauncher) && else if((weapon.type == GameObjects::Weapon::Type::BulletShooter || weapon.type == GameObjects::Weapon::Type::BulletLauncher) &&
ImGui::RadioButton("Piercing##NoElement", weapon.damageType == DamageType::Piercing)) ImGui::RadioButton("Piercing##NoElement", weapon.damageType == GameObjects::Weapon::DamageType::Piercing))
{ {
weapon.damageType = DamageType::Piercing; weapon.damageType = GameObjects::Weapon::DamageType::Piercing;
} }
else if((weapon.type == WeaponType::EnergyShooter || weapon.type == WeaponType::EnergyLauncher) && else if((weapon.type == GameObjects::Weapon::Type::EnergyShooter || weapon.type == GameObjects::Weapon::Type::EnergyLauncher) &&
ImGui::RadioButton("Plasma##NoElement", weapon.damageType == DamageType::Plasma)) ImGui::RadioButton("Plasma##NoElement", weapon.damageType == GameObjects::Weapon::DamageType::Plasma))
{ {
weapon.damageType = DamageType::Plasma; weapon.damageType = GameObjects::Weapon::DamageType::Plasma;
} }
ImGui::SameLine(); ImGui::SameLine();
if(ImGui::RadioButton("Heat##Heat", weapon.damageType == DamageType::Heat)) { if(ImGui::RadioButton("Heat##Heat", weapon.damageType == GameObjects::Weapon::DamageType::Heat)) {
weapon.damageType = DamageType::Heat; weapon.damageType = GameObjects::Weapon::DamageType::Heat;
} }
ImGui::SameLine(); ImGui::SameLine();
if(ImGui::RadioButton("Freeze##Freeze", weapon.damageType == DamageType::Freeze)) { if(ImGui::RadioButton("Freeze##Freeze", weapon.damageType == GameObjects::Weapon::DamageType::Freeze)) {
weapon.damageType = DamageType::Freeze; weapon.damageType = GameObjects::Weapon::DamageType::Freeze;
} }
ImGui::SameLine(); ImGui::SameLine();
if(ImGui::RadioButton("Shock##Shock", weapon.damageType == DamageType::Shock)) { if(ImGui::RadioButton("Shock##Shock", weapon.damageType == GameObjects::Weapon::DamageType::Shock)) {
weapon.damageType = DamageType::Shock; weapon.damageType = GameObjects::Weapon::DamageType::Shock;
} }
} }
if(weapon.type == WeaponType::Melee) { if(weapon.type == GameObjects::Weapon::Type::Melee) {
ImGui::Checkbox("##DualWield", &weapon.dualWield); ImGui::Checkbox("##DualWield", &weapon.dualWield);
if(ImGui::RadioButton("Default##Default", weapon.effectColourMode == EffectColourMode::Default)) { if(ImGui::RadioButton("Default##Default", weapon.effectColourMode == GameObjects::Weapon::EffectColourMode::Default)) {
weapon.effectColourMode = EffectColourMode::Default; weapon.effectColourMode = GameObjects::Weapon::EffectColourMode::Default;
} }
ImGui::SameLine(); ImGui::SameLine();
if(ImGui::RadioButton("Custom##Custom", weapon.effectColourMode == EffectColourMode::Custom)) { if(ImGui::RadioButton("Custom##Custom", weapon.effectColourMode == GameObjects::Weapon::EffectColourMode::Custom)) {
weapon.effectColourMode = EffectColourMode::Custom; weapon.effectColourMode = GameObjects::Weapon::EffectColourMode::Custom;
} }
bool custom_effect = (weapon.effectColourMode == EffectColourMode::Custom); bool custom_effect = (weapon.effectColourMode == GameObjects::Weapon::EffectColourMode::Custom);
if(!custom_effect) { if(!custom_effect) {
ImGui::BeginDisabled(); ImGui::BeginDisabled();
} }
@ -436,18 +438,18 @@ SaveTool::drawWeaponEditor(Weapon& weapon) {
const auto* map = [this, &weapon]()-> const std::map<std::int32_t, Containers::StringView>* { const auto* map = [this, &weapon]()-> const std::map<std::int32_t, Containers::StringView>* {
switch(weapon.type) { switch(weapon.type) {
case WeaponType::Melee: case GameObjects::Weapon::Type::Melee:
return _selectedWeaponPart == 0 ? &melee_grips : &melee_assaulters; return _selectedWeaponPart == 0 ? &GameData::melee_grips : &GameData::melee_assaulters;
case WeaponType::Shield: case GameObjects::Weapon::Type::Shield:
return _selectedWeaponPart == 0 ? &shield_handles : &shield_shells; return _selectedWeaponPart == 0 ? &GameData::shield_handles : &GameData::shield_shells;
case WeaponType::BulletShooter: case GameObjects::Weapon::Type::BulletShooter:
return _selectedWeaponPart == 0 ? &bshooter_triggers : &bshooter_barrels; return _selectedWeaponPart == 0 ? &GameData::bshooter_triggers : &GameData::bshooter_barrels;
case WeaponType::EnergyShooter: case GameObjects::Weapon::Type::EnergyShooter:
return _selectedWeaponPart == 0 ? &eshooter_triggers : &eshooter_busters; return _selectedWeaponPart == 0 ? &GameData::eshooter_triggers : &GameData::eshooter_busters;
case WeaponType::BulletLauncher: case GameObjects::Weapon::Type::BulletLauncher:
return _selectedWeaponPart == 0 ? &blauncher_pods : &blauncher_projectiles; return _selectedWeaponPart == 0 ? &GameData::blauncher_pods : &GameData::blauncher_projectiles;
case WeaponType::EnergyLauncher: case GameObjects::Weapon::Type::EnergyLauncher:
return _selectedWeaponPart == 0 ? &elauncher_generators : &elauncher_pods; return _selectedWeaponPart == 0 ? &GameData::elauncher_generators : &GameData::elauncher_pods;
} }
return nullptr; return nullptr;
@ -489,14 +491,14 @@ SaveTool::drawWeaponEditor(Weapon& weapon) {
} }
} }
if(weapon.type == WeaponType::Shield || if(weapon.type == GameObjects::Weapon::Type::Shield ||
(weapon.type == WeaponType::BulletLauncher && _selectedWeaponPart != 0)) (weapon.type == GameObjects::Weapon::Type::BulletLauncher && _selectedWeaponPart != 0))
{ {
ImGui::SameLine(); ImGui::SameLine();
if(ImGui::SmallButton("Unequip")) { if(ImGui::SmallButton("Unequip")) {
part.id = -1; part.id = -1;
} }
if(weapon.type == WeaponType::Shield && _selectedWeaponPart == 0) { if(weapon.type == GameObjects::Weapon::Type::Shield && _selectedWeaponPart == 0) {
drawTooltip("This will make the whole shield and its accessories invisible."); drawTooltip("This will make the whole shield and its accessories invisible.");
} }
else { else {
@ -515,7 +517,7 @@ SaveTool::drawWeaponEditor(Weapon& weapon) {
ImGui::PushID(i); ImGui::PushID(i);
if(ImGui::BeginCombo("##Style", getStyleName(part.styles[i], weapon.customStyles).data())) { if(ImGui::BeginCombo("##Style", getStyleName(part.styles[i], weapon.customStyles).data())) {
for(const auto& style: style_names) { for(const auto& style: GameData::style_names) {
if(ImGui::Selectable(getStyleName(style.first, weapon.customStyles).data(), if(ImGui::Selectable(getStyleName(style.first, weapon.customStyles).data(),
part.styles[i] == style.first)) { part.styles[i] == style.first)) {
part.styles[i] = style.first; part.styles[i] = style.first;
@ -562,3 +564,5 @@ SaveTool::drawWeaponEditor(Weapon& weapon) {
ImGui::EndChild(); ImGui::EndChild();
} }
} }
}

View file

@ -20,12 +20,14 @@
#include "../FontAwesome/IconsFontAwesome5.h" #include "../FontAwesome/IconsFontAwesome5.h"
#include "SaveTool.h" #include "Application.h"
extern const ImVec2 center_pivot; extern const ImVec2 center_pivot;
namespace mbst {
void void
SaveTool::drawProfileManager() { Application::drawProfileManager() {
static std::size_t profile_index = 0; static std::size_t profile_index = 0;
ImGui::SetNextWindowPos(ImVec2{Vector2{windowSize() / 2.0f} / dpiScaling()}, ImGuiCond_Always, center_pivot); ImGui::SetNextWindowPos(ImVec2{Vector2{windowSize() / 2.0f} / dpiScaling()}, ImGuiCond_Always, center_pivot);
@ -81,7 +83,7 @@ SaveTool::drawProfileManager() {
ImGui::TextUnformatted("Actions"); ImGui::TextUnformatted("Actions");
for(std::size_t i = 0; i < _profileManager->profiles().size(); ++i) { for(std::size_t i = 0; i < _profileManager->profiles().size(); ++i) {
Profile& profile = _profileManager->profiles()[i]; GameObjects::Profile& profile = _profileManager->profiles()[i];
ImGui::TableNextRow(); ImGui::TableNextRow();
@ -127,7 +129,7 @@ SaveTool::drawProfileManager() {
} }
ImGuiID ImGuiID
SaveTool::drawBackupListPopup() { Application::drawBackupListPopup() {
ImGui::SetNextWindowPos(ImVec2{Vector2{windowSize() / 2.0f} / dpiScaling()}, ImGuiCond_Always, center_pivot); ImGui::SetNextWindowPos(ImVec2{Vector2{windowSize() / 2.0f} / dpiScaling()}, ImGuiCond_Always, center_pivot);
if(!ImGui::BeginPopupModal("Backups##BackupsModal", nullptr, if(!ImGui::BeginPopupModal("Backups##BackupsModal", nullptr,
ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoMove)) ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoMove))
@ -283,7 +285,7 @@ SaveTool::drawBackupListPopup() {
backup.timestamp.second); backup.timestamp.second);
ImGui::TableSetColumnIndex(2); ImGui::TableSetColumnIndex(2);
ImGui::TextUnformatted(backup.type == ProfileType::Demo ? "Demo" : "Full"); ImGui::TextUnformatted(backup.demo ? "Demo" : "Full");
ImGui::TableSetColumnIndex(3); ImGui::TableSetColumnIndex(3);
ImGui::PushID(int(i)); ImGui::PushID(int(i));
@ -327,7 +329,7 @@ SaveTool::drawBackupListPopup() {
} }
ImGuiID ImGuiID
SaveTool::drawBackupProfilePopup(std::size_t profile_index) { Application::drawBackupProfilePopup(std::size_t profile_index) {
if(!ImGui::BeginPopupModal("Include builds ?##IncludeBuildsDialog", nullptr, if(!ImGui::BeginPopupModal("Include builds ?##IncludeBuildsDialog", nullptr,
ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoMove)) ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoMove))
{ {
@ -372,7 +374,7 @@ SaveTool::drawBackupProfilePopup(std::size_t profile_index) {
} }
ImGuiID ImGuiID
SaveTool::drawDeleteProfilePopup(std::size_t profile_index) { Application::drawDeleteProfilePopup(std::size_t profile_index) {
if(!ImGui::BeginPopupModal("Confirmation##DeleteProfileConfirmation", nullptr, if(!ImGui::BeginPopupModal("Confirmation##DeleteProfileConfirmation", nullptr,
ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoMove)) ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoMove))
{ {
@ -417,3 +419,5 @@ SaveTool::drawDeleteProfilePopup(std::size_t profile_index) {
return 0; return 0;
} }
}

View file

@ -20,10 +20,12 @@
#include "../Logger/Logger.h" #include "../Logger/Logger.h"
#include "SaveTool.h" #include "Application.h"
namespace mbst {
void void
SaveTool::updateCheckEvent(SDL_Event& event) { Application::updateCheckEvent(SDL_Event& event) {
_updateThread.join(); _updateThread.join();
switch(static_cast<UpdateChecker::Result>(event.user.code)) { switch(static_cast<UpdateChecker::Result>(event.user.code)) {
@ -72,7 +74,7 @@ SaveTool::updateCheckEvent(SDL_Event& event) {
} }
void void
SaveTool::checkForUpdates() { Application::checkForUpdates() {
SDL_Event event; SDL_Event event;
SDL_zero(event); SDL_zero(event);
event.type = _updateEventId; event.type = _updateEventId;
@ -89,3 +91,5 @@ SaveTool::checkForUpdates() {
SDL_PushEvent(&event); SDL_PushEvent(&event);
} }
}

View file

@ -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 "SaveTool.h"
#include <Corrade/version.h> #include <Corrade/version.h>
#include <Magnum/version.h> #include <Magnum/version.h>
@ -29,10 +27,14 @@
#include "../FontAwesome/IconsFontAwesome5.h" #include "../FontAwesome/IconsFontAwesome5.h"
#include "../FontAwesome/IconsFontAwesome5Brands.h" #include "../FontAwesome/IconsFontAwesome5Brands.h"
#include "Application.h"
extern const ImVec2 center_pivot; extern const ImVec2 center_pivot;
namespace mbst {
void void
SaveTool::drawAbout() { Application::drawAbout() {
ImGui::SetNextWindowPos(ImVec2{Vector2{windowSize() / 2.0f}}, ImGuiCond_Always, center_pivot); ImGui::SetNextWindowPos(ImVec2{Vector2{windowSize() / 2.0f}}, ImGuiCond_Always, center_pivot);
ImGui::SetNextWindowSize({float(windowSize().x()) * 0.8f, float(windowSize().y()) * 0.75f}, ImGuiCond_Always); ImGui::SetNextWindowSize({float(windowSize().x()) * 0.8f, float(windowSize().y()) * 0.75f}, ImGuiCond_Always);
@ -60,7 +62,7 @@ SaveTool::drawAbout() {
ImGui::TextWrapped("This application, made for the M.A.S.S. Builder community by Guillaume Jacquemin (aka William JCM), " ImGui::TextWrapped("This application, made for the M.A.S.S. Builder community by Guillaume Jacquemin (aka William JCM), "
"is a rewrite of the wxWidgets-powered M.A.S.S. Builder Save Tool (formerly known as wxMASSManager)."); "is a rewrite of the wxWidgets-powered M.A.S.S. Builder Save Tool (formerly known as wxMASSManager).");
auto website = "https://williamjcm.ovh/coding/mbst"; auto website = "https://williamjcm.ovh/mbst";
drawAlignedText(ICON_FA_GLOBE " %s", website); drawAlignedText(ICON_FA_GLOBE " %s", website);
ImGui::SameLine(); ImGui::SameLine();
if(ImGui::Button("Copy to clipboard")) { if(ImGui::Button("Copy to clipboard")) {
@ -267,3 +269,5 @@ SaveTool::drawAbout() {
ImGui::EndPopup(); ImGui::EndPopup();
} }
}

View file

@ -20,10 +20,12 @@
#include "../FontAwesome/IconsFontAwesome5.h" #include "../FontAwesome/IconsFontAwesome5.h"
#include "../FontAwesome/IconsFontAwesome5Brands.h" #include "../FontAwesome/IconsFontAwesome5Brands.h"
#include "SaveTool.h" #include "Application.h"
namespace mbst {
void void
SaveTool::drawMainMenu() { Application::drawMainMenu() {
if(!ImGui::BeginMainMenuBar()) { if(!ImGui::BeginMainMenuBar()) {
return; return;
} }
@ -239,3 +241,5 @@ SaveTool::drawMainMenu() {
ImGui::EndMainMenuBar(); ImGui::EndMainMenuBar();
} }
}

View file

@ -37,7 +37,7 @@ set_directory_properties(PROPERTIES CORRADE_USE_PEDANTIC_FLAGS ON)
corrade_add_resource(Assets assets.conf) corrade_add_resource(Assets assets.conf)
add_subdirectory(Logger EXCLUDE_FROM_ALL) add_subdirectory(Logger EXCLUDE_FROM_ALL)
add_subdirectory(UESaveFile EXCLUDE_FROM_ALL) add_subdirectory(Gvas EXCLUDE_FROM_ALL)
if(CORRADE_TARGET_WINDOWS) if(CORRADE_TARGET_WINDOWS)
set(SAVETOOL_RC_FILE resource.rc) set(SAVETOOL_RC_FILE resource.rc)
@ -45,19 +45,19 @@ endif()
add_executable(MassBuilderSaveTool add_executable(MassBuilderSaveTool
main.cpp main.cpp
SaveTool/SaveTool.h Application/Application.h
SaveTool/SaveTool.cpp Application/Application.cpp
SaveTool/SaveTool_drawAbout.cpp Application/Application_drawAbout.cpp
SaveTool/SaveTool_drawMainMenu.cpp Application/Application_drawMainMenu.cpp
SaveTool/SaveTool_FileWatcher.cpp Application/Application_FileWatcher.cpp
SaveTool/SaveTool_Initialisation.cpp Application/Application_Initialisation.cpp
SaveTool/SaveTool_MainManager.cpp Application/Application_MainManager.cpp
SaveTool/SaveTool_MassViewer.cpp Application/Application_MassViewer.cpp
SaveTool/SaveTool_MassViewer_Frame.cpp Application/Application_MassViewer_Frame.cpp
SaveTool/SaveTool_MassViewer_Armour.cpp Application/Application_MassViewer_Armour.cpp
SaveTool/SaveTool_MassViewer_Weapons.cpp Application/Application_MassViewer_Weapons.cpp
SaveTool/SaveTool_ProfileManager.cpp Application/Application_ProfileManager.cpp
SaveTool/SaveTool_UpdateChecker.cpp Application/Application_UpdateChecker.cpp
Configuration/Configuration.h Configuration/Configuration.h
Configuration/Configuration.cpp Configuration/Configuration.cpp
ProfileManager/ProfileManager.h ProfileManager/ProfileManager.h
@ -102,7 +102,9 @@ add_executable(MassBuilderSaveTool
UpdateChecker/UpdateChecker.h UpdateChecker/UpdateChecker.h
UpdateChecker/UpdateChecker.cpp UpdateChecker/UpdateChecker.cpp
Utilities/Crc32.h Utilities/Crc32.h
Utilities/Crc32.cpp
Version/Version.h Version/Version.h
Version/Version.cpp
FontAwesome/IconsFontAwesome5.h FontAwesome/IconsFontAwesome5.h
FontAwesome/IconsFontAwesome5Brands.h FontAwesome/IconsFontAwesome5Brands.h
${SAVETOOL_RC_FILE} ${SAVETOOL_RC_FILE}
@ -145,7 +147,7 @@ target_link_libraries(MassBuilderSaveTool PRIVATE
Magnum::Sdl2Application Magnum::Sdl2Application
MagnumIntegration::ImGui MagnumIntegration::ImGui
Logger Logger
UESaveFile Gvas
CURL::libcurl_static CURL::libcurl_static
) )

View file

@ -20,6 +20,8 @@
#include "Configuration.h" #include "Configuration.h"
namespace mbst {
Configuration::Configuration() { Configuration::Configuration() {
Containers::String exe_path = Utility::Path::split(*Utility::Path::executableLocation()).first(); Containers::String exe_path = Utility::Path::split(*Utility::Path::executableLocation()).first();
_conf = Utility::Configuration{Utility::Path::join(exe_path, "MassBuilderSaveTool.ini")}; _conf = Utility::Configuration{Utility::Path::join(exe_path, "MassBuilderSaveTool.ini")};
@ -174,3 +176,5 @@ Configuration&
conf() { conf() {
return Configuration::instance(); return Configuration::instance();
} }
}

View file

@ -20,18 +20,20 @@
using namespace Corrade; using namespace Corrade;
namespace mbst {
class Configuration { class Configuration {
public: public:
static Configuration& instance(); static auto instance() -> Configuration&;
~Configuration(); ~Configuration();
void save(); void save();
int swapInterval() const; auto swapInterval() const -> int;
void setSwapInterval(int interval); void setSwapInterval(int interval);
float fpsCap() const; auto fpsCap() const -> float;
void setFpsCap(float cap); void setFpsCap(float cap);
bool cheatMode() const; bool cheatMode() const;
@ -65,3 +67,5 @@ class Configuration {
}; };
Configuration& conf(); Configuration& conf();
}

View file

@ -23,6 +23,8 @@
#include "BinaryReader.h" #include "BinaryReader.h"
namespace Gvas {
BinaryReader::BinaryReader(Containers::StringView filename) { BinaryReader::BinaryReader(Containers::StringView filename) {
_file = std::fopen(filename.data(), "rb"); _file = std::fopen(filename.data(), "rb");
@ -144,3 +146,5 @@ BinaryReader::peekChar() {
std::ungetc(c, _file); std::ungetc(c, _file);
return c; return c;
} }
}

View file

@ -25,6 +25,8 @@
using namespace Corrade; using namespace Corrade;
namespace Gvas {
class BinaryReader { class BinaryReader {
public: public:
explicit BinaryReader(Containers::StringView filename); explicit BinaryReader(Containers::StringView filename);
@ -32,7 +34,7 @@ class BinaryReader {
bool open(); bool open();
bool eof(); bool eof();
std::int64_t position(); auto position() -> std::int64_t;
bool seek(std::int64_t position); bool seek(std::int64_t position);
@ -63,8 +65,10 @@ class BinaryReader {
bool readUEString(Containers::String& str); bool readUEString(Containers::String& str);
std::int32_t peekChar(); auto peekChar() -> std::int32_t;
private: private:
std::FILE* _file = nullptr; std::FILE* _file = nullptr;
}; };
}

View file

@ -22,6 +22,8 @@
using namespace Containers::Literals; using namespace Containers::Literals;
namespace Gvas {
BinaryWriter::BinaryWriter(Containers::StringView filename) { BinaryWriter::BinaryWriter(Containers::StringView filename) {
_file = std::fopen(filename.data(), "wb"); _file = std::fopen(filename.data(), "wb");
if(!_file) { if(!_file) {
@ -157,3 +159,5 @@ BinaryWriter::writeUEStringToArray(Containers::StringView value) {
writeDataToArray(Containers::ArrayView<const char>{value}) + writeDataToArray(Containers::ArrayView<const char>{value}) +
writeValueToArray<char>('\0'); writeValueToArray<char>('\0');
} }
}

View file

@ -26,6 +26,8 @@
using namespace Corrade; using namespace Corrade;
namespace Gvas {
class BinaryWriter { class BinaryWriter {
public: public:
explicit BinaryWriter(Containers::StringView filename); explicit BinaryWriter(Containers::StringView filename);
@ -41,10 +43,10 @@ class BinaryWriter {
void closeFile(); void closeFile();
std::int64_t position(); auto position() -> std::int64_t;
Containers::ArrayView<const char> array() const; auto array() const -> Containers::ArrayView<const char>;
std::size_t arrayPosition() const; auto arrayPosition() const -> std::size_t;
bool flushToFile(); bool flushToFile();
bool writeChar(char value); bool writeChar(char value);
@ -72,12 +74,12 @@ class BinaryWriter {
bool writeUEString(Containers::StringView str); bool writeUEString(Containers::StringView str);
template<typename T, typename U = std::conditional_t<std::is_trivially_copyable<T>::value, T, T&>> template<typename T, typename U = std::conditional_t<std::is_trivially_copyable<T>::value, T, T&>>
std::size_t writeValueToArray(U value) { auto writeValueToArray(U value) -> std::size_t {
Containers::ArrayView<T> view{&value, 1}; Containers::ArrayView<T> view{&value, 1};
return writeDataToArray(view); return writeDataToArray(view);
} }
std::size_t writeUEStringToArray(Containers::StringView value); auto writeUEStringToArray(Containers::StringView value) -> std::size_t;
template<typename T> template<typename T>
void writeValueToArrayAt(T& value, std::size_t position) { void writeValueToArrayAt(T& value, std::size_t position) {
@ -86,7 +88,7 @@ class BinaryWriter {
} }
template<typename T> template<typename T>
std::size_t writeDataToArray(Containers::ArrayView<T> view) { auto writeDataToArray(Containers::ArrayView<T> view) -> std::size_t {
arrayAppend(_data, Containers::arrayCast<const char>(view)); arrayAppend(_data, Containers::arrayCast<const char>(view));
_index += sizeof(T) * view.size(); _index += sizeof(T) * view.size();
return sizeof(T) * view.size(); return sizeof(T) * view.size();
@ -106,3 +108,5 @@ class BinaryWriter {
Containers::Array<char> _data; Containers::Array<char> _data;
std::size_t _index = 0; std::size_t _index = 0;
}; };
}

102
src/Gvas/CMakeLists.txt Normal file
View file

@ -0,0 +1,102 @@
# MassBuilderSaveTool
# Copyright (C) 2021-2023 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/>.
add_library(Gvas STATIC EXCLUDE_FROM_ALL
Serialisers/Serialisers.h
Serialisers/AbstractUnrealCollectionProperty.h
Serialisers/AbstractUnrealProperty.h
Serialisers/AbstractUnrealStruct.h
Serialisers/ArrayProperty.h
Serialisers/ArrayProperty.cpp
Serialisers/BoolProperty.h
Serialisers/BoolProperty.cpp
Serialisers/ByteProperty.h
Serialisers/ByteProperty.cpp
Serialisers/ColourProperty.h
Serialisers/ColourProperty.cpp
Serialisers/DateTimeProperty.h
Serialisers/DateTimeProperty.cpp
Serialisers/EnumProperty.h
Serialisers/EnumProperty.cpp
Serialisers/FloatProperty.h
Serialisers/FloatProperty.cpp
Serialisers/GuidProperty.h
Serialisers/GuidProperty.cpp
Serialisers/IntProperty.h
Serialisers/IntProperty.cpp
Serialisers/MapProperty.h
Serialisers/MapProperty.cpp
Serialisers/ResourceProperty.h
Serialisers/ResourceProperty.cpp
Serialisers/RotatorProperty.h
Serialisers/RotatorProperty.cpp
Serialisers/StringProperty.h
Serialisers/StringProperty.cpp
Serialisers/SetProperty.h
Serialisers/SetProperty.cpp
Serialisers/Struct.h
Serialisers/Struct.cpp
Serialisers/TextProperty.h
Serialisers/TextProperty.cpp
Serialisers/UnrealProperty.h
Serialisers/VectorProperty.h
Serialisers/VectorProperty.cpp
Serialisers/Vector2DProperty.h
Serialisers/Vector2DProperty.cpp
Types/Types.h
Types/ArrayProperty.h
Types/BoolProperty.h
Types/ByteProperty.h
Types/ColourStructProperty.h
Types/DateTimeStructProperty.h
Types/EnumProperty.h
Types/FloatProperty.h
Types/GenericStructProperty.h
Types/GuidStructProperty.h
Types/IntProperty.h
Types/MapProperty.h
Types/NoneProperty.h
Types/RotatorStructProperty.h
Types/SetProperty.h
Types/StringProperty.h
Types/StructProperty.h
Types/ResourceItemValue.h
Types/TextProperty.h
Types/UnrealProperty.h
Types/UnrealPropertyBase.h
Types/Vector2DStructProperty.h
Types/VectorStructProperty.h
Gvas.h
Debug.h
Debug.cpp
File.h
File.cpp
BinaryReader.h
BinaryReader.cpp
BinaryWriter.h
BinaryWriter.cpp
PropertySerialiser.h
PropertySerialiser.cpp
)
target_link_libraries(Gvas PRIVATE
Corrade::Containers
Corrade::Utility
Magnum::Magnum
Logger
)

View file

@ -23,19 +23,19 @@
#include "Debug.h" #include "Debug.h"
Utility::Debug& Utility::Debug&
operator<<(Utility::Debug& debug, const ArrayProperty* prop) { operator<<(Utility::Debug& debug, const Gvas::Types::ArrayProperty* prop) {
return debug << (*prop->name) << Utility::Debug::nospace << ":" << return debug << (*prop->name) << Utility::Debug::nospace << ":" <<
prop->propertyType << "of" << prop->items.size() << prop->itemType; prop->propertyType << "of" << prop->items.size() << prop->itemType;
} }
Utility::Debug& Utility::Debug&
operator<<(Utility::Debug& debug, const SetProperty* prop) { operator<<(Utility::Debug& debug, const Gvas::Types::SetProperty* prop) {
return debug << (*prop->name) << Utility::Debug::nospace << ":" << return debug << (*prop->name) << Utility::Debug::nospace << ":" <<
prop->propertyType << "of" << prop->items.size() << prop->itemType; prop->propertyType << "of" << prop->items.size() << prop->itemType;
} }
Utility::Debug& Utility::Debug&
operator<<(Utility::Debug& debug, const GenericStructProperty* prop) { operator<<(Utility::Debug& debug, const Gvas::Types::GenericStructProperty* prop) {
debug << (*prop->name) << Utility::Debug::nospace << ":" << debug << (*prop->name) << Utility::Debug::nospace << ":" <<
prop->structType << "(" << Utility::Debug::nospace << prop->propertyType << Utility::Debug::nospace << prop->structType << "(" << Utility::Debug::nospace << prop->propertyType << Utility::Debug::nospace <<
") Contents:"; ") Contents:";
@ -46,8 +46,8 @@ operator<<(Utility::Debug& debug, const GenericStructProperty* prop) {
} }
Utility::Debug& Utility::Debug&
operator<<(Utility::Debug& debug, const StructProperty* prop) { operator<<(Utility::Debug& debug, const Gvas::Types::StructProperty* prop) {
auto cast = dynamic_cast<const GenericStructProperty*>(prop); auto cast = dynamic_cast<const Gvas::Types::GenericStructProperty*>(prop);
if(cast) { if(cast) {
return debug << cast; return debug << cast;
} }
@ -57,21 +57,21 @@ operator<<(Utility::Debug& debug, const StructProperty* prop) {
} }
Utility::Debug& Utility::Debug&
operator<<(Utility::Debug& debug, const UnrealPropertyBase* prop) { operator<<(Utility::Debug& debug, const Gvas::Types::UnrealPropertyBase* prop) {
if(prop->propertyType == "ArrayProperty") { if(prop->propertyType == "ArrayProperty") {
auto array_prop = dynamic_cast<const ArrayProperty*>(prop); auto array_prop = dynamic_cast<const Gvas::Types::ArrayProperty*>(prop);
if(array_prop) { if(array_prop) {
return debug << array_prop; return debug << array_prop;
} }
} }
else if(prop->propertyType == "SetProperty") { else if(prop->propertyType == "SetProperty") {
auto set_prop = dynamic_cast<const SetProperty*>(prop); auto set_prop = dynamic_cast<const Gvas::Types::SetProperty*>(prop);
if(set_prop) { if(set_prop) {
return debug << set_prop; return debug << set_prop;
} }
} }
else if(prop->propertyType == "StructProperty") { else if(prop->propertyType == "StructProperty") {
auto struct_prop = dynamic_cast<const StructProperty*>(prop); auto struct_prop = dynamic_cast<const Gvas::Types::StructProperty*>(prop);
if(struct_prop) { if(struct_prop) {
return debug << struct_prop; return debug << struct_prop;
} }

29
src/Gvas/Debug.h Normal file
View file

@ -0,0 +1,29 @@
#pragma once
// MassBuilderSaveTool
// Copyright (C) 2021-2023 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 <Corrade/Utility/Debug.h>
#include "Types/Types.h"
using namespace Corrade;
Utility::Debug& operator<<(Utility::Debug& debug, const Gvas::Types::ArrayProperty* prop);
Utility::Debug& operator<<(Utility::Debug& debug, const Gvas::Types::SetProperty* prop);
Utility::Debug& operator<<(Utility::Debug& debug, const Gvas::Types::GenericStructProperty* prop);
Utility::Debug& operator<<(Utility::Debug& debug, const Gvas::Types::StructProperty* prop);
Utility::Debug& operator<<(Utility::Debug& debug, const Gvas::Types::UnrealPropertyBase* prop);

View file

@ -17,15 +17,18 @@
#include <Corrade/Containers/Optional.h> #include <Corrade/Containers/Optional.h>
#include <Corrade/Utility/Path.h> #include <Corrade/Utility/Path.h>
#include "BinaryReader.h"
#include "BinaryWriter.h"
#include "../Logger/Logger.h" #include "../Logger/Logger.h"
#include "UESaveFile.h" #include "BinaryReader.h"
#include "BinaryWriter.h"
#include "File.h"
using namespace Containers::Literals; using namespace Containers::Literals;
UESaveFile::UESaveFile(Containers::String filepath): namespace Gvas {
File::File(Containers::String filepath):
_propSerialiser{PropertySerialiser::instance()} _propSerialiser{PropertySerialiser::instance()}
{ {
_filepath = std::move(filepath); _filepath = std::move(filepath);
@ -34,46 +37,46 @@ UESaveFile::UESaveFile(Containers::String filepath):
} }
bool bool
UESaveFile::valid() const { File::valid() const {
return _valid; return _valid;
} }
Containers::StringView Containers::StringView
UESaveFile::lastError() const { File::lastError() const {
return _lastError; return _lastError;
} }
bool bool
UESaveFile::reloadData() { File::reloadData() {
if(_noReloadAfterSave) { if(_noReloadAfterSave) {
_noReloadAfterSave = false; _noReloadAfterSave = false;
return valid(); return valid();
} }
_properties = Containers::Array<UnrealPropertyBase::ptr>{}; _properties = Containers::Array<Types::UnrealPropertyBase::ptr>{};
loadData(); loadData();
return valid(); return valid();
} }
Containers::StringView Containers::StringView
UESaveFile::saveType() { File::saveType() {
return _saveType; return _saveType;
} }
void void
UESaveFile::appendProperty(UnrealPropertyBase::ptr prop) { File::appendProperty(Types::UnrealPropertyBase::ptr prop) {
auto none_prop = std::move(_properties.back()); auto none_prop = std::move(_properties.back());
_properties.back() = std::move(prop); _properties.back() = std::move(prop);
arrayAppend(_properties, std::move(none_prop)); arrayAppend(_properties, std::move(none_prop));
} }
Containers::ArrayView<UnrealPropertyBase::ptr> Containers::ArrayView<Types::UnrealPropertyBase::ptr>
UESaveFile::props() { File::props() {
return _properties; return _properties;
} }
bool bool
UESaveFile::saveToFile() { File::saveToFile() {
LOG_INFO_FORMAT("Writing to {}.", _filepath); LOG_INFO_FORMAT("Writing to {}.", _filepath);
bool temp_file = _filepath.hasSuffix(".tmp"); bool temp_file = _filepath.hasSuffix(".tmp");
@ -161,7 +164,7 @@ UESaveFile::saveToFile() {
} }
void void
UESaveFile::loadData() { File::loadData() {
LOG_INFO_FORMAT("Reading data from {}.", _filepath); LOG_INFO_FORMAT("Reading data from {}.", _filepath);
_valid = false; _valid = false;
@ -244,7 +247,7 @@ UESaveFile::loadData() {
return; return;
} }
UnrealPropertyBase::ptr prop; Types::UnrealPropertyBase::ptr prop;
while((prop = _propSerialiser->read(reader)) != nullptr) { while((prop = _propSerialiser->read(reader)) != nullptr) {
arrayAppend(_properties, std::move(prop)); arrayAppend(_properties, std::move(prop));
} }
@ -265,3 +268,5 @@ UESaveFile::loadData() {
_valid = true; _valid = true;
} }
}

View file

@ -29,19 +29,21 @@
using namespace Corrade; using namespace Corrade;
class UESaveFile { namespace Gvas {
class File {
public: public:
explicit UESaveFile(Containers::String filepath); explicit File(Containers::String filepath);
bool valid() const; bool valid() const;
Containers::StringView lastError() const; auto lastError() const -> Containers::StringView;
bool reloadData(); bool reloadData();
Containers::StringView saveType(); auto saveType() -> Containers::StringView;
template<typename T> template<typename T>
std::enable_if_t<std::is_base_of<UnrealPropertyBase, T>::value, T*> std::enable_if_t<std::is_base_of<Types::UnrealPropertyBase, T>::value, T*>
at(Containers::StringView name) { at(Containers::StringView name) {
for(auto& prop : _properties) { for(auto& prop : _properties) {
if(prop->name == name) { if(prop->name == name) {
@ -51,9 +53,9 @@ class UESaveFile {
return nullptr; return nullptr;
} }
void appendProperty(UnrealPropertyBase::ptr prop); void appendProperty(Types::UnrealPropertyBase::ptr prop);
Containers::ArrayView<UnrealPropertyBase::ptr> props(); auto props() -> Containers::ArrayView<Types::UnrealPropertyBase::ptr>;
bool saveToFile(); bool saveToFile();
@ -88,7 +90,9 @@ class UESaveFile {
Containers::String _saveType; Containers::String _saveType;
Containers::Array<UnrealPropertyBase::ptr> _properties; Containers::Array<Types::UnrealPropertyBase::ptr> _properties;
Containers::Reference<PropertySerialiser> _propSerialiser; Containers::Reference<PropertySerialiser> _propSerialiser;
}; };
}

26
src/Gvas/Gvas.h Normal file
View file

@ -0,0 +1,26 @@
#pragma once
// MassBuilderSaveTool
// Copyright (C) 2021-2023 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/>.
namespace Gvas {
class BinaryReader;
class BinaryWriter;
class File;
class PropertySerialiser;
}

View file

@ -16,55 +16,57 @@
#include <algorithm> #include <algorithm>
#include "Serialisers/ArrayPropertySerialiser.h" #include "../Logger/Logger.h"
#include "Serialisers/BoolPropertySerialiser.h"
#include "Serialisers/BytePropertySerialiser.h" #include "Serialisers/ArrayProperty.h"
#include "Serialisers/ColourPropertySerialiser.h" #include "Serialisers/BoolProperty.h"
#include "Serialisers/DateTimePropertySerialiser.h" #include "Serialisers/ByteProperty.h"
#include "Serialisers/EnumPropertySerialiser.h" #include "Serialisers/ColourProperty.h"
#include "Serialisers/FloatPropertySerialiser.h" #include "Serialisers/DateTimeProperty.h"
#include "Serialisers/GuidPropertySerialiser.h" #include "Serialisers/EnumProperty.h"
#include "Serialisers/IntPropertySerialiser.h" #include "Serialisers/FloatProperty.h"
#include "Serialisers/MapPropertySerialiser.h" #include "Serialisers/GuidProperty.h"
#include "Serialisers/ResourcePropertySerialiser.h" #include "Serialisers/IntProperty.h"
#include "Serialisers/RotatorPropertySerialiser.h" #include "Serialisers/MapProperty.h"
#include "Serialisers/StringPropertySerialiser.h" #include "Serialisers/ResourceProperty.h"
#include "Serialisers/SetPropertySerialiser.h" #include "Serialisers/RotatorProperty.h"
#include "Serialisers/StructSerialiser.h" #include "Serialisers/StringProperty.h"
#include "Serialisers/TextPropertySerialiser.h" #include "Serialisers/SetProperty.h"
#include "Serialisers/VectorPropertySerialiser.h" #include "Serialisers/Struct.h"
#include "Serialisers/Vector2DPropertySerialiser.h" #include "Serialisers/TextProperty.h"
#include "Serialisers/VectorProperty.h"
#include "Serialisers/Vector2DProperty.h"
#include "Types/NoneProperty.h" #include "Types/NoneProperty.h"
#include "BinaryReader.h" #include "BinaryReader.h"
#include "BinaryWriter.h" #include "BinaryWriter.h"
#include "../Logger/Logger.h"
#include "PropertySerialiser.h" #include "PropertySerialiser.h"
PropertySerialiser::PropertySerialiser() { namespace Gvas {
arrayAppend(_serialisers, Containers::pointer<ArrayPropertySerialiser>());
arrayAppend(_serialisers, Containers::pointer<BoolPropertySerialiser>());
arrayAppend(_serialisers, Containers::pointer<BytePropertySerialiser>());
arrayAppend(_serialisers, Containers::pointer<ColourPropertySerialiser>());
arrayAppend(_serialisers, Containers::pointer<DateTimePropertySerialiser>());
arrayAppend(_serialisers, Containers::pointer<EnumPropertySerialiser>());
arrayAppend(_serialisers, Containers::pointer<FloatPropertySerialiser>());
arrayAppend(_serialisers, Containers::pointer<GuidPropertySerialiser>());
arrayAppend(_serialisers, Containers::pointer<IntPropertySerialiser>());
arrayAppend(_serialisers, Containers::pointer<MapPropertySerialiser>());
arrayAppend(_serialisers, Containers::pointer<ResourcePropertySerialiser>());
arrayAppend(_serialisers, Containers::pointer<RotatorPropertySerialiser>());
arrayAppend(_serialisers, Containers::pointer<StringPropertySerialiser>());
arrayAppend(_serialisers, Containers::pointer<SetPropertySerialiser>());
arrayAppend(_serialisers, Containers::pointer<TextPropertySerialiser>());
arrayAppend(_serialisers, Containers::pointer<VectorPropertySerialiser>());
arrayAppend(_serialisers, Containers::pointer<Vector2DPropertySerialiser>());
arrayAppend(_serialisers, Containers::pointer<StructSerialiser>());
arrayAppend(_collectionSerialisers, Containers::pointer<StructSerialiser>()); PropertySerialiser::PropertySerialiser() {
arrayAppend(_serialisers, Containers::pointer<Serialisers::ArrayProperty>());
arrayAppend(_serialisers, Containers::pointer<Serialisers::BoolProperty>());
arrayAppend(_serialisers, Containers::pointer<Serialisers::ByteProperty>());
arrayAppend(_serialisers, Containers::pointer<Serialisers::ColourProperty>());
arrayAppend(_serialisers, Containers::pointer<Serialisers::DateTimeProperty>());
arrayAppend(_serialisers, Containers::pointer<Serialisers::EnumProperty>());
arrayAppend(_serialisers, Containers::pointer<Serialisers::FloatProperty>());
arrayAppend(_serialisers, Containers::pointer<Serialisers::GuidProperty>());
arrayAppend(_serialisers, Containers::pointer<Serialisers::IntProperty>());
arrayAppend(_serialisers, Containers::pointer<Serialisers::MapProperty>());
arrayAppend(_serialisers, Containers::pointer<Serialisers::ResourceProperty>());
arrayAppend(_serialisers, Containers::pointer<Serialisers::RotatorProperty>());
arrayAppend(_serialisers, Containers::pointer<Serialisers::StringProperty>());
arrayAppend(_serialisers, Containers::pointer<Serialisers::SetProperty>());
arrayAppend(_serialisers, Containers::pointer<Serialisers::TextProperty>());
arrayAppend(_serialisers, Containers::pointer<Serialisers::VectorProperty>());
arrayAppend(_serialisers, Containers::pointer<Serialisers::Vector2DProperty>());
arrayAppend(_serialisers, Containers::pointer<Serialisers::Struct>());
arrayAppend(_collectionSerialisers, Containers::pointer<Serialisers::Struct>());
} }
PropertySerialiser& PropertySerialiser&
@ -73,7 +75,7 @@ PropertySerialiser::instance() {
return serialiser; return serialiser;
} }
UnrealPropertyBase::ptr Types::UnrealPropertyBase::ptr
PropertySerialiser::read(BinaryReader& reader) { PropertySerialiser::read(BinaryReader& reader) {
if(reader.peekChar() < 0 || reader.eof()) { if(reader.peekChar() < 0 || reader.eof()) {
return nullptr; return nullptr;
@ -85,7 +87,7 @@ PropertySerialiser::read(BinaryReader& reader) {
} }
if(name == "None") { if(name == "None") {
return Containers::pointer<NoneProperty>(); return Containers::pointer<Types::NoneProperty>();
} }
Containers::String type; Containers::String type;
@ -101,7 +103,7 @@ PropertySerialiser::read(BinaryReader& reader) {
return deserialise(std::move(name), std::move(type), value_length, reader); return deserialise(std::move(name), std::move(type), value_length, reader);
} }
UnrealPropertyBase::ptr Types::UnrealPropertyBase::ptr
PropertySerialiser::readItem(BinaryReader& reader, Containers::String type, std::size_t value_length, PropertySerialiser::readItem(BinaryReader& reader, Containers::String type, std::size_t value_length,
Containers::String name) Containers::String name)
{ {
@ -112,7 +114,7 @@ PropertySerialiser::readItem(BinaryReader& reader, Containers::String type, std:
return deserialise(std::move(name), std::move(type), value_length, reader); return deserialise(std::move(name), std::move(type), value_length, reader);
} }
Containers::Array<UnrealPropertyBase::ptr> Containers::Array<Types::UnrealPropertyBase::ptr>
PropertySerialiser::readSet(BinaryReader& reader, Containers::StringView item_type, std::uint32_t count) { PropertySerialiser::readSet(BinaryReader& reader, Containers::StringView item_type, std::uint32_t count) {
if(reader.peekChar() < 0 || reader.eof()) { if(reader.peekChar() < 0 || reader.eof()) {
return nullptr; return nullptr;
@ -120,7 +122,7 @@ PropertySerialiser::readSet(BinaryReader& reader, Containers::StringView item_ty
auto serialiser = getCollectionSerialiser(item_type); auto serialiser = getCollectionSerialiser(item_type);
Containers::Array<UnrealPropertyBase::ptr> array; Containers::Array<Types::UnrealPropertyBase::ptr> array;
if(serialiser) { if(serialiser) {
Containers::String name; Containers::String name;
@ -156,11 +158,11 @@ PropertySerialiser::readSet(BinaryReader& reader, Containers::StringView item_ty
return array; return array;
} }
UnrealPropertyBase::ptr Types::UnrealPropertyBase::ptr
PropertySerialiser::deserialise(Containers::String name, Containers::String type, std::size_t value_length, PropertySerialiser::deserialise(Containers::String name, Containers::String type, std::size_t value_length,
BinaryReader& reader) BinaryReader& reader)
{ {
UnrealPropertyBase::ptr prop; Types::UnrealPropertyBase::ptr prop;
auto serialiser = getSerialiser(type); auto serialiser = getSerialiser(type);
if(serialiser == nullptr) { if(serialiser == nullptr) {
@ -180,7 +182,7 @@ PropertySerialiser::deserialise(Containers::String name, Containers::String type
return prop; return prop;
} }
bool PropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, Containers::StringView item_type, bool PropertySerialiser::serialise(Types::UnrealPropertyBase::ptr& prop, Containers::StringView item_type,
std::size_t& bytes_written, BinaryWriter& writer) std::size_t& bytes_written, BinaryWriter& writer)
{ {
auto serialiser = getSerialiser(item_type); auto serialiser = getSerialiser(item_type);
@ -191,8 +193,8 @@ bool PropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, Containers::St
} }
bool bool
PropertySerialiser::write(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer) { PropertySerialiser::write(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer) {
if(prop->name == "None" && prop->propertyType == "NoneProperty" && dynamic_cast<NoneProperty*>(prop.get())) { if(prop->name == "None" && prop->propertyType == "NoneProperty" && dynamic_cast<Types::NoneProperty*>(prop.get())) {
bytes_written += writer.writeUEStringToArray(*prop->name); bytes_written += writer.writeUEStringToArray(*prop->name);
return true; return true;
} }
@ -215,10 +217,10 @@ PropertySerialiser::write(UnrealPropertyBase::ptr& prop, std::size_t& bytes_writ
} }
bool bool
PropertySerialiser::writeItem(UnrealPropertyBase::ptr& prop, Containers::StringView item_type, PropertySerialiser::writeItem(Types::UnrealPropertyBase::ptr& prop, Containers::StringView item_type,
std::size_t& bytes_written, BinaryWriter& writer) std::size_t& bytes_written, BinaryWriter& writer)
{ {
if(prop->name == "None" && prop->propertyType == "NoneProperty" && dynamic_cast<NoneProperty*>(prop.get())) { if(prop->name == "None" && prop->propertyType == "NoneProperty" && dynamic_cast<Types::NoneProperty*>(prop.get())) {
bytes_written += writer.writeUEStringToArray(*prop->name); bytes_written += writer.writeUEStringToArray(*prop->name);
return true; return true;
} }
@ -226,7 +228,7 @@ PropertySerialiser::writeItem(UnrealPropertyBase::ptr& prop, Containers::StringV
return serialise(prop, item_type, bytes_written, writer); return serialise(prop, item_type, bytes_written, writer);
} }
bool PropertySerialiser::writeSet(Containers::ArrayView<UnrealPropertyBase::ptr> props, bool PropertySerialiser::writeSet(Containers::ArrayView<Types::UnrealPropertyBase::ptr> props,
Containers::StringView item_type, std::size_t& bytes_written, BinaryWriter& writer) Containers::StringView item_type, std::size_t& bytes_written, BinaryWriter& writer)
{ {
auto serialiser = getCollectionSerialiser(item_type); auto serialiser = getCollectionSerialiser(item_type);
@ -244,7 +246,7 @@ bool PropertySerialiser::writeSet(Containers::ArrayView<UnrealPropertyBase::ptr>
} }
} }
AbstractUnrealPropertySerialiser* Serialisers::AbstractUnrealProperty*
PropertySerialiser::getSerialiser(Containers::StringView item_type) { PropertySerialiser::getSerialiser(Containers::StringView item_type) {
for(auto& item : _serialisers) { for(auto& item : _serialisers) {
for(auto serialiser_type : item->types()) { for(auto serialiser_type : item->types()) {
@ -257,7 +259,7 @@ PropertySerialiser::getSerialiser(Containers::StringView item_type) {
return nullptr; return nullptr;
} }
AbstractUnrealCollectionPropertySerialiser* Serialisers::AbstractUnrealCollectionProperty*
PropertySerialiser::getCollectionSerialiser(Containers::StringView item_type) { PropertySerialiser::getCollectionSerialiser(Containers::StringView item_type) {
for(auto& item : _collectionSerialisers) { for(auto& item : _collectionSerialisers) {
for(Containers::StringView serialiser_type : item->types()) { for(Containers::StringView serialiser_type : item->types()) {
@ -269,3 +271,5 @@ PropertySerialiser::getCollectionSerialiser(Containers::StringView item_type) {
return nullptr; return nullptr;
} }
}

View file

@ -0,0 +1,64 @@
#pragma once
// MassBuilderSaveTool
// Copyright (C) 2021-2023 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 <Corrade/Containers/GrowableArray.h>
#include <Corrade/Containers/String.h>
#include <Corrade/Containers/StringView.h>
#include "Serialisers/AbstractUnrealProperty.h"
#include "Serialisers/AbstractUnrealCollectionProperty.h"
#include "Types/UnrealPropertyBase.h"
#include "Gvas.h"
using namespace Corrade;
namespace Gvas {
class PropertySerialiser {
public:
static auto instance() -> PropertySerialiser&;
auto read(BinaryReader& reader) -> Types::UnrealPropertyBase::ptr;
auto readItem(BinaryReader& reader, Containers::String type, std::size_t value_length, Containers::String name)
-> Types::UnrealPropertyBase::ptr;
auto readSet(BinaryReader& reader, Containers::StringView item_type, std::uint32_t count)
-> Containers::Array<Types::UnrealPropertyBase::ptr>;
auto deserialise(Containers::String name, Containers::String type, std::size_t value_length,
BinaryReader& reader) -> Types::UnrealPropertyBase::ptr;
bool serialise(Types::UnrealPropertyBase::ptr& prop, Containers::StringView item_type,
std::size_t& bytes_written, BinaryWriter& writer);
bool write(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer);
bool writeItem(Types::UnrealPropertyBase::ptr& prop, Containers::StringView item_type,
std::size_t& bytes_written, BinaryWriter& writer);
bool writeSet(Containers::ArrayView<Types::UnrealPropertyBase::ptr> props, Containers::StringView item_type,
std::size_t& bytes_written, BinaryWriter& writer);
private:
PropertySerialiser();
auto getSerialiser(Containers::StringView item_type) -> Serialisers::AbstractUnrealProperty*;
auto getCollectionSerialiser(Containers::StringView item_type) -> Serialisers::AbstractUnrealCollectionProperty*;
Containers::Array<Serialisers::AbstractUnrealProperty::ptr> _serialisers;
Containers::Array<Serialisers::AbstractUnrealCollectionProperty::ptr> _collectionSerialisers;
};
}

View file

@ -21,29 +21,31 @@
#include <Corrade/Containers/Pointer.h> #include <Corrade/Containers/Pointer.h>
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include "../Gvas.h"
#include "../Types/UnrealPropertyBase.h" #include "../Types/UnrealPropertyBase.h"
using namespace Corrade; using namespace Corrade;
class BinaryReader; namespace Gvas { namespace Serialisers {
class BinaryWriter;
class PropertySerialiser;
using PropertyArray = Containers::Array<UnrealPropertyBase::ptr>; using PropertyArray = Containers::Array<Types::UnrealPropertyBase::ptr>;
using PropertyArrayView = Containers::ArrayView<UnrealPropertyBase::ptr>; using PropertyArrayView = Containers::ArrayView<Types::UnrealPropertyBase::ptr>;
using StringArrayView = Containers::ArrayView<const Containers::String>;
class AbstractUnrealCollectionPropertySerialiser { class AbstractUnrealCollectionProperty {
public: public:
using ptr = Containers::Pointer<AbstractUnrealCollectionPropertySerialiser>; using ptr = Containers::Pointer<AbstractUnrealCollectionProperty>;
virtual ~AbstractUnrealCollectionPropertySerialiser() = default; virtual ~AbstractUnrealCollectionProperty() = default;
virtual StringArrayView types() = 0; virtual auto types() -> StringArrayView = 0;
virtual PropertyArray deserialise(Containers::StringView name, Containers::StringView type, virtual auto deserialise(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::size_t value_length, std::uint32_t count, BinaryReader& reader, std::uint32_t count, BinaryReader& reader, PropertySerialiser& serialiser)
PropertySerialiser& serialiser) = 0; -> PropertyArray = 0;
virtual bool serialise(Containers::ArrayView<UnrealPropertyBase::ptr> props, Containers::StringView item_type, virtual bool serialise(PropertyArrayView props, Containers::StringView item_type,
std::size_t& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) = 0; std::size_t& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) = 0;
}; };
}}

View file

@ -20,28 +20,30 @@
#include <Corrade/Containers/Pointer.h> #include <Corrade/Containers/Pointer.h>
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include "../Gvas.h"
#include "../Types/UnrealPropertyBase.h" #include "../Types/UnrealPropertyBase.h"
using namespace Corrade; using namespace Corrade;
class BinaryReader;
class BinaryWriter; namespace Gvas { namespace Serialisers {
class PropertySerialiser;
using StringArrayView = Containers::ArrayView<const Containers::String>; using StringArrayView = Containers::ArrayView<const Containers::String>;
class AbstractUnrealPropertySerialiser { class AbstractUnrealProperty {
public: public:
using ptr = Containers::Pointer<AbstractUnrealPropertySerialiser>; using ptr = Containers::Pointer<AbstractUnrealProperty>;
virtual ~AbstractUnrealPropertySerialiser() = default; virtual ~AbstractUnrealProperty() = default;
virtual StringArrayView types() = 0; virtual auto types() -> StringArrayView = 0;
virtual UnrealPropertyBase::ptr deserialise(Containers::StringView name, Containers::StringView type, virtual auto deserialise(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::size_t value_length, BinaryReader& reader, BinaryReader& reader, PropertySerialiser& serialiser)
PropertySerialiser& serialiser) = 0; -> Types::UnrealPropertyBase::ptr = 0;
virtual bool serialise(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, virtual bool serialise(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) = 0; PropertySerialiser& serialiser) = 0;
}; };
}}

View file

@ -21,22 +21,25 @@
#include <Corrade/Containers/Pointer.h> #include <Corrade/Containers/Pointer.h>
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include "../Gvas.h"
#include "../Types/UnrealPropertyBase.h" #include "../Types/UnrealPropertyBase.h"
using namespace Corrade; using namespace Corrade;
class BinaryReader; namespace Gvas { namespace Serialisers {
class BinaryWriter;
class AbstractUnrealStructSerialiser { class AbstractUnrealStruct {
public: public:
using ptr = Containers::Pointer<AbstractUnrealStructSerialiser>; using ptr = Containers::Pointer<AbstractUnrealStruct>;
virtual ~AbstractUnrealStructSerialiser() = default; virtual ~AbstractUnrealStruct() = default;
virtual bool supportsType(Containers::StringView type) = 0; virtual bool supportsType(Containers::StringView type) = 0;
virtual UnrealPropertyBase::ptr deserialise(BinaryReader& reader) = 0; virtual auto deserialise(BinaryReader& reader) -> Types::UnrealPropertyBase::ptr = 0;
virtual bool serialise(UnrealPropertyBase::ptr& structProp, BinaryWriter& writer, std::size_t& bytes_written) = 0; virtual bool serialise(Types::UnrealPropertyBase::ptr& structProp, BinaryWriter& writer,
std::size_t& bytes_written) = 0;
}; };
}}

View file

@ -21,12 +21,13 @@
#include "../PropertySerialiser.h" #include "../PropertySerialiser.h"
#include "../../Logger/Logger.h" #include "../../Logger/Logger.h"
#include "ArrayPropertySerialiser.h" #include "ArrayProperty.h"
UnrealPropertyBase::ptr namespace Gvas { namespace Serialisers {
ArrayPropertySerialiser::deserialiseProperty(Containers::StringView name, Containers::StringView type,
std::size_t value_length, BinaryReader& reader, Types::UnrealPropertyBase::ptr
PropertySerialiser& serialiser) ArrayProperty::deserialiseProperty(Containers::StringView name, Containers::StringView type, std::size_t value_length,
BinaryReader& reader, PropertySerialiser& serialiser)
{ {
Containers::String item_type; Containers::String item_type;
if(!reader.readUEString(item_type)) { if(!reader.readUEString(item_type)) {
@ -46,7 +47,7 @@ ArrayPropertySerialiser::deserialiseProperty(Containers::StringView name, Contai
return nullptr; return nullptr;
} }
auto prop = Containers::pointer<ArrayProperty>(); auto prop = Containers::pointer<Types::ArrayProperty>();
prop->itemType = std::move(item_type); prop->itemType = std::move(item_type);
prop->items = serialiser.readSet(reader, prop->itemType, item_count); prop->items = serialiser.readSet(reader, prop->itemType, item_count);
@ -54,10 +55,10 @@ ArrayPropertySerialiser::deserialiseProperty(Containers::StringView name, Contai
} }
bool bool
ArrayPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, ArrayProperty::serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
BinaryWriter& writer, PropertySerialiser& serialiser) PropertySerialiser& serialiser)
{ {
auto array_prop = dynamic_cast<ArrayProperty*>(prop.get()); auto array_prop = dynamic_cast<Types::ArrayProperty*>(prop.get());
if(!array_prop) { if(!array_prop) {
LOG_ERROR("The property is not a valid array property."); LOG_ERROR("The property is not a valid array property.");
return false; return false;
@ -74,3 +75,5 @@ ArrayPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std::s
return ret; return ret;
} }
}}

View file

@ -18,20 +18,24 @@
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include "UnrealPropertySerialiser.h" #include "../Gvas.h"
#include "UnrealProperty.h"
#include "../Types/ArrayProperty.h" #include "../Types/ArrayProperty.h"
using namespace Corrade; using namespace Corrade;
class ArrayPropertySerialiser : public UnrealPropertySerialiser<ArrayProperty> { namespace Gvas { namespace Serialisers {
class ArrayProperty : public UnrealProperty<Types::ArrayProperty> {
public: public:
using ptr = Containers::Pointer<ArrayPropertySerialiser>; using ptr = Containers::Pointer<ArrayProperty>;
private: private:
UnrealPropertyBase::ptr deserialiseProperty(Containers::StringView name, Containers::StringView type, auto deserialiseProperty(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::size_t value_length, BinaryReader& reader, BinaryReader& reader, PropertySerialiser& serialiser)
PropertySerialiser& serialiser) override; -> Types::UnrealPropertyBase::ptr override;
bool serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, bool serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) override; PropertySerialiser& serialiser) override;
}; };
}}

View file

@ -18,17 +18,19 @@
#include "../BinaryWriter.h" #include "../BinaryWriter.h"
#include "../../Logger/Logger.h" #include "../../Logger/Logger.h"
#include "BoolPropertySerialiser.h" #include "BoolProperty.h"
namespace Gvas { namespace Serialisers {
StringArrayView StringArrayView
BoolPropertySerialiser::types() { BoolProperty::types() {
using namespace Containers::Literals; using namespace Containers::Literals;
static const Containers::Array<Containers::String> types{InPlaceInit, {"BoolProperty"_s}}; static const Containers::Array<Containers::String> types{InPlaceInit, {"BoolProperty"_s}};
return types; return types;
} }
UnrealPropertyBase::ptr Types::UnrealPropertyBase::ptr
BoolPropertySerialiser::deserialise(Containers::StringView name, Containers::StringView type, std::size_t value_length, BoolProperty::deserialise(Containers::StringView name, Containers::StringView type, std::size_t value_length,
BinaryReader& reader, PropertySerialiser& serialiser) BinaryReader& reader, PropertySerialiser& serialiser)
{ {
if(value_length != 0) { if(value_length != 0) {
@ -47,17 +49,17 @@ BoolPropertySerialiser::deserialise(Containers::StringView name, Containers::Str
return nullptr; return nullptr;
} }
auto prop = Containers::pointer<BoolProperty>(); auto prop = Containers::pointer<Types::BoolProperty>();
prop->value = value; prop->value = value;
return prop; return prop;
} }
bool bool
BoolPropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, BoolProperty::serialise(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) PropertySerialiser& serialiser)
{ {
auto bool_prop = dynamic_cast<BoolProperty*>(prop.get()); auto bool_prop = dynamic_cast<Types::BoolProperty*>(prop.get());
if(!bool_prop) { if(!bool_prop) {
LOG_ERROR("The property is not a valid bool property."); LOG_ERROR("The property is not a valid bool property.");
return false; return false;
@ -67,3 +69,5 @@ BoolPropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, std::size_t& by
return true; return true;
} }
}}

View file

@ -19,22 +19,26 @@
#include <Corrade/Containers/ArrayView.h> #include <Corrade/Containers/ArrayView.h>
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include "AbstractUnrealPropertySerialiser.h" #include "AbstractUnrealProperty.h"
#include "../Types/BoolProperty.h" #include "../Types/BoolProperty.h"
using namespace Corrade; using namespace Corrade;
class BoolPropertySerialiser : public AbstractUnrealPropertySerialiser { namespace Gvas { namespace Serialisers {
class BoolProperty : public AbstractUnrealProperty {
public: public:
using ptr = Containers::Pointer<BoolPropertySerialiser>; using ptr = Containers::Pointer<BoolProperty>;
StringArrayView types() override; auto types() -> StringArrayView override;
UnrealPropertyBase::ptr deserialise(Containers::StringView name, Containers::StringView type, auto deserialise(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::size_t value_length, BinaryReader& reader, BinaryReader& reader, PropertySerialiser& serialiser)
PropertySerialiser& serialiser) override; -> Types::UnrealPropertyBase::ptr override;
bool serialise(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, bool serialise(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) override; PropertySerialiser& serialiser) override;
}; };
}}

View file

@ -18,20 +18,22 @@
#include "../BinaryWriter.h" #include "../BinaryWriter.h"
#include "../../Logger/Logger.h" #include "../../Logger/Logger.h"
#include "BytePropertySerialiser.h" #include "ByteProperty.h"
namespace Gvas { namespace Serialisers {
StringArrayView StringArrayView
BytePropertySerialiser::types() { ByteProperty::types() {
using namespace Containers::Literals; using namespace Containers::Literals;
static const Containers::Array<Containers::String> types{InPlaceInit, {"ByteProperty"_s}}; static const Containers::Array<Containers::String> types{InPlaceInit, {"ByteProperty"_s}};
return types; return types;
} }
UnrealPropertyBase::ptr Types::UnrealPropertyBase::ptr
BytePropertySerialiser::deserialise(Containers::StringView name, Containers::StringView type, std::size_t value_length, ByteProperty::deserialise(Containers::StringView name, Containers::StringView type, std::size_t value_length,
BinaryReader& reader, PropertySerialiser& serialiser) BinaryReader& reader, PropertySerialiser& serialiser)
{ {
auto prop = Containers::pointer<ByteProperty>(); auto prop = Containers::pointer<Types::ByteProperty>();
if(value_length != std::size_t(-1)) { if(value_length != std::size_t(-1)) {
if(!reader.readUEString(prop->enumType)) { if(!reader.readUEString(prop->enumType)) {
@ -66,10 +68,10 @@ BytePropertySerialiser::deserialise(Containers::StringView name, Containers::Str
} }
bool bool
BytePropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, ByteProperty::serialise(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) PropertySerialiser& serialiser)
{ {
auto byte_prop = dynamic_cast<ByteProperty*>(prop.get()); auto byte_prop = dynamic_cast<Types::ByteProperty*>(prop.get());
if(!byte_prop) { if(!byte_prop) {
LOG_ERROR("The property is not a valid byte property."); LOG_ERROR("The property is not a valid byte property.");
return false; return false;
@ -88,3 +90,5 @@ BytePropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, std::size_t& by
return true; return true;
} }
}}

View file

@ -19,20 +19,24 @@
#include <Corrade/Containers/ArrayView.h> #include <Corrade/Containers/ArrayView.h>
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include "AbstractUnrealPropertySerialiser.h" #include "AbstractUnrealProperty.h"
#include "../Types/ByteProperty.h" #include "../Types/ByteProperty.h"
class BytePropertySerialiser : public AbstractUnrealPropertySerialiser { namespace Gvas { namespace Serialisers {
class ByteProperty : public AbstractUnrealProperty {
public: public:
using ptr = Containers::Pointer<BytePropertySerialiser>; using ptr = Containers::Pointer<ByteProperty>;
StringArrayView types() override; auto types() -> StringArrayView override;
UnrealPropertyBase::ptr deserialise(Containers::StringView name, Containers::StringView type, auto deserialise(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::size_t value_length, BinaryReader& reader, BinaryReader& reader, PropertySerialiser& serialiser)
PropertySerialiser& serialiser) override; -> Types::UnrealPropertyBase::ptr override;
bool serialise(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, bool serialise(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) override; PropertySerialiser& serialiser) override;
}; };
}}

View file

@ -18,14 +18,15 @@
#include "../BinaryWriter.h" #include "../BinaryWriter.h"
#include "../../Logger/Logger.h" #include "../../Logger/Logger.h"
#include "ColourPropertySerialiser.h" #include "ColourProperty.h"
UnrealPropertyBase::ptr namespace Gvas { namespace Serialisers {
ColourPropertySerialiser::deserialiseProperty(Containers::StringView name, Containers::StringView type,
std::size_t value_length, BinaryReader& reader, Types::UnrealPropertyBase::ptr
PropertySerialiser& serialiser) ColourProperty::deserialiseProperty(Containers::StringView name, Containers::StringView type, std::size_t value_length,
BinaryReader& reader, PropertySerialiser& serialiser)
{ {
auto prop = Containers::pointer<ColourStructProperty>(); auto prop = Containers::pointer<Types::ColourStructProperty>();
if(!reader.readFloat(prop->r) || !reader.readFloat(prop->g) || if(!reader.readFloat(prop->r) || !reader.readFloat(prop->g) ||
!reader.readFloat(prop->b) || !reader.readFloat(prop->a)) !reader.readFloat(prop->b) || !reader.readFloat(prop->a))
@ -38,10 +39,10 @@ ColourPropertySerialiser::deserialiseProperty(Containers::StringView name, Conta
} }
bool bool
ColourPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, ColourProperty::serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written,
BinaryWriter& writer, PropertySerialiser& serialiser) BinaryWriter& writer, PropertySerialiser& serialiser)
{ {
auto colour_prop = dynamic_cast<ColourStructProperty*>(prop.get()); auto colour_prop = dynamic_cast<Types::ColourStructProperty*>(prop.get());
if(!colour_prop) { if(!colour_prop) {
LOG_ERROR("The property is not a valid colour property."); LOG_ERROR("The property is not a valid colour property.");
return false; return false;
@ -54,3 +55,5 @@ ColourPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std::
return true; return true;
} }
}}

View file

@ -18,20 +18,24 @@
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include "UnrealPropertySerialiser.h" #include "UnrealProperty.h"
#include "../Types/ColourStructProperty.h" #include "../Types/ColourStructProperty.h"
using namespace Corrade; using namespace Corrade;
class ColourPropertySerialiser : public UnrealPropertySerialiser<ColourStructProperty> { namespace Gvas { namespace Serialisers {
class ColourProperty : public UnrealProperty<Types::ColourStructProperty> {
public: public:
using ptr = Containers::Pointer<ColourPropertySerialiser>; using ptr = Containers::Pointer<ColourProperty>;
private: private:
UnrealPropertyBase::ptr deserialiseProperty(Containers::StringView name, Containers::StringView type, auto deserialiseProperty(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::size_t value_length, BinaryReader& reader, BinaryReader& reader, PropertySerialiser& serialiser)
PropertySerialiser& serialiser) override; -> Types::UnrealPropertyBase::ptr override;
bool serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, bool serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) override; PropertySerialiser& serialiser) override;
}; };
}}

View file

@ -18,14 +18,15 @@
#include "../BinaryWriter.h" #include "../BinaryWriter.h"
#include "../../Logger/Logger.h" #include "../../Logger/Logger.h"
#include "DateTimePropertySerialiser.h" #include "DateTimeProperty.h"
UnrealPropertyBase::ptr namespace Gvas { namespace Serialisers {
DateTimePropertySerialiser::deserialiseProperty(Containers::StringView name, Containers::StringView type,
std::size_t value_length, BinaryReader& reader, Types::UnrealPropertyBase::ptr
PropertySerialiser& serialiser) DateTimeProperty::deserialiseProperty(Containers::StringView name, Containers::StringView type,
std::size_t value_length, BinaryReader& reader, PropertySerialiser& serialiser)
{ {
auto prop = Containers::pointer<DateTimeStructProperty>(); auto prop = Containers::pointer<Types::DateTimeStructProperty>();
if(!reader.readInt64(prop->timestamp)) { if(!reader.readInt64(prop->timestamp)) {
LOG_ERROR_FORMAT("Couldn't read date/time property {}'s value.", name); LOG_ERROR_FORMAT("Couldn't read date/time property {}'s value.", name);
@ -36,10 +37,10 @@ DateTimePropertySerialiser::deserialiseProperty(Containers::StringView name, Con
} }
bool bool
DateTimePropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, DateTimeProperty::serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written,
BinaryWriter& writer, PropertySerialiser& serialiser) BinaryWriter& writer, PropertySerialiser& serialiser)
{ {
auto dt_prop = dynamic_cast<DateTimeStructProperty*>(prop.get()); auto dt_prop = dynamic_cast<Types::DateTimeStructProperty*>(prop.get());
if(!dt_prop) { if(!dt_prop) {
LOG_ERROR("The property is not a valid date/time property."); LOG_ERROR("The property is not a valid date/time property.");
return false; return false;
@ -49,3 +50,5 @@ DateTimePropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std
return true; return true;
} }
}}

View file

@ -18,18 +18,22 @@
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include "UnrealPropertySerialiser.h" #include "UnrealProperty.h"
#include "../Types/DateTimeStructProperty.h" #include "../Types/DateTimeStructProperty.h"
class DateTimePropertySerialiser : public UnrealPropertySerialiser<DateTimeStructProperty> { namespace Gvas { namespace Serialisers {
class DateTimeProperty : public UnrealProperty<Types::DateTimeStructProperty> {
public: public:
using ptr = Containers::Pointer<DateTimePropertySerialiser>; using ptr = Containers::Pointer<DateTimeProperty>;
private: private:
UnrealPropertyBase::ptr deserialiseProperty(Containers::StringView name, Containers::StringView type, auto deserialiseProperty(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::size_t value_length, BinaryReader& reader, BinaryReader& reader, PropertySerialiser& serialiser)
PropertySerialiser& serialiser) override; -> Types::UnrealPropertyBase::ptr override;
bool serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, bool serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) override; PropertySerialiser& serialiser) override;
}; };
}}

View file

@ -18,20 +18,22 @@
#include "../BinaryWriter.h" #include "../BinaryWriter.h"
#include "../../Logger/Logger.h" #include "../../Logger/Logger.h"
#include "EnumPropertySerialiser.h" #include "EnumProperty.h"
namespace Gvas { namespace Serialisers {
StringArrayView StringArrayView
EnumPropertySerialiser::types() { EnumProperty::types() {
using namespace Containers::Literals; using namespace Containers::Literals;
static const Containers::Array<Containers::String> types{InPlaceInit, {"EnumProperty"_s}}; static const Containers::Array<Containers::String> types{InPlaceInit, {"EnumProperty"_s}};
return types; return types;
} }
UnrealPropertyBase::ptr Types::UnrealPropertyBase::ptr
EnumPropertySerialiser::deserialise(Containers::StringView name, Containers::StringView type, std::size_t value_length, EnumProperty::deserialise(Containers::StringView name, Containers::StringView type, std::size_t value_length,
BinaryReader& reader, PropertySerialiser& serialiser) BinaryReader& reader, PropertySerialiser& serialiser)
{ {
auto prop = Containers::pointer<EnumProperty>(); auto prop = Containers::pointer<Types::EnumProperty>();
if(!reader.readUEString(prop->enumType)) { if(!reader.readUEString(prop->enumType)) {
LOG_ERROR_FORMAT("Couldn't read enum property {}'s enum type.", name); LOG_ERROR_FORMAT("Couldn't read enum property {}'s enum type.", name);
@ -53,10 +55,10 @@ EnumPropertySerialiser::deserialise(Containers::StringView name, Containers::Str
} }
bool bool
EnumPropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, EnumProperty::serialise(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) PropertySerialiser& serialiser)
{ {
auto enum_prop = dynamic_cast<EnumProperty*>(prop.get()); auto enum_prop = dynamic_cast<Types::EnumProperty*>(prop.get());
if(!enum_prop) { if(!enum_prop) {
LOG_ERROR("The property is not a valid enum property."); LOG_ERROR("The property is not a valid enum property.");
return false; return false;
@ -68,3 +70,5 @@ EnumPropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, std::size_t& by
return true; return true;
} }
}}

View file

@ -19,20 +19,24 @@
#include <Corrade/Containers/ArrayView.h> #include <Corrade/Containers/ArrayView.h>
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include "AbstractUnrealPropertySerialiser.h" #include "AbstractUnrealProperty.h"
#include "../Types/EnumProperty.h" #include "../Types/EnumProperty.h"
class EnumPropertySerialiser : public AbstractUnrealPropertySerialiser { namespace Gvas { namespace Serialisers {
class EnumProperty : public AbstractUnrealProperty {
public: public:
using ptr = Containers::Pointer<EnumPropertySerialiser>; using ptr = Containers::Pointer<EnumProperty>;
StringArrayView types() override; auto types() -> StringArrayView override;
UnrealPropertyBase::ptr deserialise(Containers::StringView name, Containers::StringView type, auto deserialise(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::size_t value_length, BinaryReader& reader, BinaryReader& reader, PropertySerialiser& serialiser)
PropertySerialiser& serialiser) override; -> Types::UnrealPropertyBase::ptr override;
bool serialise(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, bool serialise(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) override; PropertySerialiser& serialiser) override;
}; };
}}

View file

@ -18,20 +18,22 @@
#include "../BinaryWriter.h" #include "../BinaryWriter.h"
#include "../../Logger/Logger.h" #include "../../Logger/Logger.h"
#include "FloatPropertySerialiser.h" #include "FloatProperty.h"
namespace Gvas { namespace Serialisers {
StringArrayView StringArrayView
FloatPropertySerialiser::types() { FloatProperty::types() {
using namespace Containers::Literals; using namespace Containers::Literals;
static const Containers::Array<Containers::String> types{InPlaceInit, {"FloatProperty"_s}}; static const Containers::Array<Containers::String> types{InPlaceInit, {"FloatProperty"_s}};
return types; return types;
} }
UnrealPropertyBase::ptr Types::UnrealPropertyBase::ptr
FloatPropertySerialiser::deserialise(Containers::StringView name, Containers::StringView type, FloatProperty::deserialise(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::size_t value_length, BinaryReader& reader, PropertySerialiser& serialiser) BinaryReader& reader, PropertySerialiser& serialiser)
{ {
auto prop = Containers::pointer<FloatProperty>(); auto prop = Containers::pointer<Types::FloatProperty>();
char terminator; char terminator;
if(!reader.readChar(terminator) || terminator != '\0') { if(!reader.readChar(terminator) || terminator != '\0') {
@ -48,10 +50,10 @@ FloatPropertySerialiser::deserialise(Containers::StringView name, Containers::St
} }
bool bool
FloatPropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, FloatProperty::serialise(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) PropertySerialiser& serialiser)
{ {
auto float_prop = dynamic_cast<FloatProperty*>(prop.get()); auto float_prop = dynamic_cast<Types::FloatProperty*>(prop.get());
if(!float_prop) { if(!float_prop) {
LOG_ERROR("The property is not a valid float property."); LOG_ERROR("The property is not a valid float property.");
return false; return false;
@ -62,3 +64,5 @@ FloatPropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, std::size_t& b
return true; return true;
} }
}}

View file

@ -19,20 +19,24 @@
#include <Corrade/Containers/ArrayView.h> #include <Corrade/Containers/ArrayView.h>
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include "AbstractUnrealPropertySerialiser.h" #include "AbstractUnrealProperty.h"
#include "../Types/FloatProperty.h" #include "../Types/FloatProperty.h"
class FloatPropertySerialiser : public AbstractUnrealPropertySerialiser { namespace Gvas { namespace Serialisers {
class FloatProperty : public AbstractUnrealProperty {
public: public:
using ptr = Containers::Pointer<FloatPropertySerialiser>; using ptr = Containers::Pointer<FloatProperty>;
StringArrayView types() override; auto types() -> StringArrayView override;
UnrealPropertyBase::ptr deserialise(Containers::StringView name, Containers::StringView type, auto deserialise(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::size_t value_length, BinaryReader& reader, BinaryReader& reader, PropertySerialiser& serialiser)
PropertySerialiser& serialiser) override; -> Types::UnrealPropertyBase::ptr override;
bool serialise(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, bool serialise(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) override; PropertySerialiser& serialiser) override;
}; };
}}

View file

@ -18,16 +18,17 @@
#include "../BinaryWriter.h" #include "../BinaryWriter.h"
#include "../../Logger/Logger.h" #include "../../Logger/Logger.h"
#include "GuidPropertySerialiser.h" #include "GuidProperty.h"
using namespace Containers::Literals; using namespace Containers::Literals;
UnrealPropertyBase::ptr namespace Gvas { namespace Serialisers {
GuidPropertySerialiser::deserialiseProperty(Containers::StringView name, Containers::StringView type,
std::size_t value_length, BinaryReader& reader, Types::UnrealPropertyBase::ptr
PropertySerialiser& serialiser) GuidProperty::deserialiseProperty(Containers::StringView name, Containers::StringView type, std::size_t value_length,
BinaryReader& reader, PropertySerialiser& serialiser)
{ {
auto prop = Containers::pointer<GuidStructProperty>(); auto prop = Containers::pointer<Types::GuidStructProperty>();
if(!reader.readStaticArray(prop->guid)) { if(!reader.readStaticArray(prop->guid)) {
LOG_ERROR_FORMAT("Couldn't read GUID property {}'s value.", name); LOG_ERROR_FORMAT("Couldn't read GUID property {}'s value.", name);
@ -38,12 +39,12 @@ GuidPropertySerialiser::deserialiseProperty(Containers::StringView name, Contain
} }
bool bool
GuidPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, GuidProperty::serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
BinaryWriter& writer, PropertySerialiser& serialiser) PropertySerialiser& serialiser)
{ {
auto guid_prop = dynamic_cast<GuidStructProperty*>(prop.get()); auto guid_prop = dynamic_cast<Types::GuidStructProperty*>(prop.get());
if(!guid_prop) { if(!guid_prop) {
LOG_ERROR("The property is not a valid byte property."); LOG_ERROR("The property is not a valid GUID property.");
return false; return false;
} }
@ -51,3 +52,5 @@ GuidPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std::si
return true; return true;
} }
}}

View file

@ -18,18 +18,22 @@
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include "UnrealPropertySerialiser.h" #include "UnrealProperty.h"
#include "../Types/GuidStructProperty.h" #include "../Types/GuidStructProperty.h"
class GuidPropertySerialiser : public UnrealPropertySerialiser<GuidStructProperty> { namespace Gvas { namespace Serialisers {
class GuidProperty : public UnrealProperty<Types::GuidStructProperty> {
public: public:
using ptr = Containers::Pointer<GuidPropertySerialiser>; using ptr = Containers::Pointer<GuidProperty>;
private: private:
UnrealPropertyBase::ptr deserialiseProperty(Containers::StringView name, Containers::StringView type, auto deserialiseProperty(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::size_t value_length, BinaryReader& reader, BinaryReader& reader, PropertySerialiser& serialiser)
PropertySerialiser& serialiser) override; -> Types::UnrealPropertyBase::ptr override;
bool serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, bool serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) override; PropertySerialiser& serialiser) override;
}; };
}}

View file

@ -18,14 +18,15 @@
#include "../BinaryWriter.h" #include "../BinaryWriter.h"
#include "../../Logger/Logger.h" #include "../../Logger/Logger.h"
#include "IntPropertySerialiser.h" #include "IntProperty.h"
UnrealPropertyBase::ptr namespace Gvas { namespace Serialisers {
IntPropertySerialiser::deserialiseProperty(Containers::StringView name, Containers::StringView type,
std::size_t value_length, BinaryReader& reader, Types::UnrealPropertyBase::ptr
PropertySerialiser& serialiser) IntProperty::deserialiseProperty(Containers::StringView name, Containers::StringView type, std::size_t value_length,
BinaryReader& reader, PropertySerialiser& serialiser)
{ {
auto prop = Containers::pointer<IntProperty>(); auto prop = Containers::pointer<Types::IntProperty>();
if(value_length == std::size_t(-1)) { if(value_length == std::size_t(-1)) {
if(!reader.readInt32(prop->value)) { if(!reader.readInt32(prop->value)) {
@ -54,10 +55,10 @@ IntPropertySerialiser::deserialiseProperty(Containers::StringView name, Containe
} }
bool bool
IntPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, IntProperty::serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
BinaryWriter& writer, PropertySerialiser& serialiser) PropertySerialiser& serialiser)
{ {
auto int_prop = dynamic_cast<IntProperty*>(prop.get()); auto int_prop = dynamic_cast<Types::IntProperty*>(prop.get());
if(!int_prop) { if(!int_prop) {
LOG_ERROR("The property is not a valid int property."); LOG_ERROR("The property is not a valid int property.");
return false; return false;
@ -71,3 +72,5 @@ IntPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std::siz
return true; return true;
} }
}}

View file

@ -18,18 +18,22 @@
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include "UnrealPropertySerialiser.h" #include "UnrealProperty.h"
#include "../Types/IntProperty.h" #include "../Types/IntProperty.h"
class IntPropertySerialiser : public UnrealPropertySerialiser<IntProperty> { namespace Gvas { namespace Serialisers {
class IntProperty : public UnrealProperty<Types::IntProperty> {
public: public:
using ptr = Containers::Pointer<IntPropertySerialiser>; using ptr = Containers::Pointer<IntProperty>;
private: private:
UnrealPropertyBase::ptr deserialiseProperty(Containers::StringView name, Containers::StringView type, auto deserialiseProperty(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::size_t value_length, BinaryReader& reader, BinaryReader& reader, PropertySerialiser& serialiser)
PropertySerialiser& serialiser) override; -> Types::UnrealPropertyBase::ptr override;
bool serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, bool serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) override; PropertySerialiser& serialiser) override;
}; };
}}

View file

@ -20,16 +20,17 @@
#include "../Types/NoneProperty.h" #include "../Types/NoneProperty.h"
#include "../../Logger/Logger.h" #include "../../Logger/Logger.h"
#include "MapPropertySerialiser.h" #include "MapProperty.h"
using namespace Containers::Literals; using namespace Containers::Literals;
UnrealPropertyBase::ptr namespace Gvas { namespace Serialisers {
MapPropertySerialiser::deserialiseProperty(Containers::StringView name, Containers::StringView type,
std::size_t value_length, BinaryReader& reader, Types::UnrealPropertyBase::ptr
PropertySerialiser& serialiser) MapProperty::deserialiseProperty(Containers::StringView name, Containers::StringView type, std::size_t value_length,
BinaryReader& reader, PropertySerialiser& serialiser)
{ {
auto prop = Containers::pointer<MapProperty>(); auto prop = Containers::pointer<Types::MapProperty>();
if(!reader.readUEString(prop->keyType)) { if(!reader.readUEString(prop->keyType)) {
LOG_ERROR_FORMAT("Couldn't read map property {}'s key type.", name); LOG_ERROR_FORMAT("Couldn't read map property {}'s key type.", name);
@ -65,7 +66,7 @@ MapPropertySerialiser::deserialiseProperty(Containers::StringView name, Containe
arrayReserve(prop->map, count); arrayReserve(prop->map, count);
for(std::uint32_t i = 0; i < count; i++) { for(std::uint32_t i = 0; i < count; i++) {
MapProperty::KeyValuePair pair; Types::MapProperty::KeyValuePair pair;
if(prop->keyType == "IntProperty"_s || prop->keyType == "StrProperty"_s) { if(prop->keyType == "IntProperty"_s || prop->keyType == "StrProperty"_s) {
pair.key = serialiser.readItem(reader, prop->keyType, -1, name); pair.key = serialiser.readItem(reader, prop->keyType, -1, name);
@ -79,14 +80,14 @@ MapPropertySerialiser::deserialiseProperty(Containers::StringView name, Containe
return nullptr; return nullptr;
} }
UnrealPropertyBase::ptr value_item; Types::UnrealPropertyBase::ptr value_item;
if(prop->valueType == "StructProperty"_s) { if(prop->valueType == "StructProperty"_s) {
while((value_item = serialiser.read(reader)) != nullptr) { while((value_item = serialiser.read(reader)) != nullptr) {
arrayAppend(pair.values, std::move(value_item)); arrayAppend(pair.values, std::move(value_item));
if(pair.values.back()->name == "None"_s && if(pair.values.back()->name == "None"_s &&
pair.values.back()->propertyType == "NoneProperty"_s && pair.values.back()->propertyType == "NoneProperty"_s &&
dynamic_cast<NoneProperty*>(pair.values.back().get()) != nullptr) dynamic_cast<Types::NoneProperty*>(pair.values.back().get()) != nullptr)
{ {
break; break;
} }
@ -109,10 +110,10 @@ MapPropertySerialiser::deserialiseProperty(Containers::StringView name, Containe
} }
bool bool
MapPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, MapProperty::serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
BinaryWriter& writer, PropertySerialiser& serialiser) PropertySerialiser& serialiser)
{ {
auto map_prop = dynamic_cast<MapProperty*>(prop.get()); auto map_prop = dynamic_cast<Types::MapProperty*>(prop.get());
if(!map_prop) { if(!map_prop) {
LOG_ERROR("The property is not a valid map property."); LOG_ERROR("The property is not a valid map property.");
return false; return false;
@ -154,3 +155,5 @@ MapPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std::siz
return true; return true;
} }
}}

View file

@ -18,18 +18,22 @@
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include "UnrealPropertySerialiser.h" #include "UnrealProperty.h"
#include "../Types/MapProperty.h" #include "../Types/MapProperty.h"
class MapPropertySerialiser : public UnrealPropertySerialiser<MapProperty> { namespace Gvas { namespace Serialisers {
class MapProperty : public UnrealProperty<Types::MapProperty> {
public: public:
using ptr = Containers::Pointer<MapPropertySerialiser>; using ptr = Containers::Pointer<MapProperty>;
private: private:
UnrealPropertyBase::ptr deserialiseProperty(Containers::StringView name, Containers::StringView type, auto deserialiseProperty(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::size_t value_length, BinaryReader& reader, BinaryReader& reader, PropertySerialiser& serialiser)
PropertySerialiser& serialiser) override; -> Types::UnrealPropertyBase::ptr override;
bool serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, bool serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) override; PropertySerialiser& serialiser) override;
}; };
}}

View file

@ -21,16 +21,17 @@
#include "../Types/NoneProperty.h" #include "../Types/NoneProperty.h"
#include "../../Logger/Logger.h" #include "../../Logger/Logger.h"
#include "ResourcePropertySerialiser.h" #include "ResourceProperty.h"
using namespace Containers::Literals; using namespace Containers::Literals;
UnrealPropertyBase::ptr namespace Gvas { namespace Serialisers {
ResourcePropertySerialiser::deserialiseProperty(Containers::StringView name, Containers::StringView type,
std::size_t value_length, BinaryReader& reader, Types::UnrealPropertyBase::ptr
PropertySerialiser& serialiser) ResourceProperty::deserialiseProperty(Containers::StringView name, Containers::StringView type,
std::size_t value_length, BinaryReader& reader, PropertySerialiser& serialiser)
{ {
auto prop = Containers::pointer<ResourceItemValue>(); auto prop = Containers::pointer<Types::ResourceItemValue>();
auto id_prop = serialiser.read(reader); auto id_prop = serialiser.read(reader);
if(!id_prop) { if(!id_prop) {
@ -40,13 +41,13 @@ ResourcePropertySerialiser::deserialiseProperty(Containers::StringView name, Con
if((*id_prop->name) != "ID_4_AAE08F17428E229EC7A2209F51081A21"_s || if((*id_prop->name) != "ID_4_AAE08F17428E229EC7A2209F51081A21"_s ||
id_prop->propertyType != "IntProperty"_s || id_prop->propertyType != "IntProperty"_s ||
dynamic_cast<IntProperty*>(id_prop.get()) == nullptr) dynamic_cast<Types::IntProperty*>(id_prop.get()) == nullptr)
{ {
LOG_ERROR("The ID property is invalid."_s); LOG_ERROR("The ID property is invalid."_s);
return nullptr; return nullptr;
} }
prop->id = dynamic_cast<IntProperty*>(id_prop.get())->value; prop->id = dynamic_cast<Types::IntProperty*>(id_prop.get())->value;
auto value_prop = serialiser.read(reader); auto value_prop = serialiser.read(reader);
if(!value_prop) { if(!value_prop) {
@ -56,20 +57,20 @@ ResourcePropertySerialiser::deserialiseProperty(Containers::StringView name, Con
if((*value_prop->name) != "Quantity_3_560F09B5485C365D3041888910019CE3"_s || if((*value_prop->name) != "Quantity_3_560F09B5485C365D3041888910019CE3"_s ||
value_prop->propertyType != "IntProperty"_s || value_prop->propertyType != "IntProperty"_s ||
dynamic_cast<IntProperty*>(value_prop.get()) == nullptr) dynamic_cast<Types::IntProperty*>(value_prop.get()) == nullptr)
{ {
LOG_ERROR("The value property is invalid."_s); LOG_ERROR("The value property is invalid."_s);
return nullptr; return nullptr;
} }
prop->quantity = dynamic_cast<IntProperty*>(value_prop.get())->value; prop->quantity = dynamic_cast<Types::IntProperty*>(value_prop.get())->value;
auto none_prop = serialiser.read(reader); auto none_prop = serialiser.read(reader);
if(!none_prop || if(!none_prop ||
(*none_prop->name) != "None"_s || (*none_prop->name) != "None"_s ||
none_prop->propertyType != "NoneProperty"_s || none_prop->propertyType != "NoneProperty"_s ||
!dynamic_cast<NoneProperty*>(none_prop.get())) !dynamic_cast<Types::NoneProperty*>(none_prop.get()))
{ {
LOG_ERROR("Couldn't find a terminating NoneProperty."_s); LOG_ERROR("Couldn't find a terminating NoneProperty."_s);
return nullptr; return nullptr;
@ -79,10 +80,10 @@ ResourcePropertySerialiser::deserialiseProperty(Containers::StringView name, Con
} }
bool bool
ResourcePropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, ResourceProperty::serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written,
BinaryWriter& writer, PropertySerialiser& serialiser) BinaryWriter& writer, PropertySerialiser& serialiser)
{ {
auto res_prop = dynamic_cast<ResourceItemValue*>(prop.get()); auto res_prop = dynamic_cast<Types::ResourceItemValue*>(prop.get());
if(!res_prop) { if(!res_prop) {
LOG_ERROR("The property is not a valid ResourceItemValue property."); LOG_ERROR("The property is not a valid ResourceItemValue property.");
return false; return false;
@ -104,3 +105,5 @@ ResourcePropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std
return true; return true;
} }
}}

View file

@ -18,18 +18,22 @@
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include "UnrealPropertySerialiser.h" #include "UnrealProperty.h"
#include "../Types/ResourceItemValue.h" #include "../Types/ResourceItemValue.h"
class ResourcePropertySerialiser : public UnrealPropertySerialiser<ResourceItemValue> { namespace Gvas { namespace Serialisers {
class ResourceProperty : public UnrealProperty<Types::ResourceItemValue> {
public: public:
using ptr = Containers::Pointer<ResourcePropertySerialiser>; using ptr = Containers::Pointer<ResourceProperty>;
private: private:
UnrealPropertyBase::ptr deserialiseProperty(Containers::StringView name, Containers::StringView type, auto deserialiseProperty(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::size_t value_length, BinaryReader& reader, BinaryReader& reader, PropertySerialiser& serialiser)
PropertySerialiser& serialiser) override; -> Types::UnrealPropertyBase::ptr override;
bool serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, bool serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) override; PropertySerialiser& serialiser) override;
}; };
}}

View file

@ -18,14 +18,15 @@
#include "../BinaryWriter.h" #include "../BinaryWriter.h"
#include "../../Logger/Logger.h" #include "../../Logger/Logger.h"
#include "RotatorPropertySerialiser.h" #include "RotatorProperty.h"
UnrealPropertyBase::ptr namespace Gvas { namespace Serialisers {
RotatorPropertySerialiser::deserialiseProperty(Containers::StringView name, Containers::StringView type,
std::size_t value_length, BinaryReader& reader, Types::UnrealPropertyBase::ptr
PropertySerialiser& serialiser) RotatorProperty::deserialiseProperty(Containers::StringView name, Containers::StringView type, std::size_t value_length,
BinaryReader& reader, PropertySerialiser& serialiser)
{ {
auto prop = Containers::pointer<RotatorStructProperty>(); auto prop = Containers::pointer<Types::RotatorStructProperty>();
if(!reader.readFloat(prop->x) || !reader.readFloat(prop->y) || !reader.readFloat(prop->z)) { if(!reader.readFloat(prop->x) || !reader.readFloat(prop->y) || !reader.readFloat(prop->z)) {
LOG_ERROR_FORMAT("Couldn't read rotator property {}'s value.", name); LOG_ERROR_FORMAT("Couldn't read rotator property {}'s value.", name);
@ -36,10 +37,10 @@ RotatorPropertySerialiser::deserialiseProperty(Containers::StringView name, Cont
} }
bool bool
RotatorPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, RotatorProperty::serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written,
BinaryWriter& writer, PropertySerialiser& serialiser) BinaryWriter& writer, PropertySerialiser& serialiser)
{ {
auto rotator = dynamic_cast<RotatorStructProperty*>(prop.get()); auto rotator = dynamic_cast<Types::RotatorStructProperty*>(prop.get());
if(!rotator) { if(!rotator) {
LOG_ERROR("The property is not a valid rotator property."); LOG_ERROR("The property is not a valid rotator property.");
return false; return false;
@ -50,3 +51,5 @@ RotatorPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std:
return true; return true;
} }
}}

View file

@ -18,18 +18,22 @@
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include "UnrealPropertySerialiser.h" #include "UnrealProperty.h"
#include "../Types/RotatorStructProperty.h" #include "../Types/RotatorStructProperty.h"
class RotatorPropertySerialiser : public UnrealPropertySerialiser<RotatorStructProperty> { namespace Gvas { namespace Serialisers {
class RotatorProperty : public UnrealProperty<Types::RotatorStructProperty> {
public: public:
using ptr = Containers::Pointer<RotatorPropertySerialiser>; using ptr = Containers::Pointer<RotatorProperty>;
private: private:
UnrealPropertyBase::ptr deserialiseProperty(Containers::StringView name, Containers::StringView type, auto deserialiseProperty(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::size_t value_length, BinaryReader& reader, BinaryReader& reader, PropertySerialiser& serialiser)
PropertySerialiser& serialiser) override; -> Types::UnrealPropertyBase::ptr override;
bool serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, bool serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) override; PropertySerialiser& serialiser) override;
}; };
}}

View file

@ -0,0 +1,44 @@
#pragma once
// MassBuilderSaveTool
// Copyright (C) 2021-2023 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/>.
namespace Gvas { namespace Serialisers {
class AbstractUnrealCollectionProperty;
class AbstractUnrealProperty;
class AbstractUnrealStruct;
class ArrayProperty;
class BoolProperty;
class ByteProperty;
class ColourProperty;
class DateTimeProperty;
class EnumProperty;
class FloatProperty;
class GuidProperty;
class IntProperty;
class MapProperty;
class ResourceProperty;
class RotatorProperty;
class SetProperty;
class StringProperty;
class Struct;
class TextProperty;
class UnrealProperty;
class Vector2DProperty;
class VectorProperty;
}}

View file

@ -19,12 +19,13 @@
#include "../PropertySerialiser.h" #include "../PropertySerialiser.h"
#include "../../Logger/Logger.h" #include "../../Logger/Logger.h"
#include "SetPropertySerialiser.h" #include "SetProperty.h"
UnrealPropertyBase::ptr namespace Gvas { namespace Serialisers {
SetPropertySerialiser::deserialiseProperty(Containers::StringView name, Containers::StringView type,
std::size_t value_length, BinaryReader& reader, Types::UnrealPropertyBase::ptr
PropertySerialiser& serialiser) SetProperty::deserialiseProperty(Containers::StringView name, Containers::StringView type, std::size_t value_length,
BinaryReader& reader, PropertySerialiser& serialiser)
{ {
Containers::String item_type; Containers::String item_type;
if(!reader.readUEString(item_type)) { if(!reader.readUEString(item_type)) {
@ -50,7 +51,7 @@ SetPropertySerialiser::deserialiseProperty(Containers::StringView name, Containe
return nullptr; return nullptr;
} }
auto prop = Containers::pointer<SetProperty>(); auto prop = Containers::pointer<Types::SetProperty>();
prop->itemType = std::move(item_type); prop->itemType = std::move(item_type);
prop->items = serialiser.readSet(reader, prop->itemType, item_count); prop->items = serialiser.readSet(reader, prop->itemType, item_count);
@ -58,10 +59,10 @@ SetPropertySerialiser::deserialiseProperty(Containers::StringView name, Containe
} }
bool bool
SetPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, SetProperty::serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
BinaryWriter& writer, PropertySerialiser& serialiser) PropertySerialiser& serialiser)
{ {
auto set_prop = dynamic_cast<SetProperty*>(prop.get()); auto set_prop = dynamic_cast<Types::SetProperty*>(prop.get());
if(!set_prop) { if(!set_prop) {
LOG_ERROR("The property is not a valid set property."); LOG_ERROR("The property is not a valid set property.");
return false; return false;
@ -80,3 +81,5 @@ SetPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std::siz
return true; return true;
} }
}}

View file

@ -18,18 +18,22 @@
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include "UnrealPropertySerialiser.h" #include "UnrealProperty.h"
#include "../Types/SetProperty.h" #include "../Types/SetProperty.h"
class SetPropertySerialiser : public UnrealPropertySerialiser<SetProperty> { namespace Gvas { namespace Serialisers {
class SetProperty : public UnrealProperty<Types::SetProperty> {
public: public:
using ptr = Containers::Pointer<SetPropertySerialiser>; using ptr = Containers::Pointer<SetProperty>;
private: private:
UnrealPropertyBase::ptr deserialiseProperty(Containers::StringView name, Containers::StringView type, auto deserialiseProperty(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::size_t value_length, BinaryReader& reader, BinaryReader& reader, PropertySerialiser& serialiser)
PropertySerialiser& serialiser) override; -> Types::UnrealPropertyBase::ptr override;
bool serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, bool serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) override; PropertySerialiser& serialiser) override;
}; };
}}

View file

@ -18,10 +18,12 @@
#include "../BinaryWriter.h" #include "../BinaryWriter.h"
#include "../../Logger/Logger.h" #include "../../Logger/Logger.h"
#include "StringPropertySerialiser.h" #include "StringProperty.h"
namespace Gvas { namespace Serialisers {
StringArrayView StringArrayView
StringPropertySerialiser::types() { StringProperty::types() {
using namespace Containers::Literals; using namespace Containers::Literals;
static const Containers::Array<Containers::String> types{InPlaceInit, { static const Containers::Array<Containers::String> types{InPlaceInit, {
"NameProperty"_s, "StrProperty"_s, "SoftObjectProperty"_s, "ObjectProperty"_s "NameProperty"_s, "StrProperty"_s, "SoftObjectProperty"_s, "ObjectProperty"_s
@ -29,11 +31,11 @@ StringPropertySerialiser::types() {
return types; return types;
} }
UnrealPropertyBase::ptr Types::UnrealPropertyBase::ptr
StringPropertySerialiser::deserialise(Containers::StringView name, Containers::StringView type, StringProperty::deserialise(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::size_t value_length, BinaryReader& reader, PropertySerialiser& serialiser) BinaryReader& reader, PropertySerialiser& serialiser)
{ {
auto prop = Containers::pointer<StringProperty>(type); auto prop = Containers::pointer<Types::StringProperty>(type);
if(value_length != std::size_t(-1)) { if(value_length != std::size_t(-1)) {
char terminator; char terminator;
@ -54,10 +56,10 @@ StringPropertySerialiser::deserialise(Containers::StringView name, Containers::S
} }
bool bool
StringPropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, StringProperty::serialise(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) PropertySerialiser& serialiser)
{ {
auto str_prop = dynamic_cast<StringProperty*>(prop.get()); auto str_prop = dynamic_cast<Types::StringProperty*>(prop.get());
if(!str_prop) { if(!str_prop) {
LOG_ERROR("The property is not a valid string property."); LOG_ERROR("The property is not a valid string property.");
return false; return false;
@ -71,3 +73,5 @@ StringPropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, std::size_t&
return true; return true;
} }
}}

View file

@ -19,20 +19,24 @@
#include <Corrade/Containers/ArrayView.h> #include <Corrade/Containers/ArrayView.h>
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include "AbstractUnrealPropertySerialiser.h" #include "AbstractUnrealProperty.h"
#include "../Types/StringProperty.h" #include "../Types/StringProperty.h"
class StringPropertySerialiser : public AbstractUnrealPropertySerialiser { namespace Gvas { namespace Serialisers {
class StringProperty : public AbstractUnrealProperty {
public: public:
using ptr = Containers::Pointer<StringPropertySerialiser>; using ptr = Containers::Pointer<StringProperty>;
StringArrayView types() override; auto types() -> StringArrayView override;
UnrealPropertyBase::ptr deserialise(Containers::StringView name, Containers::StringView type, auto deserialise(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::size_t value_length, BinaryReader& reader, BinaryReader& reader, PropertySerialiser& serialiser)
PropertySerialiser& serialiser) override; -> Types::UnrealPropertyBase::ptr override;
bool serialise(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, bool serialise(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) override; PropertySerialiser& serialiser) override;
}; };
}}

View file

@ -23,17 +23,19 @@
#include "../Types/NoneProperty.h" #include "../Types/NoneProperty.h"
#include "../../Logger/Logger.h" #include "../../Logger/Logger.h"
#include "StructSerialiser.h" #include "Struct.h"
namespace Gvas { namespace Serialisers {
StringArrayView StringArrayView
StructSerialiser::types() { Struct::types() {
using namespace Containers::Literals; using namespace Containers::Literals;
static const Containers::Array<Containers::String> types{InPlaceInit, {"StructProperty"_s}}; static const Containers::Array<Containers::String> types{InPlaceInit, {"StructProperty"_s}};
return types; return types;
} }
Containers::Array<UnrealPropertyBase::ptr> PropertyArray
StructSerialiser::deserialise(Containers::StringView name, Containers::StringView type, std::size_t value_length, Struct::deserialise(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::uint32_t count, BinaryReader& reader, PropertySerialiser& serialiser) std::uint32_t count, BinaryReader& reader, PropertySerialiser& serialiser)
{ {
Containers::String item_type; Containers::String item_type;
@ -54,16 +56,16 @@ StructSerialiser::deserialise(Containers::StringView name, Containers::StringVie
return nullptr; return nullptr;
} }
Containers::Array<UnrealPropertyBase::ptr> array; Containers::Array<Types::UnrealPropertyBase::ptr> array;
if(count == 0) { if(count == 0) {
auto prop = Containers::pointer<GenericStructProperty>(); auto prop = Containers::pointer<Types::GenericStructProperty>();
prop->structType = std::move(item_type); prop->structType = std::move(item_type);
prop->structGuid = std::move(guid); prop->structGuid = std::move(guid);
} }
else { else {
for(std::uint32_t i = 0; i < count; i++) { for(std::uint32_t i = 0; i < count; i++) {
auto prop = Containers::pointer<UnrealPropertyBase>(); auto prop = Containers::pointer<Types::UnrealPropertyBase>();
prop = serialiser.readItem(reader, item_type, std::size_t(-1), name); prop = serialiser.readItem(reader, item_type, std::size_t(-1), name);
@ -76,7 +78,7 @@ StructSerialiser::deserialise(Containers::StringView name, Containers::StringVie
return nullptr; return nullptr;
} }
dynamic_cast<StructProperty*>(prop.get())->structGuid = guid; dynamic_cast<Types::StructProperty*>(prop.get())->structGuid = guid;
arrayAppend(array, std::move(prop)); arrayAppend(array, std::move(prop));
} }
@ -85,8 +87,8 @@ StructSerialiser::deserialise(Containers::StringView name, Containers::StringVie
return array; return array;
} }
UnrealPropertyBase::ptr Types::UnrealPropertyBase::ptr
StructSerialiser::deserialise(Containers::StringView name, Containers::StringView type, std::size_t value_length, Struct::deserialise(Containers::StringView name, Containers::StringView type, std::size_t value_length,
BinaryReader& reader, PropertySerialiser& serialiser) BinaryReader& reader, PropertySerialiser& serialiser)
{ {
Containers::String item_type; Containers::String item_type;
@ -96,7 +98,7 @@ StructSerialiser::deserialise(Containers::StringView name, Containers::StringVie
} }
if(item_type == "None") { if(item_type == "None") {
return NoneProperty::ptr{}; return Containers::pointer<Types::NoneProperty>();
} }
Containers::StaticArray<16, char> guid{ValueInit}; Containers::StaticArray<16, char> guid{ValueInit};
@ -111,12 +113,12 @@ StructSerialiser::deserialise(Containers::StringView name, Containers::StringVie
return nullptr; return nullptr;
} }
UnrealPropertyBase::ptr prop = serialiser.readItem(reader, item_type, value_length, name); auto prop = serialiser.readItem(reader, item_type, value_length, name);
if(!prop) { if(!prop) {
prop = readStructValue(name, item_type, value_length, reader, serialiser); prop = readStructValue(name, item_type, value_length, reader, serialiser);
if(prop) { if(prop) {
dynamic_cast<GenericStructProperty*>(prop.get())->structGuid = std::move(guid); dynamic_cast<Types::GenericStructProperty*>(prop.get())->structGuid = std::move(guid);
} }
} }
@ -124,15 +126,15 @@ StructSerialiser::deserialise(Containers::StringView name, Containers::StringVie
} }
bool bool
StructSerialiser::serialise(Containers::ArrayView<UnrealPropertyBase::ptr> props, Containers::StringView item_type, Struct::serialise(PropertyArrayView props, Containers::StringView item_type, std::size_t& bytes_written,
std::size_t& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) BinaryWriter& writer, PropertySerialiser& serialiser)
{ {
bytes_written += writer.writeUEStringToArray(*(props.front()->name)); bytes_written += writer.writeUEStringToArray(*(props.front()->name));
bytes_written += writer.writeUEStringToArray(item_type); bytes_written += writer.writeUEStringToArray(item_type);
std::size_t vl_pos = writer.arrayPosition(); std::size_t vl_pos = writer.arrayPosition();
bytes_written += writer.writeValueToArray<std::size_t>(0ull); bytes_written += writer.writeValueToArray<std::size_t>(0ull);
auto struct_prop = dynamic_cast<StructProperty*>(props.front().get()); auto struct_prop = dynamic_cast<Types::StructProperty*>(props.front().get());
if(!struct_prop) { if(!struct_prop) {
LOG_ERROR("The property is not a valid struct property."); LOG_ERROR("The property is not a valid struct property.");
return false; return false;
@ -146,7 +148,7 @@ StructSerialiser::serialise(Containers::ArrayView<UnrealPropertyBase::ptr> props
std::size_t bytes_written_here = 0; std::size_t bytes_written_here = 0;
for(auto& prop : props) { for(auto& prop : props) {
struct_prop = dynamic_cast<StructProperty*>(prop.get()); struct_prop = dynamic_cast<Types::StructProperty*>(prop.get());
if(!struct_prop) { if(!struct_prop) {
LOG_ERROR("The property is not a valid struct property."); LOG_ERROR("The property is not a valid struct property.");
return false; return false;
@ -168,10 +170,10 @@ StructSerialiser::serialise(Containers::ArrayView<UnrealPropertyBase::ptr> props
} }
bool bool
StructSerialiser::serialise(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, Struct::serialise(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) PropertySerialiser& serialiser)
{ {
auto struct_prop = dynamic_cast<StructProperty*>(prop.get()); auto struct_prop = dynamic_cast<Types::StructProperty*>(prop.get());
if(!struct_prop) { if(!struct_prop) {
LOG_ERROR("The property is not a valid struct property."); LOG_ERROR("The property is not a valid struct property.");
return false; return false;
@ -194,22 +196,22 @@ StructSerialiser::serialise(UnrealPropertyBase::ptr& prop, std::size_t& bytes_wr
return true; return true;
} }
StructProperty::ptr Types::StructProperty::ptr
StructSerialiser::readStructValue(Containers::StringView name, Containers::StringView type, std::size_t value_length, Struct::readStructValue(Containers::StringView name, Containers::StringView type, std::size_t value_length,
BinaryReader& reader, PropertySerialiser& serialiser) BinaryReader& reader, PropertySerialiser& serialiser)
{ {
static_cast<void>(value_length); static_cast<void>(value_length);
auto st_prop = Containers::pointer<GenericStructProperty>(); auto st_prop = Containers::pointer<Types::GenericStructProperty>();
st_prop->structType = type; st_prop->structType = type;
UnrealPropertyBase::ptr prop; Types::UnrealPropertyBase::ptr prop;
while((prop = serialiser.read(reader)) != nullptr) { while((prop = serialiser.read(reader)) != nullptr) {
arrayAppend(st_prop->properties, std::move(prop)); arrayAppend(st_prop->properties, std::move(prop));
if(st_prop->properties.back()->name == "None" && if(st_prop->properties.back()->name == "None" &&
st_prop->properties.back()->propertyType == "NoneProperty" && st_prop->properties.back()->propertyType == "NoneProperty" &&
dynamic_cast<NoneProperty*>(st_prop->properties.back().get()) != nullptr) dynamic_cast<Types::NoneProperty*>(st_prop->properties.back().get()) != nullptr)
{ {
break; break;
} }
@ -221,10 +223,10 @@ StructSerialiser::readStructValue(Containers::StringView name, Containers::Strin
} }
bool bool
StructSerialiser::writeStructValue(StructProperty* prop, std::size_t& bytes_written, BinaryWriter& writer, Struct::writeStructValue(Types::StructProperty* prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) PropertySerialiser& serialiser)
{ {
auto struct_prop = dynamic_cast<GenericStructProperty*>(prop); auto struct_prop = dynamic_cast<Types::GenericStructProperty*>(prop);
if(!struct_prop) { if(!struct_prop) {
LOG_ERROR("The property is not a valid struct property."); LOG_ERROR("The property is not a valid struct property.");
return false; return false;
@ -239,3 +241,5 @@ StructSerialiser::writeStructValue(StructProperty* prop, std::size_t& bytes_writ
return true; return true;
} }
}}

View file

@ -0,0 +1,55 @@
#pragma once
// MassBuilderSaveTool
// Copyright (C) 2021-2023 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 <Corrade/Containers/ArrayView.h>
#include <Corrade/Containers/StringView.h>
#include "AbstractUnrealCollectionProperty.h"
#include "AbstractUnrealProperty.h"
#include "AbstractUnrealStruct.h"
#include "../Types/StructProperty.h"
namespace Gvas { namespace Serialisers {
class Struct : public AbstractUnrealProperty, public AbstractUnrealCollectionProperty {
public:
using ptr = Containers::Pointer<Struct>;
auto types() -> StringArrayView override;
auto deserialise(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::uint32_t count, BinaryReader& reader, PropertySerialiser& serialiser)
-> PropertyArray override;
auto deserialise(Containers::StringView name, Containers::StringView type, std::size_t value_length,
BinaryReader& reader, PropertySerialiser& serialiser)
-> Types::UnrealPropertyBase::ptr override;
bool serialise(PropertyArrayView props, Containers::StringView item_type, std::size_t& bytes_written,
BinaryWriter& writer, PropertySerialiser& serialiser) override;
bool serialise(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) override;
private:
auto readStructValue(Containers::StringView name, Containers::StringView type, std::size_t value_length,
BinaryReader& reader, PropertySerialiser& serialiser) -> Types::StructProperty::ptr;
bool writeStructValue(Types::StructProperty* prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser);
};
}}

View file

@ -16,17 +16,20 @@
#include <Corrade/Containers/String.h> #include <Corrade/Containers/String.h>
#include "../../Logger/Logger.h"
#include "../BinaryReader.h" #include "../BinaryReader.h"
#include "../BinaryWriter.h" #include "../BinaryWriter.h"
#include "TextPropertySerialiser.h" #include "TextProperty.h"
UnrealPropertyBase::ptr namespace Gvas { namespace Serialisers {
TextPropertySerialiser::deserialiseProperty(Containers::StringView name, Containers::StringView type,
std::size_t value_length, BinaryReader& reader, Types::UnrealPropertyBase::ptr
PropertySerialiser& serialiser) TextProperty::deserialiseProperty(Containers::StringView name, Containers::StringView type, std::size_t value_length,
BinaryReader& reader, PropertySerialiser& serialiser)
{ {
auto prop = Containers::pointer<TextProperty>(); auto prop = Containers::pointer<Types::TextProperty>();
auto start_position = reader.position(); auto start_position = reader.position();
@ -70,12 +73,12 @@ TextPropertySerialiser::deserialiseProperty(Containers::StringView name, Contain
} }
bool bool
TextPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, TextProperty::serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
BinaryWriter& writer, PropertySerialiser& serialiser) PropertySerialiser& serialiser)
{ {
auto text_prop = dynamic_cast<TextProperty*>(prop.get()); auto text_prop = dynamic_cast<Types::TextProperty*>(prop.get());
if(!text_prop) { if(!text_prop) {
LOG_ERROR("The property is not a valid text property.");
return false; return false;
} }
@ -87,3 +90,5 @@ TextPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std::si
return true; return true;
} }
}}

View file

@ -18,18 +18,22 @@
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include "UnrealPropertySerialiser.h" #include "UnrealProperty.h"
#include "../Types/TextProperty.h" #include "../Types/TextProperty.h"
class TextPropertySerialiser : public UnrealPropertySerialiser<TextProperty> { namespace Gvas { namespace Serialisers {
class TextProperty : public UnrealProperty<Types::TextProperty> {
public: public:
using ptr = Containers::Pointer<TextPropertySerialiser>; using ptr = Containers::Pointer<TextProperty>;
private: private:
UnrealPropertyBase::ptr deserialiseProperty(Containers::StringView name, Containers::StringView type, auto deserialiseProperty(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::size_t value_length, BinaryReader& reader, BinaryReader& reader, PropertySerialiser& serialiser)
PropertySerialiser& serialiser) override; -> Types::UnrealPropertyBase::ptr override;
bool serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, bool serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) override; PropertySerialiser& serialiser) override;
}; };
}}

View file

@ -22,23 +22,25 @@
#include <Corrade/Containers/ArrayView.h> #include <Corrade/Containers/ArrayView.h>
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include "AbstractUnrealPropertySerialiser.h" #include "AbstractUnrealProperty.h"
#include "../Types/StructProperty.h" #include "../Types/StructProperty.h"
namespace Gvas { namespace Serialisers {
template<typename T> template<typename T>
class UnrealPropertySerialiser : public AbstractUnrealPropertySerialiser { class UnrealProperty : public AbstractUnrealProperty {
static_assert(std::is_base_of<UnrealPropertyBase, T>::value, "T must be derived from UnrealPropertyBase."); static_assert(std::is_base_of<Types::UnrealPropertyBase, T>::value, "T must be derived from UnrealPropertyBase.");
public: public:
using ptr = Containers::Pointer<UnrealPropertySerialiser<T>>; using ptr = Containers::Pointer<UnrealProperty<T>>;
StringArrayView types() override { auto types() -> StringArrayView override {
static const Containers::Array<Containers::String> types = []{ static const Containers::Array<Containers::String> types = []{
Containers::Array<Containers::String> array; Containers::Array<Containers::String> array;
Containers::Pointer<T> p(new T); Containers::Pointer<T> p(new T);
if(std::is_base_of<StructProperty, T>::value) { if(std::is_base_of<Types::StructProperty, T>::value) {
array = Containers::Array<Containers::String>{InPlaceInit, { array = Containers::Array<Containers::String>{InPlaceInit, {
dynamic_cast<StructProperty*>(p.get())->structType dynamic_cast<Types::StructProperty*>(p.get())->structType
}}; }};
} }
else { else {
@ -49,24 +51,26 @@ class UnrealPropertySerialiser : public AbstractUnrealPropertySerialiser {
return types; return types;
} }
UnrealPropertyBase::ptr deserialise(Containers::StringView name, Containers::StringView type, auto deserialise(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::size_t value_length, BinaryReader& reader, BinaryReader& reader, PropertySerialiser& serialiser)
PropertySerialiser& serialiser) override -> Types::UnrealPropertyBase::ptr override
{ {
return deserialiseProperty(name, type, value_length, reader, serialiser); return deserialiseProperty(name, type, value_length, reader, serialiser);
} }
bool serialise(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, bool serialise(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) override PropertySerialiser& serialiser) override
{ {
return serialiseProperty(prop, bytes_written, writer, serialiser); return serialiseProperty(prop, bytes_written, writer, serialiser);
} }
private: private:
virtual UnrealPropertyBase::ptr deserialiseProperty(Containers::StringView name, Containers::StringView type, virtual auto deserialiseProperty(Containers::StringView name, Containers::StringView type,
std::size_t value_length, BinaryReader& reader, std::size_t value_length, BinaryReader& reader, PropertySerialiser& serialiser)
PropertySerialiser& serialiser) = 0; -> Types::UnrealPropertyBase::ptr = 0;
virtual bool serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, virtual bool serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written,
PropertySerialiser& serialiser) = 0; BinaryWriter& writer, PropertySerialiser& serialiser) = 0;
}; };
}}

View file

@ -18,14 +18,15 @@
#include "../BinaryWriter.h" #include "../BinaryWriter.h"
#include "../../Logger/Logger.h" #include "../../Logger/Logger.h"
#include "Vector2DPropertySerialiser.h" #include "Vector2DProperty.h"
UnrealPropertyBase::ptr namespace Gvas { namespace Serialisers {
Vector2DPropertySerialiser::deserialiseProperty(Containers::StringView name, Containers::StringView type,
std::size_t value_length, BinaryReader& reader, Types::UnrealPropertyBase::ptr
PropertySerialiser& serialiser) Vector2DProperty::deserialiseProperty(Containers::StringView name, Containers::StringView type,
std::size_t value_length, BinaryReader& reader, PropertySerialiser& serialiser)
{ {
auto prop = Containers::pointer<Vector2DStructProperty>(); auto prop = Containers::pointer<Types::Vector2DStructProperty>();
if(!reader.readFloat(prop->x) || !reader.readFloat(prop->y)) { if(!reader.readFloat(prop->x) || !reader.readFloat(prop->y)) {
LOG_ERROR_FORMAT("Couldn't read 2D vector property {}'s value.", name); LOG_ERROR_FORMAT("Couldn't read 2D vector property {}'s value.", name);
@ -36,10 +37,10 @@ Vector2DPropertySerialiser::deserialiseProperty(Containers::StringView name, Con
} }
bool bool
Vector2DPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, Vector2DProperty::serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written,
BinaryWriter& writer, PropertySerialiser& serialiser) BinaryWriter& writer, PropertySerialiser& serialiser)
{ {
auto vector = dynamic_cast<Vector2DStructProperty*>(prop.get()); auto vector = dynamic_cast<Types::Vector2DStructProperty*>(prop.get());
if(!vector) { if(!vector) {
LOG_ERROR("The property is not a valid 2D vector property."); LOG_ERROR("The property is not a valid 2D vector property.");
return false; return false;
@ -49,3 +50,5 @@ Vector2DPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std
return true; return true;
} }
}}

View file

@ -18,18 +18,22 @@
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include "UnrealPropertySerialiser.h" #include "UnrealProperty.h"
#include "../Types/Vector2DStructProperty.h" #include "../Types/Vector2DStructProperty.h"
class Vector2DPropertySerialiser : public UnrealPropertySerialiser<Vector2DStructProperty> { namespace Gvas { namespace Serialisers {
class Vector2DProperty : public UnrealProperty<Types::Vector2DStructProperty> {
public: public:
using ptr = Containers::Pointer<Vector2DPropertySerialiser>; using ptr = Containers::Pointer<Vector2DProperty>;
private: private:
UnrealPropertyBase::ptr deserialiseProperty(Containers::StringView name, Containers::StringView type, auto deserialiseProperty(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::size_t value_length, BinaryReader& reader, BinaryReader& reader, PropertySerialiser& serialiser)
PropertySerialiser& serialiser) override; -> Types::UnrealPropertyBase::ptr override;
bool serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, bool serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) override; PropertySerialiser& serialiser) override;
}; };
}}

View file

@ -14,18 +14,20 @@
// 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 "../BinaryReader.h"
#include "../BinaryWriter.h"
#include "../../Logger/Logger.h" #include "../../Logger/Logger.h"
#include "VectorPropertySerialiser.h" #include "../BinaryReader.h"
#include "../BinaryWriter.h"
UnrealPropertyBase::ptr #include "VectorProperty.h"
VectorPropertySerialiser::deserialiseProperty(Containers::StringView name, Containers::StringView type,
std::size_t value_length, BinaryReader& reader, namespace Gvas { namespace Serialisers {
PropertySerialiser& serialiser)
Types::UnrealPropertyBase::ptr
VectorProperty::deserialiseProperty(Containers::StringView name, Containers::StringView type, std::size_t value_length,
BinaryReader& reader, PropertySerialiser& serialiser)
{ {
auto prop = Containers::pointer<VectorStructProperty>(); auto prop = Containers::pointer<Types::VectorStructProperty>();
if(!reader.readFloat(prop->x) || !reader.readFloat(prop->y) || !reader.readFloat(prop->z)) { if(!reader.readFloat(prop->x) || !reader.readFloat(prop->y) || !reader.readFloat(prop->z)) {
LOG_ERROR_FORMAT("Couldn't read vector property {}'s value.", name); LOG_ERROR_FORMAT("Couldn't read vector property {}'s value.", name);
@ -36,10 +38,10 @@ VectorPropertySerialiser::deserialiseProperty(Containers::StringView name, Conta
} }
bool bool
VectorPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, VectorProperty::serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written,
BinaryWriter& writer, PropertySerialiser& serialiser) BinaryWriter& writer, PropertySerialiser& serialiser)
{ {
auto vector = dynamic_cast<VectorStructProperty*>(prop.get()); auto vector = dynamic_cast<Types::VectorStructProperty*>(prop.get());
if(!vector) { if(!vector) {
LOG_ERROR("The property is not a valid vector property."); LOG_ERROR("The property is not a valid vector property.");
return false; return false;
@ -50,3 +52,5 @@ VectorPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, std::
return true; return true;
} }
}}

View file

@ -18,18 +18,22 @@
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include "UnrealPropertySerialiser.h" #include "UnrealProperty.h"
#include "../Types/VectorStructProperty.h" #include "../Types/VectorStructProperty.h"
class VectorPropertySerialiser : public UnrealPropertySerialiser<VectorStructProperty> { namespace Gvas { namespace Serialisers {
class VectorProperty : public UnrealProperty<Types::VectorStructProperty> {
public: public:
using ptr = Containers::Pointer<VectorPropertySerialiser>; using ptr = Containers::Pointer<VectorProperty>;
private: private:
UnrealPropertyBase::ptr deserialiseProperty(Containers::StringView name, Containers::StringView type, auto deserialiseProperty(Containers::StringView name, Containers::StringView type, std::size_t value_length,
std::size_t value_length, BinaryReader& reader, BinaryReader& reader, PropertySerialiser& serialiser)
PropertySerialiser& serialiser) override; -> Types::UnrealPropertyBase::ptr override;
bool serialiseProperty(UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer, bool serialiseProperty(Types::UnrealPropertyBase::ptr& prop, std::size_t& bytes_written, BinaryWriter& writer,
PropertySerialiser& serialiser) override; PropertySerialiser& serialiser) override;
}; };
}}

View file

@ -23,6 +23,8 @@
#include "UnrealPropertyBase.h" #include "UnrealPropertyBase.h"
namespace Gvas { namespace Types {
struct ArrayProperty : public UnrealPropertyBase { struct ArrayProperty : public UnrealPropertyBase {
using ptr = Containers::Pointer<ArrayProperty>; using ptr = Containers::Pointer<ArrayProperty>;
@ -44,3 +46,5 @@ struct ArrayProperty : public UnrealPropertyBase {
Containers::String itemType; Containers::String itemType;
Containers::Array<UnrealPropertyBase::ptr> items; Containers::Array<UnrealPropertyBase::ptr> items;
}; };
}}

View file

@ -23,6 +23,8 @@
using namespace Corrade; using namespace Corrade;
namespace Gvas { namespace Types {
struct BoolProperty : public UnrealProperty<bool> { struct BoolProperty : public UnrealProperty<bool> {
using ptr = Containers::Pointer<BoolProperty>; using ptr = Containers::Pointer<BoolProperty>;
@ -31,3 +33,5 @@ struct BoolProperty : public UnrealProperty<bool> {
propertyType = "BoolProperty"_s; propertyType = "BoolProperty"_s;
} }
}; };
}}

View file

@ -25,6 +25,8 @@
using namespace Corrade; using namespace Corrade;
namespace Gvas { namespace Types {
struct ByteProperty : public UnrealProperty<Containers::Array<char>> { struct ByteProperty : public UnrealProperty<Containers::Array<char>> {
using ptr = Containers::Pointer<ByteProperty>; using ptr = Containers::Pointer<ByteProperty>;
@ -33,7 +35,10 @@ struct ByteProperty : public UnrealProperty<Containers::Array<char>> {
propertyType = "ByteProperty"_s; propertyType = "ByteProperty"_s;
} }
// For some reason, M.A.S.S. Builder stores EnumProperties as ByteProperties. Ugh... // M.A.S.S. Builder stores EnumProperties as ByteProperties.
// I wonder if it's a general UE thing and agc93/unsave was just wrong.
Containers::String enumType; Containers::String enumType;
Containers::String enumValue; Containers::String enumValue;
}; };
}}

View file

@ -23,6 +23,8 @@
using namespace Corrade; using namespace Corrade;
namespace Gvas { namespace Types {
struct ColourStructProperty : public StructProperty { struct ColourStructProperty : public StructProperty {
using ptr = Containers::Pointer<ColourStructProperty>; using ptr = Containers::Pointer<ColourStructProperty>;
ColourStructProperty() { ColourStructProperty() {
@ -31,3 +33,5 @@ struct ColourStructProperty : public StructProperty {
} }
float r = 0.0f, g = 0.0f, b = 0.0f, a = 0.0f; float r = 0.0f, g = 0.0f, b = 0.0f, a = 0.0f;
}; };
}}

View file

@ -23,6 +23,8 @@
using namespace Corrade; using namespace Corrade;
namespace Gvas { namespace Types {
struct DateTimeStructProperty : public StructProperty { struct DateTimeStructProperty : public StructProperty {
using ptr = Containers::Pointer<DateTimeStructProperty>; using ptr = Containers::Pointer<DateTimeStructProperty>;
@ -33,3 +35,5 @@ struct DateTimeStructProperty : public StructProperty {
std::int64_t timestamp = 0; std::int64_t timestamp = 0;
}; };
}}

View file

@ -24,6 +24,8 @@
using namespace Corrade; using namespace Corrade;
namespace Gvas { namespace Types {
struct EnumProperty : public UnrealProperty<Containers::String> { struct EnumProperty : public UnrealProperty<Containers::String> {
using ptr = Containers::Pointer<EnumProperty>; using ptr = Containers::Pointer<EnumProperty>;
@ -34,3 +36,5 @@ struct EnumProperty : public UnrealProperty<Containers::String> {
Containers::String enumType; Containers::String enumType;
}; };
}}

View file

@ -23,6 +23,8 @@
using namespace Corrade; using namespace Corrade;
namespace Gvas { namespace Types {
struct FloatProperty : public UnrealProperty<float> { struct FloatProperty : public UnrealProperty<float> {
using ptr = Containers::Pointer<FloatProperty>; using ptr = Containers::Pointer<FloatProperty>;
@ -31,3 +33,5 @@ struct FloatProperty : public UnrealProperty<float> {
propertyType = "FloatProperty"_s; propertyType = "FloatProperty"_s;
} }
}; };
}}

View file

@ -26,6 +26,8 @@
using namespace Corrade; using namespace Corrade;
namespace Gvas { namespace Types {
struct GenericStructProperty : public StructProperty { struct GenericStructProperty : public StructProperty {
using ptr = Containers::Pointer<GenericStructProperty>; using ptr = Containers::Pointer<GenericStructProperty>;
@ -53,3 +55,5 @@ struct GenericStructProperty : public StructProperty {
Containers::Array<UnrealPropertyBase::ptr> properties; Containers::Array<UnrealPropertyBase::ptr> properties;
}; };
}}

View file

@ -24,6 +24,8 @@
using namespace Corrade; using namespace Corrade;
namespace Gvas { namespace Types {
struct GuidStructProperty : public StructProperty { struct GuidStructProperty : public StructProperty {
using ptr = Containers::Pointer<GuidStructProperty>; using ptr = Containers::Pointer<GuidStructProperty>;
@ -34,3 +36,5 @@ struct GuidStructProperty : public StructProperty {
Containers::StaticArray<16, char> guid{ValueInit}; Containers::StaticArray<16, char> guid{ValueInit};
}; };
}}

View file

@ -23,6 +23,8 @@
using namespace Corrade; using namespace Corrade;
namespace Gvas { namespace Types {
struct IntProperty : public UnrealProperty<std::int32_t> { struct IntProperty : public UnrealProperty<std::int32_t> {
using ptr = Containers::Pointer<IntProperty>; using ptr = Containers::Pointer<IntProperty>;
@ -31,3 +33,5 @@ struct IntProperty : public UnrealProperty<std::int32_t> {
propertyType = "IntProperty"_s; propertyType = "IntProperty"_s;
} }
}; };
}}

View file

@ -16,6 +16,7 @@
// 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 <Corrade/Containers/Array.h>
#include <Corrade/Containers/Pointer.h> #include <Corrade/Containers/Pointer.h>
#include <Corrade/Containers/String.h> #include <Corrade/Containers/String.h>
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
@ -24,6 +25,8 @@
using namespace Corrade; using namespace Corrade;
namespace Gvas { namespace Types {
struct MapProperty : public UnrealPropertyBase { struct MapProperty : public UnrealPropertyBase {
using ptr = Containers::Pointer<MapProperty>; using ptr = Containers::Pointer<MapProperty>;
@ -42,3 +45,5 @@ struct MapProperty : public UnrealPropertyBase {
Containers::Array<KeyValuePair> map; Containers::Array<KeyValuePair> map;
}; };
}}

View file

@ -23,6 +23,8 @@
using namespace Corrade; using namespace Corrade;
namespace Gvas { namespace Types {
struct NoneProperty : UnrealPropertyBase { struct NoneProperty : UnrealPropertyBase {
using ptr = Containers::Pointer<NoneProperty>; using ptr = Containers::Pointer<NoneProperty>;
@ -32,3 +34,5 @@ struct NoneProperty : UnrealPropertyBase {
propertyType = "NoneProperty"_s; propertyType = "NoneProperty"_s;
} }
}; };
}}

View file

@ -23,6 +23,8 @@
using namespace Corrade; using namespace Corrade;
namespace Gvas { namespace Types {
struct ResourceItemValue : public StructProperty { struct ResourceItemValue : public StructProperty {
using ptr = Containers::Pointer<ResourceItemValue>; using ptr = Containers::Pointer<ResourceItemValue>;
@ -38,3 +40,5 @@ struct ResourceItemValue : public StructProperty {
std::int32_t id = 0; std::int32_t id = 0;
std::int32_t quantity = 0; std::int32_t quantity = 0;
}; };
}}

View file

@ -23,6 +23,8 @@
using namespace Corrade; using namespace Corrade;
namespace Gvas { namespace Types {
struct RotatorStructProperty : public StructProperty { struct RotatorStructProperty : public StructProperty {
using ptr = Containers::Pointer<RotatorStructProperty>; using ptr = Containers::Pointer<RotatorStructProperty>;
@ -33,3 +35,5 @@ struct RotatorStructProperty : public StructProperty {
float x = 0.0f, y = 0.0f, z = 0.0f; float x = 0.0f, y = 0.0f, z = 0.0f;
}; };
}}

View file

@ -25,6 +25,8 @@
using namespace Corrade; using namespace Corrade;
namespace Gvas { namespace Types {
struct SetProperty : public UnrealPropertyBase { struct SetProperty : public UnrealPropertyBase {
using ptr = Containers::Pointer<SetProperty>; using ptr = Containers::Pointer<SetProperty>;
@ -44,3 +46,5 @@ struct SetProperty : public UnrealPropertyBase {
Containers::String itemType; Containers::String itemType;
Containers::Array<UnrealPropertyBase::ptr> items; Containers::Array<UnrealPropertyBase::ptr> items;
}; };
}}

View file

@ -25,6 +25,8 @@
using namespace Corrade; using namespace Corrade;
using namespace Containers::Literals; using namespace Containers::Literals;
namespace Gvas { namespace Types {
struct StringProperty : public UnrealProperty<Containers::String> { struct StringProperty : public UnrealProperty<Containers::String> {
using ptr = Containers::Pointer<StringProperty>; using ptr = Containers::Pointer<StringProperty>;
@ -32,3 +34,5 @@ struct StringProperty : public UnrealProperty<Containers::String> {
propertyType = type; propertyType = type;
} }
}; };
}}

View file

@ -25,6 +25,8 @@
using namespace Corrade; using namespace Corrade;
namespace Gvas { namespace Types {
struct StructProperty : public UnrealPropertyBase { struct StructProperty : public UnrealPropertyBase {
using ptr = Containers::Pointer<StructProperty>; using ptr = Containers::Pointer<StructProperty>;
@ -36,3 +38,5 @@ struct StructProperty : public UnrealPropertyBase {
Containers::StaticArray<16, char> structGuid{ValueInit}; Containers::StaticArray<16, char> structGuid{ValueInit};
Containers::String structType; Containers::String structType;
}; };
}}

View file

@ -25,6 +25,8 @@
using namespace Corrade; using namespace Corrade;
namespace Gvas { namespace Types {
struct TextProperty : public UnrealProperty<Containers::String> { struct TextProperty : public UnrealProperty<Containers::String> {
using ptr = Containers::Pointer<TextProperty>; using ptr = Containers::Pointer<TextProperty>;
@ -37,3 +39,5 @@ struct TextProperty : public UnrealProperty<Containers::String> {
char id = 0; char id = 0;
Containers::Array<Containers::String> data; Containers::Array<Containers::String> data;
}; };
}}

View file

@ -16,18 +16,30 @@
// 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 <Corrade/Utility/Debug.h> namespace Gvas { namespace Types {
struct ArrayProperty;
struct SetProperty;
struct GenericStructProperty;
struct StructProperty;
struct UnrealPropertyBase; struct UnrealPropertyBase;
template<typename T>
struct UnrealProperty;
struct ArrayProperty;
struct BoolProperty;
struct ByteProperty;
struct ColourStructProperty;
struct DateTimeStructProperty;
struct EnumProperty;
struct FloatProperty;
struct GenericStructProperty;
struct GuidStructProperty;
struct IntProperty;
struct MapProperty;
struct NoneProperty;
struct ResourceItemValue;
struct RotatorStructProperty;
struct SetProperty;
struct StringProperty;
struct StructProperty;
struct TextProperty;
struct Vector2DStructProperty;
struct VectorStructProperty;
using namespace Corrade; }}
Utility::Debug& operator<<(Utility::Debug& debug, const ArrayProperty* prop);
Utility::Debug& operator<<(Utility::Debug& debug, const SetProperty* prop);
Utility::Debug& operator<<(Utility::Debug& debug, const GenericStructProperty* prop);
Utility::Debug& operator<<(Utility::Debug& debug, const StructProperty* prop);
Utility::Debug& operator<<(Utility::Debug& debug, const UnrealPropertyBase* prop);

View file

@ -22,9 +22,13 @@
using namespace Corrade; using namespace Corrade;
namespace Gvas { namespace Types {
template<typename T> template<typename T>
struct UnrealProperty : public UnrealPropertyBase { struct UnrealProperty : public UnrealPropertyBase {
using ptr = Containers::Pointer<UnrealProperty<T>>; using ptr = Containers::Pointer<UnrealProperty<T>>;
T value; T value;
}; };
}}

View file

@ -24,6 +24,8 @@
using namespace Corrade; using namespace Corrade;
namespace Gvas { namespace Types {
struct UnrealPropertyBase { struct UnrealPropertyBase {
using ptr = Containers::Pointer<UnrealPropertyBase>; using ptr = Containers::Pointer<UnrealPropertyBase>;
@ -33,3 +35,5 @@ struct UnrealPropertyBase {
Containers::String propertyType; Containers::String propertyType;
std::size_t valueLength = 0; std::size_t valueLength = 0;
}; };
}}

View file

@ -23,6 +23,8 @@
using namespace Corrade; using namespace Corrade;
namespace Gvas { namespace Types {
struct Vector2DStructProperty : public StructProperty { struct Vector2DStructProperty : public StructProperty {
using ptr = Containers::Pointer<Vector2DStructProperty>; using ptr = Containers::Pointer<Vector2DStructProperty>;
@ -33,3 +35,5 @@ struct Vector2DStructProperty : public StructProperty {
float x = 0.0f, y = 0.0f; float x = 0.0f, y = 0.0f;
}; };
}}

View file

@ -23,6 +23,8 @@
using namespace Corrade; using namespace Corrade;
namespace Gvas { namespace Types {
struct VectorStructProperty : public StructProperty { struct VectorStructProperty : public StructProperty {
using ptr = Containers::Pointer<VectorStructProperty>; using ptr = Containers::Pointer<VectorStructProperty>;
@ -33,3 +35,5 @@ struct VectorStructProperty : public StructProperty {
float x = 0.0f, y = 0.0f, z = 0.0f; float x = 0.0f, y = 0.0f, z = 0.0f;
}; };
}}

View file

@ -45,7 +45,7 @@ class Logger {
Logger(Logger&&) = delete; Logger(Logger&&) = delete;
Logger& operator=(Logger&&) = delete; Logger& operator=(Logger&&) = delete;
static Logger& instance(); static auto instance() -> Logger&;
void initialise(); void initialise();
@ -69,7 +69,7 @@ class Logger {
std::mutex _logMutex{}; std::mutex _logMutex{};
}; };
Logger& logger(); auto logger() -> Logger&;
#define LOG(entry_type, message) logger().lockMutex(); \ #define LOG(entry_type, message) logger().lockMutex(); \
logger().log(EntryType::entry_type, \ logger().log(EntryType::entry_type, \

View file

@ -28,7 +28,7 @@ class MagnumLogBuffer : public std::stringbuf {
~MagnumLogBuffer() override; ~MagnumLogBuffer() override;
private: private:
int sync() override; auto sync() -> int override;
EntryType _type; EntryType _type;
}; };

File diff suppressed because it is too large Load diff

View file

@ -25,6 +25,8 @@
using namespace Corrade; using namespace Corrade;
using namespace Containers::Literals; using namespace Containers::Literals;
namespace mbst { namespace GameData {
struct ArmourSet { struct ArmourSet {
Containers::StringView name; Containers::StringView name;
bool neck_compatible; bool neck_compatible;
@ -55,3 +57,5 @@ static const std::map<std::int32_t, ArmourSet> armour_sets {
{26, {"Axial Core S-Type"_s, false}}, {26, {"Axial Core S-Type"_s, false}},
{27, {"Axial Core X-Type"_s, false}}, {27, {"Axial Core X-Type"_s, false}},
}; };
}}

View file

@ -23,36 +23,40 @@
using namespace Corrade; using namespace Corrade;
using namespace Containers::Literals; using namespace Containers::Literals;
namespace mbst { namespace GameData {
static const std::map<std::int32_t, Containers::StringView> mission_id_map {{ static const std::map<std::int32_t, Containers::StringView> mission_id_map {{
// Story missions // Story missions
{0x0064, "Mission 1 - Training"_s}, {100, "Mission 1 - Training"_s},
{0x0065, "Mission 2 - Patrol Operation"_s}, {101, "Mission 2 - Patrol Operation"_s},
{0x0066, "Mission 3 - Fusion Cells in the Snow"_s}, {102, "Mission 3 - Fusion Cells in the Snow"_s},
{0x0067, "Mission 4 - Earning Changes"_s}, {103, "Mission 4 - Earning Changes"_s},
{0x0068, "Mission 5 - Unexpected Coordination"_s}, {104, "Mission 5 - Unexpected Coordination"_s},
{0x0069, "Mission 6 - Empowering Void"_s}, {105, "Mission 6 - Empowering Void"_s},
{0x006A, "Mission 7 - Logisitics Obstacles"_s}, {106, "Mission 7 - Logisitics Obstacles"_s},
{0x006B, "Mission 8 - Wrath of the Wastelands"_s}, {107, "Mission 8 - Wrath of the Wastelands"_s},
{0x006C, "Mission 9 - Suspicious Originator"_s}, {108, "Mission 9 - Suspicious Originator"_s},
{0x006D, "Mission 10 - Researchers Data Recovery"_s}, {109, "Mission 10 - Researchers Data Recovery"_s},
{0x006E, "Mission 11 - Tempestuous Sector"_s}, {110, "Mission 11 - Tempestuous Sector"_s},
{0x006F, "Mission 12 - Clashes of Metal"_s}, {111, "Mission 12 - Clashes of Metal"_s},
{0x0070, "Mission 13 - The Sandstorm Glutton"_s}, {112, "Mission 13 - The Sandstorm Glutton"_s},
{0x0071, "Mission 14 - An Icy Investigation"_s}, {113, "Mission 14 - An Icy Investigation"_s},
{0x0072, "Mission 15 - Outposts Line of Defense"_s}, {114, "Mission 15 - Outposts Line of Defense"_s},
{0x0073, "Mission 16 - Hidden in the Pass"_s}, {115, "Mission 16 - Hidden in the Pass"_s},
{0x0074, "Mission 17 - Homebase Security"_s}, {116, "Mission 17 - Homebase Security"_s},
// Hunting grounds // Hunting grounds
{0x00C8, "Hunt 1 - Desert Pathway Safety"_s}, {200, "Hunt 1 - Desert Pathway Safety"_s},
{0x00C9, "Hunt 2 - Snowfield Custodian"_s}, {201, "Hunt 2 - Snowfield Custodian"_s},
{0x00CA, "Hunt 3 - Abandoned Valley Raid"_s}, {202, "Hunt 3 - Abandoned Valley Raid"_s},
{0x00CB, "Hunt 4 - Depths of the Machineries"_s}, {203, "Hunt 4 - Depths of the Machineries"_s},
{0x00CC, "Hunt 5 - Crater Crashers"_s}, {204, "Hunt 5 - Crater Crashers"_s},
{0x00CD, "Hunt 6 - Prototype Performance Tests"_s}, {205, "Hunt 6 - Prototype Performance Tests"_s},
// Challenges // Challenges
{0x012C, "Challenge 1 - Redline Battlefront"_s}, {300, "Challenge 1 - Redline Battlefront"_s},
{0x0140, "Challenge 2 - Void Convergence"_s}, {320, "Challenge 2 - Void Convergence"_s},
{0x0190, "Challenge 3 - Gates of Ascension"_s} {400, "Challenge 3 - Gates of Ascension"_s}
}}; }};
}}

View file

@ -22,6 +22,8 @@
using namespace Corrade; using namespace Corrade;
using namespace Containers::Literals; using namespace Containers::Literals;
namespace mbst { namespace GameData {
struct StoryProgressPoint { struct StoryProgressPoint {
std::int32_t id{}; std::int32_t id{};
Containers::StringView chapter = nullptr; Containers::StringView chapter = nullptr;
@ -109,3 +111,5 @@ static const Corrade::Containers::Array<StoryProgressPoint> story_progress
{0x070A, "Chapter 3"_s, "Got hunt 6 briefing"_s, "After mission 17"_s}, {0x070A, "Chapter 3"_s, "Got hunt 6 briefing"_s, "After mission 17"_s},
} }
}; };
}}

View file

@ -25,6 +25,8 @@
using namespace Corrade; using namespace Corrade;
using namespace Containers::Literals; using namespace Containers::Literals;
namespace mbst { namespace GameData {
extern const std::map<std::int32_t, Containers::StringView> style_names extern const std::map<std::int32_t, Containers::StringView> style_names
#ifdef STYLENAMES_DEFINITION #ifdef STYLENAMES_DEFINITION
{ {
@ -193,3 +195,5 @@ extern const std::map<std::int32_t, Containers::StringView> style_names
} }
#endif #endif
; ;
}}

View file

@ -25,6 +25,8 @@ using namespace Corrade;
using namespace Containers::Literals; using namespace Containers::Literals;
namespace mbst { namespace GameData {
// region Melee // region Melee
static const std::map<std::int32_t, Containers::StringView> melee_grips { static const std::map<std::int32_t, Containers::StringView> melee_grips {
{0, "Combat Grip (1H)"_s}, {0, "Combat Grip (1H)"_s},
@ -430,3 +432,5 @@ static const std::map<std::int32_t, Containers::StringView> elauncher_pods {
{399, "P Base EPod (Photon)"_s}, {399, "P Base EPod (Photon)"_s},
}; };
// endregion // endregion
}}

Some files were not shown because too many files have changed in this diff Show more