Compare commits
128 commits
f323215844
...
f522d20dd4
Author | SHA1 | Date | |
---|---|---|---|
f522d20dd4 | |||
6208825aa6 | |||
572585e648 | |||
de2ba9ce7f | |||
d0ddc73852 | |||
a1c17b7138 | |||
350ad59f8e | |||
883d5d3f41 | |||
77d7eaefad | |||
82170b3078 | |||
88abf91047 | |||
955ec010b8 | |||
7cb9ea28b2 | |||
975f471a68 | |||
76210e147a | |||
5e06c48492 | |||
2ff32c4c78 | |||
4000421a8c | |||
8f1e3668a3 | |||
a6c0614979 | |||
2cabe6a3ba | |||
afc163f344 | |||
353a71d8ab | |||
bbc40d7c93 | |||
28db82c8a9 | |||
9f324c30fd | |||
41cd92352d | |||
940fe3feee | |||
d74a7bc219 | |||
51faed7210 | |||
8fb837bfc0 | |||
0ac1e759ca | |||
a4045e8e9b | |||
1ec4522baf | |||
13d09e4aa0 | |||
ed0c4a73bb | |||
8102d1d83a | |||
9a9c08391a | |||
51602c713a | |||
1621a4dbd5 | |||
7fb269f862 | |||
1378676bbc | |||
96768c1aab | |||
bd05a98820 | |||
7059295cb3 | |||
065e63f27c | |||
a05f3eeed0 | |||
321e8feed0 | |||
c6de9c1940 | |||
fe0db983ce | |||
bd8ff47f1e | |||
83fa5822bf | |||
8d87cdd619 | |||
0900f92b9f | |||
af71806e13 | |||
247578a386 | |||
4ca6f62d9b | |||
e461d5a505 | |||
d79debe69f | |||
83fe02a8dc | |||
7e452db3a4 | |||
80bb85c0d8 | |||
4df90efd67 | |||
b92c37e4b6 | |||
dd460b4313 | |||
05a2b1cfb0 | |||
8fedbdd4e5 | |||
3ac5288f12 | |||
8bae723018 | |||
3714162b50 | |||
a22aa6f7ae | |||
d03e75a8e9 | |||
4429e581f3 | |||
2d0d5817f2 | |||
bfe9a2c3a8 | |||
8c81b7811b | |||
0904384e0d | |||
6f3da0b4a7 | |||
19c00a3ce3 | |||
79762e176e | |||
b5b5b3b38c | |||
e4cfd3834a | |||
e77cce5b42 | |||
18aa7f659e | |||
1612e4372b | |||
b377e0de6c | |||
0a438a4d72 | |||
e839d1c19b | |||
5689ec6c1a | |||
c2d0fbd941 | |||
2b2320ae0a | |||
10368e09db | |||
bd255ef8d5 | |||
911e18fc0a | |||
0c257bcfa6 | |||
9bc4aaf66b | |||
79e3193309 | |||
76e36791d7 | |||
50a7b1d7f0 | |||
1caa472833 | |||
d3d065c945 | |||
b8b156a724 | |||
9c1aeb753e | |||
0006c90a21 | |||
0826d4aede | |||
b3220ca8e1 | |||
48210c7186 | |||
f500e982e6 | |||
2e1949ed5d | |||
10becfdc31 | |||
f286ec0633 | |||
ce29d6174c | |||
de07b760d0 | |||
66d96bd893 | |||
083b60aac4 | |||
918b26ab5e | |||
32bc179120 | |||
c64684b34c | |||
40840e3128 | |||
c7c379c419 | |||
a9a5bfb2af | |||
5f4576a2bc | |||
f3318e0ed1 | |||
7fcf8b518e | |||
69021eacdf | |||
bd6e55826d | |||
597e9dfe98 | |||
4cdd1b35ec |
125 changed files with 8816 additions and 1332 deletions
|
@ -1,5 +1,5 @@
|
||||||
# MassBuilderSaveTool
|
# MassBuilderSaveTool
|
||||||
# Copyright (C) 2021 Guillaume Jacquemin
|
# Copyright (C) 2021-2022 Guillaume Jacquemin
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# MassBuilderSaveTool
|
# MassBuilderSaveTool
|
||||||
# Copyright (C) 2021 Guillaume Jacquemin
|
# Copyright (C) 2021-2022 Guillaume Jacquemin
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -18,7 +18,7 @@ set(CMAKE_CXX_STANDARD 14)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
set(SAVETOOL_PROJECT_VERSION 1.2.0)
|
set(SAVETOOL_PROJECT_VERSION 1.3.0-pre)
|
||||||
|
|
||||||
find_package(Corrade REQUIRED Main Containers Utility Interconnect)
|
find_package(Corrade REQUIRED Main Containers Utility Interconnect)
|
||||||
find_package(Magnum REQUIRED GL Sdl2Application)
|
find_package(Magnum REQUIRED GL Sdl2Application)
|
||||||
|
@ -28,6 +28,86 @@ set_directory_properties(PROPERTIES CORRADE_USE_PEDANTIC_FLAGS ON)
|
||||||
|
|
||||||
corrade_add_resource(Assets assets.conf)
|
corrade_add_resource(Assets assets.conf)
|
||||||
|
|
||||||
|
add_library(UESaveFile STATIC EXCLUDE_FROM_ALL
|
||||||
|
UESaveFile/Serialisers/AbstractUnrealCollectionPropertySerialiser.h
|
||||||
|
UESaveFile/Serialisers/AbstractUnrealPropertySerialiser.h
|
||||||
|
UESaveFile/Serialisers/AbstractUnrealStructSerialiser.h
|
||||||
|
UESaveFile/Serialisers/ArrayPropertySerialiser.h
|
||||||
|
UESaveFile/Serialisers/ArrayPropertySerialiser.cpp
|
||||||
|
UESaveFile/Serialisers/BoolPropertySerialiser.h
|
||||||
|
UESaveFile/Serialisers/BoolPropertySerialiser.cpp
|
||||||
|
UESaveFile/Serialisers/BytePropertySerialiser.h
|
||||||
|
UESaveFile/Serialisers/BytePropertySerialiser.cpp
|
||||||
|
UESaveFile/Serialisers/ColourPropertySerialiser.h
|
||||||
|
UESaveFile/Serialisers/ColourPropertySerialiser.cpp
|
||||||
|
UESaveFile/Serialisers/DateTimePropertySerialiser.h
|
||||||
|
UESaveFile/Serialisers/DateTimePropertySerialiser.cpp
|
||||||
|
UESaveFile/Serialisers/EnumPropertySerialiser.h
|
||||||
|
UESaveFile/Serialisers/EnumPropertySerialiser.cpp
|
||||||
|
UESaveFile/Serialisers/FloatPropertySerialiser.h
|
||||||
|
UESaveFile/Serialisers/FloatPropertySerialiser.cpp
|
||||||
|
UESaveFile/Serialisers/GuidPropertySerialiser.h
|
||||||
|
UESaveFile/Serialisers/GuidPropertySerialiser.cpp
|
||||||
|
UESaveFile/Serialisers/IntPropertySerialiser.h
|
||||||
|
UESaveFile/Serialisers/IntPropertySerialiser.cpp
|
||||||
|
UESaveFile/Serialisers/MapPropertySerialiser.h
|
||||||
|
UESaveFile/Serialisers/MapPropertySerialiser.cpp
|
||||||
|
UESaveFile/Serialisers/ResourcePropertySerialiser.h
|
||||||
|
UESaveFile/Serialisers/ResourcePropertySerialiser.cpp
|
||||||
|
UESaveFile/Serialisers/RotatorPropertySerialiser.h
|
||||||
|
UESaveFile/Serialisers/RotatorPropertySerialiser.cpp
|
||||||
|
UESaveFile/Serialisers/StringPropertySerialiser.h
|
||||||
|
UESaveFile/Serialisers/StringPropertySerialiser.cpp
|
||||||
|
UESaveFile/Serialisers/SetPropertySerialiser.h
|
||||||
|
UESaveFile/Serialisers/SetPropertySerialiser.cpp
|
||||||
|
UESaveFile/Serialisers/StructSerialiser.h
|
||||||
|
UESaveFile/Serialisers/StructSerialiser.cpp
|
||||||
|
UESaveFile/Serialisers/TextPropertySerialiser.h
|
||||||
|
UESaveFile/Serialisers/TextPropertySerialiser.cpp
|
||||||
|
UESaveFile/Serialisers/UnrealPropertySerialiser.h
|
||||||
|
UESaveFile/Serialisers/VectorPropertySerialiser.h
|
||||||
|
UESaveFile/Serialisers/VectorPropertySerialiser.cpp
|
||||||
|
UESaveFile/Serialisers/Vector2DPropertySerialiser.h
|
||||||
|
UESaveFile/Serialisers/Vector2DPropertySerialiser.cpp
|
||||||
|
|
||||||
|
UESaveFile/Types/ArrayProperty.h
|
||||||
|
UESaveFile/Types/BoolProperty.h
|
||||||
|
UESaveFile/Types/ByteProperty.h
|
||||||
|
UESaveFile/Types/ColourStructProperty.h
|
||||||
|
UESaveFile/Types/DateTimeStructProperty.h
|
||||||
|
UESaveFile/Types/EnumProperty.h
|
||||||
|
UESaveFile/Types/FloatProperty.h
|
||||||
|
UESaveFile/Types/GenericStructProperty.h
|
||||||
|
UESaveFile/Types/GuidStructProperty.h
|
||||||
|
UESaveFile/Types/IntProperty.h
|
||||||
|
UESaveFile/Types/MapProperty.h
|
||||||
|
UESaveFile/Types/NoneProperty.h
|
||||||
|
UESaveFile/Types/RotatorStructProperty.h
|
||||||
|
UESaveFile/Types/SetProperty.h
|
||||||
|
UESaveFile/Types/StringProperty.h
|
||||||
|
UESaveFile/Types/StructProperty.h
|
||||||
|
UESaveFile/Types/ResourceItemValue.h
|
||||||
|
UESaveFile/Types/TextProperty.h
|
||||||
|
UESaveFile/Types/UnrealProperty.h
|
||||||
|
UESaveFile/Types/UnrealPropertyBase.h
|
||||||
|
UESaveFile/Types/VectorStructProperty.h
|
||||||
|
|
||||||
|
UESaveFile/Debug.h
|
||||||
|
UESaveFile/Debug.cpp
|
||||||
|
UESaveFile/UESaveFile.h
|
||||||
|
UESaveFile/UESaveFile.cpp
|
||||||
|
UESaveFile/BinaryReader.h
|
||||||
|
UESaveFile/BinaryReader.cpp
|
||||||
|
UESaveFile/BinaryWriter.h
|
||||||
|
UESaveFile/BinaryWriter.cpp
|
||||||
|
UESaveFile/PropertySerialiser.h
|
||||||
|
UESaveFile/PropertySerialiser.cpp)
|
||||||
|
|
||||||
|
target_link_libraries(UESaveFile PRIVATE
|
||||||
|
Corrade::Containers
|
||||||
|
Corrade::Utility
|
||||||
|
Magnum::Magnum)
|
||||||
|
|
||||||
add_executable(MassBuilderSaveTool WIN32
|
add_executable(MassBuilderSaveTool WIN32
|
||||||
main.cpp
|
main.cpp
|
||||||
SaveTool/SaveTool.h
|
SaveTool/SaveTool.h
|
||||||
|
@ -35,19 +115,40 @@ add_executable(MassBuilderSaveTool WIN32
|
||||||
SaveTool/SaveTool_drawAbout.cpp
|
SaveTool/SaveTool_drawAbout.cpp
|
||||||
SaveTool/SaveTool_drawMainMenu.cpp
|
SaveTool/SaveTool_drawMainMenu.cpp
|
||||||
SaveTool/SaveTool_MainManager.cpp
|
SaveTool/SaveTool_MainManager.cpp
|
||||||
|
SaveTool/SaveTool_MassViewer.cpp
|
||||||
|
SaveTool/SaveTool_MassViewer_Frame.cpp
|
||||||
|
SaveTool/SaveTool_MassViewer_Armour.cpp
|
||||||
|
SaveTool/SaveTool_MassViewer_Weapons.cpp
|
||||||
SaveTool/SaveTool_ProfileManager.cpp
|
SaveTool/SaveTool_ProfileManager.cpp
|
||||||
ProfileManager/ProfileManager.h
|
ProfileManager/ProfileManager.h
|
||||||
ProfileManager/ProfileManager.cpp
|
ProfileManager/ProfileManager.cpp
|
||||||
Profile/Profile.h
|
Profile/Profile.h
|
||||||
Profile/Profile.cpp
|
Profile/Profile.cpp
|
||||||
|
Profile/ResourceIDs.h
|
||||||
MassManager/MassManager.h
|
MassManager/MassManager.h
|
||||||
MassManager/MassManager.cpp
|
MassManager/MassManager.cpp
|
||||||
|
Mass/Accessory.h
|
||||||
|
Mass/ArmourPart.h
|
||||||
|
Mass/CustomStyle.h
|
||||||
|
Mass/Decal.h
|
||||||
|
Mass/Joints.h
|
||||||
Mass/Mass.h
|
Mass/Mass.h
|
||||||
Mass/Mass.cpp
|
Mass/Mass.cpp
|
||||||
|
Mass/Weapon.h
|
||||||
|
Mass/Weapon.cpp
|
||||||
|
Mass/WeaponPart.h
|
||||||
|
Maps/Accessories.h
|
||||||
|
Maps/ArmourSets.h
|
||||||
|
Maps/ArmourSlots.hpp
|
||||||
|
Maps/DamageTypes.hpp
|
||||||
|
Maps/EffectColourModes.hpp
|
||||||
Maps/LastMissionId.h
|
Maps/LastMissionId.h
|
||||||
Maps/StoryProgress.h
|
Maps/StoryProgress.h
|
||||||
|
Maps/StyleNames.h
|
||||||
|
Maps/WeaponTypes.hpp
|
||||||
ToastQueue/ToastQueue.h
|
ToastQueue/ToastQueue.h
|
||||||
ToastQueue/ToastQueue.cpp
|
ToastQueue/ToastQueue.cpp
|
||||||
|
Utilities/Crc32.h
|
||||||
FontAwesome/IconsFontAwesome5.h
|
FontAwesome/IconsFontAwesome5.h
|
||||||
FontAwesome/IconsFontAwesome5Brands.h
|
FontAwesome/IconsFontAwesome5Brands.h
|
||||||
resource.rc
|
resource.rc
|
||||||
|
@ -57,7 +158,7 @@ if(CMAKE_BUILD_TYPE STREQUAL Debug)
|
||||||
add_compile_definitions(SAVETOOL_DEBUG_BUILD)
|
add_compile_definitions(SAVETOOL_DEBUG_BUILD)
|
||||||
endif()
|
endif()
|
||||||
add_compile_definitions(SAVETOOL_VERSION="${SAVETOOL_PROJECT_VERSION}"
|
add_compile_definitions(SAVETOOL_VERSION="${SAVETOOL_PROJECT_VERSION}"
|
||||||
SAVETOOL_CODENAME="Cute Quindolia"
|
SAVETOOL_CODENAME="Dickish Cyclops"
|
||||||
SUPPORTED_GAME_VERSION="0.7.6")
|
SUPPORTED_GAME_VERSION="0.7.6")
|
||||||
|
|
||||||
if(CMAKE_BUILD_TYPE STREQUAL Release)
|
if(CMAKE_BUILD_TYPE STREQUAL Release)
|
||||||
|
@ -66,6 +167,10 @@ endif()
|
||||||
|
|
||||||
target_link_options(MassBuilderSaveTool PRIVATE -static -static-libgcc -static-libstdc++)
|
target_link_options(MassBuilderSaveTool PRIVATE -static -static-libgcc -static-libstdc++)
|
||||||
|
|
||||||
|
if(CMAKE_BUILD_TYPE STREQUAL Release)
|
||||||
|
target_link_options(MassBuilderSaveTool PRIVATE -Wl,-S)
|
||||||
|
endif()
|
||||||
|
|
||||||
target_link_libraries(MassBuilderSaveTool PRIVATE
|
target_link_libraries(MassBuilderSaveTool PRIVATE
|
||||||
Corrade::Containers
|
Corrade::Containers
|
||||||
Corrade::Utility
|
Corrade::Utility
|
||||||
|
@ -75,6 +180,7 @@ target_link_libraries(MassBuilderSaveTool PRIVATE
|
||||||
Magnum::GL
|
Magnum::GL
|
||||||
Magnum::Sdl2Application
|
Magnum::Sdl2Application
|
||||||
MagnumIntegration::ImGui
|
MagnumIntegration::ImGui
|
||||||
|
UESaveFile
|
||||||
efsw
|
efsw
|
||||||
zip
|
zip
|
||||||
cpr::cpr
|
cpr::cpr
|
||||||
|
|
74
src/Maps/Accessories.h
Normal file
74
src/Maps/Accessories.h
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 <map>
|
||||||
|
|
||||||
|
#include <Magnum/Types.h>
|
||||||
|
|
||||||
|
using namespace Magnum;
|
||||||
|
|
||||||
|
static const std::map<Int, const char*> accessories {
|
||||||
|
// Primitives
|
||||||
|
{1, "Cube (S)"},
|
||||||
|
{2, "Pentagon (S)"},
|
||||||
|
{3, "Hexagon (S)"},
|
||||||
|
{4, "Cylinder (S)"},
|
||||||
|
{5, "Sphere (S)"},
|
||||||
|
{6, "TriPyramid (S)"},
|
||||||
|
{7, "SquPyramid (S)"},
|
||||||
|
{8, "PenPyramid (S)"},
|
||||||
|
{9, "HexPyramid (S)"},
|
||||||
|
{10, "Cone (S)"},
|
||||||
|
{11, "SquStick (S)"},
|
||||||
|
{12, "PenStick (S)"},
|
||||||
|
{13, "HexStick (S)"},
|
||||||
|
{14, "CycStick (S)"},
|
||||||
|
{15, "Capsule (S)"},
|
||||||
|
{16, "Decal Pad 01 (S)"},
|
||||||
|
{17, "Decal Pad 02 (S)"},
|
||||||
|
{18, "Decal Pad 03 (S)"},
|
||||||
|
{19, "Decal Pad 04 (S)"},
|
||||||
|
{20, "Decal Pad 05 (S)"},
|
||||||
|
|
||||||
|
{51, "SquBevel (S)"},
|
||||||
|
{52, "TriBevel (S)"},
|
||||||
|
{53, "PenBevel (S)"},
|
||||||
|
{54, "HexBevel (S)"},
|
||||||
|
{55, "CycBevel (S)"},
|
||||||
|
{56, "RecBevel (S)"},
|
||||||
|
{57, "DaiBevel (S)"},
|
||||||
|
{58, "MonBevel (S)"},
|
||||||
|
{59, "CofBevel (S)"},
|
||||||
|
{60, "JevBevel (S)"},
|
||||||
|
{61, "SquEmboss (S)"},
|
||||||
|
{62, "TriEmboss (S)"},
|
||||||
|
{63, "PenEmboss (S)"},
|
||||||
|
{64, "HexEmboss (S)"},
|
||||||
|
{65, "CycEmboss (S)"},
|
||||||
|
{66, "RecEmboss (S)"},
|
||||||
|
{67, "DaiEmboss (S)"},
|
||||||
|
{68, "MonEmboss (S)"},
|
||||||
|
{69, "CofEmboss (S)"},
|
||||||
|
{70, "JevEmboss (S)"},
|
||||||
|
|
||||||
|
// Armours
|
||||||
|
|
||||||
|
// Components
|
||||||
|
|
||||||
|
// Connectors
|
||||||
|
};
|
51
src/Maps/ArmourSets.h
Normal file
51
src/Maps/ArmourSets.h
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 <map>
|
||||||
|
|
||||||
|
#include <Magnum/Types.h>
|
||||||
|
|
||||||
|
using namespace Magnum;
|
||||||
|
|
||||||
|
struct ArmourSet {
|
||||||
|
const char* name;
|
||||||
|
bool neck_compatible;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const std::map<Int, ArmourSet> armour_sets {
|
||||||
|
{-1, {"<unequipped>", true}},
|
||||||
|
{0, {"Vanguard", true}},
|
||||||
|
{1, {"Assault Mk.I", true}},
|
||||||
|
{2, {"Assault Mk.II", false}},
|
||||||
|
{3, {"Assault Mk.III", false}},
|
||||||
|
{7, {"Titan 001", true}},
|
||||||
|
{8, {"Titan 002", false}},
|
||||||
|
{9, {"Titan 003", false}},
|
||||||
|
{13, {"Blitz X", true}},
|
||||||
|
{14, {"Blitz EX", false}},
|
||||||
|
{15, {"Blitz EXS", false}},
|
||||||
|
{16, {"Kaiser S-R0", true}},
|
||||||
|
{17, {"Kaiser S-R1", false}},
|
||||||
|
{18, {"Kaiser S-R2", false}},
|
||||||
|
{19, {"Hammerfall MG-A", true}},
|
||||||
|
{20, {"Hammerfall MG-S", false}},
|
||||||
|
{21, {"Hammerfall MG-X", false}},
|
||||||
|
{22, {"Panzer S-UC", true}},
|
||||||
|
{23, {"Panzer L-UC", false}},
|
||||||
|
{24, {"Panzer H-UC", false}},
|
||||||
|
};
|
56
src/Maps/ArmourSlots.hpp
Normal file
56
src/Maps/ArmourSlots.hpp
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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/>.
|
||||||
|
|
||||||
|
#ifdef c
|
||||||
|
c(Face, "enuArmorSlots::NewEnumerator0", "Face")
|
||||||
|
c(UpperHead, "enuArmorSlots::NewEnumerator1", "Upper head")
|
||||||
|
c(LowerHead, "enuArmorSlots::NewEnumerator2", "Lower head")
|
||||||
|
c(Neck, "enuArmorSlots::NewEnumerator3", "Neck")
|
||||||
|
c(UpperBody, "enuArmorSlots::NewEnumerator4", "Upper body")
|
||||||
|
c(MiddleBody, "enuArmorSlots::NewEnumerator5", "Middle body")
|
||||||
|
c(LowerBody, "enuArmorSlots::NewEnumerator6", "Lower body")
|
||||||
|
c(FrontWaist, "enuArmorSlots::NewEnumerator7", "Front waist")
|
||||||
|
c(LeftFrontSkirt, "enuArmorSlots::NewEnumerator8", "Left front skirt")
|
||||||
|
c(RightFrontSkirt, "enuArmorSlots::NewEnumerator9", "Right front skirt")
|
||||||
|
c(LeftSideSkirt, "enuArmorSlots::NewEnumerator10", "Left side skirt")
|
||||||
|
c(RightSideSkirt, "enuArmorSlots::NewEnumerator11", "Right side skirt")
|
||||||
|
c(LeftBackSkirt, "enuArmorSlots::NewEnumerator12", "Left back skirt")
|
||||||
|
c(RightBackSkirt, "enuArmorSlots::NewEnumerator13", "Right back skirt")
|
||||||
|
c(BackWaist, "enuArmorSlots::NewEnumerator14", "Back waist")
|
||||||
|
c(LeftShoulder, "enuArmorSlots::NewEnumerator15", "Left shoulder")
|
||||||
|
c(RightShoulder, "enuArmorSlots::NewEnumerator16", "Right shoulder")
|
||||||
|
c(LeftUpperArm, "enuArmorSlots::NewEnumerator17", "Left upper arm")
|
||||||
|
c(RightUpperArm, "enuArmorSlots::NewEnumerator18", "Right upper arm")
|
||||||
|
c(LeftElbow, "enuArmorSlots::NewEnumerator19", "Left elbow")
|
||||||
|
c(RightElbow, "enuArmorSlots::NewEnumerator20", "Right elbow")
|
||||||
|
c(LeftLowerArm, "enuArmorSlots::NewEnumerator21", "Left lower arm")
|
||||||
|
c(RightLowerArm, "enuArmorSlots::NewEnumerator22", "Right lower arm")
|
||||||
|
c(Backpack, "enuArmorSlots::NewEnumerator23", "Backpack")
|
||||||
|
c(LeftHand, "enuArmorSlots::NewEnumerator24", "Left hand")
|
||||||
|
c(RightHand, "enuArmorSlots::NewEnumerator25", "Right hand")
|
||||||
|
c(LeftUpperLeg, "enuArmorSlots::NewEnumerator26", "Left upper leg")
|
||||||
|
c(RightUpperLeg, "enuArmorSlots::NewEnumerator27", "Right upper leg")
|
||||||
|
c(LeftKnee, "enuArmorSlots::NewEnumerator28", "Left knee")
|
||||||
|
c(RightKnee, "enuArmorSlots::NewEnumerator29", "Right knee")
|
||||||
|
c(LeftLowerLeg, "enuArmorSlots::NewEnumerator30", "Left lower leg")
|
||||||
|
c(RightLowerLeg, "enuArmorSlots::NewEnumerator31", "Right lower leg")
|
||||||
|
c(LeftAnkle, "enuArmorSlots::NewEnumerator32", "Left ankle")
|
||||||
|
c(RightAnkle, "enuArmorSlots::NewEnumerator33", "Right ankle")
|
||||||
|
c(LeftHeel, "enuArmorSlots::NewEnumerator34", "Left heel")
|
||||||
|
c(RightHeel, "enuArmorSlots::NewEnumerator35", "Right heel")
|
||||||
|
c(LeftFoot, "enuArmorSlots::NewEnumerator36", "Left foot")
|
||||||
|
c(RightFoot, "enuArmorSlots::NewEnumerator37", "Right foot")
|
||||||
|
#endif
|
24
src/Maps/DamageTypes.hpp
Normal file
24
src/Maps/DamageTypes.hpp
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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/>.
|
||||||
|
|
||||||
|
#ifdef c
|
||||||
|
c(Physical, "enuDamageProperty::NewEnumerator0")
|
||||||
|
c(Piercing, "enuDamageProperty::NewEnumerator1")
|
||||||
|
c(Heat, "enuDamageProperty::NewEnumerator2")
|
||||||
|
c(Freeze, "enuDamageProperty::NewEnumerator3")
|
||||||
|
c(Shock, "enuDamageProperty::NewEnumerator4")
|
||||||
|
c(Plasma, "enuDamageProperty::NewEnumerator5")
|
||||||
|
#endif
|
20
src/Maps/EffectColourModes.hpp
Normal file
20
src/Maps/EffectColourModes.hpp
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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/>.
|
||||||
|
|
||||||
|
#ifdef c
|
||||||
|
c(Default, "enuWeaponEffectColorMode::NewEnumerator0")
|
||||||
|
c(Custom, "enuWeaponEffectColorMode::NewEnumerator1")
|
||||||
|
#endif
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// MassBuilderSaveTool
|
// MassBuilderSaveTool
|
||||||
// Copyright (C) 2021 Guillaume Jacquemin
|
// Copyright (C) 2021-2022 Guillaume Jacquemin
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -33,6 +33,7 @@ static const std::map<Int, const char*> mission_id_map {{
|
||||||
{0x006E, "Mission 11 - Tempestuous Sector"},
|
{0x006E, "Mission 11 - Tempestuous Sector"},
|
||||||
{0x006F, "Mission 12 - Clashes of Metal"},
|
{0x006F, "Mission 12 - Clashes of Metal"},
|
||||||
{0x0070, "Mission 13 - The Sandstorm Glutton"},
|
{0x0070, "Mission 13 - The Sandstorm Glutton"},
|
||||||
|
{0x0071, "Mission 14 - An Icy Investigation"},
|
||||||
|
|
||||||
// Hunting grounds
|
// Hunting grounds
|
||||||
{0x00C8, "Hunt 1 - Desert Pathway Safety"},
|
{0x00C8, "Hunt 1 - Desert Pathway Safety"},
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// MassBuilderSaveTool
|
// MassBuilderSaveTool
|
||||||
// Copyright (C) 2021 Guillaume Jacquemin
|
// Copyright (C) 2021-2022 Guillaume Jacquemin
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -22,7 +22,7 @@ struct StoryProgressPoint {
|
||||||
Int id;
|
Int id;
|
||||||
const char* chapter;
|
const char* chapter;
|
||||||
const char* point;
|
const char* point;
|
||||||
const char* after = "";
|
const char* after = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const Corrade::Containers::Array<StoryProgressPoint> story_progress
|
static const Corrade::Containers::Array<StoryProgressPoint> story_progress
|
||||||
|
@ -88,5 +88,7 @@ static const Corrade::Containers::Array<StoryProgressPoint> story_progress
|
||||||
{0x0579, "Chapter 2", "Returned to hangar", "After mission 13"},
|
{0x0579, "Chapter 2", "Returned to hangar", "After mission 13"},
|
||||||
{0x057A, "Chapter 2", "Talked with Reina in development section", "After mission 13"},
|
{0x057A, "Chapter 2", "Talked with Reina in development section", "After mission 13"},
|
||||||
{0x057B, "Chapter 2", "Got briefing for challenges 1, 2, and 3", "After mission 13"},
|
{0x057B, "Chapter 2", "Got briefing for challenges 1, 2, and 3", "After mission 13"},
|
||||||
|
{0x057C, "Chapter 2", "Talked with Reina about device", "After mission 13"},
|
||||||
|
{0x057D, "Chapter 2", "Got mission 14 briefing", "After mission 13"},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
192
src/Maps/StyleNames.h
Normal file
192
src/Maps/StyleNames.h
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 <map>
|
||||||
|
|
||||||
|
#include <Magnum/Magnum.h>
|
||||||
|
|
||||||
|
using namespace Magnum;
|
||||||
|
|
||||||
|
extern const std::map<Int, const char*> style_names
|
||||||
|
#ifdef STYLENAMES_DEFINITION
|
||||||
|
{
|
||||||
|
{0, "Custom Style 1"},
|
||||||
|
{1, "Custom Style 2"},
|
||||||
|
{2, "Custom Style 3"},
|
||||||
|
{3, "Custom Style 4"},
|
||||||
|
{4, "Custom Style 5"},
|
||||||
|
{5, "Custom Style 6"},
|
||||||
|
{6, "Custom Style 7"},
|
||||||
|
{7, "Custom Style 8"},
|
||||||
|
{8, "Custom Style 9"},
|
||||||
|
{9, "Custom Style 10"},
|
||||||
|
{10, "Custom Style 11"},
|
||||||
|
{11, "Custom Style 12"},
|
||||||
|
{12, "Custom Style 13"},
|
||||||
|
{13, "Custom Style 14"},
|
||||||
|
{14, "Custom Style 15"},
|
||||||
|
{15, "Custom Style 16"},
|
||||||
|
|
||||||
|
{50, "Global Style 1"},
|
||||||
|
{51, "Global Style 2"},
|
||||||
|
{52, "Global Style 3"},
|
||||||
|
{53, "Global Style 4"},
|
||||||
|
{54, "Global Style 5"},
|
||||||
|
{55, "Global Style 6"},
|
||||||
|
{56, "Global Style 7"},
|
||||||
|
{57, "Global Style 8"},
|
||||||
|
{58, "Global Style 9"},
|
||||||
|
{59, "Global Style 10"},
|
||||||
|
{60, "Global Style 11"},
|
||||||
|
{61, "Global Style 12"},
|
||||||
|
{62, "Global Style 13"},
|
||||||
|
{63, "Global Style 14"},
|
||||||
|
{64, "Global Style 15"},
|
||||||
|
{65, "Global Style 16"},
|
||||||
|
|
||||||
|
{100, "Iron"},
|
||||||
|
{101, "Silver"},
|
||||||
|
{102, "Gold"},
|
||||||
|
{103, "Bronze"},
|
||||||
|
{104, "Copper"},
|
||||||
|
{105, "Nickel"},
|
||||||
|
{106, "Cobalt"},
|
||||||
|
{107, "Aluminium"},
|
||||||
|
{108, "Titanium"},
|
||||||
|
{109, "Platinum"},
|
||||||
|
{110, "Gun Metal"},
|
||||||
|
{111, "White"},
|
||||||
|
{112, "White Metal"},
|
||||||
|
{113, "White Gloss"},
|
||||||
|
{114, "Grey"},
|
||||||
|
{115, "Grey Metal"},
|
||||||
|
{116, "Grey Gloss"},
|
||||||
|
{117, "Dark Grey"},
|
||||||
|
{118, "Dark Grey Metal"},
|
||||||
|
{119, "Dark Grey Gloss"},
|
||||||
|
{120, "Black"},
|
||||||
|
{121, "Black Metal"},
|
||||||
|
{122, "Black Gloss"},
|
||||||
|
{123, "Red"},
|
||||||
|
{124, "Red Metal"},
|
||||||
|
{125, "Red Gloss"},
|
||||||
|
{126, "Dark Red"},
|
||||||
|
{127, "Dark Red Metal"},
|
||||||
|
{128, "Dark Red Gloss"},
|
||||||
|
{129, "Orange"},
|
||||||
|
{130, "Orange Metal"},
|
||||||
|
{131, "Orange Gloss"},
|
||||||
|
{132, "Dark Orange"},
|
||||||
|
{133, "Dark Orange Metal"},
|
||||||
|
{134, "Dark Orange Gloss"},
|
||||||
|
{135, "Yellow"},
|
||||||
|
{136, "Yellow Metal"},
|
||||||
|
{137, "Yellow Gloss"},
|
||||||
|
{138, "Brown"},
|
||||||
|
{139, "Brown Metal"},
|
||||||
|
{140, "Brown Gloss"},
|
||||||
|
{141, "Dark Brown"},
|
||||||
|
{142, "Dark Brown Metal"},
|
||||||
|
{143, "Dark Brown Gloss"},
|
||||||
|
{144, "Leafgreen"},
|
||||||
|
{145, "Leafgreen Metal"},
|
||||||
|
{146, "Leafgreen Gloss"},
|
||||||
|
{147, "Military Green"},
|
||||||
|
{148, "Military Green Metal"},
|
||||||
|
{149, "Military Green Gloss"},
|
||||||
|
{150, "Green"},
|
||||||
|
{151, "Green Metal"},
|
||||||
|
{152, "Green Gloss"},
|
||||||
|
{153, "Dark Green"},
|
||||||
|
{154, "Dark Green Metal"},
|
||||||
|
{155, "Dark Green Gloss"},
|
||||||
|
{156, "Teal"},
|
||||||
|
{157, "Teal Metal"},
|
||||||
|
{158, "Teal Gloss"},
|
||||||
|
{159, "Cyan"},
|
||||||
|
{160, "Cyan Metal"},
|
||||||
|
{161, "Cyan Gloss"},
|
||||||
|
{162, "Blue"},
|
||||||
|
{163, "Blue Metal"},
|
||||||
|
{164, "Blue Gloss"},
|
||||||
|
{165, "Blue Sky"},
|
||||||
|
{166, "Blue Sky Metal"},
|
||||||
|
{167, "Blue Sky Gloss"},
|
||||||
|
{168, "Dark Blue"},
|
||||||
|
{169, "Dark Blue Metal"},
|
||||||
|
{170, "Dark Blue Gloss"},
|
||||||
|
{171, "Purple"},
|
||||||
|
{172, "Purple Metal"},
|
||||||
|
{173, "Purple Gloss"},
|
||||||
|
{174, "Dark Purple"},
|
||||||
|
{175, "Dark Purple Metal"},
|
||||||
|
{176, "Dark Purple Gloss"},
|
||||||
|
{177, "Pink"},
|
||||||
|
{178, "Pink Metal"},
|
||||||
|
{179, "Pink Gloss"},
|
||||||
|
{180, "Rosy Brown"},
|
||||||
|
{181, "Rosy Brown Metal"},
|
||||||
|
{182, "Rosy Brown Gloss"},
|
||||||
|
{183, "Ivory"},
|
||||||
|
{184, "Ivory Metal"},
|
||||||
|
{185, "Ivory Gloss"},
|
||||||
|
{186, "Slate Brown"},
|
||||||
|
{187, "Slate Brown Metal"},
|
||||||
|
{188, "Slate Brown Gloss"},
|
||||||
|
{189, "Slate Green"},
|
||||||
|
{190, "Slate Green Metal"},
|
||||||
|
{191, "Slate Green Gloss"},
|
||||||
|
{192, "Slate Blue"},
|
||||||
|
{193, "Slate Blue Metal"},
|
||||||
|
{194, "Slate Blue Gloss"},
|
||||||
|
{195, "Slate Purple"},
|
||||||
|
{196, "Slate Purple Metal"},
|
||||||
|
{197, "Slate Purple Gloss"},
|
||||||
|
{198, "White Glow"},
|
||||||
|
{199, "White Radiance"},
|
||||||
|
{200, "Red Glow"},
|
||||||
|
{201, "Red Radiance"},
|
||||||
|
{202, "Orange Glow"},
|
||||||
|
{203, "Orange Radiance"},
|
||||||
|
{204, "Yellow Glow"},
|
||||||
|
{205, "Yellow Radiance"},
|
||||||
|
{206, "Leafgreen Glow"},
|
||||||
|
{207, "Leafgreen Radiance"},
|
||||||
|
{208, "Green Glow"},
|
||||||
|
{209, "Green Radiance"},
|
||||||
|
{210, "Teal Glow"},
|
||||||
|
{211, "Teal Radiance"},
|
||||||
|
{212, "Cyan Glow"},
|
||||||
|
{213, "Cyan Radiance"},
|
||||||
|
{214, "Blue Glow"},
|
||||||
|
{215, "Blue Radiance"},
|
||||||
|
{216, "Purple Glow"},
|
||||||
|
{217, "Purple Radiance"},
|
||||||
|
{218, "Pink Glow"},
|
||||||
|
{219, "Pink Radiance"},
|
||||||
|
{220, "Grey Camo"},
|
||||||
|
{221, "Dark Grey Camo"},
|
||||||
|
{222, "Green Camo"},
|
||||||
|
{223, "Dark Green Camo"},
|
||||||
|
{224, "Brown Camo"},
|
||||||
|
{225, "Dark Brown Camo"},
|
||||||
|
{226, "Blue Camo"},
|
||||||
|
{227, "Dark Blue Camo"},
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
;
|
24
src/Maps/WeaponTypes.hpp
Normal file
24
src/Maps/WeaponTypes.hpp
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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/>.
|
||||||
|
|
||||||
|
#ifdef c
|
||||||
|
c(Melee, "enuWeaponTypes::NewEnumerator0", "Melee weapon")
|
||||||
|
c(BulletShooter, "enuWeaponTypes::NewEnumerator1", "Bullet shooter")
|
||||||
|
c(EnergyShooter, "enuWeaponTypes::NewEnumerator2", "Energy shooter")
|
||||||
|
c(BulletLauncher, "enuWeaponTypes::NewEnumerator3", "Bullet launcher")
|
||||||
|
c(EnergyLauncher, "enuWeaponTypes::NewEnumerator4", "Energy launcher")
|
||||||
|
c(Shield, "enuWeaponTypes::NewEnumerator5", "Shield")
|
||||||
|
#endif
|
36
src/Mass/Accessory.h
Normal file
36
src/Mass/Accessory.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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/StaticArray.h>
|
||||||
|
|
||||||
|
#include <Magnum/Magnum.h>
|
||||||
|
#include <Magnum/Math/Vector3.h>
|
||||||
|
|
||||||
|
using namespace Corrade;
|
||||||
|
using namespace Magnum;
|
||||||
|
|
||||||
|
struct Accessory {
|
||||||
|
Int attachIndex = -1;
|
||||||
|
Int id = -1;
|
||||||
|
Containers::StaticArray<2, Int> styles{ValueInit};
|
||||||
|
Vector3 relativePosition{0.0f};
|
||||||
|
Vector3 relativePositionOffset{0.0f};
|
||||||
|
Vector3 relativeRotation{0.0f};
|
||||||
|
Vector3 relativeRotationOffset{0.0f};
|
||||||
|
Vector3 localScale{1.0f};
|
||||||
|
};
|
79
src/Mass/ArmourPart.h
Normal file
79
src/Mass/ArmourPart.h
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 <string>
|
||||||
|
|
||||||
|
#include <Corrade/Containers/Array.h>
|
||||||
|
#include <Corrade/Containers/StaticArray.h>
|
||||||
|
|
||||||
|
#include <Magnum/Types.h>
|
||||||
|
|
||||||
|
#include "Decal.h"
|
||||||
|
#include "Accessory.h"
|
||||||
|
|
||||||
|
using namespace Corrade;
|
||||||
|
using namespace Magnum;
|
||||||
|
|
||||||
|
enum class ArmourSlot {
|
||||||
|
Face = 0,
|
||||||
|
UpperHead = 1,
|
||||||
|
LowerHead = 2,
|
||||||
|
Neck = 3,
|
||||||
|
UpperBody = 4,
|
||||||
|
MiddleBody = 5,
|
||||||
|
LowerBody = 6,
|
||||||
|
FrontWaist = 7,
|
||||||
|
LeftFrontSkirt = 8,
|
||||||
|
RightFrontSkirt = 9,
|
||||||
|
LeftSideSkirt = 10,
|
||||||
|
RightSideSkirt = 11,
|
||||||
|
LeftBackSkirt = 12,
|
||||||
|
RightBackSkirt = 13,
|
||||||
|
BackWaist = 14,
|
||||||
|
LeftShoulder = 15,
|
||||||
|
RightShoulder = 16,
|
||||||
|
LeftUpperArm = 17,
|
||||||
|
RightUpperArm = 18,
|
||||||
|
LeftElbow = 19,
|
||||||
|
RightElbow = 20,
|
||||||
|
LeftLowerArm = 21,
|
||||||
|
RightLowerArm = 22,
|
||||||
|
Backpack = 23,
|
||||||
|
LeftHand = 24,
|
||||||
|
RightHand = 25,
|
||||||
|
LeftUpperLeg = 26,
|
||||||
|
RightUpperLeg = 27,
|
||||||
|
LeftKnee = 28,
|
||||||
|
RightKnee = 29,
|
||||||
|
LeftLowerLeg = 30,
|
||||||
|
RightLowerLeg = 31,
|
||||||
|
LeftAnkle = 32,
|
||||||
|
RightAnkle = 33,
|
||||||
|
LeftHeel = 34,
|
||||||
|
RightHeel = 35,
|
||||||
|
LeftFoot = 36,
|
||||||
|
RightFoot = 37,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ArmourPart {
|
||||||
|
ArmourSlot slot = ArmourSlot::Face;
|
||||||
|
Int id = 0;
|
||||||
|
Containers::StaticArray<4, Int> styles{ValueInit};
|
||||||
|
Containers::Array<Decal> decals;
|
||||||
|
Containers::Array<Accessory> accessories;
|
||||||
|
};
|
39
src/Mass/CustomStyle.h
Normal file
39
src/Mass/CustomStyle.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 <string>
|
||||||
|
|
||||||
|
#include <Magnum/Magnum.h>
|
||||||
|
#include <Magnum/Math/Color.h>
|
||||||
|
#include <Magnum/Math/Vector2.h>
|
||||||
|
|
||||||
|
using namespace Magnum;
|
||||||
|
|
||||||
|
struct CustomStyle {
|
||||||
|
std::string name;
|
||||||
|
Color4 colour{0.0f};
|
||||||
|
Float metallic = 0.5f;
|
||||||
|
Float gloss = 0.5f;
|
||||||
|
bool glow = false;
|
||||||
|
|
||||||
|
Int patternId = 0;
|
||||||
|
Float opacity = 0.5f;
|
||||||
|
Vector2 offset{0.5f};
|
||||||
|
Float rotation = 0.0f;
|
||||||
|
Float scale = 0.5f;
|
||||||
|
};
|
38
src/Mass/Decal.h
Normal file
38
src/Mass/Decal.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 <string>
|
||||||
|
|
||||||
|
#include <Magnum/Magnum.h>
|
||||||
|
#include <Magnum/Math/Color.h>
|
||||||
|
#include <Magnum/Math/Vector2.h>
|
||||||
|
|
||||||
|
using namespace Magnum;
|
||||||
|
|
||||||
|
struct Decal {
|
||||||
|
Int id = -1;
|
||||||
|
Color4 colour{0.0f};
|
||||||
|
Vector3 position{0.0f};
|
||||||
|
Vector3 uAxis{0.0f};
|
||||||
|
Vector3 vAxis{0.0f};
|
||||||
|
Vector2 offset{0.5f};
|
||||||
|
Float scale = 0.5f;
|
||||||
|
Float rotation = 0.0f;
|
||||||
|
bool flip = false;
|
||||||
|
bool wrap = false;
|
||||||
|
};
|
32
src/Mass/Joints.h
Normal file
32
src/Mass/Joints.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 <Magnum/Types.h>
|
||||||
|
|
||||||
|
using namespace Magnum;
|
||||||
|
|
||||||
|
struct Joints {
|
||||||
|
Float neck = 0.0f;
|
||||||
|
Float body = 0.0f;
|
||||||
|
Float shoulders = 0.0f;
|
||||||
|
Float hips = 0.0f;
|
||||||
|
Float upperArms = 0.0f;
|
||||||
|
Float lowerArms = 0.0f;
|
||||||
|
Float upperLegs = 0.0f;
|
||||||
|
Float lowerLegs = 0.0f;
|
||||||
|
};
|
1355
src/Mass/Mass.cpp
1355
src/Mass/Mass.cpp
File diff suppressed because it is too large
Load diff
182
src/Mass/Mass.h
182
src/Mass/Mass.h
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// MassBuilderSaveTool
|
// MassBuilderSaveTool
|
||||||
// Copyright (C) 2021 Guillaume Jacquemin
|
// Copyright (C) 2021-2022 Guillaume Jacquemin
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -18,17 +18,37 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <Magnum/Magnum.h>
|
#include <Corrade/Containers/Optional.h>
|
||||||
|
#include <Corrade/Containers/Pointer.h>
|
||||||
|
#include <Corrade/Containers/StaticArray.h>
|
||||||
|
|
||||||
|
#include <Magnum/Magnum.h>
|
||||||
|
#include <Magnum/Math/Color.h>
|
||||||
|
#include <Magnum/Math/Vector2.h>
|
||||||
|
#include <Magnum/Math/Vector3.h>
|
||||||
|
|
||||||
|
#include "Joints.h"
|
||||||
|
#include "CustomStyle.h"
|
||||||
|
#include "Decal.h"
|
||||||
|
#include "Accessory.h"
|
||||||
|
#include "ArmourPart.h"
|
||||||
|
#include "WeaponPart.h"
|
||||||
|
#include "Weapon.h"
|
||||||
|
|
||||||
|
#include "../UESaveFile/UESaveFile.h"
|
||||||
|
|
||||||
|
using namespace Corrade;
|
||||||
using namespace Magnum;
|
using namespace Magnum;
|
||||||
|
|
||||||
enum class MassState : UnsignedByte {
|
struct ArrayProperty;
|
||||||
Empty, Invalid, Valid
|
|
||||||
};
|
|
||||||
|
|
||||||
class Mass {
|
class Mass {
|
||||||
public:
|
public:
|
||||||
explicit Mass(const std::string& filename);
|
enum class State : UnsignedByte {
|
||||||
|
Empty, Invalid, Valid
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit Mass(const std::string& path);
|
||||||
|
|
||||||
Mass(const Mass&) = delete;
|
Mass(const Mass&) = delete;
|
||||||
Mass& operator=(const Mass&) = delete;
|
Mass& operator=(const Mass&) = delete;
|
||||||
|
@ -36,23 +56,153 @@ class Mass {
|
||||||
Mass(Mass&&) = default;
|
Mass(Mass&&) = default;
|
||||||
Mass& operator=(Mass&&) = default;
|
Mass& operator=(Mass&&) = default;
|
||||||
|
|
||||||
static auto lastError() -> std::string const&;
|
auto lastError() -> std::string const&;
|
||||||
|
|
||||||
static auto getNameFromFile(const std::string& filename) -> std::string;
|
static auto getNameFromFile(const std::string& path) -> Containers::Optional<std::string>;
|
||||||
|
|
||||||
|
void refreshValues();
|
||||||
|
|
||||||
auto filename() -> std::string const&;
|
auto filename() -> std::string const&;
|
||||||
|
|
||||||
auto name() -> std::string const&;
|
auto name() -> Containers::Optional<std::string> const&;
|
||||||
auto getName() -> std::string const&;
|
auto setName(std::string new_name) -> bool;
|
||||||
|
|
||||||
auto state() -> MassState;
|
auto state() -> State;
|
||||||
|
|
||||||
auto updateSteamId(const std::string& steam_id) -> bool;
|
auto dirty() const -> bool;
|
||||||
|
void setDirty(bool dirty = true);
|
||||||
|
|
||||||
|
auto jointSliders() -> Joints&;
|
||||||
|
void getJointSliders();
|
||||||
|
auto writeJointSliders() -> bool;
|
||||||
|
|
||||||
|
auto frameStyles() -> Containers::ArrayView<Int>;
|
||||||
|
void getFrameStyles();
|
||||||
|
auto writeFrameStyles() -> bool;
|
||||||
|
|
||||||
|
auto eyeFlareColour() -> Color4&;
|
||||||
|
void getEyeFlareColour();
|
||||||
|
auto writeEyeFlareColour() -> bool;
|
||||||
|
|
||||||
|
auto frameCustomStyles() -> Containers::ArrayView<CustomStyle>;
|
||||||
|
void getFrameCustomStyles();
|
||||||
|
auto writeFrameCustomStyle(UnsignedLong index) -> bool;
|
||||||
|
|
||||||
|
auto armourParts() -> Containers::ArrayView<ArmourPart>;
|
||||||
|
void getArmourParts();
|
||||||
|
auto writeArmourPart(ArmourSlot slot) -> bool;
|
||||||
|
|
||||||
|
auto armourCustomStyles() -> Containers::ArrayView<CustomStyle>;
|
||||||
|
void getArmourCustomStyles();
|
||||||
|
auto writeArmourCustomStyle(UnsignedLong index) -> bool;
|
||||||
|
|
||||||
|
auto meleeWeapons() -> Containers::ArrayView<Weapon>;
|
||||||
|
void getMeleeWeapons();
|
||||||
|
auto writeMeleeWeapons() -> bool;
|
||||||
|
|
||||||
|
auto shields() -> Containers::ArrayView<Weapon>;
|
||||||
|
void getShields();
|
||||||
|
auto writeShields() -> bool;
|
||||||
|
|
||||||
|
auto bulletShooters() -> Containers::ArrayView<Weapon>;
|
||||||
|
void getBulletShooters();
|
||||||
|
auto writeBulletShooters() -> bool;
|
||||||
|
|
||||||
|
auto energyShooters() -> Containers::ArrayView<Weapon>;
|
||||||
|
void getEnergyShooters();
|
||||||
|
auto writeEnergyShooters() -> bool;
|
||||||
|
|
||||||
|
auto bulletLaunchers() -> Containers::ArrayView<Weapon>;
|
||||||
|
void getBulletLaunchers();
|
||||||
|
auto writeBulletLaunchers() -> bool;
|
||||||
|
|
||||||
|
auto energyLaunchers() -> Containers::ArrayView<Weapon>;
|
||||||
|
void getEnergyLaunchers();
|
||||||
|
auto writeEnergyLaunchers() -> bool;
|
||||||
|
|
||||||
|
auto globalStyles() -> Containers::ArrayView<CustomStyle>;
|
||||||
|
void getGlobalStyles();
|
||||||
|
auto writeGlobalStyle(UnsignedLong index) -> bool;
|
||||||
|
|
||||||
|
void getTuning();
|
||||||
|
|
||||||
|
auto engine() -> Int&;
|
||||||
|
auto gears() -> Containers::ArrayView<Int>;
|
||||||
|
|
||||||
|
auto os() -> Int&;
|
||||||
|
auto modules() -> Containers::ArrayView<Int>;
|
||||||
|
|
||||||
|
auto architecture() -> Int&;
|
||||||
|
auto techs() -> Containers::ArrayView<Int>;
|
||||||
|
|
||||||
|
auto account() -> std::string const&;
|
||||||
|
auto updateAccount(const std::string& new_account) -> bool;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::string _lastError;
|
void getCustomStyles(Containers::ArrayView<CustomStyle> styles, ArrayProperty* style_array);
|
||||||
|
auto setCustomStyle(const CustomStyle& style, UnsignedLong index, ArrayProperty* style_array) -> bool;
|
||||||
|
|
||||||
std::string _filename = "";
|
void getDecals(Containers::ArrayView<Decal> decals, ArrayProperty* decal_array);
|
||||||
std::string _name = "";
|
void writeDecals(Containers::ArrayView<Decal> decals, ArrayProperty* decal_array);
|
||||||
MassState _state = MassState::Empty;
|
|
||||||
|
void getAccessories(Containers::ArrayView<Accessory> accessories, ArrayProperty* accessory_array);
|
||||||
|
void writeAccessories(Containers::ArrayView<Accessory> accessories, ArrayProperty* accs_array);
|
||||||
|
|
||||||
|
void getWeaponType(const char* prop_name, Containers::ArrayView<Weapon> weapon_array);
|
||||||
|
auto writeWeaponType(const char* prop_name, Containers::ArrayView<Weapon> weapon_array) -> bool;
|
||||||
|
|
||||||
|
void getTuningCategory(const char* big_node_prop_name, Int& big_node_id,
|
||||||
|
const char* small_nodes_prop_name, Containers::ArrayView<Int> small_nodes_ids);
|
||||||
|
|
||||||
|
Containers::Optional<UESaveFile> _mass;
|
||||||
|
|
||||||
|
std::string _lastError;
|
||||||
|
|
||||||
|
std::string _folder;
|
||||||
|
std::string _filename;
|
||||||
|
State _state = State::Empty;
|
||||||
|
|
||||||
|
bool _dirty = false;
|
||||||
|
|
||||||
|
Containers::Optional<std::string> _name = Containers::NullOpt;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
Joints joints{};
|
||||||
|
|
||||||
|
Containers::StaticArray<4, Int> styles{ValueInit};
|
||||||
|
|
||||||
|
Color4 eyeFlare{0.0f};
|
||||||
|
|
||||||
|
Containers::StaticArray<16, CustomStyle> customStyles;
|
||||||
|
} _frame;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
Containers::StaticArray<38, ArmourPart> parts;
|
||||||
|
|
||||||
|
Containers::StaticArray<16, CustomStyle> customStyles;
|
||||||
|
} _armour;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
Containers::StaticArray<8, Weapon> melee;
|
||||||
|
Containers::StaticArray<1, Weapon> shields;
|
||||||
|
Containers::StaticArray<4, Weapon> bulletShooters;
|
||||||
|
Containers::StaticArray<4, Weapon> energyShooters;
|
||||||
|
Containers::StaticArray<4, Weapon> bulletLaunchers;
|
||||||
|
Containers::StaticArray<4, Weapon> energyLaunchers;
|
||||||
|
} _weapons;
|
||||||
|
|
||||||
|
Containers::Array<CustomStyle> _globalStyles;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
Int engineId;
|
||||||
|
Containers::StaticArray<7, Int> gearIds;
|
||||||
|
|
||||||
|
Int osId;
|
||||||
|
Containers::StaticArray<7, Int> moduleIds;
|
||||||
|
|
||||||
|
Int archId;
|
||||||
|
Containers::StaticArray<7, Int> techIds;
|
||||||
|
} _tuning;
|
||||||
|
|
||||||
|
std::string _account;
|
||||||
};
|
};
|
||||||
|
|
49
src/Mass/Weapon.cpp
Normal file
49
src/Mass/Weapon.cpp
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "Weapon.h"
|
||||||
|
|
||||||
|
Weapon::Weapon(const Weapon& other) {
|
||||||
|
name = other.name;
|
||||||
|
type = other.type;
|
||||||
|
parts = Containers::Array<WeaponPart>{other.parts.size()};
|
||||||
|
for(UnsignedInt i = 0; i < parts.size(); i++) {
|
||||||
|
parts[i] = other.parts[i];
|
||||||
|
}
|
||||||
|
customStyles = other.customStyles;
|
||||||
|
attached = other.attached;
|
||||||
|
damageType = other.damageType;
|
||||||
|
dualWield = other.dualWield;
|
||||||
|
effectColourMode = other.effectColourMode;
|
||||||
|
effectColour = other.effectColour;
|
||||||
|
}
|
||||||
|
|
||||||
|
Weapon& Weapon::operator=(const Weapon& other) {
|
||||||
|
name = other.name;
|
||||||
|
type = other.type;
|
||||||
|
parts = Containers::Array<WeaponPart>{other.parts.size()};
|
||||||
|
for(UnsignedInt i = 0; i < parts.size(); i++) {
|
||||||
|
parts[i] = other.parts[i];
|
||||||
|
}
|
||||||
|
customStyles = other.customStyles;
|
||||||
|
attached = other.attached;
|
||||||
|
damageType = other.damageType;
|
||||||
|
dualWield = other.dualWield;
|
||||||
|
effectColourMode = other.effectColourMode;
|
||||||
|
effectColour = other.effectColour;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
74
src/Mass/Weapon.h
Normal file
74
src/Mass/Weapon.h
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 <string>
|
||||||
|
|
||||||
|
#include <Corrade/Containers/Array.h>
|
||||||
|
#include <Corrade/Containers/StaticArray.h>
|
||||||
|
|
||||||
|
#include <Magnum/Magnum.h>
|
||||||
|
#include <Magnum/Math/Color.h>
|
||||||
|
|
||||||
|
#include "WeaponPart.h"
|
||||||
|
#include "CustomStyle.h"
|
||||||
|
|
||||||
|
using namespace Corrade;
|
||||||
|
using namespace Magnum;
|
||||||
|
|
||||||
|
enum class WeaponType {
|
||||||
|
Melee = 0,
|
||||||
|
Shield = 5,
|
||||||
|
BulletShooter = 1,
|
||||||
|
EnergyShooter = 2,
|
||||||
|
BulletLauncher = 3,
|
||||||
|
EnergyLauncher = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class DamageType {
|
||||||
|
Physical = 0,
|
||||||
|
Piercing = 1,
|
||||||
|
Plasma = 5,
|
||||||
|
Heat = 2,
|
||||||
|
Freeze = 3,
|
||||||
|
Shock = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class EffectColourMode {
|
||||||
|
Default = 0,
|
||||||
|
Custom = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Weapon {
|
||||||
|
Weapon() = default;
|
||||||
|
|
||||||
|
Weapon(const Weapon& other);
|
||||||
|
Weapon& operator=(const Weapon& other);
|
||||||
|
|
||||||
|
Weapon(Weapon&& other) = default;
|
||||||
|
Weapon& operator=(Weapon&& other) = default;
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
WeaponType type = WeaponType::Melee;
|
||||||
|
Containers::Array<WeaponPart> parts;
|
||||||
|
Containers::StaticArray<16, CustomStyle> customStyles{ValueInit};
|
||||||
|
bool attached = false;
|
||||||
|
DamageType damageType = DamageType::Physical;
|
||||||
|
bool dualWield = false;
|
||||||
|
EffectColourMode effectColourMode = EffectColourMode::Default;
|
||||||
|
Color4 effectColour{0.0f};
|
||||||
|
};
|
66
src/Mass/WeaponPart.h
Normal file
66
src/Mass/WeaponPart.h
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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/Array.h>
|
||||||
|
#include <Corrade/Containers/StaticArray.h>
|
||||||
|
|
||||||
|
#include <Magnum/Types.h>
|
||||||
|
|
||||||
|
#include "Decal.h"
|
||||||
|
#include "Accessory.h"
|
||||||
|
|
||||||
|
using namespace Corrade;
|
||||||
|
using namespace Magnum;
|
||||||
|
|
||||||
|
struct WeaponPart {
|
||||||
|
WeaponPart() = default;
|
||||||
|
|
||||||
|
WeaponPart(const WeaponPart& other) {
|
||||||
|
id = other.id;
|
||||||
|
styles = other.styles;
|
||||||
|
decals = Containers::Array<Decal>{other.decals.size()};
|
||||||
|
for(UnsignedInt i = 0; i < decals.size(); i++) {
|
||||||
|
decals[i] = other.decals[i];
|
||||||
|
}
|
||||||
|
accessories = Containers::Array<Accessory>{other.accessories.size()};
|
||||||
|
for(UnsignedInt i = 0; i < accessories.size(); i++) {
|
||||||
|
accessories[i] = other.accessories[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WeaponPart& operator=(const WeaponPart& other) {
|
||||||
|
id = other.id;
|
||||||
|
styles = other.styles;
|
||||||
|
decals = Containers::Array<Decal>{other.decals.size()};
|
||||||
|
for(UnsignedInt i = 0; i < decals.size(); i++) {
|
||||||
|
decals[i] = other.decals[i];
|
||||||
|
}
|
||||||
|
accessories = Containers::Array<Accessory>{other.accessories.size()};
|
||||||
|
for(UnsignedInt i = 0; i < accessories.size(); i++) {
|
||||||
|
accessories[i] = other.accessories[i];
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
WeaponPart(WeaponPart&& other) = default;
|
||||||
|
WeaponPart& operator=(WeaponPart&& other) = default;
|
||||||
|
|
||||||
|
Int id = 0;
|
||||||
|
Containers::StaticArray<4, Int> styles{ValueInit};
|
||||||
|
Containers::Array<Decal> decals{};
|
||||||
|
Containers::Array<Accessory> accessories{};
|
||||||
|
};
|
|
@ -1,5 +1,5 @@
|
||||||
// MassBuilderSaveTool
|
// MassBuilderSaveTool
|
||||||
// Copyright (C) 2021 Guillaume Jacquemin
|
// Copyright (C) 2021-2022 Guillaume Jacquemin
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -49,23 +49,11 @@ auto MassManager::lastError() -> std::string const& {
|
||||||
return _lastError;
|
return _lastError;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto MassManager::massName(int hangar) -> std::string const& {
|
auto MassManager::hangar(Int hangar) -> Mass& {
|
||||||
if(hangar < 0 || hangar >= 32) {
|
return _hangars[hangar];
|
||||||
return empty_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _hangars[hangar].name();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto MassManager::massState(int hangar) -> MassState {
|
void MassManager::refreshHangar(Int hangar) {
|
||||||
if(hangar < 0 || hangar >= 32) {
|
|
||||||
return MassState::Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _hangars[hangar].state();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MassManager::refreshHangar(int hangar) {
|
|
||||||
if(hangar < 0 || hangar >= 32) {
|
if(hangar < 0 || hangar >= 32) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -75,7 +63,7 @@ void MassManager::refreshHangar(int hangar) {
|
||||||
_hangars[hangar] = Mass{mass_filename};
|
_hangars[hangar] = Mass{mass_filename};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto MassManager::importMass(const std::string& staged_fn, int hangar) -> bool {
|
auto MassManager::importMass(const std::string& staged_fn, Int hangar) -> bool {
|
||||||
if(hangar < 0 || hangar >= 32) {
|
if(hangar < 0 || hangar >= 32) {
|
||||||
_lastError = "Hangar out of range in MassManager::importMass()";
|
_lastError = "Hangar out of range in MassManager::importMass()";
|
||||||
return false;
|
return false;
|
||||||
|
@ -91,18 +79,22 @@ auto MassManager::importMass(const std::string& staged_fn, int hangar) -> bool {
|
||||||
std::string source = Utility::Directory::join(_stagingAreaDirectory, staged_fn);
|
std::string source = Utility::Directory::join(_stagingAreaDirectory, staged_fn);
|
||||||
Utility::Directory::copy(source, source + ".tmp");
|
Utility::Directory::copy(source, source + ".tmp");
|
||||||
|
|
||||||
if(!Mass{source + ".tmp"}.updateSteamId(_steamId))
|
|
||||||
{
|
{
|
||||||
_lastError = "The M.A.S.S. file at " + source + " seems to be corrupt.";
|
Mass mass{source + ".tmp"};
|
||||||
|
if(!mass.updateAccount(_steamId)) {
|
||||||
|
_lastError = mass.lastError();
|
||||||
Utility::Directory::rm(source + ".tmp");
|
Utility::Directory::rm(source + ".tmp");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Utility::Directory::exists(_hangars[hangar].filename())) {
|
|
||||||
Utility::Directory::rm(_hangars[hangar].filename());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!Utility::Directory::move(source + ".tmp", _hangars[hangar].filename())) {
|
std::string dest = Utility::Directory::join(_saveDirectory, _hangars[hangar].filename());
|
||||||
|
|
||||||
|
if(Utility::Directory::exists(dest)) {
|
||||||
|
Utility::Directory::rm(dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!Utility::Directory::move(source + ".tmp", dest)) {
|
||||||
_lastError = Utility::formatString("Couldn't move {} to hangar {:.2d}", staged_fn, hangar + 1);
|
_lastError = Utility::formatString("Couldn't move {} to hangar {:.2d}", staged_fn, hangar + 1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -110,20 +102,20 @@ auto MassManager::importMass(const std::string& staged_fn, int hangar) -> bool {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto MassManager::exportMass(int hangar) -> bool {
|
auto MassManager::exportMass(Int hangar) -> bool {
|
||||||
if(hangar < 0 || hangar >= 32) {
|
if(hangar < 0 || hangar >= 32) {
|
||||||
_lastError = "Hangar out of range in MassManager::exportMass()";
|
_lastError = "Hangar out of range in MassManager::exportMass()";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_hangars[hangar].state() != MassState::Valid) {
|
if(_hangars[hangar].state() != Mass::State::Valid) {
|
||||||
_lastError = Utility::formatString("There is no valid data to export in hangar {:.2d}", hangar + 1);
|
_lastError = Utility::formatString("There is no valid data to export in hangar {:.2d}", hangar + 1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string source = Utility::Directory::join(_saveDirectory, _hangars[hangar].filename());
|
std::string source = Utility::Directory::join(_saveDirectory, _hangars[hangar].filename());
|
||||||
std::string dest = Utility::Directory::join(_stagingAreaDirectory,
|
std::string dest = Utility::Directory::join(_stagingAreaDirectory,
|
||||||
Utility::formatString("{}_{}.sav", _hangars[hangar].name(), _steamId));
|
Utility::formatString("{}_{}.sav", *_hangars[hangar].name(), _steamId));
|
||||||
|
|
||||||
if(!Utility::Directory::copy(source, dest)) {
|
if(!Utility::Directory::copy(source, dest)) {
|
||||||
_lastError = Utility::formatString("Couldn't export data from hangar {:.2d} to {}", hangar, dest);
|
_lastError = Utility::formatString("Couldn't export data from hangar {:.2d} to {}", hangar, dest);
|
||||||
|
@ -133,7 +125,7 @@ auto MassManager::exportMass(int hangar) -> bool {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto MassManager::moveMass(int source, int destination) -> bool {
|
auto MassManager::moveMass(Int source, Int destination) -> bool {
|
||||||
if(source < 0 || source >= 32) {
|
if(source < 0 || source >= 32) {
|
||||||
_lastError = "Source hangar out of range.";
|
_lastError = "Source hangar out of range.";
|
||||||
return false;
|
return false;
|
||||||
|
@ -144,38 +136,38 @@ auto MassManager::moveMass(int source, int destination) -> bool {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string source_file = _hangars[source].filename();
|
std::string source_file = Utility::Directory::join(_saveDirectory, _hangars[source].filename());
|
||||||
std::string dest_file = _hangars[destination].filename();
|
std::string dest_file = Utility::Directory::join(_saveDirectory, _hangars[destination].filename());
|
||||||
MassState dest_state = _hangars[destination].state();
|
Mass::State dest_state = _hangars[destination].state();
|
||||||
|
|
||||||
switch(dest_state) {
|
switch(dest_state) {
|
||||||
case MassState::Empty:
|
case Mass::State::Empty:
|
||||||
break;
|
break;
|
||||||
case MassState::Invalid:
|
case Mass::State::Invalid:
|
||||||
Utility::Directory::rm(dest_file);
|
Utility::Directory::rm(dest_file);
|
||||||
break;
|
break;
|
||||||
case MassState::Valid:
|
case Mass::State::Valid:
|
||||||
Utility::Directory::move(dest_file, dest_file + ".tmp");
|
Utility::Directory::move(dest_file, dest_file + ".tmp");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Utility::Directory::move(source_file, dest_file);
|
Utility::Directory::move(source_file, dest_file);
|
||||||
|
|
||||||
if(dest_state == MassState::Valid) {
|
if(dest_state == Mass::State::Valid) {
|
||||||
Utility::Directory::move(dest_file + ".tmp", source_file);
|
Utility::Directory::move(dest_file + ".tmp", source_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto MassManager::deleteMass(int hangar) -> bool {
|
auto MassManager::deleteMass(Int hangar) -> bool {
|
||||||
if(hangar < 0 || hangar >= 32) {
|
if(hangar < 0 || hangar >= 32) {
|
||||||
_lastError = "Hangar out of bounds";
|
_lastError = "Hangar out of range.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!Utility::Directory::rm(_hangars[hangar].filename())) {
|
if(!Utility::Directory::rm(Utility::Directory::join(_saveDirectory, _hangars[hangar].filename()))) {
|
||||||
_lastError = "Deletion failed. Maybe the file was already deleted, or it's locked by another application.";
|
_lastError = Utility::formatString("Deletion failed: {}", std::strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +191,7 @@ void MassManager::refreshStagedMasses() {
|
||||||
file_list.erase(iter, file_list.end());
|
file_list.erase(iter, file_list.end());
|
||||||
|
|
||||||
for(const std::string& file : file_list) {
|
for(const std::string& file : file_list) {
|
||||||
std::string name = Mass::getNameFromFile(Utility::Directory::join(_stagingAreaDirectory, file));
|
std::string name = *Mass::getNameFromFile(Utility::Directory::join(_stagingAreaDirectory, file));
|
||||||
|
|
||||||
if(!name.empty()) {
|
if(!name.empty()) {
|
||||||
_stagedMasses[file] = name;
|
_stagedMasses[file] = name;
|
||||||
|
@ -214,7 +206,7 @@ auto MassManager::deleteStagedMass(const std::string& filename) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!Utility::Directory::rm(Utility::Directory::join(_stagingAreaDirectory, filename))) {
|
if(!Utility::Directory::rm(Utility::Directory::join(_stagingAreaDirectory, filename))) {
|
||||||
_lastError = "The file " + filename + " couldn't be deleted for unknown reasons.";
|
_lastError = Utility::formatString("{} couldn't be deleted: {}", filename, std::strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// MassBuilderSaveTool
|
// MassBuilderSaveTool
|
||||||
// Copyright (C) 2021 Guillaume Jacquemin
|
// Copyright (C) 2021-2022 Guillaume Jacquemin
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -31,8 +31,7 @@ class MassManager {
|
||||||
|
|
||||||
auto lastError() -> std::string const&;
|
auto lastError() -> std::string const&;
|
||||||
|
|
||||||
auto massName(int hangar) -> std::string const&;
|
auto hangar(int hangar) -> Mass&;
|
||||||
auto massState(int hangar) -> MassState;
|
|
||||||
|
|
||||||
void refreshHangar(int hangar);
|
void refreshHangar(int hangar);
|
||||||
|
|
||||||
|
|
|
@ -1,94 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
// MassBuilderSaveTool
|
|
||||||
// Copyright (C) 2021 Guillaume Jacquemin
|
|
||||||
//
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
constexpr char company_name_locator[] = "CompanyName\0\f\0\0\0StrProperty";
|
|
||||||
constexpr char active_slot_locator[] = "ActiveFrameSlot\0\f\0\0\0IntProperty";
|
|
||||||
constexpr char credits_locator[] = "Credit\0\f\0\0\0IntProperty";
|
|
||||||
constexpr char story_progress_locator[] = "StoryProgress\0\f\0\0\0IntProperty";
|
|
||||||
constexpr char last_mission_id_locator[] = "LastMissionID\0\f\0\0\0IntProperty";
|
|
||||||
|
|
||||||
constexpr char verse_steel_locator[] =
|
|
||||||
"ID_4_AAE08F17428E229EC7A2209F51081A21\0\f\0\0\0IntProperty\0\x04\0\0\0\0\0\0\0\0\x00\x35\f\0,\0\0\0"
|
|
||||||
"Quantity_3_560F09B5485C365D3041888910019CE3\0\f\0\0\0IntProperty";
|
|
||||||
constexpr char undinium_locator[] =
|
|
||||||
"ID_4_AAE08F17428E229EC7A2209F51081A21\0\f\0\0\0IntProperty\0\x04\0\0\0\0\0\0\0\0\x01\x35\f\0,\0\0\0"
|
|
||||||
"Quantity_3_560F09B5485C365D3041888910019CE3\0\f\0\0\0IntProperty";
|
|
||||||
constexpr char necrium_alloy_locator[] =
|
|
||||||
"ID_4_AAE08F17428E229EC7A2209F51081A21\0\f\0\0\0IntProperty\0\x04\0\0\0\0\0\0\0\0\x02\x35\f\0,\0\0\0"
|
|
||||||
"Quantity_3_560F09B5485C365D3041888910019CE3\0\f\0\0\0IntProperty";
|
|
||||||
constexpr char lunarite_locator[] =
|
|
||||||
"ID_4_AAE08F17428E229EC7A2209F51081A21\0\f\0\0\0IntProperty\0\x04\0\0\0\0\0\0\0\0\x03\x35\f\0,\0\0\0"
|
|
||||||
"Quantity_3_560F09B5485C365D3041888910019CE3\0\f\0\0\0IntProperty";
|
|
||||||
constexpr char asterite_locator[] =
|
|
||||||
"ID_4_AAE08F17428E229EC7A2209F51081A21\0\f\0\0\0IntProperty\0\x04\0\0\0\0\0\0\0\0\x04\x35\f\0,\0\0\0"
|
|
||||||
"Quantity_3_560F09B5485C365D3041888910019CE3\0\f\0\0\0IntProperty";
|
|
||||||
|
|
||||||
constexpr char ednil_locator[] =
|
|
||||||
"ID_4_AAE08F17428E229EC7A2209F51081A21\0\f\0\0\0IntProperty\0\x04\0\0\0\0\0\0\0\0\x0a\x35\f\0,\0\0\0"
|
|
||||||
"Quantity_3_560F09B5485C365D3041888910019CE3\0\f\0\0\0IntProperty";
|
|
||||||
constexpr char nuflalt_locator[] =
|
|
||||||
"ID_4_AAE08F17428E229EC7A2209F51081A21\0\f\0\0\0IntProperty\0\x04\0\0\0\0\0\0\0\0\x0b\x35\f\0,\0\0\0"
|
|
||||||
"Quantity_3_560F09B5485C365D3041888910019CE3\0\f\0\0\0IntProperty";
|
|
||||||
constexpr char aurelene_locator[] =
|
|
||||||
"ID_4_AAE08F17428E229EC7A2209F51081A21\0\f\0\0\0IntProperty\0\x04\0\0\0\0\0\0\0\0\f\x35\f\0,\0\0\0"
|
|
||||||
"Quantity_3_560F09B5485C365D3041888910019CE3\0\f\0\0\0IntProperty";
|
|
||||||
constexpr char soldus_locator[] =
|
|
||||||
"ID_4_AAE08F17428E229EC7A2209F51081A21\0\f\0\0\0IntProperty\0\x04\0\0\0\0\0\0\0\0\x0d\x35\f\0,\0\0\0"
|
|
||||||
"Quantity_3_560F09B5485C365D3041888910019CE3\0\f\0\0\0IntProperty";
|
|
||||||
constexpr char synthesized_n_locator[] =
|
|
||||||
"ID_4_AAE08F17428E229EC7A2209F51081A21\0\f\0\0\0IntProperty\0\x04\0\0\0\0\0\0\0\0\x0e\x35\f\0,\0\0\0"
|
|
||||||
"Quantity_3_560F09B5485C365D3041888910019CE3\0\f\0\0\0IntProperty";
|
|
||||||
|
|
||||||
constexpr char alcarbonite_locator[] =
|
|
||||||
"ID_4_AAE08F17428E229EC7A2209F51081A21\0\f\0\0\0IntProperty\0\x04\0\0\0\0\0\0\0\0\x14\x35\f\0,\0\0\0"
|
|
||||||
"Quantity_3_560F09B5485C365D3041888910019CE3\0\f\0\0\0IntProperty";
|
|
||||||
constexpr char keriphene_locator[] =
|
|
||||||
"ID_4_AAE08F17428E229EC7A2209F51081A21\0\f\0\0\0IntProperty\0\x04\0\0\0\0\0\0\0\0\x15\x35\f\0,\0\0\0"
|
|
||||||
"Quantity_3_560F09B5485C365D3041888910019CE3\0\f\0\0\0IntProperty";
|
|
||||||
constexpr char nitinol_cm_locator[] =
|
|
||||||
"ID_4_AAE08F17428E229EC7A2209F51081A21\0\f\0\0\0IntProperty\0\x04\0\0\0\0\0\0\0\0\x16\x35\f\0,\0\0\0"
|
|
||||||
"Quantity_3_560F09B5485C365D3041888910019CE3\0\f\0\0\0IntProperty";
|
|
||||||
constexpr char quarkium_locator[] =
|
|
||||||
"ID_4_AAE08F17428E229EC7A2209F51081A21\0\f\0\0\0IntProperty\0\x04\0\0\0\0\0\0\0\0\x17\x35\f\0,\0\0\0"
|
|
||||||
"Quantity_3_560F09B5485C365D3041888910019CE3\0\f\0\0\0IntProperty";
|
|
||||||
constexpr char alterene_locator[] =
|
|
||||||
"ID_4_AAE08F17428E229EC7A2209F51081A21\0\f\0\0\0IntProperty\0\x04\0\0\0\0\0\0\0\0\x18\x35\f\0,\0\0\0"
|
|
||||||
"Quantity_3_560F09B5485C365D3041888910019CE3\0\f\0\0\0IntProperty";
|
|
||||||
|
|
||||||
constexpr char mixed_composition_locator[] =
|
|
||||||
"ID_4_AAE08F17428E229EC7A2209F51081A21\0\f\0\0\0IntProperty\0\x04\0\0\0\0\0\0\0\0\xa0\xbb\x0d\0,\0\0\0"
|
|
||||||
"Quantity_3_560F09B5485C365D3041888910019CE3\0\f\0\0\0IntProperty";
|
|
||||||
constexpr char void_residue_locator[] =
|
|
||||||
"ID_4_AAE08F17428E229EC7A2209F51081A21\0\f\0\0\0IntProperty\0\x04\0\0\0\0\0\0\0\0\xa1\xbb\x0d\0,\0\0\0"
|
|
||||||
"Quantity_3_560F09B5485C365D3041888910019CE3\0\f\0\0\0IntProperty";
|
|
||||||
constexpr char muscular_construction_locator[] =
|
|
||||||
"ID_4_AAE08F17428E229EC7A2209F51081A21\0\f\0\0\0IntProperty\0\x04\0\0\0\0\0\0\0\0\xa2\xbb\x0d\0,\0\0\0"
|
|
||||||
"Quantity_3_560F09B5485C365D3041888910019CE3\0\f\0\0\0IntProperty";
|
|
||||||
constexpr char mineral_exoskeletology_locator[] =
|
|
||||||
"ID_4_AAE08F17428E229EC7A2209F51081A21\0\f\0\0\0IntProperty\0\x04\0\0\0\0\0\0\0\0\xa3\xbb\x0d\0,\0\0\0"
|
|
||||||
"Quantity_3_560F09B5485C365D3041888910019CE3\0\f\0\0\0IntProperty";
|
|
||||||
constexpr char carbonized_skin_locator[] =
|
|
||||||
"ID_4_AAE08F17428E229EC7A2209F51081A21\0\f\0\0\0IntProperty\0\x04\0\0\0\0\0\0\0\0\xa4\xbb\x0d\0,\0\0\0"
|
|
||||||
"Quantity_3_560F09B5485C365D3041888910019CE3\0\f\0\0\0IntProperty";
|
|
||||||
|
|
||||||
constexpr char engine_inventory_locator[] = "InventoryEngine\0\x0e\0\0\0ArrayProperty";
|
|
||||||
constexpr char gear_inventory_locator[] = "InventoryGear\0\x0e\0\0\0ArrayProperty";
|
|
||||||
constexpr char os_inventory_locator[] = "InventoryOS\0\x0e\0\0\0ArrayProperty";
|
|
||||||
constexpr char module_inventory_locator[] = "InventoryModule\0\x0e\0\0\0ArrayProperty";
|
|
||||||
constexpr char arch_inventory_locator[] = "InventoryArchitect\0\x0e\0\0\0ArrayProperty";
|
|
||||||
constexpr char tech_inventory_locator[] = "InventoryTech\0\x0e\0\0\0ArrayProperty";
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// MassBuilderSaveTool
|
// MassBuilderSaveTool
|
||||||
// Copyright (C) 2021 Guillaume Jacquemin
|
// Copyright (C) 2021-2022 Guillaume Jacquemin
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -20,6 +20,10 @@
|
||||||
|
|
||||||
#include <Magnum/Magnum.h>
|
#include <Magnum/Magnum.h>
|
||||||
|
|
||||||
|
#include "../UESaveFile/UESaveFile.h"
|
||||||
|
|
||||||
|
#include "ResourceIDs.h"
|
||||||
|
|
||||||
using namespace Magnum;
|
using namespace Magnum;
|
||||||
|
|
||||||
enum class ProfileType : UnsignedByte {
|
enum class ProfileType : UnsignedByte {
|
||||||
|
@ -27,6 +31,11 @@ enum class ProfileType : UnsignedByte {
|
||||||
FullGame
|
FullGame
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ProfileVersion : UnsignedByte {
|
||||||
|
Legacy, // pre-0.8
|
||||||
|
Normal // 0.8 and later
|
||||||
|
};
|
||||||
|
|
||||||
class Profile {
|
class Profile {
|
||||||
public:
|
public:
|
||||||
explicit Profile(const std::string& path);
|
explicit Profile(const std::string& path);
|
||||||
|
@ -39,148 +48,128 @@ class Profile {
|
||||||
|
|
||||||
auto type() const -> ProfileType;
|
auto type() const -> ProfileType;
|
||||||
|
|
||||||
auto steamId() const -> std::string const&;
|
auto version() const -> ProfileVersion;
|
||||||
|
|
||||||
|
auto account() const -> std::string const&;
|
||||||
|
|
||||||
void refreshValues();
|
void refreshValues();
|
||||||
|
|
||||||
auto companyName() const -> std::string const&;
|
auto companyName() const -> std::string const&;
|
||||||
auto getCompanyName() -> std::string const&;
|
|
||||||
auto renameCompany(const std::string& new_name) -> bool;
|
auto renameCompany(const std::string& new_name) -> bool;
|
||||||
|
|
||||||
auto activeFrameSlot() const -> Int;
|
auto activeFrameSlot() const -> Int;
|
||||||
auto getActiveFrameSlot() -> Int;
|
|
||||||
|
|
||||||
auto credits() const -> Int;
|
auto credits() const -> Int;
|
||||||
auto getCredits() -> Int;
|
|
||||||
auto setCredits(Int credits) -> bool;
|
auto setCredits(Int credits) -> bool;
|
||||||
|
|
||||||
auto storyProgress() const -> Int;
|
auto storyProgress() const -> Int;
|
||||||
auto getStoryProgress() -> Int;
|
|
||||||
auto setStoryProgress(Int progress) -> bool;
|
auto setStoryProgress(Int progress) -> bool;
|
||||||
|
|
||||||
auto lastMissionId() const -> Int;
|
auto lastMissionId() const -> Int;
|
||||||
auto getLastMissionId() -> Int;
|
|
||||||
|
|
||||||
auto verseSteel() const -> Int;
|
auto verseSteel() const -> Int;
|
||||||
auto getVerseSteel() -> Int;
|
|
||||||
auto setVerseSteel(Int amount) -> bool;
|
auto setVerseSteel(Int amount) -> bool;
|
||||||
|
|
||||||
auto undinium() const -> Int;
|
auto undinium() const -> Int;
|
||||||
auto getUndinium() -> Int;
|
|
||||||
auto setUndinium(Int amount) -> bool;
|
auto setUndinium(Int amount) -> bool;
|
||||||
|
|
||||||
auto necriumAlloy() const -> Int;
|
auto necriumAlloy() const -> Int;
|
||||||
auto getNecriumAlloy() -> Int;
|
|
||||||
auto setNecriumAlloy(Int amount) -> bool;
|
auto setNecriumAlloy(Int amount) -> bool;
|
||||||
|
|
||||||
auto lunarite() const -> Int;
|
auto lunarite() const -> Int;
|
||||||
auto getLunarite() -> Int;
|
|
||||||
auto setLunarite(Int amount) -> bool;
|
auto setLunarite(Int amount) -> bool;
|
||||||
|
|
||||||
auto asterite() const -> Int;
|
auto asterite() const -> Int;
|
||||||
auto getAsterite() -> Int;
|
|
||||||
auto setAsterite(Int amount) -> bool;
|
auto setAsterite(Int amount) -> bool;
|
||||||
|
|
||||||
auto ednil() const -> Int;
|
auto ednil() const -> Int;
|
||||||
auto getEdnil() -> Int;
|
|
||||||
auto setEdnil(Int amount) -> bool;
|
auto setEdnil(Int amount) -> bool;
|
||||||
|
|
||||||
auto nuflalt() const -> Int;
|
auto nuflalt() const -> Int;
|
||||||
auto getNuflalt() -> Int;
|
|
||||||
auto setNuflalt(Int amount) -> bool;
|
auto setNuflalt(Int amount) -> bool;
|
||||||
|
|
||||||
auto aurelene() const -> Int;
|
auto aurelene() const -> Int;
|
||||||
auto getAurelene() -> Int;
|
|
||||||
auto setAurelene(Int amount) -> bool;
|
auto setAurelene(Int amount) -> bool;
|
||||||
|
|
||||||
auto soldus() const -> Int;
|
auto soldus() const -> Int;
|
||||||
auto getSoldus() -> Int;
|
|
||||||
auto setSoldus(Int amount) -> bool;
|
auto setSoldus(Int amount) -> bool;
|
||||||
|
|
||||||
auto synthesizedN() const -> Int;
|
auto synthesisedN() const -> Int;
|
||||||
auto getSynthesizedN() -> Int;
|
auto setSynthesisedN(Int amount) -> bool;
|
||||||
auto setSynthesizedN(Int amount) -> bool;
|
|
||||||
|
|
||||||
auto alcarbonite() const -> Int;
|
auto alcarbonite() const -> Int;
|
||||||
auto getAlcarbonite() -> Int;
|
|
||||||
auto setAlcarbonite(Int amount) -> bool;
|
auto setAlcarbonite(Int amount) -> bool;
|
||||||
|
|
||||||
auto keriphene() const -> Int;
|
auto keriphene() const -> Int;
|
||||||
auto getKeriphene() -> Int;
|
|
||||||
auto setKeriphene(Int amount) -> bool;
|
auto setKeriphene(Int amount) -> bool;
|
||||||
|
|
||||||
auto nitinolCM() const -> Int;
|
auto nitinolCM() const -> Int;
|
||||||
auto getNitinolCM() -> Int;
|
|
||||||
auto setNitinolCM(Int amount) -> bool;
|
auto setNitinolCM(Int amount) -> bool;
|
||||||
|
|
||||||
auto quarkium() const -> Int;
|
auto quarkium() const -> Int;
|
||||||
auto getQuarkium() -> Int;
|
|
||||||
auto setQuarkium(Int amount) -> bool;
|
auto setQuarkium(Int amount) -> bool;
|
||||||
|
|
||||||
auto alterene() const -> Int;
|
auto alterene() const -> Int;
|
||||||
auto getAlterene() -> Int;
|
|
||||||
auto setAlterene(Int amount) -> bool;
|
auto setAlterene(Int amount) -> bool;
|
||||||
|
|
||||||
auto mixedComposition() const -> Int;
|
auto mixedComposition() const -> Int;
|
||||||
auto getMixedComposition() -> Int;
|
|
||||||
auto setMixedComposition(Int amount) -> bool;
|
auto setMixedComposition(Int amount) -> bool;
|
||||||
|
|
||||||
auto voidResidue() const -> Int;
|
auto voidResidue() const -> Int;
|
||||||
auto getVoidResidue() -> Int;
|
|
||||||
auto setVoidResidue(Int amount) -> bool;
|
auto setVoidResidue(Int amount) -> bool;
|
||||||
|
|
||||||
auto muscularConstruction() const -> Int;
|
auto muscularConstruction() const -> Int;
|
||||||
auto getMuscularConstruction() -> Int;
|
|
||||||
auto setMuscularConstruction(Int amount) -> bool;
|
auto setMuscularConstruction(Int amount) -> bool;
|
||||||
|
|
||||||
auto mineralExoskeletology() const -> Int;
|
auto mineralExoskeletology() const -> Int;
|
||||||
auto getMineralExoskeletology() -> Int;
|
|
||||||
auto setMineralExoskeletology(Int amount) -> bool;
|
auto setMineralExoskeletology(Int amount) -> bool;
|
||||||
|
|
||||||
auto carbonizedSkin() const -> Int;
|
auto carbonisedSkin() const -> Int;
|
||||||
auto getCarbonizedSkin() -> Int;
|
auto setCarbonisedSkin(Int amount) -> bool;
|
||||||
auto setCarbonizedSkin(Int amount) -> bool;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _profileDirectory;
|
auto getResource(const char* container, MaterialID id) -> Int;
|
||||||
|
auto setResource(const char* container, MaterialID id, Int amount) -> bool;
|
||||||
|
|
||||||
std::string _filename;
|
std::string _filename;
|
||||||
|
|
||||||
ProfileType _type;
|
ProfileType _type;
|
||||||
|
ProfileVersion _version;
|
||||||
|
|
||||||
std::string _steamId;
|
UESaveFile _profile;
|
||||||
|
|
||||||
|
std::string _name;
|
||||||
|
Int _activeFrameSlot = 0;
|
||||||
|
Int _credits = 0;
|
||||||
|
Int _storyProgress = 0;
|
||||||
|
Int _lastMissionId = 0;
|
||||||
|
|
||||||
|
Int _verseSteel = 0;
|
||||||
|
Int _undinium = 0;
|
||||||
|
Int _necriumAlloy = 0;
|
||||||
|
Int _lunarite = 0;
|
||||||
|
Int _asterite = 0;
|
||||||
|
|
||||||
|
Int _ednil = 0;
|
||||||
|
Int _nuflalt = 0;
|
||||||
|
Int _aurelene = 0;
|
||||||
|
Int _soldus = 0;
|
||||||
|
Int _synthesisedN = 0;
|
||||||
|
|
||||||
|
Int _alcarbonite = 0;
|
||||||
|
Int _keriphene = 0;
|
||||||
|
Int _nitinolCM = 0;
|
||||||
|
Int _quarkium = 0;
|
||||||
|
Int _alterene = 0;
|
||||||
|
|
||||||
|
Int _mixedComposition = 0;
|
||||||
|
Int _voidResidue = 0;
|
||||||
|
Int _muscularConstruction = 0;
|
||||||
|
Int _mineralExoskeletology = 0;
|
||||||
|
Int _carbonisedSkin = 0;
|
||||||
|
|
||||||
|
std::string _account;
|
||||||
|
|
||||||
bool _valid = false;
|
bool _valid = false;
|
||||||
std::string _lastError;
|
std::string _lastError;
|
||||||
|
|
||||||
std::string _companyName;
|
|
||||||
|
|
||||||
Int _activeFrameSlot = 0;
|
|
||||||
|
|
||||||
Int _credits;
|
|
||||||
|
|
||||||
Int _storyProgress;
|
|
||||||
|
|
||||||
Int _lastMissionId;
|
|
||||||
|
|
||||||
Int _verseSteel;
|
|
||||||
Int _undinium;
|
|
||||||
Int _necriumAlloy;
|
|
||||||
Int _lunarite;
|
|
||||||
Int _asterite;
|
|
||||||
Int _ednil;
|
|
||||||
Int _nuflalt;
|
|
||||||
Int _aurelene;
|
|
||||||
Int _soldus;
|
|
||||||
Int _synthesizedN;
|
|
||||||
Int _alcarbonite;
|
|
||||||
Int _keriphene;
|
|
||||||
Int _nitinolCM;
|
|
||||||
Int _quarkium;
|
|
||||||
Int _alterene;
|
|
||||||
|
|
||||||
Int _mixedComposition;
|
|
||||||
Int _voidResidue;
|
|
||||||
Int _muscularConstruction;
|
|
||||||
Int _mineralExoskeletology;
|
|
||||||
Int _carbonizedSkin;
|
|
||||||
};
|
};
|
||||||
|
|
47
src/Profile/ResourceIDs.h
Normal file
47
src/Profile/ResourceIDs.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 <Magnum/Types.h>
|
||||||
|
|
||||||
|
using namespace Magnum;
|
||||||
|
|
||||||
|
enum MaterialID : Int {
|
||||||
|
VerseSteel = 0xC3500,
|
||||||
|
Undinium = 0xC3501,
|
||||||
|
NecriumAlloy = 0xC3502,
|
||||||
|
Lunarite = 0xC3503,
|
||||||
|
Asterite = 0xC3504,
|
||||||
|
|
||||||
|
Ednil = 0xC350A,
|
||||||
|
Nuflalt = 0xC350B,
|
||||||
|
Aurelene = 0xC350C,
|
||||||
|
Soldus = 0xC350D,
|
||||||
|
SynthesisedN = 0xC350E,
|
||||||
|
|
||||||
|
Alcarbonite = 0xC3514,
|
||||||
|
Keriphene = 0xC3515,
|
||||||
|
NitinolCM = 0xC3516,
|
||||||
|
Quarkium = 0xC3517,
|
||||||
|
Alterene = 0xC3518,
|
||||||
|
|
||||||
|
MixedComposition = 0xDBBA0,
|
||||||
|
VoidResidue = 0xDBBA1,
|
||||||
|
MuscularConstruction = 0xDBBA2,
|
||||||
|
MineralExoskeletology = 0xDBBA3,
|
||||||
|
CarbonisedSkin = 0xDBBA4
|
||||||
|
};
|
|
@ -1,5 +1,5 @@
|
||||||
// MassBuilderSaveTool
|
// MassBuilderSaveTool
|
||||||
// Copyright (C) 2021 Guillaume Jacquemin
|
// Copyright (C) 2021-2022 Guillaume Jacquemin
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -31,8 +31,6 @@
|
||||||
|
|
||||||
#include "ProfileManager.h"
|
#include "ProfileManager.h"
|
||||||
|
|
||||||
using namespace Corrade;
|
|
||||||
|
|
||||||
ProfileManager::ProfileManager(const std::string& save_dir, const std::string& backup_dir):
|
ProfileManager::ProfileManager(const std::string& save_dir, const std::string& backup_dir):
|
||||||
_saveDirectory{save_dir},
|
_saveDirectory{save_dir},
|
||||||
_backupsDirectory{backup_dir}
|
_backupsDirectory{backup_dir}
|
||||||
|
@ -48,12 +46,12 @@ auto ProfileManager::lastError() -> std::string const& {
|
||||||
return _lastError;
|
return _lastError;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ProfileManager::profiles() -> std::vector<Profile> const& {
|
auto ProfileManager::profiles() -> Containers::ArrayView<Profile> {
|
||||||
return _profiles;
|
return _profiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ProfileManager::refreshProfiles() -> bool {
|
auto ProfileManager::refreshProfiles() -> bool {
|
||||||
_profiles.clear();
|
_profiles = Containers::Array<Profile>{};
|
||||||
|
|
||||||
using Utility::Directory::Flag;
|
using Utility::Directory::Flag;
|
||||||
std::vector<std::string> files = Utility::Directory::list(_saveDirectory, Flag::SkipSpecial|Flag::SkipDirectories|Flag::SkipDotAndDotDot);
|
std::vector<std::string> files = Utility::Directory::list(_saveDirectory, Flag::SkipSpecial|Flag::SkipDirectories|Flag::SkipDotAndDotDot);
|
||||||
|
@ -74,11 +72,11 @@ auto ProfileManager::refreshProfiles() -> bool {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
_profiles.push_back(std::move(profile));
|
arrayAppend(_profiles, std::move(profile));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_profiles.empty()) {
|
if(_profiles.empty()) {
|
||||||
_lastError = "No profiles were found.";
|
_lastError = "No valid profiles were found.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,14 +84,14 @@ auto ProfileManager::refreshProfiles() -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ProfileManager::getProfile(std::size_t index) -> Profile* {
|
auto ProfileManager::getProfile(std::size_t index) -> Profile* {
|
||||||
return &(_profiles.at(index));
|
return index <= _profiles.size() ? &(_profiles[index]) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ProfileManager::deleteProfile(std::size_t index, bool delete_builds) -> bool {
|
auto ProfileManager::deleteProfile(std::size_t index, bool delete_builds) -> bool {
|
||||||
if(!Utility::Directory::rm(Utility::Directory::join(_saveDirectory, _profiles.at(index).filename()))) {
|
if(!Utility::Directory::rm(Utility::Directory::join(_saveDirectory, _profiles[index].filename()))) {
|
||||||
_lastError = Utility::formatString("Couldn't delete {} (filename: {}).",
|
_lastError = Utility::formatString("Couldn't delete {} (filename: {}).",
|
||||||
_profiles.at(index).companyName(),
|
_profiles[index].companyName(),
|
||||||
_profiles.at(index).filename());
|
_profiles[index].filename());
|
||||||
refreshProfiles();
|
refreshProfiles();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -101,13 +99,18 @@ auto ProfileManager::deleteProfile(std::size_t index, bool delete_builds) -> boo
|
||||||
if(delete_builds) {
|
if(delete_builds) {
|
||||||
for(UnsignedByte i = 0; i < 32; ++i) {
|
for(UnsignedByte i = 0; i < 32; ++i) {
|
||||||
std::string filename = Utility::formatString("{}Unit{:.2d}{}.sav",
|
std::string filename = Utility::formatString("{}Unit{:.2d}{}.sav",
|
||||||
_profiles.at(index).type() == ProfileType::Demo ? "Demo": "",
|
_profiles[index].type() == ProfileType::Demo ? "Demo": "",
|
||||||
i, _profiles.at(index).steamId());
|
i, _profiles[index].account());
|
||||||
Utility::Directory::rm(Utility::Directory::join(_saveDirectory, filename));
|
Utility::Directory::rm(Utility::Directory::join(_saveDirectory, filename));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_profiles.erase(_profiles.cbegin() + index);
|
std::string file = _profiles[index].filename();
|
||||||
|
auto it = std::remove_if(_profiles.begin(), _profiles.end(), [&file](Profile& profile){return profile.filename() == file;});
|
||||||
|
|
||||||
|
if(it != _profiles.end()) {
|
||||||
|
arrayRemoveSuffix(_profiles, 1);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -117,7 +120,7 @@ auto ProfileManager::backupProfile(std::size_t index, bool backup_builds) -> boo
|
||||||
std::tm* time = std::localtime(×tamp);
|
std::tm* time = std::localtime(×tamp);
|
||||||
|
|
||||||
std::string filename = Utility::formatString("{}_{}{:.2d}{:.2d}_{:.2d}{:.2d}{:.2d}.mbprofbackup",
|
std::string filename = Utility::formatString("{}_{}{:.2d}{:.2d}_{:.2d}{:.2d}{:.2d}.mbprofbackup",
|
||||||
Utility::String::replaceAll(_profiles.at(index).companyName(), " ", "_"),
|
Utility::String::replaceAll(_profiles[index].companyName(), " ", "_"),
|
||||||
time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
|
time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
|
||||||
time->tm_hour, time->tm_min, time->tm_sec);
|
time->tm_hour, time->tm_min, time->tm_sec);
|
||||||
|
|
||||||
|
@ -130,21 +133,21 @@ auto ProfileManager::backupProfile(std::size_t index, bool backup_builds) -> boo
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
zip_source_t* profile_source = zip_source_file(zip, Utility::Directory::toNativeSeparators(Utility::Directory::join(_saveDirectory, _profiles.at(index).filename())).c_str(), 0, 0);
|
zip_source_t* profile_source = zip_source_file(zip, Utility::Directory::toNativeSeparators(Utility::Directory::join(_saveDirectory, _profiles[index].filename())).c_str(), 0, 0);
|
||||||
if(profile_source == nullptr) {
|
if(profile_source == nullptr) {
|
||||||
_lastError = zip_strerror(zip);
|
_lastError = zip_strerror(zip);
|
||||||
zip_source_free(profile_source);
|
zip_source_free(profile_source);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(zip_file_add(zip, _profiles.at(index).filename().c_str(), profile_source, ZIP_FL_ENC_UTF_8) == -1) {
|
if(zip_file_add(zip, _profiles[index].filename().c_str(), profile_source, ZIP_FL_ENC_UTF_8) == -1) {
|
||||||
_lastError = zip_strerror(zip);
|
_lastError = zip_strerror(zip);
|
||||||
zip_source_free(profile_source);
|
zip_source_free(profile_source);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string comment = Utility::String::join({_profiles.at(index).companyName(),
|
std::string comment = Utility::String::join({_profiles[index].companyName(),
|
||||||
_profiles.at(index).type() == ProfileType::Demo ? "demo" : "full",
|
_profiles[index].type() == ProfileType::Demo ? "demo" : "full",
|
||||||
Utility::formatString("{}-{:.2d}-{:.2d}-{:.2d}-{:.2d}-{:.2d}",
|
Utility::formatString("{}-{:.2d}-{:.2d}-{:.2d}-{:.2d}-{:.2d}",
|
||||||
time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
|
time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
|
||||||
time->tm_hour, time->tm_min, time->tm_sec)
|
time->tm_hour, time->tm_min, time->tm_sec)
|
||||||
|
@ -154,8 +157,8 @@ auto ProfileManager::backupProfile(std::size_t index, bool backup_builds) -> boo
|
||||||
if(backup_builds) {
|
if(backup_builds) {
|
||||||
for(UnsignedByte i = 0; i < 32; ++i) {
|
for(UnsignedByte i = 0; i < 32; ++i) {
|
||||||
std::string build_filename = Utility::formatString("{}Unit{:.2d}{}.sav",
|
std::string build_filename = Utility::formatString("{}Unit{:.2d}{}.sav",
|
||||||
_profiles.at(index).type() == ProfileType::Demo ? "Demo": "",
|
_profiles[index].type() == ProfileType::Demo ? "Demo": "",
|
||||||
i, _profiles.at(index).steamId());
|
i, _profiles[index].account());
|
||||||
|
|
||||||
if(!Utility::Directory::exists(Utility::Directory::join(_saveDirectory, build_filename))) {
|
if(!Utility::Directory::exists(Utility::Directory::join(_saveDirectory, build_filename))) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -184,12 +187,12 @@ auto ProfileManager::backupProfile(std::size_t index, bool backup_builds) -> boo
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ProfileManager::backups() -> std::vector<Backup> const& {
|
auto ProfileManager::backups() -> Containers::ArrayView<Backup> {
|
||||||
return _backups;
|
return _backups;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfileManager::refreshBackups() {
|
void ProfileManager::refreshBackups() {
|
||||||
_backups.clear();
|
_backups = Containers::Array<Backup>{};
|
||||||
|
|
||||||
using Utility::Directory::Flag;
|
using Utility::Directory::Flag;
|
||||||
std::vector<std::string> files = Utility::Directory::list(_backupsDirectory, Flag::SkipSpecial|Flag::SkipDirectories|Flag::SkipDotAndDotDot);
|
std::vector<std::string> files = Utility::Directory::list(_backupsDirectory, Flag::SkipSpecial|Flag::SkipDirectories|Flag::SkipDotAndDotDot);
|
||||||
|
@ -255,29 +258,34 @@ void ProfileManager::refreshBackups() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
backup.includedFiles.reserve(num_entries);
|
arrayReserve(backup.includedFiles, num_entries);
|
||||||
|
|
||||||
for(Long i = 0; i < num_entries; i++) {
|
for(Long i = 0; i < num_entries; i++) {
|
||||||
backup.includedFiles.emplace_back(zip_get_name(zip, i, ZIP_FL_UNCHANGED));
|
arrayAppend(backup.includedFiles, InPlaceInit, zip_get_name(zip, i, ZIP_FL_UNCHANGED));
|
||||||
}
|
}
|
||||||
|
|
||||||
_backups.push_back(std::move(backup));
|
arrayAppend(_backups, std::move(backup));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ProfileManager::deleteBackup(std::size_t index) -> bool {
|
auto ProfileManager::deleteBackup(std::size_t index) -> bool {
|
||||||
if(!Utility::Directory::rm(Utility::Directory::join(_backupsDirectory, _backups.at(index).filename))) {
|
if(!Utility::Directory::rm(Utility::Directory::join(_backupsDirectory, _backups[index].filename))) {
|
||||||
_lastError = "Couldn't delete " + _backups.at(index).filename;
|
_lastError = "Couldn't delete " + _backups[index].filename;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_backups.erase(_backups.begin() + index);
|
std::string file = _backups[index].filename;
|
||||||
|
auto it = std::remove_if(_backups.begin(), _backups.end(), [&file](Backup& backup){return backup.filename == file;});
|
||||||
|
|
||||||
|
if(it != _backups.end()) {
|
||||||
|
arrayRemoveSuffix(_backups, 1);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ProfileManager::restoreBackup(std::size_t index) -> bool {
|
auto ProfileManager::restoreBackup(std::size_t index) -> bool {
|
||||||
const Backup& backup = _backups.at(index);
|
const Backup& backup = _backups[index];
|
||||||
|
|
||||||
static const char* error_format = "Extraction of file {} failed: {}";
|
static const char* error_format = "Extraction of file {} failed: {}";
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// MassBuilderSaveTool
|
// MassBuilderSaveTool
|
||||||
// Copyright (C) 2021 Guillaume Jacquemin
|
// Copyright (C) 2021-2022 Guillaume Jacquemin
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -17,10 +17,13 @@
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
|
||||||
|
#include <Corrade/Containers/Array.h>
|
||||||
|
|
||||||
#include "../Profile/Profile.h"
|
#include "../Profile/Profile.h"
|
||||||
|
|
||||||
|
using namespace Corrade;
|
||||||
|
|
||||||
struct Backup {
|
struct Backup {
|
||||||
std::string filename;
|
std::string filename;
|
||||||
std::string company;
|
std::string company;
|
||||||
|
@ -33,7 +36,7 @@ struct Backup {
|
||||||
int minute;
|
int minute;
|
||||||
int second;
|
int second;
|
||||||
} timestamp;
|
} timestamp;
|
||||||
std::vector<std::string> includedFiles;
|
Containers::Array<std::string> includedFiles;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ProfileManager {
|
class ProfileManager {
|
||||||
|
@ -43,14 +46,14 @@ class ProfileManager {
|
||||||
auto ready() const -> bool;
|
auto ready() const -> bool;
|
||||||
auto lastError() -> std::string const&;
|
auto lastError() -> std::string const&;
|
||||||
|
|
||||||
auto profiles() -> std::vector<Profile> const&;
|
auto profiles() -> Containers::ArrayView<Profile>;
|
||||||
auto refreshProfiles() -> bool;
|
auto refreshProfiles() -> bool;
|
||||||
|
|
||||||
auto getProfile(std::size_t index) -> Profile*;
|
auto getProfile(std::size_t index) -> Profile*;
|
||||||
auto deleteProfile(std::size_t index, bool delete_builds) -> bool;
|
auto deleteProfile(std::size_t index, bool delete_builds) -> bool;
|
||||||
auto backupProfile(std::size_t index, bool backup_builds) -> bool;
|
auto backupProfile(std::size_t index, bool backup_builds) -> bool;
|
||||||
|
|
||||||
auto backups() -> std::vector<Backup> const&;
|
auto backups() -> Containers::ArrayView<Backup>;
|
||||||
void refreshBackups();
|
void refreshBackups();
|
||||||
|
|
||||||
auto deleteBackup(std::size_t index) -> bool;
|
auto deleteBackup(std::size_t index) -> bool;
|
||||||
|
@ -63,6 +66,6 @@ class ProfileManager {
|
||||||
const std::string& _saveDirectory;
|
const std::string& _saveDirectory;
|
||||||
const std::string& _backupsDirectory;
|
const std::string& _backupsDirectory;
|
||||||
|
|
||||||
std::vector<Profile> _profiles;
|
Containers::Array<Profile> _profiles;
|
||||||
std::vector<Backup> _backups;
|
Containers::Array<Backup> _backups;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// MassBuilderSaveTool
|
// MassBuilderSaveTool
|
||||||
// Copyright (C) 2021 Guillaume Jacquemin
|
// Copyright (C) 2021-2022 Guillaume Jacquemin
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -49,9 +49,6 @@
|
||||||
extern const ImVec2 center_pivot = {0.5f, 0.5f};
|
extern const ImVec2 center_pivot = {0.5f, 0.5f};
|
||||||
|
|
||||||
#ifdef SAVETOOL_DEBUG_BUILD
|
#ifdef SAVETOOL_DEBUG_BUILD
|
||||||
#include <Corrade/Utility/Tweakable.h>
|
|
||||||
|
|
||||||
#define tw CORRADE_TWEAKABLE
|
|
||||||
Utility::Tweakable tweak;
|
Utility::Tweakable tweak;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -65,7 +62,7 @@ SaveTool::SaveTool(const Arguments& arguments):
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(SDL_VERSION_ATLEAST(2, 0, 5)) {
|
if(SDL_VERSION_ATLEAST(2, 0, 5)) {
|
||||||
if(SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1") == SDL_TRUE) {
|
if(SDL_SetHintWithPriority(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1", SDL_HINT_OVERRIDE) == SDL_TRUE) {
|
||||||
Utility::Debug{} << "Clickthrough is available.";
|
Utility::Debug{} << "Clickthrough is available.";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -98,6 +95,10 @@ SaveTool::SaveTool(const Arguments& arguments):
|
||||||
|
|
||||||
_backupsDir = Utility::Directory::join(Utility::Directory::path(Utility::Directory::executableLocation()), "backups");
|
_backupsDir = Utility::Directory::join(Utility::Directory::path(Utility::Directory::executableLocation()), "backups");
|
||||||
_stagingDir = Utility::Directory::join(Utility::Directory::path(Utility::Directory::executableLocation()), "staging");
|
_stagingDir = Utility::Directory::join(Utility::Directory::path(Utility::Directory::executableLocation()), "staging");
|
||||||
|
_armouryDir = Utility::Directory::join(Utility::Directory::path(Utility::Directory::executableLocation()), "armoury");
|
||||||
|
_armoursDir = Utility::Directory::join(_armouryDir, "armours");
|
||||||
|
_weaponsDir = Utility::Directory::join(_armouryDir, "weapons");
|
||||||
|
_stylesDir = Utility::Directory::join(_armouryDir, "styles");
|
||||||
|
|
||||||
if(!Utility::Directory::exists(_backupsDir)) {
|
if(!Utility::Directory::exists(_backupsDir)) {
|
||||||
Utility::Directory::mkpath(_backupsDir);
|
Utility::Directory::mkpath(_backupsDir);
|
||||||
|
@ -107,6 +108,22 @@ SaveTool::SaveTool(const Arguments& arguments):
|
||||||
Utility::Directory::mkpath(_stagingDir);
|
Utility::Directory::mkpath(_stagingDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!Utility::Directory::exists(_armouryDir)) {
|
||||||
|
Utility::Directory::mkpath(_armouryDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!Utility::Directory::exists(_armoursDir)) {
|
||||||
|
Utility::Directory::mkpath(_armoursDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!Utility::Directory::exists(_weaponsDir)) {
|
||||||
|
Utility::Directory::mkpath(_weaponsDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!Utility::Directory::exists(_stylesDir)) {
|
||||||
|
Utility::Directory::mkpath(_stylesDir);
|
||||||
|
}
|
||||||
|
|
||||||
if(!findGameDataDirectory()) {
|
if(!findGameDataDirectory()) {
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error initialising the app", _lastError.c_str(), window());
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error initialising the app", _lastError.c_str(), window());
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
@ -206,43 +223,69 @@ void SaveTool::handleFileAction(efsw::WatchID watch_id,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_moved_after_save = false;
|
||||||
|
|
||||||
switch(action) {
|
switch(action) {
|
||||||
case efsw::Actions::Add:
|
case efsw::Actions::Add:
|
||||||
if(Utility::String::endsWith(filename, _currentProfile->steamId() + ".sav")) {
|
if(Utility::String::endsWith(filename, _currentProfile->account() + ".sav")) {
|
||||||
if(Utility::String::beginsWith(filename, Utility::formatString("{}Unit", _currentProfile->type() == ProfileType::Demo ? "Demo" : ""))) {
|
if(Utility::String::beginsWith(filename, Utility::formatString("{}Unit", _currentProfile->type() == ProfileType::Demo ? "Demo" : ""))) {
|
||||||
int index = ((filename[_currentProfile->type() == ProfileType::Demo ? 8 : 4] - 0x30) * 10) +
|
int index = ((filename[_currentProfile->type() == ProfileType::Demo ? 8 : 4] - 0x30) * 10) +
|
||||||
(filename[_currentProfile->type() == ProfileType::Demo ? 9 : 5] - 0x30);
|
(filename[_currentProfile->type() == ProfileType::Demo ? 9 : 5] - 0x30);
|
||||||
|
if(!_currentMass || _currentMass != &(_massManager->hangar(index))) {
|
||||||
_massManager->refreshHangar(index);
|
_massManager->refreshHangar(index);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
_currentMass->setDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case efsw::Actions::Delete:
|
case efsw::Actions::Delete:
|
||||||
if(Utility::String::endsWith(filename, _currentProfile->steamId() + ".sav")) {
|
if(Utility::String::endsWith(filename, _currentProfile->account() + ".sav")) {
|
||||||
if(Utility::String::beginsWith(filename, Utility::formatString("{}Unit", _currentProfile->type() == ProfileType::Demo ? "Demo" : ""))) {
|
if(Utility::String::beginsWith(filename, Utility::formatString("{}Unit", _currentProfile->type() == ProfileType::Demo ? "Demo" : ""))) {
|
||||||
int index = ((filename[_currentProfile->type() == ProfileType::Demo ? 8 : 4] - 0x30) * 10) +
|
int index = ((filename[_currentProfile->type() == ProfileType::Demo ? 8 : 4] - 0x30) * 10) +
|
||||||
(filename[_currentProfile->type() == ProfileType::Demo ? 9 : 5] - 0x30);
|
(filename[_currentProfile->type() == ProfileType::Demo ? 9 : 5] - 0x30);
|
||||||
|
if(!_currentMass || _currentMass != &(_massManager->hangar(index))) {
|
||||||
_massManager->refreshHangar(index);
|
_massManager->refreshHangar(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case efsw::Actions::Modified:
|
case efsw::Actions::Modified:
|
||||||
if(filename == _currentProfile->filename()) {
|
if(filename == _currentProfile->filename()) {
|
||||||
_currentProfile->refreshValues();
|
_currentProfile->refreshValues();
|
||||||
}
|
}
|
||||||
else if(Utility::String::endsWith(filename, _currentProfile->steamId() + ".sav")) {
|
else if(Utility::String::endsWith(filename, _currentProfile->account() + ".sav")) {
|
||||||
if(Utility::String::beginsWith(filename, Utility::formatString("{}Unit", _currentProfile->type() == ProfileType::Demo ? "Demo" : ""))) {
|
if(Utility::String::beginsWith(filename, Utility::formatString("{}Unit", _currentProfile->type() == ProfileType::Demo ? "Demo" : ""))) {
|
||||||
int index = ((filename[_currentProfile->type() == ProfileType::Demo ? 8 : 4] - 0x30) * 10) +
|
int index = ((filename[_currentProfile->type() == ProfileType::Demo ? 8 : 4] - 0x30) * 10) +
|
||||||
(filename[_currentProfile->type() == ProfileType::Demo ? 9 : 5] - 0x30);
|
(filename[_currentProfile->type() == ProfileType::Demo ? 9 : 5] - 0x30);
|
||||||
|
|
||||||
|
if(!_currentMass || _currentMass != &(_massManager->hangar(index))) {
|
||||||
_massManager->refreshHangar(index);
|
_massManager->refreshHangar(index);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
if(!is_moved_after_save) {
|
||||||
|
is_moved_after_save = false;
|
||||||
|
_currentMass->setDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case efsw::Actions::Moved:
|
case efsw::Actions::Moved:
|
||||||
if(Utility::String::endsWith(filename, _currentProfile->steamId() + ".sav")) {
|
if(Utility::String::endsWith(filename, _currentProfile->account() + ".sav")) {
|
||||||
if(Utility::String::beginsWith(filename, Utility::formatString("{}Unit", _currentProfile->type() == ProfileType::Demo ? "Demo" : ""))) {
|
if(Utility::String::endsWith(old_filename, ".tmp")) {
|
||||||
|
is_moved_after_save = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Utility::String::beginsWith(filename, Utility::formatString("{}Unit", _currentProfile->type() == ProfileType::Demo ? "Demo" : "")) &&
|
||||||
|
Utility::String::endsWith(old_filename, ".sav"))
|
||||||
|
{
|
||||||
int index = ((filename[_currentProfile->type() == ProfileType::Demo ? 8 : 4] - 0x30) * 10) +
|
int index = ((filename[_currentProfile->type() == ProfileType::Demo ? 8 : 4] - 0x30) * 10) +
|
||||||
(filename[_currentProfile->type() == ProfileType::Demo ? 9 : 5] - 0x30);
|
(filename[_currentProfile->type() == ProfileType::Demo ? 9 : 5] - 0x30);
|
||||||
_massManager->refreshHangar(index);
|
_massManager->refreshHangar(index);
|
||||||
|
|
||||||
int old_index = ((old_filename[_currentProfile->type() == ProfileType::Demo ? 8 : 4] - 0x30) * 10) +
|
int old_index = ((old_filename[_currentProfile->type() == ProfileType::Demo ? 8 : 4] - 0x30) * 10) +
|
||||||
(old_filename[_currentProfile->type() == ProfileType::Demo ? 9 : 5] - 0x30);
|
(old_filename[_currentProfile->type() == ProfileType::Demo ? 9 : 5] - 0x30);
|
||||||
_massManager->refreshHangar(old_index);
|
_massManager->refreshHangar(old_index);
|
||||||
|
@ -376,25 +419,37 @@ void SaveTool::updateCheckEvent(SDL_Event& event) {
|
||||||
return ( major * 10000 + minor * 100 + patch) >
|
return ( major * 10000 + minor * 100 + patch) >
|
||||||
(other.major * 10000 + other.minor * 100 + other.patch);
|
(other.major * 10000 + other.minor * 100 + other.patch);
|
||||||
}
|
}
|
||||||
|
operator std::string() const {
|
||||||
|
return Utility::formatString("{}.{}.{}", major, minor, patch);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const Version current_ver{SAVETOOL_VERSION};
|
static const Version current_ver{SAVETOOL_VERSION};
|
||||||
Version latest_ver{response[0]["tag_name"]};
|
|
||||||
|
|
||||||
if(latest_ver == current_ver) {
|
for(auto& release : response) {
|
||||||
_queue.addToast(Toast::Type::Success, "The application is already up to date.");
|
if(release["prerelease"] == true) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else if(latest_ver > current_ver) {
|
|
||||||
|
Version latest_ver{release["tag_name"]};
|
||||||
|
|
||||||
|
if(latest_ver > current_ver || (latest_ver == current_ver && Utility::String::endsWith(SAVETOOL_VERSION, "-pre"))) {
|
||||||
_queue.addToast(Toast::Type::Warning, "Your version is out of date.\nCheck the settings for more information.",
|
_queue.addToast(Toast::Type::Warning, "Your version is out of date.\nCheck the settings for more information.",
|
||||||
std::chrono::milliseconds{5000});
|
std::chrono::milliseconds{5000});
|
||||||
_updateAvailable = true;
|
_updateAvailable = true;
|
||||||
_latestVersion = Utility::formatString("{}.{}.{}", latest_ver.major, latest_ver.minor, latest_ver.patch);
|
_latestVersion = latest_ver;
|
||||||
_releaseLink = response[0]["html_url"];
|
_releaseLink = release["html_url"];
|
||||||
_downloadLink = response[0]["assets"][0]["browser_download_url"];
|
_downloadLink = release["assets"][0]["browser_download_url"];
|
||||||
|
}
|
||||||
|
else if(latest_ver == current_ver || (current_ver > latest_ver && Utility::String::endsWith(SAVETOOL_VERSION, "-pre"))) {
|
||||||
|
_queue.addToast(Toast::Type::Success, "The application is already up to date.");
|
||||||
}
|
}
|
||||||
else if(current_ver > latest_ver) {
|
else if(current_ver > latest_ver) {
|
||||||
_queue.addToast(Toast::Type::Warning, "Your version is more recent than the latest one in the repo. How???");
|
_queue.addToast(Toast::Type::Warning, "Your version is more recent than the latest one in the repo. How???");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveTool::initialiseConfiguration() {
|
void SaveTool::initialiseConfiguration() {
|
||||||
|
@ -526,10 +581,8 @@ auto SaveTool::findGameDataDirectory() -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveTool::initialiseMassManager() {
|
void SaveTool::initialiseMassManager() {
|
||||||
_currentProfile->refreshValues();
|
|
||||||
|
|
||||||
_massManager.emplace(_saveDir,
|
_massManager.emplace(_saveDir,
|
||||||
_currentProfile->steamId(),
|
_currentProfile->account(),
|
||||||
_currentProfile->type() == ProfileType::Demo,
|
_currentProfile->type() == ProfileType::Demo,
|
||||||
_stagingDir);
|
_stagingDir);
|
||||||
|
|
||||||
|
@ -576,6 +629,9 @@ void SaveTool::drawGui() {
|
||||||
case UiState::MainManager:
|
case UiState::MainManager:
|
||||||
drawManager();
|
drawManager();
|
||||||
break;
|
break;
|
||||||
|
case UiState::MassViewer:
|
||||||
|
drawMassViewer();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_aboutPopup) {
|
if(_aboutPopup) {
|
||||||
|
@ -712,7 +768,7 @@ void SaveTool::drawTooltip(const char* text, Float wrap_pos) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveTool::openUri(const std::string& uri) {
|
void SaveTool::openUri(const std::string& uri) {
|
||||||
ShellExecuteW(nullptr, nullptr, Utility::Unicode::widen(uri).c_str(), nullptr, nullptr, SW_SHOW);
|
ShellExecuteW(nullptr, nullptr, Utility::Unicode::widen(uri).c_str(), nullptr, nullptr, SW_SHOWDEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveTool::checkGameState() {
|
void SaveTool::checkGameState() {
|
||||||
|
@ -738,8 +794,7 @@ void SaveTool::checkGameState() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveTool::checkForUpdates() {
|
void SaveTool::checkForUpdates() {
|
||||||
cpr::Response r = cpr::Get(cpr::Url{"https://williamjcm.ovh/git/api/v1/repos/williamjcm/MassBuilderSaveTool/releases"},
|
cpr::Response r = cpr::Get(cpr::Url{"https://williamjcm.ovh/git/api/v1/repos/williamjcm/MassBuilderSaveTool/releases"}, cpr::Timeout{10000});
|
||||||
cpr::Parameters{{"limit", "1"}}, cpr::Timeout{10000});
|
|
||||||
|
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
SDL_zero(event);
|
SDL_zero(event);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// MassBuilderSaveTool
|
// MassBuilderSaveTool
|
||||||
// Copyright (C) 2021 Guillaume Jacquemin
|
// Copyright (C) 2021-2022 Guillaume Jacquemin
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
#include <Magnum/Platform/Sdl2Application.h>
|
#include <Magnum/Platform/Sdl2Application.h>
|
||||||
#include <Magnum/ImGuiIntegration/Context.h>
|
#include <Magnum/ImGuiIntegration/Context.h>
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL.h>
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <imgui_internal.h>
|
#include <imgui_internal.h>
|
||||||
|
@ -36,6 +36,12 @@
|
||||||
#include "../MassManager/MassManager.h"
|
#include "../MassManager/MassManager.h"
|
||||||
#include "../ToastQueue/ToastQueue.h"
|
#include "../ToastQueue/ToastQueue.h"
|
||||||
|
|
||||||
|
#ifdef SAVETOOL_DEBUG_BUILD
|
||||||
|
#include <Corrade/Utility/Tweakable.h>
|
||||||
|
|
||||||
|
#define tw CORRADE_TWEAKABLE
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace Corrade;
|
using namespace Corrade;
|
||||||
using namespace Magnum;
|
using namespace Magnum;
|
||||||
|
|
||||||
|
@ -88,18 +94,48 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener
|
||||||
void drawMainMenu();
|
void drawMainMenu();
|
||||||
void drawDisclaimer();
|
void drawDisclaimer();
|
||||||
void drawInitialisation();
|
void drawInitialisation();
|
||||||
|
|
||||||
void drawProfileManager();
|
void drawProfileManager();
|
||||||
auto drawBackupListPopup() -> ImGuiID;
|
auto drawBackupListPopup() -> ImGuiID;
|
||||||
auto drawBackupProfilePopup(std::size_t profile_index) -> ImGuiID;
|
auto drawBackupProfilePopup(std::size_t profile_index) -> ImGuiID;
|
||||||
auto drawDeleteProfilePopup(std::size_t profile_index) -> ImGuiID;
|
auto drawDeleteProfilePopup(std::size_t profile_index) -> ImGuiID;
|
||||||
|
|
||||||
void drawManager();
|
void drawManager();
|
||||||
auto drawIntEditPopup(int* value_to_edit, int max) -> bool;
|
auto drawIntEditPopup(int* value_to_edit, int max) -> bool;
|
||||||
auto drawRenamePopup(Containers::ArrayView<char> name_view) -> bool;
|
auto drawRenamePopup(Containers::ArrayView<char> name_view) -> bool;
|
||||||
void drawGeneralInfo();
|
void drawGeneralInfo();
|
||||||
void drawResearchInventory();
|
void drawResearchInventory();
|
||||||
|
template<typename Getter, typename Setter>
|
||||||
|
void drawMaterialRow(const char* name, Int tier, Getter getter, Setter setter);
|
||||||
|
void drawUnavailableMaterialRow(const char* name, Int tier);
|
||||||
void drawMassManager();
|
void drawMassManager();
|
||||||
auto drawDeleteMassPopup(int mass_index) -> ImGuiID;
|
auto drawDeleteMassPopup(int mass_index) -> ImGuiID;
|
||||||
auto drawDeleteStagedMassPopup(const std::string& filename) -> ImGuiID;
|
auto drawDeleteStagedMassPopup(const std::string& filename) -> ImGuiID;
|
||||||
|
|
||||||
|
void drawMassViewer();
|
||||||
|
void drawFrameInfo();
|
||||||
|
void drawJointSliders();
|
||||||
|
void drawFrameStyles();
|
||||||
|
void drawEyeColourPicker();
|
||||||
|
void drawCustomFrameStyles();
|
||||||
|
void drawArmour();
|
||||||
|
void drawCustomArmourStyles();
|
||||||
|
void drawWeapons();
|
||||||
|
void drawWeaponCategory(const char* name, Containers::ArrayView<Weapon> weapons_view, bool& dirty, const char* payload_type, const char* payload_tooltip);
|
||||||
|
void drawWeaponEditor(Weapon& weapon);
|
||||||
|
void drawGlobalStyles();
|
||||||
|
void drawTuning();
|
||||||
|
void drawDecalEditor(Decal& decal);
|
||||||
|
void drawAccessoryEditor(Accessory& accessory, Containers::ArrayView<CustomStyle> style_view);
|
||||||
|
auto getStyleName(Int id, Containers::ArrayView<CustomStyle> view) -> const char*;
|
||||||
|
|
||||||
|
enum DCSResult {
|
||||||
|
DCS_Fail,
|
||||||
|
DCS_ResetStyle,
|
||||||
|
DCS_Save
|
||||||
|
};
|
||||||
|
auto drawCustomStyle(CustomStyle& style) -> DCSResult;
|
||||||
|
|
||||||
void drawAbout();
|
void drawAbout();
|
||||||
void drawGameState();
|
void drawGameState();
|
||||||
|
|
||||||
|
@ -136,6 +172,12 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
void drawAlignedText(const char* text, Args... args) {
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
|
ImGui::Text(text, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
void openUri(const std::string& uri);
|
void openUri(const std::string& uri);
|
||||||
|
|
||||||
void checkGameState();
|
void checkGameState();
|
||||||
|
@ -152,7 +194,8 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener
|
||||||
Disclaimer,
|
Disclaimer,
|
||||||
Initialising,
|
Initialising,
|
||||||
ProfileManager,
|
ProfileManager,
|
||||||
MainManager
|
MainManager,
|
||||||
|
MassViewer
|
||||||
} _uiState{UiState::Disclaimer};
|
} _uiState{UiState::Disclaimer};
|
||||||
|
|
||||||
bool _aboutPopup{false};
|
bool _aboutPopup{false};
|
||||||
|
@ -179,6 +222,10 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener
|
||||||
|
|
||||||
std::string _backupsDir;
|
std::string _backupsDir;
|
||||||
std::string _stagingDir;
|
std::string _stagingDir;
|
||||||
|
std::string _armouryDir;
|
||||||
|
std::string _armoursDir;
|
||||||
|
std::string _weaponsDir;
|
||||||
|
std::string _stylesDir;
|
||||||
|
|
||||||
enum class GameState : UnsignedByte {
|
enum class GameState : UnsignedByte {
|
||||||
Unknown, NotRunning, Running
|
Unknown, NotRunning, Running
|
||||||
|
@ -190,6 +237,9 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener
|
||||||
Profile* _currentProfile{nullptr};
|
Profile* _currentProfile{nullptr};
|
||||||
|
|
||||||
Containers::Pointer<MassManager> _massManager;
|
Containers::Pointer<MassManager> _massManager;
|
||||||
|
Mass* _currentMass{nullptr};
|
||||||
|
|
||||||
|
Weapon* _currentWeapon = nullptr;
|
||||||
|
|
||||||
Containers::Pointer<efsw::FileWatcher> _fileWatcher;
|
Containers::Pointer<efsw::FileWatcher> _fileWatcher;
|
||||||
enum watchID {
|
enum watchID {
|
||||||
|
@ -214,5 +264,20 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener
|
||||||
std::string _releaseLink;
|
std::string _releaseLink;
|
||||||
std::string _downloadLink;
|
std::string _downloadLink;
|
||||||
|
|
||||||
|
bool _jointsDirty{false};
|
||||||
|
bool _stylesDirty{false};
|
||||||
|
bool _eyeFlareDirty{false};
|
||||||
|
Containers::StaticArray<38, Int> _selectedArmourDecals{ValueInit};
|
||||||
|
Containers::StaticArray<38, Int> _selectedArmourAccessories{ValueInit};
|
||||||
|
Int _selectedWeaponPart{0};
|
||||||
|
Int _selectedWeaponDecal{0};
|
||||||
|
Int _selectedWeaponAccessory{0};
|
||||||
|
bool _meleeDirty{false};
|
||||||
|
bool _shieldsDirty{false};
|
||||||
|
bool _bShootersDirty{false};
|
||||||
|
bool _eShootersDirty{false};
|
||||||
|
bool _bLaunchersDirty{false};
|
||||||
|
bool _eLaunchersDirty{false};
|
||||||
|
|
||||||
bool _cheatMode{false};
|
bool _cheatMode{false};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// MassBuilderSaveTool
|
// MassBuilderSaveTool
|
||||||
// Copyright (C) 2021 Guillaume Jacquemin
|
// Copyright (C) 2021-2022 Guillaume Jacquemin
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -42,8 +42,7 @@ void SaveTool::drawManager() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::AlignTextToFramePadding();
|
drawAlignedText("Current profile: %s (%s)",
|
||||||
ImGui::Text("Current profile: %s (%s)",
|
|
||||||
_currentProfile->companyName().c_str(),
|
_currentProfile->companyName().c_str(),
|
||||||
_currentProfile->type() == ProfileType::Demo ? "demo" : "full game");
|
_currentProfile->type() == ProfileType::Demo ? "demo" : "full game");
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
@ -107,8 +106,8 @@ auto SaveTool::drawIntEditPopup(int* value_to_edit, int max) -> bool {
|
||||||
drawHelpMarker("You can either drag the widget left or right to change the value,\n"
|
drawHelpMarker("You can either drag the widget left or right to change the value,\n"
|
||||||
"or click on it while holding Ctrl to edit the value directly.");
|
"or click on it while holding Ctrl to edit the value directly.");
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
drawUnsafeWidget([](auto... args){ return ImGui::DragInt("", args...); },
|
drawUnsafeWidget([](auto... args){ return ImGui::SliderInt("", args...); },
|
||||||
value_to_edit, 1.0f, 0, max, "%d", ImGuiSliderFlags_AlwaysClamp);
|
value_to_edit, 0, max, "%d", ImGuiSliderFlags_AlwaysClamp);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if(drawUnsafeWidget([]{ return ImGui::Button("Apply"); })) {
|
if(drawUnsafeWidget([]{ return ImGui::Button("Apply"); })) {
|
||||||
apply = true;
|
apply = true;
|
||||||
|
@ -188,7 +187,7 @@ void SaveTool::drawGeneralInfo() {
|
||||||
{
|
{
|
||||||
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);
|
||||||
if(std::strcmp(it->after, "") == 0) {
|
if(!it->after) {
|
||||||
ImGui::TextWrapped("%s - %s", it->chapter, it->point);
|
ImGui::TextWrapped("%s - %s", it->chapter, it->point);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -226,8 +225,7 @@ void SaveTool::drawGeneralInfo() {
|
||||||
}
|
}
|
||||||
if(drawRenamePopup(name_buf)) {
|
if(drawRenamePopup(name_buf)) {
|
||||||
if(!_currentProfile->renameCompany(name_buf.data())) {
|
if(!_currentProfile->renameCompany(name_buf.data())) {
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",
|
_queue.addToast(Toast::Type::Error, _currentProfile->lastError());
|
||||||
_currentProfile->lastError().c_str(), window());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,8 +242,7 @@ void SaveTool::drawGeneralInfo() {
|
||||||
}
|
}
|
||||||
if(drawIntEditPopup(&credits, 20000000)) {
|
if(drawIntEditPopup(&credits, 20000000)) {
|
||||||
if(!_currentProfile->setCredits(credits)) {
|
if(!_currentProfile->setCredits(credits)) {
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",
|
_queue.addToast(Toast::Type::Error, _currentProfile->lastError());
|
||||||
_currentProfile->lastError().c_str(), window());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,11 +258,10 @@ void SaveTool::drawGeneralInfo() {
|
||||||
}
|
}
|
||||||
for(const auto& sp : story_progress) {
|
for(const auto& sp : story_progress) {
|
||||||
if(ImGui::BeginMenu(sp.chapter)) {
|
if(ImGui::BeginMenu(sp.chapter)) {
|
||||||
if(std::strcmp(sp.after, "") == 0) {
|
if(!sp.after) {
|
||||||
if(ImGui::MenuItem(sp.point)) {
|
if(ImGui::MenuItem(sp.point)) {
|
||||||
if(!_currentProfile->setStoryProgress(sp.id)) {
|
if(!_currentProfile->setStoryProgress(sp.id)) {
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",
|
_queue.addToast(Toast::Type::Error, _currentProfile->lastError());
|
||||||
_currentProfile->lastError().c_str(), window());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -273,8 +269,7 @@ void SaveTool::drawGeneralInfo() {
|
||||||
if(ImGui::BeginMenu(sp.after)) {
|
if(ImGui::BeginMenu(sp.after)) {
|
||||||
if(ImGui::MenuItem(sp.point)) {
|
if(ImGui::MenuItem(sp.point)) {
|
||||||
if(!_currentProfile->setStoryProgress(sp.id)) {
|
if(!_currentProfile->setStoryProgress(sp.id)) {
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",
|
_queue.addToast(Toast::Type::Error, _currentProfile->lastError());
|
||||||
_currentProfile->lastError().c_str(), window());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
|
@ -292,45 +287,6 @@ void SaveTool::drawResearchInventory() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define unavRow(name, tier) \
|
|
||||||
ImGui::TableNextRow(); \
|
|
||||||
ImGui::TableSetColumnIndex(0); \
|
|
||||||
ImGui::TextUnformatted("T" #tier); \
|
|
||||||
ImGui::TableSetColumnIndex(1); \
|
|
||||||
ImGui::TextUnformatted(name); \
|
|
||||||
ImGui::TableSetColumnIndex(2); \
|
|
||||||
ImGui::TextDisabled("Unavailable as of game version " SUPPORTED_GAME_VERSION);
|
|
||||||
|
|
||||||
#define matRow(name, tier, var, getter, setter) \
|
|
||||||
ImGui::TableNextRow(); \
|
|
||||||
ImGui::TableSetColumnIndex(0); \
|
|
||||||
ImGui::TextUnformatted("T" #tier); \
|
|
||||||
ImGui::TableSetColumnIndex(1); \
|
|
||||||
ImGui::TextUnformatted(name); \
|
|
||||||
ImGui::TableSetColumnIndex(2); \
|
|
||||||
if(_currentProfile->getter() != -1) { \
|
|
||||||
ImGui::Text("%i", _currentProfile->getter()); \
|
|
||||||
if(_cheatMode) { \
|
|
||||||
ImGui::TableSetColumnIndex(3); \
|
|
||||||
ImGui::PushID(#setter); \
|
|
||||||
static Int var = _currentProfile->getter(); \
|
|
||||||
if(drawUnsafeWidget([]{ return ImGui::SmallButton(ICON_FA_EDIT); })) { \
|
|
||||||
(var) = _currentProfile->getter(); \
|
|
||||||
ImGui::OpenPopup("int_edit"); \
|
|
||||||
} \
|
|
||||||
if(drawIntEditPopup(&(var), 9999)) { \
|
|
||||||
if(!_currentProfile->set##setter((var))) { \
|
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", \
|
|
||||||
_currentProfile->lastError().c_str(), window()); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
ImGui::PopID(); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
else { \
|
|
||||||
ImGui::TextDisabled("Not found in the save file"); \
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ImGui::BeginTable("##ResearchInventoryTable", 4,
|
if(ImGui::BeginTable("##ResearchInventoryTable", 4,
|
||||||
ImGuiTableFlags_BordersOuter|ImGuiTableFlags_ScrollY|ImGuiTableFlags_BordersInnerH))
|
ImGuiTableFlags_BordersOuter|ImGuiTableFlags_ScrollY|ImGuiTableFlags_BordersInnerH))
|
||||||
{
|
{
|
||||||
|
@ -343,55 +299,136 @@ void SaveTool::drawResearchInventory() {
|
||||||
ImGui::TableSetColumnIndex(1);
|
ImGui::TableSetColumnIndex(1);
|
||||||
ImGui::Text("Engine materials");
|
ImGui::Text("Engine materials");
|
||||||
|
|
||||||
matRow("Verse steel", 1, verse_steel, verseSteel, VerseSteel)
|
drawMaterialRow("Verse steel", 1,
|
||||||
matRow("Undinium", 2, undinium, undinium, Undinium)
|
[this]{ return _currentProfile->verseSteel(); },
|
||||||
matRow("Necrium alloy", 3, necrium_alloy, necriumAlloy, NecriumAlloy)
|
[this](Int amount){ return _currentProfile->setVerseSteel(amount); });
|
||||||
matRow("Lunarite", 4, lunarite, lunarite, Lunarite)
|
drawMaterialRow("Undinium", 2,
|
||||||
matRow("Asterite", 5, asterite, asterite, Asterite)
|
[this]{ return _currentProfile->undinium(); },
|
||||||
unavRow("Hallite fragma", 6)
|
[this](Int amount){ return _currentProfile->setUndinium(amount); });
|
||||||
unavRow("Unnoctinium", 7)
|
drawMaterialRow("Necrium alloy", 3,
|
||||||
|
[this]{ return _currentProfile->necriumAlloy(); },
|
||||||
|
[this](Int amount){ return _currentProfile->setNecriumAlloy(amount); });
|
||||||
|
drawMaterialRow("Lunarite", 4,
|
||||||
|
[this]{ return _currentProfile->lunarite(); },
|
||||||
|
[this](Int amount){ return _currentProfile->setLunarite(amount); });
|
||||||
|
drawMaterialRow("Asterite", 5,
|
||||||
|
[this]{ return _currentProfile->asterite(); },
|
||||||
|
[this](Int amount){ return _currentProfile->setAsterite(amount); });
|
||||||
|
drawUnavailableMaterialRow("Hallite fragma", 6);
|
||||||
|
drawUnavailableMaterialRow("Unnoctinium", 7);
|
||||||
|
|
||||||
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
||||||
ImGui::TableSetColumnIndex(1);
|
ImGui::TableSetColumnIndex(1);
|
||||||
ImGui::Text("OS materials");
|
ImGui::Text("OS materials");
|
||||||
|
|
||||||
matRow("Ednil", 1, ednil, ednil, Ednil)
|
drawMaterialRow("Ednil", 1,
|
||||||
matRow("Nuflalt", 2, nuflalt, nuflalt, Nuflalt)
|
[this]{ return _currentProfile->ednil(); },
|
||||||
matRow("Aurelene", 3, aurelene, aurelene, Aurelene)
|
[this](Int amount){ return _currentProfile->setEdnil(amount); });
|
||||||
matRow("Soldus", 4, soldus, soldus, Soldus)
|
drawMaterialRow("Nuflalt", 2,
|
||||||
matRow("Synthesized N", 5, synthesized_n, synthesizedN, SynthesizedN)
|
[this]{ return _currentProfile->nuflalt(); },
|
||||||
unavRow("Nanoc", 6)
|
[this](Int amount){ return _currentProfile->setNuflalt(amount); });
|
||||||
unavRow("Abyssillite", 7)
|
drawMaterialRow("Aurelene", 3,
|
||||||
|
[this]{ return _currentProfile->aurelene(); },
|
||||||
|
[this](Int amount){ return _currentProfile->setAurelene(amount); });
|
||||||
|
drawMaterialRow("Soldus", 4,
|
||||||
|
[this]{ return _currentProfile->soldus(); },
|
||||||
|
[this](Int amount){ return _currentProfile->setSoldus(amount); });
|
||||||
|
drawMaterialRow("Synthesized N", 5,
|
||||||
|
[this]{ return _currentProfile->synthesisedN(); },
|
||||||
|
[this](Int amount){ return _currentProfile->setSynthesisedN(amount); });
|
||||||
|
drawUnavailableMaterialRow("Nanoc", 6);
|
||||||
|
drawUnavailableMaterialRow("Abyssillite", 7);
|
||||||
|
|
||||||
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
||||||
ImGui::TableSetColumnIndex(1);
|
ImGui::TableSetColumnIndex(1);
|
||||||
ImGui::Text("Architect materials");
|
ImGui::Text("Architect materials");
|
||||||
|
|
||||||
matRow("Alcarbonite", 1, alcarbonite, alcarbonite, Alcarbonite)
|
drawMaterialRow("Alcarbonite", 1,
|
||||||
matRow("Keriphene", 2, keriphene, keriphene, Keriphene)
|
[this]{ return _currentProfile->alcarbonite(); },
|
||||||
matRow("Nitinol-CM", 3, nitinol_cm, nitinolCM, NitinolCM)
|
[this](Int amount){ return _currentProfile->setAlcarbonite(amount); });
|
||||||
matRow("Quarkium", 4, quarkium, quarkium, Quarkium)
|
drawMaterialRow("Keripehene", 2,
|
||||||
matRow("Alterene", 5, alterene, alterene, Alterene)
|
[this]{ return _currentProfile->keriphene(); },
|
||||||
unavRow("Cosmium", 6)
|
[this](Int amount){ return _currentProfile->setKeriphene(amount); });
|
||||||
unavRow("Purified quarkium", 7)
|
drawMaterialRow("Nitinol-CM", 3,
|
||||||
|
[this]{ return _currentProfile->nitinolCM(); },
|
||||||
|
[this](Int amount){ return _currentProfile->setNitinolCM(amount); });
|
||||||
|
drawMaterialRow("Quarkium", 4,
|
||||||
|
[this]{ return _currentProfile->quarkium(); },
|
||||||
|
[this](Int amount){ return _currentProfile->setQuarkium(amount); });
|
||||||
|
drawMaterialRow("Alterene", 5,
|
||||||
|
[this]{ return _currentProfile->alterene(); },
|
||||||
|
[this](Int amount){ return _currentProfile->setAlterene(amount); });
|
||||||
|
drawUnavailableMaterialRow("Cosmium", 6);
|
||||||
|
drawUnavailableMaterialRow("Purified quarkium", 7);
|
||||||
|
|
||||||
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
||||||
ImGui::TableSetColumnIndex(1);
|
ImGui::TableSetColumnIndex(1);
|
||||||
ImGui::Text("Quark data");
|
ImGui::Text("Quark data");
|
||||||
|
|
||||||
matRow("Mixed composition", 1, mixed_composition, mixedComposition, MixedComposition)
|
drawMaterialRow("Mixed composition", 1,
|
||||||
matRow("Void residue", 2, void_residue, voidResidue, VoidResidue)
|
[this]{ return _currentProfile->mixedComposition(); },
|
||||||
matRow("Muscular construction", 3, muscular_construction, muscularConstruction, MuscularConstruction)
|
[this](Int amount){ return _currentProfile->setMixedComposition(amount); });
|
||||||
matRow("Mineral exoskeletology", 4, mineral_exoskeletology, mineralExoskeletology, MineralExoskeletology)
|
drawMaterialRow("Void residue", 2,
|
||||||
matRow("Carbonized skin", 5, carbonized_skin, carbonizedSkin, CarbonizedSkin)
|
[this]{ return _currentProfile->voidResidue(); },
|
||||||
unavRow("Isolated void particle", 6)
|
[this](Int amount){ return _currentProfile->setVoidResidue(amount); });
|
||||||
unavRow("Weaponised physiology", 7)
|
drawMaterialRow("Muscular construction", 3,
|
||||||
|
[this]{ return _currentProfile->muscularConstruction(); },
|
||||||
|
[this](Int amount){ return _currentProfile->setMuscularConstruction(amount); });
|
||||||
|
drawMaterialRow("Mineral exoskeletology", 4,
|
||||||
|
[this]{ return _currentProfile->mineralExoskeletology(); },
|
||||||
|
[this](Int amount){ return _currentProfile->setMineralExoskeletology(amount); });
|
||||||
|
drawMaterialRow("Carbonized skin", 5,
|
||||||
|
[this]{ return _currentProfile->carbonisedSkin(); },
|
||||||
|
[this](Int amount){ return _currentProfile->setCarbonisedSkin(amount); });
|
||||||
|
drawUnavailableMaterialRow("Isolated void particle", 6);
|
||||||
|
drawUnavailableMaterialRow("Weaponised physiology", 7);
|
||||||
|
|
||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#undef unavRow
|
template<typename Getter, typename Setter>
|
||||||
#undef matRow
|
void SaveTool::drawMaterialRow(const char* name, Int tier, Getter getter, Setter setter) {
|
||||||
|
static_assert(std::is_same<decltype(getter()), Int>::value, "getter doesn't return an Int, and/or doesn't take zero arguments.");
|
||||||
|
static_assert(std::is_same<decltype(setter(0)), bool>::value, "setter doesn't return a bool, and/or doesn't take a single Int as an argument.");
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableSetColumnIndex(0);
|
||||||
|
ImGui::Text("T%i", tier);
|
||||||
|
ImGui::TableSetColumnIndex(1);
|
||||||
|
ImGui::TextUnformatted(name);
|
||||||
|
ImGui::TableSetColumnIndex(2);
|
||||||
|
if(getter() != -1) {
|
||||||
|
ImGui::Text("%i", getter());
|
||||||
|
if(_cheatMode) {
|
||||||
|
ImGui::TableSetColumnIndex(3);
|
||||||
|
ImGui::PushID(name);
|
||||||
|
static Int var = 0;
|
||||||
|
if(drawUnsafeWidget(ImGui::SmallButton, ICON_FA_EDIT)) {
|
||||||
|
(var) = getter();
|
||||||
|
ImGui::OpenPopup("int_edit");
|
||||||
|
}
|
||||||
|
if(drawIntEditPopup(&(var), 9999)) {
|
||||||
|
if(!setter(var)) {
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentProfile->lastError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ImGui::TextDisabled("Not found in the save file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveTool::drawUnavailableMaterialRow(const char* name, Int tier) {
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableSetColumnIndex(0);
|
||||||
|
ImGui::Text("T%i", tier);
|
||||||
|
ImGui::TableSetColumnIndex(1);
|
||||||
|
ImGui::TextUnformatted(name);
|
||||||
|
ImGui::TableSetColumnIndex(2);
|
||||||
|
ImGui::TextDisabled("Unavailable as of game version " SUPPORTED_GAME_VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveTool::drawMassManager() {
|
void SaveTool::drawMassManager() {
|
||||||
|
@ -409,7 +446,7 @@ void SaveTool::drawMassManager() {
|
||||||
ImGui::TableSetupColumn("##Hangar", ImGuiTableColumnFlags_WidthFixed);
|
ImGui::TableSetupColumn("##Hangar", ImGuiTableColumnFlags_WidthFixed);
|
||||||
ImGui::TableSetupColumn("##MASSName", ImGuiTableColumnFlags_WidthStretch);
|
ImGui::TableSetupColumn("##MASSName", ImGuiTableColumnFlags_WidthStretch);
|
||||||
ImGui::TableSetupColumn("##Active", ImGuiTableColumnFlags_WidthFixed);
|
ImGui::TableSetupColumn("##Active", ImGuiTableColumnFlags_WidthFixed);
|
||||||
ImGui::TableSetupColumn("##DeleteButton", ImGuiTableColumnFlags_WidthFixed);
|
ImGui::TableSetupColumn("##Buttons", ImGuiTableColumnFlags_WidthFixed);
|
||||||
|
|
||||||
ImGui::TableSetupScrollFreeze(0, 1);
|
ImGui::TableSetupScrollFreeze(0, 1);
|
||||||
|
|
||||||
|
@ -429,17 +466,17 @@ void SaveTool::drawMassManager() {
|
||||||
ImGui::TableSetColumnIndex(0);
|
ImGui::TableSetColumnIndex(0);
|
||||||
ImGui::Selectable(Utility::formatString("{:.2d}", i + 1).c_str(),
|
ImGui::Selectable(Utility::formatString("{:.2d}", i + 1).c_str(),
|
||||||
false, ImGuiSelectableFlags_SpanAllColumns|ImGuiSelectableFlags_AllowItemOverlap);
|
false, ImGuiSelectableFlags_SpanAllColumns|ImGuiSelectableFlags_AllowItemOverlap);
|
||||||
if(_massManager->massState(i) == MassState::Valid &&
|
if(_massManager->hangar(i).state() == Mass::State::Valid &&
|
||||||
ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceNoHoldToOpenOthers))
|
ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceNoHoldToOpenOthers))
|
||||||
{
|
{
|
||||||
drag_drop_index = i;
|
drag_drop_index = i;
|
||||||
ImGui::SetDragDropPayload("Mass", &drag_drop_index, sizeof(int));
|
ImGui::SetDragDropPayload("Mass", &drag_drop_index, sizeof(int));
|
||||||
|
|
||||||
ImGui::Text("%s - Hangar %.2d", _massManager->massName(i).c_str(), i + 1);
|
ImGui::Text("%s - Hangar %.2d", (*_massManager->hangar(i).name()).c_str(), i + 1);
|
||||||
|
|
||||||
ImGui::EndDragDropSource();
|
ImGui::EndDragDropSource();
|
||||||
}
|
}
|
||||||
if((!_unsafeMode && _gameState == GameState::NotRunning) && ImGui::BeginDragDropTarget()) {
|
if((_unsafeMode || _gameState == GameState::NotRunning) && ImGui::BeginDragDropTarget()) {
|
||||||
if(const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("StagedMass")) {
|
if(const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("StagedMass")) {
|
||||||
if(payload->DataSize != sizeof(std::string)) {
|
if(payload->DataSize != sizeof(std::string)) {
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal error",
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal error",
|
||||||
|
@ -451,11 +488,10 @@ void SaveTool::drawMassManager() {
|
||||||
std::string file = *(static_cast<std::string*>(payload->Data));
|
std::string file = *(static_cast<std::string*>(payload->Data));
|
||||||
|
|
||||||
if(!_massManager->importMass(file, i)) {
|
if(!_massManager->importMass(file, i)) {
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error importing M.A.S.S.",
|
_queue.addToast(Toast::Type::Error, _massManager->lastError());
|
||||||
_massManager->lastError().c_str(), window());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(const ImGuiPayload* 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 SaveTool::drawMassManager()",
|
||||||
|
@ -466,9 +502,7 @@ void SaveTool::drawMassManager() {
|
||||||
int index = *(static_cast<int*>(payload->Data));
|
int index = *(static_cast<int*>(payload->Data));
|
||||||
|
|
||||||
if(!_massManager->moveMass(index, i)) {
|
if(!_massManager->moveMass(index, i)) {
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",
|
_queue.addToast(Toast::Type::Error, _massManager->lastError());
|
||||||
_massManager->lastError().c_str(),
|
|
||||||
window());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,15 +510,15 @@ void SaveTool::drawMassManager() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(1);
|
ImGui::TableSetColumnIndex(1);
|
||||||
switch(_massManager->massState(i)) {
|
switch(_massManager->hangar(i).state()) {
|
||||||
case MassState::Empty:
|
case Mass::State::Empty:
|
||||||
ImGui::TextDisabled("<empty>");
|
ImGui::TextDisabled("<empty>");
|
||||||
break;
|
break;
|
||||||
case MassState::Invalid:
|
case Mass::State::Invalid:
|
||||||
ImGui::TextDisabled("<invalid>");
|
ImGui::TextDisabled("<invalid>");
|
||||||
break;
|
break;
|
||||||
case MassState::Valid:
|
case Mass::State::Valid:
|
||||||
ImGui::TextUnformatted(_massManager->massName(i).c_str());
|
ImGui::TextUnformatted((*_massManager->hangar(i).name()).c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,9 +528,21 @@ void SaveTool::drawMassManager() {
|
||||||
drawTooltip("This is the currently active frame slot.");
|
drawTooltip("This is the currently active frame slot.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_massManager->massState(i) != MassState::Empty) {
|
if(_massManager->hangar(i).state() != Mass::State::Empty) {
|
||||||
ImGui::TableSetColumnIndex(3);
|
ImGui::TableSetColumnIndex(3);
|
||||||
ImGui::PushID(i);
|
ImGui::PushID(i);
|
||||||
|
if(_massManager->hangar(i).state() == Mass::State::Valid) {
|
||||||
|
if(ImGui::SmallButton(ICON_FA_SEARCH)) {
|
||||||
|
_currentMass = &_massManager->hangar(i);
|
||||||
|
_uiState = UiState::MassViewer;
|
||||||
|
}
|
||||||
|
ImGui::SameLine(0.0f, 2.0f);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.0f);
|
||||||
|
ImGui::SmallButton(ICON_FA_SEARCH);
|
||||||
|
ImGui::PopStyleVar();
|
||||||
|
}
|
||||||
if(drawUnsafeWidget(ImGui::SmallButton, ICON_FA_TRASH_ALT)) {
|
if(drawUnsafeWidget(ImGui::SmallButton, ICON_FA_TRASH_ALT)) {
|
||||||
mass_to_delete = i;
|
mass_to_delete = i;
|
||||||
ImGui::OpenPopup(mass_deletion_popup_ID);
|
ImGui::OpenPopup(mass_deletion_popup_ID);
|
||||||
|
@ -569,9 +615,7 @@ void SaveTool::drawMassManager() {
|
||||||
int index = *(static_cast<int*>(payload->Data));
|
int index = *(static_cast<int*>(payload->Data));
|
||||||
|
|
||||||
if(!_massManager->exportMass(index)) {
|
if(!_massManager->exportMass(index)) {
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",
|
_queue.addToast(Toast::Type::Error, _massManager->lastError());
|
||||||
_massManager->lastError().c_str(),
|
|
||||||
window());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -588,7 +632,7 @@ auto SaveTool::drawDeleteMassPopup(int mass_index) -> ImGuiID {
|
||||||
return ImGui::GetID("Confirmation##DeleteMassConfirmation");
|
return ImGui::GetID("Confirmation##DeleteMassConfirmation");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_massManager->massState(mass_index) == MassState::Empty) {
|
if(_massManager->hangar(mass_index).state() == Mass::State::Empty) {
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -601,13 +645,13 @@ auto SaveTool::drawDeleteMassPopup(int mass_index) -> ImGuiID {
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::PushTextWrapPos(windowSize().x() * 0.40f);
|
ImGui::PushTextWrapPos(windowSize().x() * 0.40f);
|
||||||
if(_massManager->massState(mass_index) == MassState::Invalid) {
|
if(_massManager->hangar(mass_index).state() == 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);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ImGui::Text("Are you sure you want to delete the M.A.S.S. named %s in hangar %.2i ? This operation is irreversible.",
|
ImGui::Text("Are you sure you want to delete the M.A.S.S. named %s in hangar %.2i ? This operation is irreversible.",
|
||||||
_massManager->massName(mass_index).c_str(), mass_index + 1);
|
(*_massManager->hangar(mass_index).name()).c_str(), mass_index + 1);
|
||||||
}
|
}
|
||||||
ImGui::PopTextWrapPos();
|
ImGui::PopTextWrapPos();
|
||||||
|
|
||||||
|
@ -620,8 +664,7 @@ auto SaveTool::drawDeleteMassPopup(int mass_index) -> ImGuiID {
|
||||||
ImGui::TableSetColumnIndex(1);
|
ImGui::TableSetColumnIndex(1);
|
||||||
if(ImGui::Button("Yes")) {
|
if(ImGui::Button("Yes")) {
|
||||||
if(!_massManager->deleteMass(mass_index)) {
|
if(!_massManager->deleteMass(mass_index)) {
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error when deleting M.A.S.S.",
|
_queue.addToast(Toast::Type::Error, _massManager->lastError());
|
||||||
_massManager->lastError().c_str(), window());
|
|
||||||
}
|
}
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
|
@ -659,8 +702,7 @@ auto SaveTool::drawDeleteStagedMassPopup(const std::string& filename) -> ImGuiID
|
||||||
ImGui::TableSetColumnIndex(1);
|
ImGui::TableSetColumnIndex(1);
|
||||||
if(ImGui::Button("Yes")) {
|
if(ImGui::Button("Yes")) {
|
||||||
if(!_massManager->deleteStagedMass(filename)) {
|
if(!_massManager->deleteStagedMass(filename)) {
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error when deleting M.A.S.S.",
|
_queue.addToast(Toast::Type::Error, _massManager->lastError());
|
||||||
_massManager->lastError().c_str(), window());
|
|
||||||
}
|
}
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
|
|
607
src/SaveTool/SaveTool_MassViewer.cpp
Normal file
607
src/SaveTool/SaveTool_MassViewer.cpp
Normal file
|
@ -0,0 +1,607 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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/ScopeGuard.h>
|
||||||
|
|
||||||
|
#include <Magnum/ImGuiIntegration/Integration.h>
|
||||||
|
|
||||||
|
#include "../Maps/Accessories.h"
|
||||||
|
|
||||||
|
#define STYLENAMES_DEFINITION
|
||||||
|
#include "../Maps/StyleNames.h"
|
||||||
|
|
||||||
|
#include "../FontAwesome/IconsFontAwesome5.h"
|
||||||
|
|
||||||
|
#include "SaveTool.h"
|
||||||
|
|
||||||
|
void SaveTool::drawMassViewer() {
|
||||||
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
||||||
|
_currentMass = nullptr;
|
||||||
|
_currentWeapon = nullptr;
|
||||||
|
_uiState = UiState::MainManager;
|
||||||
|
_queue.addToast(Toast::Type::Error, "The selected M.A.S.S. isn't valid anymore.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SetNextWindowPos({0.0f, ImGui::GetItemRectSize().y}, ImGuiCond_Always);
|
||||||
|
ImGui::SetNextWindowSize({Float(windowSize().x()), Float(windowSize().y()) - ImGui::GetItemRectSize().y},
|
||||||
|
ImGuiCond_Always);
|
||||||
|
if(!ImGui::Begin("##MassViewer", nullptr,
|
||||||
|
ImGuiWindowFlags_NoDecoration|ImGuiWindowFlags_NoMove|
|
||||||
|
ImGuiWindowFlags_NoBackground|ImGuiWindowFlags_NoBringToFrontOnFocus))
|
||||||
|
{
|
||||||
|
ImGui::End();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ImGui::BeginChild("##MassInfo",
|
||||||
|
{0.0f, 0.0f},
|
||||||
|
true, ImGuiWindowFlags_MenuBar))
|
||||||
|
{
|
||||||
|
if(ImGui::BeginMenuBar()) {
|
||||||
|
if(ImGui::BeginTable("##MassViewerMenuTable", 4)) {
|
||||||
|
ImGui::TableSetupColumn("##MassName");
|
||||||
|
ImGui::TableSetupColumn("##Spacer", ImGuiTableColumnFlags_WidthStretch);
|
||||||
|
ImGui::TableSetupColumn("##Updates");
|
||||||
|
ImGui::TableSetupColumn("##Close", ImGuiTableColumnFlags_WidthFixed);
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
|
||||||
|
ImGui::TableSetColumnIndex(0);
|
||||||
|
ImGui::Text("M.A.S.S.: %s", (*_currentMass->name()).c_str());
|
||||||
|
drawTooltip(_currentMass->filename().c_str());
|
||||||
|
|
||||||
|
ImGui::TableSetColumnIndex(2);
|
||||||
|
if(_currentMass->dirty()) {
|
||||||
|
ImGui::TextUnformatted("External changes detected");
|
||||||
|
ImGui::SameLine();
|
||||||
|
if(ImGui::SmallButton(ICON_FA_SYNC_ALT " Refresh")) {
|
||||||
|
_currentMass->refreshValues();
|
||||||
|
_currentMass->setDirty(false);
|
||||||
|
_jointsDirty = false;
|
||||||
|
_stylesDirty = false;
|
||||||
|
_eyeFlareDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TableSetColumnIndex(3);
|
||||||
|
if(ImGui::SmallButton(ICON_FA_TIMES)) {
|
||||||
|
_currentWeapon = nullptr;
|
||||||
|
_currentMass = nullptr;
|
||||||
|
_uiState = UiState::MainManager;
|
||||||
|
_jointsDirty = false;
|
||||||
|
_stylesDirty = false;
|
||||||
|
_eyeFlareDirty = false;
|
||||||
|
_selectedArmourDecals = Containers::StaticArray<38, Int>{ValueInit};
|
||||||
|
_selectedArmourAccessories = Containers::StaticArray<38, Int>{ValueInit};
|
||||||
|
_selectedWeaponPart = 0;
|
||||||
|
_selectedWeaponDecal = 0;
|
||||||
|
_selectedWeaponAccessory = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndMenuBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TextColored(ImColor(255, 255, 0), ICON_FA_EXCLAMATION_TRIANGLE);
|
||||||
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||||
|
ImGui::TextWrapped("WARNING: Colours in this app may look different from in-game colours, due to unavoidable differences in the rendering pipeline.");
|
||||||
|
ImGui::TextColored(ImColor(255, 255, 0), ICON_FA_EXCLAMATION_TRIANGLE);
|
||||||
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||||
|
ImGui::TextWrapped("Real-time updates are disabled on this screen.");
|
||||||
|
|
||||||
|
if(_currentMass) {
|
||||||
|
if(ImGui::BeginTabBar("##MassTabBar")) {
|
||||||
|
if(ImGui::BeginTabItem("Frame")) {
|
||||||
|
drawFrameInfo();
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ImGui::BeginTabItem("Custom frame styles")) {
|
||||||
|
drawCustomFrameStyles();
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ImGui::BeginTabItem("Armour parts")) {
|
||||||
|
drawArmour();
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ImGui::BeginTabItem("Custom armour styles")) {
|
||||||
|
drawCustomArmourStyles();
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ImGui::BeginTabItem("Weapons (WIP)")) {
|
||||||
|
drawWeapons();
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_currentMass->globalStyles().size() != 0 && ImGui::BeginTabItem("Global styles")) {
|
||||||
|
drawGlobalStyles();
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ImGui::BeginTabItem("Tuning (WIP)")) {
|
||||||
|
drawTuning();
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndTabBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveTool::drawGlobalStyles() {
|
||||||
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ImGui::BeginChild("##GlobalStyles")) {
|
||||||
|
ImGui::EndChild();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TextWrapped("In-game values are multiplied by 100. For example, 0.500 here is equal to 50 in-game.");
|
||||||
|
|
||||||
|
for(UnsignedInt i = 0; i < _currentMass->globalStyles().size(); i++) {
|
||||||
|
ImGui::PushID(i);
|
||||||
|
DCSResult result;
|
||||||
|
result = drawCustomStyle(_currentMass->globalStyles()[i]);
|
||||||
|
switch(result) {
|
||||||
|
case DCS_ResetStyle:
|
||||||
|
_currentMass->getGlobalStyles();
|
||||||
|
break;
|
||||||
|
case DCS_Save:
|
||||||
|
if(!_currentMass->writeGlobalStyle(i)) {
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveTool::drawTuning() {
|
||||||
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ImGui::BeginTable("##TuningTable", 3)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TableSetupColumn("##EngineColumn");
|
||||||
|
ImGui::TableSetupColumn("##OSColumn");
|
||||||
|
ImGui::TableSetupColumn("##ArchitectureColumn");
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
|
||||||
|
ImGui::TableSetColumnIndex(0);
|
||||||
|
|
||||||
|
if(ImGui::BeginTable("##EngineTable", 1, ImGuiTableFlags_Borders)) {
|
||||||
|
ImGui::TableSetupColumn("##Engine");
|
||||||
|
|
||||||
|
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted("Engine");
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("%i", _currentMass->engine());
|
||||||
|
|
||||||
|
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted("Gears");
|
||||||
|
|
||||||
|
for(UnsignedInt i = 0; i < _currentMass->gears().size(); i++) {
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("%i", _currentMass->gears()[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TableSetColumnIndex(1);
|
||||||
|
|
||||||
|
if(ImGui::BeginTable("##OSTable", 1, ImGuiTableFlags_Borders)) {
|
||||||
|
ImGui::TableSetupColumn("##OS");
|
||||||
|
|
||||||
|
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted("OS");
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("%i", _currentMass->os());
|
||||||
|
|
||||||
|
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted("Modules");
|
||||||
|
|
||||||
|
for(UnsignedInt i = 0; i < _currentMass->modules().size(); i++) {
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("%i", _currentMass->modules()[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TableSetColumnIndex(2);
|
||||||
|
|
||||||
|
if(ImGui::BeginTable("##ArchTable", 1, ImGuiTableFlags_Borders)) {
|
||||||
|
ImGui::TableSetupColumn("##Arch");
|
||||||
|
|
||||||
|
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted("Architecture");
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("%i", _currentMass->architecture());
|
||||||
|
|
||||||
|
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted("Techs");
|
||||||
|
|
||||||
|
for(UnsignedInt i = 0; i < _currentMass->techs().size(); i++) {
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("%i", _currentMass->techs()[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto SaveTool::drawCustomStyle(CustomStyle& style) -> DCSResult {
|
||||||
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
||||||
|
return DCS_Fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, {8.0f, 0.0f});
|
||||||
|
|
||||||
|
Containers::ScopeGuard guard{[]{ ImGui::PopStyleVar(); }};
|
||||||
|
|
||||||
|
DCSResult return_value = DCS_Fail;
|
||||||
|
|
||||||
|
if(!ImGui::BeginChild("##CustomStyle", {0.0f, 244.0f}, true, ImGuiWindowFlags_MenuBar)) {
|
||||||
|
ImGui::EndChild();
|
||||||
|
return DCS_Fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ImGui::BeginMenuBar()) {
|
||||||
|
ImGui::TextUnformatted(style.name.c_str());
|
||||||
|
|
||||||
|
static Containers::StaticArray<33, char> name_buf{ValueInit};
|
||||||
|
if(ImGui::SmallButton(ICON_FA_EDIT " Rename")) {
|
||||||
|
for(auto& c : name_buf) {
|
||||||
|
c = '\0';
|
||||||
|
}
|
||||||
|
std::strncpy(name_buf.data(), style.name.c_str(), 32);
|
||||||
|
ImGui::OpenPopup("name_edit");
|
||||||
|
}
|
||||||
|
if(drawRenamePopup(name_buf)) {
|
||||||
|
style.name = name_buf.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndMenuBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ImGui::BeginTable("##StyleTable", 2, ImGuiTableFlags_BordersInnerV)) {
|
||||||
|
ImGui::TableSetupColumn("##Colour", ImGuiTableColumnFlags_WidthStretch);
|
||||||
|
ImGui::TableSetupColumn("##Pattern", ImGuiTableColumnFlags_WidthStretch);
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
drawAlignedText("Colour:");
|
||||||
|
drawAlignedText("Metallic:");
|
||||||
|
drawAlignedText("Gloss:");
|
||||||
|
drawAlignedText("Glow:");
|
||||||
|
ImGui::EndGroup();
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
ImGui::ColorEdit3("##Picker", &style.colour.r());
|
||||||
|
ImGui::SameLine();
|
||||||
|
drawHelpMarker("Right-click for more option, click the coloured square for the full picker.");
|
||||||
|
|
||||||
|
ImGui::SetNextItemWidth(-FLT_MIN);
|
||||||
|
ImGui::SliderFloat("##SliderMetallic", &style.metallic, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
ImGui::SetNextItemWidth(-FLT_MIN);
|
||||||
|
ImGui::SliderFloat("##SliderGloss", &style.gloss,0.0f, 1.0f);
|
||||||
|
|
||||||
|
ImGui::Checkbox("##Glow", &style.glow);
|
||||||
|
ImGui::EndGroup();
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
drawAlignedText("Pattern:");
|
||||||
|
drawAlignedText("Opacity:");
|
||||||
|
drawAlignedText("X offset:");
|
||||||
|
drawAlignedText("Y offset:");
|
||||||
|
drawAlignedText("Rotation:");
|
||||||
|
drawAlignedText("Scale:");
|
||||||
|
ImGui::EndGroup();
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
drawAlignedText("%i", style.patternId);
|
||||||
|
ImGui::PushItemWidth(-FLT_MIN);
|
||||||
|
ImGui::SliderFloat("##SliderOpacity", &style.opacity, 0.0f, 1.0f);
|
||||||
|
ImGui::SliderFloat("##SliderOffsetX", &style.offset.x(), 0.0f, 1.0f);
|
||||||
|
ImGui::SliderFloat("##SliderOffsetY", &style.offset.y(), 0.0f, 1.0f);
|
||||||
|
ImGui::SliderFloat("##SliderRotation", &style.rotation, 0.0f, 1.0f);
|
||||||
|
ImGui::SliderFloat("##SliderScale", &style.scale, 0.0f, 1.0f);
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
||||||
|
return_value = DCS_Save;
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if(ImGui::Button(ICON_FA_UNDO " Reset")) {
|
||||||
|
return_value = DCS_ResetStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndChild();
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveTool::drawDecalEditor(Decal& decal) {
|
||||||
|
ImGui::Text("ID: %i", decal.id);
|
||||||
|
|
||||||
|
if(ImGui::BeginTable("##DecalTable", 2, ImGuiTableFlags_BordersInnerV)) {
|
||||||
|
ImGui::TableSetupColumn("##Normal", ImGuiTableColumnFlags_WidthStretch);
|
||||||
|
ImGui::TableSetupColumn("##Advanced", ImGuiTableColumnFlags_WidthStretch);
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
drawAlignedText("Colour:");
|
||||||
|
drawAlignedText("Offset:");
|
||||||
|
drawAlignedText("Rotation:");
|
||||||
|
drawAlignedText("Scale:");
|
||||||
|
drawAlignedText("Flip X:");
|
||||||
|
drawAlignedText("Surface wrap:");
|
||||||
|
ImGui::EndGroup();
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
ImGui::ColorEdit3("##Picker", &decal.colour.r());
|
||||||
|
ImGui::SameLine();
|
||||||
|
drawHelpMarker("Right-click for more option, click the coloured square for the full picker.");
|
||||||
|
|
||||||
|
ImGui::PushMultiItemsWidths(2, ImGui::CalcItemWidth());
|
||||||
|
ImGui::SliderFloat("##OffsetX", &decal.offset.x(), 0.0f, 1.0f, "X: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||||
|
ImGui::SliderFloat("##OffsetY", &decal.offset.y(), 0.0f, 1.0f, "Y: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::SameLine();
|
||||||
|
drawHelpMarker("0.0 = -100 in-game\n1.0 = 100 in-game");
|
||||||
|
|
||||||
|
ImGui::SliderFloat("##Rotation", &decal.rotation, 0.0f, 1.0f);
|
||||||
|
ImGui::SameLine();
|
||||||
|
drawHelpMarker("0.0 = 0 in-game\n1.0 = 360 in-game");
|
||||||
|
|
||||||
|
ImGui::SliderFloat("##Scale", &decal.scale, 0.0f, 1.0f);
|
||||||
|
ImGui::SameLine();
|
||||||
|
drawHelpMarker("0.0 = 1 in-game\n1.0 = 100 in-game");
|
||||||
|
|
||||||
|
ImGui::Checkbox("##Flip", &decal.flip);
|
||||||
|
|
||||||
|
ImGui::Checkbox("##Wrap", &decal.wrap);
|
||||||
|
ImGui::EndGroup();
|
||||||
|
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
|
||||||
|
ImGui::TextColored(ImColor(255, 255, 0), ICON_FA_EXCLAMATION_TRIANGLE);
|
||||||
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||||
|
ImGui::TextUnformatted("Advanced settings. Touch these at your own risk.");
|
||||||
|
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
drawAlignedText("Position:");
|
||||||
|
drawAlignedText("U axis:");
|
||||||
|
drawAlignedText("V axis:");
|
||||||
|
ImGui::EndGroup();
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());
|
||||||
|
ImGui::DragFloat("##PosX", &decal.position.x(), 1.0f, -FLT_MAX, +FLT_MAX, "X: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||||
|
ImGui::DragFloat("##PosY", &decal.position.y(), 1.0f, -FLT_MAX, +FLT_MAX, "Y: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||||
|
ImGui::DragFloat("##PosZ", &decal.position.z(), 1.0f, -FLT_MAX, +FLT_MAX, "Z: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
|
||||||
|
ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());
|
||||||
|
ImGui::DragFloat("##UX", &decal.uAxis.x(), 1.0f, -FLT_MAX, +FLT_MAX, "X: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||||
|
ImGui::DragFloat("##UY", &decal.uAxis.y(), 1.0f, -FLT_MAX, +FLT_MAX, "Y: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||||
|
ImGui::DragFloat("##UZ", &decal.uAxis.z(), 1.0f, -FLT_MAX, +FLT_MAX, "Z: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
|
||||||
|
ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());
|
||||||
|
ImGui::DragFloat("##VX", &decal.vAxis.x(), 1.0f, -FLT_MAX, +FLT_MAX, "X: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||||
|
ImGui::DragFloat("##VY", &decal.vAxis.y(), 1.0f, -FLT_MAX, +FLT_MAX, "Y: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||||
|
ImGui::DragFloat("##VZ", &decal.vAxis.z(), 1.0f, -FLT_MAX, +FLT_MAX, "Z: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveTool::drawAccessoryEditor(Accessory& accessory, Containers::ArrayView<CustomStyle> style_view) {
|
||||||
|
if(accessory.id < 1) {
|
||||||
|
ImGui::TextUnformatted("Accessory: <none>");
|
||||||
|
}
|
||||||
|
else if(accessories.find(accessory.id) != accessories.cend()) {
|
||||||
|
ImGui::Text("Accessory #%i - %s", accessory.id, accessories.at(accessory.id));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ImGui::Text("Accessory #%i", accessory.id);
|
||||||
|
drawTooltip("WARNING: accessory mapping is a WIP.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SAVETOOL_DEBUG_BUILD
|
||||||
|
ImGui::SameLine(0.0f, ImGui::GetStyle().FramePadding.x * 5.0f);
|
||||||
|
ImGui::Text("Attach index: %i", accessory.attachIndex);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
drawAlignedText("Styles:");
|
||||||
|
drawAlignedText("Base position:");
|
||||||
|
drawAlignedText("Position offset:");
|
||||||
|
drawAlignedText("Base rotation:");
|
||||||
|
drawAlignedText("Rotation offset:");
|
||||||
|
drawAlignedText("Scale:");
|
||||||
|
ImGui::EndGroup();
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushMultiItemsWidths(2, ImGui::CalcItemWidth());
|
||||||
|
if(ImGui::BeginCombo("##Style1", getStyleName(accessory.styles[0], style_view))) {
|
||||||
|
for(const auto& style : style_names) {
|
||||||
|
if(ImGui::Selectable(getStyleName(style.first, style_view), accessory.styles[0] == style.first)) {
|
||||||
|
accessory.styles[0] = style.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||||
|
if(ImGui::BeginCombo("##Style2", getStyleName(accessory.styles[1], style_view))) {
|
||||||
|
for(const auto& style : style_names) {
|
||||||
|
if(ImGui::Selectable(getStyleName(style.first, style_view), accessory.styles[1] == style.first)) {
|
||||||
|
accessory.styles[1] = style.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
|
||||||
|
ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());
|
||||||
|
ImGui::DragFloat("##PosX", &accessory.relativePosition.x(), 1.0f, -FLT_MAX, +FLT_MAX, "X: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||||
|
ImGui::DragFloat("##PosY", &accessory.relativePosition.y(), 1.0f, -FLT_MAX, +FLT_MAX, "Y: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||||
|
ImGui::DragFloat("##PosZ", &accessory.relativePosition.z(), 1.0f, -FLT_MAX, +FLT_MAX, "Z: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
|
||||||
|
ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());
|
||||||
|
ImGui::SliderFloat("##PosOffsetX", &accessory.relativePositionOffset.x(), -500.0f, +500.0f, "X: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||||
|
ImGui::SliderFloat("##PosOffsetY", &accessory.relativePositionOffset.y(), -500.0f, +500.0f, "Y: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||||
|
ImGui::SliderFloat("##PosOffsetZ", &accessory.relativePositionOffset.z(), -500.0f, +500.0f, "Z: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::SameLine();
|
||||||
|
drawHelpMarker("+/-500.0 = +/-250 in-game");
|
||||||
|
|
||||||
|
ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());
|
||||||
|
ImGui::DragFloat("##RotX", &accessory.relativeRotation.x(), 1.0f, -FLT_MAX, +FLT_MAX, "Roll: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||||
|
ImGui::DragFloat("##RotY", &accessory.relativeRotation.y(), 1.0f, -FLT_MAX, +FLT_MAX, "Yaw: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||||
|
ImGui::DragFloat("##RotZ", &accessory.relativeRotation.z(), 1.0f, -FLT_MAX, +FLT_MAX, "Pitch: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
|
||||||
|
ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());
|
||||||
|
ImGui::SliderFloat("##RotOffsetX", &accessory.relativeRotationOffset.x(), -180.0f, +180.0f, "Roll: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||||
|
ImGui::SliderFloat("##RotOffsetY", &accessory.relativeRotationOffset.y(), -180.0f, +180.0f, "Yaw: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||||
|
ImGui::SliderFloat("##RotOffsetZ", &accessory.relativeRotationOffset.z(), -180.0f, +180.0f, "Pitch: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
|
||||||
|
ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());
|
||||||
|
ImGui::SliderFloat("##ScaleX", &accessory.localScale.x(), -3.0f, +3.0f, "X: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||||
|
ImGui::SliderFloat("##ScaleY", &accessory.localScale.y(), -3.0f, +3.0f, "Y: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||||
|
ImGui::SliderFloat("##ScaleZ", &accessory.localScale.z(), -3.0f, +3.0f, "Z: %.3f");
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::SameLine();
|
||||||
|
drawHelpMarker("+/-3.0 = +/-150 in-game");
|
||||||
|
ImGui::EndGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto SaveTool::getStyleName(Int id, Containers::ArrayView<CustomStyle> view) -> const char* {
|
||||||
|
if(id >= 0 && id <= 15) {
|
||||||
|
return view[id].name.c_str();
|
||||||
|
}
|
||||||
|
else if(id >= 50 && id <= 65) {
|
||||||
|
return _currentMass->globalStyles()[id - 50].name.c_str();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return style_names.at(id);
|
||||||
|
}
|
||||||
|
}
|
198
src/SaveTool/SaveTool_MassViewer_Armour.cpp
Normal file
198
src/SaveTool/SaveTool_MassViewer_Armour.cpp
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "../FontAwesome/IconsFontAwesome5.h"
|
||||||
|
|
||||||
|
#include "../Maps/ArmourSets.h"
|
||||||
|
#include "../Maps/StyleNames.h"
|
||||||
|
|
||||||
|
#include "SaveTool.h"
|
||||||
|
|
||||||
|
void SaveTool::drawArmour() {
|
||||||
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ImGui::Button(ICON_FA_UNDO_ALT " Reset all")) {
|
||||||
|
_currentMass->getArmourParts();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ImGui::BeginChild("##ArmourParts")) {
|
||||||
|
ImGui::EndChild();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* slot_labels[] = {
|
||||||
|
#define c(enumerator, strenum, name) name,
|
||||||
|
#include "../Maps/ArmourSlots.hpp"
|
||||||
|
#undef c
|
||||||
|
};
|
||||||
|
|
||||||
|
for(UnsignedInt i = 0; i < _currentMass->armourParts().size(); i++) {
|
||||||
|
ImGui::PushID(i);
|
||||||
|
|
||||||
|
auto& part = _currentMass->armourParts()[i];
|
||||||
|
|
||||||
|
static char header[129] = {'\0'};
|
||||||
|
|
||||||
|
std::memset(header, '\0', 129);
|
||||||
|
|
||||||
|
if(armour_sets.find(part.id) != armour_sets.cend()) {
|
||||||
|
std::snprintf(header, 128, "%s: %s###%u", slot_labels[UnsignedInt(part.slot)], armour_sets.at(part.id).name, UnsignedInt(part.slot));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::snprintf(header, 128, "%s: %i###%u", slot_labels[UnsignedInt(part.slot)], part.id, UnsignedInt(part.slot));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ImGui::CollapsingHeader(header)) {
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
|
||||||
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvailWidth() * 0.491f);
|
||||||
|
if(ImGui::BeginListBox("##ChangePart")) {
|
||||||
|
if(std::strncmp("Neck", slot_labels[UnsignedInt(part.slot)], 4) != 0) {
|
||||||
|
for(auto& set : armour_sets) {
|
||||||
|
if(ImGui::Selectable(set.second.name, set.first == part.id, ImGuiSelectableFlags_SpanAvailWidth)) {
|
||||||
|
part.id = set.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for(auto& set : armour_sets) {
|
||||||
|
if(!set.second.neck_compatible) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ImGui::Selectable(set.second.name, set.first == part.id, ImGuiSelectableFlags_SpanAvailWidth)) {
|
||||||
|
part.id = set.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndListBox();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndGroup();
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
|
||||||
|
ImGui::TextUnformatted("Styles:");
|
||||||
|
|
||||||
|
for(Int j = 0; j < 4; j++) {
|
||||||
|
drawAlignedText("Slot %d:", j + 1);
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
ImGui::PushID(j);
|
||||||
|
|
||||||
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvailWidth() - 2.0f);
|
||||||
|
if(ImGui::BeginCombo("##Style", getStyleName(part.styles[j], _currentMass->armourCustomStyles()))) {
|
||||||
|
for(const auto& style : style_names) {
|
||||||
|
if(ImGui::Selectable(getStyleName(style.first, _currentMass->armourCustomStyles()), part.styles[j] == style.first)) {
|
||||||
|
part.styles[j] = style.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndGroup();
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
ImGui::PushID("Decal");
|
||||||
|
|
||||||
|
drawAlignedText("Showing/editing decal");
|
||||||
|
for(UnsignedInt j = 0; j < part.decals.size(); j++) {
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::RadioButton(std::to_string(j + 1).c_str(), &_selectedArmourDecals[i], j);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawDecalEditor(part.decals[_selectedArmourDecals[i]]);
|
||||||
|
|
||||||
|
ImGui::PopID();
|
||||||
|
|
||||||
|
if(!part.accessories.size()) {
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
ImGui::PushID("Accessory");
|
||||||
|
|
||||||
|
drawAlignedText("Showing/editing accessory");
|
||||||
|
for(UnsignedInt j = 0; j < part.accessories.size(); j++) {
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::RadioButton(std::string{char(65 + j)}.c_str(), &_selectedArmourAccessories[i], j);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawAccessoryEditor(part.accessories[_selectedArmourAccessories[i]], _currentMass->armourCustomStyles());
|
||||||
|
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
||||||
|
if(!_currentMass->writeArmourPart(part.slot)) {
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveTool::drawCustomArmourStyles() {
|
||||||
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ImGui::BeginChild("##ArmourStyles")) {
|
||||||
|
ImGui::EndChild();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TextWrapped("In-game values are multiplied by 100. For example, 0.500 here is equal to 50 in-game.");
|
||||||
|
|
||||||
|
for(UnsignedInt i = 0; i < _currentMass->armourCustomStyles().size(); i++) {
|
||||||
|
ImGui::PushID(i);
|
||||||
|
DCSResult result;
|
||||||
|
result = drawCustomStyle(_currentMass->armourCustomStyles()[i]);
|
||||||
|
switch(result) {
|
||||||
|
case DCS_ResetStyle:
|
||||||
|
_currentMass->getArmourCustomStyles();
|
||||||
|
break;
|
||||||
|
case DCS_Save:
|
||||||
|
if(_currentMass->writeArmourCustomStyle(i)) {
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
307
src/SaveTool/SaveTool_MassViewer_Frame.cpp
Normal file
307
src/SaveTool/SaveTool_MassViewer_Frame.cpp
Normal file
|
@ -0,0 +1,307 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "../FontAwesome/IconsFontAwesome5.h"
|
||||||
|
|
||||||
|
#include "../Maps/StyleNames.h"
|
||||||
|
|
||||||
|
#include "SaveTool.h"
|
||||||
|
|
||||||
|
void SaveTool::drawFrameInfo() {
|
||||||
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ImGui::BeginChild("##FrameInfo")) {
|
||||||
|
ImGui::EndChild();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
|
||||||
|
if(ImGui::BeginChild("##JointSliders", {(ImGui::GetContentRegionAvailWidth() / 2.0f) - (ImGui::GetStyle().WindowPadding.x / 2.0f), 300.0f}, true, ImGuiWindowFlags_MenuBar)) {
|
||||||
|
if(ImGui::BeginMenuBar()) {
|
||||||
|
ImGui::TextUnformatted("Joint sliders");
|
||||||
|
|
||||||
|
ImGui::EndMenuBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
drawJointSliders();
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
|
||||||
|
if(ImGui::BeginChild("##FrameStyles", {(ImGui::GetContentRegionAvailWidth() / 2.0f) - (ImGui::GetStyle().WindowPadding.x / 2.0f), 0.0f}, true, ImGuiWindowFlags_MenuBar)) {
|
||||||
|
if(ImGui::BeginMenuBar()) {
|
||||||
|
ImGui::TextUnformatted("Frame styles");
|
||||||
|
|
||||||
|
ImGui::EndMenuBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
drawFrameStyles();
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
|
||||||
|
ImGui::EndGroup();
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
if(ImGui::BeginChild("##EyeFlare", {0.0f, 0.0f}, true, ImGuiWindowFlags_MenuBar)) {
|
||||||
|
if(ImGui::BeginMenuBar()) {
|
||||||
|
ImGui::TextUnformatted("Eye flare colour");
|
||||||
|
drawHelpMarker("Right-click the picker for more options.", 250.0f);
|
||||||
|
|
||||||
|
ImGui::EndMenuBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
drawEyeColourPicker();
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveTool::drawJointSliders() {
|
||||||
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TextWrapped("In-game values are multiplied by 100.\nFor example, 0.500 here is equal to 50 in-game.");
|
||||||
|
|
||||||
|
if(ImGui::BeginTable("##JointSliderTable", 2, ImGuiTableFlags_Borders)) {
|
||||||
|
ImGui::TableSetupColumn("##SliderLabel", ImGuiTableColumnFlags_WidthFixed);
|
||||||
|
ImGui::TableSetupColumn("##Sliders", ImGuiTableColumnFlags_WidthStretch);
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableSetColumnIndex(0);
|
||||||
|
drawAlignedText("Neck");
|
||||||
|
ImGui::TableSetColumnIndex(1);
|
||||||
|
ImGui::SetNextItemWidth(-1.0f);
|
||||||
|
if(ImGui::SliderFloat("##NeckSlider", &_currentMass->jointSliders().neck, 0.0f, 1.0f)) {
|
||||||
|
_jointsDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableSetColumnIndex(0);
|
||||||
|
drawAlignedText("Body");
|
||||||
|
ImGui::TableSetColumnIndex(1);
|
||||||
|
ImGui::SetNextItemWidth(-1.0f);
|
||||||
|
if(ImGui::SliderFloat("##BodySlider", &_currentMass->jointSliders().body, 0.0f, 1.0f)) {
|
||||||
|
_jointsDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableSetColumnIndex(0);
|
||||||
|
drawAlignedText("Shoulders");
|
||||||
|
ImGui::TableSetColumnIndex(1);
|
||||||
|
ImGui::SetNextItemWidth(-1.0f);
|
||||||
|
if(ImGui::SliderFloat("##ShouldersSlider", &_currentMass->jointSliders().shoulders, 0.0f, 1.0f)) {
|
||||||
|
_jointsDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableSetColumnIndex(0);
|
||||||
|
drawAlignedText("Hips");
|
||||||
|
ImGui::TableSetColumnIndex(1);
|
||||||
|
ImGui::SetNextItemWidth(-1.0f);
|
||||||
|
if(ImGui::SliderFloat("##HipsSlider", &_currentMass->jointSliders().hips, 0.0f, 1.0f)) {
|
||||||
|
_jointsDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableSetColumnIndex(0);
|
||||||
|
drawAlignedText("Arms");
|
||||||
|
ImGui::TableSetColumnIndex(1);
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2{2.0f, 1.0f});
|
||||||
|
if(ImGui::BeginTable("##UpperLowerArmsLayoutTable", 2)) {
|
||||||
|
ImGui::TableSetupColumn("##UpperArms", ImGuiTableColumnFlags_WidthStretch);
|
||||||
|
ImGui::TableSetupColumn("##LowerArms", ImGuiTableColumnFlags_WidthStretch);
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::SetNextItemWidth(-1.0f);
|
||||||
|
if(ImGui::SliderFloat("##UpperArmsSlider", &_currentMass->jointSliders().upperArms, 0.0f, 1.0f, "Upper: %.3f")) {
|
||||||
|
_jointsDirty = true;
|
||||||
|
}
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::SetNextItemWidth(-1.0f);
|
||||||
|
if(ImGui::SliderFloat("##LowerArmsSlider", &_currentMass->jointSliders().lowerArms, 0.0f, 1.0f, "Lower: %.3f")) {
|
||||||
|
_jointsDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
ImGui::PopStyleVar();
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableSetColumnIndex(0);
|
||||||
|
drawAlignedText("Legs");
|
||||||
|
ImGui::TableSetColumnIndex(1);
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2{2.0f, 1.0f});
|
||||||
|
if(ImGui::BeginTable("##UpperLowerLegsLayoutTable", 2)) {
|
||||||
|
ImGui::TableSetupColumn("##UpperLegs", ImGuiTableColumnFlags_WidthStretch);
|
||||||
|
ImGui::TableSetupColumn("##LowerLegs", ImGuiTableColumnFlags_WidthStretch);
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::SetNextItemWidth(-1.0f);
|
||||||
|
if(ImGui::SliderFloat("##UpperLegsSlider", &_currentMass->jointSliders().upperLegs, 0.0f, 1.0f, "Upper: %.3f")) {
|
||||||
|
_jointsDirty = true;
|
||||||
|
}
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::SetNextItemWidth(-1.0f);
|
||||||
|
if(ImGui::SliderFloat("##LowerLegsSlider", &_currentMass->jointSliders().lowerLegs, 0.0f, 1.0f, "Lower: %.3f")) {
|
||||||
|
_jointsDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
ImGui::PopStyleVar();
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!_jointsDirty) {
|
||||||
|
ImGui::BeginDisabled();
|
||||||
|
ImGui::Button(ICON_FA_SAVE " Save");
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Button(ICON_FA_UNDO " Reset");
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
||||||
|
if(!_currentMass->writeJointSliders()) {
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
_jointsDirty = false;
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if(ImGui::Button(ICON_FA_UNDO " Reset")) {
|
||||||
|
_currentMass->getJointSliders();
|
||||||
|
_jointsDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveTool::drawFrameStyles() {
|
||||||
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Int i = 0; i < 4; i++) {
|
||||||
|
drawAlignedText("Slot %d:", i + 1);
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
ImGui::PushID(i);
|
||||||
|
|
||||||
|
if(ImGui::BeginCombo("##Style", getStyleName(_currentMass->frameStyles()[i], _currentMass->frameCustomStyles()))) {
|
||||||
|
for(const auto& style : style_names) {
|
||||||
|
if(ImGui::Selectable(getStyleName(style.first, _currentMass->frameCustomStyles()), _currentMass->frameStyles()[i] == style.first)) {
|
||||||
|
_currentMass->frameStyles()[i] = style.first;
|
||||||
|
_stylesDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!_stylesDirty) {
|
||||||
|
ImGui::BeginDisabled();
|
||||||
|
ImGui::Button(ICON_FA_SAVE " Save");
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Button(ICON_FA_UNDO " Reset");
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
||||||
|
if(!_currentMass->writeFrameStyles()) {
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
_stylesDirty = false;
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if(ImGui::Button(ICON_FA_UNDO " Reset")) {
|
||||||
|
_currentMass->getFrameStyles();
|
||||||
|
_stylesDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveTool::drawEyeColourPicker() {
|
||||||
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ImGui::ColorPicker3("##EyeFlarePicker", &_currentMass->eyeFlareColour().x())) {
|
||||||
|
_eyeFlareDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!_eyeFlareDirty) {
|
||||||
|
ImGui::BeginDisabled();
|
||||||
|
ImGui::Button(ICON_FA_SAVE " Save");
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Button(ICON_FA_UNDO " Reset");
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
||||||
|
if(!_currentMass->writeEyeFlareColour()) {
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
_eyeFlareDirty = false;
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if(ImGui::Button(ICON_FA_UNDO " Reset")) {
|
||||||
|
_currentMass->getEyeFlareColour();
|
||||||
|
_eyeFlareDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveTool::drawCustomFrameStyles() {
|
||||||
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ImGui::BeginChild("##FrameStyles")) {
|
||||||
|
ImGui::EndChild();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TextWrapped("In-game values are multiplied by 100. For example, 0.500 here is equal to 50 in-game.");
|
||||||
|
|
||||||
|
for(UnsignedInt i = 0; i < _currentMass->frameCustomStyles().size(); i++) {
|
||||||
|
ImGui::PushID(i);
|
||||||
|
DCSResult result;
|
||||||
|
result = drawCustomStyle(_currentMass->frameCustomStyles()[i]);
|
||||||
|
switch(result) {
|
||||||
|
case DCS_ResetStyle:
|
||||||
|
_currentMass->getFrameCustomStyles();
|
||||||
|
break;
|
||||||
|
case DCS_Save:
|
||||||
|
if(!_currentMass->writeFrameCustomStyle(i)) {
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
475
src/SaveTool/SaveTool_MassViewer_Weapons.cpp
Normal file
475
src/SaveTool/SaveTool_MassViewer_Weapons.cpp
Normal file
|
@ -0,0 +1,475 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "../FontAwesome/IconsFontAwesome5.h"
|
||||||
|
|
||||||
|
#include "../Maps/StyleNames.h"
|
||||||
|
|
||||||
|
#include "SaveTool.h"
|
||||||
|
|
||||||
|
void SaveTool::drawWeapons() {
|
||||||
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
||||||
|
_currentWeapon = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
|
||||||
|
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
|
||||||
|
if(!ImGui::BeginTable("##WeaponsList", 1,
|
||||||
|
ImGuiTableFlags_ScrollY|ImGuiTableFlags_BordersOuter|ImGuiTableFlags_BordersInnerH,
|
||||||
|
{ImGui::GetContentRegionAvailWidth() * 0.2f, -footer_height_to_reserve}))
|
||||||
|
{
|
||||||
|
ImGui::EndGroup();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TableSetupColumn("Weapon");
|
||||||
|
|
||||||
|
drawWeaponCategory("Melee weapons", _currentMass->meleeWeapons(), _meleeDirty, "MeleeWeapon", "Melee weapon");
|
||||||
|
drawWeaponCategory("Shield", _currentMass->shields(), _shieldsDirty, "Shield", "Shield");
|
||||||
|
drawWeaponCategory("Bullet shooters", _currentMass->bulletShooters(), _bShootersDirty, "BShooter", "Bullet shooter");
|
||||||
|
drawWeaponCategory("Energy shooters", _currentMass->energyShooters(), _eShootersDirty, "EShooter", "Energy shooter");
|
||||||
|
drawWeaponCategory("Bullet launchers", _currentMass->bulletLaunchers(), _bLaunchersDirty, "BLauncher", "Bullet launcher");
|
||||||
|
drawWeaponCategory("Energy launchers", _currentMass->energyLaunchers(), _eLaunchersDirty, "ELauncher", "Energy launcher");
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
|
||||||
|
bool dirty = _meleeDirty || _shieldsDirty || _bShootersDirty || _eShootersDirty || _bLaunchersDirty || _eLaunchersDirty;
|
||||||
|
|
||||||
|
if(!dirty) {
|
||||||
|
ImGui::BeginDisabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
||||||
|
if(_meleeDirty) {
|
||||||
|
if(!_currentMass->writeMeleeWeapons()) {
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_meleeDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_shieldsDirty) {
|
||||||
|
if(!_currentMass->writeShields()) {
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_shieldsDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_bShootersDirty) {
|
||||||
|
if(!_currentMass->writeBulletShooters()) {
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_bShootersDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_eShootersDirty) {
|
||||||
|
if(_currentMass->writeEnergyShooters()) {
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_eShootersDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_bLaunchersDirty) {
|
||||||
|
if(_currentMass->writeBulletLaunchers()) {
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_bLaunchersDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_eLaunchersDirty) {
|
||||||
|
if(_currentMass->writeEnergyLaunchers()) {
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_eLaunchersDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
if(ImGui::Button(ICON_FA_UNDO_ALT " Reset")) {
|
||||||
|
if(_meleeDirty) {
|
||||||
|
_currentMass->getMeleeWeapons();
|
||||||
|
_meleeDirty = false;
|
||||||
|
}
|
||||||
|
if(_shieldsDirty) {
|
||||||
|
_currentMass->getShields();
|
||||||
|
_shieldsDirty = false;
|
||||||
|
}
|
||||||
|
if(_bShootersDirty) {
|
||||||
|
_currentMass->getBulletShooters();
|
||||||
|
_bShootersDirty = false;
|
||||||
|
}
|
||||||
|
if(_eShootersDirty) {
|
||||||
|
_currentMass->getEnergyShooters();
|
||||||
|
_eShootersDirty = false;
|
||||||
|
}
|
||||||
|
if(_bLaunchersDirty) {
|
||||||
|
_currentMass->getBulletLaunchers();
|
||||||
|
_bLaunchersDirty = false;
|
||||||
|
}
|
||||||
|
if(_eLaunchersDirty) {
|
||||||
|
_currentMass->getEnergyLaunchers();
|
||||||
|
_eLaunchersDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!dirty) {
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndGroup();
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
if(!_currentWeapon) {
|
||||||
|
ImGui::TextUnformatted("No weapon selected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
|
||||||
|
if(!ImGui::BeginChild("##WeaponChild", {0.0f, -footer_height_to_reserve})) {
|
||||||
|
ImGui::EndChild();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
drawWeaponEditor(*_currentWeapon);
|
||||||
|
|
||||||
|
ImGui::EndChild();
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
if(drawUnsafeWidget([](){ return ImGui::Button(ICON_FA_SAVE " Save changes to weapon category"); })) {
|
||||||
|
switch(_currentWeapon->type) {
|
||||||
|
case WeaponType::Melee:
|
||||||
|
if(!_currentMass->writeMeleeWeapons()) {
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WeaponType::Shield:
|
||||||
|
if(!_currentMass->writeShields()) {
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WeaponType::BulletShooter:
|
||||||
|
if(!_currentMass->writeBulletShooters()) {
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WeaponType::EnergyShooter:
|
||||||
|
if(!_currentMass->writeEnergyShooters()) {
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WeaponType::BulletLauncher:
|
||||||
|
if(!_currentMass->writeBulletLaunchers()) {
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WeaponType::EnergyLauncher:
|
||||||
|
if(!_currentMass->writeEnergyLaunchers()) {
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_queue.addToast(Toast::Type::Error, "Unknown weapon type");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
if(ImGui::Button(ICON_FA_UNDO_ALT " Reset weapon category")) {
|
||||||
|
switch(_currentWeapon->type) {
|
||||||
|
case WeaponType::Melee:
|
||||||
|
_currentMass->getMeleeWeapons();
|
||||||
|
break;
|
||||||
|
case WeaponType::Shield:
|
||||||
|
_currentMass->getShields();
|
||||||
|
break;
|
||||||
|
case WeaponType::BulletShooter:
|
||||||
|
_currentMass->getBulletShooters();
|
||||||
|
break;
|
||||||
|
case WeaponType::EnergyShooter:
|
||||||
|
_currentMass->getEnergyShooters();
|
||||||
|
break;
|
||||||
|
case WeaponType::BulletLauncher:
|
||||||
|
_currentMass->getBulletLaunchers();
|
||||||
|
break;
|
||||||
|
case WeaponType::EnergyLauncher:
|
||||||
|
_currentMass->getEnergyLaunchers();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_queue.addToast(Toast::Type::Error, "Unknown weapon type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveTool::drawWeaponCategory(const char* name, Containers::ArrayView<Weapon> weapons_view, bool& dirty,
|
||||||
|
const char* payload_type, const char* payload_tooltip)
|
||||||
|
{
|
||||||
|
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted(name);
|
||||||
|
|
||||||
|
ImGui::PushID(payload_type);
|
||||||
|
|
||||||
|
for(UnsignedInt i = 0; i < weapons_view.size(); i++) {
|
||||||
|
auto& weapon = weapons_view[i];
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
|
||||||
|
ImGui::PushID(i);
|
||||||
|
|
||||||
|
if(ImGui::Selectable(weapon.name.c_str(), _currentWeapon == &weapon)) {
|
||||||
|
_currentWeapon = &weapon;
|
||||||
|
}
|
||||||
|
if(ImGui::BeginDragDropSource()) {
|
||||||
|
ImGui::SetDragDropPayload(payload_type, &i, sizeof(UnsignedInt));
|
||||||
|
if(ImGui::GetIO().KeyCtrl) {
|
||||||
|
ImGui::Text("%s %i - %s (copy)", payload_tooltip, i + 1, weapon.name.c_str());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ImGui::Text("%s %i - %s", payload_tooltip, i + 1, weapon.name.c_str());
|
||||||
|
}
|
||||||
|
ImGui::EndDragDropSource();
|
||||||
|
}
|
||||||
|
if(ImGui::BeginDragDropTarget()) {
|
||||||
|
if(const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(payload_type)) {
|
||||||
|
int index = *static_cast<int*>(payload->Data);
|
||||||
|
|
||||||
|
if(!ImGui::GetIO().KeyCtrl) {
|
||||||
|
if(_currentWeapon == &weapons_view[index]) {
|
||||||
|
_currentWeapon = &weapons_view[i];
|
||||||
|
}
|
||||||
|
else if (_currentWeapon == &weapons_view[i]) {
|
||||||
|
_currentWeapon = &weapons_view[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::swap(weapons_view[index], weapons_view[i]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
weapons_view[i] = weapons_view[index];
|
||||||
|
}
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndDragDropTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::PopID();
|
||||||
|
|
||||||
|
if(weapon.attached == true) {
|
||||||
|
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, 0x1F008CFFu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveTool::drawWeaponEditor(Weapon& weapon) {
|
||||||
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid || !_currentWeapon) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* labels[] {
|
||||||
|
#define c(enumerator, strenum, name) name,
|
||||||
|
#include "../Maps/WeaponTypes.hpp"
|
||||||
|
#undef c
|
||||||
|
};
|
||||||
|
|
||||||
|
drawAlignedText("%s: %s", labels[UnsignedInt(weapon.type)], weapon.name.c_str());
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
static Containers::StaticArray<33, char> name_buf{ValueInit};
|
||||||
|
if(ImGui::Button(ICON_FA_EDIT " Rename")) {
|
||||||
|
for(auto& c : name_buf) {
|
||||||
|
c = '\0';
|
||||||
|
}
|
||||||
|
std::strncpy(name_buf.data(), weapon.name.c_str(), 32);
|
||||||
|
ImGui::OpenPopup("name_edit");
|
||||||
|
}
|
||||||
|
if(drawRenamePopup(name_buf)) {
|
||||||
|
weapon.name = name_buf.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
drawAlignedText("Equipped:");
|
||||||
|
|
||||||
|
if(weapon.type != WeaponType::Shield) {
|
||||||
|
drawAlignedText("Damage type:");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(weapon.type == WeaponType::Melee) {
|
||||||
|
drawAlignedText("Dual-wield:");
|
||||||
|
|
||||||
|
drawAlignedText("Custom effect mode:");
|
||||||
|
|
||||||
|
drawAlignedText("Custom effect colour:");
|
||||||
|
}
|
||||||
|
ImGui::EndGroup();
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
ImGui::Checkbox("##EquippedCheckbox", &weapon.attached);
|
||||||
|
|
||||||
|
if(weapon.type != WeaponType::Shield) {
|
||||||
|
if(weapon.type == WeaponType::Melee &&
|
||||||
|
ImGui::RadioButton("Physical##NoElement", weapon.damageType == DamageType::Physical))
|
||||||
|
{
|
||||||
|
weapon.damageType = DamageType::Physical;
|
||||||
|
}
|
||||||
|
else if((weapon.type == WeaponType::BulletShooter || weapon.type == WeaponType::BulletLauncher) &&
|
||||||
|
ImGui::RadioButton("Piercing##NoElement", weapon.damageType == DamageType::Piercing))
|
||||||
|
{
|
||||||
|
weapon.damageType = DamageType::Piercing;
|
||||||
|
}
|
||||||
|
else if((weapon.type == WeaponType::EnergyShooter || weapon.type == WeaponType::EnergyLauncher) &&
|
||||||
|
ImGui::RadioButton("Plasma##NoElement", weapon.damageType == DamageType::Plasma))
|
||||||
|
{
|
||||||
|
weapon.damageType = DamageType::Plasma;
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if(ImGui::RadioButton("Heat##Heat", weapon.damageType == DamageType::Heat)) {
|
||||||
|
weapon.damageType = DamageType::Heat;
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if(ImGui::RadioButton("Freeze##Freeze", weapon.damageType == DamageType::Freeze)) {
|
||||||
|
weapon.damageType = DamageType::Freeze;
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if(ImGui::RadioButton("Shock##Shock", weapon.damageType == DamageType::Freeze)) {
|
||||||
|
weapon.damageType = DamageType::Freeze;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(weapon.type == WeaponType::Melee) {
|
||||||
|
ImGui::Checkbox("##DualWield", &weapon.dualWield);
|
||||||
|
|
||||||
|
if(ImGui::RadioButton("Default##Default", weapon.effectColourMode == EffectColourMode::Default)) {
|
||||||
|
weapon.effectColourMode = EffectColourMode::Default;
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if(ImGui::RadioButton("Custom##Custom", weapon.effectColourMode == EffectColourMode::Custom)) {
|
||||||
|
weapon.effectColourMode = EffectColourMode::Custom;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool custom_effect = (weapon.effectColourMode == EffectColourMode::Custom);
|
||||||
|
if(!custom_effect) {
|
||||||
|
ImGui::BeginDisabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::ColorEdit3("##CustomEffectColourPicker", &weapon.effectColour.x(), ImGuiColorEditFlags_HDR|ImGuiColorEditFlags_Float);
|
||||||
|
|
||||||
|
if(!custom_effect) {
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndGroup();
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
if(ImGui::CollapsingHeader("Weapon parts")) {
|
||||||
|
drawAlignedText("Viewing/editing part:");
|
||||||
|
for(Int i = 0; UnsignedLong(i) < weapon.parts.size(); i++) {
|
||||||
|
if(UnsignedLong(_selectedWeaponPart) >= weapon.parts.size()) {
|
||||||
|
_selectedWeaponPart = 0;
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::RadioButton(std::to_string(i + 1).c_str(), &_selectedWeaponPart, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& part = weapon.parts[_selectedWeaponPart];
|
||||||
|
|
||||||
|
ImGui::Text("ID: %i", part.id);
|
||||||
|
|
||||||
|
if(ImGui::BeginChild("##PartDetails", {0.0f, 0.0f}, true)) {
|
||||||
|
ImGui::TextUnformatted("Styles:");
|
||||||
|
|
||||||
|
for(Int i = 0; i < 4; i++) {
|
||||||
|
drawAlignedText("Slot %d:", i + 1);
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
ImGui::PushID(i);
|
||||||
|
|
||||||
|
if(ImGui::BeginCombo("##Style", getStyleName(part.styles[i], weapon.customStyles))) {
|
||||||
|
for(const auto& style: style_names) {
|
||||||
|
if(ImGui::Selectable(getStyleName(style.first, weapon.customStyles),
|
||||||
|
part.styles[i] == style.first)) {
|
||||||
|
part.styles[i] = style.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
ImGui::PushID("Decal");
|
||||||
|
|
||||||
|
drawAlignedText("Showing/editing decal");
|
||||||
|
for(UnsignedLong i = 0; i < part.decals.size(); i++) {
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::RadioButton(std::to_string(i + 1).c_str(), &_selectedWeaponDecal, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawDecalEditor(part.decals[_selectedWeaponDecal]);
|
||||||
|
|
||||||
|
ImGui::PopID();
|
||||||
|
|
||||||
|
if(part.accessories.size() != 0) {
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
ImGui::PushID("Accessory");
|
||||||
|
|
||||||
|
drawAlignedText("Showing/editing accessory");
|
||||||
|
for(UnsignedLong i = 0; i < part.accessories.size(); i++) {
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::RadioButton(std::string{char(65 + i)}.c_str(), &_selectedWeaponAccessory, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawAccessoryEditor(part.accessories[_selectedWeaponAccessory], weapon.customStyles);
|
||||||
|
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
// MassBuilderSaveTool
|
// MassBuilderSaveTool
|
||||||
// Copyright (C) 2021 Guillaume Jacquemin
|
// Copyright (C) 2021-2022 Guillaume Jacquemin
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -81,7 +81,7 @@ void SaveTool::drawProfileManager() {
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(0);
|
ImGui::TableSetColumnIndex(0);
|
||||||
ImGui::PushID(i);
|
ImGui::PushID(i);
|
||||||
if(ImGui::Selectable(_profileManager->profiles().at(i).companyName().c_str(), false,
|
if(ImGui::Selectable(_profileManager->profiles()[i].companyName().c_str(), false,
|
||||||
ImGuiSelectableFlags_SpanAllColumns|ImGuiSelectableFlags_AllowItemOverlap))
|
ImGuiSelectableFlags_SpanAllColumns|ImGuiSelectableFlags_AllowItemOverlap))
|
||||||
{
|
{
|
||||||
_currentProfile = _profileManager->getProfile(i);
|
_currentProfile = _profileManager->getProfile(i);
|
||||||
|
@ -90,7 +90,7 @@ void SaveTool::drawProfileManager() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(1);
|
ImGui::TableSetColumnIndex(1);
|
||||||
ImGui::TextUnformatted(_profileManager->profiles().at(i).type() == ProfileType::Demo ? "Demo" : "Full");
|
ImGui::TextUnformatted(_profileManager->profiles()[i].type() == ProfileType::Demo ? "Demo (legacy)" : "Full (legacy)");
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(2);
|
ImGui::TableSetColumnIndex(2);
|
||||||
if(ImGui::SmallButton(ICON_FA_FILE_ARCHIVE)) {
|
if(ImGui::SmallButton(ICON_FA_FILE_ARCHIVE)) {
|
||||||
|
@ -132,13 +132,13 @@ auto SaveTool::drawBackupListPopup() -> ImGuiID {
|
||||||
{
|
{
|
||||||
ImGui::PushTextWrapPos(windowSize().x() * 0.40f);
|
ImGui::PushTextWrapPos(windowSize().x() * 0.40f);
|
||||||
ImGui::Text("Are you sure you want to restore the %s backup from %.4i-%.2i-%.2i %.2i:%.2i:%.2i ? Any existing data will be overwritten.",
|
ImGui::Text("Are you sure you want to restore the %s backup from %.4i-%.2i-%.2i %.2i:%.2i:%.2i ? Any existing data will be overwritten.",
|
||||||
_profileManager->backups().at(backup_index).company.c_str(),
|
_profileManager->backups()[backup_index].company.c_str(),
|
||||||
_profileManager->backups().at(backup_index).timestamp.year,
|
_profileManager->backups()[backup_index].timestamp.year,
|
||||||
_profileManager->backups().at(backup_index).timestamp.month,
|
_profileManager->backups()[backup_index].timestamp.month,
|
||||||
_profileManager->backups().at(backup_index).timestamp.day,
|
_profileManager->backups()[backup_index].timestamp.day,
|
||||||
_profileManager->backups().at(backup_index).timestamp.hour,
|
_profileManager->backups()[backup_index].timestamp.hour,
|
||||||
_profileManager->backups().at(backup_index).timestamp.minute,
|
_profileManager->backups()[backup_index].timestamp.minute,
|
||||||
_profileManager->backups().at(backup_index).timestamp.second);
|
_profileManager->backups()[backup_index].timestamp.second);
|
||||||
ImGui::PopTextWrapPos();
|
ImGui::PopTextWrapPos();
|
||||||
|
|
||||||
if(ImGui::BeginTable("##RestoreBackupLayout", 2)) {
|
if(ImGui::BeginTable("##RestoreBackupLayout", 2)) {
|
||||||
|
@ -150,8 +150,7 @@ auto SaveTool::drawBackupListPopup() -> ImGuiID {
|
||||||
ImGui::TableSetColumnIndex(1);
|
ImGui::TableSetColumnIndex(1);
|
||||||
if(ImGui::Button("Yes")) {
|
if(ImGui::Button("Yes")) {
|
||||||
if(!_profileManager->restoreBackup(backup_index)) {
|
if(!_profileManager->restoreBackup(backup_index)) {
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error when restoring backup",
|
_queue.addToast(Toast::Type::Error, _profileManager->lastError());
|
||||||
_profileManager->lastError().c_str(), window());
|
|
||||||
}
|
}
|
||||||
_profileManager->refreshProfiles();
|
_profileManager->refreshProfiles();
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
|
@ -172,13 +171,13 @@ auto SaveTool::drawBackupListPopup() -> ImGuiID {
|
||||||
{
|
{
|
||||||
ImGui::PushTextWrapPos(windowSize().x() * 0.40f);
|
ImGui::PushTextWrapPos(windowSize().x() * 0.40f);
|
||||||
ImGui::Text("Are you sure you want to delete the %s backup from %.4i-%.2i-%.2i %.2i:%.2i:%.2i ? This operation is irreversible.",
|
ImGui::Text("Are you sure you want to delete the %s backup from %.4i-%.2i-%.2i %.2i:%.2i:%.2i ? This operation is irreversible.",
|
||||||
_profileManager->backups().at(backup_index).company.c_str(),
|
_profileManager->backups()[backup_index].company.c_str(),
|
||||||
_profileManager->backups().at(backup_index).timestamp.year,
|
_profileManager->backups()[backup_index].timestamp.year,
|
||||||
_profileManager->backups().at(backup_index).timestamp.month,
|
_profileManager->backups()[backup_index].timestamp.month,
|
||||||
_profileManager->backups().at(backup_index).timestamp.day,
|
_profileManager->backups()[backup_index].timestamp.day,
|
||||||
_profileManager->backups().at(backup_index).timestamp.hour,
|
_profileManager->backups()[backup_index].timestamp.hour,
|
||||||
_profileManager->backups().at(backup_index).timestamp.minute,
|
_profileManager->backups()[backup_index].timestamp.minute,
|
||||||
_profileManager->backups().at(backup_index).timestamp.second);
|
_profileManager->backups()[backup_index].timestamp.second);
|
||||||
ImGui::PopTextWrapPos();
|
ImGui::PopTextWrapPos();
|
||||||
|
|
||||||
if(ImGui::BeginTable("##DeleteBackupLayout", 2)) {
|
if(ImGui::BeginTable("##DeleteBackupLayout", 2)) {
|
||||||
|
@ -190,8 +189,7 @@ auto SaveTool::drawBackupListPopup() -> ImGuiID {
|
||||||
ImGui::TableSetColumnIndex(1);
|
ImGui::TableSetColumnIndex(1);
|
||||||
if(ImGui::Button("Yes")) {
|
if(ImGui::Button("Yes")) {
|
||||||
if(!_profileManager->deleteBackup(backup_index)) {
|
if(!_profileManager->deleteBackup(backup_index)) {
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error when deleting backup",
|
_queue.addToast(Toast::Type::Error, _profileManager->lastError());
|
||||||
_profileManager->lastError().c_str(), window());
|
|
||||||
}
|
}
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
|
@ -251,10 +249,10 @@ auto SaveTool::drawBackupListPopup() -> ImGuiID {
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(0);
|
ImGui::TableSetColumnIndex(0);
|
||||||
ImGui::TextUnformatted(_profileManager->backups().at(i).company.c_str());
|
ImGui::TextUnformatted(_profileManager->backups()[i].company.c_str());
|
||||||
if(ImGui::IsItemHovered()) {
|
if(ImGui::IsItemHovered()) {
|
||||||
ImGui::BeginTooltip();
|
ImGui::BeginTooltip();
|
||||||
for(const auto& file : _profileManager->backups().at(i).includedFiles) {
|
for(const auto& file : _profileManager->backups()[i].includedFiles) {
|
||||||
ImGui::TextUnformatted(file.c_str());
|
ImGui::TextUnformatted(file.c_str());
|
||||||
}
|
}
|
||||||
ImGui::EndTooltip();
|
ImGui::EndTooltip();
|
||||||
|
@ -262,15 +260,15 @@ auto SaveTool::drawBackupListPopup() -> ImGuiID {
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(1);
|
ImGui::TableSetColumnIndex(1);
|
||||||
ImGui::Text("%.4i-%.2i-%.2i %.2i:%.2i:%.2i",
|
ImGui::Text("%.4i-%.2i-%.2i %.2i:%.2i:%.2i",
|
||||||
_profileManager->backups().at(i).timestamp.year,
|
_profileManager->backups()[i].timestamp.year,
|
||||||
_profileManager->backups().at(i).timestamp.month,
|
_profileManager->backups()[i].timestamp.month,
|
||||||
_profileManager->backups().at(i).timestamp.day,
|
_profileManager->backups()[i].timestamp.day,
|
||||||
_profileManager->backups().at(i).timestamp.hour,
|
_profileManager->backups()[i].timestamp.hour,
|
||||||
_profileManager->backups().at(i).timestamp.minute,
|
_profileManager->backups()[i].timestamp.minute,
|
||||||
_profileManager->backups().at(i).timestamp.second);
|
_profileManager->backups()[i].timestamp.second);
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(2);
|
ImGui::TableSetColumnIndex(2);
|
||||||
ImGui::TextUnformatted(_profileManager->backups().at(i).type == ProfileType::Demo ? "Demo" : "Full");
|
ImGui::TextUnformatted(_profileManager->backups()[i].type == ProfileType::Demo ? "Demo" : "Full");
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(3);
|
ImGui::TableSetColumnIndex(3);
|
||||||
ImGui::PushID(i);
|
ImGui::PushID(i);
|
||||||
|
@ -363,8 +361,8 @@ auto SaveTool::drawDeleteProfilePopup(std::size_t profile_index) -> ImGuiID {
|
||||||
|
|
||||||
ImGui::PushTextWrapPos(windowSize().x() * 0.40f);
|
ImGui::PushTextWrapPos(windowSize().x() * 0.40f);
|
||||||
ImGui::Text("Are you sure you want to delete the %s %s profile ? This operation is irreversible.",
|
ImGui::Text("Are you sure you want to delete the %s %s profile ? This operation is irreversible.",
|
||||||
_profileManager->profiles().at(profile_index).companyName().c_str(),
|
_profileManager->profiles()[profile_index].companyName().c_str(),
|
||||||
_profileManager->profiles().at(profile_index).type() == ProfileType::Demo ? "demo" : "full game");
|
_profileManager->profiles()[profile_index].type() == ProfileType::Demo ? "demo" : "full game");
|
||||||
ImGui::PopTextWrapPos();
|
ImGui::PopTextWrapPos();
|
||||||
|
|
||||||
if(ImGui::BeginTable("##DeleteProfileLayout", 2)) {
|
if(ImGui::BeginTable("##DeleteProfileLayout", 2)) {
|
||||||
|
@ -378,8 +376,7 @@ auto SaveTool::drawDeleteProfilePopup(std::size_t profile_index) -> ImGuiID {
|
||||||
ImGui::TableSetColumnIndex(1);
|
ImGui::TableSetColumnIndex(1);
|
||||||
if(ImGui::Button("Yes")) {
|
if(ImGui::Button("Yes")) {
|
||||||
if(!_profileManager->deleteProfile(profile_index, delete_builds)) {
|
if(!_profileManager->deleteProfile(profile_index, delete_builds)) {
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error when deleting profile",
|
_queue.addToast(Toast::Type::Error, _profileManager->lastError());
|
||||||
_profileManager->lastError().c_str(), window());
|
|
||||||
}
|
}
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// MassBuilderSaveTool
|
// MassBuilderSaveTool
|
||||||
// Copyright (C) 2021 Guillaume Jacquemin
|
// Copyright (C) 2021-2022 Guillaume Jacquemin
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -57,9 +57,8 @@ void 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).");
|
||||||
|
|
||||||
ImGui::AlignTextToFramePadding();
|
|
||||||
const char* repo = "https://williamjcm.ovh/git/williamjcm/MassBuilderSaveTool";
|
const char* repo = "https://williamjcm.ovh/git/williamjcm/MassBuilderSaveTool";
|
||||||
ImGui::Text(ICON_FA_GIT_ALT " %s", repo);
|
drawAlignedText(ICON_FA_GIT_ALT " %s", repo);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if(ImGui::Button("Copy to clipboard")) {
|
if(ImGui::Button("Copy to clipboard")) {
|
||||||
ImGui::SetClipboardText(repo);
|
ImGui::SetClipboardText(repo);
|
||||||
|
@ -90,9 +89,8 @@ void SaveTool::drawAbout() {
|
||||||
|
|
||||||
if(ImGui::TreeNodeEx("Corrade", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
if(ImGui::TreeNodeEx("Corrade", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
||||||
ImGui::Text("Version used: %s", CORRADE_VERSION_STRING);
|
ImGui::Text("Version used: %s", CORRADE_VERSION_STRING);
|
||||||
ImGui::AlignTextToFramePadding();
|
|
||||||
const char* corrade_website = "https://magnum.graphics/corrade";
|
const char* corrade_website = "https://magnum.graphics/corrade";
|
||||||
ImGui::Text(ICON_FA_GLOBE " %s", corrade_website);
|
drawAlignedText(ICON_FA_GLOBE " %s", corrade_website);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if(ImGui::Button("Copy to clipboard")) {
|
if(ImGui::Button("Copy to clipboard")) {
|
||||||
ImGui::SetClipboardText(corrade_website);
|
ImGui::SetClipboardText(corrade_website);
|
||||||
|
@ -119,9 +117,8 @@ void SaveTool::drawAbout() {
|
||||||
ImGui::TextUnformatted("Versions used:");
|
ImGui::TextUnformatted("Versions used:");
|
||||||
ImGui::BulletText("Magnum: %s", MAGNUM_VERSION_STRING);
|
ImGui::BulletText("Magnum: %s", MAGNUM_VERSION_STRING);
|
||||||
ImGui::BulletText("Integration: %s", MAGNUMINTEGRATION_VERSION_STRING);
|
ImGui::BulletText("Integration: %s", MAGNUMINTEGRATION_VERSION_STRING);
|
||||||
ImGui::AlignTextToFramePadding();
|
|
||||||
const char* magnum_website = "https://magnum.graphics";
|
const char* magnum_website = "https://magnum.graphics";
|
||||||
ImGui::Text(ICON_FA_GLOBE " %s", magnum_website);
|
drawAlignedText(ICON_FA_GLOBE " %s", magnum_website);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if(ImGui::Button("Copy to clipboard")) {
|
if(ImGui::Button("Copy to clipboard")) {
|
||||||
ImGui::SetClipboardText(magnum_website);
|
ImGui::SetClipboardText(magnum_website);
|
||||||
|
@ -146,9 +143,8 @@ void SaveTool::drawAbout() {
|
||||||
|
|
||||||
if(ImGui::TreeNodeEx("Dear ImGui", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
if(ImGui::TreeNodeEx("Dear ImGui", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
||||||
ImGui::Text("Version used: %s", IMGUI_VERSION);
|
ImGui::Text("Version used: %s", IMGUI_VERSION);
|
||||||
ImGui::AlignTextToFramePadding();
|
|
||||||
const char* imgui_repo = "https://github.com/ocornut/imgui";
|
const char* imgui_repo = "https://github.com/ocornut/imgui";
|
||||||
ImGui::Text(ICON_FA_GITHUB " %s", imgui_repo);
|
drawAlignedText(ICON_FA_GITHUB " %s", imgui_repo);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if(ImGui::Button("Copy to clipboard")) {
|
if(ImGui::Button("Copy to clipboard")) {
|
||||||
ImGui::SetClipboardText(imgui_repo);
|
ImGui::SetClipboardText(imgui_repo);
|
||||||
|
@ -173,9 +169,8 @@ void SaveTool::drawAbout() {
|
||||||
|
|
||||||
if(ImGui::TreeNodeEx("Simple DirectMedia Layer (SDL) 2", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
if(ImGui::TreeNodeEx("Simple DirectMedia Layer (SDL) 2", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
||||||
ImGui::Text("Version used: %i.%i.%i", SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL);
|
ImGui::Text("Version used: %i.%i.%i", SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL);
|
||||||
ImGui::AlignTextToFramePadding();
|
|
||||||
const char* sdl_website = "https://www.libsdl.org/";
|
const char* sdl_website = "https://www.libsdl.org/";
|
||||||
ImGui::Text(ICON_FA_GLOBE " %s", sdl_website);
|
drawAlignedText(ICON_FA_GLOBE " %s", sdl_website);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if(ImGui::Button("Copy to clipboard")) {
|
if(ImGui::Button("Copy to clipboard")) {
|
||||||
ImGui::SetClipboardText(sdl_website);
|
ImGui::SetClipboardText(sdl_website);
|
||||||
|
@ -200,9 +195,8 @@ void SaveTool::drawAbout() {
|
||||||
|
|
||||||
if(ImGui::TreeNodeEx("libzip", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
if(ImGui::TreeNodeEx("libzip", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
||||||
ImGui::Text("Version used: %s", LIBZIP_VERSION);
|
ImGui::Text("Version used: %s", LIBZIP_VERSION);
|
||||||
ImGui::AlignTextToFramePadding();
|
|
||||||
const char* libzip_website = "https://libzip.org/";
|
const char* libzip_website = "https://libzip.org/";
|
||||||
ImGui::Text(ICON_FA_GLOBE " %s", libzip_website);
|
drawAlignedText(ICON_FA_GLOBE " %s", libzip_website);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if(ImGui::Button("Copy to clipboard")) {
|
if(ImGui::Button("Copy to clipboard")) {
|
||||||
ImGui::SetClipboardText(libzip_website);
|
ImGui::SetClipboardText(libzip_website);
|
||||||
|
@ -226,9 +220,8 @@ void SaveTool::drawAbout() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ImGui::TreeNodeEx("Entropia File System Watcher (efsw)", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
if(ImGui::TreeNodeEx("Entropia File System Watcher (efsw)", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
||||||
ImGui::AlignTextToFramePadding();
|
|
||||||
const char* efsw_repo = "https://github.com/SpartanJ/efsw";
|
const char* efsw_repo = "https://github.com/SpartanJ/efsw";
|
||||||
ImGui::Text(ICON_FA_GITHUB " %s", efsw_repo);
|
drawAlignedText(ICON_FA_GITHUB " %s", efsw_repo);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if(ImGui::Button("Copy to clipboard")) {
|
if(ImGui::Button("Copy to clipboard")) {
|
||||||
ImGui::SetClipboardText(efsw_repo);
|
ImGui::SetClipboardText(efsw_repo);
|
||||||
|
@ -252,9 +245,8 @@ void SaveTool::drawAbout() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ImGui::TreeNodeEx("C++ Requests (cpr)", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
if(ImGui::TreeNodeEx("C++ Requests (cpr)", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
||||||
ImGui::AlignTextToFramePadding();
|
|
||||||
const char* cpr_website = "https://whoshuu.github.io/cpr/";
|
const char* cpr_website = "https://whoshuu.github.io/cpr/";
|
||||||
ImGui::Text(ICON_FA_GLOBE " %s", cpr_website);
|
drawAlignedText(ICON_FA_GLOBE " %s", cpr_website);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if(ImGui::Button("Copy to clipboard")) {
|
if(ImGui::Button("Copy to clipboard")) {
|
||||||
ImGui::SetClipboardText(cpr_website);
|
ImGui::SetClipboardText(cpr_website);
|
||||||
|
@ -278,9 +270,8 @@ void SaveTool::drawAbout() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ImGui::TreeNodeEx("JSON for Modern C++ (aka json.hpp)", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
if(ImGui::TreeNodeEx("JSON for Modern C++ (aka json.hpp)", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
||||||
ImGui::AlignTextToFramePadding();
|
|
||||||
const char* json_website = "https://json.nlohmann.me/";
|
const char* json_website = "https://json.nlohmann.me/";
|
||||||
ImGui::Text(ICON_FA_GLOBE " %s", json_website);
|
drawAlignedText(ICON_FA_GLOBE " %s", json_website);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if(ImGui::Button("Copy to clipboard")) {
|
if(ImGui::Button("Copy to clipboard")) {
|
||||||
ImGui::SetClipboardText(json_website);
|
ImGui::SetClipboardText(json_website);
|
||||||
|
@ -305,9 +296,8 @@ void SaveTool::drawAbout() {
|
||||||
|
|
||||||
if(ImGui::TreeNodeEx("Font Awesome", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
if(ImGui::TreeNodeEx("Font Awesome", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
||||||
ImGui::TextUnformatted("Version used: 5.15.3");
|
ImGui::TextUnformatted("Version used: 5.15.3");
|
||||||
ImGui::AlignTextToFramePadding();
|
|
||||||
const char* fa_website = "https://fontawesome.com/";
|
const char* fa_website = "https://fontawesome.com/";
|
||||||
ImGui::Text(ICON_FA_GLOBE " %s", fa_website);
|
drawAlignedText(ICON_FA_GLOBE " %s", fa_website);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if(ImGui::Button("Copy to clipboard")) {
|
if(ImGui::Button("Copy to clipboard")) {
|
||||||
ImGui::SetClipboardText(fa_website);
|
ImGui::SetClipboardText(fa_website);
|
||||||
|
@ -323,9 +313,8 @@ void SaveTool::drawAbout() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ImGui::TreeNodeEx("IconFontCppHeaders", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
if(ImGui::TreeNodeEx("IconFontCppHeaders", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
||||||
ImGui::AlignTextToFramePadding();
|
|
||||||
const char* icon_repo = "https://github.com/juliettef/IconFontCppHeaders";
|
const char* icon_repo = "https://github.com/juliettef/IconFontCppHeaders";
|
||||||
ImGui::Text(ICON_FA_GITHUB " %s", icon_repo);
|
drawAlignedText(ICON_FA_GITHUB " %s", icon_repo);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if(ImGui::Button("Copy to clipboard")) {
|
if(ImGui::Button("Copy to clipboard")) {
|
||||||
ImGui::SetClipboardText(icon_repo);
|
ImGui::SetClipboardText(icon_repo);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// MassBuilderSaveTool
|
// MassBuilderSaveTool
|
||||||
// Copyright (C) 2021 Guillaume Jacquemin
|
// Copyright (C) 2021-2022 Guillaume Jacquemin
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -55,8 +55,7 @@ void SaveTool::drawMainMenu() {
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
if(ImGui::BeginMenu(ICON_FA_COG " Settings")) {
|
if(ImGui::BeginMenu(ICON_FA_COG " Settings")) {
|
||||||
ImGui::AlignTextToFramePadding();
|
drawAlignedText("Frame limiter:");
|
||||||
ImGui::TextUnformatted("Frame limiter:");
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
static UnsignedByte selection = static_cast<UnsignedByte>(_framelimit);
|
static UnsignedByte selection = static_cast<UnsignedByte>(_framelimit);
|
||||||
|
@ -118,8 +117,7 @@ void SaveTool::drawMainMenu() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_updateAvailable) {
|
if(_updateAvailable) {
|
||||||
ImGui::AlignTextToFramePadding();
|
drawAlignedText("Version %s is available.", _latestVersion.c_str());
|
||||||
ImGui::Text("Version %s is available.", _latestVersion.c_str());
|
|
||||||
if(ImGui::Button(ICON_FA_FILE_SIGNATURE " Release notes")) {
|
if(ImGui::Button(ICON_FA_FILE_SIGNATURE " Release notes")) {
|
||||||
openUri(_releaseLink);
|
openUri(_releaseLink);
|
||||||
}
|
}
|
||||||
|
@ -181,6 +179,20 @@ void SaveTool::drawMainMenu() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(ImGui::BeginMenu("Help")) {
|
if(ImGui::BeginMenu("Help")) {
|
||||||
|
if(ImGui::BeginMenu(ICON_FA_BOOK " ImGui user guide")) {
|
||||||
|
ImGui::BulletText("CTRL+Click on a slider or drag box to input value as text.");
|
||||||
|
ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields.");
|
||||||
|
ImGui::BulletText("While inputing text:\n");
|
||||||
|
ImGui::Indent();
|
||||||
|
ImGui::BulletText("CTRL+Left/Right to word jump.");
|
||||||
|
ImGui::BulletText("CTRL+A or double-click to select all.");
|
||||||
|
ImGui::BulletText("CTRL+X/C/V to use clipboard cut/copy/paste.");
|
||||||
|
ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo.");
|
||||||
|
ImGui::BulletText("ESCAPE to revert.");
|
||||||
|
ImGui::BulletText("You can apply arithmetic operators +,*,/ on numerical values.\nUse +- to subtract.");
|
||||||
|
ImGui::Unindent();
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
ImGui::MenuItem(ICON_FA_INFO_CIRCLE " About", nullptr, &_aboutPopup);
|
ImGui::MenuItem(ICON_FA_INFO_CIRCLE " About", nullptr, &_aboutPopup);
|
||||||
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// MassBuilderSaveTool
|
// MassBuilderSaveTool
|
||||||
// Copyright (C) 2021 Guillaume Jacquemin
|
// Copyright (C) 2021-2022 Guillaume Jacquemin
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// MassBuilderSaveTool
|
// MassBuilderSaveTool
|
||||||
// Copyright (C) 2021 Guillaume Jacquemin
|
// Copyright (C) 2021-2022 Guillaume Jacquemin
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
|
126
src/UESaveFile/BinaryReader.cpp
Normal file
126
src/UESaveFile/BinaryReader.cpp
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 Guillaume Jacquemin
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "BinaryReader.h"
|
||||||
|
|
||||||
|
BinaryReader::BinaryReader(const std::string& filename) {
|
||||||
|
_file = std::fopen(filename.c_str(), "rb");
|
||||||
|
|
||||||
|
if(!_file) {
|
||||||
|
Utility::Error{} << "Couldn't open" << filename.c_str() << "for reading:\n"
|
||||||
|
<< std::strerror(errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BinaryReader::~BinaryReader() {
|
||||||
|
closeFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryReader::open() -> bool {
|
||||||
|
return _file;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryReader::eof() -> bool {
|
||||||
|
return std::feof(_file) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryReader::position() -> Long {
|
||||||
|
return _ftelli64(_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryReader::seek(Long position) -> bool {
|
||||||
|
return _fseeki64(_file, position, SEEK_SET) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BinaryReader::closeFile() {
|
||||||
|
std::fclose(_file);
|
||||||
|
_file = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryReader::readChar(char& value) -> bool {
|
||||||
|
return std::fread(&value, sizeof(char), 1, _file) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryReader::readByte(Byte& value) -> bool {
|
||||||
|
return std::fread(&value, sizeof(Byte), 1, _file) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryReader::readUnsignedByte(UnsignedByte& value) -> bool {
|
||||||
|
return std::fread(&value, sizeof(UnsignedByte), 1, _file) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryReader::readShort(Short& value) -> bool {
|
||||||
|
return std::fread(&value, sizeof(Short), 1, _file) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryReader::readUnsignedShort(UnsignedShort& value) -> bool {
|
||||||
|
return std::fread(&value, sizeof(UnsignedShort), 1, _file) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryReader::readInt(Int& value) -> bool {
|
||||||
|
return std::fread(&value, sizeof(Int), 1, _file) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryReader::readUnsignedInt(UnsignedInt& value) -> bool {
|
||||||
|
return std::fread(&value, sizeof(UnsignedInt), 1, _file) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryReader::readLong(Long& value) -> bool {
|
||||||
|
return std::fread(&value, sizeof(Long), 1, _file) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryReader::readUnsignedLong(UnsignedLong& value) -> bool {
|
||||||
|
return std::fread(&value, sizeof(UnsignedLong), 1, _file) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryReader::readFloat(Float& value) -> bool {
|
||||||
|
return std::fread(&value, sizeof(Float), 1, _file) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryReader::readDouble(Double& value) -> bool {
|
||||||
|
return std::fread(&value, sizeof(Double), 1, _file) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryReader::readArray(Containers::Array<char>& array, std::size_t count) -> bool {
|
||||||
|
if(array.size() < count) {
|
||||||
|
array = Containers::Array<char>{ValueInit, count};
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::fread(array.data(), sizeof(char), count, _file) == count;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryReader::readUEString(std::string& str) -> bool {
|
||||||
|
UnsignedInt length = 0;
|
||||||
|
if(!readUnsignedInt(length) || length == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
str = std::string{};
|
||||||
|
str.resize(length - 1);
|
||||||
|
|
||||||
|
return std::fread(&str[0], sizeof(char), length, _file) == length;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryReader::peekChar() -> Int {
|
||||||
|
Int c;
|
||||||
|
c = std::fgetc(_file);
|
||||||
|
std::ungetc(c, _file);
|
||||||
|
return c;
|
||||||
|
}
|
72
src/UESaveFile/BinaryReader.h
Normal file
72
src/UESaveFile/BinaryReader.h
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 <cstdio>
|
||||||
|
|
||||||
|
#include <Corrade/Containers/Array.h>
|
||||||
|
#include <Corrade/Containers/StaticArray.h>
|
||||||
|
#include <Corrade/Utility/StlForwardString.h>
|
||||||
|
|
||||||
|
#include <Magnum/Types.h>
|
||||||
|
|
||||||
|
using namespace Corrade;
|
||||||
|
using namespace Magnum;
|
||||||
|
|
||||||
|
class BinaryReader {
|
||||||
|
public:
|
||||||
|
explicit BinaryReader(const std::string& filename);
|
||||||
|
~BinaryReader();
|
||||||
|
|
||||||
|
auto open() -> bool;
|
||||||
|
auto eof() -> bool;
|
||||||
|
auto position() -> Long;
|
||||||
|
|
||||||
|
auto seek(Long position) -> bool;
|
||||||
|
|
||||||
|
void closeFile();
|
||||||
|
|
||||||
|
auto readChar(char& value) -> bool;
|
||||||
|
auto readByte(Byte& value) -> bool;
|
||||||
|
auto readUnsignedByte(UnsignedByte& value) -> bool;
|
||||||
|
auto readShort(Short& value) -> bool;
|
||||||
|
auto readUnsignedShort(UnsignedShort& value) -> bool;
|
||||||
|
auto readInt(Int& value) -> bool;
|
||||||
|
auto readUnsignedInt(UnsignedInt& value) -> bool;
|
||||||
|
auto readLong(Long& value) -> bool;
|
||||||
|
auto readUnsignedLong(UnsignedLong& value) -> bool;
|
||||||
|
auto readFloat(Float& value) -> bool;
|
||||||
|
auto readDouble(Double& value) -> bool;
|
||||||
|
auto readArray(Containers::Array<char>& array, std::size_t count) -> bool;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto readValue(T& value) -> bool {
|
||||||
|
return fread(&value, sizeof(T), 1, _file) == sizeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t S>
|
||||||
|
auto readStaticArray(Containers::StaticArray<S, char>& array) -> bool {
|
||||||
|
return std::fread(array.data(), sizeof(char), S, _file) == S;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto readUEString(std::string& str) -> bool;
|
||||||
|
|
||||||
|
auto peekChar() -> Int;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::FILE* _file = nullptr;
|
||||||
|
};
|
137
src/UESaveFile/BinaryWriter.cpp
Normal file
137
src/UESaveFile/BinaryWriter.cpp
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 Guillaume Jacquemin
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "BinaryWriter.h"
|
||||||
|
|
||||||
|
BinaryWriter::BinaryWriter(const std::string& filename) {
|
||||||
|
_file = std::fopen(filename.c_str(), "wb");
|
||||||
|
if(!_file) {
|
||||||
|
Utility::Error{} << "Couldn't open" << filename.c_str() << "for reading:\n"
|
||||||
|
<< std::strerror(errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BinaryWriter::~BinaryWriter() {
|
||||||
|
closeFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryWriter::open() -> bool {
|
||||||
|
return _file;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BinaryWriter::closeFile() {
|
||||||
|
std::fflush(_file);
|
||||||
|
std::fclose(_file);
|
||||||
|
_file = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryWriter::position() -> Long {
|
||||||
|
return _ftelli64(_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryWriter::array() const -> Containers::ArrayView<const char> {
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryWriter::arrayPosition() const -> UnsignedLong {
|
||||||
|
return _index;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryWriter::flushToFile() -> bool {
|
||||||
|
bool ret = writeArray(_data);
|
||||||
|
std::fflush(_file);
|
||||||
|
_data = Containers::Array<char>{};
|
||||||
|
_index = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryWriter::writeChar(char value) -> bool {
|
||||||
|
return std::fwrite(&value, sizeof(char), 1, _file) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryWriter::writeByte(Byte value) -> bool {
|
||||||
|
return std::fwrite(&value, sizeof(Byte), 1, _file) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryWriter::writeUnsignedByte(UnsignedByte value) -> bool {
|
||||||
|
return std::fwrite(&value, sizeof(UnsignedByte), 1, _file) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryWriter::writeShort(Short value) -> bool {
|
||||||
|
return std::fwrite(&value, sizeof(Short), 1, _file) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryWriter::writeUnsignedShort(UnsignedShort value) -> bool {
|
||||||
|
return std::fwrite(&value, sizeof(UnsignedShort), 1, _file) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryWriter::writeInt(Int value) -> bool {
|
||||||
|
return std::fwrite(&value, sizeof(Int), 1, _file) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryWriter::writeUnsignedInt(UnsignedInt value) -> bool {
|
||||||
|
return std::fwrite(&value, sizeof(UnsignedInt), 1, _file) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryWriter::writeLong(Long value) -> bool {
|
||||||
|
return std::fwrite(&value, sizeof(Long), 1, _file) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryWriter::writeUnsignedLong(UnsignedLong value) -> bool {
|
||||||
|
return std::fwrite(&value, sizeof(UnsignedLong), 1, _file) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryWriter::writeFloat(Float value) -> bool {
|
||||||
|
return std::fwrite(&value, sizeof(Float), 1, _file) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryWriter::writeDouble(Double value) -> bool {
|
||||||
|
return std::fwrite(&value, sizeof(Double), 1, _file) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryWriter::writeArray(Containers::ArrayView<const char> array) -> bool {
|
||||||
|
if(array.size() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::fwrite(array.data(), sizeof(char), array.size(), _file) == array.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryWriter::writeUEString(const std::string& str) -> bool {
|
||||||
|
if(str.length() > UINT32_MAX) {
|
||||||
|
Utility::Error{} << "BinaryWriter::writeUEString(): string is too big.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeUnsignedInt(static_cast<UnsignedInt>(str.length()) + 1);
|
||||||
|
|
||||||
|
if(str.length() > 0) {
|
||||||
|
std::size_t count = std::fwrite(&str[0], sizeof(char), str.length(), _file);
|
||||||
|
if(count != str.length()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return writeChar('\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BinaryWriter::writeUEStringToArray(const std::string& value) -> UnsignedLong {
|
||||||
|
Containers::ArrayView<const char> view{value.c_str(), value.length()};
|
||||||
|
return writeValueToArray<UnsignedInt>(UnsignedInt(value.length()) + 1u) + writeDataToArray(view) + writeValueToArray<char>('\0');
|
||||||
|
}
|
110
src/UESaveFile/BinaryWriter.h
Normal file
110
src/UESaveFile/BinaryWriter.h
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 <cstdio>
|
||||||
|
|
||||||
|
#include <Corrade/Containers/ArrayView.h>
|
||||||
|
#include <Corrade/Containers/GrowableArray.h>
|
||||||
|
#include <Corrade/Containers/StaticArray.h>
|
||||||
|
#include <Corrade/Utility/StlForwardString.h>
|
||||||
|
|
||||||
|
#include <Magnum/Types.h>
|
||||||
|
|
||||||
|
using namespace Corrade;
|
||||||
|
using namespace Magnum;
|
||||||
|
|
||||||
|
class BinaryWriter {
|
||||||
|
public:
|
||||||
|
explicit BinaryWriter(const std::string& filename);
|
||||||
|
~BinaryWriter();
|
||||||
|
|
||||||
|
BinaryWriter(const BinaryWriter& other) = delete;
|
||||||
|
BinaryWriter& operator=(const BinaryWriter& other) = delete;
|
||||||
|
|
||||||
|
BinaryWriter(BinaryWriter&& other) = default;
|
||||||
|
BinaryWriter& operator=(BinaryWriter&& other) = default;
|
||||||
|
|
||||||
|
auto open() -> bool;
|
||||||
|
|
||||||
|
void closeFile();
|
||||||
|
|
||||||
|
auto position() -> Long;
|
||||||
|
|
||||||
|
auto array() const -> Containers::ArrayView<const char>;
|
||||||
|
auto arrayPosition() const -> UnsignedLong;
|
||||||
|
auto flushToFile() -> bool;
|
||||||
|
|
||||||
|
auto writeByte(Byte value) -> bool;
|
||||||
|
auto writeChar(char value) -> bool;
|
||||||
|
auto writeUnsignedByte(UnsignedByte value) -> bool;
|
||||||
|
auto writeShort(Short value) -> bool;
|
||||||
|
auto writeUnsignedShort(UnsignedShort value) -> bool;
|
||||||
|
auto writeInt(Int value) -> bool;
|
||||||
|
auto writeUnsignedInt(UnsignedInt value) -> bool;
|
||||||
|
auto writeLong(Long value) -> bool;
|
||||||
|
auto writeUnsignedLong(UnsignedLong value) -> bool;
|
||||||
|
auto writeFloat(Float value) -> bool;
|
||||||
|
auto writeDouble(Double value) -> bool;
|
||||||
|
auto writeArray(Containers::ArrayView<const char> array) -> bool;
|
||||||
|
template<std::size_t size>
|
||||||
|
auto writeString(const char(&str)[size]) -> bool {
|
||||||
|
return writeArray({str, size - 1});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t S>
|
||||||
|
auto writeStaticArray(Containers::StaticArrayView<S, const char> array) -> bool {
|
||||||
|
return std::fwrite(array.data(), sizeof(char), S, _file) == S;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto writeUEString(const std::string& str) -> bool;
|
||||||
|
|
||||||
|
template<typename T, typename U = std::conditional_t<std::is_trivially_copyable<T>::value, T, T&>>
|
||||||
|
auto writeValueToArray(U value) -> UnsignedLong {
|
||||||
|
Containers::ArrayView<T> view{&value, 1};
|
||||||
|
return writeDataToArray(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto writeUEStringToArray(const std::string& value) -> UnsignedLong;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void writeValueToArrayAt(T& value, UnsignedLong position) {
|
||||||
|
Containers::ArrayView<T> view{&value, 1};
|
||||||
|
writeDataToArrayAt(view, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto writeDataToArray(Containers::ArrayView<T> view) -> UnsignedLong {
|
||||||
|
arrayAppend(_data, Containers::arrayCast<const char>(view));
|
||||||
|
_index += sizeof(T) * view.size();
|
||||||
|
return sizeof(T) * view.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void writeDataToArrayAt(Containers::ArrayView<T> view, UnsignedLong position) {
|
||||||
|
auto casted_view = Containers::arrayCast<const char>(view);
|
||||||
|
for(UnsignedLong i = 0; i < casted_view.size(); i++) {
|
||||||
|
_data[position + i] = casted_view[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
FILE* _file = nullptr;
|
||||||
|
|
||||||
|
Containers::Array<char> _data;
|
||||||
|
UnsignedLong _index = 0;
|
||||||
|
};
|
76
src/UESaveFile/Debug.cpp
Normal file
76
src/UESaveFile/Debug.cpp
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "Types/UnrealPropertyBase.h"
|
||||||
|
#include "Types/ArrayProperty.h"
|
||||||
|
#include "Types/SetProperty.h"
|
||||||
|
#include "Types/StructProperty.h"
|
||||||
|
#include "Types/GenericStructProperty.h"
|
||||||
|
|
||||||
|
#include "Debug.h"
|
||||||
|
|
||||||
|
Utility::Debug& operator<<(Utility::Debug& debug, const ArrayProperty* prop) {
|
||||||
|
return debug << (*prop->name).c_str() << Utility::Debug::nospace << ":" <<
|
||||||
|
prop->propertyType.c_str() << "of" << prop->items.size() << prop->itemType.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
Utility::Debug& operator<<(Utility::Debug& debug, const SetProperty* prop) {
|
||||||
|
return debug << (*prop->name).c_str() << Utility::Debug::nospace << ":" <<
|
||||||
|
prop->propertyType.c_str() << "of" << prop->items.size() << prop->itemType.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
Utility::Debug& operator<<(Utility::Debug& debug, const GenericStructProperty* prop) {
|
||||||
|
debug << (*prop->name).c_str() << Utility::Debug::nospace << ":" <<
|
||||||
|
prop->structType.c_str() << "(" << Utility::Debug::nospace << prop->propertyType.c_str() << Utility::Debug::nospace <<
|
||||||
|
") Contents:";
|
||||||
|
for(const auto& item : prop->properties) {
|
||||||
|
debug << "\n " << Utility::Debug::nospace << item.get();
|
||||||
|
}
|
||||||
|
return debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
Utility::Debug& operator<<(Utility::Debug& debug, const StructProperty* prop) {
|
||||||
|
auto cast = dynamic_cast<const GenericStructProperty*>(prop);
|
||||||
|
if(cast) {
|
||||||
|
return debug << cast;
|
||||||
|
}
|
||||||
|
|
||||||
|
return debug << (*prop->name).c_str() << Utility::Debug::nospace << ":" <<
|
||||||
|
prop->structType.c_str() << "(" << Utility::Debug::nospace << prop->propertyType.c_str() << Utility::Debug::nospace << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
Utility::Debug& operator<<(Utility::Debug& debug, const UnrealPropertyBase* prop) {
|
||||||
|
if(prop->propertyType == "ArrayProperty") {
|
||||||
|
auto array_prop = dynamic_cast<const ArrayProperty*>(prop);
|
||||||
|
if(array_prop) {
|
||||||
|
return debug << array_prop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(prop->propertyType == "SetProperty") {
|
||||||
|
auto set_prop = dynamic_cast<const SetProperty*>(prop);
|
||||||
|
if(set_prop) {
|
||||||
|
return debug << set_prop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(prop->propertyType == "StructProperty") {
|
||||||
|
auto struct_prop = dynamic_cast<const StructProperty*>(prop);
|
||||||
|
if(struct_prop) {
|
||||||
|
return debug << struct_prop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return debug << (*prop->name).c_str() << Utility::Debug::nospace << ":" << prop->propertyType.c_str();
|
||||||
|
}
|
33
src/UESaveFile/Debug.h
Normal file
33
src/UESaveFile/Debug.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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>
|
||||||
|
|
||||||
|
struct ArrayProperty;
|
||||||
|
struct SetProperty;
|
||||||
|
struct GenericStructProperty;
|
||||||
|
struct StructProperty;
|
||||||
|
struct UnrealPropertyBase;
|
||||||
|
|
||||||
|
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);
|
254
src/UESaveFile/PropertySerialiser.cpp
Normal file
254
src/UESaveFile/PropertySerialiser.cpp
Normal file
|
@ -0,0 +1,254 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 <algorithm>
|
||||||
|
|
||||||
|
#include "Serialisers/ArrayPropertySerialiser.h"
|
||||||
|
#include "Serialisers/BoolPropertySerialiser.h"
|
||||||
|
#include "Serialisers/BytePropertySerialiser.h"
|
||||||
|
#include "Serialisers/ColourPropertySerialiser.h"
|
||||||
|
#include "Serialisers/DateTimePropertySerialiser.h"
|
||||||
|
#include "Serialisers/EnumPropertySerialiser.h"
|
||||||
|
#include "Serialisers/FloatPropertySerialiser.h"
|
||||||
|
#include "Serialisers/GuidPropertySerialiser.h"
|
||||||
|
#include "Serialisers/IntPropertySerialiser.h"
|
||||||
|
#include "Serialisers/MapPropertySerialiser.h"
|
||||||
|
#include "Serialisers/ResourcePropertySerialiser.h"
|
||||||
|
#include "Serialisers/RotatorPropertySerialiser.h"
|
||||||
|
#include "Serialisers/StringPropertySerialiser.h"
|
||||||
|
#include "Serialisers/SetPropertySerialiser.h"
|
||||||
|
#include "Serialisers/StructSerialiser.h"
|
||||||
|
#include "Serialisers/TextPropertySerialiser.h"
|
||||||
|
#include "Serialisers/VectorPropertySerialiser.h"
|
||||||
|
#include "Serialisers/Vector2DPropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "Types/NoneProperty.h"
|
||||||
|
|
||||||
|
#include "BinaryReader.h"
|
||||||
|
#include "BinaryWriter.h"
|
||||||
|
|
||||||
|
#include "PropertySerialiser.h"
|
||||||
|
|
||||||
|
|
||||||
|
PropertySerialiser::PropertySerialiser() {
|
||||||
|
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>());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PropertySerialiser::read(BinaryReader& reader) -> UnrealPropertyBase::ptr {
|
||||||
|
if(reader.peekChar() < 0 || reader.eof()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
if(!reader.readUEString(name)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(name == "None") {
|
||||||
|
return Containers::pointer<NoneProperty>();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string type;
|
||||||
|
if(!reader.readUEString(type)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnsignedLong value_length;
|
||||||
|
if(!reader.readUnsignedLong(value_length)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return deserialise(std::move(name), std::move(type), value_length, reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PropertySerialiser::readItem(BinaryReader& reader, std::string type, UnsignedLong value_length, std::string name) -> UnrealPropertyBase::ptr {
|
||||||
|
if(reader.peekChar() < 0 || reader.eof()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return deserialise(std::move(name), std::move(type), value_length, reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PropertySerialiser::readSet(BinaryReader& reader, const std::string& item_type, UnsignedInt count) -> Containers::Array<UnrealPropertyBase::ptr> {
|
||||||
|
if(reader.peekChar() < 0 || reader.eof()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto serialiser = getCollectionSerialiser(item_type);
|
||||||
|
|
||||||
|
Containers::Array<UnrealPropertyBase::ptr> array;
|
||||||
|
|
||||||
|
if(serialiser) {
|
||||||
|
std::string name;
|
||||||
|
if(!reader.readUEString(name)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string type;
|
||||||
|
if(!reader.readUEString(type)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnsignedLong value_length;
|
||||||
|
if(!reader.readUnsignedLong(value_length)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
array = serialiser->deserialise(name, type, value_length, count, reader, *this);
|
||||||
|
|
||||||
|
for(auto& item : array) {
|
||||||
|
if(item->name == Containers::NullOpt) {
|
||||||
|
item->name.emplace(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for(UnsignedInt i = 0; i < count; i++) {
|
||||||
|
auto item = readItem(reader, item_type, UnsignedLong(-1), "");
|
||||||
|
arrayAppend(array, std::move(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PropertySerialiser::deserialise(std::string name, std::string type, UnsignedLong value_length,
|
||||||
|
BinaryReader& reader) -> UnrealPropertyBase::ptr
|
||||||
|
{
|
||||||
|
UnrealPropertyBase::ptr prop;
|
||||||
|
auto serialiser = getSerialiser(type);
|
||||||
|
|
||||||
|
if(serialiser == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
prop = serialiser->deserialise(name, type, value_length, reader, *this);
|
||||||
|
|
||||||
|
if(!prop) {
|
||||||
|
!Utility::Error{} << "No prop in" << __func__;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
prop->name = std::move(name);
|
||||||
|
prop->propertyType = std::move(type);
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, const std::string& item_type, UnsignedLong& bytes_written,
|
||||||
|
BinaryWriter& writer) -> bool
|
||||||
|
{
|
||||||
|
auto serialiser = getSerialiser(item_type);
|
||||||
|
if(!serialiser) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return serialiser->serialise(prop, bytes_written, writer, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PropertySerialiser::write(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer) -> bool {
|
||||||
|
if(prop->name == "None" && prop->propertyType == "NoneProperty" && dynamic_cast<NoneProperty*>(prop.get())) {
|
||||||
|
bytes_written += writer.writeUEStringToArray(*prop->name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_written += writer.writeUEStringToArray(*prop->name);
|
||||||
|
bytes_written += writer.writeUEStringToArray(prop->propertyType);
|
||||||
|
|
||||||
|
UnsignedLong value_length = 0;
|
||||||
|
UnsignedLong vl_position = writer.arrayPosition();
|
||||||
|
|
||||||
|
bytes_written += writer.writeValueToArray<UnsignedLong>(value_length);
|
||||||
|
|
||||||
|
bool ret = serialise(prop, prop->propertyType, value_length, writer);
|
||||||
|
|
||||||
|
writer.writeValueToArrayAt(value_length, vl_position);
|
||||||
|
|
||||||
|
bytes_written += value_length;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PropertySerialiser::writeItem(UnrealPropertyBase::ptr& prop, const std::string& item_type,
|
||||||
|
UnsignedLong& bytes_written, BinaryWriter& writer) -> bool
|
||||||
|
{
|
||||||
|
if(prop->name == "None" && prop->propertyType == "NoneProperty" && dynamic_cast<NoneProperty*>(prop.get())) {
|
||||||
|
bytes_written += writer.writeUEStringToArray(*prop->name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return serialise(prop, item_type, bytes_written, writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PropertySerialiser::writeSet(Containers::ArrayView<UnrealPropertyBase::ptr> props, const std::string& item_type,
|
||||||
|
UnsignedLong& bytes_written, BinaryWriter& writer) -> bool
|
||||||
|
{
|
||||||
|
auto serialiser = getCollectionSerialiser(item_type);
|
||||||
|
if(serialiser) {
|
||||||
|
return serialiser->serialise(props, item_type, bytes_written, writer, *this);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for(auto& prop : props) {
|
||||||
|
if(!writeItem(prop, item_type, bytes_written, writer)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PropertySerialiser::getSerialiser(const std::string& item_type) -> AbstractUnrealPropertySerialiser* {
|
||||||
|
for(auto& item : _serialisers) {
|
||||||
|
for(const std::string& serialiser_type : item->types()) {
|
||||||
|
if(item_type == serialiser_type) {
|
||||||
|
return item.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PropertySerialiser::getCollectionSerialiser(const std::string& item_type) -> AbstractUnrealCollectionPropertySerialiser* {
|
||||||
|
for(auto& item : _collectionSerialisers) {
|
||||||
|
for(const std::string& serialiser_type : item->types()) {
|
||||||
|
if(item_type == serialiser_type) {
|
||||||
|
return item.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
51
src/UESaveFile/PropertySerialiser.h
Normal file
51
src/UESaveFile/PropertySerialiser.h
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "Serialisers/AbstractUnrealPropertySerialiser.h"
|
||||||
|
#include "Serialisers/AbstractUnrealCollectionPropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "Types/UnrealPropertyBase.h"
|
||||||
|
|
||||||
|
using namespace Corrade;
|
||||||
|
|
||||||
|
class BinaryReader;
|
||||||
|
class BinaryWriter;
|
||||||
|
|
||||||
|
class PropertySerialiser {
|
||||||
|
public:
|
||||||
|
PropertySerialiser();
|
||||||
|
|
||||||
|
auto read(BinaryReader& reader) -> UnrealPropertyBase::ptr;
|
||||||
|
auto readItem(BinaryReader& reader, std::string type, UnsignedLong value_length, std::string name) -> UnrealPropertyBase::ptr;
|
||||||
|
auto readSet(BinaryReader& reader, const std::string& item_type, UnsignedInt count) -> Containers::Array<UnrealPropertyBase::ptr>;
|
||||||
|
auto deserialise(std::string name, std::string type, UnsignedLong value_length, BinaryReader& reader) -> UnrealPropertyBase::ptr;
|
||||||
|
|
||||||
|
auto serialise(UnrealPropertyBase::ptr& prop, const std::string& item_type, UnsignedLong& bytes_written, BinaryWriter& writer) -> bool;
|
||||||
|
auto write(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer) -> bool;
|
||||||
|
auto writeItem(UnrealPropertyBase::ptr& prop, const std::string& item_type, UnsignedLong& bytes_written, BinaryWriter& writer) -> bool;
|
||||||
|
auto writeSet(Containers::ArrayView<UnrealPropertyBase::ptr> props, const std::string& item_type, UnsignedLong& bytes_written, BinaryWriter& writer) -> bool;
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto getSerialiser(const std::string& item_type) -> AbstractUnrealPropertySerialiser*;
|
||||||
|
auto getCollectionSerialiser(const std::string& item_type) -> AbstractUnrealCollectionPropertySerialiser*;
|
||||||
|
|
||||||
|
Containers::Array<AbstractUnrealPropertySerialiser::ptr> _serialisers;
|
||||||
|
Containers::Array<AbstractUnrealCollectionPropertySerialiser::ptr> _collectionSerialisers;
|
||||||
|
};
|
|
@ -0,0 +1,47 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 <string>
|
||||||
|
|
||||||
|
#include <Corrade/Containers/Array.h>
|
||||||
|
#include <Corrade/Containers/ArrayView.h>
|
||||||
|
#include <Corrade/Containers/Pointer.h>
|
||||||
|
|
||||||
|
#include <Magnum/Types.h>
|
||||||
|
|
||||||
|
#include "../Types/UnrealPropertyBase.h"
|
||||||
|
|
||||||
|
using namespace Corrade;
|
||||||
|
using namespace Magnum;
|
||||||
|
|
||||||
|
class BinaryReader;
|
||||||
|
class BinaryWriter;
|
||||||
|
class PropertySerialiser;
|
||||||
|
|
||||||
|
class AbstractUnrealCollectionPropertySerialiser {
|
||||||
|
public:
|
||||||
|
using ptr = Containers::Pointer<AbstractUnrealCollectionPropertySerialiser>;
|
||||||
|
|
||||||
|
virtual ~AbstractUnrealCollectionPropertySerialiser() = default;
|
||||||
|
|
||||||
|
virtual auto types() -> Containers::ArrayView<const std::string> = 0;
|
||||||
|
|
||||||
|
virtual auto deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, UnsignedInt count, BinaryReader& reader, PropertySerialiser& serialiser) -> Containers::Array<UnrealPropertyBase::ptr> = 0;
|
||||||
|
|
||||||
|
virtual auto serialise(Containers::ArrayView<UnrealPropertyBase::ptr> props, const std::string& item_type, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool = 0;
|
||||||
|
};
|
|
@ -0,0 +1,46 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 <string>
|
||||||
|
|
||||||
|
#include <Corrade/Containers/Array.h>
|
||||||
|
#include <Corrade/Containers/Pointer.h>
|
||||||
|
|
||||||
|
#include <Magnum/Types.h>
|
||||||
|
|
||||||
|
#include "../Types/UnrealPropertyBase.h"
|
||||||
|
|
||||||
|
using namespace Corrade;
|
||||||
|
using namespace Magnum;
|
||||||
|
|
||||||
|
class BinaryReader;
|
||||||
|
class BinaryWriter;
|
||||||
|
class PropertySerialiser;
|
||||||
|
|
||||||
|
class AbstractUnrealPropertySerialiser {
|
||||||
|
public:
|
||||||
|
using ptr = Containers::Pointer<AbstractUnrealPropertySerialiser>;
|
||||||
|
|
||||||
|
virtual ~AbstractUnrealPropertySerialiser() = default;
|
||||||
|
|
||||||
|
virtual auto types() -> Containers::ArrayView<const std::string> = 0;
|
||||||
|
|
||||||
|
virtual auto deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr = 0;
|
||||||
|
|
||||||
|
virtual auto serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool = 0;
|
||||||
|
};
|
46
src/UESaveFile/Serialisers/AbstractUnrealStructSerialiser.h
Normal file
46
src/UESaveFile/Serialisers/AbstractUnrealStructSerialiser.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 <string>
|
||||||
|
|
||||||
|
#include <Corrade/Containers/Array.h>
|
||||||
|
#include <Corrade/Containers/ArrayView.h>
|
||||||
|
#include <Corrade/Containers/Pointer.h>
|
||||||
|
|
||||||
|
#include <Magnum/Types.h>
|
||||||
|
|
||||||
|
#include "../Types/UnrealPropertyBase.h"
|
||||||
|
|
||||||
|
using namespace Corrade;
|
||||||
|
using namespace Magnum;
|
||||||
|
|
||||||
|
class BinaryReader;
|
||||||
|
class BinaryWriter;
|
||||||
|
|
||||||
|
class AbstractUnrealStructSerialiser {
|
||||||
|
public:
|
||||||
|
using ptr = Containers::Pointer<AbstractUnrealStructSerialiser>;
|
||||||
|
|
||||||
|
virtual ~AbstractUnrealStructSerialiser() = default;
|
||||||
|
|
||||||
|
virtual auto supportsType(const std::string& type) -> bool = 0;
|
||||||
|
|
||||||
|
virtual auto deserialise(BinaryReader& reader) -> UnrealPropertyBase::ptr = 0;
|
||||||
|
|
||||||
|
virtual auto serialise(UnrealPropertyBase::ptr& structProp, BinaryWriter& writer, UnsignedLong& bytes_written) -> bool = 0;
|
||||||
|
};
|
66
src/UESaveFile/Serialisers/ArrayPropertySerialiser.cpp
Normal file
66
src/UESaveFile/Serialisers/ArrayPropertySerialiser.cpp
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "../BinaryReader.h"
|
||||||
|
#include "../BinaryWriter.h"
|
||||||
|
#include "../PropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "ArrayPropertySerialiser.h"
|
||||||
|
|
||||||
|
auto ArrayPropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||||
|
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||||
|
{
|
||||||
|
std::string item_type;
|
||||||
|
if(!reader.readUEString(item_type)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
char terminator;
|
||||||
|
if(!reader.readChar(terminator) || terminator != '\0') {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnsignedInt item_count;
|
||||||
|
if(!reader.readUnsignedInt(item_count)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto prop = Containers::pointer<ArrayProperty>();
|
||||||
|
prop->itemType = std::move(item_type);
|
||||||
|
prop->items = serialiser.readSet(reader, prop->itemType, item_count);
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ArrayPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written,
|
||||||
|
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||||
|
{
|
||||||
|
auto array_prop = dynamic_cast<ArrayProperty*>(prop.get());
|
||||||
|
if(!array_prop) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.writeUEStringToArray(array_prop->itemType);
|
||||||
|
writer.writeValueToArray<char>('\0');
|
||||||
|
bytes_written += writer.writeValueToArray<UnsignedInt>(UnsignedInt(array_prop->items.size()));
|
||||||
|
|
||||||
|
UnsignedLong start_pos = writer.arrayPosition();
|
||||||
|
UnsignedLong dummy_bytes_written = 0;
|
||||||
|
bool ret = serialiser.writeSet(array_prop->items, array_prop->itemType, dummy_bytes_written, writer);
|
||||||
|
bytes_written += writer.arrayPosition() - start_pos;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
30
src/UESaveFile/Serialisers/ArrayPropertySerialiser.h
Normal file
30
src/UESaveFile/Serialisers/ArrayPropertySerialiser.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "UnrealPropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "../Types/ArrayProperty.h"
|
||||||
|
|
||||||
|
class ArrayPropertySerialiser : public UnrealPropertySerialiser<ArrayProperty> {
|
||||||
|
public:
|
||||||
|
using ptr = Containers::Pointer<ArrayPropertySerialiser>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override;
|
||||||
|
auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||||
|
};
|
61
src/UESaveFile/Serialisers/BoolPropertySerialiser.cpp
Normal file
61
src/UESaveFile/Serialisers/BoolPropertySerialiser.cpp
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "../BinaryReader.h"
|
||||||
|
#include "../BinaryWriter.h"
|
||||||
|
|
||||||
|
#include "BoolPropertySerialiser.h"
|
||||||
|
|
||||||
|
auto BoolPropertySerialiser::types() -> Containers::ArrayView<const std::string> {
|
||||||
|
static const Containers::Array<std::string> types{InPlaceInit, {"BoolProperty"}};
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BoolPropertySerialiser::deserialise(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||||
|
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||||
|
{
|
||||||
|
if(value_length != 0) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Short value;
|
||||||
|
if(!reader.readShort(value)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(value > 1 || value < 0) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto prop = Containers::pointer<BoolProperty>();
|
||||||
|
prop->value = value;
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BoolPropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written,
|
||||||
|
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||||
|
{
|
||||||
|
auto bool_prop = dynamic_cast<BoolProperty*>(prop.get());
|
||||||
|
|
||||||
|
if(!bool_prop) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.writeValueToArray<Short>(Short(bool_prop->value));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
32
src/UESaveFile/Serialisers/BoolPropertySerialiser.h
Normal file
32
src/UESaveFile/Serialisers/BoolPropertySerialiser.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "AbstractUnrealPropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "../Types/BoolProperty.h"
|
||||||
|
|
||||||
|
class BoolPropertySerialiser : public AbstractUnrealPropertySerialiser {
|
||||||
|
public:
|
||||||
|
using ptr = Containers::Pointer<BoolPropertySerialiser>;
|
||||||
|
|
||||||
|
auto types() -> Containers::ArrayView<const std::string> override;
|
||||||
|
|
||||||
|
auto deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override;
|
||||||
|
|
||||||
|
auto serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||||
|
};
|
82
src/UESaveFile/Serialisers/BytePropertySerialiser.cpp
Normal file
82
src/UESaveFile/Serialisers/BytePropertySerialiser.cpp
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "../BinaryReader.h"
|
||||||
|
#include "../BinaryWriter.h"
|
||||||
|
|
||||||
|
#include "BytePropertySerialiser.h"
|
||||||
|
|
||||||
|
auto BytePropertySerialiser::types() -> Containers::ArrayView<const std::string> {
|
||||||
|
static const Containers::Array<std::string> types{InPlaceInit, {"ByteProperty"}};
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BytePropertySerialiser::deserialise(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||||
|
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||||
|
{
|
||||||
|
auto prop = Containers::pointer<ByteProperty>();
|
||||||
|
|
||||||
|
if(value_length != UnsignedLong(-1)) {
|
||||||
|
if(!reader.readUEString(prop->enumType)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
char terminator;
|
||||||
|
if(!reader.readChar(terminator) || terminator != '\0') {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!reader.readUEString(prop->enumValue)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
prop->valueLength = value_length;
|
||||||
|
|
||||||
|
//UnsignedInt count = 0;
|
||||||
|
//if(!reader.readUnsignedInt(count)) {
|
||||||
|
// return nullptr;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//if(!reader.readArray(prop->value, count)) {
|
||||||
|
// return nullptr;
|
||||||
|
//}
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BytePropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written,
|
||||||
|
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||||
|
{
|
||||||
|
auto byte_prop = dynamic_cast<ByteProperty*>(prop.get());
|
||||||
|
|
||||||
|
if(!byte_prop) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//writer.writeValueToArray<char>('\0');
|
||||||
|
//bytes_written += writer.writeValueToArray<UnsignedInt>(byte_prop->value.size());
|
||||||
|
//bytes_written += writer.writeDataToArray<char>(byte_prop->value);
|
||||||
|
|
||||||
|
if(byte_prop->valueLength != UnsignedLong(-1)) {
|
||||||
|
writer.writeUEStringToArray(byte_prop->enumType);
|
||||||
|
writer.writeValueToArray<char>('\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_written += writer.writeUEStringToArray(byte_prop->enumValue);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
32
src/UESaveFile/Serialisers/BytePropertySerialiser.h
Normal file
32
src/UESaveFile/Serialisers/BytePropertySerialiser.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "AbstractUnrealPropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "../Types/ByteProperty.h"
|
||||||
|
|
||||||
|
class BytePropertySerialiser : public AbstractUnrealPropertySerialiser {
|
||||||
|
public:
|
||||||
|
using ptr = Containers::Pointer<BytePropertySerialiser>;
|
||||||
|
|
||||||
|
auto types() -> Containers::ArrayView<const std::string> override;
|
||||||
|
|
||||||
|
auto deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override;
|
||||||
|
|
||||||
|
auto serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||||
|
};
|
49
src/UESaveFile/Serialisers/ColourPropertySerialiser.cpp
Normal file
49
src/UESaveFile/Serialisers/ColourPropertySerialiser.cpp
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "../BinaryReader.h"
|
||||||
|
#include "../BinaryWriter.h"
|
||||||
|
|
||||||
|
#include "ColourPropertySerialiser.h"
|
||||||
|
|
||||||
|
auto ColourPropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||||
|
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||||
|
{
|
||||||
|
auto prop = Containers::pointer<ColourStructProperty>();
|
||||||
|
|
||||||
|
if(!reader.readFloat(prop->r) || !reader.readFloat(prop->g) ||
|
||||||
|
!reader.readFloat(prop->b) || !reader.readFloat(prop->a))
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ColourPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written,
|
||||||
|
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||||
|
{
|
||||||
|
auto colour_prop = dynamic_cast<ColourStructProperty*>(prop.get());
|
||||||
|
|
||||||
|
if(!colour_prop) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_written += writer.writeValueToArray<Float>(colour_prop->r) + writer.writeValueToArray<Float>(colour_prop->g) +
|
||||||
|
writer.writeValueToArray<Float>(colour_prop->b) + writer.writeValueToArray<Float>(colour_prop->a);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
30
src/UESaveFile/Serialisers/ColourPropertySerialiser.h
Normal file
30
src/UESaveFile/Serialisers/ColourPropertySerialiser.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "UnrealPropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "../Types/ColourStructProperty.h"
|
||||||
|
|
||||||
|
class ColourPropertySerialiser : public UnrealPropertySerialiser<ColourStructProperty> {
|
||||||
|
public:
|
||||||
|
using ptr = Containers::Pointer<ColourPropertySerialiser>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override;
|
||||||
|
auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||||
|
};
|
46
src/UESaveFile/Serialisers/DateTimePropertySerialiser.cpp
Normal file
46
src/UESaveFile/Serialisers/DateTimePropertySerialiser.cpp
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "../BinaryReader.h"
|
||||||
|
#include "../BinaryWriter.h"
|
||||||
|
|
||||||
|
#include "DateTimePropertySerialiser.h"
|
||||||
|
|
||||||
|
auto DateTimePropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||||
|
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||||
|
{
|
||||||
|
auto prop = Containers::pointer<DateTimeStructProperty>();
|
||||||
|
|
||||||
|
if(!reader.readUnsignedLong(prop->timestamp)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto DateTimePropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written,
|
||||||
|
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||||
|
{
|
||||||
|
auto dt_prop = dynamic_cast<DateTimeStructProperty*>(prop.get());
|
||||||
|
|
||||||
|
if(!dt_prop) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_written += writer.writeValueToArray<UnsignedLong>(dt_prop->timestamp);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
30
src/UESaveFile/Serialisers/DateTimePropertySerialiser.h
Normal file
30
src/UESaveFile/Serialisers/DateTimePropertySerialiser.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "UnrealPropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "../Types/DateTimeStructProperty.h"
|
||||||
|
|
||||||
|
class DateTimePropertySerialiser : public UnrealPropertySerialiser<DateTimeStructProperty> {
|
||||||
|
public:
|
||||||
|
using ptr = Containers::Pointer<DateTimePropertySerialiser>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override;
|
||||||
|
auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||||
|
};
|
62
src/UESaveFile/Serialisers/EnumPropertySerialiser.cpp
Normal file
62
src/UESaveFile/Serialisers/EnumPropertySerialiser.cpp
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "../BinaryReader.h"
|
||||||
|
#include "../BinaryWriter.h"
|
||||||
|
|
||||||
|
#include "EnumPropertySerialiser.h"
|
||||||
|
|
||||||
|
auto EnumPropertySerialiser::types() -> Containers::ArrayView<const std::string> {
|
||||||
|
static const Containers::Array<std::string> types{InPlaceInit, {"EnumProperty"}};
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto EnumPropertySerialiser::deserialise(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||||
|
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||||
|
{
|
||||||
|
auto prop = Containers::pointer<EnumProperty>();
|
||||||
|
|
||||||
|
if(!reader.readUEString(prop->enumType)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
char terminator;
|
||||||
|
if(!reader.readChar(terminator) || terminator != '\0') {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!reader.readUEString(prop->value)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto EnumPropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written,
|
||||||
|
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||||
|
{
|
||||||
|
auto enum_prop = dynamic_cast<EnumProperty*>(prop.get());
|
||||||
|
|
||||||
|
if(!enum_prop) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.writeUEStringToArray(enum_prop->enumType);
|
||||||
|
writer.writeValueToArray<char>('\0');
|
||||||
|
bytes_written += writer.writeUEStringToArray(enum_prop->value);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
32
src/UESaveFile/Serialisers/EnumPropertySerialiser.h
Normal file
32
src/UESaveFile/Serialisers/EnumPropertySerialiser.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "AbstractUnrealPropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "../Types/EnumProperty.h"
|
||||||
|
|
||||||
|
class EnumPropertySerialiser : public AbstractUnrealPropertySerialiser {
|
||||||
|
public:
|
||||||
|
using ptr = Containers::Pointer<EnumPropertySerialiser>;
|
||||||
|
|
||||||
|
auto types() -> Containers::ArrayView<const std::string> override;
|
||||||
|
|
||||||
|
auto deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override;
|
||||||
|
|
||||||
|
auto serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||||
|
};
|
57
src/UESaveFile/Serialisers/FloatPropertySerialiser.cpp
Normal file
57
src/UESaveFile/Serialisers/FloatPropertySerialiser.cpp
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "../BinaryReader.h"
|
||||||
|
#include "../BinaryWriter.h"
|
||||||
|
|
||||||
|
#include "FloatPropertySerialiser.h"
|
||||||
|
|
||||||
|
auto FloatPropertySerialiser::types() -> Containers::ArrayView<const std::string> {
|
||||||
|
static const Containers::Array<std::string> types{InPlaceInit, {"FloatProperty"}};
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto FloatPropertySerialiser::deserialise(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||||
|
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||||
|
{
|
||||||
|
auto prop = Containers::pointer<FloatProperty>();
|
||||||
|
|
||||||
|
char terminator;
|
||||||
|
if(!reader.readChar(terminator) || terminator != '\0') {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!reader.readFloat(prop->value)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto FloatPropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written,
|
||||||
|
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||||
|
{
|
||||||
|
auto float_prop = dynamic_cast<FloatProperty*>(prop.get());
|
||||||
|
|
||||||
|
if(!float_prop) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.writeValueToArray<char>('\0');
|
||||||
|
bytes_written += writer.writeValueToArray<Float>(float_prop->value);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
32
src/UESaveFile/Serialisers/FloatPropertySerialiser.h
Normal file
32
src/UESaveFile/Serialisers/FloatPropertySerialiser.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "AbstractUnrealPropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "../Types/FloatProperty.h"
|
||||||
|
|
||||||
|
class FloatPropertySerialiser : public AbstractUnrealPropertySerialiser {
|
||||||
|
public:
|
||||||
|
using ptr = Containers::Pointer<FloatPropertySerialiser>;
|
||||||
|
|
||||||
|
auto types() -> Containers::ArrayView<const std::string> override;
|
||||||
|
|
||||||
|
auto deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override;
|
||||||
|
|
||||||
|
auto serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||||
|
};
|
47
src/UESaveFile/Serialisers/GuidPropertySerialiser.cpp
Normal file
47
src/UESaveFile/Serialisers/GuidPropertySerialiser.cpp
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "../BinaryReader.h"
|
||||||
|
#include "../BinaryWriter.h"
|
||||||
|
|
||||||
|
#include "GuidPropertySerialiser.h"
|
||||||
|
|
||||||
|
auto GuidPropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||||
|
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||||
|
{
|
||||||
|
auto prop = Containers::pointer<GuidStructProperty>();
|
||||||
|
|
||||||
|
if(!reader.readStaticArray(prop->guid)) {
|
||||||
|
Utility::Error{} << "Couldn't read guid in" << __func__;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto GuidPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written,
|
||||||
|
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||||
|
{
|
||||||
|
auto guid_prop = dynamic_cast<GuidStructProperty*>(prop.get());
|
||||||
|
|
||||||
|
if(!guid_prop) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_written += writer.writeDataToArray<char>({guid_prop->guid.data(), guid_prop->guid.size()});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
31
src/UESaveFile/Serialisers/GuidPropertySerialiser.h
Normal file
31
src/UESaveFile/Serialisers/GuidPropertySerialiser.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "UnrealPropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "../Types/GuidStructProperty.h"
|
||||||
|
|
||||||
|
class GuidPropertySerialiser : public UnrealPropertySerialiser<GuidStructProperty> {
|
||||||
|
public:
|
||||||
|
using ptr = Containers::Pointer<GuidPropertySerialiser>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||||
|
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override;
|
||||||
|
auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||||
|
};
|
66
src/UESaveFile/Serialisers/IntPropertySerialiser.cpp
Normal file
66
src/UESaveFile/Serialisers/IntPropertySerialiser.cpp
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "../BinaryReader.h"
|
||||||
|
#include "../BinaryWriter.h"
|
||||||
|
|
||||||
|
#include "IntPropertySerialiser.h"
|
||||||
|
|
||||||
|
auto IntPropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||||
|
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||||
|
{
|
||||||
|
auto prop = Containers::pointer<IntProperty>();
|
||||||
|
|
||||||
|
if(value_length == UnsignedLong(-1)) {
|
||||||
|
if(!reader.readInt(prop->value)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
prop->valueLength = UnsignedLong(-1);
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
char terminator;
|
||||||
|
if(!reader.readChar(terminator) || terminator != '\0') {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!reader.readInt(prop->value)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
prop->name.emplace(name);
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto IntPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written,
|
||||||
|
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||||
|
{
|
||||||
|
auto int_prop = dynamic_cast<IntProperty*>(prop.get());
|
||||||
|
|
||||||
|
if(!int_prop) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(prop->valueLength != UnsignedLong(-1)) {
|
||||||
|
writer.writeValueToArray<char>('\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_written += writer.writeValueToArray<Int>(int_prop->value);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
30
src/UESaveFile/Serialisers/IntPropertySerialiser.h
Normal file
30
src/UESaveFile/Serialisers/IntPropertySerialiser.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "UnrealPropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "../Types/IntProperty.h"
|
||||||
|
|
||||||
|
class IntPropertySerialiser : public UnrealPropertySerialiser<IntProperty> {
|
||||||
|
public:
|
||||||
|
using ptr = Containers::Pointer<IntPropertySerialiser>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override;
|
||||||
|
auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||||
|
};
|
140
src/UESaveFile/Serialisers/MapPropertySerialiser.cpp
Normal file
140
src/UESaveFile/Serialisers/MapPropertySerialiser.cpp
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "../BinaryReader.h"
|
||||||
|
#include "../BinaryWriter.h"
|
||||||
|
#include "../PropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "../Types/NoneProperty.h"
|
||||||
|
|
||||||
|
#include "MapPropertySerialiser.h"
|
||||||
|
|
||||||
|
auto MapPropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||||
|
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||||
|
{
|
||||||
|
auto prop = Containers::pointer<MapProperty>();
|
||||||
|
|
||||||
|
if(!reader.readUEString(prop->keyType)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!reader.readUEString(prop->valueType)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
char terminator;
|
||||||
|
if(!reader.readChar(terminator) || terminator != '\0') {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnsignedInt null;
|
||||||
|
if(!reader.readUnsignedInt(null) || null != 0u) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnsignedInt count;
|
||||||
|
if(!reader.readUnsignedInt(count)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin dirty code because the MapProperty format doesn't seem to match any of the GVAS reading stuff I've found,
|
||||||
|
// so I'm just gonna write stuff that matches the only MapProperty I can find in MB's save files.
|
||||||
|
|
||||||
|
arrayReserve(prop->map, count);
|
||||||
|
|
||||||
|
for(UnsignedInt i = 0; i < count; i++) {
|
||||||
|
MapProperty::KeyValuePair pair;
|
||||||
|
|
||||||
|
if(prop->keyType == "IntProperty" || prop->keyType == "StrProperty") {
|
||||||
|
pair.key = serialiser.readItem(reader, prop->keyType, -1, name);
|
||||||
|
if(pair.key == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // Add other branches depending on key type, should more maps appear in the future.
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnrealPropertyBase::ptr value_item;
|
||||||
|
if(prop->valueType == "StructProperty") {
|
||||||
|
while((value_item = serialiser.read(reader)) != nullptr) {
|
||||||
|
arrayAppend(pair.values, std::move(value_item));
|
||||||
|
|
||||||
|
if(pair.values.back()->name == "None" &&
|
||||||
|
pair.values.back()->propertyType == "NoneProperty" &&
|
||||||
|
dynamic_cast<NoneProperty*>(pair.values.back().get()) != nullptr)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(prop->valueType == "ByteProperty") {
|
||||||
|
if((value_item = serialiser.readItem(reader, prop->valueType, -1, name)) == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
arrayAppend(pair.values, std::move(value_item));
|
||||||
|
}
|
||||||
|
|
||||||
|
arrayAppend(prop->map, std::move(pair));
|
||||||
|
}
|
||||||
|
|
||||||
|
// End dirty code
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto MapPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written,
|
||||||
|
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||||
|
{
|
||||||
|
auto map_prop = dynamic_cast<MapProperty*>(prop.get());
|
||||||
|
if(!map_prop) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.writeUEStringToArray(map_prop->keyType);
|
||||||
|
writer.writeUEStringToArray(map_prop->valueType);
|
||||||
|
writer.writeValueToArray<char>('\0');
|
||||||
|
|
||||||
|
UnsignedLong value_start = writer.arrayPosition();
|
||||||
|
writer.writeValueToArray<UnsignedInt>(0u);
|
||||||
|
|
||||||
|
writer.writeValueToArray<UnsignedInt>(UnsignedInt(map_prop->map.size()));
|
||||||
|
|
||||||
|
UnsignedLong dummy_bytes_written = 0;
|
||||||
|
for(auto& pair : map_prop->map) {
|
||||||
|
if(!serialiser.writeItem(pair.key, map_prop->keyType, dummy_bytes_written, writer)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto& value : pair.values) {
|
||||||
|
if(map_prop->valueType == "StructProperty") {
|
||||||
|
if(!serialiser.write(value, dummy_bytes_written, writer)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(!serialiser.writeItem(value, map_prop->valueType, dummy_bytes_written, writer)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_written += (writer.arrayPosition() - value_start);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
30
src/UESaveFile/Serialisers/MapPropertySerialiser.h
Normal file
30
src/UESaveFile/Serialisers/MapPropertySerialiser.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "UnrealPropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "../Types/MapProperty.h"
|
||||||
|
|
||||||
|
class MapPropertySerialiser : public UnrealPropertySerialiser<MapProperty> {
|
||||||
|
public:
|
||||||
|
using ptr = Containers::Pointer<MapPropertySerialiser>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override;
|
||||||
|
auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||||
|
};
|
103
src/UESaveFile/Serialisers/ResourcePropertySerialiser.cpp
Normal file
103
src/UESaveFile/Serialisers/ResourcePropertySerialiser.cpp
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "../BinaryReader.h"
|
||||||
|
#include "../BinaryWriter.h"
|
||||||
|
#include "../PropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "../Types/IntProperty.h"
|
||||||
|
#include "../Types/NoneProperty.h"
|
||||||
|
|
||||||
|
#include "ResourcePropertySerialiser.h"
|
||||||
|
|
||||||
|
auto ResourcePropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||||
|
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||||
|
{
|
||||||
|
auto prop = Containers::pointer<ResourceItemValue>();
|
||||||
|
|
||||||
|
std::string str;
|
||||||
|
if(!reader.readUEString(str) || str != "ID_4_AAE08F17428E229EC7A2209F51081A21") {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!reader.readUEString(str) || str != "IntProperty") {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!reader.readUnsignedLong(value_length) || value_length != 4ull) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
char terminator;
|
||||||
|
if(!reader.readChar(terminator) || terminator != '\0') {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!reader.readInt(prop->id)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!reader.readUEString(str) || str != "Quantity_3_560F09B5485C365D3041888910019CE3") {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!reader.readUEString(str) || str != "IntProperty") {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!reader.readUnsignedLong(value_length) || value_length != 4ull) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!reader.readChar(terminator) || terminator != '\0') {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!reader.readInt(prop->quantity)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!reader.readUEString(str) || str != "None") {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ResourcePropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written,
|
||||||
|
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||||
|
{
|
||||||
|
auto res_prop = dynamic_cast<ResourceItemValue*>(prop.get());
|
||||||
|
if(!res_prop) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_written += writer.writeUEStringToArray("ID_4_AAE08F17428E229EC7A2209F51081A21") +
|
||||||
|
writer.writeUEStringToArray("IntProperty") +
|
||||||
|
writer.writeValueToArray<UnsignedLong>(4ull) +
|
||||||
|
writer.writeValueToArray<char>('\0') +
|
||||||
|
writer.writeValueToArray<Int>(res_prop->id);
|
||||||
|
|
||||||
|
bytes_written += writer.writeUEStringToArray("Quantity_3_560F09B5485C365D3041888910019CE3") +
|
||||||
|
writer.writeUEStringToArray("IntProperty") +
|
||||||
|
writer.writeValueToArray<UnsignedLong>(4ull) +
|
||||||
|
writer.writeValueToArray<char>('\0') +
|
||||||
|
writer.writeValueToArray<Int>(res_prop->quantity);
|
||||||
|
|
||||||
|
bytes_written += writer.writeUEStringToArray("None");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
30
src/UESaveFile/Serialisers/ResourcePropertySerialiser.h
Normal file
30
src/UESaveFile/Serialisers/ResourcePropertySerialiser.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "UnrealPropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "../Types/ResourceItemValue.h"
|
||||||
|
|
||||||
|
class ResourcePropertySerialiser : public UnrealPropertySerialiser<ResourceItemValue> {
|
||||||
|
public:
|
||||||
|
using ptr = Containers::Pointer<ResourcePropertySerialiser>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override;
|
||||||
|
auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||||
|
};
|
47
src/UESaveFile/Serialisers/RotatorPropertySerialiser.cpp
Normal file
47
src/UESaveFile/Serialisers/RotatorPropertySerialiser.cpp
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "../BinaryReader.h"
|
||||||
|
#include "../BinaryWriter.h"
|
||||||
|
|
||||||
|
#include "RotatorPropertySerialiser.h"
|
||||||
|
|
||||||
|
auto RotatorPropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||||
|
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||||
|
{
|
||||||
|
auto prop = Containers::pointer<RotatorStructProperty>();
|
||||||
|
|
||||||
|
if(!reader.readFloat(prop->x) || !reader.readFloat(prop->y) || !reader.readFloat(prop->z)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto RotatorPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written,
|
||||||
|
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||||
|
{
|
||||||
|
auto rotator = dynamic_cast<RotatorStructProperty*>(prop.get());
|
||||||
|
|
||||||
|
if(!rotator) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_written += writer.writeValueToArray<Float>(rotator->x) + writer.writeValueToArray<Float>(rotator->y) +
|
||||||
|
writer.writeValueToArray<Float>(rotator->z);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
30
src/UESaveFile/Serialisers/RotatorPropertySerialiser.h
Normal file
30
src/UESaveFile/Serialisers/RotatorPropertySerialiser.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "UnrealPropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "../Types/RotatorStructProperty.h"
|
||||||
|
|
||||||
|
class RotatorPropertySerialiser : public UnrealPropertySerialiser<RotatorStructProperty> {
|
||||||
|
public:
|
||||||
|
using ptr = Containers::Pointer<RotatorPropertySerialiser>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override;
|
||||||
|
auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||||
|
};
|
73
src/UESaveFile/Serialisers/SetPropertySerialiser.cpp
Normal file
73
src/UESaveFile/Serialisers/SetPropertySerialiser.cpp
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "../BinaryReader.h"
|
||||||
|
#include "../BinaryWriter.h"
|
||||||
|
#include "../PropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "SetPropertySerialiser.h"
|
||||||
|
|
||||||
|
auto SetPropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||||
|
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||||
|
{
|
||||||
|
std::string item_type;
|
||||||
|
if(!reader.readUEString(item_type)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
char terminator;
|
||||||
|
if(!reader.readChar(terminator) || terminator != '\0') {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnsignedInt four_bytes;
|
||||||
|
if(!reader.readUnsignedInt(four_bytes) || four_bytes != 0u) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnsignedInt item_count;
|
||||||
|
if(!reader.readUnsignedInt(item_count)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto prop = Containers::pointer<SetProperty>();
|
||||||
|
prop->itemType = std::move(item_type);
|
||||||
|
prop->items = serialiser.readSet(reader, prop->itemType, item_count);
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto SetPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written,
|
||||||
|
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||||
|
{
|
||||||
|
auto set_prop = dynamic_cast<SetProperty*>(prop.get());
|
||||||
|
if(!set_prop) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.writeUEStringToArray(set_prop->itemType);
|
||||||
|
writer.writeValueToArray<char>('\0');
|
||||||
|
|
||||||
|
bytes_written += writer.writeValueToArray<UnsignedInt>(0u);
|
||||||
|
bytes_written += writer.writeValueToArray<UnsignedInt>(UnsignedInt(set_prop->items.size()));
|
||||||
|
|
||||||
|
UnsignedLong start_pos = writer.arrayPosition();
|
||||||
|
UnsignedLong dummy_bytes_written = 0;
|
||||||
|
serialiser.writeSet(set_prop->items, set_prop->itemType, dummy_bytes_written, writer);
|
||||||
|
bytes_written += writer.arrayPosition() - start_pos;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
30
src/UESaveFile/Serialisers/SetPropertySerialiser.h
Normal file
30
src/UESaveFile/Serialisers/SetPropertySerialiser.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "UnrealPropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "../Types/SetProperty.h"
|
||||||
|
|
||||||
|
class SetPropertySerialiser : public UnrealPropertySerialiser<SetProperty> {
|
||||||
|
public:
|
||||||
|
using ptr = Containers::Pointer<SetPropertySerialiser>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override;
|
||||||
|
auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||||
|
};
|
64
src/UESaveFile/Serialisers/StringPropertySerialiser.cpp
Normal file
64
src/UESaveFile/Serialisers/StringPropertySerialiser.cpp
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "../BinaryReader.h"
|
||||||
|
#include "../BinaryWriter.h"
|
||||||
|
|
||||||
|
#include "StringPropertySerialiser.h"
|
||||||
|
|
||||||
|
auto StringPropertySerialiser::types() -> Containers::ArrayView<const std::string> {
|
||||||
|
static const Containers::Array<std::string> types{InPlaceInit, {"NameProperty", "StrProperty", "SoftObjectProperty", "ObjectProperty"}};
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto StringPropertySerialiser::deserialise(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||||
|
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||||
|
{
|
||||||
|
auto prop = Containers::pointer<StringProperty>(type);
|
||||||
|
|
||||||
|
if(value_length != UnsignedLong(-1)) {
|
||||||
|
char terminator;
|
||||||
|
if(!reader.readChar(terminator) || terminator != '\0') {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!reader.readUEString(prop->value)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
prop->valueLength = value_length;
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto StringPropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written,
|
||||||
|
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||||
|
{
|
||||||
|
auto str_prop = dynamic_cast<StringProperty*>(prop.get());
|
||||||
|
|
||||||
|
if(!str_prop) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(str_prop->valueLength != UnsignedLong(-1)) {
|
||||||
|
writer.writeValueToArray<char>('\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_written += writer.writeUEStringToArray(str_prop->value);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
32
src/UESaveFile/Serialisers/StringPropertySerialiser.h
Normal file
32
src/UESaveFile/Serialisers/StringPropertySerialiser.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "AbstractUnrealPropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "../Types/StringProperty.h"
|
||||||
|
|
||||||
|
class StringPropertySerialiser : public AbstractUnrealPropertySerialiser {
|
||||||
|
public:
|
||||||
|
using ptr = Containers::Pointer<StringPropertySerialiser>;
|
||||||
|
|
||||||
|
auto types() -> Containers::ArrayView<const std::string> override;
|
||||||
|
|
||||||
|
auto deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override;
|
||||||
|
|
||||||
|
auto serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||||
|
};
|
218
src/UESaveFile/Serialisers/StructSerialiser.cpp
Normal file
218
src/UESaveFile/Serialisers/StructSerialiser.cpp
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "../BinaryReader.h"
|
||||||
|
#include "../BinaryWriter.h"
|
||||||
|
#include "../PropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "../Types/GenericStructProperty.h"
|
||||||
|
#include "../Types/NoneProperty.h"
|
||||||
|
|
||||||
|
#include "StructSerialiser.h"
|
||||||
|
|
||||||
|
auto StructSerialiser::types() -> Containers::ArrayView<const std::string> {
|
||||||
|
static const Containers::Array<std::string> types{InPlaceInit, {"StructProperty"}};
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto StructSerialiser::deserialise(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||||
|
UnsignedInt count, BinaryReader& reader, PropertySerialiser& serialiser) -> Containers::Array<UnrealPropertyBase::ptr>
|
||||||
|
{
|
||||||
|
std::string item_type;
|
||||||
|
if(!reader.readUEString(item_type)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Containers::StaticArray<16, char> guid{ValueInit};
|
||||||
|
if(!reader.readStaticArray(guid)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
char terminator;
|
||||||
|
if(!reader.readChar(terminator) || terminator != '\0') {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Containers::Array<UnrealPropertyBase::ptr> array;
|
||||||
|
|
||||||
|
if(count == 0) {
|
||||||
|
auto prop = Containers::pointer<GenericStructProperty>();
|
||||||
|
prop->structType = std::move(item_type);
|
||||||
|
prop->structGuid = std::move(guid);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for(UnsignedInt i = 0; i < count; i++) {
|
||||||
|
auto prop = Containers::pointer<UnrealPropertyBase>();
|
||||||
|
|
||||||
|
prop = serialiser.readItem(reader, item_type, UnsignedLong(-1), name);
|
||||||
|
|
||||||
|
if(!prop) {
|
||||||
|
prop = readStructValue(name, item_type, value_length, reader, serialiser);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!prop) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static_cast<StructProperty*>(prop.get())->structGuid = guid;
|
||||||
|
|
||||||
|
arrayAppend(array, std::move(prop));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto StructSerialiser::deserialise(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||||
|
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||||
|
{
|
||||||
|
std::string item_type;
|
||||||
|
if(!reader.readUEString(item_type)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(item_type == "None") {
|
||||||
|
return Containers::pointer<NoneProperty>();
|
||||||
|
}
|
||||||
|
|
||||||
|
Containers::StaticArray<16, char> guid{ValueInit};
|
||||||
|
if(!reader.readStaticArray(guid)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
char terminator;
|
||||||
|
if(!reader.readChar(terminator) || terminator != '\0') {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnrealPropertyBase::ptr prop = serialiser.readItem(reader, item_type, value_length, name);
|
||||||
|
|
||||||
|
if(!prop) {
|
||||||
|
prop = readStructValue(name, item_type, value_length, reader, serialiser);
|
||||||
|
if(prop) {
|
||||||
|
dynamic_cast<GenericStructProperty*>(prop.get())->structGuid = std::move(guid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto StructSerialiser::serialise(Containers::ArrayView<UnrealPropertyBase::ptr> props, const std::string& item_type,
|
||||||
|
UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||||
|
{
|
||||||
|
bytes_written += writer.writeUEStringToArray(*(props.front()->name));
|
||||||
|
bytes_written += writer.writeUEStringToArray(item_type);
|
||||||
|
UnsignedLong vl_pos = writer.arrayPosition();
|
||||||
|
bytes_written += writer.writeValueToArray<UnsignedLong>(0ull);
|
||||||
|
|
||||||
|
auto struct_prop = dynamic_cast<StructProperty*>(props.front().get());
|
||||||
|
if(!struct_prop) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_written += writer.writeUEStringToArray(struct_prop->structType);
|
||||||
|
bytes_written += writer.writeDataToArray(arrayView(struct_prop->structGuid));
|
||||||
|
bytes_written += writer.writeValueToArray<char>('\0');
|
||||||
|
|
||||||
|
UnsignedLong vl_start = writer.arrayPosition();
|
||||||
|
|
||||||
|
UnsignedLong bytes_written_here = 0;
|
||||||
|
for(auto& prop : props) {
|
||||||
|
struct_prop = dynamic_cast<StructProperty*>(prop.get());
|
||||||
|
|
||||||
|
if(!struct_prop) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!serialiser.writeItem(prop, struct_prop->structType, bytes_written_here, writer)) {
|
||||||
|
if(!writeStructValue(struct_prop, bytes_written_here, writer, serialiser)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UnsignedLong vl_stop = writer.arrayPosition() - vl_start;
|
||||||
|
writer.writeValueToArrayAt(vl_stop, vl_pos);
|
||||||
|
bytes_written += vl_stop;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto StructSerialiser::serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written,
|
||||||
|
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||||
|
{
|
||||||
|
auto struct_prop = dynamic_cast<StructProperty*>(prop.get());
|
||||||
|
|
||||||
|
if(!struct_prop) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.writeUEStringToArray(struct_prop->structType);
|
||||||
|
writer.writeDataToArray(arrayView(struct_prop->structGuid));
|
||||||
|
writer.writeValueToArray<char>('\0');
|
||||||
|
|
||||||
|
if(!serialiser.writeItem(prop, struct_prop->structType, bytes_written, writer)) {
|
||||||
|
UnsignedLong dummy_bytes_written = 0;
|
||||||
|
UnsignedLong vl_start = writer.arrayPosition();
|
||||||
|
if(!writeStructValue(struct_prop, dummy_bytes_written, writer, serialiser)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bytes_written += writer.arrayPosition() - vl_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto StructSerialiser::readStructValue(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||||
|
BinaryReader& reader, PropertySerialiser& serialiser) -> StructProperty::ptr
|
||||||
|
{
|
||||||
|
auto st_prop = Containers::pointer<GenericStructProperty>();
|
||||||
|
st_prop->structType = type;
|
||||||
|
|
||||||
|
UnrealPropertyBase::ptr prop;
|
||||||
|
while((prop = serialiser.read(reader)) != nullptr) {
|
||||||
|
arrayAppend(st_prop->properties, std::move(prop));
|
||||||
|
|
||||||
|
if(st_prop->properties.back()->name == "None" &&
|
||||||
|
st_prop->properties.back()->propertyType == "NoneProperty" &&
|
||||||
|
dynamic_cast<NoneProperty*>(st_prop->properties.back().get()) != nullptr)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
st_prop->name.emplace(name);
|
||||||
|
|
||||||
|
return st_prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto StructSerialiser::writeStructValue(StructProperty* prop, UnsignedLong& bytes_written,
|
||||||
|
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||||
|
{
|
||||||
|
auto struct_prop = dynamic_cast<GenericStructProperty*>(prop);
|
||||||
|
|
||||||
|
if(!struct_prop) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto& item : struct_prop->properties) {
|
||||||
|
if(!serialiser.write(item, bytes_written, writer)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
45
src/UESaveFile/Serialisers/StructSerialiser.h
Normal file
45
src/UESaveFile/Serialisers/StructSerialiser.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "AbstractUnrealCollectionPropertySerialiser.h"
|
||||||
|
#include "AbstractUnrealPropertySerialiser.h"
|
||||||
|
#include "AbstractUnrealStructSerialiser.h"
|
||||||
|
|
||||||
|
#include "../Types/StructProperty.h"
|
||||||
|
|
||||||
|
class StructSerialiser : public AbstractUnrealPropertySerialiser, public AbstractUnrealCollectionPropertySerialiser {
|
||||||
|
public:
|
||||||
|
using ptr = Containers::Pointer<StructSerialiser>;
|
||||||
|
|
||||||
|
auto types() -> Containers::ArrayView<const std::string> override;
|
||||||
|
|
||||||
|
auto deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, UnsignedInt count,
|
||||||
|
BinaryReader& reader, PropertySerialiser& serialiser) -> Containers::Array<UnrealPropertyBase::ptr> override;
|
||||||
|
auto deserialise(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||||
|
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override;
|
||||||
|
|
||||||
|
auto serialise(Containers::ArrayView<UnrealPropertyBase::ptr> props, const std::string& item_type, UnsignedLong& bytes_written,
|
||||||
|
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||||
|
auto serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written,
|
||||||
|
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto readStructValue(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||||
|
BinaryReader& reader, PropertySerialiser& serialiser) -> StructProperty::ptr;
|
||||||
|
auto writeStructValue(StructProperty* prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool;
|
||||||
|
};
|
84
src/UESaveFile/Serialisers/TextPropertySerialiser.cpp
Normal file
84
src/UESaveFile/Serialisers/TextPropertySerialiser.cpp
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "../BinaryReader.h"
|
||||||
|
#include "../BinaryWriter.h"
|
||||||
|
|
||||||
|
#include "TextPropertySerialiser.h"
|
||||||
|
|
||||||
|
auto TextPropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||||
|
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||||
|
{
|
||||||
|
auto prop = Containers::pointer<TextProperty>();
|
||||||
|
|
||||||
|
Long start_position = reader.position();
|
||||||
|
|
||||||
|
char terminator;
|
||||||
|
if(!reader.readChar(terminator) || terminator != '\0') {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(reader.peekChar() > 0) {
|
||||||
|
if(!reader.readArray(prop->flags, 8)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(!reader.readArray(prop->flags, 4)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!reader.readChar(prop->id)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto interval = reader.position() - start_position;
|
||||||
|
|
||||||
|
do {
|
||||||
|
std::string str;
|
||||||
|
|
||||||
|
if(!reader.readUEString(str)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
arrayAppend(prop->data, std::move(str));
|
||||||
|
|
||||||
|
interval = reader.position() - start_position;
|
||||||
|
} while(UnsignedLong(interval) < value_length);
|
||||||
|
|
||||||
|
prop->value = prop->data.back();
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto TextPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written,
|
||||||
|
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||||
|
{
|
||||||
|
auto text_prop = dynamic_cast<TextProperty*>(prop.get());
|
||||||
|
|
||||||
|
if(!text_prop) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.writeValueToArray<char>('\0');
|
||||||
|
bytes_written += writer.writeDataToArray<char>(text_prop->flags);
|
||||||
|
for(const auto& str : text_prop->data) {
|
||||||
|
bytes_written += writer.writeUEStringToArray(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
30
src/UESaveFile/Serialisers/TextPropertySerialiser.h
Normal file
30
src/UESaveFile/Serialisers/TextPropertySerialiser.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "UnrealPropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "../Types/TextProperty.h"
|
||||||
|
|
||||||
|
class TextPropertySerialiser : public UnrealPropertySerialiser<TextProperty> {
|
||||||
|
public:
|
||||||
|
using ptr = Containers::Pointer<TextPropertySerialiser>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override;
|
||||||
|
auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||||
|
};
|
58
src/UESaveFile/Serialisers/UnrealPropertySerialiser.h
Normal file
58
src/UESaveFile/Serialisers/UnrealPropertySerialiser.h
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 <type_traits>
|
||||||
|
|
||||||
|
#include "AbstractUnrealPropertySerialiser.h"
|
||||||
|
#include "../Types/StructProperty.h"
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class UnrealPropertySerialiser : public AbstractUnrealPropertySerialiser {
|
||||||
|
static_assert(std::is_base_of<UnrealPropertyBase, T>::value, "T must be derived from UnrealPropertyBase.");
|
||||||
|
|
||||||
|
public:
|
||||||
|
using ptr = Containers::Pointer<UnrealPropertySerialiser<T>>;
|
||||||
|
|
||||||
|
auto types() -> Containers::ArrayView<const std::string> override {
|
||||||
|
static const Containers::Array<std::string> types = []{
|
||||||
|
Containers::Array<std::string> array;
|
||||||
|
Containers::Pointer<T> p(new T);
|
||||||
|
if(std::is_base_of<StructProperty, T>::value) {
|
||||||
|
array = Containers::Array<std::string>{InPlaceInit, {dynamic_cast<StructProperty*>(p.get())->structType}};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
array = Containers::Array<std::string>{InPlaceInit, {p->propertyType}};
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}();
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override {
|
||||||
|
return deserialiseProperty(name, type, value_length, reader, serialiser);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override {
|
||||||
|
return serialiseProperty(prop, bytes_written, writer, serialiser);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> typename UnrealPropertyBase::ptr = 0;
|
||||||
|
|
||||||
|
virtual auto serialiseProperty(typename UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool = 0;
|
||||||
|
};
|
46
src/UESaveFile/Serialisers/Vector2DPropertySerialiser.cpp
Normal file
46
src/UESaveFile/Serialisers/Vector2DPropertySerialiser.cpp
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "../BinaryReader.h"
|
||||||
|
#include "../BinaryWriter.h"
|
||||||
|
|
||||||
|
#include "Vector2DPropertySerialiser.h"
|
||||||
|
|
||||||
|
auto Vector2DPropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||||
|
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||||
|
{
|
||||||
|
auto prop = Containers::pointer<Vector2DStructProperty>();
|
||||||
|
|
||||||
|
if(!reader.readFloat(prop->x) || !reader.readFloat(prop->y)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Vector2DPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written,
|
||||||
|
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||||
|
{
|
||||||
|
auto vector = dynamic_cast<Vector2DStructProperty*>(prop.get());
|
||||||
|
|
||||||
|
if(!vector) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_written += writer.writeValueToArray<Float>(vector->x) + writer.writeValueToArray<Float>(vector->y);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
30
src/UESaveFile/Serialisers/Vector2DPropertySerialiser.h
Normal file
30
src/UESaveFile/Serialisers/Vector2DPropertySerialiser.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "UnrealPropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "../Types/Vector2DStructProperty.h"
|
||||||
|
|
||||||
|
class Vector2DPropertySerialiser : public UnrealPropertySerialiser<Vector2DStructProperty> {
|
||||||
|
public:
|
||||||
|
using ptr = Containers::Pointer<Vector2DPropertySerialiser>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override;
|
||||||
|
auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||||
|
};
|
47
src/UESaveFile/Serialisers/VectorPropertySerialiser.cpp
Normal file
47
src/UESaveFile/Serialisers/VectorPropertySerialiser.cpp
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "../BinaryReader.h"
|
||||||
|
#include "../BinaryWriter.h"
|
||||||
|
|
||||||
|
#include "VectorPropertySerialiser.h"
|
||||||
|
|
||||||
|
auto VectorPropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||||
|
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||||
|
{
|
||||||
|
auto prop = Containers::pointer<VectorStructProperty>();
|
||||||
|
|
||||||
|
if(!reader.readFloat(prop->x) || !reader.readFloat(prop->y) || !reader.readFloat(prop->z)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto VectorPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written,
|
||||||
|
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||||
|
{
|
||||||
|
auto vector = dynamic_cast<VectorStructProperty*>(prop.get());
|
||||||
|
|
||||||
|
if(!vector) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_written += writer.writeValueToArray<Float>(vector->x) + writer.writeValueToArray<Float>(vector->y) +
|
||||||
|
writer.writeValueToArray<Float>(vector->z);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
30
src/UESaveFile/Serialisers/VectorPropertySerialiser.h
Normal file
30
src/UESaveFile/Serialisers/VectorPropertySerialiser.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "UnrealPropertySerialiser.h"
|
||||||
|
|
||||||
|
#include "../Types/VectorStructProperty.h"
|
||||||
|
|
||||||
|
class VectorPropertySerialiser : public UnrealPropertySerialiser<VectorStructProperty> {
|
||||||
|
public:
|
||||||
|
using ptr = Containers::Pointer<VectorPropertySerialiser>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override;
|
||||||
|
auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||||
|
};
|
42
src/UESaveFile/Types/ArrayProperty.h
Normal file
42
src/UESaveFile/Types/ArrayProperty.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "UnrealPropertyBase.h"
|
||||||
|
|
||||||
|
struct ArrayProperty : public UnrealPropertyBase {
|
||||||
|
using ptr = Containers::Pointer<ArrayProperty>;
|
||||||
|
|
||||||
|
ArrayProperty() {
|
||||||
|
propertyType = "ArrayProperty";
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::enable_if_t<std::is_base_of<UnrealPropertyBase, T>::value, T*>
|
||||||
|
at(std::size_t index) {
|
||||||
|
if(index >= items.size()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<T*>(items[index].get());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string itemType;
|
||||||
|
Containers::Array<UnrealPropertyBase::ptr> items;
|
||||||
|
};
|
27
src/UESaveFile/Types/BoolProperty.h
Normal file
27
src/UESaveFile/Types/BoolProperty.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "UnrealProperty.h"
|
||||||
|
|
||||||
|
struct BoolProperty : public UnrealProperty<bool> {
|
||||||
|
using ptr = Containers::Pointer<BoolProperty>;
|
||||||
|
|
||||||
|
BoolProperty() {
|
||||||
|
propertyType = "BoolProperty";
|
||||||
|
}
|
||||||
|
};
|
33
src/UESaveFile/Types/ByteProperty.h
Normal file
33
src/UESaveFile/Types/ByteProperty.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "UnrealProperty.h"
|
||||||
|
|
||||||
|
struct ByteProperty : public UnrealProperty<Containers::Array<char>> {
|
||||||
|
using ptr = Containers::Pointer<ByteProperty>;
|
||||||
|
|
||||||
|
ByteProperty() {
|
||||||
|
propertyType = "ByteProperty";
|
||||||
|
}
|
||||||
|
|
||||||
|
// For some reason, M.A.S.S. Builder stores EnumProperties as ByteProperties. Ugh...
|
||||||
|
std::string enumType;
|
||||||
|
std::string enumValue;
|
||||||
|
};
|
27
src/UESaveFile/Types/ColourStructProperty.h
Normal file
27
src/UESaveFile/Types/ColourStructProperty.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "StructProperty.h"
|
||||||
|
|
||||||
|
struct ColourStructProperty : public StructProperty {
|
||||||
|
using ptr = Containers::Pointer<ColourStructProperty>;
|
||||||
|
ColourStructProperty() {
|
||||||
|
structType = "LinearColor";
|
||||||
|
}
|
||||||
|
Float r = 0.0f, g = 0.0f, b = 0.0f, a = 0.0f;
|
||||||
|
};
|
29
src/UESaveFile/Types/DateTimeStructProperty.h
Normal file
29
src/UESaveFile/Types/DateTimeStructProperty.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "StructProperty.h"
|
||||||
|
|
||||||
|
struct DateTimeStructProperty : public StructProperty {
|
||||||
|
using ptr = Containers::Pointer<DateTimeStructProperty>;
|
||||||
|
|
||||||
|
DateTimeStructProperty() {
|
||||||
|
structType = "DateTime";
|
||||||
|
}
|
||||||
|
|
||||||
|
UnsignedLong timestamp = 0;
|
||||||
|
};
|
29
src/UESaveFile/Types/EnumProperty.h
Normal file
29
src/UESaveFile/Types/EnumProperty.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "UnrealProperty.h"
|
||||||
|
|
||||||
|
struct EnumProperty : public UnrealProperty<std::string> {
|
||||||
|
using ptr = Containers::Pointer<EnumProperty>;
|
||||||
|
|
||||||
|
EnumProperty() {
|
||||||
|
propertyType = "EnumProperty";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string enumType;
|
||||||
|
};
|
27
src/UESaveFile/Types/FloatProperty.h
Normal file
27
src/UESaveFile/Types/FloatProperty.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "UnrealProperty.h"
|
||||||
|
|
||||||
|
struct FloatProperty : public UnrealProperty<Float> {
|
||||||
|
using ptr = Containers::Pointer<FloatProperty>;
|
||||||
|
|
||||||
|
FloatProperty() {
|
||||||
|
propertyType = "FloatProperty";
|
||||||
|
}
|
||||||
|
};
|
51
src/UESaveFile/Types/GenericStructProperty.h
Normal file
51
src/UESaveFile/Types/GenericStructProperty.h
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 <algorithm>
|
||||||
|
|
||||||
|
#include <Corrade/Containers/GrowableArray.h>
|
||||||
|
|
||||||
|
#include "StructProperty.h"
|
||||||
|
|
||||||
|
struct GenericStructProperty : public StructProperty {
|
||||||
|
using ptr = Containers::Pointer<GenericStructProperty>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::enable_if_t<std::is_base_of<UnrealPropertyBase, T>::value, T*>
|
||||||
|
at(const std::string& name) {
|
||||||
|
for(auto& item : properties) {
|
||||||
|
if(item->name == name) {
|
||||||
|
return static_cast<T*>(item.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::enable_if_t<std::is_base_of<UnrealPropertyBase, T>::value, typename T::ptr>
|
||||||
|
atMove(const std::string& name) {
|
||||||
|
for(auto& item : properties) {
|
||||||
|
if(item && item->name == name) {
|
||||||
|
return Containers::Pointer<T>{static_cast<T*>(item.release())};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Containers::Array<UnrealPropertyBase::ptr> properties;
|
||||||
|
};
|
31
src/UESaveFile/Types/GuidStructProperty.h
Normal file
31
src/UESaveFile/Types/GuidStructProperty.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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/StaticArray.h>
|
||||||
|
|
||||||
|
#include "StructProperty.h"
|
||||||
|
|
||||||
|
struct GuidStructProperty : public StructProperty {
|
||||||
|
using ptr = Containers::Pointer<GuidStructProperty>;
|
||||||
|
|
||||||
|
GuidStructProperty() {
|
||||||
|
structType = "Guid";
|
||||||
|
}
|
||||||
|
|
||||||
|
Containers::StaticArray<16, char> guid{ValueInit};
|
||||||
|
};
|
27
src/UESaveFile/Types/IntProperty.h
Normal file
27
src/UESaveFile/Types/IntProperty.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "UnrealProperty.h"
|
||||||
|
|
||||||
|
struct IntProperty : public UnrealProperty<Int> {
|
||||||
|
using ptr = Containers::Pointer<IntProperty>;
|
||||||
|
|
||||||
|
IntProperty() {
|
||||||
|
propertyType = "IntProperty";
|
||||||
|
}
|
||||||
|
};
|
37
src/UESaveFile/Types/MapProperty.h
Normal file
37
src/UESaveFile/Types/MapProperty.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2022 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 "UnrealPropertyBase.h"
|
||||||
|
|
||||||
|
struct MapProperty : public UnrealPropertyBase {
|
||||||
|
using ptr = Containers::Pointer<MapProperty>;
|
||||||
|
|
||||||
|
MapProperty() {
|
||||||
|
propertyType = "MapProperty";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string keyType;
|
||||||
|
std::string valueType;
|
||||||
|
|
||||||
|
struct KeyValuePair {
|
||||||
|
UnrealPropertyBase::ptr key;
|
||||||
|
Containers::Array<UnrealPropertyBase::ptr> values;
|
||||||
|
};
|
||||||
|
|
||||||
|
Containers::Array<KeyValuePair> map;
|
||||||
|
};
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue