Compare commits
No commits in common. "master" and "mass-viewer" have entirely different histories.
master
...
mass-viewe
|
@ -1,4 +1,4 @@
|
|||
*build*/
|
||||
build*/
|
||||
.idea/
|
||||
*.kdev4
|
||||
*~
|
||||
|
|
|
@ -26,7 +26,11 @@
|
|||
path = third-party/efsw
|
||||
url = https://github.com/SpartanJ/efsw
|
||||
branch = master
|
||||
[submodule "libcurl"]
|
||||
path = third-party/curl
|
||||
url = https://github.com/curl/curl
|
||||
[submodule "third-party/cpr"]
|
||||
path = third-party/cpr
|
||||
url = https://github.com/whoshuu/cpr
|
||||
branch = master
|
||||
[submodule "json.hpp"]
|
||||
path = third-party/json
|
||||
url = https://github.com/nlohmann/json
|
||||
branch = master
|
||||
|
|
|
@ -21,20 +21,16 @@ set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/modules/" ${CMAKE_MODULE_PATH})
|
|||
|
||||
SET(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
|
||||
set(CORRADE_BUILD_DEPRECATED OFF CACHE BOOL "" FORCE)
|
||||
set(CORRADE_BUILD_STATIC ON CACHE BOOL "" FORCE)
|
||||
set(CORRADE_BUILD_STATIC_PIC ON CACHE BOOL "" FORCE)
|
||||
set(CORRADE_BUILD_STATIC_UNIQUE_GLOBALS OFF CACHE BOOL "" FORCE)
|
||||
set(CORRADE_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
||||
set(CORRADE_WITH_INTERCONNECT OFF CACHE BOOL "" FORCE)
|
||||
set(CORRADE_WITH_PLUGINMANAGER OFF CACHE BOOL "" FORCE)
|
||||
set(CORRADE_WITH_TESTSUITE OFF CACHE BOOL "" FORCE)
|
||||
set(CORRADE_WITH_MAIN ON CACHE BOOL "" FORCE)
|
||||
set(CORRADE_UTILITY_USE_ANSI_COLORS ON CACHE BOOL "" FORCE)
|
||||
set(BUILD_STATIC ON CACHE BOOL "" FORCE)
|
||||
set(BUILD_STATIC_PIC ON CACHE BOOL "" FORCE)
|
||||
set(BUILD_STATIC_UNIQUE_GLOBALS OFF CACHE BOOL "" FORCE)
|
||||
|
||||
set(WITH_INTERCONNECT ON CACHE BOOL "" FORCE)
|
||||
set(WITH_PLUGINMANAGER ON CACHE BOOL "" FORCE)
|
||||
set(WITH_TESTSUITE OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_MAIN ON CACHE BOOL "" FORCE)
|
||||
add_subdirectory(third-party/corrade EXCLUDE_FROM_ALL)
|
||||
|
||||
set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
|
||||
set(DIRECTX OFF CACHE BOOL "" FORCE) # We use OpenGL.
|
||||
set(SDL_ATOMIC OFF CACHE BOOL "" FORCE)
|
||||
set(SDL_CPUINFO OFF CACHE BOOL "" FORCE)
|
||||
set(SDL_EVENTS ON CACHE BOOL "" FORCE)
|
||||
|
@ -50,34 +46,26 @@ set(SDL_TIMERS ON CACHE BOOL "" FORCE)
|
|||
set(SDL_SHARED OFF CACHE BOOL "" FORCE)
|
||||
add_subdirectory(third-party/SDL EXCLUDE_FROM_ALL)
|
||||
|
||||
set(MAGNUM_BUILD_STATIC ON CACHE BOOL "" FORCE)
|
||||
set(MAGNUM_BUILD_STATIC_PIC ON CACHE BOOL "" FORCE)
|
||||
set(MAGNUM_BUILD_STATIC_UNIQUE_GLOBALS OFF CACHE BOOL "" FORCE)
|
||||
set(MAGNUM_BUILD_DEPRECATED OFF CACHE BOOL "" FORCE)
|
||||
set(MAGNUM_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
||||
|
||||
set(MAGNUM_TARGET_GL ON CACHE BOOL "" FORCE)
|
||||
set(MAGNUM_TARGET_GLES OFF CACHE BOOL "" FORCE)
|
||||
set(MAGNUM_TARGET_VK OFF CACHE BOOL "" FORCE)
|
||||
set(MAGNUM_WITH_AUDIO OFF CACHE BOOL "" FORCE)
|
||||
set(MAGNUM_WITH_DEBUGTOOLS OFF CACHE BOOL "" FORCE)
|
||||
set(MAGNUM_WITH_GL ON CACHE BOOL "" FORCE)
|
||||
set(MAGNUM_WITH_MATERIALTOOLS OFF CACHE BOOL "" FORCE)
|
||||
set(MAGNUM_WITH_MESHTOOLS OFF CACHE BOOL "" FORCE)
|
||||
set(MAGNUM_WITH_PRIMITIVES OFF CACHE BOOL "" FORCE)
|
||||
set(MAGNUM_WITH_SCENEGRAPH OFF CACHE BOOL "" FORCE)
|
||||
set(MAGNUM_WITH_SCENETOOLS OFF CACHE BOOL "" FORCE)
|
||||
set(MAGNUM_WITH_SHADERS ON CACHE BOOL "" FORCE)
|
||||
set(MAGNUM_WITH_SHADERTOOLS OFF CACHE BOOL "" FORCE)
|
||||
set(MAGNUM_WITH_TEXT OFF CACHE BOOL "" FORCE)
|
||||
set(MAGNUM_WITH_TEXTURETOOLS OFF CACHE BOOL "" FORCE)
|
||||
set(MAGNUM_WITH_TRADE OFF CACHE BOOL "" FORCE)
|
||||
set(MAGNUM_WITH_VK OFF CACHE BOOL "" FORCE)
|
||||
set(MAGNUM_WITH_SDL2APPLICATION ON CACHE BOOL "" FORCE)
|
||||
set(TARGET_GL ON CACHE BOOL "" FORCE)
|
||||
set(TARGET_GLES OFF CACHE BOOL "" FORCE)
|
||||
set(TARGET_VK OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_AUDIO OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_DEBUGTOOLS OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_GL ON CACHE BOOL "" FORCE)
|
||||
set(WITH_MESHTOOLS OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_PRIMITIVES OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_SCENEGRAPH OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_SHADERS ON CACHE BOOL "" FORCE)
|
||||
set(WITH_SHADERTOOLS OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_TEXT OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_TEXTURETOOLS OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_TRADE OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_VK OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_SDL2APPLICATION ON CACHE BOOL "" FORCE)
|
||||
add_subdirectory(third-party/magnum EXCLUDE_FROM_ALL)
|
||||
|
||||
set(IMGUI_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third-party/imgui)
|
||||
set(MAGNUM_WITH_IMGUI ON CACHE BOOL "" FORCE)
|
||||
set(WITH_IMGUI ON CACHE BOOL "" FORCE)
|
||||
add_subdirectory(third-party/magnum-integration EXCLUDE_FROM_ALL)
|
||||
|
||||
set(ENABLE_COMMONCRYPTO OFF CACHE BOOL "" FORCE)
|
||||
|
@ -92,6 +80,7 @@ set(BUILD_TOOLS OFF CACHE BOOL "" FORCE)
|
|||
set(BUILD_REGRESS OFF CACHE BOOL "" FORCE)
|
||||
set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
||||
set(BUILD_DOC OFF CACHE BOOL "" FORCE)
|
||||
set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
|
||||
add_subdirectory(third-party/libzip EXCLUDE_FROM_ALL)
|
||||
|
||||
set(VERBOSE OFF CACHE BOOL "" FORCE)
|
||||
|
@ -99,20 +88,11 @@ set(BUILD_TEST_APP OFF CACHE BOOL "" FORCE)
|
|||
set(EFSW_INSTALL OFF CACHE BOOL "" FORCE)
|
||||
add_subdirectory(third-party/efsw EXCLUDE_FROM_ALL)
|
||||
|
||||
set(BUILD_TESTING OFF CACHE BOOL "" FORCE)
|
||||
set(BUILD_CURL_EXE OFF CACHE BOOL "" FORCE)
|
||||
set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
|
||||
set(ENABLE_UNICODE ON CACHE BOOL "" FORCE)
|
||||
set(ENABLE_INET_PTON OFF CACHE BOOL "" FORCE)
|
||||
set(ENABLE_DEBUG OFF CACHE BOOL "" FORCE)
|
||||
set(ENABLE_THREADED_RESOLVER OFF CACHE BOOL "" FORCE)
|
||||
set(HTTP_ONLY ON CACHE BOOL "" FORCE)
|
||||
set(USE_LIBIDN2 OFF CACHE BOOL "" FORCE)
|
||||
set(USE_WIN32_IDN ON CACHE BOOL "" FORCE)
|
||||
set(CURL_USE_LIBPSL OFF CACHE BOOL "" FORCE)
|
||||
set(CURL_STATIC_CRT OFF CACHE BOOL "" FORCE)
|
||||
set(CURL_USE_SCHANNEL ON CACHE BOOL "" FORCE)
|
||||
set(CURL_USE_LIBSSH2 OFF CACHE BOOL "" FORCE) # For some reason, even when HTTP_ONLY is set to ON, libcurl will try to link to libssh2.
|
||||
add_subdirectory(third-party/curl EXCLUDE_FROM_ALL)
|
||||
set(CPR_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
||||
set(CMAKE_USE_LIBSSH2 OFF CACHE BOOL "" FORCE) # For some reason, even when HTTP_ONLY is set to ON, libcurl will try to link to libssh2.
|
||||
add_subdirectory(third-party/cpr EXCLUDE_FROM_ALL)
|
||||
|
||||
set(JSON_BuildTests OFF CACHE BOOL "" FORCE)
|
||||
add_subdirectory(third-party/json)
|
||||
|
||||
add_subdirectory(src)
|
||||
|
|
14
README.md
14
README.md
|
@ -1,20 +1,16 @@
|
|||
# M.A.S.S. Builder Save Tool
|
||||
|
||||
A save file manager and editor for M.A.S.S. Builder. Based on [wxMASSManager](https://git.williamjcm.ovh/williamjcm/wxMASSManager),
|
||||
this is a fork using Magnum and ImGui for the UI.
|
||||
A save file manager and editor for M.A.S.S. Builder. Based on [wxMASSManager](https://williamjcm.ovh/git/williamjcm/wxMASSManager), this is a fork using Magnum and ImGui for the UI.
|
||||
|
||||
## Installing
|
||||
|
||||
Get the `MassBuilderSaveTool-<version>.zip` file from the [the main website](https://williamjcm.ovh/mbst) or on the
|
||||
[Releases](https://git.williamjcm.ovh/williamjcm/MassBuilderSaveTool/releases) page, and extract it somewhere. Then,
|
||||
launch `MassBuilderSaveTool-<version>.exe`.
|
||||
Get the `MassBuilderSaveTool-<version>.zip` file from the [Releases](https://williamjcm.ovh/git/williamjcm/MassBuilderSaveTool/releases) page, and extract it somewhere. Then, launch `MassBuilderSaveTool.exe`.
|
||||
|
||||
## Building on MSYS2 - IGNORE IF YOU JUST WANT TO USE THE APP!
|
||||
|
||||
1. Install the 64-bit (`x86_64`) version of [MSYS2](https://www.msys2.org/) in its default path (`C:\msys64`), and
|
||||
update it fully.
|
||||
2. Run `pacman -S git mingw-w64-ucrt-x86_64-toolchain mingw-w64-ucrt-x86_64-cmake mingw-w64-ucrt-x86_64-ninja`.
|
||||
3. In a `URCT64` shell, type `git clone https://github.com/williamjcm/MassBuilderSaveTool`.
|
||||
1. Install the 64-bit (`x86_64`) version of [MSYS2](https://www.msys2.org/) in its default path (`C:\msys64`), and update it fully.
|
||||
2. Run `pacman -S git mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja`.
|
||||
3. In a `MINGW64` shell, type `git clone https://github.com/williamjcm/MassBuilderSaveTool`.
|
||||
4. Type `cd MassBuilderSaveTool && git submodule init && git submodule update && mkdir build && cd build`.
|
||||
5. Type `cmake -GNinja -DCMAKE_BUILD_TYPE=Release ..`
|
||||
6. Type `ninja`
|
||||
|
|
|
@ -62,8 +62,8 @@
|
|||
#
|
||||
# Features of found Corrade library are exposed in these variables:
|
||||
#
|
||||
# CORRADE_MSVC_COMPATIBILITY - Defined if compiled with compatibility
|
||||
# mode for MSVC 2019+ without the /permissive- flag set
|
||||
# CORRADE_MSVC2019_COMPATIBILITY - Defined if compiled with compatibility
|
||||
# mode for MSVC 2019
|
||||
# CORRADE_MSVC2017_COMPATIBILITY - Defined if compiled with compatibility
|
||||
# mode for MSVC 2017
|
||||
# CORRADE_MSVC2015_COMPATIBILITY - Defined if compiled with compatibility
|
||||
|
@ -100,7 +100,7 @@
|
|||
# CORRADE_TARGET_MINGW - Defined if compiling under MinGW
|
||||
# CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT - Defined if PluginManager
|
||||
# doesn't support dynamic plugin loading due to platform limitations
|
||||
# CORRADE_TESTSUITE_TARGET_XCTEST - Defined if TestSuite is targeting Xcode
|
||||
# CORRADE_TESTSUITE_TARGET_XCTEST - Defined if TestSuite is targetting Xcode
|
||||
# XCTest
|
||||
# CORRADE_UTILITY_USE_ANSI_COLORS - Defined if ANSI escape sequences are used
|
||||
# for colored output with Utility::Debug on Windows
|
||||
|
@ -264,7 +264,7 @@
|
|||
# This file is part of Corrade.
|
||||
#
|
||||
# Copyright © 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016,
|
||||
# 2017, 2018, 2019, 2020, 2021, 2022
|
||||
# 2017, 2018, 2019, 2020, 2021
|
||||
# Vladimír Vondruš <mosra@centrum.cz>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||
|
@ -312,7 +312,7 @@ string(REGEX REPLACE "\n" ";" _corradeConfigure "${_corradeConfigure}")
|
|||
set(_corradeFlags
|
||||
MSVC2015_COMPATIBILITY
|
||||
MSVC2017_COMPATIBILITY
|
||||
MSVC_COMPATIBILITY
|
||||
MSVC2019_COMPATIBILITY
|
||||
BUILD_DEPRECATED
|
||||
BUILD_STATIC
|
||||
BUILD_STATIC_UNIQUE_GLOBALS
|
||||
|
@ -529,7 +529,7 @@ foreach(_component ${Corrade_FIND_COMPONENTS})
|
|||
set_property(TARGET Corrade::${_component} APPEND PROPERTY
|
||||
COMPATIBLE_INTERFACE_NUMBER_MAX CORRADE_CXX_STANDARD)
|
||||
|
||||
# Path::libraryLocation() needs this
|
||||
# Directory::libraryLocation() needs this
|
||||
if(CORRADE_TARGET_UNIX)
|
||||
set_property(TARGET Corrade::${_component} APPEND PROPERTY
|
||||
INTERFACE_LINK_LIBRARIES ${CMAKE_DL_LIBS})
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
# This file is part of Magnum.
|
||||
#
|
||||
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
|
||||
# 2020, 2021, 2022 Vladimír Vondruš <mosra@centrum.cz>
|
||||
# 2020, 2021 Vladimír Vondruš <mosra@centrum.cz>
|
||||
# Copyright © 2018 Jonathan Hale <squareys@googlemail.com>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||
|
@ -59,18 +59,11 @@
|
|||
#
|
||||
|
||||
# In 1.71 ImGui depends on the ApplicationServices framework for macOS
|
||||
# clipboard support. Since 1.72 the dependency is optional and used only if
|
||||
# IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS is enabled, but link to it
|
||||
# always to be nice to users.
|
||||
# clipboard support. It's removed again in 1.72. TODO: remove once obsolete
|
||||
if(CORRADE_TARGET_APPLE)
|
||||
find_library(_IMGUI_ApplicationServices_LIBRARY ApplicationServices)
|
||||
mark_as_advanced(_IMGUI_ApplicationServices_LIBRARY)
|
||||
set(_IMGUI_EXTRA_LIBRARIES ${_IMGUI_ApplicationServices_LIBRARY})
|
||||
|
||||
# Since 1.82, ImGui on MinGW needs the imm32 library. For MSVC the library
|
||||
# seems to be linked implicitly so this is not needed.
|
||||
elseif(CORRADE_TARGET_WINDOWS AND CORRADE_TARGET_MINGW)
|
||||
set(_IMGUI_EXTRA_LIBRARIES imm32)
|
||||
endif()
|
||||
|
||||
# Vcpkg distributes imgui as a library with a config file, so try that first --
|
||||
|
@ -82,6 +75,7 @@ endif()
|
|||
if(NOT IMGUI_DIR AND TARGET imgui::imgui)
|
||||
if(NOT TARGET ImGui::ImGui)
|
||||
add_library(ImGui::ImGui INTERFACE IMPORTED)
|
||||
# TODO: remove once 1.71 is obsolete
|
||||
set_property(TARGET ImGui::ImGui APPEND PROPERTY
|
||||
INTERFACE_LINK_LIBRARIES imgui::imgui ${_IMGUI_EXTRA_LIBRARIES})
|
||||
|
||||
|
@ -110,6 +104,7 @@ else()
|
|||
add_library(ImGui::ImGui INTERFACE IMPORTED)
|
||||
set_property(TARGET ImGui::ImGui APPEND PROPERTY
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${ImGui_INCLUDE_DIR})
|
||||
# TODO: remove once 1.71 is obsolete
|
||||
if(_IMGUI_EXTRA_LIBRARIES)
|
||||
set_property(TARGET ImGui::ImGui APPEND PROPERTY
|
||||
INTERFACE_LINK_LIBRARIES ${_IMGUI_EXTRA_LIBRARIES})
|
||||
|
|
|
@ -60,7 +60,6 @@
|
|||
# MeshTools - MeshTools library
|
||||
# Primitives - Primitives library
|
||||
# SceneGraph - SceneGraph library
|
||||
# SceneTools - SceneTools library
|
||||
# Shaders - Shaders library
|
||||
# ShaderTools - ShaderTools library
|
||||
# Text - Text library
|
||||
|
@ -202,7 +201,7 @@
|
|||
# This file is part of Magnum.
|
||||
#
|
||||
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
|
||||
# 2020, 2021, 2022 Vladimír Vondruš <mosra@centrum.cz>
|
||||
# 2020, 2021 Vladimír Vondruš <mosra@centrum.cz>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||
# copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -230,7 +229,7 @@ foreach(_component ${Magnum_FIND_COMPONENTS})
|
|||
|
||||
# Unrolling the transitive dependencies here so this doesn't need to be
|
||||
# after resolving inter-component dependencies. Listing also all plugins.
|
||||
if(_component MATCHES "^(Audio|DebugTools|MeshTools|Primitives|SceneTools|ShaderTools|Text|TextureTools|Trade|.+Importer|.+ImageConverter|.+Font|.+ShaderConverter)$")
|
||||
if(_component MATCHES "^(Audio|DebugTools|MeshTools|Primitives|ShaderTools|Text|TextureTools|Trade|.+Importer|.+ImageConverter|.+Font|.+ShaderConverter)$")
|
||||
set(_MAGNUM_${_COMPONENT}_CORRADE_DEPENDENCIES PluginManager)
|
||||
endif()
|
||||
|
||||
|
@ -355,8 +354,8 @@ endif()
|
|||
# Component distinction (listing them explicitly to avoid mistakes with finding
|
||||
# components from other repositories)
|
||||
set(_MAGNUM_LIBRARY_COMPONENTS
|
||||
Audio DebugTools GL MeshTools Primitives SceneGraph SceneTools Shaders
|
||||
ShaderTools Text TextureTools Trade
|
||||
Audio DebugTools GL MeshTools Primitives SceneGraph Shaders ShaderTools
|
||||
Text TextureTools Trade
|
||||
WindowlessEglApplication EglContext OpenGLTester)
|
||||
set(_MAGNUM_PLUGIN_COMPONENTS
|
||||
AnyAudioImporter AnyImageConverter AnyImageImporter AnySceneConverter
|
||||
|
@ -388,7 +387,8 @@ if(CORRADE_TARGET_EMSCRIPTEN)
|
|||
endif()
|
||||
if(CORRADE_TARGET_IOS)
|
||||
list(APPEND _MAGNUM_LIBRARY_COMPONENTS WindowlessIosApplication)
|
||||
elseif(CORRADE_TARGET_APPLE AND NOT MAGNUM_TARGET_GLES)
|
||||
endif()
|
||||
if(CORRADE_TARGET_APPLE AND NOT CORRADE_TARGET_IOS)
|
||||
list(APPEND _MAGNUM_LIBRARY_COMPONENTS WindowlessCglApplication CglContext)
|
||||
endif()
|
||||
if(CORRADE_TARGET_UNIX AND NOT CORRADE_TARGET_APPLE)
|
||||
|
@ -430,7 +430,7 @@ if(MAGNUM_TARGET_HEADLESS OR CORRADE_TARGET_EMSCRIPTEN OR CORRADE_TARGET_ANDROID
|
|||
list(APPEND _MAGNUM_OpenGLTester_DEPENDENCIES WindowlessEglApplication)
|
||||
elseif(CORRADE_TARGET_IOS)
|
||||
list(APPEND _MAGNUM_OpenGLTester_DEPENDENCIES WindowlessIosApplication)
|
||||
elseif(CORRADE_TARGET_APPLE AND NOT MAGNUM_TARGET_GLES)
|
||||
elseif(CORRADE_TARGET_APPLE)
|
||||
list(APPEND _MAGNUM_OpenGLTester_DEPENDENCIES WindowlessCglApplication)
|
||||
elseif(CORRADE_TARGET_UNIX)
|
||||
if(MAGNUM_TARGET_GLES AND NOT MAGNUM_TARGET_DESKTOP_GLES)
|
||||
|
@ -451,11 +451,8 @@ if(MAGNUM_TARGET_GL)
|
|||
# GL not required by Primitives themselves, but transitively by MeshTools
|
||||
list(APPEND _MAGNUM_Primitives_DEPENDENCIES GL)
|
||||
endif()
|
||||
|
||||
set(_MAGNUM_SceneGraph_DEPENDENCIES )
|
||||
set(_MAGNUM_SceneTools_DEPENDENCIES Trade)
|
||||
set(_MAGNUM_Shaders_DEPENDENCIES GL)
|
||||
|
||||
set(_MAGNUM_Text_DEPENDENCIES TextureTools)
|
||||
if(MAGNUM_TARGET_GL)
|
||||
list(APPEND _MAGNUM_Text_DEPENDENCIES GL)
|
||||
|
@ -469,7 +466,6 @@ endif()
|
|||
set(_MAGNUM_Trade_DEPENDENCIES )
|
||||
set(_MAGNUM_VulkanTester_DEPENDENCIES Vk)
|
||||
set(_MAGNUM_AndroidApplication_DEPENDENCIES GL)
|
||||
|
||||
set(_MAGNUM_EmscriptenApplication_DEPENDENCIES)
|
||||
if(MAGNUM_TARGET_GL)
|
||||
list(APPEND _MAGNUM_EmscriptenApplication_DEPENDENCIES GL)
|
||||
|
@ -612,7 +608,7 @@ foreach(_component ${Magnum_FIND_COMPONENTS})
|
|||
|
||||
# Dynamic plugins don't have any prefix (e.g. `lib` on Linux),
|
||||
# search with empty prefix and then reset that back so we don't
|
||||
# accidentally break something else
|
||||
# accidentaly break something else
|
||||
set(_tmp_prefixes "${CMAKE_FIND_LIBRARY_PREFIXES}")
|
||||
set(CMAKE_FIND_LIBRARY_PREFIXES "${CMAKE_FIND_LIBRARY_PREFIXES};")
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
# This file is part of Magnum.
|
||||
#
|
||||
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
|
||||
# 2020, 2021, 2022 Vladimír Vondruš <mosra@centrum.cz>
|
||||
# 2020, 2021 Vladimír Vondruš <mosra@centrum.cz>
|
||||
# Copyright © 2018 Konstantinos Chatzilygeroudis <costashatz@gmail.com>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
# This file is part of Magnum.
|
||||
#
|
||||
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
|
||||
# 2020, 2021, 2022 Vladimír Vondruš <mosra@centrum.cz>
|
||||
# 2020, 2021 Vladimír Vondruš <mosra@centrum.cz>
|
||||
# Copyright © 2018 Jonathan Hale <squareys@googlemail.com>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||
|
@ -168,38 +168,37 @@ find_path(SDL2_INCLUDE_DIR
|
|||
if(CORRADE_TARGET_WINDOWS)
|
||||
find_file(SDL2_DLL_RELEASE
|
||||
NAMES SDL2.dll
|
||||
PATH_SUFFIXES bin ${_SDL2_RUNTIME_PATH_SUFFIX} ${_SDL2_LIBRARY_PATH_SUFFIX})
|
||||
PATH_SUFFIXES ${_SDL2_RUNTIME_PATH_SUFFIX} ${_SDL2_LIBRARY_PATH_SUFFIX})
|
||||
find_file(SDL2_DLL_DEBUG
|
||||
NAMES SDL2d.dll # not sure?
|
||||
PATH_SUFFIXES bin ${_SDL2_RUNTIME_PATH_SUFFIX} ${_SDL2_LIBRARY_PATH_SUFFIX})
|
||||
PATH_SUFFIXES ${_SDL2_RUNTIME_PATH_SUFFIX} ${_SDL2_LIBRARY_PATH_SUFFIX})
|
||||
endif()
|
||||
|
||||
# (Static) macOS / iOS dependencies. On macOS these were mainly needed when
|
||||
# building SDL statically using its CMake project, on iOS always.
|
||||
if(CORRADE_TARGET_APPLE AND (SDL2_LIBRARY_DEBUG MATCHES "${CMAKE_STATIC_LIBRARY_SUFFIX}$" OR SDL2_LIBRARY_RELEASE MATCHES "${CMAKE_STATIC_LIBRARY_SUFFIX}$"))
|
||||
set(_SDL2_FRAMEWORKS
|
||||
iconv # should be in the system, needed by iOS as well now
|
||||
AudioToolbox
|
||||
AVFoundation
|
||||
CoreHaptics # needed since 2.0.18(?) on iOS and macOS
|
||||
Foundation
|
||||
Metal # needed since 2.0.8 on iOS, since 2.0.14 on macOS
|
||||
GameController) # needed since 2.0.18(?) on macOS as well
|
||||
# (Static) macOS / iOS dependencies
|
||||
if(CORRADE_TARGET_APPLE AND SDL2_LIBRARY MATCHES "${CMAKE_STATIC_LIBRARY_SUFFIX}$")
|
||||
if(CORRADE_TARGET_IOS)
|
||||
list(APPEND _SDL2_FRAMEWORKS
|
||||
CoreBluetooth # needed since 2.0.10
|
||||
set(_SDL2_FRAMEWORKS
|
||||
AudioToolbox
|
||||
AVFoundation
|
||||
CoreGraphics
|
||||
CoreMotion
|
||||
Foundation
|
||||
GameController
|
||||
Metal # needed since 2.0.8
|
||||
QuartzCore
|
||||
UIKit)
|
||||
else()
|
||||
list(APPEND _SDL2_FRAMEWORKS
|
||||
# Those are needed when building SDL statically using its CMake project
|
||||
set(_SDL2_FRAMEWORKS
|
||||
iconv # should be in the system
|
||||
AudioToolbox
|
||||
AVFoundation
|
||||
Carbon
|
||||
Cocoa
|
||||
CoreAudio
|
||||
CoreVideo
|
||||
ForceFeedback
|
||||
Foundation
|
||||
IOKit)
|
||||
endif()
|
||||
set(_SDL2_FRAMEWORK_LIBRARIES )
|
||||
|
@ -248,7 +247,7 @@ if(NOT TARGET SDL2::SDL2)
|
|||
endif()
|
||||
|
||||
# Link frameworks on macOS / iOS if we have a static SDL
|
||||
if(CORRADE_TARGET_APPLE AND (SDL2_LIBRARY_DEBUG MATCHES "${CMAKE_STATIC_LIBRARY_SUFFIX}$" OR SDL2_LIBRARY_RELEASE MATCHES "${CMAKE_STATIC_LIBRARY_SUFFIX}$"))
|
||||
if(CORRADE_TARGET_APPLE AND SDL2_LIBRARY MATCHES ".*libSDL2.a$")
|
||||
set_property(TARGET SDL2::SDL2 APPEND PROPERTY
|
||||
INTERFACE_LINK_LIBRARIES ${_SDL2_FRAMEWORK_LIBRARIES})
|
||||
endif()
|
||||
|
|
|
@ -11,16 +11,4 @@
|
|||
/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
<asmv3:application>
|
||||
<asmv3:windowsSettings>
|
||||
<activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">
|
||||
UTF-8
|
||||
</activeCodePage>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
|
||||
true/pm</dpiAware> <!-- legacy -->
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
|
||||
permonitorv2,permonitor
|
||||
</dpiAwareness> <!-- falls back to pm if pmv2 is not available -->
|
||||
</asmv3:windowsSettings>
|
||||
</asmv3:application>
|
||||
</assembly>
|
||||
</assembly>
|
|
@ -18,9 +18,9 @@ set(CMAKE_CXX_STANDARD 14)
|
|||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
set(SAVETOOL_PROJECT_VERSION 1.4.3)
|
||||
set(SAVETOOL_PROJECT_VERSION 1.3.0-pre)
|
||||
|
||||
find_package(Corrade REQUIRED Main Containers Utility)
|
||||
find_package(Corrade REQUIRED Main Containers Utility Interconnect)
|
||||
find_package(Magnum REQUIRED GL Sdl2Application)
|
||||
find_package(MagnumIntegration REQUIRED ImGui)
|
||||
|
||||
|
@ -28,101 +28,85 @@ set_directory_properties(PROPERTIES CORRADE_USE_PEDANTIC_FLAGS ON)
|
|||
|
||||
corrade_add_resource(Assets assets.conf)
|
||||
|
||||
add_library(Logger STATIC EXCLUDE_FROM_ALL
|
||||
Logger/Logger.h
|
||||
Logger/Logger.cpp
|
||||
Logger/EntryType.h
|
||||
Logger/MagnumLogBuffer.h
|
||||
Logger/MagnumLogBuffer.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(Logger PRIVATE
|
||||
Corrade::Utility
|
||||
Magnum::Magnum
|
||||
)
|
||||
|
||||
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/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/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
|
||||
)
|
||||
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
|
||||
Logger
|
||||
)
|
||||
Corrade::Containers
|
||||
Corrade::Utility
|
||||
Magnum::Magnum)
|
||||
|
||||
add_executable(MassBuilderSaveTool WIN32
|
||||
main.cpp
|
||||
|
@ -130,51 +114,37 @@ add_executable(MassBuilderSaveTool WIN32
|
|||
SaveTool/SaveTool.cpp
|
||||
SaveTool/SaveTool_drawAbout.cpp
|
||||
SaveTool/SaveTool_drawMainMenu.cpp
|
||||
SaveTool/SaveTool_FileWatcher.cpp
|
||||
SaveTool/SaveTool_Initialisation.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_UpdateChecker.cpp
|
||||
ProfileManager/ProfileManager.h
|
||||
ProfileManager/ProfileManager.cpp
|
||||
Profile/Profile.h
|
||||
Profile/Profile.cpp
|
||||
Profile/PropertyNames.h
|
||||
Profile/ResourceIDs.h
|
||||
MassManager/MassManager.h
|
||||
MassManager/MassManager.cpp
|
||||
Mass/Accessory.h
|
||||
Mass/ArmourPart.h
|
||||
Mass/BulletLauncherAttachment.h
|
||||
Mass/CustomStyle.h
|
||||
Mass/Decal.h
|
||||
Mass/Joints.h
|
||||
Mass/Mass.h
|
||||
Mass/Mass.cpp
|
||||
Mass/Mass_Frame.cpp
|
||||
Mass/Mass_Armour.cpp
|
||||
Mass/Mass_Weapons.cpp
|
||||
Mass/Mass_Styles.cpp
|
||||
Mass/Mass_DecalsAccessories.cpp
|
||||
Mass/PropertyNames.h
|
||||
Mass/Weapon.h
|
||||
Mass/Weapon.cpp
|
||||
Mass/WeaponPart.h
|
||||
Maps/Accessories.h
|
||||
Maps/ArmourSets.h
|
||||
Maps/ArmourSlots.hpp
|
||||
Maps/BulletLauncherAttachmentStyles.hpp
|
||||
Maps/BulletLauncherSockets.hpp
|
||||
Maps/DamageTypes.hpp
|
||||
Maps/EffectColourModes.hpp
|
||||
Maps/LastMissionId.h
|
||||
Maps/StoryProgress.h
|
||||
Maps/StyleNames.h
|
||||
Maps/WeaponParts.h
|
||||
Maps/WeaponTypes.hpp
|
||||
ToastQueue/ToastQueue.h
|
||||
ToastQueue/ToastQueue.cpp
|
||||
|
@ -182,17 +152,14 @@ add_executable(MassBuilderSaveTool WIN32
|
|||
FontAwesome/IconsFontAwesome5.h
|
||||
FontAwesome/IconsFontAwesome5Brands.h
|
||||
resource.rc
|
||||
${Assets}
|
||||
)
|
||||
${Assets})
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL Debug)
|
||||
add_compile_definitions(SAVETOOL_DEBUG_BUILD)
|
||||
endif()
|
||||
add_compile_definitions(
|
||||
SAVETOOL_VERSION="${SAVETOOL_PROJECT_VERSION}"
|
||||
SAVETOOL_CODENAME="Enigmatic Ellenier"
|
||||
SUPPORTED_GAME_VERSION="0.9.x"
|
||||
)
|
||||
add_compile_definitions(SAVETOOL_VERSION="${SAVETOOL_PROJECT_VERSION}"
|
||||
SAVETOOL_CODENAME="Dickish Cyclops"
|
||||
SUPPORTED_GAME_VERSION="0.7.6")
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL Release)
|
||||
set_target_properties(MassBuilderSaveTool PROPERTIES OUTPUT_NAME MassBuilderSaveTool-${SAVETOOL_PROJECT_VERSION})
|
||||
|
@ -207,16 +174,16 @@ endif()
|
|||
target_link_libraries(MassBuilderSaveTool PRIVATE
|
||||
Corrade::Containers
|
||||
Corrade::Utility
|
||||
Corrade::Interconnect
|
||||
Corrade::Main
|
||||
Magnum::Magnum
|
||||
Magnum::GL
|
||||
Magnum::Sdl2Application
|
||||
MagnumIntegration::ImGui
|
||||
Logger
|
||||
UESaveFile
|
||||
efsw
|
||||
zip
|
||||
libcurl
|
||||
cpr::cpr
|
||||
nlohmann_json::nlohmann_json
|
||||
imm32
|
||||
wtsapi32
|
||||
)
|
||||
wtsapi32)
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
#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/>.
|
||||
|
||||
enum class EntryType {
|
||||
Info,
|
||||
Warning,
|
||||
Error,
|
||||
};
|
|
@ -1,112 +0,0 @@
|
|||
// 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 <iostream>
|
||||
|
||||
#include <Corrade/Utility/Debug.h>
|
||||
|
||||
#include "Logger.h"
|
||||
|
||||
using Containers::Array;
|
||||
using Utility::Debug;
|
||||
using Utility::Warning;
|
||||
using Utility::Error;
|
||||
|
||||
using namespace Magnum;
|
||||
|
||||
Logger&
|
||||
Logger::instance() {
|
||||
static Logger logger;
|
||||
return logger;
|
||||
}
|
||||
|
||||
void
|
||||
Logger::initialise() {
|
||||
#ifndef SAVETOOL_DEBUG_BUILD
|
||||
_logFile.open("SaveToolLog.txt", std::ios::trunc);
|
||||
_logFile << "In case you encounter a bug:\n" <<
|
||||
"1. Do not run the Save Tool again, as this log will be cleared.\n" <<
|
||||
"2. Go to either the official Sekai Project Discord guild, or the community M.A.S.S. Builder one.\n" <<
|
||||
"3. Mention me (William JCM#2301) to get my attention, with a description of the bug.\n"
|
||||
" Please include as many details as possible, I don't want to play \"20 questions\", and neither do you.\n" <<
|
||||
"4. Send me this file _when I ask for it_, preferably in DMs.\n" <<
|
||||
std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
Logger::indent() {
|
||||
_indentLevel++;
|
||||
}
|
||||
|
||||
void
|
||||
Logger::unindent() {
|
||||
if(_indentLevel > 0) {
|
||||
_indentLevel--;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Logger::log(EntryType type, StringView location, StringView message) {
|
||||
Debug d{
|
||||
#ifndef SAVETOOL_DEBUG_BUILD
|
||||
&_logFile
|
||||
#else
|
||||
&std::cout
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef SAVETOOL_DEBUG_BUILD
|
||||
#define COLOURED_TEXT(colour, text) Debug::color(Debug::Color::colour) << (text) << Debug::resetColor
|
||||
#else
|
||||
#define COLOURED_TEXT(colour, text) (text)
|
||||
#endif
|
||||
switch(type) {
|
||||
case EntryType::Info:
|
||||
d << COLOURED_TEXT(Default, "[ INFO]"_s);
|
||||
break;
|
||||
case EntryType::Warning:
|
||||
d << COLOURED_TEXT(Yellow, "[WARNING]"_s);
|
||||
break;
|
||||
case EntryType::Error:
|
||||
d << COLOURED_TEXT(Red, "[ ERROR]"_s);
|
||||
break;
|
||||
}
|
||||
#undef COLOURED_TEXT
|
||||
|
||||
d << "["_s << Debug::nospace << location << Debug::nospace << "]";
|
||||
|
||||
for(UnsignedInt i = 0; i < _indentLevel; i++) {
|
||||
d << Debug::nospace << " "_s << Debug::nospace;
|
||||
}
|
||||
|
||||
d << ((message.back() == '\n') ? message.exceptSuffix(1) : message);
|
||||
}
|
||||
|
||||
void
|
||||
Logger::lockMutex() {
|
||||
_logMutex.lock();
|
||||
}
|
||||
|
||||
void
|
||||
Logger::unlockMutex() {
|
||||
_logMutex.unlock();
|
||||
}
|
||||
|
||||
Logger&
|
||||
logger() {
|
||||
return Logger::instance();
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
#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 <ctime>
|
||||
|
||||
#include <mutex>
|
||||
#ifndef SAVETOOL_DEBUG_BUILD
|
||||
#include <fstream>
|
||||
#endif
|
||||
|
||||
#include <Corrade/Containers/String.h>
|
||||
#include <Corrade/Containers/ArrayView.h>
|
||||
#include <Corrade/Utility/Format.h>
|
||||
|
||||
#include <Magnum/Types.h>
|
||||
|
||||
#include "EntryType.h"
|
||||
|
||||
using namespace Corrade;
|
||||
|
||||
using Containers::ArrayView;
|
||||
using Containers::String;
|
||||
using Containers::StringView;
|
||||
|
||||
using namespace Magnum;
|
||||
|
||||
using namespace Containers::Literals;
|
||||
|
||||
class Logger {
|
||||
public:
|
||||
Logger(const Logger&) = delete;
|
||||
Logger& operator=(const Logger&) = delete;
|
||||
|
||||
Logger(Logger&&) = delete;
|
||||
Logger& operator=(Logger&&) = delete;
|
||||
|
||||
static auto instance() -> Logger&;
|
||||
|
||||
void initialise();
|
||||
|
||||
void indent();
|
||||
void unindent();
|
||||
|
||||
void log(EntryType type, StringView location, StringView message);
|
||||
|
||||
void lockMutex();
|
||||
void unlockMutex();
|
||||
|
||||
private:
|
||||
Logger() = default;
|
||||
|
||||
#ifndef SAVETOOL_DEBUG_BUILD
|
||||
std::ofstream _logFile;
|
||||
#endif
|
||||
|
||||
UnsignedInt _indentLevel = 0;
|
||||
|
||||
std::mutex _logMutex{};
|
||||
};
|
||||
|
||||
auto logger() -> Logger&;
|
||||
|
||||
#define LOG(entry_type, message) logger().lockMutex(); \
|
||||
logger().log(EntryType::entry_type, \
|
||||
Utility::format("{}:{}", StringView{__builtin_FILE()}.find("src"_s).data() + 4, __builtin_LINE()), \
|
||||
message); \
|
||||
logger().unlockMutex()
|
||||
|
||||
#define LOG_INFO(message) LOG(Info, message)
|
||||
#define LOG_WARNING(message) LOG(Warning, message)
|
||||
#define LOG_ERROR(message) LOG(Error, message)
|
||||
|
||||
#define LOG_INFO_FORMAT(message, ...) LOG_INFO(Utility::format(message, __VA_ARGS__))
|
||||
#define LOG_WARNING_FORMAT(message, ...) LOG_WARNING(Utility::format(message, __VA_ARGS__))
|
||||
#define LOG_ERROR_FORMAT(message, ...) LOG_ERROR(Utility::format(message, __VA_ARGS__))
|
|
@ -1,30 +0,0 @@
|
|||
// 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 "MagnumLogBuffer.h"
|
||||
|
||||
MagnumLogBuffer::MagnumLogBuffer(EntryType type): std::stringbuf(std::ios_base::out), _type{type} {}
|
||||
|
||||
MagnumLogBuffer::~MagnumLogBuffer() = default;
|
||||
|
||||
int
|
||||
MagnumLogBuffer::sync() {
|
||||
logger().lockMutex();
|
||||
logger().log(_type, "Corrade/Magnum"_s, str().c_str());
|
||||
logger().unlockMutex();
|
||||
str({});
|
||||
return 0;
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
#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 <sstream>
|
||||
|
||||
#include "Logger.h"
|
||||
|
||||
#include "EntryType.h"
|
||||
|
||||
class MagnumLogBuffer : public std::stringbuf {
|
||||
public:
|
||||
explicit MagnumLogBuffer(EntryType type);
|
||||
~MagnumLogBuffer();
|
||||
|
||||
private:
|
||||
int sync() override;
|
||||
|
||||
EntryType _type;
|
||||
};
|
|
@ -18,667 +18,57 @@
|
|||
|
||||
#include <map>
|
||||
|
||||
#include <Corrade/Containers/StringView.h>
|
||||
|
||||
#include <Magnum/Types.h>
|
||||
|
||||
using namespace Corrade;
|
||||
using namespace Containers::Literals;
|
||||
using namespace Magnum;
|
||||
|
||||
enum AccessorySize {
|
||||
S,
|
||||
M,
|
||||
L,
|
||||
XL
|
||||
};
|
||||
|
||||
struct AccessoryData{
|
||||
Containers::StringView name;
|
||||
AccessorySize size = AccessorySize::S;
|
||||
};
|
||||
|
||||
static const std::map<Int, AccessoryData> accessories {
|
||||
// region Primitives
|
||||
{1, {"Cube"_s, AccessorySize::S}},
|
||||
{2, {"Pentagon"_s, AccessorySize::S}},
|
||||
{3, {"Hexagon"_s, AccessorySize::S}},
|
||||
{4, {"Cylinder"_s, AccessorySize::S}},
|
||||
{5, {"Sphere"_s, AccessorySize::S}},
|
||||
{6, {"TriPyramid"_s, AccessorySize::S}},
|
||||
{7, {"SquPyramid"_s, AccessorySize::S}},
|
||||
{8, {"PenPyramid"_s, AccessorySize::S}},
|
||||
{9, {"HexPyramid"_s, AccessorySize::S}},
|
||||
{10, {"Cone"_s, AccessorySize::S}},
|
||||
{11, {"SquStick"_s, AccessorySize::S}},
|
||||
{12, {"PenStick"_s, AccessorySize::S}},
|
||||
{13, {"HexStick"_s, AccessorySize::S}},
|
||||
{14, {"CycStick"_s, AccessorySize::S}},
|
||||
{15, {"Capsule"_s, AccessorySize::S}},
|
||||
{16, {"Decal Pad 01"_s, AccessorySize::S}},
|
||||
{17, {"Decal Pad 02"_s, AccessorySize::S}},
|
||||
{18, {"Decal Pad 03"_s, AccessorySize::S}},
|
||||
{19, {"Decal Pad 04"_s, AccessorySize::S}},
|
||||
{20, {"Decal Pad 05"_s, AccessorySize::S}},
|
||||
{21, {"Triangle"_s, AccessorySize::S}},
|
||||
{22, {"ThinStar"_s, AccessorySize::S}},
|
||||
{23, {"Star"_s, AccessorySize::S}},
|
||||
{24, {"SixSideStar"_s, AccessorySize::S}},
|
||||
{25, {"Asterisk"_s, AccessorySize::S}},
|
||||
{26, {"Ring"_s, AccessorySize::S}},
|
||||
{27, {"SawedRing"_s, AccessorySize::S}},
|
||||
{28, {"HalfRing"_s, AccessorySize::S}},
|
||||
{29, {"Cresent"_s, AccessorySize::S}},
|
||||
{30, {"Donut"_s, AccessorySize::S}},
|
||||
{31, {"FiveCogWheel"_s, AccessorySize::S}},
|
||||
{32, {"SixCogWheel"_s, AccessorySize::S}},
|
||||
{33, {"SevenCogWheel"_s, AccessorySize::S}},
|
||||
{34, {"EightCogWheel"_s, AccessorySize::S}},
|
||||
{35, {"TwelveCogWheel"_s, AccessorySize::S}},
|
||||
|
||||
{51, {"SquBevel"_s, AccessorySize::S}},
|
||||
{52, {"TriBevel"_s, AccessorySize::S}},
|
||||
{53, {"PenBevel"_s, AccessorySize::S}},
|
||||
{54, {"HexBevel"_s, AccessorySize::S}},
|
||||
{55, {"CycBevel"_s, AccessorySize::S}},
|
||||
{56, {"RecBevel"_s, AccessorySize::S}},
|
||||
{57, {"DaiBevel"_s, AccessorySize::S}},
|
||||
{58, {"MonBevel"_s, AccessorySize::S}},
|
||||
{59, {"CofBevel"_s, AccessorySize::S}},
|
||||
{60, {"JevBevel"_s, AccessorySize::S}},
|
||||
{61, {"SquEmboss"_s, AccessorySize::S}},
|
||||
{62, {"TriEmboss"_s, AccessorySize::S}},
|
||||
{63, {"PenEmboss"_s, AccessorySize::S}},
|
||||
{64, {"HexEmboss"_s, AccessorySize::S}},
|
||||
{65, {"CycEmboss"_s, AccessorySize::S}},
|
||||
{66, {"RecEmboss"_s, AccessorySize::S}},
|
||||
{67, {"DaiEmboss"_s, AccessorySize::S}},
|
||||
{68, {"MonEmboss"_s, AccessorySize::S}},
|
||||
{69, {"CofEmboss"_s, AccessorySize::S}},
|
||||
{70, {"JevEmboss"_s, AccessorySize::S}},
|
||||
|
||||
{101, {"Flat Hex Pin"_s, AccessorySize::S}},
|
||||
{102, {"Cross Circle Pin"_s, AccessorySize::S}},
|
||||
{103, {"Flat Circle Pin"_s, AccessorySize::S}},
|
||||
{104, {"Hex Circle Pin"_s, AccessorySize::S}},
|
||||
{105, {"Circle Button Pin"_s, AccessorySize::S}},
|
||||
{106, {"Hexagon Pin"_s, AccessorySize::S}},
|
||||
{107, {"Cross Square Pin"_s, AccessorySize::S}},
|
||||
{108, {"Flat Square Pin"_s, AccessorySize::S}},
|
||||
{109, {"Quad Corner Pin"_s, AccessorySize::S}},
|
||||
{110, {"Bi Corner Pin"_s, AccessorySize::S}},
|
||||
{111, {"Circle Pin"_s, AccessorySize::S}},
|
||||
{112, {"Flat End Pin"_s, AccessorySize::S}},
|
||||
{113, {"Flat Cut Pin"_s, AccessorySize::S}},
|
||||
{114, {"Radial Pin"_s, AccessorySize::S}},
|
||||
{115, {"Diamiter Pin"_s, AccessorySize::S}},
|
||||
|
||||
{151, {"TriPoint"_s, AccessorySize::S}},
|
||||
{152, {"SquPoint"_s, AccessorySize::S}},
|
||||
{153, {"PenPoint"_s, AccessorySize::S}},
|
||||
{154, {"HexPoint"_s, AccessorySize::S}},
|
||||
{155, {"CycPoint"_s, AccessorySize::S}},
|
||||
{156, {"Bevel SquCutPoint"_s, AccessorySize::S}},
|
||||
{157, {"Bevel HexCutPoint"_s, AccessorySize::S}},
|
||||
{158, {"Bevel HexPoint"_s, AccessorySize::S}},
|
||||
{159, {"Bevel CycCutPoint"_s, AccessorySize::S}},
|
||||
{160, {"Bevel CycPoint"_s, AccessorySize::S}},
|
||||
|
||||
{201, {"Shaped Edge 01"_s, AccessorySize::M}},
|
||||
{202, {"Shaped Edge 02"_s, AccessorySize::M}},
|
||||
{203, {"Shaped Edge 03"_s, AccessorySize::M}},
|
||||
{204, {"Shaped Edge 04"_s, AccessorySize::M}},
|
||||
{205, {"Shaped Edge 05"_s, AccessorySize::M}},
|
||||
{206, {"Shaped Edge 06"_s, AccessorySize::M}},
|
||||
{207, {"Shaped Edge 07"_s, AccessorySize::M}},
|
||||
{208, {"Shaped Edge 08"_s, AccessorySize::M}},
|
||||
{209, {"Shaped Edge 09"_s, AccessorySize::M}},
|
||||
{210, {"Shaped Edge 10"_s, AccessorySize::M}},
|
||||
{211, {"Shaped Edge 11"_s, AccessorySize::M}},
|
||||
{212, {"Shaped Edge 12"_s, AccessorySize::M}},
|
||||
{213, {"Shaped Edge 13"_s, AccessorySize::M}},
|
||||
{214, {"Shaped Edge 14"_s, AccessorySize::M}},
|
||||
{215, {"Shaped Edge 15"_s, AccessorySize::M}},
|
||||
{216, {"Shaped Edge 16"_s, AccessorySize::M}},
|
||||
{217, {"Shaped Edge 17"_s, AccessorySize::M}},
|
||||
{218, {"Shaped Edge 18"_s, AccessorySize::M}},
|
||||
{219, {"Shaped Edge 19"_s, AccessorySize::M}},
|
||||
{220, {"Shaped Edge 20"_s, AccessorySize::M}},
|
||||
|
||||
{251, {"Fish Tail 01"_s, AccessorySize::M}},
|
||||
{252, {"Fish Tail 02"_s, AccessorySize::M}},
|
||||
{253, {"Fish Tail 03"_s, AccessorySize::M}},
|
||||
{254, {"Fish Tail 04"_s, AccessorySize::M}},
|
||||
{255, {"Fish Tail 05"_s, AccessorySize::M}},
|
||||
{256, {"Based Separator 01"_s, AccessorySize::M}},
|
||||
{257, {"Based Separator 02"_s, AccessorySize::M}},
|
||||
{258, {"Based Separator 03"_s, AccessorySize::M}},
|
||||
{259, {"Based Separator 04"_s, AccessorySize::M}},
|
||||
{260, {"Based Separator 05"_s, AccessorySize::M}},
|
||||
{261, {"Based Separator 06"_s, AccessorySize::M}},
|
||||
{262, {"Based Separator 07"_s, AccessorySize::M}},
|
||||
{263, {"Based Separator 08"_s, AccessorySize::M}},
|
||||
{264, {"Based Separator 09"_s, AccessorySize::M}},
|
||||
{265, {"Based Separator 10"_s, AccessorySize::M}},
|
||||
|
||||
{301, {"Rectangular Box 01"_s, AccessorySize::M}},
|
||||
{302, {"Rectangular Box 02"_s, AccessorySize::M}},
|
||||
{303, {"Rectangular Box 03"_s, AccessorySize::M}},
|
||||
{304, {"Rectangular Box 04"_s, AccessorySize::M}},
|
||||
{305, {"Rectangular Box 05"_s, AccessorySize::M}},
|
||||
{306, {"CofBox 01"_s, AccessorySize::M}},
|
||||
{307, {"CofBox 02"_s, AccessorySize::M}},
|
||||
{308, {"CofBox 03"_s, AccessorySize::M}},
|
||||
{309, {"CofBox 04"_s, AccessorySize::M}},
|
||||
{310, {"CofBox 05"_s, AccessorySize::M}},
|
||||
{311, {"Triangular Box 01"_s, AccessorySize::M}},
|
||||
{312, {"Triangular Box 02"_s, AccessorySize::M}},
|
||||
{313, {"Triangular Box 03"_s, AccessorySize::M}},
|
||||
{314, {"Triangular Box 04"_s, AccessorySize::M}},
|
||||
{315, {"Triangular Box 05"_s, AccessorySize::M}},
|
||||
{316, {"Diagonal Box A01"_s, AccessorySize::M}},
|
||||
{317, {"Diagonal Box A02"_s, AccessorySize::M}},
|
||||
{318, {"Diagonal Box A03"_s, AccessorySize::M}},
|
||||
{319, {"Diagonal Box A04"_s, AccessorySize::M}},
|
||||
{320, {"Diagonal Box A05"_s, AccessorySize::M}},
|
||||
{321, {"Diagonal Box B01"_s, AccessorySize::M}},
|
||||
{322, {"Diagonal Box B02"_s, AccessorySize::M}},
|
||||
{323, {"Diagonal Box B03"_s, AccessorySize::M}},
|
||||
{324, {"Diagonal Box B04"_s, AccessorySize::M}},
|
||||
{325, {"Diagonal Box B05"_s, AccessorySize::M}},
|
||||
// endregion
|
||||
|
||||
// region Armours
|
||||
{1001, {"Short Layer 01"_s, AccessorySize::M}},
|
||||
{1002, {"Short Layer 02"_s, AccessorySize::M}},
|
||||
{1003, {"Short Layer 03"_s, AccessorySize::M}},
|
||||
{1004, {"Short Layer 04"_s, AccessorySize::M}},
|
||||
{1005, {"Short Layer 05"_s, AccessorySize::M}},
|
||||
{1006, {"Long Layer 01"_s, AccessorySize::M}},
|
||||
{1007, {"Long Layer 02"_s, AccessorySize::M}},
|
||||
{1008, {"Long Layer 03"_s, AccessorySize::M}},
|
||||
{1009, {"Long Layer 04"_s, AccessorySize::M}},
|
||||
{1010, {"Long Layer 05"_s, AccessorySize::M}},
|
||||
{1011, {"Diagonal Long Layer 01"_s, AccessorySize::M}},
|
||||
{1012, {"Diagonal Long Layer 02"_s, AccessorySize::M}},
|
||||
{1013, {"Diagonal Long Layer 03"_s, AccessorySize::M}},
|
||||
{1014, {"Diagonal Long Layer 04"_s, AccessorySize::M}},
|
||||
{1015, {"Diagonal Long Layer 05"_s, AccessorySize::M}},
|
||||
|
||||
{1051, {"Sloped Layer 01"_s, AccessorySize::M}},
|
||||
{1052, {"Sloped Layer 02"_s, AccessorySize::M}},
|
||||
{1053, {"Sloped Layer 03"_s, AccessorySize::M}},
|
||||
{1054, {"Sloped Layer 04"_s, AccessorySize::M}},
|
||||
{1055, {"Sloped Layer 05"_s, AccessorySize::M}},
|
||||
{1056, {"Sloped Layer 06"_s, AccessorySize::M}},
|
||||
{1057, {"Sloped Layer 07"_s, AccessorySize::M}},
|
||||
{1058, {"Sloped Layer 08"_s, AccessorySize::M}},
|
||||
{1059, {"Sloped Layer 09"_s, AccessorySize::M}},
|
||||
{1060, {"Sloped Layer 10"_s, AccessorySize::M}},
|
||||
{1061, {"Sloped Layer 11"_s, AccessorySize::M}},
|
||||
{1062, {"Sloped Layer 12"_s, AccessorySize::M}},
|
||||
{1063, {"Sloped Layer 13"_s, AccessorySize::M}},
|
||||
{1064, {"Sloped Layer 14"_s, AccessorySize::M}},
|
||||
{1065, {"Sloped Layer 15"_s, AccessorySize::M}},
|
||||
|
||||
{1101, {"Raised Center 01"_s, AccessorySize::M}},
|
||||
{1102, {"Raised Center 02"_s, AccessorySize::M}},
|
||||
{1103, {"Raised Center 03"_s, AccessorySize::M}},
|
||||
{1104, {"Raised Center 04"_s, AccessorySize::M}},
|
||||
{1105, {"Raised Center 05"_s, AccessorySize::M}},
|
||||
{1106, {"Raised Block 01"_s, AccessorySize::M}},
|
||||
{1107, {"Raised Block 02"_s, AccessorySize::M}},
|
||||
{1108, {"Raised Block 03"_s, AccessorySize::M}},
|
||||
{1109, {"Raised Pointed"_s, AccessorySize::M}},
|
||||
{1110, {"Raised Cover"_s, AccessorySize::M}},
|
||||
{1111, {"Raised Slant 01"_s, AccessorySize::M}},
|
||||
{1112, {"Raised Slant 02"_s, AccessorySize::M}},
|
||||
{1113, {"Raised Slant 03"_s, AccessorySize::M}},
|
||||
{1114, {"Raised Slant 04"_s, AccessorySize::M}},
|
||||
{1115, {"Raised Slant 05"_s, AccessorySize::M}},
|
||||
|
||||
{1151, {"Wide Patch 01"_s, AccessorySize::L}},
|
||||
{1152, {"Wide Patch 02"_s, AccessorySize::L}},
|
||||
{1153, {"Wide Patch 03"_s, AccessorySize::L}},
|
||||
{1154, {"Wide Patch 04"_s, AccessorySize::L}},
|
||||
{1155, {"Wide Patch 05"_s, AccessorySize::L}},
|
||||
|
||||
{1201, {"Pointed Armour 01"_s, AccessorySize::L}},
|
||||
{1202, {"Pointed Armour 02"_s, AccessorySize::L}},
|
||||
{1203, {"Pointed Armour 03"_s, AccessorySize::L}},
|
||||
{1204, {"Pointed Armour 04"_s, AccessorySize::L}},
|
||||
{1205, {"Pointed Armour 05"_s, AccessorySize::L}},
|
||||
{1206, {"Pointed Armour 06"_s, AccessorySize::L}},
|
||||
{1207, {"Pointed Armour 07"_s, AccessorySize::L}},
|
||||
{1208, {"Pointed Armour 08"_s, AccessorySize::L}},
|
||||
{1209, {"Pointed Armour 09"_s, AccessorySize::L}},
|
||||
{1210, {"Pointed Armour 10"_s, AccessorySize::L}},
|
||||
{1211, {"Pointed Armour 11"_s, AccessorySize::L}},
|
||||
{1212, {"Pointed Armour 12"_s, AccessorySize::L}},
|
||||
{1213, {"Pointed Armour 13"_s, AccessorySize::L}},
|
||||
{1214, {"Pointed Armour 14"_s, AccessorySize::L}},
|
||||
{1215, {"Pointed Armour 15"_s, AccessorySize::L}},
|
||||
|
||||
{1251, {"E Limb Cover 01"_s, AccessorySize::L}},
|
||||
{1252, {"E Limb Cover 02"_s, AccessorySize::L}},
|
||||
{1253, {"E Limb Cover 03"_s, AccessorySize::L}},
|
||||
{1254, {"E Limb Cover 04"_s, AccessorySize::L}},
|
||||
{1255, {"E Limb Cover 05"_s, AccessorySize::L}},
|
||||
{1256, {"E Limb Cover 06"_s, AccessorySize::L}},
|
||||
{1257, {"E Limb Cover 07"_s, AccessorySize::L}},
|
||||
{1258, {"E Limb Cover 08"_s, AccessorySize::L}},
|
||||
{1259, {"E Limb Cover 09"_s, AccessorySize::L}},
|
||||
{1260, {"E Limb Cover 10"_s, AccessorySize::L}},
|
||||
|
||||
{1301, {"C Limb Cover 01"_s, AccessorySize::L}},
|
||||
{1302, {"C Limb Cover 02"_s, AccessorySize::L}},
|
||||
{1303, {"C Limb Cover 03"_s, AccessorySize::L}},
|
||||
{1304, {"C Limb Cover 04"_s, AccessorySize::L}},
|
||||
{1305, {"C Limb Cover 05"_s, AccessorySize::L}},
|
||||
{1306, {"C Limb Cover 06"_s, AccessorySize::L}},
|
||||
{1307, {"C Limb Cover 07"_s, AccessorySize::L}},
|
||||
{1308, {"C Limb Cover 08"_s, AccessorySize::L}},
|
||||
{1309, {"C Limb Cover 09"_s, AccessorySize::L}},
|
||||
{1310, {"C Limb Cover 10"_s, AccessorySize::L}},
|
||||
{1311, {"C Limb Cover 11"_s, AccessorySize::L}},
|
||||
{1312, {"C Limb Cover 12"_s, AccessorySize::L}},
|
||||
{1313, {"C Limb Cover 13"_s, AccessorySize::L}},
|
||||
{1314, {"C Limb Cover 14"_s, AccessorySize::L}},
|
||||
{1315, {"C Limb Cover 15"_s, AccessorySize::L}},
|
||||
{1316, {"C Limb Cover 16"_s, AccessorySize::L}},
|
||||
{1317, {"C Limb Cover 17"_s, AccessorySize::L}},
|
||||
{1318, {"C Limb Cover 18"_s, AccessorySize::L}},
|
||||
{1319, {"C Limb Cover 19"_s, AccessorySize::L}},
|
||||
{1320, {"C Limb Cover 20"_s, AccessorySize::L}},
|
||||
|
||||
{1351, {"P Limb Cover 01"_s, AccessorySize::XL}},
|
||||
{1352, {"P Limb Cover 02"_s, AccessorySize::XL}},
|
||||
{1353, {"P Limb Cover 03"_s, AccessorySize::XL}},
|
||||
{1354, {"P Limb Cover 04"_s, AccessorySize::XL}},
|
||||
{1355, {"P Limb Cover 05"_s, AccessorySize::XL}},
|
||||
|
||||
{1401, {"Flat Cover 01"_s, AccessorySize::XL}},
|
||||
{1402, {"Flat Cover 02"_s, AccessorySize::XL}},
|
||||
{1403, {"Flat Cover 03"_s, AccessorySize::XL}},
|
||||
{1404, {"Flat Cover 04"_s, AccessorySize::XL}},
|
||||
{1405, {"Flat Cover 05"_s, AccessorySize::XL}},
|
||||
{1406, {"Flat Cover 06"_s, AccessorySize::XL}},
|
||||
{1407, {"Flat Cover 07"_s, AccessorySize::XL}},
|
||||
{1408, {"Flat Cover 08"_s, AccessorySize::XL}},
|
||||
{1409, {"Flat Cover 09"_s, AccessorySize::XL}},
|
||||
{1410, {"Flat Cover 10"_s, AccessorySize::XL}},
|
||||
|
||||
{1451, {"L Side Opening 01"_s, AccessorySize::XL}},
|
||||
{1452, {"L Side Opening 02"_s, AccessorySize::XL}},
|
||||
{1453, {"L Side Opening 03"_s, AccessorySize::XL}},
|
||||
{1454, {"L Side Opening 04"_s, AccessorySize::XL}},
|
||||
{1455, {"L Side Opening 05"_s, AccessorySize::XL}},
|
||||
{1456, {"L Side Opening 06"_s, AccessorySize::XL}},
|
||||
{1457, {"L Side Opening 07"_s, AccessorySize::XL}},
|
||||
{1458, {"L Side Opening 08"_s, AccessorySize::XL}},
|
||||
{1459, {"L Side Opening 09"_s, AccessorySize::XL}},
|
||||
{1460, {"L Side Opening 10"_s, AccessorySize::XL}},
|
||||
// endregion
|
||||
|
||||
// region Components
|
||||
{2001, {"Disc Padding 01"_s, AccessorySize::M}},
|
||||
{2002, {"Disc Padding 02"_s, AccessorySize::M}},
|
||||
{2003, {"Disc Padding 03"_s, AccessorySize::M}},
|
||||
{2004, {"Disc Padding 04"_s, AccessorySize::M}},
|
||||
{2005, {"Disc Padding 05"_s, AccessorySize::M}},
|
||||
{2006, {"Thin Padding 01"_s, AccessorySize::M}},
|
||||
{2007, {"Thin Padding 02"_s, AccessorySize::M}},
|
||||
{2008, {"Thin Padding 03"_s, AccessorySize::M}},
|
||||
{2009, {"Thin Padding 04"_s, AccessorySize::M}},
|
||||
{2010, {"Thin Padding 05"_s, AccessorySize::M}},
|
||||
{2011, {"Thick Padding 01"_s, AccessorySize::M}},
|
||||
{2012, {"Thick Padding 02"_s, AccessorySize::M}},
|
||||
{2013, {"Thick Padding 03"_s, AccessorySize::M}},
|
||||
{2014, {"Thick Padding 04"_s, AccessorySize::M}},
|
||||
{2015, {"Thick Padding 05"_s, AccessorySize::M}},
|
||||
{2016, {"Thick Padding 06"_s, AccessorySize::M}},
|
||||
{2017, {"Thick Padding 07"_s, AccessorySize::M}},
|
||||
{2018, {"Thick Padding 08"_s, AccessorySize::M}},
|
||||
{2019, {"Thick Padding 09"_s, AccessorySize::M}},
|
||||
{2020, {"Thick Padding 10"_s, AccessorySize::M}},
|
||||
{2021, {"CSide Padding 01"_s, AccessorySize::M}},
|
||||
{2022, {"CSide Padding 02"_s, AccessorySize::M}},
|
||||
{2023, {"CSide Padding 03"_s, AccessorySize::M}},
|
||||
{2024, {"CSide Padding 04"_s, AccessorySize::M}},
|
||||
{2025, {"CSide Padding 05"_s, AccessorySize::M}},
|
||||
|
||||
{2051, {"Container 01"_s, AccessorySize::L}},
|
||||
{2052, {"Container 02"_s, AccessorySize::L}},
|
||||
{2053, {"Container 03"_s, AccessorySize::L}},
|
||||
{2054, {"Container 04"_s, AccessorySize::L}},
|
||||
{2055, {"Container 05"_s, AccessorySize::L}},
|
||||
|
||||
{2101, {"Plating 01"_s, AccessorySize::L}},
|
||||
{2102, {"Plating 02"_s, AccessorySize::L}},
|
||||
{2103, {"Plating 03"_s, AccessorySize::L}},
|
||||
{2104, {"Plating 04"_s, AccessorySize::L}},
|
||||
{2105, {"Plating 05"_s, AccessorySize::L}},
|
||||
|
||||
{2151, {"Complex Base 01"_s, AccessorySize::L}},
|
||||
{2152, {"Complex Base 02"_s, AccessorySize::L}},
|
||||
{2153, {"Complex Base 03"_s, AccessorySize::L}},
|
||||
{2154, {"Complex Base 04"_s, AccessorySize::L}},
|
||||
{2155, {"Complex Base 05"_s, AccessorySize::L}},
|
||||
{2156, {"Complex Base 06"_s, AccessorySize::L}},
|
||||
{2157, {"Complex Base 07"_s, AccessorySize::L}},
|
||||
{2158, {"Complex Base 08"_s, AccessorySize::L}},
|
||||
{2159, {"Complex Base 09"_s, AccessorySize::L}},
|
||||
{2160, {"Complex Base 10"_s, AccessorySize::L}},
|
||||
|
||||
{2201, {"Long Base 01"_s, AccessorySize::XL}},
|
||||
{2202, {"Long Base 02"_s, AccessorySize::XL}},
|
||||
{2203, {"Long Base 03"_s, AccessorySize::XL}},
|
||||
{2204, {"Long Base 04"_s, AccessorySize::XL}},
|
||||
{2205, {"Long Base 05"_s, AccessorySize::XL}},
|
||||
|
||||
{2251, {"Straight Wing 01"_s, AccessorySize::XL}},
|
||||
{2252, {"Straight Wing 02"_s, AccessorySize::XL}},
|
||||
{2253, {"Straight Wing 03"_s, AccessorySize::XL}},
|
||||
{2254, {"Straight Wing 04"_s, AccessorySize::XL}},
|
||||
{2255, {"Straight Wing 05"_s, AccessorySize::XL}},
|
||||
{2256, {"Straight Wing 06"_s, AccessorySize::XL}},
|
||||
{2257, {"Straight Wing 07"_s, AccessorySize::XL}},
|
||||
{2258, {"Straight Wing 08"_s, AccessorySize::XL}},
|
||||
{2259, {"Straight Wing 09"_s, AccessorySize::XL}},
|
||||
{2260, {"Straight Wing 10"_s, AccessorySize::XL}},
|
||||
|
||||
{2301, {"Triangular Wing 01"_s, AccessorySize::XL}},
|
||||
{2302, {"Triangular Wing 02"_s, AccessorySize::XL}},
|
||||
{2303, {"Triangular Wing 03"_s, AccessorySize::XL}},
|
||||
{2304, {"Triangular Wing 04"_s, AccessorySize::XL}},
|
||||
{2305, {"Triangular Wing 05"_s, AccessorySize::XL}},
|
||||
{2306, {"Triangular Wing 06"_s, AccessorySize::XL}},
|
||||
{2307, {"Triangular Wing 07"_s, AccessorySize::XL}},
|
||||
{2308, {"Triangular Wing 08"_s, AccessorySize::XL}},
|
||||
{2309, {"Triangular Wing 09"_s, AccessorySize::XL}},
|
||||
{2310, {"Triangular Wing 10"_s, AccessorySize::XL}},
|
||||
{2311, {"Triangular Wing 11"_s, AccessorySize::L}},
|
||||
{2312, {"Triangular Wing 12"_s, AccessorySize::L}},
|
||||
{2313, {"Triangular Wing 13"_s, AccessorySize::L}},
|
||||
{2314, {"Triangular Wing 14"_s, AccessorySize::L}},
|
||||
{2315, {"Triangular Wing 15"_s, AccessorySize::L}},
|
||||
|
||||
{2351, {"Complex Wing 01"_s, AccessorySize::XL}},
|
||||
{2352, {"Complex Wing 02"_s, AccessorySize::XL}},
|
||||
{2353, {"Complex Wing 03"_s, AccessorySize::XL}},
|
||||
{2354, {"Complex Wing 04"_s, AccessorySize::XL}},
|
||||
{2355, {"Complex Wing 05"_s, AccessorySize::XL}},
|
||||
{2356, {"Complex Wing 06"_s, AccessorySize::L}},
|
||||
{2357, {"Complex Wing 07"_s, AccessorySize::L}},
|
||||
{2358, {"Complex Wing 08"_s, AccessorySize::L}},
|
||||
{2359, {"Complex Wing 09"_s, AccessorySize::L}},
|
||||
{2360, {"Complex Wing 10"_s, AccessorySize::L}},
|
||||
|
||||
{2401, {"Blade 01"_s, AccessorySize::XL}},
|
||||
{2402, {"Blade 02"_s, AccessorySize::XL}},
|
||||
{2403, {"Blade 03"_s, AccessorySize::XL}},
|
||||
{2404, {"Blade 04"_s, AccessorySize::XL}},
|
||||
{2405, {"Blade 05"_s, AccessorySize::XL}},
|
||||
{2406, {"Blade 06"_s, AccessorySize::XL}},
|
||||
{2407, {"Blade 07"_s, AccessorySize::XL}},
|
||||
{2408, {"Blade 08"_s, AccessorySize::XL}},
|
||||
{2409, {"Blade 09"_s, AccessorySize::XL}},
|
||||
{2410, {"Blade 10"_s, AccessorySize::XL}},
|
||||
{2411, {"Blade 11"_s, AccessorySize::XL}},
|
||||
{2412, {"Blade 12"_s, AccessorySize::XL}},
|
||||
{2413, {"Blade 13"_s, AccessorySize::XL}},
|
||||
{2414, {"Blade 14"_s, AccessorySize::XL}},
|
||||
{2415, {"Blade 15"_s, AccessorySize::XL}},
|
||||
|
||||
{2426, {"Curved Blade 01"_s, AccessorySize::XL}},
|
||||
{2427, {"Curved Blade 02"_s, AccessorySize::XL}},
|
||||
{2428, {"Curved Blade 03"_s, AccessorySize::XL}},
|
||||
{2429, {"Curved Blade 04"_s, AccessorySize::XL}},
|
||||
{2430, {"Curved Blade 05"_s, AccessorySize::XL}},
|
||||
{2431, {"Axe Head 01"_s, AccessorySize::XL}},
|
||||
{2432, {"Axe Head 02"_s, AccessorySize::XL}},
|
||||
{2433, {"Axe Head 03"_s, AccessorySize::XL}},
|
||||
{2434, {"Axe Head 04"_s, AccessorySize::XL}},
|
||||
{2435, {"Axe Head 05"_s, AccessorySize::XL}},
|
||||
|
||||
{2451, {"Horn 01"_s, AccessorySize::M}},
|
||||
{2452, {"Horn 02"_s, AccessorySize::M}},
|
||||
{2453, {"Horn 03"_s, AccessorySize::M}},
|
||||
{2454, {"Horn 04"_s, AccessorySize::M}},
|
||||
{2455, {"Horn 05"_s, AccessorySize::M}},
|
||||
{2456, {"Horn 06"_s, AccessorySize::M}},
|
||||
{2457, {"Horn 07"_s, AccessorySize::M}},
|
||||
{2458, {"Horn 08"_s, AccessorySize::M}},
|
||||
{2459, {"Horn 09"_s, AccessorySize::M}},
|
||||
{2460, {"Horn 10"_s, AccessorySize::M}},
|
||||
{2461, {"Horn 11"_s, AccessorySize::M}},
|
||||
{2462, {"Horn 12"_s, AccessorySize::M}},
|
||||
{2463, {"Horn 13"_s, AccessorySize::M}},
|
||||
{2464, {"Horn 14"_s, AccessorySize::M}},
|
||||
{2465, {"Horn 15"_s, AccessorySize::M}},
|
||||
|
||||
{2471, {"Mask"_s, AccessorySize::M}},
|
||||
{2472, {"Droplet"_s, AccessorySize::M}},
|
||||
{2473, {"Thigh"_s, AccessorySize::M}},
|
||||
{2474, {"LegS"_s, AccessorySize::M}},
|
||||
{2475, {"LegTH"_s, AccessorySize::M}},
|
||||
{2476, {"Plume 01"_s, AccessorySize::M}},
|
||||
{2477, {"Plume 02"_s, AccessorySize::M}},
|
||||
{2478, {"Plume 03"_s, AccessorySize::M}},
|
||||
{2479, {"Plume 04"_s, AccessorySize::M}},
|
||||
{2480, {"Plume 05"_s, AccessorySize::M}},
|
||||
|
||||
{2491, {"Tail 01"_s, AccessorySize::XL}},
|
||||
{2492, {"Tail 02"_s, AccessorySize::XL}},
|
||||
{2493, {"Tail 03"_s, AccessorySize::XL}},
|
||||
{2494, {"Tail 04"_s, AccessorySize::XL}},
|
||||
{2495, {"Tail 05"_s, AccessorySize::XL}},
|
||||
|
||||
{2501, {"Finger 01"_s, AccessorySize::M}},
|
||||
{2502, {"Finger 02"_s, AccessorySize::M}},
|
||||
{2503, {"Finger 03"_s, AccessorySize::M}},
|
||||
{2504, {"Finger 04"_s, AccessorySize::M}},
|
||||
{2505, {"Finger 05"_s, AccessorySize::M}},
|
||||
|
||||
{2510, {"Clamp 01"_s, AccessorySize::M}},
|
||||
{2511, {"Clamp 02"_s, AccessorySize::M}},
|
||||
{2512, {"Clamp 03"_s, AccessorySize::M}},
|
||||
{2513, {"Clamp 04"_s, AccessorySize::M}},
|
||||
{2514, {"Clamp 05"_s, AccessorySize::M}},
|
||||
|
||||
{2521, {"Fabric 01"_s, AccessorySize::XL}},
|
||||
{2522, {"Fabric 02"_s, AccessorySize::XL}},
|
||||
{2523, {"Fabric 03"_s, AccessorySize::XL}},
|
||||
{2524, {"Fabric 04"_s, AccessorySize::XL}},
|
||||
{2525, {"Fabric 05"_s, AccessorySize::XL}},
|
||||
|
||||
{2551, {"Energy Barrel 01"_s, AccessorySize::XL}},
|
||||
{2552, {"Energy Barrel 02"_s, AccessorySize::XL}},
|
||||
{2553, {"Energy Barrel 03"_s, AccessorySize::XL}},
|
||||
{2554, {"Energy Barrel 04"_s, AccessorySize::XL}},
|
||||
{2555, {"Energy Barrel 05"_s, AccessorySize::XL}},
|
||||
|
||||
{2601, {"L Bullet Barrel 01"_s, AccessorySize::XL}},
|
||||
{2602, {"L Bullet Barrel 02"_s, AccessorySize::XL}},
|
||||
{2603, {"L Bullet Barrel 03"_s, AccessorySize::XL}},
|
||||
{2604, {"L Bullet Barrel 04"_s, AccessorySize::XL}},
|
||||
{2605, {"L Bullet Barrel 05"_s, AccessorySize::XL}},
|
||||
{2606, {"S Bullet Barrel 01"_s, AccessorySize::XL}},
|
||||
{2607, {"S Bullet Barrel 02"_s, AccessorySize::XL}},
|
||||
{2608, {"S Bullet Barrel 03"_s, AccessorySize::XL}},
|
||||
{2609, {"S Bullet Barrel 04"_s, AccessorySize::XL}},
|
||||
{2610, {"S Bullet Barrel 05"_s, AccessorySize::XL}},
|
||||
{2611, {"B Bullet Barrel 01"_s, AccessorySize::XL}},
|
||||
{2612, {"B Bullet Barrel 02"_s, AccessorySize::XL}},
|
||||
{2613, {"B Bullet Barrel 03"_s, AccessorySize::XL}},
|
||||
{2614, {"B Bullet Barrel 04"_s, AccessorySize::XL}},
|
||||
{2615, {"B Bullet Barrel 05"_s, AccessorySize::XL}},
|
||||
{2616, {"B Bullet Barrel 06"_s, AccessorySize::XL}},
|
||||
{2617, {"B Bullet Barrel 07"_s, AccessorySize::XL}},
|
||||
{2618, {"B Bullet Barrel 08"_s, AccessorySize::XL}},
|
||||
{2619, {"B Bullet Barrel 09"_s, AccessorySize::XL}},
|
||||
{2620, {"B Bullet Barrel 10"_s, AccessorySize::XL}},
|
||||
|
||||
{2651, {"Cylinder Scope 01"_s, AccessorySize::M}},
|
||||
{2652, {"Cylinder Scope 02"_s, AccessorySize::M}},
|
||||
{2653, {"Cylinder Scope 03"_s, AccessorySize::M}},
|
||||
{2654, {"Cylinder Scope 04"_s, AccessorySize::M}},
|
||||
{2655, {"Cylinder Scope 05"_s, AccessorySize::M}},
|
||||
{2656, {"Elec Scope 01"_s, AccessorySize::M}},
|
||||
{2657, {"Elec Scope 02"_s, AccessorySize::M}},
|
||||
{2658, {"Elec Scope 03"_s, AccessorySize::M}},
|
||||
{2659, {"Elec Scope 04"_s, AccessorySize::M}},
|
||||
{2660, {"Elec Scope 05"_s, AccessorySize::M}},
|
||||
{2661, {"Mark Scope 01"_s, AccessorySize::S}},
|
||||
{2662, {"Mark Scope 02"_s, AccessorySize::S}},
|
||||
{2663, {"Mark Scope 03"_s, AccessorySize::S}},
|
||||
{2664, {"Mark Scope 04"_s, AccessorySize::S}},
|
||||
{2665, {"Mark Scope 05"_s, AccessorySize::S}},
|
||||
|
||||
{2701, {"S Single Weaponry"_s, AccessorySize::M}},
|
||||
{2702, {"S Packed Weaponry 01"_s, AccessorySize::M}},
|
||||
{2703, {"S Packed Weaponry 02"_s, AccessorySize::M}},
|
||||
{2704, {"S Packed Weaponry 03"_s, AccessorySize::M}},
|
||||
{2705, {"S Packed Weaponry 04"_s, AccessorySize::M}},
|
||||
{2706, {"L Single Weaponry"_s, AccessorySize::XL}},
|
||||
{2707, {"L Packed Weaponry 01"_s, AccessorySize::XL}},
|
||||
{2708, {"L Packed Weaponry 02"_s, AccessorySize::XL}},
|
||||
{2709, {"L Packed Weaponry 03"_s, AccessorySize::XL}},
|
||||
{2710, {"L Packed Weaponry 04"_s, AccessorySize::XL}},
|
||||
{2711, {"Atk Single Weaponry"_s, AccessorySize::XL}},
|
||||
{2712, {"Atk Packed Weaponry 01"_s, AccessorySize::XL}},
|
||||
{2713, {"Atk Packed Weaponry 02"_s, AccessorySize::XL}},
|
||||
{2714, {"Atk Packed Weaponry 03"_s, AccessorySize::XL}},
|
||||
{2715, {"Atk Packed Weaponry 04"_s, AccessorySize::XL}},
|
||||
|
||||
{2751, {"Vent 01"_s, AccessorySize::M}},
|
||||
{2752, {"Vent 02"_s, AccessorySize::M}},
|
||||
{2753, {"Vent 03"_s, AccessorySize::M}},
|
||||
{2754, {"Vent 04"_s, AccessorySize::M}},
|
||||
{2755, {"Vent 05"_s, AccessorySize::M}},
|
||||
{2756, {"Vent 06"_s, AccessorySize::M}},
|
||||
{2757, {"Vent 07"_s, AccessorySize::M}},
|
||||
{2758, {"Vent 08"_s, AccessorySize::M}},
|
||||
{2759, {"Vent 09"_s, AccessorySize::M}},
|
||||
{2760, {"Vent 10"_s, AccessorySize::M}},
|
||||
|
||||
{2901, {"Complex Construct 01"_s, AccessorySize::L}},
|
||||
{2902, {"Complex Construct 02"_s, AccessorySize::L}},
|
||||
{2903, {"Complex Construct 03"_s, AccessorySize::L}},
|
||||
{2904, {"Complex Construct 04"_s, AccessorySize::L}},
|
||||
{2905, {"Complex Construct 05"_s, AccessorySize::L}},
|
||||
|
||||
{2950, {"Q Mask 01"_s, AccessorySize::M}},
|
||||
{2951, {"Q Mask 02"_s, AccessorySize::M}},
|
||||
{2952, {"Q Mask 03"_s, AccessorySize::M}},
|
||||
{2953, {"Q Mask 04"_s, AccessorySize::M}},
|
||||
{2954, {"Q Mask 05"_s, AccessorySize::M}},
|
||||
// endregion
|
||||
|
||||
// region Connectors
|
||||
{3001, {"Circular Vent 01"_s, AccessorySize::M}},
|
||||
{3002, {"Circular Vent 02"_s, AccessorySize::M}},
|
||||
{3003, {"Circular Vent 03"_s, AccessorySize::M}},
|
||||
{3004, {"Circular Vent 04"_s, AccessorySize::M}},
|
||||
{3005, {"Circular Vent 05"_s, AccessorySize::M}},
|
||||
{3006, {"Circular Vent 06"_s, AccessorySize::M}},
|
||||
{3007, {"Circular Vent 07"_s, AccessorySize::M}},
|
||||
{3008, {"Circular Vent 08"_s, AccessorySize::M}},
|
||||
{3009, {"Circular Vent 09"_s, AccessorySize::M}},
|
||||
{3010, {"Circular Vent 10"_s, AccessorySize::M}},
|
||||
{3011, {"Circular Vent 11"_s, AccessorySize::M}},
|
||||
{3012, {"Circular Vent 12"_s, AccessorySize::M}},
|
||||
{3013, {"Circular Vent 13"_s, AccessorySize::M}},
|
||||
{3014, {"Circular Vent 14"_s, AccessorySize::M}},
|
||||
{3015, {"Circular Vent 15"_s, AccessorySize::M}},
|
||||
|
||||
{3051, {"Reactor 01"_s, AccessorySize::L}},
|
||||
{3052, {"Reactor 02"_s, AccessorySize::L}},
|
||||
{3053, {"Reactor 03"_s, AccessorySize::L}},
|
||||
{3054, {"Reactor 04"_s, AccessorySize::L}},
|
||||
{3055, {"Reactor 05"_s, AccessorySize::L}},
|
||||
|
||||
{3101, {"Connecting Tube 01"_s, AccessorySize::XL}},
|
||||
{3102, {"Connecting Tube 02"_s, AccessorySize::XL}},
|
||||
{3103, {"Connecting Tube 03"_s, AccessorySize::XL}},
|
||||
{3104, {"Connecting Tube 04"_s, AccessorySize::XL}},
|
||||
{3105, {"Connecting Tube 05"_s, AccessorySize::XL}},
|
||||
|
||||
{3151, {"Latch 01"_s, AccessorySize::M}},
|
||||
{3152, {"Latch 02"_s, AccessorySize::M}},
|
||||
{3153, {"Latch 03"_s, AccessorySize::M}},
|
||||
{3154, {"Latch 04"_s, AccessorySize::M}},
|
||||
{3155, {"Latch 05"_s, AccessorySize::M}},
|
||||
{3156, {"Latch 06"_s, AccessorySize::M}},
|
||||
{3157, {"Latch 07"_s, AccessorySize::M}},
|
||||
{3158, {"Latch 08"_s, AccessorySize::M}},
|
||||
{3159, {"Latch 09"_s, AccessorySize::M}},
|
||||
{3160, {"Latch 10"_s, AccessorySize::M}},
|
||||
{3161, {"Latch 11"_s, AccessorySize::M}},
|
||||
{3162, {"Latch 12"_s, AccessorySize::M}},
|
||||
{3163, {"Latch 13"_s, AccessorySize::M}},
|
||||
{3164, {"Latch 14"_s, AccessorySize::M}},
|
||||
{3165, {"Latch 15"_s, AccessorySize::M}},
|
||||
|
||||
{3201, {"Short Connector 01"_s, AccessorySize::M}},
|
||||
{3202, {"Short Connector 02"_s, AccessorySize::M}},
|
||||
{3203, {"Short Connector 03"_s, AccessorySize::M}},
|
||||
{3204, {"Short Connector 04"_s, AccessorySize::M}},
|
||||
{3205, {"Short Connector 05"_s, AccessorySize::M}},
|
||||
{3206, {"Antenna 01"_s, AccessorySize::S}},
|
||||
{3207, {"Antenna 02"_s, AccessorySize::S}},
|
||||
{3208, {"Antenna 03"_s, AccessorySize::S}},
|
||||
{3209, {"Antenna 04"_s, AccessorySize::S}},
|
||||
{3210, {"Antenna 05"_s, AccessorySize::S}},
|
||||
|
||||
{3226, {"Long Connector 01"_s, AccessorySize::XL}},
|
||||
{3227, {"Long Connector 02"_s, AccessorySize::XL}},
|
||||
{3228, {"Long Connector 03"_s, AccessorySize::XL}},
|
||||
{3229, {"Long Connector 04"_s, AccessorySize::XL}},
|
||||
{3230, {"Long Connector 05"_s, AccessorySize::XL}},
|
||||
{3231, {"Long Connector 06"_s, AccessorySize::XL}},
|
||||
{3232, {"Long Connector 07"_s, AccessorySize::XL}},
|
||||
{3233, {"Long Connector 08"_s, AccessorySize::XL}},
|
||||
{3234, {"Long Connector 09"_s, AccessorySize::XL}},
|
||||
{3235, {"Long Connector 10"_s, AccessorySize::XL}},
|
||||
|
||||
{3251, {"Complex Connector 01"_s, AccessorySize::XL}},
|
||||
{3252, {"Complex Connector 02"_s, AccessorySize::XL}},
|
||||
{3253, {"Complex Connector 03"_s, AccessorySize::XL}},
|
||||
{3254, {"Complex Connector 04"_s, AccessorySize::XL}},
|
||||
{3255, {"Complex Connector 05"_s, AccessorySize::XL}},
|
||||
|
||||
{3301, {"Tube Line 01"_s, AccessorySize::L}},
|
||||
{3302, {"Tube Line 02"_s, AccessorySize::L}},
|
||||
{3303, {"Tube Line 03"_s, AccessorySize::L}},
|
||||
{3304, {"Tube Line 04"_s, AccessorySize::XL}},
|
||||
{3305, {"Tube Line 05"_s, AccessorySize::XL}},
|
||||
{3306, {"Tube Line 06"_s, AccessorySize::M}},
|
||||
{3307, {"Tube Line 07"_s, AccessorySize::M}},
|
||||
{3308, {"Tube Line 08"_s, AccessorySize::M}},
|
||||
{3309, {"Tube Line 09"_s, AccessorySize::L}},
|
||||
{3310, {"Tube Line 10"_s, AccessorySize::L}},
|
||||
|
||||
{3351, {"Radar Plate 01"_s, AccessorySize::M}},
|
||||
{3352, {"Radar Plate 02"_s, AccessorySize::M}},
|
||||
{3353, {"Radar Plate 03"_s, AccessorySize::M}},
|
||||
{3354, {"Radar Plate 04"_s, AccessorySize::M}},
|
||||
{3355, {"Radar Plate 05"_s, AccessorySize::M}},
|
||||
{3356, {"Radar Pod 01"_s, AccessorySize::M}},
|
||||
{3357, {"Radar Pod 02"_s, AccessorySize::M}},
|
||||
{3358, {"Radar Pod 03"_s, AccessorySize::M}},
|
||||
{3359, {"Radar Pod 04"_s, AccessorySize::M}},
|
||||
{3360, {"Radar Pod 05"_s, AccessorySize::M}},
|
||||
|
||||
{3401, {"Tri Pod 01"_s, AccessorySize::M}},
|
||||
{3402, {"Tri Pod 02"_s, AccessorySize::M}},
|
||||
{3403, {"Tri Pod 03"_s, AccessorySize::M}},
|
||||
{3404, {"Tri Pod 04"_s, AccessorySize::M}},
|
||||
{3405, {"Tri Pod 05"_s, AccessorySize::M}},
|
||||
{3406, {"Signal Pod 01"_s, AccessorySize::M}},
|
||||
{3407, {"Signal Pod 02"_s, AccessorySize::M}},
|
||||
{3408, {"Signal Pod 03"_s, AccessorySize::M}},
|
||||
{3409, {"Signal Pod 04"_s, AccessorySize::M}},
|
||||
{3410, {"Signal Pod 05"_s, AccessorySize::M}},
|
||||
// endregion
|
||||
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
|
||||
};
|
||||
|
|
|
@ -18,41 +18,34 @@
|
|||
|
||||
#include <map>
|
||||
|
||||
#include <Corrade/Containers/StringView.h>
|
||||
|
||||
#include <Magnum/Types.h>
|
||||
|
||||
using namespace Corrade;
|
||||
using namespace Containers::Literals;
|
||||
using namespace Magnum;
|
||||
|
||||
struct ArmourSet {
|
||||
Containers::StringView name;
|
||||
const char* name;
|
||||
bool neck_compatible;
|
||||
};
|
||||
|
||||
static const std::map<Int, ArmourSet> armour_sets {
|
||||
{-1, {"<unequipped>"_s, true}},
|
||||
{0, {"Vanguard"_s, true}},
|
||||
{1, {"Assault Mk.I"_s, true}},
|
||||
{2, {"Assault Mk.II"_s, false}},
|
||||
{3, {"Assault Mk.III"_s, false}},
|
||||
{7, {"Titan 001"_s, true}},
|
||||
{8, {"Titan 002"_s, false}},
|
||||
{9, {"Titan 003"_s, false}},
|
||||
{13, {"Blitz X"_s, true}},
|
||||
{14, {"Blitz EX"_s, false}},
|
||||
{15, {"Blitz EXS"_s, false}},
|
||||
{16, {"Kaiser S-R0"_s, true}},
|
||||
{17, {"Kaiser S-R1"_s, false}},
|
||||
{18, {"Kaiser S-R2"_s, false}},
|
||||
{19, {"Hammerfall MG-A"_s, true}},
|
||||
{20, {"Hammerfall MG-S"_s, false}},
|
||||
{21, {"Hammerfall MG-X"_s, false}},
|
||||
{22, {"Panzer S-UC"_s, true}},
|
||||
{23, {"Panzer L-UC"_s, false}},
|
||||
{24, {"Panzer H-UC"_s, false}},
|
||||
{25, {"Axial Core R-Type"_s, true}},
|
||||
{26, {"Axial Core S-Type"_s, false}},
|
||||
{27, {"Axial Core X-Type"_s, false}},
|
||||
{-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}},
|
||||
};
|
||||
|
|
|
@ -15,42 +15,42 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifdef c
|
||||
c(Face, "enuArmorSlots::NewEnumerator0"_s, "Face"_s)
|
||||
c(UpperHead, "enuArmorSlots::NewEnumerator1"_s, "Upper head"_s)
|
||||
c(LowerHead, "enuArmorSlots::NewEnumerator2"_s, "Lower head"_s)
|
||||
c(Neck, "enuArmorSlots::NewEnumerator3"_s, "Neck"_s)
|
||||
c(UpperBody, "enuArmorSlots::NewEnumerator4"_s, "Upper body"_s)
|
||||
c(MiddleBody, "enuArmorSlots::NewEnumerator5"_s, "Middle body"_s)
|
||||
c(LowerBody, "enuArmorSlots::NewEnumerator6"_s, "Lower body"_s)
|
||||
c(FrontWaist, "enuArmorSlots::NewEnumerator7"_s, "Front waist"_s)
|
||||
c(LeftFrontSkirt, "enuArmorSlots::NewEnumerator8"_s, "Left front skirt"_s)
|
||||
c(RightFrontSkirt, "enuArmorSlots::NewEnumerator9"_s, "Right front skirt"_s)
|
||||
c(LeftSideSkirt, "enuArmorSlots::NewEnumerator10"_s, "Left side skirt"_s)
|
||||
c(RightSideSkirt, "enuArmorSlots::NewEnumerator11"_s, "Right side skirt"_s)
|
||||
c(LeftBackSkirt, "enuArmorSlots::NewEnumerator12"_s, "Left back skirt"_s)
|
||||
c(RightBackSkirt, "enuArmorSlots::NewEnumerator13"_s, "Right back skirt"_s)
|
||||
c(BackWaist, "enuArmorSlots::NewEnumerator14"_s, "Back waist"_s)
|
||||
c(LeftShoulder, "enuArmorSlots::NewEnumerator15"_s, "Left shoulder"_s)
|
||||
c(RightShoulder, "enuArmorSlots::NewEnumerator16"_s, "Right shoulder"_s)
|
||||
c(LeftUpperArm, "enuArmorSlots::NewEnumerator17"_s, "Left upper arm"_s)
|
||||
c(RightUpperArm, "enuArmorSlots::NewEnumerator18"_s, "Right upper arm"_s)
|
||||
c(LeftElbow, "enuArmorSlots::NewEnumerator19"_s, "Left elbow"_s)
|
||||
c(RightElbow, "enuArmorSlots::NewEnumerator20"_s, "Right elbow"_s)
|
||||
c(LeftLowerArm, "enuArmorSlots::NewEnumerator21"_s, "Left lower arm"_s)
|
||||
c(RightLowerArm, "enuArmorSlots::NewEnumerator22"_s, "Right lower arm"_s)
|
||||
c(Backpack, "enuArmorSlots::NewEnumerator23"_s, "Backpack"_s)
|
||||
c(LeftHand, "enuArmorSlots::NewEnumerator24"_s, "Left hand"_s)
|
||||
c(RightHand, "enuArmorSlots::NewEnumerator25"_s, "Right hand"_s)
|
||||
c(LeftUpperLeg, "enuArmorSlots::NewEnumerator26"_s, "Left upper leg"_s)
|
||||
c(RightUpperLeg, "enuArmorSlots::NewEnumerator27"_s, "Right upper leg"_s)
|
||||
c(LeftKnee, "enuArmorSlots::NewEnumerator28"_s, "Left knee"_s)
|
||||
c(RightKnee, "enuArmorSlots::NewEnumerator29"_s, "Right knee"_s)
|
||||
c(LeftLowerLeg, "enuArmorSlots::NewEnumerator30"_s, "Left lower leg"_s)
|
||||
c(RightLowerLeg, "enuArmorSlots::NewEnumerator31"_s, "Right lower leg"_s)
|
||||
c(LeftAnkle, "enuArmorSlots::NewEnumerator32"_s, "Left ankle"_s)
|
||||
c(RightAnkle, "enuArmorSlots::NewEnumerator33"_s, "Right ankle"_s)
|
||||
c(LeftHeel, "enuArmorSlots::NewEnumerator34"_s, "Left heel"_s)
|
||||
c(RightHeel, "enuArmorSlots::NewEnumerator35"_s, "Right heel"_s)
|
||||
c(LeftFoot, "enuArmorSlots::NewEnumerator36"_s, "Left foot"_s)
|
||||
c(RightFoot, "enuArmorSlots::NewEnumerator37"_s, "Right foot"_s)
|
||||
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
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
// 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(NotFound, "NotARealValue"_s)
|
||||
c(ActiveOne, "enuBLAttachmentStyle::NewEnumerator0"_s)
|
||||
c(ActiveOnePerSlot, "enuBLAttachmentStyle::NewEnumerator1"_s)
|
||||
c(AllEquipped, "enuBLAttachmentStyle::NewEnumerator2"_s)
|
||||
#endif
|
|
@ -1,24 +0,0 @@
|
|||
// 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(Auto, "None"_s, "Auto"_s)
|
||||
c(Shoulders, "Shoulder"_s, "Shoulders"_s)
|
||||
c(Body, "Body"_s, "Body"_s)
|
||||
c(Backpack, "Backpack"_s, "Backpack"_s)
|
||||
c(Hip, "Hip"_s, "Hips"_s)
|
||||
c(LowerLegs, "LowerLeg"_s, "Lower legs"_s)
|
||||
#endif
|
|
@ -15,10 +15,10 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifdef c
|
||||
c(Physical, "enuDamageProperty::NewEnumerator0"_s)
|
||||
c(Piercing, "enuDamageProperty::NewEnumerator1"_s)
|
||||
c(Heat, "enuDamageProperty::NewEnumerator2"_s)
|
||||
c(Freeze, "enuDamageProperty::NewEnumerator3"_s)
|
||||
c(Shock, "enuDamageProperty::NewEnumerator4"_s)
|
||||
c(Plasma, "enuDamageProperty::NewEnumerator5"_s)
|
||||
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
|
||||
|
|
|
@ -15,6 +15,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifdef c
|
||||
c(Default, "enuWeaponEffectColorMode::NewEnumerator0"_s)
|
||||
c(Custom, "enuWeaponEffectColorMode::NewEnumerator1"_s)
|
||||
c(Default, "enuWeaponEffectColorMode::NewEnumerator0")
|
||||
c(Custom, "enuWeaponEffectColorMode::NewEnumerator1")
|
||||
#endif
|
||||
|
|
|
@ -18,44 +18,31 @@
|
|||
|
||||
#include <map>
|
||||
|
||||
#include <Corrade/Containers/StringView.h>
|
||||
|
||||
#include <Magnum/Types.h>
|
||||
|
||||
using namespace Corrade;
|
||||
using namespace Containers::Literals;
|
||||
using namespace Magnum;
|
||||
|
||||
static const std::map<Int, Containers::StringView> mission_id_map {{
|
||||
static const std::map<Int, const char*> mission_id_map {{
|
||||
// Story missions
|
||||
{0x0064, "Mission 1 - Training"_s},
|
||||
{0x0065, "Mission 2 - Patrol Operation"_s},
|
||||
{0x0066, "Mission 3 - Fusion Cells in the Snow"_s},
|
||||
{0x0067, "Mission 4 - Earning Changes"_s},
|
||||
{0x0068, "Mission 5 - Unexpected Coordination"_s},
|
||||
{0x0069, "Mission 6 - Empowering Void"_s},
|
||||
{0x006A, "Mission 7 - Logisitics Obstacles"_s},
|
||||
{0x006B, "Mission 8 - Wrath of the Wastelands"_s},
|
||||
{0x006C, "Mission 9 - Suspicious Originator"_s},
|
||||
{0x006D, "Mission 10 - Researchers Data Recovery"_s},
|
||||
{0x006E, "Mission 11 - Tempestuous Sector"_s},
|
||||
{0x006F, "Mission 12 - Clashes of Metal"_s},
|
||||
{0x0070, "Mission 13 - The Sandstorm Glutton"_s},
|
||||
{0x0071, "Mission 14 - An Icy Investigation"_s},
|
||||
{0x0072, "Mission 15 - Outposts Line of Defense"_s},
|
||||
{0x0073, "Mission 16 - Hidden in the Pass"_s},
|
||||
{0x0074, "Mission 17 - Homebase Security"_s},
|
||||
{0x0064, "Mission 1 - Training"},
|
||||
{0x0065, "Mission 2 - Patrol Operation"},
|
||||
{0x0066, "Mission 3 - Fusion Cells in the Snow"},
|
||||
{0x0067, "Mission 4 - Earning Changes"},
|
||||
{0x0068, "Mission 5 - Unexpected Coordination"},
|
||||
{0x0069, "Mission 6 - Empowering Void"},
|
||||
{0x006A, "Mission 7 - Logisitics Obstacles"},
|
||||
{0x006B, "Mission 8 - Wrath of the Wastelands"},
|
||||
{0x006C, "Mission 9 - Suspicious Originator"},
|
||||
{0x006D, "Mission 10 - Researchers Data Recovery"},
|
||||
{0x006E, "Mission 11 - Tempestuous Sector"},
|
||||
{0x006F, "Mission 12 - Clashes of Metal"},
|
||||
{0x0070, "Mission 13 - The Sandstorm Glutton"},
|
||||
{0x0071, "Mission 14 - An Icy Investigation"},
|
||||
|
||||
// Hunting grounds
|
||||
{0x00C8, "Hunt 1 - Desert Pathway Safety"_s},
|
||||
{0x00C9, "Hunt 2 - Snowfield Custodian"_s},
|
||||
{0x00CA, "Hunt 3 - Abandoned Valley Raid"_s},
|
||||
{0x00CB, "Hunt 4 - Depths of the Machineries"_s},
|
||||
{0x00CC, "Hunt 5 - Crater Crashers"_s},
|
||||
{0x00CD, "Hunt 6 - Prototype Performance Tests"_s},
|
||||
{0x00C8, "Hunt 1 - Desert Pathway Safety"},
|
||||
{0x00C9, "Hunt 2 - Snowfield Custodian"},
|
||||
{0x00CA, "Hunt 3 - Abandoned Valley Raid"},
|
||||
{0x00CB, "Hunt 4 - Depths of the Machineries"},
|
||||
|
||||
// Challenges
|
||||
{0x012C, "Challenge 1 - Redline Battlefront"_s},
|
||||
{0x0140, "Challenge 2 - Void Convergence"_s},
|
||||
{0x0190, "Challenge 3 - Gates of Ascension"_s}
|
||||
{0x012C, "Challenge 1 - Redline Battlefront"},
|
||||
{0x0140, "Challenge 2 - Void Convergence"},
|
||||
{0x0190, "Challenge 3 - Gates of Ascension"}
|
||||
}};
|
||||
|
|
|
@ -17,98 +17,78 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include <Corrade/Containers/Array.h>
|
||||
#include <Corrade/Containers/StringView.h>
|
||||
|
||||
#include <Magnum/Types.h>
|
||||
|
||||
using namespace Corrade;
|
||||
using namespace Containers::Literals;
|
||||
using namespace Magnum;
|
||||
|
||||
struct StoryProgressPoint {
|
||||
Int id;
|
||||
Containers::StringView chapter;
|
||||
Containers::StringView point;
|
||||
Containers::StringView after = nullptr;
|
||||
const char* chapter;
|
||||
const char* point;
|
||||
const char* after = nullptr;
|
||||
};
|
||||
|
||||
static const Corrade::Containers::Array<StoryProgressPoint> story_progress
|
||||
{
|
||||
InPlaceInit,
|
||||
{
|
||||
{0x0000, "Chapter 1"_s, "Chapter start (company isn't named yet)"_s},
|
||||
{0x0064, "Chapter 1"_s, "First time in the hangar"_s},
|
||||
{0x0065, "Chapter 1"_s, "After 1st meeting with Quin in mission section"_s},
|
||||
{0x0066, "Chapter 1"_s, "Talking with Reina and Quin in hangar"_s, "After training"_s},
|
||||
{0x0067, "Chapter 1"_s, "Returned to hangar"_s, "After training"_s},
|
||||
{0x0068, "Chapter 1"_s, "Talked with Quin in development section"_s, "After training"_s},
|
||||
{0x0069, "Chapter 1"_s, "Talked with Waltz in armour section"_s, "After training"_s},
|
||||
{0x00C8, "Chapter 1"_s, "Talked with Kael in tuning section"_s, "After training"_s},
|
||||
{0x00C9, "Chapter 1"_s, "Got mission 2 briefing"_s, "After training"_s},
|
||||
{0x012C, "Chapter 1"_s, "Talking with Reina"_s, "After mission 2"_s},
|
||||
{0x012D, "Chapter 1"_s, "Returned to hangar"_s, "After mission 2"_s},
|
||||
{0x012E, "Chapter 1"_s, "Talked with Kael in tuning section"_s, "After mission 2"_s},
|
||||
{0x012F, "Chapter 1"_s, "Talked with Reina in hangar"_s, "After mission 2"_s},
|
||||
{0x0130, "Chapter 1"_s, "Got mission 3 briefing"_s, "After mission 2"_s},
|
||||
{0x0190, "Chapter 1"_s, "Talking with Reina"_s, "After mission 3"_s},
|
||||
{0x0191, "Chapter 1"_s, "Returned to hangar"_s, "After mission 3"_s},
|
||||
{0x0192, "Chapter 1"_s, "Talked with Waltz in armour section"_s, "After mission 3"_s},
|
||||
{0x0193, "Chapter 1"_s, "Got mission 4 briefing"_s, "After mission 3"_s},
|
||||
{0x01F4, "Chapter 1"_s, "Talking with Reina"_s, "After mission 4"_s},
|
||||
{0x01F5, "Chapter 1"_s, "Returned to hangar"_s, "After mission 4"_s},
|
||||
{0x01F6, "Chapter 1"_s, "Talked with Waltz in armour section"_s, "After mission 4"_s},
|
||||
{0x01F7, "Chapter 1"_s, "Talked with Reina in hangar"_s, "After mission 4"_s},
|
||||
{0x01F8, "Chapter 1"_s, "Got mission 5 and hunt 1 briefing"_s, "After mission 4"_s},
|
||||
{0x0258, "Chapter 1"_s, "Meeting Neon and Aine"_s, "After mission 5"_s},
|
||||
{0x0259, "Chapter 1"_s, "Returned to hangar"_s, "After mission 5"_s},
|
||||
{0x025A, "Chapter 1"_s, "Got mission 6 briefing"_s, "After mission 5"_s},
|
||||
{0x02BC, "Chapter 1"_s, "Talking with Reina"_s, "After mission 6"_s},
|
||||
{0x02BD, "Chapter 1"_s, "Returned to hangar"_s, "After mission 6"_s},
|
||||
{0x02BE, "Chapter 1"_s, "Got hunt 2 briefing"_s, "After mission 6"_s},
|
||||
{0x02BF, "Chapter 1"_s, "Met Ellenier"_s, "After mission 6"_s},
|
||||
{0x02C0, "Chapter 1"_s, "Got mission 7 briefing"_s, "After mission 6"_s},
|
||||
{0x0320, "Chapter 1"_s, "Talking with Nier"_s, "After mission 7"_s},
|
||||
{0x0321, "Chapter 1"_s, "Returned to hangar"_s, "After mission 7"_s},
|
||||
{0x0322, "Chapter 1"_s, "Talked with Quin, Reina, and Nier in development section"_s, "After mission 7"_s},
|
||||
{0x0323, "Chapter 1"_s, "Got mission 8 briefing"_s, "After mission 7"_s},
|
||||
{0x0384, "Chapter 1"_s, "Talking with crew in hangar"_s, "After mission 8"_s},
|
||||
{0x0385, "Chapter 1"_s, "Returned to hangar"_s, "After mission 8"_s},
|
||||
{0x0386, "Chapter 1"_s, "Got hunt 3 briefing"_s, "After mission 8"_s},
|
||||
{0x0387, "Chapter 1"_s, "Talked with Reina, Nier, and Quin in development section"_s, "After mission 8"_s},
|
||||
{0x0000, "Chapter 1", "Chapter start (company isn't named yet)"},
|
||||
{0x0064, "Chapter 1", "First time in the hangar"},
|
||||
{0x0065, "Chapter 1", "After 1st meeting with Quin in mission section"},
|
||||
{0x0066, "Chapter 1", "Talking with Reina and Quin in hangar", "After training"},
|
||||
{0x0067, "Chapter 1", "Returned to hangar", "After training"},
|
||||
{0x0068, "Chapter 1", "Talked with Quin in development section", "After training"},
|
||||
{0x0069, "Chapter 1", "Talked with Waltz in armour section", "After training"},
|
||||
{0x00C8, "Chapter 1", "Talked with Kael in tuning section", "After training"},
|
||||
{0x00C9, "Chapter 1", "Got mission 2 briefing", "After training"},
|
||||
{0x012C, "Chapter 1", "Talking with Reina", "After mission 2"},
|
||||
{0x012D, "Chapter 1", "Returned to hangar", "After mission 2"},
|
||||
{0x012E, "Chapter 1", "Talked with Kael in tuning section", "After mission 2"},
|
||||
{0x012F, "Chapter 1", "Talked with Reina in hangar", "After mission 2"},
|
||||
{0x0130, "Chapter 1", "Got mission 3 briefing", "After mission 2"},
|
||||
{0x0190, "Chapter 1", "Talking with Reina", "After mission 3"},
|
||||
{0x0191, "Chapter 1", "Returned to hangar", "After mission 3"},
|
||||
{0x0192, "Chapter 1", "Talked with Waltz in armour section", "After mission 3"},
|
||||
{0x0193, "Chapter 1", "Got mission 4 briefing", "After mission 3"},
|
||||
{0x01F4, "Chapter 1", "Talking with Reina", "After mission 4"},
|
||||
{0x01F5, "Chapter 1", "Returned to hangar", "After mission 4"},
|
||||
{0x01F6, "Chapter 1", "Talked with Waltz in armour section", "After mission 4"},
|
||||
{0x01F7, "Chapter 1", "Talked with Reina in hangar", "After mission 4"},
|
||||
{0x01F8, "Chapter 1", "Got mission 5 and hunt 1 briefing", "After mission 4"},
|
||||
{0x0258, "Chapter 1", "Meeting Neon and Aine", "After mission 5"},
|
||||
{0x0259, "Chapter 1", "Returned to hangar", "After mission 5"},
|
||||
{0x025A, "Chapter 1", "Got mission 6 briefing", "After mission 5"},
|
||||
{0x02BC, "Chapter 1", "Talking with Reina", "After mission 6"},
|
||||
{0x02BD, "Chapter 1", "Returned to hangar", "After mission 6"},
|
||||
{0x02BE, "Chapter 1", "Got hunt 2 briefing", "After mission 6"},
|
||||
{0x02BF, "Chapter 1", "Met Ellenier", "After mission 6"},
|
||||
{0x02C0, "Chapter 1", "Got mission 7 briefing", "After mission 6"},
|
||||
{0x0320, "Chapter 1", "Talking with Nier", "After mission 7"},
|
||||
{0x0321, "Chapter 1", "Returned to hangar", "After mission 7"},
|
||||
{0x0322, "Chapter 1", "Talked with Quin, Reina, and Nier in development section", "After mission 7"},
|
||||
{0x0323, "Chapter 1", "Got mission 8 briefing", "After mission 7"},
|
||||
{0x0384, "Chapter 1", "Talking with crew in hangar", "After mission 8"},
|
||||
{0x0385, "Chapter 1", "Returned to hangar", "After mission 8"},
|
||||
{0x0386, "Chapter 1", "Got hunt 3 briefing", "After mission 8"},
|
||||
{0x0387, "Chapter 1", "Talked with Reina, Nier, and Quin in development section", "After mission 8"},
|
||||
|
||||
{0x0388, "Chapter 2"_s, "Chapter start"_s},
|
||||
{0x0389, "Chapter 2"_s, "Got mission 9 briefing"_s},
|
||||
{0x03E8, "Chapter 2"_s, "Talking with Reina in hangar"_s, "After mission 9"_s},
|
||||
{0x03E9, "Chapter 2"_s, "Returned to hangar"_s, "After mission 9"_s},
|
||||
{0x03EA, "Chapter 2"_s, "Talked with crew in armour section"_s, "After mission 9"_s},
|
||||
{0x03EB, "Chapter 2"_s, "Got mission 10 briefing"_s, "After mission 9"_s},
|
||||
{0x044C, "Chapter 2"_s, "Talking with Reina in hangar"_s, "After mission 10"_s},
|
||||
{0x044D, "Chapter 2"_s, "Returned to hangar"_s, "After mission 10"_s},
|
||||
{0x044E, "Chapter 2"_s, "Got mission 11 briefing"_s, "After mission 10"_s},
|
||||
{0x04B0, "Chapter 2"_s, "Talking with Reina and Nier in hangar"_s, "After mission 11"_s},
|
||||
{0x04B1, "Chapter 2"_s, "Returned to hangar"_s, "After mission 11"_s},
|
||||
{0x04B2, "Chapter 2"_s, "Got mission 12 briefing"_s, "After mission 11"_s},
|
||||
{0x0514, "Chapter 2"_s, "Talking with Reina and Waltz in hangar"_s, "After mission 12"_s},
|
||||
{0x0515, "Chapter 2"_s, "Returned to hangar"_s, "After mission 12"_s},
|
||||
{0x0516, "Chapter 2"_s, "Got hunt 4 and mission 13 briefing"_s, "After mission 12"_s},
|
||||
|
||||
{0x0578, "Chapter 3"_s, "Chapter start, talking with Reina"_s, "After mission 13"_s},
|
||||
{0x0579, "Chapter 3"_s, "Returned to hangar"_s, "After mission 13"_s},
|
||||
{0x057A, "Chapter 3"_s, "Talked with Reina in development section"_s, "After mission 13"_s},
|
||||
{0x057B, "Chapter 3"_s, "Got briefing for challenges 1, 2, and 3"_s, "After mission 13"_s},
|
||||
{0x057C, "Chapter 3"_s, "Talked with Reina about device"_s, "After mission 13"_s},
|
||||
{0x057D, "Chapter 3"_s, "Got mission 14 briefing"_s, "After mission 13"_s},
|
||||
{0x05DC, "Chapter 3"_s, "Talking with Reina and Nier"_s, "After mission 14"_s},
|
||||
{0x05DD, "Chapter 3"_s, "Returned to hangar"_s, "After mission 14"_s},
|
||||
{0x05DE, "Chapter 3"_s, "Got briefing for mission 15 and hunt 5"_s, "After mission 14"_s},
|
||||
{0x0640, "Chapter 3"_s, "Talking with Nier and Kazu, and Reina"_s, "After mission 15"_s},
|
||||
{0x0641, "Chapter 3"_s, "Returned to hangar"_s, "After mission 15"_s},
|
||||
{0x0642, "Chapter 3"_s, "Talked with Reina and Nier in dev section"_s, "After mission 15"_s},
|
||||
{0x0643, "Chapter 3"_s, "Got briefing for mission 16"_s, "After mission 15"_s},
|
||||
{0x06A4, "Chapter 3"_s, "Talking with Kunai"_s, "After mission 16"_s},
|
||||
{0x06A5, "Chapter 3"_s, "Returned to hangar"_s, "After mission 16"_s},
|
||||
{0x06A6, "Chapter 3"_s, "Got mission 17 briefing"_s, "After mission 16"_s},
|
||||
{0x0708, "Chapter 3"_s, "Debriefing"_s, "After mission 17"_s},
|
||||
{0x070A, "Chapter 3"_s, "Got hunt 6 briefing"_s, "After mission 17"_s},
|
||||
{0x0388, "Chapter 2", "Chapter start"},
|
||||
{0x0389, "Chapter 2", "Got mission 9 briefing"},
|
||||
{0x03E8, "Chapter 2", "Talking with Reina in hangar", "After mission 9"},
|
||||
{0x03E9, "Chapter 2", "Returned to hangar", "After mission 9"},
|
||||
{0x03EA, "Chapter 2", "Talked with crew in armour section", "After mission 9"},
|
||||
{0x03EB, "Chapter 2", "Got mission 10 briefing", "After mission 9"},
|
||||
{0x044C, "Chapter 2", "Talking with Reina in hangar", "After mission 10"},
|
||||
{0x044D, "Chapter 2", "Returned to hangar", "After mission 10"},
|
||||
{0x044E, "Chapter 2", "Got mission 11 briefing", "After mission 10"},
|
||||
{0x04B0, "Chapter 2", "Talking with Reina and Nier in hangar", "After mission 11"},
|
||||
{0x04B1, "Chapter 2", "Returned to hangar", "After mission 11"},
|
||||
{0x04B2, "Chapter 2", "Got mission 12 briefing", "After mission 11"},
|
||||
{0x0514, "Chapter 2", "Talking with Reina and Waltz in hangar", "After mission 12"},
|
||||
{0x0515, "Chapter 2", "Returned to hangar", "After mission 12"},
|
||||
{0x0516, "Chapter 2", "Got hunt 4 and mission 13 briefing", "After mission 12"},
|
||||
{0x0578, "Chapter 2", "Talking with Reina in 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"},
|
||||
{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"},
|
||||
}
|
||||
};
|
||||
|
|
|
@ -18,179 +18,175 @@
|
|||
|
||||
#include <map>
|
||||
|
||||
#include <Corrade/Containers/StringView.h>
|
||||
|
||||
#include <Magnum/Magnum.h>
|
||||
|
||||
using namespace Corrade;
|
||||
using namespace Containers::Literals;
|
||||
using namespace Magnum;
|
||||
|
||||
extern const std::map<Int, Containers::StringView> style_names
|
||||
extern const std::map<Int, const char*> style_names
|
||||
#ifdef STYLENAMES_DEFINITION
|
||||
{
|
||||
{0, "Custom Style 1"_s},
|
||||
{1, "Custom Style 2"_s},
|
||||
{2, "Custom Style 3"_s},
|
||||
{3, "Custom Style 4"_s},
|
||||
{4, "Custom Style 5"_s},
|
||||
{5, "Custom Style 6"_s},
|
||||
{6, "Custom Style 7"_s},
|
||||
{7, "Custom Style 8"_s},
|
||||
{8, "Custom Style 9"_s},
|
||||
{9, "Custom Style 10"_s},
|
||||
{10, "Custom Style 11"_s},
|
||||
{11, "Custom Style 12"_s},
|
||||
{12, "Custom Style 13"_s},
|
||||
{13, "Custom Style 14"_s},
|
||||
{14, "Custom Style 15"_s},
|
||||
{15, "Custom Style 16"_s},
|
||||
{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"_s},
|
||||
{51, "Global Style 2"_s},
|
||||
{52, "Global Style 3"_s},
|
||||
{53, "Global Style 4"_s},
|
||||
{54, "Global Style 5"_s},
|
||||
{55, "Global Style 6"_s},
|
||||
{56, "Global Style 7"_s},
|
||||
{57, "Global Style 8"_s},
|
||||
{58, "Global Style 9"_s},
|
||||
{59, "Global Style 10"_s},
|
||||
{60, "Global Style 11"_s},
|
||||
{61, "Global Style 12"_s},
|
||||
{62, "Global Style 13"_s},
|
||||
{63, "Global Style 14"_s},
|
||||
{64, "Global Style 15"_s},
|
||||
{65, "Global Style 16"_s},
|
||||
{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"_s},
|
||||
{101, "Silver"_s},
|
||||
{102, "Gold"_s},
|
||||
{103, "Bronze"_s},
|
||||
{104, "Copper"_s},
|
||||
{105, "Nickel"_s},
|
||||
{106, "Cobalt"_s},
|
||||
{107, "Aluminium"_s},
|
||||
{108, "Titanium"_s},
|
||||
{109, "Platinum"_s},
|
||||
{110, "Gun Metal"_s},
|
||||
{111, "White"_s},
|
||||
{112, "White Metal"_s},
|
||||
{113, "White Gloss"_s},
|
||||
{114, "Grey"_s},
|
||||
{115, "Grey Metal"_s},
|
||||
{116, "Grey Gloss"_s},
|
||||
{117, "Dark Grey"_s},
|
||||
{118, "Dark Grey Metal"_s},
|
||||
{119, "Dark Grey Gloss"_s},
|
||||
{120, "Black"_s},
|
||||
{121, "Black Metal"_s},
|
||||
{122, "Black Gloss"_s},
|
||||
{123, "Red"_s},
|
||||
{124, "Red Metal"_s},
|
||||
{125, "Red Gloss"_s},
|
||||
{126, "Dark Red"_s},
|
||||
{127, "Dark Red Metal"_s},
|
||||
{128, "Dark Red Gloss"_s},
|
||||
{129, "Orange"_s},
|
||||
{130, "Orange Metal"_s},
|
||||
{131, "Orange Gloss"_s},
|
||||
{132, "Dark Orange"_s},
|
||||
{133, "Dark Orange Metal"_s},
|
||||
{134, "Dark Orange Gloss"_s},
|
||||
{135, "Yellow"_s},
|
||||
{136, "Yellow Metal"_s},
|
||||
{137, "Yellow Gloss"_s},
|
||||
{138, "Brown"_s},
|
||||
{139, "Brown Metal"_s},
|
||||
{140, "Brown Gloss"_s},
|
||||
{141, "Dark Brown"_s},
|
||||
{142, "Dark Brown Metal"_s},
|
||||
{143, "Dark Brown Gloss"_s},
|
||||
{144, "Leafgreen"_s},
|
||||
{145, "Leafgreen Metal"_s},
|
||||
{146, "Leafgreen Gloss"_s},
|
||||
{147, "Military Green"_s},
|
||||
{148, "Military Green Metal"_s},
|
||||
{149, "Military Green Gloss"_s},
|
||||
{150, "Green"_s},
|
||||
{151, "Green Metal"_s},
|
||||
{152, "Green Gloss"_s},
|
||||
{153, "Dark Green"_s},
|
||||
{154, "Dark Green Metal"_s},
|
||||
{155, "Dark Green Gloss"_s},
|
||||
{156, "Teal"_s},
|
||||
{157, "Teal Metal"_s},
|
||||
{158, "Teal Gloss"_s},
|
||||
{159, "Cyan"_s},
|
||||
{160, "Cyan Metal"_s},
|
||||
{161, "Cyan Gloss"_s},
|
||||
{162, "Blue"_s},
|
||||
{163, "Blue Metal"_s},
|
||||
{164, "Blue Gloss"_s},
|
||||
{165, "Blue Sky"_s},
|
||||
{166, "Blue Sky Metal"_s},
|
||||
{167, "Blue Sky Gloss"_s},
|
||||
{168, "Dark Blue"_s},
|
||||
{169, "Dark Blue Metal"_s},
|
||||
{170, "Dark Blue Gloss"_s},
|
||||
{171, "Purple"_s},
|
||||
{172, "Purple Metal"_s},
|
||||
{173, "Purple Gloss"_s},
|
||||
{174, "Dark Purple"_s},
|
||||
{175, "Dark Purple Metal"_s},
|
||||
{176, "Dark Purple Gloss"_s},
|
||||
{177, "Pink"_s},
|
||||
{178, "Pink Metal"_s},
|
||||
{179, "Pink Gloss"_s},
|
||||
{180, "Rosy Brown"_s},
|
||||
{181, "Rosy Brown Metal"_s},
|
||||
{182, "Rosy Brown Gloss"_s},
|
||||
{183, "Ivory"_s},
|
||||
{184, "Ivory Metal"_s},
|
||||
{185, "Ivory Gloss"_s},
|
||||
{186, "Slate Brown"_s},
|
||||
{187, "Slate Brown Metal"_s},
|
||||
{188, "Slate Brown Gloss"_s},
|
||||
{189, "Slate Green"_s},
|
||||
{190, "Slate Green Metal"_s},
|
||||
{191, "Slate Green Gloss"_s},
|
||||
{192, "Slate Blue"_s},
|
||||
{193, "Slate Blue Metal"_s},
|
||||
{194, "Slate Blue Gloss"_s},
|
||||
{195, "Slate Purple"_s},
|
||||
{196, "Slate Purple Metal"_s},
|
||||
{197, "Slate Purple Gloss"_s},
|
||||
{198, "White Glow"_s},
|
||||
{199, "White Radiance"_s},
|
||||
{200, "Red Glow"_s},
|
||||
{201, "Red Radiance"_s},
|
||||
{202, "Orange Glow"_s},
|
||||
{203, "Orange Radiance"_s},
|
||||
{204, "Yellow Glow"_s},
|
||||
{205, "Yellow Radiance"_s},
|
||||
{206, "Leafgreen Glow"_s},
|
||||
{207, "Leafgreen Radiance"_s},
|
||||
{208, "Green Glow"_s},
|
||||
{209, "Green Radiance"_s},
|
||||
{210, "Teal Glow"_s},
|
||||
{211, "Teal Radiance"_s},
|
||||
{212, "Cyan Glow"_s},
|
||||
{213, "Cyan Radiance"_s},
|
||||
{214, "Blue Glow"_s},
|
||||
{215, "Blue Radiance"_s},
|
||||
{216, "Purple Glow"_s},
|
||||
{217, "Purple Radiance"_s},
|
||||
{218, "Pink Glow"_s},
|
||||
{219, "Pink Radiance"_s},
|
||||
{220, "Grey Camo"_s},
|
||||
{221, "Dark Grey Camo"_s},
|
||||
{222, "Green Camo"_s},
|
||||
{223, "Dark Green Camo"_s},
|
||||
{224, "Brown Camo"_s},
|
||||
{225, "Dark Brown Camo"_s},
|
||||
{226, "Blue Camo"_s},
|
||||
{227, "Dark Blue Camo"_s},
|
||||
{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
|
||||
;
|
||||
|
|
|
@ -1,433 +0,0 @@
|
|||
#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 <Corrade/Containers/StringView.h>
|
||||
|
||||
#include <Magnum/Types.h>
|
||||
|
||||
using namespace Corrade;
|
||||
using namespace Magnum;
|
||||
|
||||
using namespace Containers::Literals;
|
||||
|
||||
// region Melee
|
||||
static const std::map<Int, Containers::StringView> melee_grips {
|
||||
{0, "Combat Grip (1H)"_s},
|
||||
{1, "Knuckle Guard Grip (1H)"_s},
|
||||
{2, "Dual Guard Grip (1H)"_s},
|
||||
{3, "Sepal Grip (1H)"_s},
|
||||
{4, "Warrior Grip (1H)"_s},
|
||||
{5, "Guardian Grip (1H)"_s},
|
||||
{6, "Knight Guard Grip (1H)"_s},
|
||||
{7, "Saber Guard Grip (1H)"_s},
|
||||
|
||||
{100, "Combat Side Grip (1H)"_s},
|
||||
{101, "Hollowed Side Grip (1H)"_s},
|
||||
{102, "Pulled Back Side Grip (1H)"_s},
|
||||
{103, "Plated Side Grip (1H)"_s},
|
||||
{104, "Locked Side Grip (1H)"_s},
|
||||
{105, "Longpoint Side Grip (1H)"_s},
|
||||
|
||||
{200, "Combat Dual Grip (1H)"_s},
|
||||
{201, "Hollowed Dual Grip (1H)"_s},
|
||||
{202, "Plated Dual Grip (1H)"_s},
|
||||
|
||||
{400, "Combat Twin Grip (1H)"_s},
|
||||
{401, "Sepal Twin Grip (1H)"_s},
|
||||
{402, "Hollowed Twin Grip (1H)"_s},
|
||||
{403, "Knuckle Guard Twin Grip (1H)"_s},
|
||||
{404, "Arched Twin Grip (1H)"_s},
|
||||
|
||||
{1000, "Combat Knuckle (R/L)"_s},
|
||||
{1001, "Battle Fist (R/L)"_s},
|
||||
{1002, "Guard Knuckle (R/L)"_s},
|
||||
|
||||
{2000, "Combat Polearm (2H)"_s},
|
||||
{2001, "Dual Guard Polearm (2H)"_s},
|
||||
{2002, "Sepal Polearm (2H)"_s},
|
||||
{2003, "Fin Polearm (2H)"_s},
|
||||
{2004, "Arched Polearm (2H)"_s},
|
||||
|
||||
{2100, "Combat Side Polearm (2H)"_s},
|
||||
{2101, "Plated Side Polearm (2H)"_s},
|
||||
{2102, "Locked Side Polearm (2H)"_s},
|
||||
{2103, "Fin Side Polearm (2H)"_s},
|
||||
|
||||
{2200, "Combat Dual Polearm (2H)"_s},
|
||||
|
||||
{2400, "Combat Twin Blade (2H)"_s},
|
||||
{2401, "Guard Twin Blade (2H)"_s},
|
||||
{2402, "Sepal Twin Blade (2H)"_s},
|
||||
{2403, "Fin Twin Blade (2H)"_s},
|
||||
{2404, "Arched Twin Blade (2H)"_s},
|
||||
};
|
||||
|
||||
static const std::map<Int, Containers::StringView> melee_assaulters {
|
||||
{0, "Long Metal Blade"_s},
|
||||
{1, "Long Assault Blade"_s},
|
||||
{2, "Long Fin Blade"_s},
|
||||
{3, "Long Double Blades"_s},
|
||||
{4, "Long Straight Blade"_s},
|
||||
{5, "Long Faceted Blade"_s},
|
||||
{6, "Long Interlocked Blade"_s},
|
||||
{7, "Long Frontbreak Blade"_s},
|
||||
{8, "Long Encased Blade"_s},
|
||||
{9, "Long Flat Gouger"_s},
|
||||
{10, "Long Curved Blade"_s},
|
||||
{11, "Long Broad Blade"_s},
|
||||
|
||||
{20, "Long Combat Edge"_s},
|
||||
{21, "Long Attached Edge"_s},
|
||||
|
||||
{40, "Katana Blade"_s},
|
||||
{41, "Custom Katana Blade"_s},
|
||||
|
||||
{60, "Energy Blade (Motion)"_s},
|
||||
{61, "Powered Blade"_s},
|
||||
|
||||
{100, "Short Metal Blade"_s},
|
||||
{101, "Short Assault Blade"_s},
|
||||
{102, "Short Fin Blade"_s},
|
||||
|
||||
{120, "Short Combat Edge"_s},
|
||||
|
||||
{160, "Short Energy Blade (Motion)"_s},
|
||||
{161, "Short Powered Blade"_s},
|
||||
|
||||
{180, "Triclaw"_s},
|
||||
{181, "Straight Triclaw"_s},
|
||||
{182, "Griphold Claw"_s},
|
||||
{183, "Energy Claw"_s},
|
||||
{184, "Openhold Claw"_s},
|
||||
{185, "Hooktusk Claw"_s},
|
||||
|
||||
{200, "Bracer"_s},
|
||||
{201, "Custom Bracer"_s},
|
||||
|
||||
{210, "Expanded Bracer"_s},
|
||||
{211, "Expanded Custom Bracer"_s},
|
||||
|
||||
{300, "Heavy Smasher"_s},
|
||||
{301, "Heavy Basher"_s},
|
||||
{302, "Heavy Torch Mace"_s},
|
||||
|
||||
{400, "Light Smasher"_s},
|
||||
{401, "Light Basher"_s},
|
||||
{402, "Light Torch Mace"_s},
|
||||
|
||||
{420, "War Hammer"_s},
|
||||
{421, "Great Hammer"_s},
|
||||
{422, "Spiked Hammer"_s},
|
||||
{423, "Broadhead Hammer"_s},
|
||||
|
||||
{440, "Morning Star"_s},
|
||||
{441, "Spike Ball"_s},
|
||||
|
||||
{500, "Combat Lance"_s},
|
||||
{501, "Gouger Lance"_s},
|
||||
|
||||
{510, "Piercer"_s},
|
||||
|
||||
{600, "Short Combat Lance"_s},
|
||||
|
||||
{605, "Short Combat Drill (Motion)"_s},
|
||||
|
||||
{610, "Short Piercer"_s},
|
||||
|
||||
{700, "Combat Axe"_s},
|
||||
{701, "Custom Combat Axe"_s},
|
||||
{702, "Piercing Axe"_s},
|
||||
{703, "Frontbreak Axe"_s},
|
||||
{704, "Maiming Axe"_s},
|
||||
{705, "Delta Axe"_s},
|
||||
|
||||
{800, "Combat Scythe"_s},
|
||||
{801, "Reaper Blade"_s},
|
||||
{802, "Clawtooth Scythe"_s},
|
||||
{803, "Wingpoint Scythe"_s},
|
||||
{804, "Snakebone Scythe"_s},
|
||||
|
||||
{900, "Short Combat Scythe"_s},
|
||||
{901, "Short Reaper Blade"_s},
|
||||
{902, "Short Clawtooth Scythe"_s},
|
||||
{903, "Short Wingpoint Scythe"_s},
|
||||
{904, "Short Snakebone Scythe"_s},
|
||||
};
|
||||
// endregion
|
||||
|
||||
// region Shields
|
||||
static const std::map<Int, Containers::StringView> shield_handles {
|
||||
{0, "Balanced Handle"_s},
|
||||
{1, "Expanded Handle"_s},
|
||||
{2, "Lowguard Handle"_s},
|
||||
{3, "Longblocker Handle"_s},
|
||||
{4, "Winged Handle"_s},
|
||||
{5, "Stopper Handle"_s},
|
||||
{6, "Layered Handle"_s},
|
||||
{7, "Riotguard Handle"_s},
|
||||
{8, "Blitz Handle"_s},
|
||||
{9, "Foldable Handle"_s},
|
||||
{10, "Board Handle"_s},
|
||||
{11, "Knight Handle"_s},
|
||||
{12, "Cargwall Handle"_s},
|
||||
|
||||
{100, "Buckler Handle"_s},
|
||||
{101, "Star Handle"_s},
|
||||
};
|
||||
|
||||
static const std::map<Int, Containers::StringView> shield_shells {
|
||||
{0, "Balanced Shell"_s},
|
||||
{1, "Compass Shell"_s},
|
||||
{2, "Uppoint Shell"_s},
|
||||
{3, "Pointed Shell"_s},
|
||||
{4, "Padded Shell"_s},
|
||||
{5, "Pincer Shell"_s},
|
||||
{6, "Fang Shell"_s},
|
||||
{7, "Holder Shell"_s},
|
||||
{8, "Composite Shell"_s},
|
||||
{9, "Mechanical Shell"_s},
|
||||
{10, "Layered Shell"_s},
|
||||
{11, "Parted Shell"_s},
|
||||
{12, "Tapst Shell"_s},
|
||||
{13, "Sidloc Shell"_s},
|
||||
|
||||
{100, "V-Cross Shell"_s},
|
||||
};
|
||||
// endregion
|
||||
|
||||
// region Bullet Shooters
|
||||
static const std::map<Int, Containers::StringView> bshooter_triggers {
|
||||
{0, "BL-Combat Trigger (1H)"_s},
|
||||
{1, "Light Machine Trigger (1H)"_s},
|
||||
{2, "Tactical Trigger (1H)"_s},
|
||||
{3, "Compact Trigger (1H)"_s},
|
||||
{4, "Longhold Trigger (1H)"_s},
|
||||
{5, "Downhold Trigger (1H)"_s},
|
||||
{6, "Cellblock Trigger (1H)"_s},
|
||||
{99, "Base Trigger (1H)"_s},
|
||||
|
||||
{100, "BL-Machine Trigger (2H)"_s},
|
||||
{101, "BL-Short Trigger (2H)"_s},
|
||||
{102, "Shielded Trigger (2H)"_s},
|
||||
{103, "Platedframe Trigger (2H)"_s},
|
||||
{104, "Sidebox Trigger (2H) (Motion)"_s},
|
||||
{199, "2H Base Trigger (2H)"_s},
|
||||
};
|
||||
|
||||
static const std::map<Int, Containers::StringView> bshooter_barrels {
|
||||
{0, "BL-Combat Barrel (1 shot)"_s},
|
||||
{1, "Shock Absorb Barrel (1 shot) (Motion)"_s},
|
||||
{2, "Muzzlemod Barrel (1 shot)"_s},
|
||||
{3, "Triangular Barrel (1 shot)"_s},
|
||||
{4, "Recoilblock Barrel (1 shot) (Motion)"_s},
|
||||
{97, "Short S Base Barrel (1 shot)"_s},
|
||||
{98, "Medium S Base Barrel (1 shot)"_s},
|
||||
{99, "Long S Base Barrel (1 shot)"_s},
|
||||
|
||||
{100, "Six-Barrel Gatling (Auto) (Motion)"_s},
|
||||
{101, "Modded Six-Barrel Gatling (Auto) (Motion)"_s},
|
||||
{102, "Four-Barrel Gatling (Auto) (Motion)"_s},
|
||||
{103, "Retro Style Gatling (Auto) (Motion)"_s},
|
||||
{197, "Short G Base Barrel (Auto)"_s},
|
||||
{198, "Medium G Base Barrel (Auto)"_s},
|
||||
{199, "Long G Base Barrel (Auto)"_s},
|
||||
|
||||
{200, "Blast Barrel (Spread)"_s},
|
||||
{201, "Wideblast Barrel (Spread) (Motion)"_s},
|
||||
{202, "Pelleter Barrel (Spread) (Motion)"_s},
|
||||
{203, "Lockhold Barrel (Spread) (Motion)"_s},
|
||||
{297, "Short B Base Barrel (Spread)"_s},
|
||||
{298, "Medium B Base Barrel (Spread)"_s},
|
||||
{299, "Long B Base Barrel (Spread)"_s},
|
||||
|
||||
{300, "Propulsive Barrel (Detonate)"_s},
|
||||
{301, "Roundbox Barrel (Detonate)"_s},
|
||||
{302, "ShieldDet Barrel (Detonate)"_s},
|
||||
{303, "RecoilDet Barrel (Detonate) (Motion)"_s},
|
||||
{397, "Short D Base Barrel (Detonate)"_s},
|
||||
{398, "Medium D Base Barrel (Detonate)"_s},
|
||||
{399, "Long D Base Barrel (Detonate)"_s},
|
||||
};
|
||||
// endregion
|
||||
|
||||
//region Energy Shooters
|
||||
static const std::map<Int, Containers::StringView> eshooter_triggers {
|
||||
{0, "EN-Rifle Trigger (1H)"_s},
|
||||
{1, "Underarm Trigger (1H)"_s},
|
||||
{2, "EN-Inverted Trigger (1H)"_s},
|
||||
{3, "EN-Submachine Trigger (1H) (Motion)"_s},
|
||||
{4, "EN-Needler Trigger (1H)"_s},
|
||||
{5, "Angular Trigger (1H)"_s},
|
||||
{6, "Exposed Trigger (1H)"_s},
|
||||
{99, "Base EnTrigger (1H)"_s},
|
||||
|
||||
{100, "EN-Combat Trigger (2H)"_s},
|
||||
{101, "EN-Alternate Trigger (2H)"_s},
|
||||
{102, "Framed Trigger (2H) (Motion)"_s},
|
||||
{103, "Stabilised Trigger (2H)"_s},
|
||||
{104, "EN-Heavy Trigger (2H)"_s},
|
||||
{199, "2H Base EnTrigger (2H)"_s},
|
||||
};
|
||||
|
||||
static const std::map<Int, Containers::StringView> eshooter_busters {
|
||||
{0, "EN-Combat Buster (1 shot)"_s},
|
||||
{1, "Delta Cycler (1 shot) (Motion)"_s},
|
||||
{2, "EN-Longbarrel Buster (1 shot)"_s},
|
||||
{3, "Kinetic Buster (1 shot) (Motion)"_s},
|
||||
{97, "Short S Base Buster (1 shot)"_s},
|
||||
{98, "Medium S Base Buster (1 shot)"_s},
|
||||
{99, "Long S Base Buster (1 shot)"_s},
|
||||
|
||||
{100, "EN-Rifle Buster (Auto)"_s},
|
||||
{101, "EN-Focus Buster (Auto)"_s},
|
||||
{102, "Machinist Buster (Auto)"_s},
|
||||
{103, "EN-Precision Buster (Auto) (Motion)"_s},
|
||||
{197, "Short A Base Buster (Auto)"_s},
|
||||
{198, "Medium A Base Buster (Auto)"_s},
|
||||
{199, "Long A Base Buster (Auto)"_s},
|
||||
|
||||
{200, "Railcharge Buster (Ray) (Motion)"_s},
|
||||
{201, "Clawcharge Buster (Ray)"_s},
|
||||
{202, "Twizelcharge Buster (Ray)"_s},
|
||||
{203, "Deltacharge Buster (Ray)"_s},
|
||||
{297, "Short R Base Buster (Ray)"_s},
|
||||
{298, "Medium R Base Buster (Ray)"_s},
|
||||
{299, "Long R Base Buster (Ray)"_s},
|
||||
|
||||
{300, "Subsonic Buster (Wave)"_s},
|
||||
{301, "Amplifier Buster (Wave) (Motion)"_s},
|
||||
{302, "Cyclonwave Buster (Wave)"_s},
|
||||
{303, "Warhorn Buster (Wave) (Motion)"_s},
|
||||
{397, "Short W Base Buster (Wave)"_s},
|
||||
{398, "Medium W Base Buster (Wave)"_s},
|
||||
{399, "Long W Base Buster (Wave)"_s},
|
||||
};
|
||||
// endregion
|
||||
|
||||
// region Bullet Launchers
|
||||
static const std::map<Int, Containers::StringView> blauncher_pods {
|
||||
{0, "BL-Delta Pack Launcher (Missile x12)"_s},
|
||||
{1, "BL-Twin Pack Launcher (Missile x12)"_s},
|
||||
{2, "Detector Launcher (Missile x12)"_s},
|
||||
{3, "BL-Triplet Pack Launcher (Missile x12)"_s},
|
||||
{4, "Shielded Launcher (Missile x12)"_s},
|
||||
{99, "H Base Pod (Missile x12)"_s},
|
||||
|
||||
{100, "Warhead Pod (Nuke x2)"_s},
|
||||
{101, "Warhead Launcher (Nuke x2)"_s},
|
||||
{102, "Triangular Warhead Pod (Nuke x2)"_s},
|
||||
{103, "Expanded Warhead Pod (Nuke x2)"_s},
|
||||
{104, "Shielded Warhead Pod (Nuke x2)"_s},
|
||||
{199, "N Base Pod (Nuke x2)"_s},
|
||||
|
||||
{200, "Widepack Launcher (Salvo x24)"_s},
|
||||
{201, "Covered Launcher (Salvo x24)"_s},
|
||||
{202, "Double Delta Launcher (Salvo x24)"_s},
|
||||
{203, "Hexagonal Launcher (Salvo x24)"_s},
|
||||
{204, "Shielded Six Launcher (Salvo x24)"_s},
|
||||
{299, "S Base Pod (Salvo x24)"_s},
|
||||
|
||||
{300, "Sentinel Cluster Pod (Cluster x40)"_s},
|
||||
{301, "Pincer Cluster Pod (Cluster x40)"_s},
|
||||
{302, "Elliptical Cluster Pod (Cluster x40)"_s},
|
||||
{303, "Sawed Cluster Pod (Cluster x40)"_s},
|
||||
{304, "Pentagonal Cluster Pod (Cluster x40)"_s},
|
||||
{399, "C Base Pod (Cluster x40)"_s},
|
||||
};
|
||||
|
||||
static const std::map<Int, Containers::StringView> blauncher_projectiles {
|
||||
{0, "Flathead Missile"_s},
|
||||
{1, "Warhead Missile"_s},
|
||||
{2, "Pointhead Missile"_s},
|
||||
{3, "Marker Missile"_s},
|
||||
{4, "ArB Missile"_s},
|
||||
};
|
||||
// endregion
|
||||
|
||||
// region Energy Launchers
|
||||
static const std::map<Int, Containers::StringView> elauncher_generators {
|
||||
{0, "Fly Unit"_s},
|
||||
{1, "Assault Unit (Motion)"_s},
|
||||
{2, "Falcon Unit"_s},
|
||||
{3, "Drake Unit (Motion)"_s},
|
||||
{4, "Kingfisher Unit"_s},
|
||||
{5, "Tri-Edge Unit"_s},
|
||||
{6, "Flatline Unit"_s},
|
||||
{7, "Boost Unit"_s},
|
||||
{8, "Sparrow Unit"_s},
|
||||
{9, "Guarded Unit"_s},
|
||||
{10, "Sailtail Unit"_s},
|
||||
{11, "Tri-Covered Unit"_s},
|
||||
{12, "Pointy Unit"_s},
|
||||
{13, "Scope-Like Unit"_s},
|
||||
{14, "Rotating Unit (Motion)"_s},
|
||||
{15, "Clamper Unit"_s},
|
||||
{16, "Quadsat Unit"_s},
|
||||
{17, "Squ-Rotating Unit (Motion)"_s},
|
||||
{18, "Bloom Unit"_s},
|
||||
{19, "Edge-Rotating Unit (Motion)"_s},
|
||||
{20, "Shipend Unit"_s},
|
||||
{21, "Revwing Unit"_s},
|
||||
{22, "Viper Unit"_s},
|
||||
{23, "EX Unit"_s},
|
||||
{24, "Aery Unit"_s},
|
||||
{25, "Carrier Unit"_s},
|
||||
{26, "Compartment Unit"_s},
|
||||
{27, "Flatedge Unit"_s},
|
||||
{99, "Base Generator"},
|
||||
};
|
||||
|
||||
static const std::map<Int, Containers::StringView> elauncher_pods {
|
||||
{0, "EN-Dual Claw Launcher (Echo) (Motion)"_s},
|
||||
{1, "EN-Assault Launcher (Echo)"_s},
|
||||
{2, "EN-Tactical Launcher (Echo)"_s},
|
||||
{3, "EN-Force Focus Launcher (Echo) (Motion)"_s},
|
||||
{4, "EN-Needler Launcher (Echo)"_s},
|
||||
{5, "Spark Launcher (Echo)"_s},
|
||||
{6, "Pinpoint Launcher (Echo)"_s},
|
||||
{99, "E Base EPod (Echo)"_s},
|
||||
|
||||
{100, "Raystream Launcher (Beam)"_s},
|
||||
{101, "Perpetum Launcher (Beam)"_s},
|
||||
{102, "Scorcher Launcher (Beam)"_s},
|
||||
{103, "Concentrator Launcher (Beam)"_s},
|
||||
{104, "Crosshair Launcher (Beam)"_s},
|
||||
{105, "Powerlined Launcher (Beam)"_s},
|
||||
{106, "Attached Launcher (Beam)"_s},
|
||||
{199, "B Base EPod (Beam)"_s},
|
||||
|
||||
{200, "Hilt Launcher (Slash) (Motion)"_s},
|
||||
{201, "Underangle Launcher (Slash)"_s},
|
||||
{202, "Crossblade Launcher (Slash)"_s},
|
||||
{203, "Deltablade Launcher (Slash) (Motion)"_s},
|
||||
{204, "Spike Launcher (Slash)"_s},
|
||||
{205, "Tri-Pronged Launcher (Slash) (Motion)"_s},
|
||||
{206, "Heavyblade Launcher (Slash)"_s},
|
||||
{299, "S Base EPod (Slash)"_s},
|
||||
|
||||
{300, "Covering Launcher (Photon)"_s},
|
||||
{301, "Boxhead Launcher (Photon)"_s},
|
||||
{302, "Stabilised Launcher (Photon)"_s},
|
||||
{303, "Flatline Launcher (Photon)"_s},
|
||||
{304, "Shelled Launcher (Photon)"_s},
|
||||
{305, "Widearm Launcher (Photon)"_s},
|
||||
{306, "Wingspan Launcher (Photon)"_s},
|
||||
{399, "P Base EPod (Photon)"_s},
|
||||
};
|
||||
// endregion
|
|
@ -15,10 +15,10 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifdef c
|
||||
c(Melee, "enuWeaponTypes::NewEnumerator0"_s, "Melee weapon"_s)
|
||||
c(BulletShooter, "enuWeaponTypes::NewEnumerator1"_s, "Bullet shooter"_s)
|
||||
c(EnergyShooter, "enuWeaponTypes::NewEnumerator2"_s, "Energy shooter"_s)
|
||||
c(BulletLauncher, "enuWeaponTypes::NewEnumerator3"_s, "Bullet launcher"_s)
|
||||
c(EnergyLauncher, "enuWeaponTypes::NewEnumerator4"_s, "Energy launcher"_s)
|
||||
c(Shield, "enuWeaponTypes::NewEnumerator5"_s, "Shield"_s)
|
||||
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
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
// 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>
|
||||
|
||||
|
@ -28,9 +30,44 @@ using namespace Corrade;
|
|||
using namespace Magnum;
|
||||
|
||||
enum class ArmourSlot {
|
||||
#define c(enumerator, enumstr, name) enumerator,
|
||||
#include "../Maps/ArmourSlots.hpp"
|
||||
#undef c
|
||||
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 {
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
#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/String.h>
|
||||
|
||||
#include <Magnum/Magnum.h>
|
||||
#include <Magnum/Math/Vector3.h>
|
||||
|
||||
using namespace Corrade;
|
||||
using namespace Magnum;
|
||||
|
||||
enum class BulletLauncherAttachmentStyle {
|
||||
#define c(enumerator, enumstr) enumerator,
|
||||
#include "../Maps/BulletLauncherAttachmentStyles.hpp"
|
||||
#undef c
|
||||
};
|
||||
|
||||
enum class BulletLauncherSocket {
|
||||
#define c(enumerator, enumstr, name) enumerator,
|
||||
#include "../Maps/BulletLauncherSockets.hpp"
|
||||
#undef c
|
||||
};
|
||||
|
||||
struct BulletLauncherAttachment {
|
||||
BulletLauncherSocket socket = BulletLauncherSocket::Auto;
|
||||
Vector3 relativeLocation;
|
||||
Vector3 offsetLocation;
|
||||
Vector3 relativeRotation;
|
||||
Vector3 offsetRotation;
|
||||
Vector3 relativeScale;
|
||||
};
|
|
@ -16,17 +16,16 @@
|
|||
// 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/String.h>
|
||||
#include <string>
|
||||
|
||||
#include <Magnum/Magnum.h>
|
||||
#include <Magnum/Math/Color.h>
|
||||
#include <Magnum/Math/Vector2.h>
|
||||
|
||||
using namespace Corrade;
|
||||
using namespace Magnum;
|
||||
|
||||
struct CustomStyle {
|
||||
Containers::String name;
|
||||
std::string name;
|
||||
Color4 colour{0.0f};
|
||||
Float metallic = 0.5f;
|
||||
Float gloss = 0.5f;
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
// 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>
|
||||
|
|
1162
src/Mass/Mass.cpp
1162
src/Mass/Mass.cpp
File diff suppressed because it is too large
Load Diff
|
@ -16,11 +16,11 @@
|
|||
// 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/Optional.h>
|
||||
#include <Corrade/Containers/Pointer.h>
|
||||
#include <Corrade/Containers/StaticArray.h>
|
||||
#include <Corrade/Containers/String.h>
|
||||
#include <Corrade/Containers/StringView.h>
|
||||
|
||||
#include <Magnum/Magnum.h>
|
||||
#include <Magnum/Math/Color.h>
|
||||
|
@ -28,7 +28,6 @@
|
|||
#include <Magnum/Math/Vector3.h>
|
||||
|
||||
#include "Joints.h"
|
||||
#include "BulletLauncherAttachment.h"
|
||||
#include "CustomStyle.h"
|
||||
#include "Decal.h"
|
||||
#include "Accessory.h"
|
||||
|
@ -49,7 +48,7 @@ class Mass {
|
|||
Empty, Invalid, Valid
|
||||
};
|
||||
|
||||
explicit Mass(Containers::StringView path);
|
||||
explicit Mass(const std::string& path);
|
||||
|
||||
Mass(const Mass&) = delete;
|
||||
Mass& operator=(const Mass&) = delete;
|
||||
|
@ -57,16 +56,16 @@ class Mass {
|
|||
Mass(Mass&&) = default;
|
||||
Mass& operator=(Mass&&) = default;
|
||||
|
||||
auto lastError() -> Containers::StringView;
|
||||
auto lastError() -> std::string const&;
|
||||
|
||||
static auto getNameFromFile(Containers::StringView path) -> Containers::Optional<Containers::String>;
|
||||
static auto getNameFromFile(const std::string& path) -> Containers::Optional<std::string>;
|
||||
|
||||
void refreshValues();
|
||||
|
||||
auto filename() -> Containers::StringView;
|
||||
auto filename() -> std::string const&;
|
||||
|
||||
auto name() -> Containers::StringView;
|
||||
auto setName(Containers::StringView new_name) -> bool;
|
||||
auto name() -> Containers::Optional<std::string> const&;
|
||||
auto setName(std::string new_name) -> bool;
|
||||
|
||||
auto state() -> State;
|
||||
|
||||
|
@ -93,11 +92,6 @@ class Mass {
|
|||
void getArmourParts();
|
||||
auto writeArmourPart(ArmourSlot slot) -> bool;
|
||||
|
||||
auto bulletLauncherAttachmentStyle() -> BulletLauncherAttachmentStyle&;
|
||||
auto bulletLauncherAttachments() -> Containers::ArrayView<BulletLauncherAttachment>;
|
||||
void getBulletLauncherAttachments();
|
||||
auto writeBulletLauncherAttachments() -> bool;
|
||||
|
||||
auto armourCustomStyles() -> Containers::ArrayView<CustomStyle>;
|
||||
void getArmourCustomStyles();
|
||||
auto writeArmourCustomStyle(UnsignedLong index) -> bool;
|
||||
|
@ -141,12 +135,12 @@ class Mass {
|
|||
auto architecture() -> Int&;
|
||||
auto techs() -> Containers::ArrayView<Int>;
|
||||
|
||||
auto account() -> Containers::StringView;
|
||||
auto updateAccount(Containers::StringView new_account) -> bool;
|
||||
auto account() -> std::string const&;
|
||||
auto updateAccount(const std::string& new_account) -> bool;
|
||||
|
||||
private:
|
||||
void getCustomStyles(Containers::ArrayView<CustomStyle> styles, ArrayProperty* style_array);
|
||||
auto writeCustomStyle(const CustomStyle& style, UnsignedLong index, ArrayProperty* style_array) -> bool;
|
||||
auto setCustomStyle(const CustomStyle& style, UnsignedLong index, ArrayProperty* style_array) -> bool;
|
||||
|
||||
void getDecals(Containers::ArrayView<Decal> decals, ArrayProperty* decal_array);
|
||||
void writeDecals(Containers::ArrayView<Decal> decals, ArrayProperty* decal_array);
|
||||
|
@ -154,36 +148,38 @@ class Mass {
|
|||
void getAccessories(Containers::ArrayView<Accessory> accessories, ArrayProperty* accessory_array);
|
||||
void writeAccessories(Containers::ArrayView<Accessory> accessories, ArrayProperty* accs_array);
|
||||
|
||||
void getWeaponType(Containers::StringView prop_name, Containers::ArrayView<Weapon> weapon_array);
|
||||
auto writeWeaponType(Containers::StringView prop_name, Containers::ArrayView<Weapon> weapon_array) -> bool;
|
||||
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(Containers::StringView big_node_prop_name, Int& big_node_id,
|
||||
Containers::StringView small_nodes_prop_name, Containers::ArrayView<Int> small_nodes_ids);
|
||||
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;
|
||||
|
||||
Containers::String _lastError;
|
||||
std::string _lastError;
|
||||
|
||||
Containers::String _folder;
|
||||
Containers::String _filename;
|
||||
std::string _folder;
|
||||
std::string _filename;
|
||||
State _state = State::Empty;
|
||||
|
||||
bool _dirty = false;
|
||||
|
||||
Containers::Optional<Containers::String> _name = Containers::NullOpt;
|
||||
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;
|
||||
BulletLauncherAttachmentStyle blAttachmentStyle = BulletLauncherAttachmentStyle::NotFound;
|
||||
Containers::StaticArray<4, BulletLauncherAttachment> blAttachment;
|
||||
} _armour;
|
||||
|
||||
struct {
|
||||
|
@ -208,5 +204,5 @@ class Mass {
|
|||
Containers::StaticArray<7, Int> techIds;
|
||||
} _tuning;
|
||||
|
||||
Containers::String _account;
|
||||
std::string _account;
|
||||
};
|
||||
|
|
|
@ -1,433 +0,0 @@
|
|||
// 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 "PropertyNames.h"
|
||||
#include "../Logger/Logger.h"
|
||||
#include "../UESaveFile/Types/ArrayProperty.h"
|
||||
#include "../UESaveFile/Types/ByteProperty.h"
|
||||
#include "../UESaveFile/Types/GenericStructProperty.h"
|
||||
#include "../UESaveFile/Types/IntProperty.h"
|
||||
#include "../UESaveFile/Types/StringProperty.h"
|
||||
#include "../UESaveFile/Types/VectorStructProperty.h"
|
||||
|
||||
#include "Mass.h"
|
||||
|
||||
using namespace Containers::Literals;
|
||||
|
||||
auto Mass::armourParts() -> Containers::ArrayView<ArmourPart> {
|
||||
return _armour.parts;
|
||||
}
|
||||
|
||||
void Mass::getArmourParts() {
|
||||
LOG_INFO("Getting armour parts.");
|
||||
|
||||
auto unit_data = _mass->at<GenericStructProperty>(MASS_UNIT_DATA);
|
||||
if(!unit_data) {
|
||||
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_UNIT_DATA, _filename);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
auto armour_array = unit_data->at<ArrayProperty>(MASS_ARMOUR_PARTS);
|
||||
if(!armour_array) {
|
||||
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_ARMOUR_PARTS, _filename);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
if(armour_array->items.size() != _armour.parts.size()) {
|
||||
LOG_ERROR_FORMAT("Armour part arrays are not of the same size. Expected {}, got {} instead.",
|
||||
_armour.parts.size(), armour_array->items.size());
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
for(UnsignedInt i = 0; i < armour_array->items.size(); i++) {
|
||||
auto part_prop = armour_array->at<GenericStructProperty>(i);
|
||||
auto& part = _armour.parts[i];
|
||||
|
||||
auto& armour_slot = part_prop->at<ByteProperty>(MASS_ARMOUR_SLOT)->enumValue;
|
||||
#define c(enumerator, strenum, name) if(armour_slot == (strenum)) { part.slot = ArmourSlot::enumerator; } else
|
||||
#include "../Maps/ArmourSlots.hpp"
|
||||
#undef c
|
||||
{
|
||||
LOG_ERROR_FORMAT("Invalid armour slot enumerator {}.", armour_slot);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
part.id = part_prop->at<IntProperty>(MASS_ARMOUR_ID)->value;
|
||||
|
||||
auto part_styles = part_prop->at<ArrayProperty>(MASS_ARMOUR_STYLES);
|
||||
if(!part_styles) {
|
||||
LOG_ERROR_FORMAT("Part styles not found for part number {}.", i);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
if(part_styles->items.size() != part.styles.size()) {
|
||||
LOG_ERROR_FORMAT("Armour part style arrays are not of the same size. Expected {}, got {} instead.",
|
||||
part.styles.size(), part_styles->items.size());
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
for(UnsignedInt j = 0; j < part_styles->items.size(); j++) {
|
||||
part.styles[j] = part_styles->at<IntProperty>(j)->value;
|
||||
}
|
||||
|
||||
auto decals_array = part_prop->at<ArrayProperty>(MASS_ARMOUR_DECALS);
|
||||
if(!decals_array) {
|
||||
LOG_ERROR_FORMAT("Part decals not found for part number {}.", i);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
part.decals = Containers::Array<Decal>{decals_array->items.size()};
|
||||
|
||||
getDecals(part.decals, decals_array);
|
||||
|
||||
auto accs_array = part_prop->at<ArrayProperty>(MASS_ARMOUR_ACCESSORIES);
|
||||
if(!accs_array) {
|
||||
LOG_WARNING_FORMAT("Part accessories not found for part number {}.", i);
|
||||
part.accessories = Containers::Array<Accessory>{};
|
||||
continue;
|
||||
}
|
||||
|
||||
if(part.accessories.size() != accs_array->items.size()) {
|
||||
part.accessories = Containers::Array<Accessory>{accs_array->items.size()};
|
||||
}
|
||||
|
||||
getAccessories(part.accessories, accs_array);
|
||||
}
|
||||
}
|
||||
|
||||
auto Mass::writeArmourPart(ArmourSlot slot) -> bool {
|
||||
LOG_INFO_FORMAT("Writing armour part in slot {}.", static_cast<int>(slot));
|
||||
|
||||
auto& part = *std::find_if(_armour.parts.begin(), _armour.parts.end(), [&slot](const ArmourPart& part){ return slot == part.slot; });
|
||||
|
||||
auto unit_data = _mass->at<GenericStructProperty>(MASS_UNIT_DATA);
|
||||
if(!unit_data) {
|
||||
_lastError = "Couldn't find the unit data in " + _filename + ".";
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto armour_array = unit_data->at<ArrayProperty>(MASS_ARMOUR_PARTS);
|
||||
if(!armour_array) {
|
||||
_lastError = "Couldn't find the armour part array in " + _filename + ".";
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
Containers::StringView slot_str = nullptr;
|
||||
switch(slot) {
|
||||
#define c(enumerator, strenum, name) case ArmourSlot::enumerator: \
|
||||
slot_str = strenum; \
|
||||
break;
|
||||
#include "../Maps/ArmourSlots.hpp"
|
||||
#undef c
|
||||
}
|
||||
|
||||
GenericStructProperty* part_prop = nullptr;
|
||||
|
||||
for(UnsignedInt i = 0; i < armour_array->items.size(); i++) {
|
||||
part_prop = armour_array->at<GenericStructProperty>(i);
|
||||
if(slot_str == part_prop->at<ByteProperty>(MASS_ARMOUR_SLOT)->enumValue) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
part_prop = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if(!part_prop) {
|
||||
auto prefix = "Couldn't find the armour part for slot "_s;
|
||||
switch(slot) {
|
||||
#define c(enumerator, strenum, name) case ArmourSlot::enumerator: \
|
||||
_lastError = prefix + "ArmourSlot::" #enumerator "."_s; \
|
||||
break;
|
||||
#include "../Maps/ArmourSlots.hpp"
|
||||
#undef c
|
||||
}
|
||||
LOG_ERROR(_lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
part_prop->at<IntProperty>(MASS_ARMOUR_ID)->value = part.id;
|
||||
|
||||
auto part_styles = part_prop->at<ArrayProperty>(MASS_ARMOUR_STYLES);
|
||||
for(UnsignedInt i = 0; i < part.styles.size(); i++) {
|
||||
part_styles->at<IntProperty>(i)->value = part.styles[i];
|
||||
}
|
||||
|
||||
auto decals_array = part_prop->at<ArrayProperty>(MASS_ARMOUR_DECALS);
|
||||
writeDecals(part.decals, decals_array);
|
||||
|
||||
if(part.accessories.size() != 0) {
|
||||
auto accs_array = part_prop->at<ArrayProperty>(MASS_ARMOUR_ACCESSORIES);
|
||||
writeAccessories(part.accessories, accs_array);
|
||||
}
|
||||
|
||||
if(!_mass->saveToFile()) {
|
||||
_lastError = _mass->lastError();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
auto Mass::bulletLauncherAttachmentStyle() -> BulletLauncherAttachmentStyle& {
|
||||
return _armour.blAttachmentStyle;
|
||||
}
|
||||
|
||||
auto Mass::bulletLauncherAttachments() -> Containers::ArrayView<BulletLauncherAttachment> {
|
||||
return _armour.blAttachment;
|
||||
}
|
||||
|
||||
void Mass::getBulletLauncherAttachments() {
|
||||
LOG_INFO("Getting the bullet launcher attachment data.");
|
||||
|
||||
auto unit_data = _mass->at<GenericStructProperty>(MASS_UNIT_DATA);
|
||||
if(!unit_data) {
|
||||
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_UNIT_DATA, _filename);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
auto attach_style_prop = unit_data->at<ByteProperty>(MASS_BL_ATTACHMENT_STYLE);
|
||||
auto attach_array = unit_data->at<ArrayProperty>(MASS_BL_ATTACHMENTS);
|
||||
|
||||
if(!attach_style_prop && !attach_array) {
|
||||
LOG_WARNING_FORMAT("No bullet launcher attachment data found in {}.", _filename);
|
||||
_armour.blAttachmentStyle = BulletLauncherAttachmentStyle::NotFound;
|
||||
return;
|
||||
}
|
||||
|
||||
if(attach_style_prop && !attach_array) {
|
||||
LOG_WARNING_FORMAT("No bullet launcher attachments found in {}.", _filename);
|
||||
_armour.blAttachmentStyle = BulletLauncherAttachmentStyle::NotFound;
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
if(attach_array->items.size() == _weapons.bulletLaunchers.size() &&
|
||||
attach_array->items.size() == _armour.blAttachment.size())
|
||||
{
|
||||
for(UnsignedInt i = 0; i < attach_array->items.size(); i++) {
|
||||
auto attachment_prop = attach_array->at<GenericStructProperty>(i);
|
||||
auto& attachment = _armour.blAttachment[i];
|
||||
|
||||
Containers::StringView socket = attachment_prop->at<StringProperty>(MASS_BL_ATTACHMENT_SOCKET)->value;
|
||||
#define c(enumerator, strenum, name) if(socket == (strenum)) { attachment.socket = BulletLauncherSocket::enumerator; } else
|
||||
#include "../Maps/BulletLauncherSockets.hpp"
|
||||
#undef c
|
||||
{
|
||||
LOG_ERROR_FORMAT("Invalid attachment socket {}.", socket);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
auto rel_loc_prop = attachment_prop->at<VectorStructProperty>(MASS_BL_ATTACHMENT_RELLOC);
|
||||
attachment.relativeLocation = Vector3{rel_loc_prop->x, rel_loc_prop->y, rel_loc_prop->z};
|
||||
auto off_loc_prop = attachment_prop->at<VectorStructProperty>(MASS_BL_ATTACHMENT_OFFLOC);
|
||||
attachment.offsetLocation = Vector3{off_loc_prop->x, off_loc_prop->y, off_loc_prop->z};
|
||||
auto rel_rot_prop = attachment_prop->at<VectorStructProperty>(MASS_BL_ATTACHMENT_RELROT);
|
||||
attachment.relativeRotation = Vector3{rel_rot_prop->x, rel_rot_prop->y, rel_rot_prop->z};
|
||||
auto off_rot_prop = attachment_prop->at<VectorStructProperty>(MASS_BL_ATTACHMENT_OFFROT);
|
||||
attachment.offsetRotation = Vector3{off_rot_prop->x, off_rot_prop->y, off_rot_prop->z};
|
||||
auto rel_scale_prop = attachment_prop->at<VectorStructProperty>(MASS_BL_ATTACHMENT_RELSCALE);
|
||||
attachment.relativeScale = Vector3{rel_scale_prop->x, rel_scale_prop->y, rel_scale_prop->z};
|
||||
}
|
||||
}
|
||||
|
||||
if(attach_style_prop) {
|
||||
Containers::StringView attach_style = attach_style_prop->enumValue;
|
||||
#define c(enumerator, strenum) if(attach_style == (strenum)) { _armour.blAttachmentStyle = BulletLauncherAttachmentStyle::enumerator; } else
|
||||
#include "../Maps/BulletLauncherAttachmentStyles.hpp"
|
||||
#undef c
|
||||
{
|
||||
LOG_ERROR_FORMAT("Invalid attachment style {}.", attach_style);
|
||||
_state = State::Invalid;
|
||||
}
|
||||
}
|
||||
else {
|
||||
_armour.blAttachmentStyle = BulletLauncherAttachmentStyle::ActiveOne;
|
||||
}
|
||||
}
|
||||
|
||||
auto Mass::writeBulletLauncherAttachments() -> bool {
|
||||
LOG_INFO("Writing bullet launcher attachments.");
|
||||
|
||||
auto unit_data = _mass->at<GenericStructProperty>(MASS_UNIT_DATA);
|
||||
if(!unit_data) {
|
||||
_lastError = "No unit data in " + _filename;
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto attach_style_prop = unit_data->at<ByteProperty>(MASS_BL_ATTACHMENT_STYLE);
|
||||
auto attach_array = unit_data->at<ArrayProperty>(MASS_BL_ATTACHMENTS);
|
||||
|
||||
if(!attach_style_prop && !attach_array) {
|
||||
_lastError = "No attachment properties to write to in " + _filename;
|
||||
LOG_ERROR(_lastError);
|
||||
_armour.blAttachmentStyle = BulletLauncherAttachmentStyle::NotFound;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(attach_style_prop && !attach_array) {
|
||||
_lastError = "Couldn't find the attachments in " + _filename;
|
||||
LOG_ERROR(_lastError);
|
||||
_armour.blAttachmentStyle = BulletLauncherAttachmentStyle::NotFound;
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(attach_array->items.size() == _weapons.bulletLaunchers.size() &&
|
||||
attach_array->items.size() == _armour.blAttachment.size())
|
||||
{
|
||||
for(UnsignedInt i = 0; i < attach_array->items.size(); i++) {
|
||||
auto attachment_prop = attach_array->at<GenericStructProperty>(i);
|
||||
auto& attachment = _armour.blAttachment[i];
|
||||
|
||||
auto& socket = attachment_prop->at<StringProperty>(MASS_BL_ATTACHMENT_SOCKET)->value;
|
||||
switch(attachment.socket) {
|
||||
#define c(enumerator, strenum, name) case BulletLauncherSocket::enumerator: socket = strenum; break;
|
||||
#include "../Maps/BulletLauncherSockets.hpp"
|
||||
#undef c
|
||||
default:
|
||||
_lastError = "Invalid socket type."_s;
|
||||
LOG_ERROR(_lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto rel_loc_prop = attachment_prop->at<VectorStructProperty>(MASS_BL_ATTACHMENT_RELLOC);
|
||||
rel_loc_prop->x = attachment.relativeLocation.x();
|
||||
rel_loc_prop->y = attachment.relativeLocation.y();
|
||||
rel_loc_prop->z = attachment.relativeLocation.z();
|
||||
auto off_loc_prop = attachment_prop->at<VectorStructProperty>(MASS_BL_ATTACHMENT_OFFLOC);
|
||||
off_loc_prop->x = attachment.offsetLocation.x();
|
||||
off_loc_prop->y = attachment.offsetLocation.y();
|
||||
off_loc_prop->z = attachment.offsetLocation.z();
|
||||
auto rel_rot_prop = attachment_prop->at<VectorStructProperty>(MASS_BL_ATTACHMENT_RELROT);
|
||||
rel_rot_prop->x = attachment.relativeRotation.x();
|
||||
rel_rot_prop->y = attachment.relativeRotation.y();
|
||||
rel_rot_prop->z = attachment.relativeRotation.z();
|
||||
auto off_rot_prop = attachment_prop->at<VectorStructProperty>(MASS_BL_ATTACHMENT_OFFROT);
|
||||
off_rot_prop->x = attachment.offsetRotation.x();
|
||||
off_rot_prop->y = attachment.offsetRotation.y();
|
||||
off_rot_prop->z = attachment.offsetRotation.z();
|
||||
auto rel_scale_prop = attachment_prop->at<VectorStructProperty>(MASS_BL_ATTACHMENT_RELSCALE);
|
||||
rel_scale_prop->x = attachment.relativeScale.x();
|
||||
rel_scale_prop->y = attachment.relativeScale.y();
|
||||
rel_scale_prop->z = attachment.relativeScale.z();
|
||||
}
|
||||
}
|
||||
|
||||
if(!attach_style_prop) {
|
||||
attach_style_prop = new ByteProperty;
|
||||
attach_style_prop->name.emplace(MASS_BL_ATTACHMENT_STYLE);
|
||||
attach_style_prop->enumType = "enuBLAttachmentStyle"_s;
|
||||
ByteProperty::ptr prop{attach_style_prop};
|
||||
arrayAppend(unit_data->properties, std::move(prop));
|
||||
}
|
||||
|
||||
auto& attach_style = attach_style_prop->enumValue;
|
||||
switch(_armour.blAttachmentStyle) {
|
||||
#define c(enumerator, strenum) case BulletLauncherAttachmentStyle::enumerator: \
|
||||
attach_style = strenum; \
|
||||
break;
|
||||
#include "../Maps/BulletLauncherAttachmentStyles.hpp"
|
||||
#undef c
|
||||
default:
|
||||
_lastError = "Unknown BL attachment style.";
|
||||
LOG_ERROR(_lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!_mass->saveToFile()) {
|
||||
_lastError = _mass->lastError();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
auto Mass::armourCustomStyles() -> Containers::ArrayView<CustomStyle> {
|
||||
return _armour.customStyles;
|
||||
}
|
||||
|
||||
void Mass::getArmourCustomStyles() {
|
||||
LOG_INFO("Getting the custom armour styles.");
|
||||
|
||||
auto unit_data = _mass->at<GenericStructProperty>(MASS_UNIT_DATA);
|
||||
if(!unit_data) {
|
||||
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_UNIT_DATA, _filename);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
auto armour_styles = unit_data->at<ArrayProperty>(MASS_CUSTOM_ARMOUR_STYLES);
|
||||
if(!armour_styles) {
|
||||
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_CUSTOM_ARMOUR_STYLES, _filename);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
if(armour_styles->items.size() != _armour.customStyles.size()) {
|
||||
LOG_ERROR_FORMAT("Custom armour style arrays are not of the same size. Expected {}, got {} instead.",
|
||||
_armour.customStyles.size(), armour_styles->items.size());
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
getCustomStyles(_armour.customStyles, armour_styles);
|
||||
}
|
||||
|
||||
auto Mass::writeArmourCustomStyle(UnsignedLong index) -> bool {
|
||||
LOG_INFO_FORMAT("Writing custom armour style {}.", index);
|
||||
|
||||
if(index > _armour.customStyles.size()) {
|
||||
_lastError = "Style index out of range."_s;
|
||||
LOG_ERROR(_lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto unit_data = _mass->at<GenericStructProperty>(MASS_UNIT_DATA);
|
||||
if(!unit_data) {
|
||||
_lastError = "Couldn't find unit data in "_s + _filename;
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto armour_styles = unit_data->at<ArrayProperty>(MASS_CUSTOM_ARMOUR_STYLES);
|
||||
if(!armour_styles) {
|
||||
_lastError = "Couldn't find armour custom styles in "_s + _filename;
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
return writeCustomStyle(_armour.customStyles[index], index, armour_styles);
|
||||
}
|
|
@ -1,148 +0,0 @@
|
|||
// 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 "PropertyNames.h"
|
||||
#include "../UESaveFile/Types/ArrayProperty.h"
|
||||
#include "../UESaveFile/Types/BoolProperty.h"
|
||||
#include "../UESaveFile/Types/ColourStructProperty.h"
|
||||
#include "../UESaveFile/Types/FloatProperty.h"
|
||||
#include "../UESaveFile/Types/GenericStructProperty.h"
|
||||
#include "../UESaveFile/Types/RotatorStructProperty.h"
|
||||
#include "../UESaveFile/Types/VectorStructProperty.h"
|
||||
#include "../UESaveFile/Types/Vector2DStructProperty.h"
|
||||
#include "../UESaveFile/Types/IntProperty.h"
|
||||
|
||||
#include "Mass.h"
|
||||
|
||||
using namespace Containers::Literals;
|
||||
|
||||
void Mass::getDecals(Containers::ArrayView<Decal> decals, ArrayProperty* decal_array) {
|
||||
for(UnsignedInt i = 0; i < decal_array->items.size(); i++) {
|
||||
auto decal_prop = decal_array->at<GenericStructProperty>(i);
|
||||
CORRADE_INTERNAL_ASSERT(decal_prop);
|
||||
auto& decal = decals[i];
|
||||
|
||||
decal.id = decal_prop->at<IntProperty>(MASS_DECAL_ID)->value;
|
||||
auto colour_prop = decal_prop->at<ColourStructProperty>(MASS_DECAL_COLOUR);
|
||||
decal.colour = Color4{colour_prop->r, colour_prop->g, colour_prop->b, colour_prop->a};
|
||||
auto pos_prop = decal_prop->at<VectorStructProperty>(MASS_DECAL_POSITION);
|
||||
decal.position = Vector3{pos_prop->x, pos_prop->y, pos_prop->z};
|
||||
auto u_prop = decal_prop->at<VectorStructProperty>(MASS_DECAL_UAXIS);
|
||||
decal.uAxis = Vector3{u_prop->x, u_prop->y, u_prop->z};
|
||||
auto v_prop = decal_prop->at<VectorStructProperty>(MASS_DECAL_VAXIS);
|
||||
decal.vAxis = Vector3{v_prop->x, v_prop->y, v_prop->z};
|
||||
auto offset_prop = decal_prop->at<Vector2DStructProperty>(MASS_DECAL_OFFSET);
|
||||
decal.offset = Vector2{offset_prop->x, offset_prop->y};
|
||||
decal.scale = decal_prop->at<FloatProperty>(MASS_DECAL_SCALE)->value;
|
||||
decal.rotation = decal_prop->at<FloatProperty>(MASS_DECAL_ROTATION)->value;
|
||||
decal.flip = decal_prop->at<BoolProperty>(MASS_DECAL_FLIP)->value;
|
||||
decal.wrap = decal_prop->at<BoolProperty>(MASS_DECAL_WRAP)->value;
|
||||
}
|
||||
}
|
||||
|
||||
void Mass::writeDecals(Containers::ArrayView<Decal> decals, ArrayProperty* decal_array) {
|
||||
for(UnsignedInt i = 0; i < decal_array->items.size(); i++) {
|
||||
auto decal_prop = decal_array->at<GenericStructProperty>(i);
|
||||
CORRADE_INTERNAL_ASSERT(decal_prop);
|
||||
auto& decal = decals[i];
|
||||
|
||||
decal_prop->at<IntProperty>(MASS_DECAL_ID)->value = decal.id;
|
||||
auto colour_prop = decal_prop->at<ColourStructProperty>(MASS_DECAL_COLOUR);
|
||||
colour_prop->r = decal.colour.r();
|
||||
colour_prop->g = decal.colour.g();
|
||||
colour_prop->b = decal.colour.b();
|
||||
colour_prop->a = decal.colour.a();
|
||||
auto pos_prop = decal_prop->at<VectorStructProperty>(MASS_DECAL_POSITION);
|
||||
pos_prop->x = decal.position.x();
|
||||
pos_prop->y = decal.position.y();
|
||||
pos_prop->z = decal.position.z();
|
||||
auto u_prop = decal_prop->at<VectorStructProperty>(MASS_DECAL_UAXIS);
|
||||
u_prop->x = decal.uAxis.x();
|
||||
u_prop->y = decal.uAxis.y();
|
||||
u_prop->z = decal.uAxis.z();
|
||||
auto v_prop = decal_prop->at<VectorStructProperty>(MASS_DECAL_VAXIS);
|
||||
v_prop->x = decal.vAxis.x();
|
||||
v_prop->y = decal.vAxis.y();
|
||||
v_prop->z = decal.vAxis.z();
|
||||
auto offset_prop = decal_prop->at<Vector2DStructProperty>(MASS_DECAL_OFFSET);
|
||||
offset_prop->x = decal.offset.x();
|
||||
offset_prop->y = decal.offset.y();
|
||||
decal_prop->at<FloatProperty>(MASS_DECAL_SCALE)->value = decal.scale;
|
||||
decal_prop->at<FloatProperty>(MASS_DECAL_ROTATION)->value = decal.rotation;
|
||||
decal_prop->at<BoolProperty>(MASS_DECAL_FLIP)->value = decal.flip;
|
||||
decal_prop->at<BoolProperty>(MASS_DECAL_WRAP)->value = decal.wrap;
|
||||
}
|
||||
}
|
||||
|
||||
void Mass::getAccessories(Containers::ArrayView<Accessory> accessories, ArrayProperty* accessory_array) {
|
||||
for(UnsignedInt i = 0; i < accessory_array->items.size(); i++) {
|
||||
auto acc_prop = accessory_array->at<GenericStructProperty>(i);
|
||||
CORRADE_INTERNAL_ASSERT(acc_prop);
|
||||
auto& accessory = accessories[i];
|
||||
|
||||
accessory.attachIndex = acc_prop->at<IntProperty>(MASS_ACCESSORY_ATTACH_INDEX)->value;
|
||||
accessory.id = acc_prop->at<IntProperty>(MASS_ACCESSORY_ID)->value;
|
||||
auto acc_styles = acc_prop->at<ArrayProperty>(MASS_ACCESSORY_STYLES);
|
||||
for(UnsignedInt j = 0; j < acc_styles->items.size(); j++) {
|
||||
accessory.styles[j] = acc_styles->at<IntProperty>(j)->value;
|
||||
}
|
||||
auto rel_pos_prop = acc_prop->at<VectorStructProperty>(MASS_ACCESSORY_RELPOS);
|
||||
accessory.relativePosition = Vector3{rel_pos_prop->x, rel_pos_prop->y, rel_pos_prop->z};
|
||||
auto rel_pos_offset_prop = acc_prop->at<VectorStructProperty>(MASS_ACCESSORY_OFFPOS);
|
||||
accessory.relativePositionOffset = Vector3{rel_pos_offset_prop->x, rel_pos_offset_prop->y, rel_pos_offset_prop->z};
|
||||
auto rel_rot_prop = acc_prop->at<RotatorStructProperty>(MASS_ACCESSORY_RELROT);
|
||||
accessory.relativeRotation = Vector3{rel_rot_prop->x, rel_rot_prop->y, rel_rot_prop->z};
|
||||
auto rel_rot_offset_prop = acc_prop->at<RotatorStructProperty>(MASS_ACCESSORY_OFFROT);
|
||||
accessory.relativeRotationOffset = Vector3{rel_rot_offset_prop->x, rel_rot_offset_prop->y, rel_rot_offset_prop->z};
|
||||
auto local_scale_prop = acc_prop->at<VectorStructProperty>(MASS_ACCESSORY_SCALE);
|
||||
accessory.localScale = Vector3{local_scale_prop->x, local_scale_prop->y, local_scale_prop->z};
|
||||
}
|
||||
}
|
||||
|
||||
void Mass::writeAccessories(Containers::ArrayView<Accessory> accessories, ArrayProperty* accs_array) {
|
||||
for(UnsignedInt i = 0; i < accs_array->items.size(); i++) {
|
||||
auto acc_prop = accs_array->at<GenericStructProperty>(i);
|
||||
CORRADE_INTERNAL_ASSERT(acc_prop);
|
||||
auto& accessory = accessories[i];
|
||||
|
||||
acc_prop->at<IntProperty>(MASS_ACCESSORY_ATTACH_INDEX)->value = accessory.attachIndex;
|
||||
acc_prop->at<IntProperty>(MASS_ACCESSORY_ID)->value = accessory.id;
|
||||
auto acc_styles = acc_prop->at<ArrayProperty>(MASS_ACCESSORY_STYLES);
|
||||
for(UnsignedInt j = 0; j < acc_styles->items.size(); j++) {
|
||||
acc_styles->at<IntProperty>(j)->value = accessory.styles[j];
|
||||
}
|
||||
auto rel_pos_prop = acc_prop->at<VectorStructProperty>(MASS_ACCESSORY_RELPOS);
|
||||
rel_pos_prop->x = accessory.relativePosition.x();
|
||||
rel_pos_prop->y = accessory.relativePosition.y();
|
||||
rel_pos_prop->z = accessory.relativePosition.z();
|
||||
auto rel_pos_offset_prop = acc_prop->at<VectorStructProperty>(MASS_ACCESSORY_OFFPOS);
|
||||
rel_pos_offset_prop->x = accessory.relativePositionOffset.x();
|
||||
rel_pos_offset_prop->y = accessory.relativePositionOffset.y();
|
||||
rel_pos_offset_prop->z = accessory.relativePositionOffset.z();
|
||||
auto rel_rot_prop = acc_prop->at<RotatorStructProperty>(MASS_ACCESSORY_RELROT);
|
||||
rel_rot_prop->x = accessory.relativeRotation.x();
|
||||
rel_rot_prop->y = accessory.relativeRotation.y();
|
||||
rel_rot_prop->z = accessory.relativeRotation.z();
|
||||
auto rel_rot_offset_prop = acc_prop->at<RotatorStructProperty>(MASS_ACCESSORY_OFFROT);
|
||||
rel_rot_offset_prop->x = accessory.relativeRotationOffset.x();
|
||||
rel_rot_offset_prop->y = accessory.relativeRotationOffset.y();
|
||||
rel_rot_offset_prop->z = accessory.relativeRotationOffset.z();
|
||||
auto local_scale_prop = acc_prop->at<VectorStructProperty>(MASS_ACCESSORY_SCALE);
|
||||
local_scale_prop->x = accessory.localScale.x();
|
||||
local_scale_prop->y = accessory.localScale.y();
|
||||
local_scale_prop->z = accessory.localScale.z();
|
||||
}
|
||||
}
|
|
@ -1,391 +0,0 @@
|
|||
// 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 "PropertyNames.h"
|
||||
#include "../Logger/Logger.h"
|
||||
#include "../UESaveFile/Types/ArrayProperty.h"
|
||||
#include "../UESaveFile/Types/ColourStructProperty.h"
|
||||
#include "../UESaveFile/Types/FloatProperty.h"
|
||||
#include "../UESaveFile/Types/GenericStructProperty.h"
|
||||
#include "../UESaveFile/Types/IntProperty.h"
|
||||
|
||||
#include "Mass.h"
|
||||
|
||||
using namespace Containers::Literals;
|
||||
|
||||
auto Mass::jointSliders() -> Joints& {
|
||||
return _frame.joints;
|
||||
}
|
||||
|
||||
void Mass::getJointSliders() {
|
||||
LOG_INFO("Getting joint sliders.");
|
||||
|
||||
auto unit_data = _mass->at<GenericStructProperty>(MASS_UNIT_DATA);
|
||||
if(!unit_data) {
|
||||
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_UNIT_DATA, _filename);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
auto frame_prop = unit_data->at<GenericStructProperty>(MASS_FRAME);
|
||||
if(!frame_prop) {
|
||||
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_FRAME, _filename);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
auto length = frame_prop->at<FloatProperty>(MASS_JOINT_NECK);
|
||||
_frame.joints.neck = (length ? length->value : 0.0f);
|
||||
length = frame_prop->at<FloatProperty>(MASS_JOINT_BODY);
|
||||
_frame.joints.body = (length ? length->value : 0.0f);
|
||||
length = frame_prop->at<FloatProperty>(MASS_JOINT_SHOULDER);
|
||||
_frame.joints.shoulders = (length ? length->value : 0.0f);
|
||||
length = frame_prop->at<FloatProperty>(MASS_JOINT_HIP);
|
||||
_frame.joints.hips = (length ? length->value : 0.0f);
|
||||
length = frame_prop->at<FloatProperty>(MASS_JOINT_ARM_UPPER);
|
||||
_frame.joints.upperArms = (length ? length->value : 0.0f);
|
||||
length = frame_prop->at<FloatProperty>(MASS_JOINT_ARM_LOWER);
|
||||
_frame.joints.lowerArms = (length ? length->value : 0.0f);
|
||||
length = frame_prop->at<FloatProperty>(MASS_JOINT_LEG_UPPER);
|
||||
_frame.joints.upperLegs = (length ? length->value : 0.0f);
|
||||
length = frame_prop->at<FloatProperty>(MASS_JOINT_LEG_LOWER);
|
||||
_frame.joints.lowerLegs = (length ? length->value : 0.0f);
|
||||
}
|
||||
|
||||
auto Mass::writeJointSliders() -> bool {
|
||||
LOG_INFO("Writing joint sliders");
|
||||
|
||||
auto unit_data = _mass->at<GenericStructProperty>(MASS_UNIT_DATA);
|
||||
if(!unit_data) {
|
||||
_lastError = "No unit data in "_s + _filename;
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto frame_prop = unit_data->at<GenericStructProperty>(MASS_FRAME);
|
||||
|
||||
if(!frame_prop) {
|
||||
_lastError = "No frame data in "_s + _filename;
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
Containers::Array<UnrealPropertyBase::ptr> temp;
|
||||
|
||||
auto length = frame_prop->atMove<FloatProperty>(MASS_JOINT_NECK);
|
||||
if(_frame.joints.neck != 0.0f) {
|
||||
if(!length) {
|
||||
length.emplace();
|
||||
length->name.emplace(MASS_JOINT_NECK);
|
||||
}
|
||||
length->value = _frame.joints.neck;
|
||||
arrayAppend(temp, std::move(length));
|
||||
}
|
||||
|
||||
length = frame_prop->atMove<FloatProperty>(MASS_JOINT_BODY);
|
||||
if(_frame.joints.body != 0.0f) {
|
||||
if(!length) {
|
||||
length.emplace();
|
||||
length->name.emplace(MASS_JOINT_BODY);
|
||||
}
|
||||
length->value = _frame.joints.body;
|
||||
arrayAppend(temp, std::move(length));
|
||||
}
|
||||
|
||||
length = frame_prop->atMove<FloatProperty>(MASS_JOINT_SHOULDER);
|
||||
if(_frame.joints.shoulders != 0.0f) {
|
||||
if(!length) {
|
||||
length.emplace();
|
||||
length->name.emplace(MASS_JOINT_SHOULDER);
|
||||
}
|
||||
length->value = _frame.joints.shoulders;
|
||||
arrayAppend(temp, std::move(length));
|
||||
}
|
||||
|
||||
length = frame_prop->atMove<FloatProperty>(MASS_JOINT_ARM_UPPER);
|
||||
if(_frame.joints.upperArms != 0.0f) {
|
||||
if(!length) {
|
||||
length.emplace();
|
||||
length->name.emplace(MASS_JOINT_ARM_UPPER);
|
||||
}
|
||||
length->value = _frame.joints.upperArms;
|
||||
arrayAppend(temp, std::move(length));
|
||||
}
|
||||
|
||||
length = frame_prop->atMove<FloatProperty>(MASS_JOINT_ARM_LOWER);
|
||||
if(_frame.joints.lowerArms != 0.0f) {
|
||||
if(!length) {
|
||||
length.emplace();
|
||||
length->name.emplace(MASS_JOINT_ARM_LOWER);
|
||||
}
|
||||
length->value = _frame.joints.lowerArms;
|
||||
arrayAppend(temp, std::move(length));
|
||||
}
|
||||
|
||||
length = frame_prop->atMove<FloatProperty>(MASS_JOINT_HIP);
|
||||
if(_frame.joints.hips != 0.0f) {
|
||||
if(!length) {
|
||||
length.emplace();
|
||||
length->name.emplace(MASS_JOINT_HIP);
|
||||
}
|
||||
length->value = _frame.joints.hips;
|
||||
arrayAppend(temp, std::move(length));
|
||||
}
|
||||
|
||||
length = frame_prop->atMove<FloatProperty>(MASS_JOINT_LEG_UPPER);
|
||||
if(_frame.joints.upperLegs != 0.0f) {
|
||||
if(!length) {
|
||||
length.emplace();
|
||||
length->name.emplace(MASS_JOINT_LEG_UPPER);
|
||||
}
|
||||
length->value = _frame.joints.upperLegs;
|
||||
arrayAppend(temp, std::move(length));
|
||||
}
|
||||
|
||||
length = frame_prop->atMove<FloatProperty>(MASS_JOINT_LEG_LOWER);
|
||||
if(_frame.joints.lowerLegs != 0.0f) {
|
||||
if(!length) {
|
||||
length.emplace();
|
||||
length->name.emplace(MASS_JOINT_LEG_LOWER);
|
||||
}
|
||||
length->value = _frame.joints.lowerLegs;
|
||||
arrayAppend(temp, std::move(length));
|
||||
}
|
||||
|
||||
arrayAppend(temp, std::move(frame_prop->properties[frame_prop->properties.size() - 3]));
|
||||
arrayAppend(temp, std::move(frame_prop->properties[frame_prop->properties.size() - 2]));
|
||||
arrayAppend(temp, std::move(frame_prop->properties[frame_prop->properties.size() - 1]));
|
||||
|
||||
frame_prop->properties = std::move(temp);
|
||||
|
||||
if(!_mass->saveToFile()) {
|
||||
_lastError = _mass->lastError();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
auto Mass::frameStyles() -> Containers::ArrayView<Int> {
|
||||
return _frame.styles;
|
||||
}
|
||||
|
||||
void Mass::getFrameStyles() {
|
||||
LOG_INFO("Getting frame styles.");
|
||||
|
||||
auto unit_data = _mass->at<GenericStructProperty>(MASS_UNIT_DATA);
|
||||
if(!unit_data) {
|
||||
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_UNIT_DATA, _filename);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
auto frame_prop = unit_data->at<GenericStructProperty>(MASS_FRAME);
|
||||
if(!frame_prop) {
|
||||
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_FRAME, _filename);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
auto frame_styles = frame_prop->at<ArrayProperty>(MASS_FRAME_STYLES);
|
||||
if(!frame_styles) {
|
||||
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_FRAME_STYLES, _filename);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
if(frame_styles->items.size() != _frame.styles.size()) {
|
||||
LOG_ERROR_FORMAT("Frame style arrays are not of the same size. Expected {}, got {} instead.",
|
||||
_frame.styles.size(), frame_styles->items.size());
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
for(UnsignedInt i = 0; i < frame_styles->items.size(); i++) {
|
||||
_frame.styles[i] = frame_styles->at<IntProperty>(i)->value;
|
||||
}
|
||||
}
|
||||
|
||||
auto Mass::writeFrameStyles() -> bool {
|
||||
LOG_INFO("Writing frame styles.");
|
||||
|
||||
auto unit_data = _mass->at<GenericStructProperty>(MASS_UNIT_DATA);
|
||||
if(!unit_data) {
|
||||
_lastError = "No unit data in "_s + _filename;
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto frame = unit_data->at<GenericStructProperty>(MASS_FRAME);
|
||||
if(!frame) {
|
||||
_lastError = "No frame data in "_s + _filename;
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto frame_styles = frame->at<ArrayProperty>(MASS_FRAME_STYLES);
|
||||
if(!frame_styles) {
|
||||
_lastError = "No frame styles in "_s + _filename;
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
for(UnsignedInt i = 0; i < frame_styles->items.size(); i++) {
|
||||
frame_styles->at<IntProperty>(i)->value = _frame.styles[i];
|
||||
}
|
||||
|
||||
if(!_mass->saveToFile()) {
|
||||
_lastError = _mass->lastError();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
auto Mass::eyeFlareColour() -> Color4& {
|
||||
return _frame.eyeFlare;
|
||||
}
|
||||
|
||||
void Mass::getEyeFlareColour() {
|
||||
LOG_INFO("Getting the eye flare colour.");
|
||||
|
||||
auto unit_data = _mass->at<GenericStructProperty>(MASS_UNIT_DATA);
|
||||
if(!unit_data) {
|
||||
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_UNIT_DATA, _filename);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
auto frame_prop = unit_data->at<GenericStructProperty>(MASS_FRAME);
|
||||
if(!frame_prop) {
|
||||
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_FRAME, _filename);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
auto eye_flare_prop = frame_prop->at<ColourStructProperty>(MASS_EYE_FLARE);
|
||||
if(!eye_flare_prop) {
|
||||
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_EYE_FLARE, _filename);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
_frame.eyeFlare = Color4{eye_flare_prop->r, eye_flare_prop->g, eye_flare_prop->b, eye_flare_prop->a};
|
||||
}
|
||||
|
||||
auto Mass::writeEyeFlareColour() -> bool {
|
||||
LOG_INFO("Writing the eye flare colour.");
|
||||
|
||||
auto unit_data = _mass->at<GenericStructProperty>(MASS_UNIT_DATA);
|
||||
if(!unit_data) {
|
||||
_lastError = "No unit data in "_s + _filename;
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto frame = unit_data->at<GenericStructProperty>(MASS_FRAME);
|
||||
if(!frame) {
|
||||
_lastError = "No frame data in "_s + _filename;
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto eye_flare_prop = frame->at<ColourStructProperty>(MASS_EYE_FLARE);
|
||||
if(!eye_flare_prop) {
|
||||
_lastError = "No eye flare property in "_s + _filename;
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
eye_flare_prop->r = _frame.eyeFlare.r();
|
||||
eye_flare_prop->g = _frame.eyeFlare.g();
|
||||
eye_flare_prop->b = _frame.eyeFlare.b();
|
||||
eye_flare_prop->a = _frame.eyeFlare.a();
|
||||
|
||||
if(!_mass->saveToFile()) {
|
||||
_lastError = _mass->lastError();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
auto Mass::frameCustomStyles() -> Containers::ArrayView<CustomStyle> {
|
||||
return _frame.customStyles;
|
||||
}
|
||||
|
||||
void Mass::getFrameCustomStyles() {
|
||||
LOG_INFO("Getting the frame's custom styles.");
|
||||
|
||||
auto unit_data = _mass->at<GenericStructProperty>(MASS_UNIT_DATA);
|
||||
if(!unit_data) {
|
||||
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_UNIT_DATA, _filename);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
auto frame_styles = unit_data->at<ArrayProperty>(MASS_CUSTOM_FRAME_STYLES);
|
||||
if(!frame_styles) {
|
||||
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_CUSTOM_FRAME_STYLES, _filename);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
if(frame_styles->items.size() != _frame.customStyles.size()) {
|
||||
LOG_ERROR_FORMAT("Frame custom style arrays are not of the same size. Expected {}, got {} instead.",
|
||||
_frame.customStyles.size(), frame_styles->items.size());
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
getCustomStyles(_frame.customStyles, frame_styles);
|
||||
}
|
||||
|
||||
auto Mass::writeFrameCustomStyle(UnsignedLong index) -> bool {
|
||||
LOG_INFO_FORMAT("Writing frame custom style number {}.", index);
|
||||
|
||||
if(index > _frame.customStyles.size()) {
|
||||
_lastError = "Style index out of range."_s;
|
||||
LOG_ERROR(_lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto unit_data = _mass->at<GenericStructProperty>(MASS_UNIT_DATA);
|
||||
if(!unit_data) {
|
||||
_lastError = "No unit data in "_s + _filename;
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto frame_styles = unit_data->at<ArrayProperty>(MASS_CUSTOM_FRAME_STYLES);
|
||||
if(!frame_styles) {
|
||||
_lastError = "No frame styles in "_s + _filename;
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
return writeCustomStyle(_frame.customStyles[index], index, frame_styles);
|
||||
}
|
|
@ -1,145 +0,0 @@
|
|||
// 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 "PropertyNames.h"
|
||||
#include "../Logger/Logger.h"
|
||||
#include "../UESaveFile/Types/ArrayProperty.h"
|
||||
#include "../UESaveFile/Types/ColourStructProperty.h"
|
||||
#include "../UESaveFile/Types/FloatProperty.h"
|
||||
#include "../UESaveFile/Types/GenericStructProperty.h"
|
||||
#include "../UESaveFile/Types/IntProperty.h"
|
||||
#include "../UESaveFile/Types/StringProperty.h"
|
||||
|
||||
#include "Mass.h"
|
||||
|
||||
using namespace Containers::Literals;
|
||||
|
||||
auto Mass::globalStyles() -> Containers::ArrayView<CustomStyle> {
|
||||
return _globalStyles;
|
||||
}
|
||||
|
||||
void Mass::getGlobalStyles() {
|
||||
LOG_INFO("Getting global styles.");
|
||||
|
||||
auto unit_data = _mass->at<GenericStructProperty>(MASS_UNIT_DATA);
|
||||
if(!unit_data) {
|
||||
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_UNIT_DATA, _filename);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
auto global_styles = unit_data->at<ArrayProperty>(MASS_GLOBAL_STYLES);
|
||||
if(!global_styles) {
|
||||
LOG_WARNING_FORMAT("Couldn't find global styles in {}.", _filename);
|
||||
_globalStyles = Containers::Array<CustomStyle>{0};
|
||||
return;
|
||||
}
|
||||
|
||||
if(global_styles->items.size() != _globalStyles.size()) {
|
||||
_globalStyles = Containers::Array<CustomStyle>{global_styles->items.size()};
|
||||
}
|
||||
|
||||
getCustomStyles(_globalStyles, global_styles);
|
||||
}
|
||||
|
||||
auto Mass::writeGlobalStyle(UnsignedLong index) -> bool {
|
||||
LOG_INFO_FORMAT("Writing global style number {}.", index);
|
||||
|
||||
if(index > _globalStyles.size()) {
|
||||
_lastError = "Global style index out of range"_s;
|
||||
LOG_ERROR(_lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto unit_data = _mass->at<GenericStructProperty>(MASS_UNIT_DATA);
|
||||
if(!unit_data) {
|
||||
_lastError = "No unit data found in "_s + _filename;
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto global_styles = unit_data->at<ArrayProperty>(MASS_GLOBAL_STYLES);
|
||||
if(!global_styles) {
|
||||
_lastError = "No global styles found in "_s + _filename;
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
return writeCustomStyle(_globalStyles[index], index, global_styles);
|
||||
}
|
||||
|
||||
void Mass::getCustomStyles(Containers::ArrayView<CustomStyle> styles, ArrayProperty* style_array) {
|
||||
for(UnsignedInt i = 0; i < style_array->items.size(); i++) {
|
||||
auto style_prop = style_array->at<GenericStructProperty>(i);
|
||||
auto& style = styles[i];
|
||||
|
||||
style.name = style_prop->at<StringProperty>(MASS_STYLE_NAME)->value;
|
||||
auto colour_prop = style_prop->at<ColourStructProperty>(MASS_STYLE_COLOUR);
|
||||
style.colour = Color4{colour_prop->r, colour_prop->g, colour_prop->b, colour_prop->a};
|
||||
style.metallic = style_prop->at<FloatProperty>(MASS_STYLE_METALLIC)->value;
|
||||
style.gloss = style_prop->at<FloatProperty>(MASS_STYLE_GLOSS)->value;
|
||||
style.glow = colour_prop->a != 0.0f;
|
||||
|
||||
style.patternId = style_prop->at<IntProperty>(MASS_STYLE_PATTERN_ID)->value;
|
||||
style.opacity = style_prop->at<FloatProperty>(MASS_STYLE_PATTERN_OPACITY)->value;
|
||||
style.offset = Vector2{
|
||||
style_prop->at<FloatProperty>(MASS_STYLE_PATTERN_OFFSETX)->value,
|
||||
style_prop->at<FloatProperty>(MASS_STYLE_PATTERN_OFFSETY)->value
|
||||
};
|
||||
style.rotation = style_prop->at<FloatProperty>(MASS_STYLE_PATTERN_ROTATION)->value;
|
||||
style.scale = style_prop->at<FloatProperty>(MASS_STYLE_PATTERN_SCALE)->value;
|
||||
}
|
||||
}
|
||||
|
||||
auto Mass::writeCustomStyle(const CustomStyle& style, UnsignedLong index, ArrayProperty* style_array) -> bool {
|
||||
if(!style_array) {
|
||||
_lastError = "style_array is null."_s;
|
||||
LOG_ERROR(_lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto style_prop = style_array->at<GenericStructProperty>(index);
|
||||
if(!style_prop) {
|
||||
_lastError = "Style index is out of range in "_s + _filename;
|
||||
LOG_ERROR(_lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
style_prop->at<StringProperty>(MASS_STYLE_NAME)->value = style.name;
|
||||
auto colour_prop = style_prop->at<ColourStructProperty>(MASS_STYLE_COLOUR);
|
||||
colour_prop->r = style.colour.r();
|
||||
colour_prop->g = style.colour.g();
|
||||
colour_prop->b = style.colour.b();
|
||||
colour_prop->a = style.glow ? 1.0f : 0.0f;
|
||||
style_prop->at<FloatProperty>(MASS_STYLE_METALLIC)->value = style.metallic;
|
||||
style_prop->at<FloatProperty>(MASS_STYLE_GLOSS)->value = style.gloss;
|
||||
|
||||
style_prop->at<IntProperty>(MASS_STYLE_PATTERN_ID)->value = style.patternId;
|
||||
style_prop->at<FloatProperty>(MASS_STYLE_PATTERN_OPACITY)->value = style.opacity;
|
||||
style_prop->at<FloatProperty>(MASS_STYLE_PATTERN_OFFSETX)->value = style.offset.x();
|
||||
style_prop->at<FloatProperty>(MASS_STYLE_PATTERN_OFFSETY)->value = style.offset.y();
|
||||
style_prop->at<FloatProperty>(MASS_STYLE_PATTERN_ROTATION)->value = style.rotation;
|
||||
style_prop->at<FloatProperty>(MASS_STYLE_PATTERN_SCALE)->value = style.scale;
|
||||
|
||||
if(!_mass->saveToFile()) {
|
||||
_lastError = _mass->lastError();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
|
@ -1,360 +0,0 @@
|
|||
// 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 "PropertyNames.h"
|
||||
#include "../Logger/Logger.h"
|
||||
#include "../UESaveFile/Types/ArrayProperty.h"
|
||||
#include "../UESaveFile/Types/BoolProperty.h"
|
||||
#include "../UESaveFile/Types/ByteProperty.h"
|
||||
#include "../UESaveFile/Types/ColourStructProperty.h"
|
||||
#include "../UESaveFile/Types/GenericStructProperty.h"
|
||||
#include "../UESaveFile/Types/IntProperty.h"
|
||||
#include "../UESaveFile/Types/StringProperty.h"
|
||||
|
||||
#include "Mass.h"
|
||||
|
||||
using namespace Containers::Literals;
|
||||
|
||||
auto Mass::meleeWeapons() -> Containers::ArrayView<Weapon> {
|
||||
return _weapons.melee;
|
||||
}
|
||||
|
||||
void Mass::getMeleeWeapons() {
|
||||
LOG_INFO("Getting melee weapons.");
|
||||
getWeaponType(MASS_WEAPONS_MELEE, _weapons.melee);
|
||||
}
|
||||
|
||||
auto Mass::writeMeleeWeapons() -> bool {
|
||||
LOG_INFO("Writing melee weapons.");
|
||||
return writeWeaponType(MASS_WEAPONS_MELEE, _weapons.melee);
|
||||
}
|
||||
|
||||
auto Mass::shields() -> Containers::ArrayView<Weapon> {
|
||||
return _weapons.shields;
|
||||
}
|
||||
|
||||
void Mass::getShields() {
|
||||
LOG_INFO("Getting shields.");
|
||||
getWeaponType(MASS_WEAPONS_SHIELD, _weapons.shields);
|
||||
}
|
||||
|
||||
auto Mass::writeShields() -> bool {
|
||||
LOG_INFO("Writing shields.");
|
||||
return writeWeaponType(MASS_WEAPONS_SHIELD, _weapons.shields);
|
||||
}
|
||||
|
||||
auto Mass::bulletShooters() -> Containers::ArrayView<Weapon> {
|
||||
return _weapons.bulletShooters;
|
||||
}
|
||||
|
||||
void Mass::getBulletShooters() {
|
||||
LOG_INFO("Getting bullet shooters.");
|
||||
getWeaponType(MASS_WEAPONS_BSHOOTER, _weapons.bulletShooters);
|
||||
}
|
||||
|
||||
auto Mass::writeBulletShooters() -> bool {
|
||||
LOG_INFO("Writing bullet shooters.");
|
||||
return writeWeaponType(MASS_WEAPONS_BSHOOTER, _weapons.bulletShooters);
|
||||
}
|
||||
|
||||
auto Mass::energyShooters() -> Containers::ArrayView<Weapon> {
|
||||
return _weapons.energyShooters;
|
||||
}
|
||||
|
||||
void Mass::getEnergyShooters() {
|
||||
LOG_INFO("Getting energy shooters.");
|
||||
getWeaponType(MASS_WEAPONS_ESHOOTER, _weapons.energyShooters);
|
||||
}
|
||||
|
||||
auto Mass::writeEnergyShooters() -> bool {
|
||||
LOG_INFO("Writing energy shooters.");
|
||||
return writeWeaponType(MASS_WEAPONS_ESHOOTER, _weapons.energyShooters);
|
||||
}
|
||||
|
||||
auto Mass::bulletLaunchers() -> Containers::ArrayView<Weapon> {
|
||||
return _weapons.bulletLaunchers;
|
||||
}
|
||||
|
||||
void Mass::getBulletLaunchers() {
|
||||
LOG_INFO("Getting bullet launchers.");
|
||||
getWeaponType(MASS_WEAPONS_BLAUNCHER, _weapons.bulletLaunchers);
|
||||
}
|
||||
|
||||
auto Mass::writeBulletLaunchers() -> bool {
|
||||
LOG_INFO("Writing bullet launchers.");
|
||||
return writeWeaponType(MASS_WEAPONS_BLAUNCHER, _weapons.bulletLaunchers);
|
||||
}
|
||||
|
||||
auto Mass::energyLaunchers() -> Containers::ArrayView<Weapon> {
|
||||
return _weapons.energyLaunchers;
|
||||
}
|
||||
|
||||
void Mass::getEnergyLaunchers() {
|
||||
LOG_INFO("Getting energy launchers.");
|
||||
getWeaponType(MASS_WEAPONS_ELAUNCHER, _weapons.energyLaunchers);
|
||||
}
|
||||
|
||||
auto Mass::writeEnergyLaunchers() -> bool {
|
||||
LOG_INFO("Writing energy launchers.");
|
||||
return writeWeaponType(MASS_WEAPONS_ELAUNCHER, _weapons.energyLaunchers);
|
||||
}
|
||||
|
||||
void Mass::getWeaponType(Containers::StringView prop_name, Containers::ArrayView<Weapon> weapon_array) {
|
||||
auto unit_data = _mass->at<GenericStructProperty>(MASS_UNIT_DATA);
|
||||
if(!unit_data) {
|
||||
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_UNIT_DATA, _filename);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
auto prop = unit_data->at<ArrayProperty>(prop_name);
|
||||
if(!prop) {
|
||||
LOG_ERROR_FORMAT("Couldn't find {} in {}.", prop_name, _filename);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
if(prop->items.size() != weapon_array.size()) {
|
||||
LOG_ERROR_FORMAT("Weapon arrays are not of the same size. Expected {}, got {} instead.",
|
||||
weapon_array.size(), prop->items.size());
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
for(UnsignedInt i = 0; i < weapon_array.size(); i++) {
|
||||
auto weapon_prop = prop->at<GenericStructProperty>(i);
|
||||
auto& weapon = weapon_array[i];
|
||||
|
||||
weapon.name = weapon_prop->at<StringProperty>(MASS_WEAPON_NAME)->value;
|
||||
auto& weapon_type = weapon_prop->at<ByteProperty>(MASS_WEAPON_TYPE)->enumValue;
|
||||
#define c(enumerator, strenum, name) if(weapon_type == (strenum)) { weapon.type = WeaponType::enumerator; } else
|
||||
#include "../Maps/WeaponTypes.hpp"
|
||||
#undef c
|
||||
{
|
||||
LOG_ERROR_FORMAT("Invalid weapon type {} in {}.", weapon_type, _filename);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
auto parts_prop = weapon_prop->at<ArrayProperty>(MASS_WEAPON_ELEMENT);
|
||||
weapon.parts = Containers::Array<WeaponPart>{ValueInit, parts_prop->items.size()};
|
||||
|
||||
for(UnsignedInt j = 0; j < parts_prop->items.size(); j++) {
|
||||
auto part_prop = parts_prop->at<GenericStructProperty>(j);
|
||||
auto& part = weapon.parts[j];
|
||||
|
||||
part.id = part_prop->at<IntProperty>(MASS_WEAPON_PART_ID)->value;
|
||||
|
||||
auto part_styles = part_prop->at<ArrayProperty>(MASS_WEAPON_PART_STYLES);
|
||||
for(UnsignedInt k = 0; k < part_styles->items.size(); k++) {
|
||||
part.styles[k] = part_styles->at<IntProperty>(k)->value;
|
||||
}
|
||||
|
||||
auto part_decals = part_prop->at<ArrayProperty>(MASS_WEAPON_PART_DECALS);
|
||||
if(part_decals->items.size() != part.decals.size()) {
|
||||
part.decals = Containers::Array<Decal>{part_decals->items.size()};
|
||||
}
|
||||
|
||||
getDecals(part.decals, part_decals);
|
||||
|
||||
auto part_accs = part_prop->at<ArrayProperty>(MASS_WEAPON_PART_ACCESSORIES);
|
||||
if(!part_accs) {
|
||||
part.accessories = Containers::Array<Accessory>{0};
|
||||
continue;
|
||||
}
|
||||
|
||||
if(part_accs->items.size() != part.accessories.size()) {
|
||||
part.accessories = Containers::Array<Accessory>{part_accs->items.size()};
|
||||
}
|
||||
getAccessories(part.accessories, part_accs);
|
||||
}
|
||||
|
||||
auto custom_styles = weapon_prop->at<ArrayProperty>(MASS_CUSTOM_WEAPON_STYLES);
|
||||
if(!custom_styles) {
|
||||
LOG_ERROR_FORMAT("Can't find weapon custom styles in {}", _filename);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
if(custom_styles->items.size() != weapon.customStyles.size()) {
|
||||
LOG_ERROR_FORMAT("Custom weapon style arrays are not of the same size. Expected {}, got {} instead.",
|
||||
weapon.customStyles.size(), custom_styles->items.size());
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
getCustomStyles(weapon.customStyles, custom_styles);
|
||||
|
||||
weapon.attached = weapon_prop->at<BoolProperty>(MASS_WEAPON_ATTACH)->value;
|
||||
auto& damage_type = weapon_prop->at<ByteProperty>(MASS_WEAPON_DAMAGE_TYPE)->enumValue;
|
||||
#define c(enumerator, strenum) if(damage_type == (strenum)) { weapon.damageType = DamageType::enumerator; } else
|
||||
#include "../Maps/DamageTypes.hpp"
|
||||
#undef c
|
||||
{
|
||||
LOG_ERROR_FORMAT("Invalid damage type {} in {}.", damage_type, _filename);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
weapon.dualWield = weapon_prop->at<BoolProperty>(MASS_WEAPON_DUAL_WIELD)->value;
|
||||
auto& effect_colour_mode = weapon_prop->at<ByteProperty>(MASS_WEAPON_COLOUR_EFX_MODE)->enumValue;
|
||||
#define c(enumerator, strenum) if(effect_colour_mode == (strenum)) { weapon.effectColourMode = EffectColourMode::enumerator; } else
|
||||
#include "../Maps/EffectColourModes.hpp"
|
||||
#undef c
|
||||
{
|
||||
LOG_ERROR_FORMAT("Invalid effect colour mode {} in {}.", effect_colour_mode, _filename);
|
||||
_state = State::Invalid;
|
||||
return;
|
||||
}
|
||||
auto effect_colour = weapon_prop->at<ColourStructProperty>(MASS_WEAPON_COLOUR_EFX);
|
||||
weapon.effectColour = Color4{effect_colour->r, effect_colour->g, effect_colour->b, effect_colour->a};
|
||||
}
|
||||
}
|
||||
|
||||
auto Mass::writeWeaponType(Containers::StringView prop_name, Containers::ArrayView<Weapon> weapon_array) -> bool {
|
||||
auto unit_data = _mass->at<GenericStructProperty>(MASS_UNIT_DATA);
|
||||
if(!unit_data) {
|
||||
_lastError = "No unit data in "_s + _filename;
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto prop = unit_data->at<ArrayProperty>(prop_name);
|
||||
if(!prop) {
|
||||
_lastError = prop_name + " not found in "_s + _filename;
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(prop->items.size() != weapon_array.size()) {
|
||||
_lastError = Utility::format("Weapon arrays are not of the same size. Expected {}, got {} instead.",
|
||||
weapon_array.size(), prop->items.size());
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
for(UnsignedInt i = 0; i < weapon_array.size(); i++) {
|
||||
auto weapon_prop = prop->at<GenericStructProperty>(i);
|
||||
auto& weapon = weapon_array[i];
|
||||
|
||||
weapon_prop->at<StringProperty>(MASS_WEAPON_NAME)->value = weapon.name;
|
||||
switch(weapon.type) {
|
||||
#define c(enumerator, strenum, name) case WeaponType::enumerator: weapon_prop->at<ByteProperty>(MASS_WEAPON_TYPE)->enumValue = strenum; break;
|
||||
#include "../Maps/WeaponTypes.hpp"
|
||||
#undef c
|
||||
default:
|
||||
_lastError = Utility::format("Invalid weapon type at index {}.", i);
|
||||
LOG_ERROR(_lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto parts_prop = weapon_prop->at<ArrayProperty>(MASS_WEAPON_ELEMENT);
|
||||
if(parts_prop->items.size() != weapon.parts.size()) {
|
||||
_lastError = Utility::format("Weapon part arrays are not of the same size. Expected {}, got {} instead.",
|
||||
weapon.parts.size(), parts_prop->items.size());
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
for(UnsignedInt j = 0; j < parts_prop->items.size(); j++) {
|
||||
auto part_prop = parts_prop->at<GenericStructProperty>(j);
|
||||
auto& part = weapon.parts[j];
|
||||
|
||||
part_prop->at<IntProperty>(MASS_WEAPON_PART_ID)->value = part.id;
|
||||
|
||||
auto part_styles = part_prop->at<ArrayProperty>(MASS_WEAPON_PART_STYLES);
|
||||
for(UnsignedInt k = 0; k < part_styles->items.size(); k++) {
|
||||
part_styles->at<IntProperty>(k)->value = part.styles[k];
|
||||
}
|
||||
|
||||
auto part_decals = part_prop->at<ArrayProperty>(MASS_WEAPON_PART_DECALS);
|
||||
writeDecals(part.decals, part_decals);
|
||||
|
||||
auto part_accs = part_prop->at<ArrayProperty>(MASS_WEAPON_PART_ACCESSORIES);
|
||||
if(!part_accs) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(part_accs->items.size() != part.accessories.size()) {
|
||||
_lastError = Utility::format("Part accessory arrays are not of the same size. Expected {}, got {} instead.",
|
||||
part.accessories.size(), part_accs->items.size());
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
writeAccessories(part.accessories, part_accs);
|
||||
}
|
||||
|
||||
auto custom_styles = weapon_prop->at<ArrayProperty>(MASS_CUSTOM_WEAPON_STYLES);
|
||||
if(!custom_styles) {
|
||||
_lastError = "No custom styles found for weapon."_s;
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(custom_styles->items.size() != weapon.customStyles.size()) {
|
||||
_lastError = Utility::format("Custom style arrays are not of the same size. Expected {}, got {} instead.",
|
||||
weapon.customStyles.size(), custom_styles->items.size());
|
||||
LOG_ERROR(_lastError);
|
||||
_state = State::Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
for(UnsignedInt j = 0; j < weapon.customStyles.size(); j++) {
|
||||
writeCustomStyle(weapon.customStyles[j], j, custom_styles);
|
||||
}
|
||||
|
||||
weapon_prop->at<BoolProperty>(MASS_WEAPON_ATTACH)->value = weapon.attached;
|
||||
switch(weapon.damageType) {
|
||||
#define c(enumerator, strenum) case DamageType::enumerator: weapon_prop->at<ByteProperty>(MASS_WEAPON_DAMAGE_TYPE)->enumValue = strenum; break;
|
||||
#include "../Maps/DamageTypes.hpp"
|
||||
#undef c
|
||||
default:
|
||||
_lastError = Utility::format("Invalid damage type at index {}.", i);
|
||||
LOG_ERROR(_lastError);
|
||||
return false;
|
||||
}
|
||||
weapon_prop->at<BoolProperty>(MASS_WEAPON_DUAL_WIELD)->value = weapon.dualWield;
|
||||
switch(weapon.effectColourMode) {
|
||||
#define c(enumerator, enumstr) case EffectColourMode::enumerator: \
|
||||
weapon_prop->at<ByteProperty>(MASS_WEAPON_COLOUR_EFX_MODE)->enumValue = enumstr; \
|
||||
break;
|
||||
#include "../Maps/EffectColourModes.hpp"
|
||||
#undef c
|
||||
default:
|
||||
_lastError = Utility::format("Invalid damage type at index {}.", i);
|
||||
LOG_ERROR(_lastError);
|
||||
return false;
|
||||
}
|
||||
auto effect_colour = weapon_prop->at<ColourStructProperty>(MASS_WEAPON_COLOUR_EFX);
|
||||
effect_colour->r = weapon.effectColour.r();
|
||||
effect_colour->g = weapon.effectColour.g();
|
||||
effect_colour->b = weapon.effectColour.b();
|
||||
effect_colour->a = weapon.effectColour.a();
|
||||
}
|
||||
|
||||
if(!_mass->saveToFile()) {
|
||||
_lastError = _mass->lastError();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#define MASS_UNIT_DATA "UnitData"
|
||||
#define MASS_NAME "Name_45_A037C5D54E53456407BDF091344529BB"
|
||||
#define MASS_ACCOUNT "Account"
|
||||
#define MASS_GLOBAL_STYLES "GlobalStyles_57_6A681C114035241F7BDAAE9B43A8BF1B"
|
||||
|
||||
// Frame stuff
|
||||
#define MASS_FRAME "Frame_3_F92B0F6A44A15088AF7F41B9FF290653"
|
||||
#define MASS_JOINT_NECK "NeckLength_6_ED6AF79849C27CD1A9D523A09E2BFE58"
|
||||
#define MASS_JOINT_BODY "BodyLength_7_C16287754CBA96C93BAE36A5C154996A"
|
||||
#define MASS_JOINT_SHOULDER "ShoulderLength_8_220EDF304F1C1226F0D8D39117FB3883"
|
||||
#define MASS_JOINT_ARM_UPPER "ArmUpperLength_10_249FDA3E4F3B399E7B9E5C9B7C765EAE"
|
||||
#define MASS_JOINT_ARM_LOWER "ArmLowerLength_12_ACD0F02745C28882619376926292FB36"
|
||||
#define MASS_JOINT_HIP "HipLength_14_02AEEEAC4376087B9C51F0AA7CC92818"
|
||||
#define MASS_JOINT_LEG_UPPER "LegUpperLength_16_A7C4C71249A3776F7A543D96819C0C61"
|
||||
#define MASS_JOINT_LEG_LOWER "LegLowerLength_18_D2DF39964EA0F2A2129D0491B08A032F"
|
||||
#define MASS_FRAME_STYLES "Styles_32_00A3B3284B37F1E7819458844A20EB48"
|
||||
#define MASS_EYE_FLARE "EyeFlareColor_36_AF79999C40FCA0E88A2F9A84488A38CA"
|
||||
#define MASS_CUSTOM_FRAME_STYLES "FrameStyle_44_04A44C9440363CCEC5443D98BFAF22AA"
|
||||
|
||||
// Armour stuff
|
||||
#define MASS_ARMOUR_PARTS "Armor_10_12E266C44116DDAF57E99ABB575A4B3C"
|
||||
#define MASS_ARMOUR_SLOT "Slot_3_408BA56F4C9605C7E805CF91B642249C"
|
||||
#define MASS_ARMOUR_ID "ID_5_ACD101864D3481DE96EDACACC09BDD25"
|
||||
#define MASS_ARMOUR_STYLES "Styles_47_3E31870441DFD7DB8BEE5C85C26B365B"
|
||||
#define MASS_ARMOUR_DECALS "Decals_42_F358794A4F18497970F56BA9627D3603"
|
||||
#define MASS_ARMOUR_ACCESSORIES "Accessories_52_D902DD4241FA0050C2529596255153F3"
|
||||
#define MASS_CUSTOM_ARMOUR_STYLES "ArmorStyle_42_E2F6AC3647788CB366BD469B3B7E899E"
|
||||
|
||||
// Weapon stuff
|
||||
#define MASS_WEAPONS_MELEE "WeaponCC_22_0BBEC58C4A0EA1DB9E037B9339EE26A7"
|
||||
#define MASS_WEAPONS_SHIELD "Shield_53_839BFD7945481BAEA3E43A9C5CA8E92E"
|
||||
#define MASS_WEAPONS_BSHOOTER "WeaponBS_35_6EF6E0104FD7A138DF47F88CB57A83ED"
|
||||
#define MASS_WEAPONS_ESHOOTER "WeaponES_37_1A295D544528623880A0B1AC2C7DEE99"
|
||||
#define MASS_WEAPONS_BLAUNCHER "WeaponBL_36_5FD7C41E4613A75B44AB0E90B362846E"
|
||||
#define MASS_WEAPONS_ELAUNCHER "WeaponEL_38_9D23F3884ACA15902C9E6CA6E4995995"
|
||||
#define MASS_WEAPON_NAME "Name_13_7BF0D31F4E50C50C47231BB36A485D92"
|
||||
#define MASS_WEAPON_TYPE "Type_2_35ABA8C3406F8D9BBF14A89CD6BCE976"
|
||||
#define MASS_WEAPON_ELEMENT "Element_6_8E4617CC4B2C1F1490435599784EC6E0"
|
||||
#define MASS_CUSTOM_WEAPON_STYLES "Styles_10_8C3C82444B986AD7A99595AD4985912D"
|
||||
#define MASS_WEAPON_ATTACH "Attach_15_D00AABBD4AD6A04778D56D81E51927B3"
|
||||
#define MASS_WEAPON_DAMAGE_TYPE "DamageType_18_E1FFA53540591A9087EC698117A65C83"
|
||||
#define MASS_WEAPON_DUAL_WIELD "DualWield_20_B2EB2CEA4A6A233DC7575996B6DD1222"
|
||||
#define MASS_WEAPON_COLOUR_EFX_MODE "ColorEfxMode_24_D254BCF943E852BF9ADB8AAA8FD80014"
|
||||
#define MASS_WEAPON_COLOUR_EFX "ColorEfx_26_D921B62946C493E487455A831F4520AC"
|
||||
|
||||
// Weapon part stuff
|
||||
#define MASS_WEAPON_PART_ID "ID_2_A74D75434308158E5926178822DD28EE"
|
||||
#define MASS_WEAPON_PART_STYLES "Styles_17_994C97C34A90667BE5B716BFD0B97588"
|
||||
#define MASS_WEAPON_PART_DECALS "Decals_13_8B81112B453D7230C0CDE982185E14F1"
|
||||
#define MASS_WEAPON_PART_ACCESSORIES "Accessories_21_3878DE8B4ED0EA0DB725E98BCDC20E0C"
|
||||
|
||||
// BL attachment stuff
|
||||
#define MASS_BL_ATTACHMENT_STYLE "WeaponBLAttachmentStyle_65_5943FCE8406F18D2C3F69285EB23A699"
|
||||
#define MASS_BL_ATTACHMENTS "WeaponBLAttachment_61_442D08F547510A4CEE1501BBAF297BA0"
|
||||
#define MASS_BL_ATTACHMENT_SOCKET "Socket_9_B9DBF30D4A1F0032A2BE2F8B342B35A9"
|
||||
#define MASS_BL_ATTACHMENT_RELLOC "RelativeLocation_10_2F6E75DF4C40622658340E9A22D38B02"
|
||||
#define MASS_BL_ATTACHMENT_OFFLOC "OffsetLocation_11_F42B3DA3436948FF85752DB33722382F"
|
||||
#define MASS_BL_ATTACHMENT_RELROT "RelativeRotation_12_578140464621245132CFF2A2AD85E735"
|
||||
#define MASS_BL_ATTACHMENT_OFFROT "OffsetRotation_13_B5980BCD47905D842D1490A1A520B064"
|
||||
#define MASS_BL_ATTACHMENT_RELSCALE "RelativeScale_16_37BC80EF42699F79533F7AA7B3094E38"
|
||||
|
||||
// Style stuff
|
||||
#define MASS_STYLE_NAME "Name_27_1532115A46EF2B2FA283908DF561A86B"
|
||||
#define MASS_STYLE_COLOUR "Color_5_F0D383DF40474C9464AE48A0984A212E"
|
||||
#define MASS_STYLE_METALLIC "Metallic_10_0A4CD1E4482CBF41CA61D0A856DE90B9"
|
||||
#define MASS_STYLE_GLOSS "Gloss_11_9769599842CC275A401C4282A236E240"
|
||||
#define MASS_STYLE_PATTERN_ID "PatternID_14_516DB85641DAF8ECFD2920BE2BDF1311"
|
||||
#define MASS_STYLE_PATTERN_OPACITY "Opacity_30_53BD060B4DFCA1C92302D6A0F7831131"
|
||||
#define MASS_STYLE_PATTERN_OFFSETX "OffsetX_23_70FC2E814C64BBB82452748D2AF9CD48"
|
||||
#define MASS_STYLE_PATTERN_OFFSETY "OffsetY_24_5E1F866C4C054D9B2EE337ADC180C17F"
|
||||
#define MASS_STYLE_PATTERN_ROTATION "Rotation_25_EC2DFAD84AD0A6BD3FA841ACD52EDD6D"
|
||||
#define MASS_STYLE_PATTERN_SCALE "Scale_26_19DF0708409262183E1247B317137671"
|
||||
|
||||
// Decal stuff
|
||||
#define MASS_DECAL_ID "ID_3_694C0B35404D8A3168AEC89026BC8CF9"
|
||||
#define MASS_DECAL_COLOUR "Color_8_1B0B9D2B43DA6AAB9FA549B374D3E606"
|
||||
#define MASS_DECAL_POSITION "Position_41_022C8FE84E1AAFE587261E88F2C72250"
|
||||
#define MASS_DECAL_UAXIS "UAxis_37_EBEB715F45491AECACCC07A1AE4646D1"
|
||||
#define MASS_DECAL_VAXIS "VAxis_39_C31EB2664EE202CAECFBBB84100B5E35"
|
||||
#define MASS_DECAL_OFFSET "Offset_29_B02BBBB74FC60F5EDBEBAB8020738020"
|
||||
#define MASS_DECAL_SCALE "Scale_32_959D1C2747AFD8D62808468235CBBA40"
|
||||
#define MASS_DECAL_ROTATION "Rotation_27_12D7C314493D203D5C2326A03C5F910F"
|
||||
#define MASS_DECAL_FLIP "Flip_35_CECCFB184CCD9412BD93FE9A8B656BE1"
|
||||
#define MASS_DECAL_WRAP "Wrap_43_A7C68CDF4A92AF2ECDA53F953EE7CA62"
|
||||
|
||||
// Accessory stuff
|
||||
#define MASS_ACCESSORY_ATTACH_INDEX "AttachIndex_2_4AFCF6024E4BA7426C6B9F80B8179D20"
|
||||
#define MASS_ACCESSORY_ID "ID_4_5757B32647BAE263266259B8A7DFFFC1"
|
||||
#define MASS_ACCESSORY_STYLES "Styles_7_91DEB0F24E24D13FC9472882C11D0DFD"
|
||||
#define MASS_ACCESSORY_RELPOS "RelativePosition_14_BE8FB2A94074F34B3EDA6683B227D3A1"
|
||||
#define MASS_ACCESSORY_OFFPOS "RelativePositionOffset_15_98FD0CE74E44BBAFC2D46FB4CA4E0ED6"
|
||||
#define MASS_ACCESSORY_RELROT "RelativeRotation_20_C78C73274E6E78E7878F8C98ECA342C0"
|
||||
#define MASS_ACCESSORY_OFFROT "RelativeRotationOffset_21_E07FA0EC46728B7BA763C6861249ABAA"
|
||||
#define MASS_ACCESSORY_SCALE "LocalScale_24_DC2D93A742A41A46E7E61D988F15ED53"
|
||||
|
||||
// Tuning stuff
|
||||
#define MASS_ENGINE "Engine"
|
||||
#define MASS_GEARS "Gears"
|
||||
#define MASS_OS "OS"
|
||||
#define MASS_MODULES "Modules"
|
||||
#define MASS_ARCHITECT "Architect"
|
||||
#define MASS_TECHS "Techs"
|
|
@ -16,9 +16,10 @@
|
|||
// 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 <Corrade/Containers/String.h>
|
||||
|
||||
#include <Magnum/Magnum.h>
|
||||
#include <Magnum/Math/Color.h>
|
||||
|
@ -29,19 +30,28 @@
|
|||
using namespace Corrade;
|
||||
using namespace Magnum;
|
||||
|
||||
#define c(enumerator, ...) enumerator,
|
||||
enum class WeaponType {
|
||||
#include "../Maps/WeaponTypes.hpp"
|
||||
Melee = 0,
|
||||
Shield = 5,
|
||||
BulletShooter = 1,
|
||||
EnergyShooter = 2,
|
||||
BulletLauncher = 3,
|
||||
EnergyLauncher = 4,
|
||||
};
|
||||
|
||||
enum class DamageType {
|
||||
#include "../Maps/DamageTypes.hpp"
|
||||
Physical = 0,
|
||||
Piercing = 1,
|
||||
Plasma = 5,
|
||||
Heat = 2,
|
||||
Freeze = 3,
|
||||
Shock = 4,
|
||||
};
|
||||
|
||||
enum class EffectColourMode {
|
||||
#include "../Maps/EffectColourModes.hpp"
|
||||
Default = 0,
|
||||
Custom = 1,
|
||||
};
|
||||
#undef c
|
||||
|
||||
struct Weapon {
|
||||
Weapon() = default;
|
||||
|
@ -52,7 +62,7 @@ struct Weapon {
|
|||
Weapon(Weapon&& other) = default;
|
||||
Weapon& operator=(Weapon&& other) = default;
|
||||
|
||||
Containers::String name;
|
||||
std::string name;
|
||||
WeaponType type = WeaponType::Melee;
|
||||
Containers::Array<WeaponPart> parts;
|
||||
Containers::StaticArray<16, CustomStyle> customStyles{ValueInit};
|
||||
|
|
|
@ -16,30 +16,36 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
#include <Corrade/Utility/Format.h>
|
||||
#include <Corrade/Utility/Path.h>
|
||||
|
||||
#include "../Logger/Logger.h"
|
||||
#include <Corrade/Utility/Directory.h>
|
||||
#include <Corrade/Utility/FormatStl.h>
|
||||
#include <Corrade/Utility/String.h>
|
||||
|
||||
#include "MassManager.h"
|
||||
|
||||
using namespace Containers::Literals;
|
||||
static const std::string empty_string = "";
|
||||
|
||||
MassManager::MassManager(Containers::StringView save_path, Containers::StringView account, bool demo,
|
||||
Containers::StringView staging_dir):
|
||||
_saveDirectory{save_path}, _account{account}, _demo{demo}, _stagingAreaDirectory{staging_dir}
|
||||
MassManager::MassManager(const std::string& save_path, const std::string& steam_id, bool demo, const std::string& staging_dir):
|
||||
_saveDirectory{save_path},
|
||||
_steamId{steam_id},
|
||||
_demo{demo},
|
||||
_stagingAreaDirectory{staging_dir}
|
||||
{
|
||||
Containers::String mass_filename = "";
|
||||
for(UnsignedInt i = 0; i < _hangars.size(); i++) {
|
||||
mass_filename = Utility::Path::join(_saveDirectory,
|
||||
Utility::format("{}Unit{:.2d}{}.sav", demo ? "Demo"_s : ""_s, i, _account));
|
||||
new(&_hangars[i]) Mass{mass_filename};
|
||||
Containers::arrayReserve(_hangars, 32);
|
||||
|
||||
std::string mass_filename = "";
|
||||
for(int i = 0; i < 32; i++) {
|
||||
mass_filename = Utility::Directory::join(_saveDirectory, Utility::formatString("{}Unit{:.2d}{}.sav", demo ? "Demo" : "", i, _steamId));
|
||||
Containers::arrayAppend(_hangars, Mass{mass_filename});
|
||||
}
|
||||
|
||||
if(!Utility::Directory::exists(_stagingAreaDirectory)) {
|
||||
Utility::Directory::mkpath(_stagingAreaDirectory);
|
||||
}
|
||||
|
||||
refreshStagedMasses();
|
||||
}
|
||||
|
||||
auto MassManager::lastError() -> Containers::StringView {
|
||||
auto MassManager::lastError() -> std::string const& {
|
||||
return _lastError;
|
||||
}
|
||||
|
||||
|
@ -49,53 +55,47 @@ auto MassManager::hangar(Int hangar) -> Mass& {
|
|||
|
||||
void MassManager::refreshHangar(Int hangar) {
|
||||
if(hangar < 0 || hangar >= 32) {
|
||||
_lastError = "Hangar index out of range.";
|
||||
LOG_ERROR(_lastError);
|
||||
return;
|
||||
}
|
||||
|
||||
Containers::String mass_filename =
|
||||
Utility::Path::join(_saveDirectory,
|
||||
Utility::format("{}Unit{:.2d}{}.sav", _demo ? "Demo" : "", hangar, _account));
|
||||
std::string mass_filename =
|
||||
Utility::Directory::join(_saveDirectory, Utility::formatString("{}Unit{:.2d}{}.sav", _demo ? "Demo" : "", hangar, _steamId));
|
||||
_hangars[hangar] = Mass{mass_filename};
|
||||
}
|
||||
|
||||
auto MassManager::importMass(Containers::StringView staged_fn, Int hangar) -> bool {
|
||||
auto MassManager::importMass(const std::string& staged_fn, Int hangar) -> bool {
|
||||
if(hangar < 0 || hangar >= 32) {
|
||||
_lastError = "Hangar index out of range.";
|
||||
LOG_ERROR(_lastError);
|
||||
_lastError = "Hangar out of range in MassManager::importMass()";
|
||||
return false;
|
||||
}
|
||||
|
||||
auto it = _stagedMasses.find(Containers::String::nullTerminatedView(staged_fn));
|
||||
auto it = _stagedMasses.find(staged_fn);
|
||||
|
||||
if(it == _stagedMasses.end()) {
|
||||
_lastError = "Couldn't find "_s + staged_fn + " in the staged M.A.S.S.es."_s;
|
||||
LOG_ERROR(_lastError);
|
||||
_lastError = "Couldn't find " + staged_fn + " in the staged M.A.S.S.es.";
|
||||
return false;
|
||||
}
|
||||
|
||||
Containers::String source = Utility::Path::join(_stagingAreaDirectory, staged_fn);
|
||||
Utility::Path::copy(source, source + ".tmp"_s);
|
||||
std::string source = Utility::Directory::join(_stagingAreaDirectory, staged_fn);
|
||||
Utility::Directory::copy(source, source + ".tmp");
|
||||
|
||||
{
|
||||
Mass mass{source + ".tmp"_s};
|
||||
if(!mass.updateAccount(_account)) {
|
||||
Mass mass{source + ".tmp"};
|
||||
if(!mass.updateAccount(_steamId)) {
|
||||
_lastError = mass.lastError();
|
||||
Utility::Path::remove(source + ".tmp"_s);
|
||||
Utility::Directory::rm(source + ".tmp");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Containers::String dest = Utility::Path::join(_saveDirectory, _hangars[hangar].filename());
|
||||
std::string dest = Utility::Directory::join(_saveDirectory, _hangars[hangar].filename());
|
||||
|
||||
if(Utility::Path::exists(dest)) {
|
||||
Utility::Path::remove(dest);
|
||||
if(Utility::Directory::exists(dest)) {
|
||||
Utility::Directory::rm(dest);
|
||||
}
|
||||
|
||||
if(!Utility::Path::move(source + ".tmp"_s, dest)) {
|
||||
_lastError = Utility::format("Couldn't move {} to hangar {:.2d}", staged_fn, hangar + 1);
|
||||
LOG_ERROR(_lastError);
|
||||
if(!Utility::Directory::move(source + ".tmp", dest)) {
|
||||
_lastError = Utility::formatString("Couldn't move {} to hangar {:.2d}", staged_fn, hangar + 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -104,24 +104,21 @@ auto MassManager::importMass(Containers::StringView staged_fn, Int hangar) -> bo
|
|||
|
||||
auto MassManager::exportMass(Int hangar) -> bool {
|
||||
if(hangar < 0 || hangar >= 32) {
|
||||
_lastError = "Hangar index out of range."_s;
|
||||
LOG_ERROR(_lastError);
|
||||
_lastError = "Hangar out of range in MassManager::exportMass()";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(_hangars[hangar].state() != Mass::State::Valid) {
|
||||
_lastError = Utility::format("There is no valid data to export in hangar {:.2d}", hangar + 1);
|
||||
LOG_ERROR(_lastError);
|
||||
_lastError = Utility::formatString("There is no valid data to export in hangar {:.2d}", hangar + 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
Containers::String source = Utility::Path::join(_saveDirectory, _hangars[hangar].filename());
|
||||
Containers::String dest = Utility::Path::join(_stagingAreaDirectory,
|
||||
Utility::format("{}_{}.sav", _hangars[hangar].name(), _account));
|
||||
std::string source = Utility::Directory::join(_saveDirectory, _hangars[hangar].filename());
|
||||
std::string dest = Utility::Directory::join(_stagingAreaDirectory,
|
||||
Utility::formatString("{}_{}.sav", *_hangars[hangar].name(), _steamId));
|
||||
|
||||
if(!Utility::Path::copy(source, dest)) {
|
||||
_lastError = Utility::format("Couldn't export data from hangar {:.2d} to {}", hangar, dest);
|
||||
LOG_ERROR(_lastError);
|
||||
if(!Utility::Directory::copy(source, dest)) {
|
||||
_lastError = Utility::formatString("Couldn't export data from hangar {:.2d} to {}", hangar, dest);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -130,36 +127,34 @@ auto MassManager::exportMass(Int hangar) -> bool {
|
|||
|
||||
auto MassManager::moveMass(Int source, Int destination) -> bool {
|
||||
if(source < 0 || source >= 32) {
|
||||
_lastError = "Source hangar index out of range."_s;
|
||||
LOG_ERROR(_lastError);
|
||||
_lastError = "Source hangar out of range.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(destination < 0 || destination >= 32) {
|
||||
_lastError = "Destination hangar index out of range."_s;
|
||||
LOG_ERROR(_lastError);
|
||||
_lastError = "Destination hangar out of range.";
|
||||
return false;
|
||||
}
|
||||
|
||||
Containers::String source_file = Utility::Path::join(_saveDirectory, _hangars[source].filename());
|
||||
Containers::String dest_file = Utility::Path::join(_saveDirectory, _hangars[destination].filename());
|
||||
std::string source_file = Utility::Directory::join(_saveDirectory, _hangars[source].filename());
|
||||
std::string dest_file = Utility::Directory::join(_saveDirectory, _hangars[destination].filename());
|
||||
Mass::State dest_state = _hangars[destination].state();
|
||||
|
||||
switch(dest_state) {
|
||||
case Mass::State::Empty:
|
||||
break;
|
||||
case Mass::State::Invalid:
|
||||
Utility::Path::remove(dest_file);
|
||||
Utility::Directory::rm(dest_file);
|
||||
break;
|
||||
case Mass::State::Valid:
|
||||
Utility::Path::move(dest_file, dest_file + ".tmp"_s);
|
||||
Utility::Directory::move(dest_file, dest_file + ".tmp");
|
||||
break;
|
||||
}
|
||||
|
||||
Utility::Path::move(source_file, dest_file);
|
||||
Utility::Directory::move(source_file, dest_file);
|
||||
|
||||
if(dest_state == Mass::State::Valid) {
|
||||
Utility::Path::move(dest_file + ".tmp"_s, source_file);
|
||||
Utility::Directory::move(dest_file + ".tmp", source_file);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -167,86 +162,51 @@ auto MassManager::moveMass(Int source, Int destination) -> bool {
|
|||
|
||||
auto MassManager::deleteMass(Int hangar) -> bool {
|
||||
if(hangar < 0 || hangar >= 32) {
|
||||
_lastError = "Hangar index out of range."_s;
|
||||
LOG_ERROR(_lastError);
|
||||
_lastError = "Hangar out of range.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!Utility::Path::remove(Utility::Path::join(_saveDirectory, _hangars[hangar].filename()))) {
|
||||
_lastError = Utility::format("Deletion failed: {}", std::strerror(errno));
|
||||
LOG_ERROR(_lastError);
|
||||
if(!Utility::Directory::rm(Utility::Directory::join(_saveDirectory, _hangars[hangar].filename()))) {
|
||||
_lastError = Utility::formatString("Deletion failed: {}", std::strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
auto MassManager::stagedMasses() -> std::map<Containers::String, Containers::String> const& {
|
||||
auto MassManager::stagedMasses() -> std::map<std::string, std::string> const& {
|
||||
return _stagedMasses;
|
||||
}
|
||||
|
||||
void MassManager::refreshStagedMasses() {
|
||||
_stagedMasses.clear();
|
||||
|
||||
using Utility::Path::ListFlag;
|
||||
auto file_list = Utility::Path::list(_stagingAreaDirectory,
|
||||
ListFlag::SkipSpecial|ListFlag::SkipDirectories|ListFlag::SkipDotAndDotDot);
|
||||
using Utility::Directory::Flag;
|
||||
std::vector<std::string> file_list = Utility::Directory::list(_stagingAreaDirectory, Flag::SkipSpecial|Flag::SkipDirectories|Flag::SkipDotAndDotDot);
|
||||
|
||||
if(!file_list) {
|
||||
LOG_ERROR_FORMAT("{} couldn't be opened.", _stagingAreaDirectory);
|
||||
return;
|
||||
}
|
||||
|
||||
auto iter = std::remove_if(file_list->begin(), file_list->end(), [](Containers::StringView file){
|
||||
return !file.hasSuffix(".sav"_s);
|
||||
auto iter = std::remove_if(file_list.begin(), file_list.end(), [](std::string& file){
|
||||
return !Utility::String::endsWith(file, ".sav");
|
||||
});
|
||||
|
||||
auto list_view = file_list->exceptSuffix(file_list->end() - iter);
|
||||
file_list.erase(iter, file_list.end());
|
||||
|
||||
LOG_INFO("Scanning for staged M.A.S.S.es...");
|
||||
for(Containers::StringView file : list_view) {
|
||||
auto name = Mass::getNameFromFile(Utility::Path::join(_stagingAreaDirectory, file));
|
||||
for(const std::string& file : file_list) {
|
||||
std::string name = *Mass::getNameFromFile(Utility::Directory::join(_stagingAreaDirectory, file));
|
||||
|
||||
if(name) {
|
||||
LOG_INFO_FORMAT("Found staged M.A.S.S.: {}", *name);
|
||||
_stagedMasses[file] = *name;
|
||||
}
|
||||
else {
|
||||
LOG_WARNING_FORMAT("Skipped {}.", file);
|
||||
if(!name.empty()) {
|
||||
_stagedMasses[file] = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MassManager::refreshStagedMass(Containers::StringView filename) {
|
||||
LOG_INFO_FORMAT("Refreshing staged unit with filename {}.", filename);
|
||||
|
||||
bool file_exists = Utility::Path::exists(Utility::Path::join(_stagingAreaDirectory, filename));
|
||||
auto it = _stagedMasses.find(filename);
|
||||
|
||||
if(file_exists) {
|
||||
auto name = Mass::getNameFromFile(Utility::Path::join(_stagingAreaDirectory, filename));
|
||||
if(name) {
|
||||
_stagedMasses[filename] = *name;
|
||||
}
|
||||
else if(it != _stagedMasses.cend()) {
|
||||
_stagedMasses.erase(it);
|
||||
}
|
||||
}
|
||||
else if(it != _stagedMasses.cend()) {
|
||||
_stagedMasses.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
auto MassManager::deleteStagedMass(Containers::StringView filename) -> bool {
|
||||
auto MassManager::deleteStagedMass(const std::string& filename) -> bool {
|
||||
if(_stagedMasses.find(filename) == _stagedMasses.cend()) {
|
||||
_lastError = "The file "_s + filename + " couldn't be found in the list of staged M.A.S.S.es."_s;
|
||||
LOG_ERROR(_lastError);
|
||||
_lastError = "The file " + filename + " couldn't be found in the list of staged M.A.S.S.es.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!Utility::Path::remove(Utility::Path::join(_stagingAreaDirectory, filename))) {
|
||||
_lastError = filename + " couldn't be deleted: " + std::strerror(errno);
|
||||
LOG_ERROR(_lastError);
|
||||
if(!Utility::Directory::rm(Utility::Directory::join(_stagingAreaDirectory, filename))) {
|
||||
_lastError = Utility::formatString("{} couldn't be deleted: {}", filename, std::strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,10 +17,9 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <Corrade/Containers/StaticArray.h>
|
||||
#include <Corrade/Containers/String.h>
|
||||
#include <Corrade/Containers/StringView.h>
|
||||
#include <Corrade/Containers/GrowableArray.h>
|
||||
|
||||
#include "../Mass/Mass.h"
|
||||
|
||||
|
@ -28,35 +27,34 @@ using namespace Corrade;
|
|||
|
||||
class MassManager {
|
||||
public:
|
||||
MassManager(Containers::StringView save_path, Containers::StringView account, bool demo, Containers::StringView staging_dir);
|
||||
MassManager(const std::string& save_path, const std::string& steam_id, bool demo, const std::string& staging_dir);
|
||||
|
||||
auto lastError() -> Containers::StringView;
|
||||
auto lastError() -> std::string const&;
|
||||
|
||||
auto hangar(int hangar) -> Mass&;
|
||||
|
||||
void refreshHangar(int hangar);
|
||||
|
||||
auto importMass(Containers::StringView staged_fn, int hangar) -> bool;
|
||||
auto importMass(const std::string& staged_fn, int hangar) -> bool;
|
||||
auto exportMass(int hangar) -> bool;
|
||||
|
||||
auto moveMass(int source, int destination) -> bool;
|
||||
auto deleteMass(int hangar) -> bool;
|
||||
|
||||
auto stagedMasses() -> std::map<Containers::String, Containers::String> const&;
|
||||
auto stagedMasses() -> std::map<std::string, std::string> const&;
|
||||
void refreshStagedMasses();
|
||||
void refreshStagedMass(Containers::StringView filename);
|
||||
auto deleteStagedMass(Containers::StringView filename) -> bool;
|
||||
auto deleteStagedMass(const std::string& filename) -> bool;
|
||||
|
||||
private:
|
||||
Containers::StringView _saveDirectory;
|
||||
Containers::StringView _account;
|
||||
const std::string& _saveDirectory;
|
||||
const std::string& _steamId;
|
||||
bool _demo;
|
||||
|
||||
Containers::String _lastError;
|
||||
std::string _lastError;
|
||||
|
||||
Containers::StaticArray<32, Mass> _hangars{NoInit};
|
||||
Containers::Array<Mass> _hangars;
|
||||
|
||||
Containers::StringView _stagingAreaDirectory;
|
||||
const std::string& _stagingAreaDirectory;
|
||||
|
||||
std::map<Containers::String, Containers::String> _stagedMasses;
|
||||
std::map<std::string, std::string> _stagedMasses;
|
||||
};
|
||||
|
|
|
@ -16,11 +16,12 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
#include <Corrade/Containers/Pair.h>
|
||||
#include <Corrade/Utility/Path.h>
|
||||
#include <Corrade/Containers/Array.h>
|
||||
#include <Corrade/Containers/StaticArray.h>
|
||||
#include <Corrade/Utility/Directory.h>
|
||||
#include <Corrade/Utility/FormatStl.h>
|
||||
#include <Corrade/Utility/String.h>
|
||||
|
||||
#include "PropertyNames.h"
|
||||
#include "../Logger/Logger.h"
|
||||
#include "../UESaveFile/Types/ArrayProperty.h"
|
||||
#include "../UESaveFile/Types/ResourceItemValue.h"
|
||||
#include "../UESaveFile/Types/IntProperty.h"
|
||||
|
@ -29,36 +30,34 @@
|
|||
#include "Profile.h"
|
||||
|
||||
using namespace Corrade;
|
||||
using namespace Containers::Literals;
|
||||
|
||||
Profile::Profile(Containers::StringView path):
|
||||
Profile::Profile(const std::string& path):
|
||||
_profile(path)
|
||||
{
|
||||
LOG_INFO_FORMAT("Reading profile at {}.", path);
|
||||
_filename = Utility::Directory::filename(path);
|
||||
|
||||
if(!_profile.valid()) {
|
||||
_lastError = _profile.lastError();
|
||||
_valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_filename = Utility::Path::split(path).second();
|
||||
|
||||
if(_filename.hasPrefix("Demo"_s)) {
|
||||
if(Utility::String::beginsWith(_filename, "Demo")) {
|
||||
_type = ProfileType::Demo;
|
||||
}
|
||||
else {
|
||||
_type = ProfileType::FullGame;
|
||||
}
|
||||
|
||||
auto account_prop = _profile.at<StringProperty>(PROFILE_ACCOUNT);
|
||||
auto account_prop = _profile.at<StringProperty>("Account");
|
||||
if(!account_prop) {
|
||||
_lastError = "Couldn't find an account ID in "_s + _filename;
|
||||
_lastError = "Couldn't find an account ID in " + _filename;
|
||||
_valid = false;
|
||||
return;
|
||||
}
|
||||
_account = account_prop->value;
|
||||
|
||||
if(Utility::String::beginsWith(_account, "PMCSlot")) {
|
||||
_version = ProfileVersion::Normal;
|
||||
}
|
||||
else {
|
||||
_version = ProfileVersion::Legacy;
|
||||
}
|
||||
|
||||
refreshValues();
|
||||
}
|
||||
|
||||
|
@ -66,11 +65,11 @@ auto Profile::valid() const -> bool {
|
|||
return _valid;
|
||||
}
|
||||
|
||||
auto Profile::lastError() const -> Containers::StringView {
|
||||
auto Profile::lastError() const -> std::string const& {
|
||||
return _lastError;
|
||||
}
|
||||
|
||||
auto Profile::filename() const -> Containers::StringView {
|
||||
auto Profile::filename() const -> std::string const& {
|
||||
return _filename;
|
||||
}
|
||||
|
||||
|
@ -78,94 +77,76 @@ auto Profile::type() const -> ProfileType {
|
|||
return _type;
|
||||
}
|
||||
|
||||
auto Profile::isDemo() const -> bool {
|
||||
return _type == ProfileType::Demo;
|
||||
auto Profile::version() const -> ProfileVersion {
|
||||
return _version;
|
||||
}
|
||||
|
||||
auto Profile::account() const -> Containers::StringView {
|
||||
auto Profile::account() const -> std::string const& {
|
||||
return _account;
|
||||
}
|
||||
|
||||
void Profile::refreshValues() {
|
||||
if(!_profile.reloadData()) {
|
||||
LOG_ERROR(_profile.lastError());
|
||||
_lastError = _profile.lastError();
|
||||
_valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if(_profile.saveType() != "/Game/Core/Save/bpSaveGameProfile.bpSaveGameProfile_C"_s) {
|
||||
LOG_ERROR_FORMAT("{} is not a valid profile save.", _filename);
|
||||
_valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INFO("Getting the company name.");
|
||||
auto name_prop = _profile.at<StringProperty>(PROFILE_NAME);
|
||||
auto name_prop = _profile.at<StringProperty>("CompanyName");
|
||||
if(!name_prop) {
|
||||
_lastError = "No company name in "_s + _filename;
|
||||
LOG_ERROR(_lastError);
|
||||
_lastError = "No company name in " + _filename;
|
||||
_valid = false;
|
||||
return;
|
||||
}
|
||||
_name = name_prop->value;
|
||||
|
||||
LOG_INFO("Getting the active frame slot.");
|
||||
auto prop = _profile.at<IntProperty>(PROFILE_ACTIVE_FRAME_SLOT);
|
||||
auto prop = _profile.at<IntProperty>("ActiveFrameSlot");
|
||||
_activeFrameSlot = prop ? prop->value : 0;
|
||||
|
||||
LOG_INFO("Getting the credits.");
|
||||
prop = _profile.at<IntProperty>(PROFILE_CREDITS);
|
||||
prop = _profile.at<IntProperty>("Credit");
|
||||
_credits = prop ? prop->value : 0;
|
||||
|
||||
LOG_INFO("Getting the story progress.");
|
||||
prop = _profile.at<IntProperty>(PROFILE_STORY_PROGRESS);
|
||||
prop = _profile.at<IntProperty>("StoryProgress");
|
||||
_storyProgress = prop ? prop->value : 0;
|
||||
|
||||
LOG_INFO("Getting the last mission ID.");
|
||||
prop = _profile.at<IntProperty>(PROFILE_LAST_MISSION_ID);
|
||||
prop = _profile.at<IntProperty>("LastMissionID");
|
||||
_lastMissionId = prop ? prop->value : 0;
|
||||
|
||||
LOG_INFO("Getting the materials.");
|
||||
_verseSteel = getResource(PROFILE_MATERIAL, VerseSteel);
|
||||
_undinium = getResource(PROFILE_MATERIAL, Undinium);
|
||||
_necriumAlloy = getResource(PROFILE_MATERIAL, NecriumAlloy);
|
||||
_lunarite = getResource(PROFILE_MATERIAL, Lunarite);
|
||||
_asterite = getResource(PROFILE_MATERIAL, Asterite);
|
||||
_halliteFragma = getResource(PROFILE_MATERIAL, HalliteFragma);
|
||||
_verseSteel = getResource("ResourceMaterial", VerseSteel);
|
||||
_undinium = getResource("ResourceMaterial", Undinium);
|
||||
_necriumAlloy = getResource("ResourceMaterial", NecriumAlloy);
|
||||
_lunarite = getResource("ResourceMaterial", Lunarite);
|
||||
_asterite = getResource("ResourceMaterial", Asterite);
|
||||
|
||||
_ednil = getResource(PROFILE_MATERIAL, Ednil);
|
||||
_nuflalt = getResource(PROFILE_MATERIAL, Nuflalt);
|
||||
_aurelene = getResource(PROFILE_MATERIAL, Aurelene);
|
||||
_soldus = getResource(PROFILE_MATERIAL, Soldus);
|
||||
_synthesisedN = getResource(PROFILE_MATERIAL, SynthesisedN);
|
||||
_nanoc = getResource(PROFILE_MATERIAL, Nanoc);
|
||||
_ednil = getResource("ResourceMaterial", Ednil);
|
||||
_nuflalt = getResource("ResourceMaterial", Nuflalt);
|
||||
_aurelene = getResource("ResourceMaterial", Aurelene);
|
||||
_soldus = getResource("ResourceMaterial", Soldus);
|
||||
_synthesisedN = getResource("ResourceMaterial", SynthesisedN);
|
||||
|
||||
_alcarbonite = getResource(PROFILE_MATERIAL, Alcarbonite);
|
||||
_keriphene = getResource(PROFILE_MATERIAL, Keriphene);
|
||||
_nitinolCM = getResource(PROFILE_MATERIAL, NitinolCM);
|
||||
_quarkium = getResource(PROFILE_MATERIAL, Quarkium);
|
||||
_alterene = getResource(PROFILE_MATERIAL, Alterene);
|
||||
_cosmium = getResource(PROFILE_MATERIAL, Cosmium);
|
||||
_alcarbonite = getResource("ResourceMaterial", Alcarbonite);
|
||||
_keriphene = getResource("ResourceMaterial", Keriphene);
|
||||
_nitinolCM = getResource("ResourceMaterial", NitinolCM);
|
||||
_quarkium = getResource("ResourceMaterial", Quarkium);
|
||||
_alterene = getResource("ResourceMaterial", Alterene);
|
||||
|
||||
_mixedComposition = getResource(PROFILE_QUARK_DATA, MixedComposition);
|
||||
_voidResidue = getResource(PROFILE_QUARK_DATA, VoidResidue);
|
||||
_muscularConstruction = getResource(PROFILE_QUARK_DATA, MuscularConstruction);
|
||||
_mineralExoskeletology = getResource(PROFILE_QUARK_DATA, MineralExoskeletology);
|
||||
_carbonisedSkin = getResource(PROFILE_QUARK_DATA, CarbonisedSkin);
|
||||
_isolatedVoidParticle = getResource(PROFILE_QUARK_DATA, IsolatedVoidParticle);
|
||||
_mixedComposition = getResource("ResourceQuarkData", MixedComposition);
|
||||
_voidResidue = getResource("ResourceQuarkData", VoidResidue);
|
||||
_muscularConstruction = getResource("ResourceQuarkData", MuscularConstruction);
|
||||
_mineralExoskeletology = getResource("ResourceQuarkData", MineralExoskeletology);
|
||||
_carbonisedSkin = getResource("ResourceQuarkData", CarbonisedSkin);
|
||||
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
auto Profile::companyName() const -> Containers::StringView {
|
||||
auto Profile::companyName() const -> std::string const& {
|
||||
return _name;
|
||||
}
|
||||
|
||||
auto Profile::renameCompany(Containers::StringView new_name) -> bool {
|
||||
auto name_prop = _profile.at<StringProperty>(PROFILE_NAME);
|
||||
auto Profile::renameCompany(const std::string& new_name) -> bool {
|
||||
auto name_prop = _profile.at<StringProperty>("CompanyName");
|
||||
if(!name_prop) {
|
||||
_lastError = "No company name in "_s + _filename;
|
||||
LOG_ERROR(_lastError);
|
||||
_lastError = "No company name in " + _filename;
|
||||
_valid = false;
|
||||
return false;
|
||||
}
|
||||
|
@ -189,12 +170,11 @@ auto Profile::credits() const -> Int {
|
|||
}
|
||||
|
||||
auto Profile::setCredits(Int amount) -> bool {
|
||||
auto credits_prop = _profile.at<IntProperty>(PROFILE_CREDITS);
|
||||
auto credits_prop = _profile.at<IntProperty>("Credit");
|
||||
|
||||
if(!credits_prop) {
|
||||
credits_prop = new IntProperty;
|
||||
credits_prop->name.emplace("Credit"_s);
|
||||
credits_prop->valueLength = sizeof(Int);
|
||||
credits_prop->name.emplace("Credit");
|
||||
_profile.appendProperty(IntProperty::ptr{credits_prop});
|
||||
}
|
||||
|
||||
|
@ -213,12 +193,11 @@ auto Profile::storyProgress() const -> Int {
|
|||
}
|
||||
|
||||
auto Profile::setStoryProgress(Int progress) -> bool {
|
||||
auto story_progress_prop = _profile.at<IntProperty>("StoryProgress"_s);
|
||||
auto story_progress_prop = _profile.at<IntProperty>("StoryProgress");
|
||||
|
||||
if(!story_progress_prop) {
|
||||
story_progress_prop = new IntProperty;
|
||||
story_progress_prop->name.emplace("StoryProgress"_s);
|
||||
story_progress_prop->valueLength = sizeof(Int);
|
||||
story_progress_prop->name.emplace("StoryProgress");
|
||||
_profile.appendProperty(IntProperty::ptr{story_progress_prop});
|
||||
}
|
||||
|
||||
|
@ -241,7 +220,7 @@ auto Profile::verseSteel() const -> Int {
|
|||
}
|
||||
|
||||
auto Profile::setVerseSteel(Int amount) -> bool {
|
||||
return setResource(PROFILE_MATERIAL, VerseSteel, amount);
|
||||
return setResource("ResourceMaterial", VerseSteel, amount);
|
||||
}
|
||||
|
||||
auto Profile::undinium() const -> Int {
|
||||
|
@ -249,7 +228,7 @@ auto Profile::undinium() const -> Int {
|
|||
}
|
||||
|
||||
auto Profile::setUndinium(Int amount) -> bool {
|
||||
return setResource(PROFILE_MATERIAL, Undinium, amount);
|
||||
return setResource("ResourceMaterial", Undinium, amount);
|
||||
}
|
||||
|
||||
auto Profile::necriumAlloy() const -> Int {
|
||||
|
@ -257,7 +236,7 @@ auto Profile::necriumAlloy() const -> Int {
|
|||
}
|
||||
|
||||
auto Profile::setNecriumAlloy(Int amount) -> bool {
|
||||
return setResource(PROFILE_MATERIAL, NecriumAlloy, amount);
|
||||
return setResource("ResourceMaterial", NecriumAlloy, amount);
|
||||
}
|
||||
|
||||
auto Profile::lunarite() const -> Int {
|
||||
|
@ -265,7 +244,7 @@ auto Profile::lunarite() const -> Int {
|
|||
}
|
||||
|
||||
auto Profile::setLunarite(Int amount) -> bool {
|
||||
return setResource(PROFILE_MATERIAL, Lunarite, amount);
|
||||
return setResource("ResourceMaterial", Lunarite, amount);
|
||||
}
|
||||
|
||||
auto Profile::asterite() const -> Int {
|
||||
|
@ -273,17 +252,7 @@ auto Profile::asterite() const -> Int {
|
|||
}
|
||||
|
||||
auto Profile::setAsterite(Int amount) -> bool {
|
||||
return setResource(PROFILE_MATERIAL, Asterite, amount);
|
||||
}
|
||||
|
||||
Int
|
||||
Profile::halliteFragma() const {
|
||||
return _halliteFragma;
|
||||
}
|
||||
|
||||
bool
|
||||
Profile::setHalliteFragma(Int amount) {
|
||||
return setResource(PROFILE_MATERIAL, HalliteFragma, amount);
|
||||
return setResource("ResourceMaterial", Asterite, amount);
|
||||
}
|
||||
|
||||
auto Profile::ednil() const -> Int {
|
||||
|
@ -291,7 +260,7 @@ auto Profile::ednil() const -> Int {
|
|||
}
|
||||
|
||||
auto Profile::setEdnil(Int amount) -> bool {
|
||||
return setResource(PROFILE_MATERIAL, Ednil, amount);
|
||||
return setResource("ResourceMaterial", Ednil, amount);
|
||||
}
|
||||
|
||||
auto Profile::nuflalt() const -> Int {
|
||||
|
@ -299,7 +268,7 @@ auto Profile::nuflalt() const -> Int {
|
|||
}
|
||||
|
||||
auto Profile::setNuflalt(Int amount) -> bool {
|
||||
return setResource(PROFILE_MATERIAL, Nuflalt, amount);
|
||||
return setResource("ResourceMaterial", Nuflalt, amount);
|
||||
}
|
||||
|
||||
auto Profile::aurelene() const -> Int {
|
||||
|
@ -307,7 +276,7 @@ auto Profile::aurelene() const -> Int {
|
|||
}
|
||||
|
||||
auto Profile::setAurelene(Int amount) -> bool {
|
||||
return setResource(PROFILE_MATERIAL, Aurelene, amount);
|
||||
return setResource("ResourceMaterial", Aurelene, amount);
|
||||
}
|
||||
|
||||
auto Profile::soldus() const -> Int {
|
||||
|
@ -315,7 +284,7 @@ auto Profile::soldus() const -> Int {
|
|||
}
|
||||
|
||||
auto Profile::setSoldus(Int amount) -> bool {
|
||||
return setResource(PROFILE_MATERIAL, Soldus, amount);
|
||||
return setResource("ResourceMaterial", Soldus, amount);
|
||||
}
|
||||
|
||||
auto Profile::synthesisedN() const -> Int {
|
||||
|
@ -323,17 +292,7 @@ auto Profile::synthesisedN() const -> Int {
|
|||
}
|
||||
|
||||
auto Profile::setSynthesisedN(Int amount) -> bool {
|
||||
return setResource(PROFILE_MATERIAL, SynthesisedN, amount);
|
||||
}
|
||||
|
||||
Int
|
||||
Profile::nanoc() const {
|
||||
return _nanoc;
|
||||
}
|
||||
|
||||
bool
|
||||
Profile::setNanoc(Int amount) {
|
||||
return setResource(PROFILE_MATERIAL, Nanoc, amount);
|
||||
return setResource("ResourceMaterial", SynthesisedN, amount);
|
||||
}
|
||||
|
||||
auto Profile::alcarbonite() const -> Int {
|
||||
|
@ -341,7 +300,7 @@ auto Profile::alcarbonite() const -> Int {
|
|||
}
|
||||
|
||||
auto Profile::setAlcarbonite(Int amount) -> bool {
|
||||
return setResource(PROFILE_MATERIAL, Alcarbonite, amount);
|
||||
return setResource("ResourceMaterial", Alcarbonite, amount);
|
||||
}
|
||||
|
||||
auto Profile::keriphene() const -> Int {
|
||||
|
@ -349,7 +308,7 @@ auto Profile::keriphene() const -> Int {
|
|||
}
|
||||
|
||||
auto Profile::setKeriphene(Int amount) -> bool {
|
||||
return setResource(PROFILE_MATERIAL, Keriphene, amount);
|
||||
return setResource("ResourceMaterial", Keriphene, amount);
|
||||
}
|
||||
|
||||
auto Profile::nitinolCM() const -> Int {
|
||||
|
@ -357,7 +316,7 @@ auto Profile::nitinolCM() const -> Int {
|
|||
}
|
||||
|
||||
auto Profile::setNitinolCM(Int amount) -> bool {
|
||||
return setResource(PROFILE_MATERIAL, NitinolCM, amount);
|
||||
return setResource("ResourceMaterial", NitinolCM, amount);
|
||||
}
|
||||
|
||||
auto Profile::quarkium() const -> Int {
|
||||
|
@ -365,7 +324,7 @@ auto Profile::quarkium() const -> Int {
|
|||
}
|
||||
|
||||
auto Profile::setQuarkium(Int amount) -> bool {
|
||||
return setResource(PROFILE_MATERIAL, Quarkium, amount);
|
||||
return setResource("ResourceMaterial", Quarkium, amount);
|
||||
}
|
||||
|
||||
auto Profile::alterene() const -> Int {
|
||||
|
@ -373,17 +332,7 @@ auto Profile::alterene() const -> Int {
|
|||
}
|
||||
|
||||
auto Profile::setAlterene(Int amount) -> bool {
|
||||
return setResource(PROFILE_MATERIAL, Alterene, amount);
|
||||
}
|
||||
|
||||
Int
|
||||
Profile::cosmium() const {
|
||||
return _cosmium;
|
||||
}
|
||||
|
||||
bool
|
||||
Profile::setCosmium(Int amount) {
|
||||
return setResource(PROFILE_MATERIAL, Cosmium, amount);
|
||||
return setResource("ResourceMaterial", Alterene, amount);
|
||||
}
|
||||
|
||||
auto Profile::mixedComposition() const -> Int {
|
||||
|
@ -391,7 +340,7 @@ auto Profile::mixedComposition() const -> Int {
|
|||
}
|
||||
|
||||
auto Profile::setMixedComposition(Int amount) -> bool {
|
||||
return setResource(PROFILE_QUARK_DATA, MixedComposition, amount);
|
||||
return setResource("ResourceQuarkData", MixedComposition, amount);
|
||||
}
|
||||
|
||||
auto Profile::voidResidue() const -> Int {
|
||||
|
@ -399,7 +348,7 @@ auto Profile::voidResidue() const -> Int {
|
|||
}
|
||||
|
||||
auto Profile::setVoidResidue(Int amount) -> bool {
|
||||
return setResource(PROFILE_QUARK_DATA, VoidResidue, amount);
|
||||
return setResource("ResourceQuarkData", VoidResidue, amount);
|
||||
}
|
||||
|
||||
auto Profile::muscularConstruction() const -> Int {
|
||||
|
@ -407,7 +356,7 @@ auto Profile::muscularConstruction() const -> Int {
|
|||
}
|
||||
|
||||
auto Profile::setMuscularConstruction(Int amount) -> bool {
|
||||
return setResource(PROFILE_QUARK_DATA, MuscularConstruction, amount);
|
||||
return setResource("ResourceQuarkData", MuscularConstruction, amount);
|
||||
}
|
||||
|
||||
auto Profile::mineralExoskeletology() const -> Int {
|
||||
|
@ -415,7 +364,7 @@ auto Profile::mineralExoskeletology() const -> Int {
|
|||
}
|
||||
|
||||
auto Profile::setMineralExoskeletology(Int amount) -> bool {
|
||||
return setResource(PROFILE_QUARK_DATA, MineralExoskeletology, amount);
|
||||
return setResource("ResourceQuarkData", MineralExoskeletology, amount);
|
||||
}
|
||||
|
||||
auto Profile::carbonisedSkin() const -> Int {
|
||||
|
@ -423,20 +372,10 @@ auto Profile::carbonisedSkin() const -> Int {
|
|||
}
|
||||
|
||||
auto Profile::setCarbonisedSkin(Int amount) -> bool {
|
||||
return setResource(PROFILE_QUARK_DATA, CarbonisedSkin, amount);
|
||||
return setResource("ResourceQuarkData", CarbonisedSkin, amount);
|
||||
}
|
||||
|
||||
Int
|
||||
Profile::isolatedVoidParticle() const {
|
||||
return _isolatedVoidParticle;
|
||||
}
|
||||
|
||||
bool
|
||||
Profile::setIsolatedVoidParticle(Int amount) {
|
||||
return setResource(PROFILE_QUARK_DATA, IsolatedVoidParticle, amount);
|
||||
}
|
||||
|
||||
auto Profile::getResource(Containers::StringView container, MaterialID id) -> Int {
|
||||
auto Profile::getResource(const char* container, MaterialID id) -> Int {
|
||||
auto mats_prop = _profile.at<ArrayProperty>(container);
|
||||
|
||||
if(!mats_prop) {
|
||||
|
@ -452,14 +391,13 @@ auto Profile::getResource(Containers::StringView container, MaterialID id) -> In
|
|||
return it != mats_prop->items.end() ? static_cast<ResourceItemValue*>(it->get())->quantity : 0;
|
||||
}
|
||||
|
||||
auto Profile::setResource(Containers::StringView container, MaterialID id, Int amount) -> bool {
|
||||
auto Profile::setResource(const char* container, MaterialID id, Int amount) -> bool {
|
||||
auto mats_prop = _profile.at<ArrayProperty>(container);
|
||||
|
||||
if(!mats_prop) {
|
||||
mats_prop = new ArrayProperty;
|
||||
mats_prop->name.emplace(container);
|
||||
mats_prop->itemType = "StructProperty";
|
||||
_profile.appendProperty(ArrayProperty::ptr{mats_prop});
|
||||
_lastError = "Couldn't find " + std::string{container} + " in " + _filename;
|
||||
_valid = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto predicate = [&id](UnrealPropertyBase::ptr& prop){
|
||||
|
@ -472,9 +410,6 @@ auto Profile::setResource(Containers::StringView container, MaterialID id, Int a
|
|||
ResourceItemValue* res_prop;
|
||||
if(it == mats_prop->items.end()) {
|
||||
res_prop = new ResourceItemValue;
|
||||
if(mats_prop->items.isEmpty()) {
|
||||
res_prop->name.emplace(container);
|
||||
}
|
||||
res_prop->id = id;
|
||||
ResourceItemValue::ptr prop{res_prop};
|
||||
arrayAppend(mats_prop->items, std::move(prop));
|
||||
|
|
|
@ -16,8 +16,7 @@
|
|||
// 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/String.h>
|
||||
#include <Corrade/Containers/StringView.h>
|
||||
#include <string>
|
||||
|
||||
#include <Magnum/Magnum.h>
|
||||
|
||||
|
@ -25,7 +24,6 @@
|
|||
|
||||
#include "ResourceIDs.h"
|
||||
|
||||
using namespace Corrade;
|
||||
using namespace Magnum;
|
||||
|
||||
enum class ProfileType : UnsignedByte {
|
||||
|
@ -33,25 +31,31 @@ enum class ProfileType : UnsignedByte {
|
|||
FullGame
|
||||
};
|
||||
|
||||
enum class ProfileVersion : UnsignedByte {
|
||||
Legacy, // pre-0.8
|
||||
Normal // 0.8 and later
|
||||
};
|
||||
|
||||
class Profile {
|
||||
public:
|
||||
explicit Profile(Containers::StringView path);
|
||||
explicit Profile(const std::string& path);
|
||||
|
||||
auto valid() const -> bool;
|
||||
|
||||
auto lastError() const -> Containers::StringView;
|
||||
auto lastError() const -> std::string const&;
|
||||
|
||||
auto filename() const -> Containers::StringView;
|
||||
auto filename() const -> std::string const&;
|
||||
|
||||
auto type() const -> ProfileType;
|
||||
auto isDemo() const -> bool;
|
||||
|
||||
auto account() const -> Containers::StringView;
|
||||
auto version() const -> ProfileVersion;
|
||||
|
||||
auto account() const -> std::string const&;
|
||||
|
||||
void refreshValues();
|
||||
|
||||
auto companyName() const -> Containers::StringView;
|
||||
auto renameCompany(Containers::StringView new_name) -> bool;
|
||||
auto companyName() const -> std::string const&;
|
||||
auto renameCompany(const std::string& new_name) -> bool;
|
||||
|
||||
auto activeFrameSlot() const -> Int;
|
||||
|
||||
|
@ -78,9 +82,6 @@ class Profile {
|
|||
auto asterite() const -> Int;
|
||||
auto setAsterite(Int amount) -> bool;
|
||||
|
||||
Int halliteFragma() const;
|
||||
bool setHalliteFragma(Int amount);
|
||||
|
||||
auto ednil() const -> Int;
|
||||
auto setEdnil(Int amount) -> bool;
|
||||
|
||||
|
@ -96,9 +97,6 @@ class Profile {
|
|||
auto synthesisedN() const -> Int;
|
||||
auto setSynthesisedN(Int amount) -> bool;
|
||||
|
||||
Int nanoc() const;
|
||||
bool setNanoc(Int amount);
|
||||
|
||||
auto alcarbonite() const -> Int;
|
||||
auto setAlcarbonite(Int amount) -> bool;
|
||||
|
||||
|
@ -114,9 +112,6 @@ class Profile {
|
|||
auto alterene() const -> Int;
|
||||
auto setAlterene(Int amount) -> bool;
|
||||
|
||||
Int cosmium() const;
|
||||
bool setCosmium(Int amount);
|
||||
|
||||
auto mixedComposition() const -> Int;
|
||||
auto setMixedComposition(Int amount) -> bool;
|
||||
|
||||
|
@ -132,55 +127,49 @@ class Profile {
|
|||
auto carbonisedSkin() const -> Int;
|
||||
auto setCarbonisedSkin(Int amount) -> bool;
|
||||
|
||||
Int isolatedVoidParticle() const;
|
||||
bool setIsolatedVoidParticle(Int amount);
|
||||
|
||||
private:
|
||||
auto getResource(Containers::StringView container, MaterialID id) -> Int;
|
||||
auto setResource(Containers::StringView container, MaterialID id, Int amount) -> bool;
|
||||
auto getResource(const char* container, MaterialID id) -> Int;
|
||||
auto setResource(const char* container, MaterialID id, Int amount) -> bool;
|
||||
|
||||
Containers::String _filename;
|
||||
std::string _filename;
|
||||
|
||||
ProfileType _type;
|
||||
ProfileVersion _version;
|
||||
|
||||
UESaveFile _profile;
|
||||
|
||||
Containers::String _name;
|
||||
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 _halliteFragma = 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 _nanoc = 0;
|
||||
|
||||
Int _alcarbonite = 0;
|
||||
Int _keriphene = 0;
|
||||
Int _nitinolCM = 0;
|
||||
Int _quarkium = 0;
|
||||
Int _alterene = 0;
|
||||
Int _cosmium = 0;
|
||||
|
||||
Int _mixedComposition = 0;
|
||||
Int _voidResidue = 0;
|
||||
Int _muscularConstruction = 0;
|
||||
Int _mineralExoskeletology = 0;
|
||||
Int _carbonisedSkin = 0;
|
||||
Int _isolatedVoidParticle = 0;
|
||||
|
||||
Containers::String _account;
|
||||
std::string _account;
|
||||
|
||||
bool _valid = false;
|
||||
Containers::String _lastError;
|
||||
bool _valid = false;
|
||||
std::string _lastError;
|
||||
};
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#define PROFILE_NAME "CompanyName"
|
||||
#define PROFILE_ACTIVE_FRAME_SLOT "ActiveFrameSlot"
|
||||
#define PROFILE_CREDITS "Credit"
|
||||
#define PROFILE_STORY_PROGRESS "StoryProgress"
|
||||
#define PROFILE_LAST_MISSION_ID "LastMissionID"
|
||||
#define PROFILE_MATERIAL "ResourceMaterial"
|
||||
#define PROFILE_QUARK_DATA "ResourceQuarkData"
|
||||
#define PROFILE_ACCOUNT "Account"
|
|
@ -21,31 +21,27 @@
|
|||
using namespace Magnum;
|
||||
|
||||
enum MaterialID : Int {
|
||||
VerseSteel = 0xC3500,
|
||||
Undinium = 0xC3501,
|
||||
NecriumAlloy = 0xC3502,
|
||||
Lunarite = 0xC3503,
|
||||
Asterite = 0xC3504,
|
||||
HalliteFragma = 0xC3505,
|
||||
VerseSteel = 0xC3500,
|
||||
Undinium = 0xC3501,
|
||||
NecriumAlloy = 0xC3502,
|
||||
Lunarite = 0xC3503,
|
||||
Asterite = 0xC3504,
|
||||
|
||||
Ednil = 0xC350A,
|
||||
Nuflalt = 0xC350B,
|
||||
Aurelene = 0xC350C,
|
||||
Soldus = 0xC350D,
|
||||
SynthesisedN = 0xC350E,
|
||||
Nanoc = 0xC350F,
|
||||
|
||||
Alcarbonite = 0xC3514,
|
||||
Keriphene = 0xC3515,
|
||||
NitinolCM = 0xC3516,
|
||||
Quarkium = 0xC3517,
|
||||
Alterene = 0xC3518,
|
||||
Cosmium = 0xC3519,
|
||||
|
||||
MixedComposition = 0xDBBA0,
|
||||
VoidResidue = 0xDBBA1,
|
||||
MuscularConstruction = 0xDBBA2,
|
||||
MineralExoskeletology = 0xDBBA3,
|
||||
CarbonisedSkin = 0xDBBA4,
|
||||
IsolatedVoidParticle = 0xDBBA5,
|
||||
CarbonisedSkin = 0xDBBA4
|
||||
};
|
||||
|
|
|
@ -18,22 +18,20 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
#include <regex>
|
||||
|
||||
#include <Corrade/Containers/ScopeGuard.h>
|
||||
#include <Corrade/Containers/StaticArray.h>
|
||||
#include <Corrade/Utility/Format.h>
|
||||
#include <Corrade/Utility/Path.h>
|
||||
#include <Corrade/Utility/Directory.h>
|
||||
#include <Corrade/Utility/FormatStl.h>
|
||||
#include <Corrade/Utility/String.h>
|
||||
|
||||
#include <zip.h>
|
||||
|
||||
#include "../Logger/Logger.h"
|
||||
|
||||
#include "ProfileManager.h"
|
||||
|
||||
using namespace Containers::Literals;
|
||||
|
||||
ProfileManager::ProfileManager(Containers::StringView save_dir, Containers::StringView backup_dir):
|
||||
ProfileManager::ProfileManager(const std::string& save_dir, const std::string& backup_dir):
|
||||
_saveDirectory{save_dir},
|
||||
_backupsDirectory{backup_dir}
|
||||
{
|
||||
|
@ -44,7 +42,7 @@ auto ProfileManager::ready() const -> bool {
|
|||
return _ready;
|
||||
}
|
||||
|
||||
auto ProfileManager::lastError() -> Containers::StringView {
|
||||
auto ProfileManager::lastError() -> std::string const& {
|
||||
return _lastError;
|
||||
}
|
||||
|
||||
|
@ -53,40 +51,32 @@ auto ProfileManager::profiles() -> Containers::ArrayView<Profile> {
|
|||
}
|
||||
|
||||
auto ProfileManager::refreshProfiles() -> bool {
|
||||
LOG_INFO("Refreshing profiles.");
|
||||
|
||||
_profiles = Containers::Array<Profile>{};
|
||||
|
||||
using Utility::Path::ListFlag;
|
||||
auto files = Utility::Path::list(_saveDirectory,
|
||||
ListFlag::SkipSpecial|ListFlag::SkipDirectories|ListFlag::SkipDotAndDotDot);
|
||||
using Utility::Directory::Flag;
|
||||
std::vector<std::string> files = Utility::Directory::list(_saveDirectory, Flag::SkipSpecial|Flag::SkipDirectories|Flag::SkipDotAndDotDot);
|
||||
|
||||
if(!files) {
|
||||
_lastError = _saveDirectory + " can't be opened.";
|
||||
LOG_ERROR(_lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto predicate = [](Containers::StringView file)->bool{
|
||||
return !((file.hasPrefix("DemoProfile") || file.hasPrefix("Profile")) && file.hasSuffix(".sav"));
|
||||
auto predicate = [](const std::string& file)->bool{
|
||||
std::regex regex("(Demo)?Profile[0-9]{17}\\.sav", std::regex::nosubs);
|
||||
std::cmatch m;
|
||||
return !std::regex_match(file.c_str(), m, regex);
|
||||
};
|
||||
|
||||
auto files_view = files->exceptSuffix(files->end() - std::remove_if(files->begin(), files->end(), predicate));
|
||||
files.erase(std::remove_if(files.begin(), files.end(), predicate), files.end());
|
||||
|
||||
for(const auto& file : files_view) {
|
||||
Profile profile{Utility::Path::join(_saveDirectory, file)};
|
||||
for(const std::string& file : files) {
|
||||
Profile profile{Utility::Directory::join(_saveDirectory, file)};
|
||||
|
||||
if(!profile.valid()) {
|
||||
LOG_WARNING_FORMAT("Profile {} is invalid: {}", file, profile.lastError());
|
||||
Utility::Warning{} << "Profile" << file.c_str() << "is invalid:" << profile.lastError().c_str();
|
||||
continue;
|
||||
}
|
||||
|
||||
arrayAppend(_profiles, std::move(profile));
|
||||
}
|
||||
|
||||
if(_profiles.isEmpty()) {
|
||||
_lastError = "No valid profiles were found."_s;
|
||||
LOG_ERROR(_lastError);
|
||||
if(_profiles.empty()) {
|
||||
_lastError = "No valid profiles were found.";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -98,26 +88,25 @@ auto ProfileManager::getProfile(std::size_t index) -> Profile* {
|
|||
}
|
||||
|
||||
auto ProfileManager::deleteProfile(std::size_t index, bool delete_builds) -> bool {
|
||||
if(!Utility::Path::remove(Utility::Path::join(_saveDirectory, _profiles[index].filename()))) {
|
||||
_lastError = Utility::format("Couldn't delete {} (filename: {}).",
|
||||
_profiles[index].companyName(),
|
||||
_profiles[index].filename());
|
||||
LOG_ERROR(_lastError);
|
||||
if(!Utility::Directory::rm(Utility::Directory::join(_saveDirectory, _profiles[index].filename()))) {
|
||||
_lastError = Utility::formatString("Couldn't delete {} (filename: {}).",
|
||||
_profiles[index].companyName(),
|
||||
_profiles[index].filename());
|
||||
refreshProfiles();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(delete_builds) {
|
||||
for(UnsignedByte i = 0; i < 32; ++i) {
|
||||
auto filename = Utility::format("{}Unit{:.2d}{}.sav",
|
||||
_profiles[index].type() == ProfileType::Demo ? "Demo": "",
|
||||
i, _profiles[index].account());
|
||||
Utility::Path::remove(Utility::Path::join(_saveDirectory, filename));
|
||||
std::string filename = Utility::formatString("{}Unit{:.2d}{}.sav",
|
||||
_profiles[index].type() == ProfileType::Demo ? "Demo": "",
|
||||
i, _profiles[index].account());
|
||||
Utility::Directory::rm(Utility::Directory::join(_saveDirectory, filename));
|
||||
}
|
||||
}
|
||||
|
||||
auto file = _profiles[index].filename();
|
||||
auto it = std::remove_if(_profiles.begin(), _profiles.end(), [&file](Profile& profile){ return profile.filename() == file; });
|
||||
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);
|
||||
|
@ -129,62 +118,59 @@ auto ProfileManager::deleteProfile(std::size_t index, bool delete_builds) -> boo
|
|||
auto ProfileManager::backupProfile(std::size_t index, bool backup_builds) -> bool {
|
||||
std::time_t timestamp = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
||||
std::tm* time = std::localtime(×tamp);
|
||||
auto& profile = _profiles[index];
|
||||
|
||||
auto filename = Utility::format("{}_{}{:.2d}{:.2d}_{:.2d}{:.2d}{:.2d}.backup.mbst",
|
||||
Utility::String::replaceAll(profile.companyName().data(), " ", "_").c_str(),
|
||||
time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
|
||||
time->tm_hour, time->tm_min, time->tm_sec);
|
||||
std::string filename = Utility::formatString("{}_{}{:.2d}{:.2d}_{:.2d}{:.2d}{:.2d}.mbprofbackup",
|
||||
Utility::String::replaceAll(_profiles[index].companyName(), " ", "_"),
|
||||
time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
|
||||
time->tm_hour, time->tm_min, time->tm_sec);
|
||||
|
||||
int error_code = 0;
|
||||
zip_error_t error;
|
||||
zip_t* zip = zip_open(Utility::Path::join(_backupsDirectory, filename).data(), ZIP_CREATE|ZIP_TRUNCATE, &error_code);
|
||||
zip_t* zip = zip_open(Utility::Directory::join(_backupsDirectory, filename).c_str(), ZIP_CREATE|ZIP_TRUNCATE, &error_code);
|
||||
if(zip == nullptr) {
|
||||
zip_error_init_with_code(&error, error_code);
|
||||
_lastError = zip_error_strerror(&error);
|
||||
LOG_ERROR(_lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
zip_source_t* profile_source = zip_source_file(zip, Utility::Path::toNativeSeparators(Utility::Path::join(_saveDirectory, profile.filename())).data(), 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) {
|
||||
_lastError = zip_strerror(zip);
|
||||
LOG_ERROR(_lastError);
|
||||
zip_source_free(profile_source);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(zip_file_add(zip, profile.filename().data(), 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);
|
||||
LOG_ERROR(_lastError);
|
||||
zip_source_free(profile_source);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto comment = Utility::format("{}|{}|{}-{:.2d}-{:.2d}-{:.2d}-{:.2d}-{:.2d}",
|
||||
profile.companyName(),
|
||||
profile.isDemo() ? "demo"_s : "full"_s,
|
||||
time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
|
||||
time->tm_hour, time->tm_min, time->tm_sec);
|
||||
zip_set_archive_comment(zip, comment.data(), comment.size());
|
||||
std::string comment = Utility::String::join({_profiles[index].companyName(),
|
||||
_profiles[index].type() == ProfileType::Demo ? "demo" : "full",
|
||||
Utility::formatString("{}-{:.2d}-{:.2d}-{:.2d}-{:.2d}-{:.2d}",
|
||||
time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
|
||||
time->tm_hour, time->tm_min, time->tm_sec)
|
||||
}, '|');
|
||||
zip_set_archive_comment(zip, comment.c_str(), comment.length());
|
||||
|
||||
if(backup_builds) {
|
||||
for(UnsignedByte i = 0; i < 32; ++i) {
|
||||
auto build_filename = Utility::format("{}Unit{:.2d}{}.sav",
|
||||
profile.isDemo() ? "Demo"_s : ""_s, i,
|
||||
profile.account());
|
||||
std::string build_filename = Utility::formatString("{}Unit{:.2d}{}.sav",
|
||||
_profiles[index].type() == ProfileType::Demo ? "Demo": "",
|
||||
i, _profiles[index].account());
|
||||
|
||||
if(!Utility::Path::exists(Utility::Path::join(_saveDirectory, build_filename))) {
|
||||
if(!Utility::Directory::exists(Utility::Directory::join(_saveDirectory, build_filename))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
zip_source_t* build_source = zip_source_file(zip, Utility::Path::toNativeSeparators(Utility::Path::join(_saveDirectory, build_filename)).data(), 0, 0);
|
||||
zip_source_t* build_source = zip_source_file(zip, Utility::Directory::toNativeSeparators(Utility::Directory::join(_saveDirectory, build_filename)).c_str(), 0, 0);
|
||||
if(build_source == nullptr) {
|
||||
zip_source_free(build_source);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(zip_file_add(zip, build_filename.data(), build_source, ZIP_FL_ENC_UTF_8) == -1) {
|
||||
if(zip_file_add(zip, build_filename.c_str(), build_source, ZIP_FL_ENC_UTF_8) == -1) {
|
||||
zip_source_free(build_source);
|
||||
continue;
|
||||
}
|
||||
|
@ -193,7 +179,6 @@ auto ProfileManager::backupProfile(std::size_t index, bool backup_builds) -> boo
|
|||
|
||||
if(zip_close(zip) == -1) {
|
||||
_lastError = zip_strerror(zip);
|
||||
LOG_ERROR(_lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -209,76 +194,69 @@ auto ProfileManager::backups() -> Containers::ArrayView<Backup> {
|
|||
void ProfileManager::refreshBackups() {
|
||||
_backups = Containers::Array<Backup>{};
|
||||
|
||||
using Utility::Path::ListFlag;
|
||||
auto files = Utility::Path::list(_backupsDirectory,
|
||||
ListFlag::SkipSpecial|ListFlag::SkipDirectories|ListFlag::SkipDotAndDotDot);
|
||||
using Utility::Directory::Flag;
|
||||
std::vector<std::string> files = Utility::Directory::list(_backupsDirectory, Flag::SkipSpecial|Flag::SkipDirectories|Flag::SkipDotAndDotDot);
|
||||
|
||||
if(!files) {
|
||||
_lastError = _backupsDirectory + " can't be opened.";
|
||||
LOG_ERROR(_lastError);
|
||||
return;
|
||||
}
|
||||
|
||||
auto predicate = [](Containers::StringView file)->bool{
|
||||
return !(file.hasSuffix(".mbprofbackup"_s) || file.hasSuffix(".backup.mbst"));
|
||||
auto predicate = [](const std::string& file)->bool{
|
||||
return !Utility::String::endsWith(file, ".mbprofbackup");
|
||||
};
|
||||
|
||||
auto files_view = files->exceptSuffix(files->end() - std::remove_if(files->begin(), files->end(), predicate));
|
||||
files.erase(std::remove_if(files.begin(), files.end(), predicate), files.end());
|
||||
|
||||
int error_code = 0;
|
||||
zip_t* zip = nullptr;
|
||||
for(Containers::StringView file : files_view) {
|
||||
for(const std::string& file : files) {
|
||||
Backup backup;
|
||||
backup.filename = file;
|
||||
|
||||
zip = zip_open(Utility::Path::join(_backupsDirectory, file).data(), ZIP_RDONLY, &error_code);
|
||||
zip = zip_open(Utility::Directory::join(_backupsDirectory, file).c_str(), ZIP_RDONLY, &error_code);
|
||||
if(zip == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Containers::ScopeGuard guard{zip, zip_close};
|
||||
|
||||
Long num_entries = zip_get_num_entries(zip, ZIP_FL_UNCHANGED);
|
||||
|
||||
if(num_entries == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int comment_length;
|
||||
Containers::StringView comment = zip_get_archive_comment(zip, &comment_length, ZIP_FL_UNCHANGED);
|
||||
const char* comment = zip_get_archive_comment(zip, &comment_length, ZIP_FL_UNCHANGED);
|
||||
if(comment == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto info = comment.split('|');
|
||||
auto info = Utility::String::split(comment, '|');
|
||||
|
||||
if(info.size() != 3) {
|
||||
continue;
|
||||
}
|
||||
|
||||
backup.company = info[0];
|
||||
backup.company = info.at(0);
|
||||
|
||||
if(info[1].hasPrefix("full")) {
|
||||
if(info.at(1) == "full") {
|
||||
backup.type = ProfileType::FullGame;
|
||||
}
|
||||
else if(info[1].hasPrefix("demo")) {
|
||||
else if(info.at(1) == "demo") {
|
||||
backup.type = ProfileType::Demo;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto ts = info[2].split('-');
|
||||
auto ts = Utility::String::split(info.at(2), '-');
|
||||
if(ts.size() != 6) {
|
||||
continue;
|
||||
}
|
||||
|
||||
backup.timestamp.year = std::strtol(ts[0].data(), nullptr, 10);
|
||||
backup.timestamp.month = std::strtol(ts[1].data(), nullptr, 10);
|
||||
backup.timestamp.day = std::strtol(ts[2].data(), nullptr, 10);
|
||||
backup.timestamp.hour = std::strtol(ts[3].data(), nullptr, 10);
|
||||
backup.timestamp.minute = std::strtol(ts[4].data(), nullptr, 10);
|
||||
backup.timestamp.second = std::strtol(ts[5].data(), nullptr, 10);
|
||||
backup.timestamp.year = std::stoi(ts.at(0));
|
||||
backup.timestamp.month = std::stoi(ts.at(1));
|
||||
backup.timestamp.day = std::stoi(ts.at(2));
|
||||
backup.timestamp.hour = std::stoi(ts.at(3));
|
||||
backup.timestamp.minute = std::stoi(ts.at(4));
|
||||
backup.timestamp.second = std::stoi(ts.at(5));
|
||||
|
||||
Long num_entries = zip_get_num_entries(zip, ZIP_FL_UNCHANGED);
|
||||
|
||||
if(num_entries == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
arrayReserve(backup.includedFiles, num_entries);
|
||||
|
||||
|
@ -291,13 +269,12 @@ void ProfileManager::refreshBackups() {
|
|||
}
|
||||
|
||||
auto ProfileManager::deleteBackup(std::size_t index) -> bool {
|
||||
if(!Utility::Path::remove(Utility::Path::join(_backupsDirectory, _backups[index].filename))) {
|
||||
if(!Utility::Directory::rm(Utility::Directory::join(_backupsDirectory, _backups[index].filename))) {
|
||||
_lastError = "Couldn't delete " + _backups[index].filename;
|
||||
LOG_ERROR(_lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto file = _backups[index].filename;
|
||||
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()) {
|
||||
|
@ -310,36 +287,33 @@ auto ProfileManager::deleteBackup(std::size_t index) -> bool {
|
|||
auto ProfileManager::restoreBackup(std::size_t index) -> bool {
|
||||
const Backup& backup = _backups[index];
|
||||
|
||||
auto error_format = "Extraction of file {} failed: {}"_s;
|
||||
static const char* error_format = "Extraction of file {} failed: {}";
|
||||
|
||||
int error_code = 0;
|
||||
zip_t* zip = nullptr;
|
||||
|
||||
zip = zip_open(Utility::Path::join(_backupsDirectory, backup.filename).data(), ZIP_RDONLY, &error_code);
|
||||
zip = zip_open(Utility::Directory::join(_backupsDirectory, backup.filename).c_str(), ZIP_RDONLY, &error_code);
|
||||
if(zip == nullptr) {
|
||||
zip_error_t error;
|
||||
zip_error_init_with_code(&error, error_code);
|
||||
_lastError = zip_error_strerror(&error);
|
||||
LOG_ERROR(_lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
Containers::ScopeGuard zip_guard{zip, zip_close};
|
||||
|
||||
for(Containers::StringView file : backup.includedFiles) {
|
||||
FILE* out = std::fopen(Utility::Path::join(_saveDirectory, file).data(), "wb");
|
||||
for(const std::string& file : backup.includedFiles) {
|
||||
FILE* out = std::fopen(Utility::Directory::join(_saveDirectory, file).c_str(), "wb");
|
||||
if(out == nullptr) {
|
||||
_lastError = Utility::format(error_format.data(), file, std::strerror(errno));
|
||||
LOG_ERROR(_lastError);
|
||||
_lastError = Utility::formatString(error_format, file, std::strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
Containers::ScopeGuard out_guard{out, std::fclose};
|
||||
|
||||
zip_file_t* zf = zip_fopen(zip, file.data(), ZIP_FL_ENC_GUESS);
|
||||
zip_file_t* zf = zip_fopen(zip, file.c_str(), ZIP_FL_ENC_GUESS);
|
||||
if(zf == nullptr) {
|
||||
_lastError = Utility::format(error_format.data(), file, zip_strerror(zip));
|
||||
LOG_ERROR(_lastError);
|
||||
_lastError = Utility::formatString(error_format, file, zip_strerror(zip));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -350,15 +324,13 @@ auto ProfileManager::restoreBackup(std::size_t index) -> bool {
|
|||
Long bytes_read = 0;
|
||||
while((bytes_read = zip_fread(zf, buf.data(), buf.size())) > 0) {
|
||||
if(std::fwrite(buf.data(), sizeof(char), bytes_read, out) < static_cast<std::size_t>(bytes_read)) {
|
||||
_lastError = Utility::format(error_format.data(), file, "not enough bytes written.");
|
||||
LOG_ERROR(_lastError);
|
||||
_lastError = Utility::formatString(error_format, file, "not enough bytes written.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(bytes_read == -1) {
|
||||
_lastError = Utility::format(error_format.data(), file, "couldn't read bytes from archive.");
|
||||
LOG_ERROR(_lastError);
|
||||
_lastError = Utility::formatString(error_format, file, "couldn't read bytes from archive.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,15 +19,14 @@
|
|||
#include <string>
|
||||
|
||||
#include <Corrade/Containers/Array.h>
|
||||
#include <Corrade/Containers/String.h>
|
||||
|
||||
#include "../Profile/Profile.h"
|
||||
|
||||
using namespace Corrade;
|
||||
|
||||
struct Backup {
|
||||
Containers::String filename;
|
||||
Containers::String company;
|
||||
std::string filename;
|
||||
std::string company;
|
||||
ProfileType type;
|
||||
struct {
|
||||
int year;
|
||||
|
@ -37,15 +36,15 @@ struct Backup {
|
|||
int minute;
|
||||
int second;
|
||||
} timestamp;
|
||||
Containers::Array<Containers::String> includedFiles;
|
||||
Containers::Array<std::string> includedFiles;
|
||||
};
|
||||
|
||||
class ProfileManager {
|
||||
public:
|
||||
explicit ProfileManager(Containers::StringView save_dir, Containers::StringView backup_dir);
|
||||
explicit ProfileManager(const std::string& save_dir, const std::string& backup_dir);
|
||||
|
||||
auto ready() const -> bool;
|
||||
auto lastError() -> Containers::StringView;
|
||||
auto lastError() -> std::string const&;
|
||||
|
||||
auto profiles() -> Containers::ArrayView<Profile>;
|
||||
auto refreshProfiles() -> bool;
|
||||
|
@ -62,10 +61,10 @@ class ProfileManager {
|
|||
|
||||
private:
|
||||
bool _ready = false;
|
||||
Containers::String _lastError;
|
||||
std::string _lastError;
|
||||
|
||||
Containers::StringView _saveDirectory;
|
||||
Containers::StringView _backupsDirectory;
|
||||
const std::string& _saveDirectory;
|
||||
const std::string& _backupsDirectory;
|
||||
|
||||
Containers::Array<Profile> _profiles;
|
||||
Containers::Array<Backup> _backups;
|
||||
|
|
|
@ -16,7 +16,12 @@
|
|||
|
||||
#include "SaveTool.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <Corrade/Containers/ScopeGuard.h>
|
||||
#include <Corrade/Utility/Directory.h>
|
||||
#include <Corrade/Utility/FormatStl.h>
|
||||
#include <Corrade/Utility/String.h>
|
||||
#include <Corrade/Utility/Unicode.h>
|
||||
|
||||
#include <Magnum/GL/DebugOutput.h>
|
||||
|
@ -27,17 +32,19 @@
|
|||
#include <Magnum/ImGuiIntegration/Integration.h>
|
||||
#include <Magnum/ImGuiIntegration/Context.hpp>
|
||||
|
||||
#include <SDL.h>
|
||||
#include <cpr/cpr.h>
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <windef.h>
|
||||
#include <winuser.h>
|
||||
#include <processthreadsapi.h>
|
||||
#include <shellapi.h>
|
||||
#include <shlobj.h>
|
||||
#include <wtsapi32.h>
|
||||
|
||||
#include "../FontAwesome/IconsFontAwesome5.h"
|
||||
#include "../Logger/Logger.h"
|
||||
|
||||
using namespace Containers::Literals;
|
||||
#include "../FontAwesome/IconsFontAwesome5Brands.h"
|
||||
|
||||
extern const ImVec2 center_pivot = {0.5f, 0.5f};
|
||||
|
||||
|
@ -50,11 +57,22 @@ SaveTool::SaveTool(const Arguments& arguments):
|
|||
Configuration{}.setTitle("M.A.S.S. Builder Save Tool " SAVETOOL_VERSION " (\"" SAVETOOL_CODENAME "\")")
|
||||
.setSize({960, 720})}
|
||||
{
|
||||
#ifdef SAVETOOL_DEBUG_BUILD
|
||||
#ifdef SAVETOOL_DEBUG_BUILD
|
||||
tweak.enable("", "../../");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if(SDL_VERSION_ATLEAST(2, 0, 5)) {
|
||||
if(SDL_SetHintWithPriority(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1", SDL_HINT_OVERRIDE) == SDL_TRUE) {
|
||||
Utility::Debug{} << "Clickthrough is available.";
|
||||
}
|
||||
else {
|
||||
Utility::Warning{} << "Clickthrough is not available (hint couldn't be set).";
|
||||
}
|
||||
}
|
||||
else {
|
||||
Utility::Warning{} << "Clickthrough is not available (SDL2 is too old).";
|
||||
}
|
||||
|
||||
LOG_INFO("Configuring OpenGL renderer.");
|
||||
GL::Renderer::enable(GL::Renderer::Feature::Blending);
|
||||
GL::Renderer::enable(GL::Renderer::Feature::ScissorTest);
|
||||
GL::Renderer::disable(GL::Renderer::Feature::FaceCulling);
|
||||
|
@ -64,51 +82,60 @@ SaveTool::SaveTool(const Arguments& arguments):
|
|||
GL::Renderer::setBlendEquation(GL::Renderer::BlendEquation::Add,
|
||||
GL::Renderer::BlendEquation::Add);
|
||||
|
||||
LOG_INFO("Configuring SDL2.");
|
||||
#if SDL_VERSION_ATLEAST(2,0,5)
|
||||
if(SDL_SetHintWithPriority(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1", SDL_HINT_OVERRIDE) == SDL_TRUE) {
|
||||
LOG_INFO("Clickthrough is enabled.");
|
||||
}
|
||||
else {
|
||||
LOG_WARNING("Clickthrough is disabled.");
|
||||
}
|
||||
#else
|
||||
LOG_WARNING_FORMAT("Clickthrough is disabled: SDL2 version is too old ({}.{}.{})",
|
||||
SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL);
|
||||
#endif
|
||||
initialiseGui();
|
||||
|
||||
LOG_INFO("Registering custom events.");
|
||||
if((_initEventId = SDL_RegisterEvents(3)) == UnsignedInt(-1)) {
|
||||
if((_initEventId = SDL_RegisterEvents(2)) == UnsignedInt(-1)) {
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",
|
||||
"SDL_RegisterEvents() failed in SaveTool::SaveTool(). Exiting...", window());
|
||||
"SDL_RegisterEvents failed in SaveTool::SaveTool(). Exiting...", window());
|
||||
exit(EXIT_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
_updateEventId = _initEventId + 1;
|
||||
_fileEventId = _initEventId + 2;
|
||||
|
||||
LOG_INFO("Initialising the timer subsystem.");
|
||||
if(SDL_InitSubSystem(SDL_INIT_TIMER) != 0) {
|
||||
LOG_ERROR(SDL_GetError());
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error initialising the app",
|
||||
SDL_GetError(), window());
|
||||
exit(EXIT_FAILURE);
|
||||
return;
|
||||
_backupsDir = Utility::Directory::join(Utility::Directory::path(Utility::Directory::executableLocation()), "backups");
|
||||
_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)) {
|
||||
Utility::Directory::mkpath(_backupsDir);
|
||||
}
|
||||
|
||||
initialiseGui();
|
||||
if(!Utility::Directory::exists(_stagingDir)) {
|
||||
Utility::Directory::mkpath(_stagingDir);
|
||||
}
|
||||
|
||||
if(!initialiseToolDirectories()) {
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error initialising the app",
|
||||
_lastError.data(), window());
|
||||
exit(EXIT_FAILURE);
|
||||
return;
|
||||
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()) {
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error initialising the app",
|
||||
_lastError.data(), window());
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error initialising the app", _lastError.c_str(), window());
|
||||
exit(EXIT_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
_configDir = Utility::Directory::join(_gameDataDir, "Saved/Config/WindowsNoEditor");
|
||||
_saveDir = Utility::Directory::join(_gameDataDir, "Saved/SaveGames");
|
||||
_screenshotsDir = Utility::Directory::join(_gameDataDir, "Saved/Screenshots/WindowsNoEditor");
|
||||
|
||||
if(SDL_InitSubSystem(SDL_INIT_TIMER) != 0) {
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error initialising the app", SDL_GetError(), window());
|
||||
exit(EXIT_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
@ -118,9 +145,9 @@ SaveTool::SaveTool(const Arguments& arguments):
|
|||
[](UnsignedInt interval, void* param)->UnsignedInt{
|
||||
static_cast<SaveTool*>(param)->checkGameState();
|
||||
return interval;
|
||||
}, this);
|
||||
},
|
||||
this);
|
||||
if(_gameCheckTimerId == 0) {
|
||||
LOG_ERROR(SDL_GetError());
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", SDL_GetError(), window());
|
||||
exit(EXIT_FAILURE);
|
||||
return;
|
||||
|
@ -128,11 +155,22 @@ SaveTool::SaveTool(const Arguments& arguments):
|
|||
|
||||
initialiseConfiguration();
|
||||
|
||||
LOG_INFO("Initialising update checker.");
|
||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
switch(_framelimit) {
|
||||
case Framelimit::Vsync:
|
||||
setSwapInterval(1);
|
||||
break;
|
||||
case Framelimit::HalfVsync:
|
||||
setSwapInterval(2);
|
||||
break;
|
||||
case Framelimit::FpsCap:
|
||||
setSwapInterval(0);
|
||||
setMinimalLoopPeriod(1000/_fpsCap);
|
||||
break;
|
||||
}
|
||||
|
||||
if(_checkUpdatesOnStartup) {
|
||||
_queue.addToast(Toast::Type::Default, "Checking for updates..."_s);
|
||||
_updateThread = std::thread{[this]{ checkForUpdates(); }};
|
||||
_queue.addToast(Toast::Type::Default, "Checking for updates...");
|
||||
}
|
||||
|
||||
if(GL::Context::current().isExtensionSupported<GL::Extensions::KHR::debug>() &&
|
||||
|
@ -145,57 +183,138 @@ SaveTool::SaveTool(const Arguments& arguments):
|
|||
_uiState = UiState::Initialising;
|
||||
_initThread = std::thread{[this]{ initialiseManager(); }};
|
||||
}
|
||||
|
||||
_timeline.start();
|
||||
}
|
||||
|
||||
SaveTool::~SaveTool() {
|
||||
LOG_INFO("Cleaning up.");
|
||||
|
||||
LOG_INFO("Shutting libcurl down.");
|
||||
curl_global_cleanup();
|
||||
|
||||
SDL_RemoveTimer(_gameCheckTimerId);
|
||||
|
||||
LOG_INFO("Saving the configuration.");
|
||||
_conf.setValue("cheat_mode", _cheatMode);
|
||||
_conf.setValue("unsafe_mode", _unsafeMode);
|
||||
_conf.setValue("startup_update_check", _checkUpdatesOnStartup);
|
||||
_conf.setValue("skip_disclaimer", _skipDisclaimer);
|
||||
|
||||
_conf.setValue("cheat_mode"_s, _cheatMode);
|
||||
_conf.setValue("advanced_mode"_s, _advancedMode);
|
||||
_conf.setValue("startup_update_check"_s, _checkUpdatesOnStartup);
|
||||
_conf.setValue("skip_disclaimer"_s, _skipDisclaimer);
|
||||
_conf.setValue("swap_interval"_s, _swapInterval);
|
||||
_conf.setValue("fps_cap"_s, _fpsCap);
|
||||
switch(_framelimit) {
|
||||
case Framelimit::Vsync:
|
||||
_conf.setValue("frame_limit", "vsync");
|
||||
break;
|
||||
case Framelimit::HalfVsync:
|
||||
_conf.setValue("frame_limit", "half_vsync");
|
||||
break;
|
||||
case Framelimit::FpsCap:
|
||||
_conf.setValue<UnsignedInt>("frame_limit", _fpsCap);
|
||||
break;
|
||||
}
|
||||
|
||||
_conf.save();
|
||||
}
|
||||
|
||||
LOG_INFO("Exiting.");
|
||||
void SaveTool::handleFileAction(efsw::WatchID watch_id,
|
||||
const std::string&,
|
||||
const std::string& filename,
|
||||
efsw::Action action,
|
||||
std::string old_filename)
|
||||
{
|
||||
if(watch_id == _watchIDs[StagingDir] && Utility::String::endsWith(filename, ".sav")) {
|
||||
_massManager->refreshStagedMasses();
|
||||
return;
|
||||
}
|
||||
|
||||
if(Utility::String::endsWith(filename, "Config.sav")) {
|
||||
return;
|
||||
}
|
||||
|
||||
static bool is_moved_after_save = false;
|
||||
|
||||
switch(action) {
|
||||
case efsw::Actions::Add:
|
||||
if(Utility::String::endsWith(filename, _currentProfile->account() + ".sav")) {
|
||||
if(Utility::String::beginsWith(filename, Utility::formatString("{}Unit", _currentProfile->type() == ProfileType::Demo ? "Demo" : ""))) {
|
||||
int index = ((filename[_currentProfile->type() == ProfileType::Demo ? 8 : 4] - 0x30) * 10) +
|
||||
(filename[_currentProfile->type() == ProfileType::Demo ? 9 : 5] - 0x30);
|
||||
if(!_currentMass || _currentMass != &(_massManager->hangar(index))) {
|
||||
_massManager->refreshHangar(index);
|
||||
}
|
||||
else {
|
||||
_currentMass->setDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case efsw::Actions::Delete:
|
||||
if(Utility::String::endsWith(filename, _currentProfile->account() + ".sav")) {
|
||||
if(Utility::String::beginsWith(filename, Utility::formatString("{}Unit", _currentProfile->type() == ProfileType::Demo ? "Demo" : ""))) {
|
||||
int index = ((filename[_currentProfile->type() == ProfileType::Demo ? 8 : 4] - 0x30) * 10) +
|
||||
(filename[_currentProfile->type() == ProfileType::Demo ? 9 : 5] - 0x30);
|
||||
if(!_currentMass || _currentMass != &(_massManager->hangar(index))) {
|
||||
_massManager->refreshHangar(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case efsw::Actions::Modified:
|
||||
if(filename == _currentProfile->filename()) {
|
||||
_currentProfile->refreshValues();
|
||||
}
|
||||
else if(Utility::String::endsWith(filename, _currentProfile->account() + ".sav")) {
|
||||
if(Utility::String::beginsWith(filename, Utility::formatString("{}Unit", _currentProfile->type() == ProfileType::Demo ? "Demo" : ""))) {
|
||||
int index = ((filename[_currentProfile->type() == ProfileType::Demo ? 8 : 4] - 0x30) * 10) +
|
||||
(filename[_currentProfile->type() == ProfileType::Demo ? 9 : 5] - 0x30);
|
||||
|
||||
if(!_currentMass || _currentMass != &(_massManager->hangar(index))) {
|
||||
_massManager->refreshHangar(index);
|
||||
}
|
||||
else {
|
||||
if(!is_moved_after_save) {
|
||||
is_moved_after_save = false;
|
||||
_currentMass->setDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case efsw::Actions::Moved:
|
||||
if(Utility::String::endsWith(filename, _currentProfile->account() + ".sav")) {
|
||||
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) +
|
||||
(filename[_currentProfile->type() == ProfileType::Demo ? 9 : 5] - 0x30);
|
||||
_massManager->refreshHangar(index);
|
||||
|
||||
int old_index = ((old_filename[_currentProfile->type() == ProfileType::Demo ? 8 : 4] - 0x30) * 10) +
|
||||
(old_filename[_currentProfile->type() == ProfileType::Demo ? 9 : 5] - 0x30);
|
||||
_massManager->refreshHangar(old_index);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", "Unknown file watcher action type.", window());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SaveTool::drawEvent() {
|
||||
#ifdef SAVETOOL_DEBUG_BUILD
|
||||
#ifdef SAVETOOL_DEBUG_BUILD
|
||||
tweak.update();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
GL::defaultFramebuffer.clear(GL::FramebufferClear::Color);
|
||||
|
||||
drawImGui();
|
||||
|
||||
swapBuffers();
|
||||
|
||||
if(_swapInterval == 0 && _fpsCap < 301.0f) {
|
||||
while(_timeline.currentFrameDuration() < (1.0f / _fpsCap));
|
||||
}
|
||||
|
||||
redraw();
|
||||
|
||||
_timeline.nextFrame();
|
||||
}
|
||||
|
||||
void SaveTool::viewportEvent(ViewportEvent& event) {
|
||||
GL::defaultFramebuffer.setViewport({{}, event.framebufferSize()});
|
||||
|
||||
const Vector2 size = Vector2{windowSize()}/dpiScaling();
|
||||
_imgui.relayout(size, windowSize(), framebufferSize());
|
||||
_imgui.relayout(event.windowSize());
|
||||
}
|
||||
|
||||
void SaveTool::keyPressEvent(KeyEvent& event) {
|
||||
|
@ -236,11 +355,247 @@ void SaveTool::anyEvent(SDL_Event& event) {
|
|||
else if(event.type == _updateEventId) {
|
||||
updateCheckEvent(event);
|
||||
}
|
||||
else if(event.type == _fileEventId) {
|
||||
fileUpdateEvent(event);
|
||||
}
|
||||
|
||||
void SaveTool::initEvent(SDL_Event& event) {
|
||||
_initThread.join();
|
||||
|
||||
switch(event.user.code) {
|
||||
case InitSuccess:
|
||||
_uiState = UiState::ProfileManager;
|
||||
ImGui::CloseCurrentPopup();
|
||||
break;
|
||||
case ProfileManagerFailure:
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error initialising ProfileManager", _profileManager->lastError().c_str(), window());
|
||||
exit(EXIT_FAILURE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SaveTool::updateCheckEvent(SDL_Event& event) {
|
||||
_updateThread.join();
|
||||
|
||||
cpr::Response r{std::move(*static_cast<cpr::Response*>(event.user.data1))};
|
||||
delete static_cast<cpr::Response*>(event.user.data1);
|
||||
|
||||
if(r.elapsed > 10.0) {
|
||||
_queue.addToast(Toast::Type::Error, "The request timed out.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(r.status_code != 200) {
|
||||
_queue.addToast(Toast::Type::Error, Utility::formatString("The request failed with error code {}: {}", r.status_code, r.reason));
|
||||
return;
|
||||
}
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
json response = json::parse(r.text);
|
||||
|
||||
struct Version {
|
||||
explicit Version(const std::string& str) {
|
||||
std::size_t start_point = 0;
|
||||
|
||||
if(str[0] == 'v') {
|
||||
start_point++;
|
||||
}
|
||||
|
||||
major = std::atoi(str.c_str() + start_point);
|
||||
start_point = str.find('.', start_point) + 1;
|
||||
minor = std::atoi(str.c_str() + start_point);
|
||||
start_point = str.find('.', start_point) + 1;
|
||||
patch = std::atoi(str.c_str() + start_point);
|
||||
}
|
||||
Int major;
|
||||
Int minor;
|
||||
Int patch;
|
||||
|
||||
bool operator==(const Version& other) const {
|
||||
return (major == other.major) && (minor == other.minor) && (patch == other.patch);
|
||||
}
|
||||
bool operator>(const Version& other) const {
|
||||
return ( major * 10000 + minor * 100 + 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};
|
||||
|
||||
for(auto& release : response) {
|
||||
if(release["prerelease"] == true) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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.",
|
||||
std::chrono::milliseconds{5000});
|
||||
_updateAvailable = true;
|
||||
_latestVersion = latest_ver;
|
||||
_releaseLink = release["html_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) {
|
||||
_queue.addToast(Toast::Type::Warning, "Your version is more recent than the latest one in the repo. How???");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SaveTool::initialiseConfiguration() {
|
||||
if(_conf.hasValue("cheat_mode")) {
|
||||
_cheatMode = _conf.value<bool>("cheat_mode");
|
||||
}
|
||||
else {
|
||||
_conf.setValue("cheat_mode", _cheatMode);
|
||||
}
|
||||
|
||||
if(_conf.hasValue("unsafe_mode")) {
|
||||
_unsafeMode = _conf.value<bool>("unsafe_mode");
|
||||
}
|
||||
else {
|
||||
_conf.setValue("unsafe_mode", _unsafeMode);
|
||||
}
|
||||
|
||||
if(_conf.hasValue("startup_update_check")) {
|
||||
_checkUpdatesOnStartup = _conf.value<bool>("startup_update_check");
|
||||
}
|
||||
else {
|
||||
_conf.setValue("startup_update_check", _checkUpdatesOnStartup);
|
||||
}
|
||||
|
||||
if(_conf.hasValue("skip_disclaimer")) {
|
||||
_skipDisclaimer = _conf.value<bool>("skip_disclaimer");
|
||||
}
|
||||
else {
|
||||
_conf.setValue("skip_disclaimer", _skipDisclaimer);
|
||||
}
|
||||
|
||||
if(_conf.hasValue("frame_limit")) {
|
||||
std::string frame_limit = _conf.value("frame_limit");
|
||||
if(frame_limit == "vsync") {
|
||||
_framelimit = Framelimit::Vsync;
|
||||
}
|
||||
else if(frame_limit == "half_vsync") {
|
||||
_framelimit = Framelimit::HalfVsync;
|
||||
}
|
||||
else {
|
||||
_framelimit = Framelimit::FpsCap;
|
||||
_fpsCap = std::stoul(frame_limit);
|
||||
}
|
||||
}
|
||||
else {
|
||||
_conf.setValue("frame_limit", "vsync");
|
||||
}
|
||||
|
||||
_conf.save();
|
||||
}
|
||||
|
||||
void SaveTool::initialiseGui() {
|
||||
ImGui::CreateContext();
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
auto reg_font = _rs.getRaw("SourceSansPro-Regular.ttf");
|
||||
ImFontConfig font_config;
|
||||
font_config.FontDataOwnedByAtlas = false;
|
||||
std::strcpy(font_config.Name, "Source Sans Pro");
|
||||
io.Fonts->AddFontFromMemoryTTF(const_cast<char*>(reg_font.data()), reg_font.size(), 20.0f, &font_config);
|
||||
|
||||
auto icon_font = _rs.getRaw(FONT_ICON_FILE_NAME_FAS);
|
||||
static const ImWchar icon_range[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };
|
||||
ImFontConfig icon_config;
|
||||
icon_config.FontDataOwnedByAtlas = false;
|
||||
icon_config.MergeMode = true;
|
||||
icon_config.PixelSnapH = true;
|
||||
icon_config.OversampleH = icon_config.OversampleV = 1;
|
||||
icon_config.GlyphMinAdvanceX = 18.0f;
|
||||
io.Fonts->AddFontFromMemoryTTF(const_cast<char*>(icon_font.data()), icon_font.size(), 16.0f, &icon_config, icon_range);
|
||||
|
||||
auto brand_font = _rs.getRaw(FONT_ICON_FILE_NAME_FAB);
|
||||
static const ImWchar brand_range[] = { ICON_MIN_FAB, ICON_MAX_FAB, 0 };
|
||||
io.Fonts->AddFontFromMemoryTTF(const_cast<char*>(brand_font.data()), brand_font.size(), 16.0f, &icon_config, brand_range);
|
||||
|
||||
auto mono_font = _rs.getRaw("SourceCodePro-Regular.ttf");
|
||||
ImVector<ImWchar> range;
|
||||
ImFontGlyphRangesBuilder builder;
|
||||
builder.AddRanges(io.Fonts->GetGlyphRangesDefault());
|
||||
builder.AddChar(u'š'); // This allows displaying Vladimír Vondruš' name in Corrade's and Magnum's licences.
|
||||
builder.BuildRanges(&range);
|
||||
io.Fonts->AddFontFromMemoryTTF(const_cast<char*>(mono_font.data()), mono_font.size(), 18.0f, &font_config, range.Data);
|
||||
|
||||
_imgui = ImGuiIntegration::Context(*ImGui::GetCurrentContext(), windowSize());
|
||||
|
||||
io.IniFilename = nullptr;
|
||||
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
|
||||
style.WindowTitleAlign = {0.5f, 0.5f};
|
||||
style.FrameRounding = 3.2f;
|
||||
style.Colors[ImGuiCol_WindowBg] = ImColor(0xff1f1f1f);
|
||||
}
|
||||
|
||||
void SaveTool::initialiseManager() {
|
||||
SDL_Event event;
|
||||
SDL_zero(event);
|
||||
event.type = _initEventId;
|
||||
|
||||
_profileManager.emplace(_saveDir, _backupsDir);
|
||||
if(!_profileManager->ready()) {
|
||||
event.user.code = ProfileManagerFailure;
|
||||
SDL_PushEvent(&event);
|
||||
return;
|
||||
}
|
||||
|
||||
event.user.code = InitSuccess;
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
|
||||
auto SaveTool::findGameDataDirectory() -> bool {
|
||||
wchar_t* localappdata_path = nullptr;
|
||||
Containers::ScopeGuard guard{localappdata_path, CoTaskMemFree};
|
||||
if(SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_NO_APPCONTAINER_REDIRECTION, nullptr, &localappdata_path) != S_OK)
|
||||
{
|
||||
_lastError = "SHGetKnownFolderPath() failed in SaveTool::findGameDataDirectory()";
|
||||
return false;
|
||||
}
|
||||
|
||||
_gameDataDir = Utility::Directory::join(Utility::Directory::fromNativeSeparators(Utility::Unicode::narrow(localappdata_path)), "MASS_Builder");
|
||||
|
||||
if(!Utility::Directory::exists(_gameDataDir)) {
|
||||
_lastError = _gameDataDir + " wasn't found. Make sure to play the game at least once.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SaveTool::initialiseMassManager() {
|
||||
_massManager.emplace(_saveDir,
|
||||
_currentProfile->account(),
|
||||
_currentProfile->type() == ProfileType::Demo,
|
||||
_stagingDir);
|
||||
|
||||
initialiseFileWatcher();
|
||||
}
|
||||
|
||||
void SaveTool::initialiseFileWatcher() {
|
||||
_fileWatcher.emplace();
|
||||
_watchIDs[SaveDir] = _fileWatcher->addWatch(_saveDir, this, false);
|
||||
_watchIDs[StagingDir] = _fileWatcher->addWatch(_stagingDir, this, false);
|
||||
_fileWatcher->watch();
|
||||
}
|
||||
|
||||
void SaveTool::drawImGui() {
|
||||
_imgui.newFrame();
|
||||
|
||||
|
@ -283,7 +638,7 @@ void SaveTool::drawGui() {
|
|||
drawAbout();
|
||||
}
|
||||
|
||||
#ifdef SAVETOOL_DEBUG_BUILD
|
||||
#ifdef SAVETOOL_DEBUG_BUILD
|
||||
if(_demoWindow) {
|
||||
ImGui::ShowDemoWindow(&_demoWindow);
|
||||
}
|
||||
|
@ -295,7 +650,7 @@ void SaveTool::drawGui() {
|
|||
if(_metricsWindow) {
|
||||
ImGui::ShowMetricsWindow(&_metricsWindow);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
_queue.draw(windowSize());
|
||||
}
|
||||
|
@ -314,11 +669,11 @@ void SaveTool::drawDisclaimer() {
|
|||
|
||||
ImGui::TextUnformatted("Before you start using the app, there are a few things you should know:");
|
||||
|
||||
ImGui::PushTextWrapPos(float(windowSize().x()) * 0.67f);
|
||||
ImGui::PushTextWrapPos(windowSize().x() * 0.67f);
|
||||
|
||||
ImGui::Bullet();
|
||||
ImGui::SameLine();
|
||||
ImGui::TextUnformatted(R"(For this application to work properly, it is recommended to disable Steam Cloud syncing for the game. To disable it, right-click the game in your Steam library, click "Properties", go to the "General" tab, and uncheck "Keep game saves in the Steam Cloud for M.A.S.S. Builder".)");
|
||||
ImGui::TextUnformatted("For this application to work properly, it is recommended to disable Steam Cloud syncing for the game. To disable it, right-click the game in your Steam library, click \"Properties\", go to the \"General\" tab, and uncheck \"Keep game saves in the Steam Cloud for M.A.S.S. Builder\".");
|
||||
|
||||
ImGui::Bullet();
|
||||
ImGui::SameLine();
|
||||
|
@ -393,18 +748,18 @@ void SaveTool::drawGameState() {
|
|||
}
|
||||
}
|
||||
|
||||
void SaveTool::drawHelpMarker(Containers::StringView text, Float wrap_pos) {
|
||||
void SaveTool::drawHelpMarker(const char* text, Float wrap_pos) {
|
||||
ImGui::TextUnformatted(ICON_FA_QUESTION_CIRCLE);
|
||||
drawTooltip(text, wrap_pos);
|
||||
}
|
||||
|
||||
void SaveTool::drawTooltip(Containers::StringView text, Float wrap_pos) {
|
||||
void SaveTool::drawTooltip(const char* text, Float wrap_pos) {
|
||||
if(ImGui::IsItemHovered()){
|
||||
ImGui::BeginTooltip();
|
||||
if(wrap_pos > 0.0f) {
|
||||
ImGui::PushTextWrapPos(wrap_pos);
|
||||
}
|
||||
ImGui::TextUnformatted(text.data());
|
||||
ImGui::TextUnformatted(text);
|
||||
if(wrap_pos > 0.0f) {
|
||||
ImGui::PopTextWrapPos();
|
||||
}
|
||||
|
@ -412,8 +767,8 @@ void SaveTool::drawTooltip(Containers::StringView text, Float wrap_pos) {
|
|||
}
|
||||
}
|
||||
|
||||
void SaveTool::openUri(Containers::StringView uri) {
|
||||
ShellExecuteW(nullptr, nullptr, Utility::Unicode::widen(uri.data()), nullptr, nullptr, SW_SHOWDEFAULT);
|
||||
void SaveTool::openUri(const std::string& uri) {
|
||||
ShellExecuteW(nullptr, nullptr, Utility::Unicode::widen(uri).c_str(), nullptr, nullptr, SW_SHOWDEFAULT);
|
||||
}
|
||||
|
||||
void SaveTool::checkGameState() {
|
||||
|
@ -437,3 +792,14 @@ void SaveTool::checkGameState() {
|
|||
_gameState = GameState::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
void SaveTool::checkForUpdates() {
|
||||
cpr::Response r = cpr::Get(cpr::Url{"https://williamjcm.ovh/git/api/v1/repos/williamjcm/MassBuilderSaveTool/releases"}, cpr::Timeout{10000});
|
||||
|
||||
SDL_Event event;
|
||||
SDL_zero(event);
|
||||
event.type = _updateEventId;
|
||||
event.user.code = r.status_code;
|
||||
event.user.data1 = new cpr::Response{std::move(r)};
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
|
|
|
@ -16,22 +16,16 @@
|
|||
// 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 <thread>
|
||||
|
||||
#include <Corrade/Containers/Pointer.h>
|
||||
#include <Corrade/Containers/String.h>
|
||||
#include <Corrade/Utility/Configuration.h>
|
||||
#include <Corrade/Utility/Resource.h>
|
||||
#ifdef SAVETOOL_DEBUG_BUILD
|
||||
#include <Corrade/Utility/Tweakable.h>
|
||||
#endif
|
||||
|
||||
#include <Magnum/Timeline.h>
|
||||
#include <Magnum/Platform/Sdl2Application.h>
|
||||
#include <Magnum/ImGuiIntegration/Context.h>
|
||||
|
||||
#include <SDL_timer.h>
|
||||
#include <SDL.h>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
|
@ -43,11 +37,12 @@
|
|||
#include "../ToastQueue/ToastQueue.h"
|
||||
|
||||
#ifdef SAVETOOL_DEBUG_BUILD
|
||||
#include <Corrade/Utility/Tweakable.h>
|
||||
|
||||
#define tw CORRADE_TWEAKABLE
|
||||
#endif
|
||||
|
||||
using namespace Corrade;
|
||||
using namespace Containers::Literals;
|
||||
using namespace Magnum;
|
||||
|
||||
class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener {
|
||||
|
@ -83,28 +78,12 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener
|
|||
ProfileManagerFailure
|
||||
};
|
||||
void initEvent(SDL_Event& event);
|
||||
|
||||
enum UpdateCheckStatus : Int {
|
||||
CurlInitFailed = 0,
|
||||
CurlError = 1,
|
||||
CurlTimeout = 2,
|
||||
};
|
||||
void updateCheckEvent(SDL_Event& event);
|
||||
|
||||
enum FileEventType: Int {
|
||||
FileAdded = efsw::Action::Add,
|
||||
FileDeleted = efsw::Action::Delete,
|
||||
FileModified = efsw::Action::Modified,
|
||||
FileMoved = efsw::Action::Moved,
|
||||
StagedUpdate = 1 << 3
|
||||
};
|
||||
void fileUpdateEvent(SDL_Event& event);
|
||||
|
||||
// Initialisation methods
|
||||
void initialiseConfiguration();
|
||||
void initialiseGui();
|
||||
void initialiseManager();
|
||||
auto initialiseToolDirectories() -> bool;
|
||||
auto findGameDataDirectory() -> bool;
|
||||
void initialiseMassManager();
|
||||
void initialiseFileWatcher();
|
||||
|
@ -127,11 +106,11 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener
|
|||
void drawGeneralInfo();
|
||||
void drawResearchInventory();
|
||||
template<typename Getter, typename Setter>
|
||||
void drawMaterialRow(Containers::StringView name, Int tier, Getter getter, Setter setter);
|
||||
void drawUnavailableMaterialRow(Containers::StringView name, Int tier);
|
||||
void drawMaterialRow(const char* name, Int tier, Getter getter, Setter setter);
|
||||
void drawUnavailableMaterialRow(const char* name, Int tier);
|
||||
void drawMassManager();
|
||||
auto drawDeleteMassPopup(int mass_index) -> ImGuiID;
|
||||
auto drawDeleteStagedMassPopup(Containers::StringView filename) -> ImGuiID;
|
||||
auto drawDeleteStagedMassPopup(const std::string& filename) -> ImGuiID;
|
||||
|
||||
void drawMassViewer();
|
||||
void drawFrameInfo();
|
||||
|
@ -142,14 +121,13 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener
|
|||
void drawArmour();
|
||||
void drawCustomArmourStyles();
|
||||
void drawWeapons();
|
||||
void drawWeaponCategory(Containers::StringView name, Containers::ArrayView<Weapon> weapons_view, bool& dirty,
|
||||
Containers::StringView payload_type, Containers::StringView payload_tooltip);
|
||||
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) -> Containers::StringView;
|
||||
auto getStyleName(Int id, Containers::ArrayView<CustomStyle> view) -> const char*;
|
||||
|
||||
enum DCSResult {
|
||||
DCS_Fail,
|
||||
|
@ -162,22 +140,31 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener
|
|||
void drawGameState();
|
||||
|
||||
// Convenience wrappers over ImGui stuff
|
||||
void drawHelpMarker(Containers::StringView text, Float wrap_pos = 0.0f);
|
||||
void drawTooltip(Containers::StringView text, Float wrap_pos = 0.0f);
|
||||
void drawHelpMarker(const char* text, Float wrap_pos = 0.0f);
|
||||
void drawTooltip(const char* text, Float wrap_pos = 0.0f);
|
||||
|
||||
template<typename Functor, typename... Args>
|
||||
auto drawUnsafeWidget(Functor func, Args... args) -> bool {
|
||||
GameState game_state = _gameState; // Copying the value to reduce the risk of a data race.
|
||||
ImGui::BeginDisabled(game_state != GameState::NotRunning);
|
||||
if(!_unsafeMode && game_state != GameState::NotRunning) {
|
||||
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.5f);
|
||||
}
|
||||
|
||||
bool result = func(std::forward<Args>(args)...);
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if(!_unsafeMode && game_state != GameState::NotRunning) {
|
||||
ImGui::PopItemFlag();
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
return result;
|
||||
} // Obviously, should only be used with ImGui widgets that return a bool.
|
||||
// Also, func should be a lambda if there are any default arguments, like ImGui::Button(), etc...
|
||||
|
||||
template<typename... Args>
|
||||
void drawUnsafeText(const char* text, Args... args) { // Alternative to the above, for ImGui::Text*() variants.
|
||||
if(_gameState != GameState::NotRunning) {
|
||||
if(!_unsafeMode && _gameState != GameState::NotRunning) {
|
||||
ImGui::TextDisabled(text, std::forward<Args>(args)...);
|
||||
}
|
||||
else {
|
||||
|
@ -186,19 +173,19 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener
|
|||
}
|
||||
|
||||
template<typename... Args>
|
||||
void drawAlignedText(Containers::StringView text, Args... args) {
|
||||
void drawAlignedText(const char* text, Args... args) {
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text(text.data(), std::forward<Args>(args)...);
|
||||
ImGui::Text(text, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void openUri(Containers::StringView uri);
|
||||
void openUri(const std::string& uri);
|
||||
|
||||
void checkGameState();
|
||||
|
||||
void checkForUpdates();
|
||||
|
||||
Utility::Configuration _conf{"MassBuilderSaveTool.ini"_s};
|
||||
Utility::Resource _rs{"assets"_s};
|
||||
Utility::Configuration _conf{"MassBuilderSaveTool.ini"};
|
||||
Utility::Resource _rs{"assets"};
|
||||
|
||||
// GUI-related members
|
||||
ImGuiIntegration::Context _imgui{NoCreate};
|
||||
|
@ -212,11 +199,11 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener
|
|||
} _uiState{UiState::Disclaimer};
|
||||
|
||||
bool _aboutPopup{false};
|
||||
#ifdef SAVETOOL_DEBUG_BUILD
|
||||
#ifdef SAVETOOL_DEBUG_BUILD
|
||||
bool _demoWindow{false};
|
||||
bool _styleEditor{false};
|
||||
bool _metricsWindow{false};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ToastQueue _queue;
|
||||
|
||||
|
@ -225,24 +212,23 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener
|
|||
|
||||
UnsignedInt _initEventId;
|
||||
UnsignedInt _updateEventId;
|
||||
UnsignedInt _fileEventId;
|
||||
|
||||
Containers::String _lastError;
|
||||
std::string _lastError;
|
||||
|
||||
Containers::String _gameDataDir;
|
||||
Containers::String _configDir;
|
||||
Containers::String _saveDir;
|
||||
Containers::String _screenshotsDir;
|
||||
std::string _gameDataDir;
|
||||
std::string _configDir;
|
||||
std::string _saveDir;
|
||||
std::string _screenshotsDir;
|
||||
|
||||
Containers::String _backupsDir;
|
||||
Containers::String _stagingDir;
|
||||
//Containers::String _armouryDir;
|
||||
//Containers::String _armoursDir;
|
||||
//Containers::String _weaponsDir;
|
||||
//Containers::String _stylesDir;
|
||||
std::string _backupsDir;
|
||||
std::string _stagingDir;
|
||||
std::string _armouryDir;
|
||||
std::string _armoursDir;
|
||||
std::string _weaponsDir;
|
||||
std::string _stylesDir;
|
||||
|
||||
enum class GameState : UnsignedByte {
|
||||
Unknown, NotRunning, Running
|
||||
Unknown, NotRunning, Running
|
||||
} _gameState{GameState::Unknown};
|
||||
|
||||
SDL_TimerID _gameCheckTimerId = 0;
|
||||
|
@ -262,24 +248,27 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener
|
|||
};
|
||||
Containers::StaticArray<2, efsw::WatchID> _watchIDs;
|
||||
|
||||
int _swapInterval = 1;
|
||||
float _fpsCap = 60.0f;
|
||||
enum class Framelimit: UnsignedByte {
|
||||
Vsync,
|
||||
HalfVsync,
|
||||
FpsCap
|
||||
} _framelimit{Framelimit::Vsync};
|
||||
UnsignedInt _fpsCap{60};
|
||||
|
||||
bool _skipDisclaimer{false};
|
||||
bool _checkUpdatesOnStartup{true};
|
||||
bool _unsafeMode{false};
|
||||
|
||||
bool _updateAvailable{false};
|
||||
Containers::String _latestVersion;
|
||||
Containers::String _releaseLink;
|
||||
Containers::String _downloadLink;
|
||||
std::string _latestVersion;
|
||||
std::string _releaseLink;
|
||||
std::string _downloadLink;
|
||||
|
||||
bool _modifiedBySaveTool{false};
|
||||
bool _jointsDirty{false};
|
||||
bool _stylesDirty{false};
|
||||
bool _eyeFlareDirty{false};
|
||||
Containers::StaticArray<38, Int> _selectedArmourDecals{ValueInit};
|
||||
Containers::StaticArray<38, Int> _selectedArmourAccessories{ValueInit};
|
||||
Int _selectedBLPlacement{0};
|
||||
Int _selectedWeaponPart{0};
|
||||
Int _selectedWeaponDecal{0};
|
||||
Int _selectedWeaponAccessory{0};
|
||||
|
@ -291,7 +280,4 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener
|
|||
bool _eLaunchersDirty{false};
|
||||
|
||||
bool _cheatMode{false};
|
||||
bool _advancedMode{false};
|
||||
|
||||
Timeline _timeline;
|
||||
};
|
||||
|
|
|
@ -1,150 +0,0 @@
|
|||
// 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/Format.h>
|
||||
#include <Corrade/Utility/String.h>
|
||||
#include <Corrade/Utility/Unicode.h>
|
||||
|
||||
#include <SDL_events.h>
|
||||
#include <SDL_messagebox.h>
|
||||
|
||||
#include <fileapi.h>
|
||||
#include <handleapi.h>
|
||||
|
||||
#include "SaveTool.h"
|
||||
|
||||
void SaveTool::handleFileAction(efsw::WatchID watch_id,
|
||||
const std::string&,
|
||||
const std::string& filename,
|
||||
efsw::Action action,
|
||||
std::string old_filename)
|
||||
{
|
||||
SDL_Event event;
|
||||
SDL_zero(event);
|
||||
event.type = _fileEventId;
|
||||
|
||||
event.user.data1 = Containers::String{Containers::AllocatedInit, filename.c_str()}.release();
|
||||
|
||||
if(watch_id == _watchIDs[StagingDir] && Utility::String::endsWith(filename, ".sav")) {
|
||||
event.user.code = StagedUpdate | action;
|
||||
SDL_PushEvent(&event);
|
||||
return;
|
||||
}
|
||||
|
||||
if(Utility::String::endsWith(filename, "Config.sav")) {
|
||||
return;
|
||||
} // TODO: actually do something when config files will finally be handled
|
||||
|
||||
if(!Utility::String::endsWith(filename, Utility::format("Profile{}.sav", _currentProfile->account()).data())) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.user.code = action;
|
||||
if(action == efsw::Actions::Moved) {
|
||||
event.user.data2 = Containers::String{Containers::AllocatedInit, old_filename.c_str()}.release();
|
||||
}
|
||||
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
|
||||
void SaveTool::fileUpdateEvent(SDL_Event& event) {
|
||||
Containers::String filename{static_cast<char*>(event.user.data1),
|
||||
std::strlen(static_cast<char*>(event.user.data1)), nullptr};
|
||||
|
||||
if((event.user.code & StagedUpdate) == StagedUpdate) {
|
||||
_massManager->refreshStagedMass(filename);
|
||||
return;
|
||||
}
|
||||
|
||||
Containers::String old_filename;
|
||||
|
||||
Int index = 0;
|
||||
Int old_index = 0;
|
||||
bool is_current_profile = filename == _currentProfile->filename();
|
||||
bool is_unit = filename.hasPrefix(_currentProfile->isDemo() ? "DemoUnit"_s : "Unit"_s);
|
||||
if(is_unit) {
|
||||
index = ((filename[_currentProfile->isDemo() ? 8 : 4] - 0x30) * 10) +
|
||||
(filename[_currentProfile->isDemo() ? 9 : 5] - 0x30);
|
||||
}
|
||||
|
||||
if(event.user.code == FileMoved) {
|
||||
old_filename = Containers::String{static_cast<char*>(event.user.data2), std::strlen(static_cast<char*>(event.user.data2)), nullptr};
|
||||
old_index = ((old_filename[_currentProfile->isDemo() ? 8 : 4] - 0x30) * 10) +
|
||||
(old_filename[_currentProfile->isDemo() ? 9 : 5] - 0x30);
|
||||
}
|
||||
|
||||
switch(event.user.code) {
|
||||
case FileAdded:
|
||||
if(is_unit) {
|
||||
if(!_currentMass || _currentMass != &(_massManager->hangar(index))) {
|
||||
_massManager->refreshHangar(index);
|
||||
}
|
||||
else {
|
||||
_currentMass->setDirty();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FileDeleted:
|
||||
if(is_current_profile) {
|
||||
_currentProfile = nullptr;
|
||||
_uiState = UiState::ProfileManager;
|
||||
if(!_profileManager->refreshProfiles()) {
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",
|
||||
_profileManager->lastError().data(), window());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else if(is_unit) {
|
||||
if(!_currentMass || _currentMass != &(_massManager->hangar(index))) {
|
||||
_massManager->refreshHangar(index);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FileModified:
|
||||
if(is_current_profile) {
|
||||
_currentProfile->refreshValues();
|
||||
}
|
||||
else if(is_unit) {
|
||||
if(!_currentMass || _currentMass != &(_massManager->hangar(index))) {
|
||||
_massManager->refreshHangar(index);
|
||||
}
|
||||
else {
|
||||
if(_modifiedBySaveTool && _currentMass->filename() == filename) {
|
||||
auto handle = CreateFileW(Utility::Unicode::widen(Containers::StringView{filename}), GENERIC_READ, 0,
|
||||
nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if(handle && handle != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(handle);
|
||||
_modifiedBySaveTool = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
_currentMass->setDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FileMoved:
|
||||
if(is_unit) {
|
||||
if(old_filename.hasSuffix(".sav"_s)) {
|
||||
_massManager->refreshHangar(index);
|
||||
_massManager->refreshHangar(old_index);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_queue.addToast(Toast::Type::Warning, "Unknown file action type"_s);
|
||||
}
|
||||
}
|
|
@ -1,280 +0,0 @@
|
|||
// 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/Pair.h>
|
||||
#include <Corrade/Containers/ScopeGuard.h>
|
||||
#include <Corrade/Utility/Path.h>
|
||||
#include <Corrade/Utility/Unicode.h>
|
||||
|
||||
#include <SDL_events.h>
|
||||
#include <SDL_messagebox.h>
|
||||
|
||||
#include <shlobj.h>
|
||||
|
||||
#include "../FontAwesome/IconsFontAwesome5.h"
|
||||
#include "../FontAwesome/IconsFontAwesome5Brands.h"
|
||||
#include "../Logger/Logger.h"
|
||||
|
||||
#include "SaveTool.h"
|
||||
|
||||
void SaveTool::initEvent(SDL_Event& event) {
|
||||
_initThread.join();
|
||||
|
||||
switch(event.user.code) {
|
||||
case InitSuccess:
|
||||
_uiState = UiState::ProfileManager;
|
||||
ImGui::CloseCurrentPopup();
|
||||
break;
|
||||
case ProfileManagerFailure:
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error ",
|
||||
_profileManager->lastError().data(), window());
|
||||
exit(EXIT_FAILURE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SaveTool::initialiseConfiguration() {
|
||||
LOG_INFO("Reading configuration file.");
|
||||
|
||||
if(_conf.hasValue("cheat_mode"_s)) {
|
||||
_cheatMode = _conf.value<bool>("cheat_mode"_s);
|
||||
}
|
||||
else {
|
||||
_conf.setValue("cheat_mode"_s, _cheatMode);
|
||||
}
|
||||
|
||||
if(_conf.hasValue("advanced_mode"_s)) {
|
||||
_advancedMode = _conf.value<bool>("advanced_mode"_s);
|
||||
}
|
||||
else {
|
||||
_conf.setValue("advanced_mode"_s, _advancedMode);
|
||||
}
|
||||
|
||||
if(_conf.hasValue("startup_update_check"_s)) {
|
||||
_checkUpdatesOnStartup = _conf.value<bool>("startup_update_check"_s);
|
||||
}
|
||||
else {
|
||||
_conf.setValue("startup_update_check"_s, _checkUpdatesOnStartup);
|
||||
}
|
||||
|
||||
if(_conf.hasValue("skip_disclaimer"_s)) {
|
||||
_skipDisclaimer = _conf.value<bool>("skip_disclaimer"_s);
|
||||
}
|
||||
else {
|
||||
_conf.setValue("skip_disclaimer"_s, _skipDisclaimer);
|
||||
}
|
||||
|
||||
if(_conf.hasValue("swap_interval"_s)) {
|
||||
_swapInterval = _conf.value<int>("swap_interval"_s);
|
||||
}
|
||||
else {
|
||||
_conf.setValue("swap_interval"_s, 1);
|
||||
}
|
||||
|
||||
if(_conf.hasValue("fps_cap"_s)) {
|
||||
_fpsCap = _conf.value<float>("fps_cap");
|
||||
}
|
||||
else {
|
||||
_conf.setValue("fps_cap", 60.0f);
|
||||
}
|
||||
|
||||
if(_conf.hasValue("frame_limit"_s)) {
|
||||
std::string frame_limit = _conf.value("frame_limit"_s);
|
||||
if(frame_limit == "half_vsync"_s) {
|
||||
_swapInterval = 2;
|
||||
}
|
||||
_conf.removeValue("frame_limit"_s);
|
||||
}
|
||||
|
||||
setSwapInterval(_swapInterval);
|
||||
if(_swapInterval == 0) {
|
||||
setMinimalLoopPeriod(0);
|
||||
}
|
||||
|
||||
_conf.save();
|
||||
}
|
||||
|
||||
void SaveTool::initialiseGui() {
|
||||
LOG_INFO("Initialising Dear ImGui.");
|
||||
|
||||
ImGui::CreateContext();
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
const auto size = Vector2{windowSize()}/dpiScaling();
|
||||
|
||||
auto reg_font = _rs.getRaw("SourceSansPro-Regular.ttf"_s);
|
||||
ImFontConfig font_config;
|
||||
font_config.FontDataOwnedByAtlas = false;
|
||||
std::strcpy(font_config.Name, "Source Sans Pro");
|
||||
io.Fonts->AddFontFromMemoryTTF(const_cast<char*>(reg_font.data()), int(reg_font.size()),
|
||||
20.0f * Float(framebufferSize().x()) / size.x(), &font_config);
|
||||
|
||||
auto icon_font = _rs.getRaw(FONT_ICON_FILE_NAME_FAS);
|
||||
static const ImWchar icon_range[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };
|
||||
ImFontConfig icon_config;
|
||||
icon_config.FontDataOwnedByAtlas = false;
|
||||
icon_config.MergeMode = true;
|
||||
icon_config.PixelSnapH = true;
|
||||
icon_config.OversampleH = icon_config.OversampleV = 1;
|
||||
icon_config.GlyphMinAdvanceX = 18.0f;
|
||||
io.Fonts->AddFontFromMemoryTTF(const_cast<char*>(icon_font.data()), int(icon_font.size()),
|
||||
16.0f * Float(framebufferSize().x()) / size.x(), &icon_config, icon_range);
|
||||
|
||||
auto brand_font = _rs.getRaw(FONT_ICON_FILE_NAME_FAB);
|
||||
static const ImWchar brand_range[] = { ICON_MIN_FAB, ICON_MAX_FAB, 0 };
|
||||
io.Fonts->AddFontFromMemoryTTF(const_cast<char*>(brand_font.data()), int(brand_font.size()),
|
||||
16.0f * Float(framebufferSize().x()) / size.x(), &icon_config, brand_range);
|
||||
|
||||
auto mono_font = _rs.getRaw("SourceCodePro-Regular.ttf"_s);
|
||||
ImVector<ImWchar> range;
|
||||
ImFontGlyphRangesBuilder builder;
|
||||
builder.AddRanges(io.Fonts->GetGlyphRangesDefault());
|
||||
builder.AddChar(u'š'); // This allows displaying Vladimír Vondruš' name in Corrade's and Magnum's licences.
|
||||
builder.BuildRanges(&range);
|
||||
io.Fonts->AddFontFromMemoryTTF(const_cast<char*>(mono_font.data()), int(mono_font.size()),
|
||||
18.0f * Float(framebufferSize().x()) / size.x(), &font_config, range.Data);
|
||||
|
||||
_imgui = ImGuiIntegration::Context(*ImGui::GetCurrentContext(), windowSize());
|
||||
|
||||
io.IniFilename = nullptr;
|
||||
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
|
||||
style.WindowTitleAlign = {0.5f, 0.5f};
|
||||
style.FrameRounding = 3.2f;
|
||||
style.Colors[ImGuiCol_WindowBg] = ImColor(0xff1f1f1f);
|
||||
}
|
||||
|
||||
void SaveTool::initialiseManager() {
|
||||
LOG_INFO("Initialising the profile manager.");
|
||||
|
||||
SDL_Event event;
|
||||
SDL_zero(event);
|
||||
event.type = _initEventId;
|
||||
|
||||
_profileManager.emplace(_saveDir, _backupsDir);
|
||||
if(!_profileManager->ready()) {
|
||||
event.user.code = ProfileManagerFailure;
|
||||
SDL_PushEvent(&event);
|
||||
return;
|
||||
}
|
||||
|
||||
event.user.code = InitSuccess;
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
|
||||
auto SaveTool::initialiseToolDirectories() -> bool {
|
||||
LOG_INFO("Initialising Save Tool directories.");
|
||||
|
||||
_backupsDir = Utility::Path::join(Utility::Path::split(*Utility::Path::executableLocation()).first(), "backups");
|
||||
_stagingDir = Utility::Path::join(Utility::Path::split(*Utility::Path::executableLocation()).first(), "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::Path::exists(_backupsDir)) {
|
||||
LOG_WARNING("Backups directory not found, creating...");
|
||||
if(!Utility::Path::make(_backupsDir)) {
|
||||
LOG_ERROR(_lastError = "Couldn't create the backups directory.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!Utility::Path::exists(_stagingDir)) {
|
||||
LOG_WARNING("Staging directory not found, creating...");
|
||||
if(!Utility::Path::make(_stagingDir)) {
|
||||
LOG_ERROR(_lastError = "Couldn't create the staging directory.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//if(!Utility::Directory::exists(_armouryDir)) {
|
||||
// Utility::Debug{} << "Armoury directory not found, creating...";
|
||||
// if(!Utility::Path::make(_armouryDir)) {
|
||||
// Utility::Error{} << (_lastError = "Couldn't create the armoury directory.");
|
||||
// return false;
|
||||
// }
|
||||
//}
|
||||
|
||||
//if(!Utility::Directory::exists(_armoursDir)) {
|
||||
// Utility::Debug{} << "Armours directory not found, creating...";
|
||||
// if(!Utility::Path::make(_armoursDir)) {
|
||||
// Utility::Error{} << (_lastError = "Couldn't create the armours directory.");
|
||||
// return false;
|
||||
// }
|
||||
//}
|
||||
|
||||
//if(!Utility::Directory::exists(_weaponsDir)) {
|
||||
// Utility::Debug{} << "Weapons directory not found, creating...";
|
||||
// if(!Utility::Path::make(_weaponsDir)) {
|
||||
// Utility::Error{} << (_lastError = "Couldn't create the weapons directory.");
|
||||
// return false;
|
||||
// }
|
||||
//}
|
||||
|
||||
//if(!Utility::Directory::exists(_stylesDir)) {
|
||||
// Utility::Debug{} << "Styles directory not found, creating...";
|
||||
// if(!Utility::Path::make(_stylesDir)) {
|
||||
// Utility::Error{} << (_lastError = "Couldn't create the styles directory.");
|
||||
// return false;
|
||||
// }
|
||||
//}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
auto SaveTool::findGameDataDirectory() -> bool {
|
||||
LOG_INFO("Searching for the game's save directory.");
|
||||
|
||||
wchar_t* localappdata_path = nullptr;
|
||||
Containers::ScopeGuard guard{localappdata_path, CoTaskMemFree};
|
||||
if(SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_NO_APPCONTAINER_REDIRECTION, nullptr, &localappdata_path) != S_OK)
|
||||
{
|
||||
_lastError = Utility::format("SHGetKnownFolderPath() failed with error code {}.", GetLastError());
|
||||
LOG_ERROR(_lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
_gameDataDir = Utility::Path::join(Utility::Path::fromNativeSeparators(Utility::Unicode::narrow(localappdata_path)), "MASS_Builder"_s);
|
||||
|
||||
if(!Utility::Path::exists(_gameDataDir)) {
|
||||
LOG_ERROR(_lastError = _gameDataDir + " wasn't found. Make sure to play the game at least once."_s);
|
||||
return false;
|
||||
}
|
||||
|
||||
_configDir = Utility::Path::join(_gameDataDir, "Saved/Config/WindowsNoEditor"_s);
|
||||
_saveDir = Utility::Path::join(_gameDataDir, "Saved/SaveGames"_s);
|
||||
_screenshotsDir = Utility::Path::join(_gameDataDir, "Saved/Screenshots/WindowsNoEditor"_s);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SaveTool::initialiseMassManager() {
|
||||
LOG_INFO("Initialising the M.A.S.S. manager.");
|
||||
_massManager.emplace(_saveDir, _currentProfile->account(), _currentProfile->isDemo(), _stagingDir);
|
||||
}
|
||||
|
||||
void SaveTool::initialiseFileWatcher() {
|
||||
LOG_INFO("Initialising the file watcher.");
|
||||
_fileWatcher.emplace();
|
||||
_watchIDs[SaveDir] = _fileWatcher->addWatch(_saveDir, this, false);
|
||||
_watchIDs[StagingDir] = _fileWatcher->addWatch(_stagingDir, this, false);
|
||||
_fileWatcher->watch();
|
||||
}
|
|
@ -14,18 +14,21 @@
|
|||
// 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 "SaveTool.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <Corrade/Utility/Format.h>
|
||||
#include <Corrade/Utility/Path.h>
|
||||
|
||||
#include <SDL_messagebox.h>
|
||||
#include <Corrade/Containers/Reference.h>
|
||||
#include <Corrade/Utility/Directory.h>
|
||||
#include <Corrade/Utility/FormatStl.h>
|
||||
#include <Corrade/Utility/String.h>
|
||||
|
||||
#include "../FontAwesome/IconsFontAwesome5.h"
|
||||
|
||||
#include "../Maps/LastMissionId.h"
|
||||
#include "../Maps/StoryProgress.h"
|
||||
|
||||
#include "SaveTool.h"
|
||||
static const std::string empty_str;
|
||||
|
||||
void SaveTool::drawManager() {
|
||||
ImGui::SetNextWindowPos({0.0f, ImGui::GetItemRectSize().y}, ImGuiCond_Always);
|
||||
|
@ -40,8 +43,8 @@ void SaveTool::drawManager() {
|
|||
}
|
||||
|
||||
drawAlignedText("Current profile: %s (%s)",
|
||||
_currentProfile->companyName().data(),
|
||||
_currentProfile->isDemo() ? "demo" : "full game");
|
||||
_currentProfile->companyName().c_str(),
|
||||
_currentProfile->type() == ProfileType::Demo ? "demo" : "full game");
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Button(ICON_FA_ARROW_LEFT " Back to profile manager")) {
|
||||
_currentProfile = nullptr;
|
||||
|
@ -51,7 +54,7 @@ void SaveTool::drawManager() {
|
|||
}
|
||||
|
||||
if(ImGui::BeginChild("##ProfileInfo",
|
||||
{ImGui::GetContentRegionAvail().x * 0.60f, 0.0f},
|
||||
{ImGui::GetContentRegionAvailWidth() * 0.60f, 0.0f},
|
||||
true, ImGuiWindowFlags_MenuBar))
|
||||
{
|
||||
if(ImGui::BeginMenuBar()) {
|
||||
|
@ -145,11 +148,12 @@ auto SaveTool::drawRenamePopup(Containers::ArrayView<char> name_view) -> bool {
|
|||
callback, nullptr);
|
||||
ImGui::SameLine();
|
||||
GameState game_state = _gameState;
|
||||
if(game_state != GameState::NotRunning ||
|
||||
!(len >= 6 && len <= 32) ||
|
||||
if((!_unsafeMode && game_state != GameState::NotRunning) ||
|
||||
!(len >= 6 && len <= 32) ||
|
||||
!(name_view[0] != ' ' && name_view[len - 1] != ' '))
|
||||
{
|
||||
ImGui::BeginDisabled();
|
||||
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.5f);
|
||||
}
|
||||
|
||||
if(ImGui::Button("Apply")) {
|
||||
|
@ -157,11 +161,12 @@ auto SaveTool::drawRenamePopup(Containers::ArrayView<char> name_view) -> bool {
|
|||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
if(game_state != GameState::NotRunning ||
|
||||
!(len >= 6 && len <= 32) ||
|
||||
if((!_unsafeMode && game_state != GameState::NotRunning) ||
|
||||
!(len >= 6 && len <= 32) ||
|
||||
!(name_view[0] != ' ' && name_view[len - 1] != ' '))
|
||||
{
|
||||
ImGui::EndDisabled();
|
||||
ImGui::PopItemFlag();
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
|
@ -183,10 +188,10 @@ void SaveTool::drawGeneralInfo() {
|
|||
ImGui::TextUnformatted("Story progress:");
|
||||
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.x / 4.0f);
|
||||
if(!it->after) {
|
||||
ImGui::TextWrapped("%s - %s", it->chapter.data(), it->point.data());
|
||||
ImGui::TextWrapped("%s - %s", it->chapter, it->point);
|
||||
}
|
||||
else {
|
||||
ImGui::TextWrapped("%s - %s - %s", it->chapter.data(), it->after.data(), it->point.data());
|
||||
ImGui::TextWrapped("%s - %s - %s", it->chapter, it->after, it->point);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -194,7 +199,7 @@ void SaveTool::drawGeneralInfo() {
|
|||
}
|
||||
|
||||
if(mission_id_map.find(_currentProfile->lastMissionId()) != mission_id_map.cend()) {
|
||||
ImGui::Text("Last mission: %s", mission_id_map.at(_currentProfile->lastMissionId()).data());
|
||||
ImGui::Text("Last mission: %s", mission_id_map.at(_currentProfile->lastMissionId()));
|
||||
}
|
||||
else if(_currentProfile->lastMissionId() == -1) {
|
||||
ImGui::TextUnformatted("Last mission: none");
|
||||
|
@ -203,7 +208,7 @@ void SaveTool::drawGeneralInfo() {
|
|||
ImGui::Text("Last mission: 0x%x", _currentProfile->lastMissionId());
|
||||
}
|
||||
drawTooltip("This is the last mission selected in the mission selection screen, not the last mission played.",
|
||||
float(windowSize().x()) * 0.35f);
|
||||
windowSize().x() * 0.35f);
|
||||
|
||||
const Float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
|
||||
ImGui::Dummy({ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y - footer_height_to_reserve});
|
||||
|
@ -215,7 +220,7 @@ void SaveTool::drawGeneralInfo() {
|
|||
for(auto& c : name_buf) {
|
||||
c = '\0';
|
||||
}
|
||||
std::strncpy(name_buf.data(), _currentProfile->companyName().data(), 32);
|
||||
std::strncpy(name_buf.data(), _currentProfile->companyName().c_str(), 32);
|
||||
ImGui::OpenPopup("name_edit");
|
||||
}
|
||||
if(drawRenamePopup(name_buf)) {
|
||||
|
@ -248,21 +253,21 @@ void SaveTool::drawGeneralInfo() {
|
|||
}
|
||||
drawTooltip("Story progress directly affects unlocked levels.");
|
||||
if(ImGui::BeginPopup("StoryProgressMenu")) {
|
||||
if(_gameState != GameState::NotRunning) {
|
||||
if(!_unsafeMode && _gameState != GameState::NotRunning) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
for(const auto& sp : story_progress) {
|
||||
if(ImGui::BeginMenu(sp.chapter.data())) {
|
||||
if(ImGui::BeginMenu(sp.chapter)) {
|
||||
if(!sp.after) {
|
||||
if(ImGui::MenuItem(sp.point.data())) {
|
||||
if(ImGui::MenuItem(sp.point)) {
|
||||
if(!_currentProfile->setStoryProgress(sp.id)) {
|
||||
_queue.addToast(Toast::Type::Error, _currentProfile->lastError());
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(ImGui::BeginMenu(sp.after.data())) {
|
||||
if(ImGui::MenuItem(sp.point.data())) {
|
||||
if(ImGui::BeginMenu(sp.after)) {
|
||||
if(ImGui::MenuItem(sp.point)) {
|
||||
if(!_currentProfile->setStoryProgress(sp.id)) {
|
||||
_queue.addToast(Toast::Type::Error, _currentProfile->lastError());
|
||||
}
|
||||
|
@ -309,9 +314,7 @@ void SaveTool::drawResearchInventory() {
|
|||
drawMaterialRow("Asterite", 5,
|
||||
[this]{ return _currentProfile->asterite(); },
|
||||
[this](Int amount){ return _currentProfile->setAsterite(amount); });
|
||||
drawMaterialRow("Hallite fragma", 6,
|
||||
[this]{ return _currentProfile->halliteFragma(); },
|
||||
[this](Int amount){ return _currentProfile->setHalliteFragma(amount); });
|
||||
drawUnavailableMaterialRow("Hallite fragma", 6);
|
||||
drawUnavailableMaterialRow("Unnoctinium", 7);
|
||||
|
||||
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
||||
|
@ -333,9 +336,7 @@ void SaveTool::drawResearchInventory() {
|
|||
drawMaterialRow("Synthesized N", 5,
|
||||
[this]{ return _currentProfile->synthesisedN(); },
|
||||
[this](Int amount){ return _currentProfile->setSynthesisedN(amount); });
|
||||
drawMaterialRow("Nanoc", 6,
|
||||
[this]{ return _currentProfile->nanoc(); },
|
||||
[this](Int amount){ return _currentProfile->setNanoc(amount); });
|
||||
drawUnavailableMaterialRow("Nanoc", 6);
|
||||
drawUnavailableMaterialRow("Abyssillite", 7);
|
||||
|
||||
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
||||
|
@ -357,9 +358,7 @@ void SaveTool::drawResearchInventory() {
|
|||
drawMaterialRow("Alterene", 5,
|
||||
[this]{ return _currentProfile->alterene(); },
|
||||
[this](Int amount){ return _currentProfile->setAlterene(amount); });
|
||||
drawMaterialRow("Cosmium", 6,
|
||||
[this]{ return _currentProfile->cosmium(); },
|
||||
[this](Int amount){ return _currentProfile->setCosmium(amount); });
|
||||
drawUnavailableMaterialRow("Cosmium", 6);
|
||||
drawUnavailableMaterialRow("Purified quarkium", 7);
|
||||
|
||||
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
||||
|
@ -381,9 +380,7 @@ void SaveTool::drawResearchInventory() {
|
|||
drawMaterialRow("Carbonized skin", 5,
|
||||
[this]{ return _currentProfile->carbonisedSkin(); },
|
||||
[this](Int amount){ return _currentProfile->setCarbonisedSkin(amount); });
|
||||
drawMaterialRow("Isolated void particle", 6,
|
||||
[this]{ return _currentProfile->isolatedVoidParticle(); },
|
||||
[this](Int amount){ return _currentProfile->setIsolatedVoidParticle(amount); });
|
||||
drawUnavailableMaterialRow("Isolated void particle", 6);
|
||||
drawUnavailableMaterialRow("Weaponised physiology", 7);
|
||||
|
||||
ImGui::EndTable();
|
||||
|
@ -391,7 +388,7 @@ void SaveTool::drawResearchInventory() {
|
|||
}
|
||||
|
||||
template<typename Getter, typename Setter>
|
||||
void SaveTool::drawMaterialRow(Containers::StringView name, Int tier, Getter getter, Setter setter) {
|
||||
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.");
|
||||
|
||||
|
@ -399,19 +396,18 @@ void SaveTool::drawMaterialRow(Containers::StringView name, Int tier, Getter get
|
|||
ImGui::TableSetColumnIndex(0);
|
||||
ImGui::Text("T%i", tier);
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
ImGui::TextUnformatted(name.data());
|
||||
ImGui::TextUnformatted(name);
|
||||
ImGui::TableSetColumnIndex(2);
|
||||
if(getter() != -1) {
|
||||
ImGui::Text("%i", getter());
|
||||
if(_cheatMode) {
|
||||
ImGui::TableSetColumnIndex(3);
|
||||
ImGui::PushID(name.data());
|
||||
ImGui::PushID(name);
|
||||
static Int var = 0;
|
||||
if(drawUnsafeWidget(ImGui::SmallButton, ICON_FA_EDIT)) {
|
||||
(var) = getter();
|
||||
ImGui::OpenPopup("int_edit");
|
||||
}
|
||||
drawTooltip("Edit");
|
||||
if(drawIntEditPopup(&(var), 9999)) {
|
||||
if(!setter(var)) {
|
||||
_queue.addToast(Toast::Type::Error, _currentProfile->lastError());
|
||||
|
@ -425,12 +421,12 @@ void SaveTool::drawMaterialRow(Containers::StringView name, Int tier, Getter get
|
|||
}
|
||||
}
|
||||
|
||||
void SaveTool::drawUnavailableMaterialRow(Containers::StringView name, Int tier) {
|
||||
void SaveTool::drawUnavailableMaterialRow(const char* name, Int tier) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
ImGui::Text("T%i", tier);
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
ImGui::TextUnformatted(name.data());
|
||||
ImGui::TextUnformatted(name);
|
||||
ImGui::TableSetColumnIndex(2);
|
||||
ImGui::TextDisabled("Unavailable as of game version " SUPPORTED_GAME_VERSION);
|
||||
}
|
||||
|
@ -468,7 +464,7 @@ void SaveTool::drawMassManager() {
|
|||
static int drag_drop_index = 0;
|
||||
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
ImGui::Selectable(Utility::format("{:.2d}", i + 1).data(),
|
||||
ImGui::Selectable(Utility::formatString("{:.2d}", i + 1).c_str(),
|
||||
false, ImGuiSelectableFlags_SpanAllColumns|ImGuiSelectableFlags_AllowItemOverlap);
|
||||
if(_massManager->hangar(i).state() == Mass::State::Valid &&
|
||||
ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceNoHoldToOpenOthers))
|
||||
|
@ -476,20 +472,20 @@ void SaveTool::drawMassManager() {
|
|||
drag_drop_index = i;
|
||||
ImGui::SetDragDropPayload("Mass", &drag_drop_index, sizeof(int));
|
||||
|
||||
ImGui::Text("%s - Hangar %.2d", _massManager->hangar(i).name().data(), i + 1);
|
||||
ImGui::Text("%s - Hangar %.2d", (*_massManager->hangar(i).name()).c_str(), i + 1);
|
||||
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
if(_gameState == GameState::NotRunning && ImGui::BeginDragDropTarget()) {
|
||||
if((_unsafeMode || _gameState == GameState::NotRunning) && ImGui::BeginDragDropTarget()) {
|
||||
if(const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("StagedMass")) {
|
||||
if(payload->DataSize != sizeof(Containers::String)) {
|
||||
if(payload->DataSize != sizeof(std::string)) {
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal error",
|
||||
"payload->DataSize != sizeof(Containers::String) in SaveTool::drawMassManager()",
|
||||
"payload->DataSize != sizeof(std::string) in SaveTool::drawMassManager()",
|
||||
window());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
Containers::StringView file = *static_cast<Containers::String*>(payload->Data);
|
||||
std::string file = *(static_cast<std::string*>(payload->Data));
|
||||
|
||||
if(!_massManager->importMass(file, i)) {
|
||||
_queue.addToast(Toast::Type::Error, _massManager->lastError());
|
||||
|
@ -522,7 +518,7 @@ void SaveTool::drawMassManager() {
|
|||
ImGui::TextDisabled("<invalid>");
|
||||
break;
|
||||
case Mass::State::Valid:
|
||||
ImGui::TextUnformatted(_massManager->hangar(i).name().data());
|
||||
ImGui::TextUnformatted((*_massManager->hangar(i).name()).c_str());
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -540,19 +536,17 @@ void SaveTool::drawMassManager() {
|
|||
_currentMass = &_massManager->hangar(i);
|
||||
_uiState = UiState::MassViewer;
|
||||
}
|
||||
drawTooltip("Open in M.A.S.S. editor");
|
||||
ImGui::SameLine(0.0f, 2.0f);
|
||||
}
|
||||
else{
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.0f);
|
||||
ImGui::SmallButton(ICON_FA_SEARCH);
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
ImGui::SameLine(0.0f, 2.0f);
|
||||
if(drawUnsafeWidget(ImGui::SmallButton, ICON_FA_TRASH_ALT)) {
|
||||
mass_to_delete = i;
|
||||
ImGui::OpenPopup(mass_deletion_popup_ID);
|
||||
}
|
||||
drawTooltip("Delete");
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
|
@ -563,7 +557,7 @@ void SaveTool::drawMassManager() {
|
|||
drawDeleteMassPopup(mass_to_delete);
|
||||
|
||||
static ImGuiID staged_mass_deletion_popup_ID = drawDeleteStagedMassPopup("");
|
||||
static Containers::StringView staged_mass_to_delete;
|
||||
static Containers::Reference<const std::string> staged_mass_to_delete{empty_str};
|
||||
|
||||
if(ImGui::BeginTable("##StagingArea", 2,
|
||||
ImGuiTableFlags_ScrollY|ImGuiTableFlags_BordersOuter|ImGuiTableFlags_RowBg))
|
||||
|
@ -579,32 +573,31 @@ void SaveTool::drawMassManager() {
|
|||
ImGui::TextUnformatted("Staging area");
|
||||
ImGui::SameLine();
|
||||
if(ImGui::SmallButton(ICON_FA_FOLDER_OPEN " Open staging folder")) {
|
||||
openUri(Utility::Path::toNativeSeparators(_stagingDir));
|
||||
openUri(Utility::Directory::toNativeSeparators(_stagingDir));
|
||||
}
|
||||
|
||||
for(const auto& pair : _massManager->stagedMasses()) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
Containers::String staged_formatted = Utility::format("{} ({})", pair.second, pair.first);
|
||||
ImGui::Selectable(staged_formatted.data());
|
||||
if((ImGui::CalcTextSize(staged_formatted.data()).x + ImGui::GetStyle().FramePadding.x) > ImGui::GetContentRegionAvail().x) {
|
||||
drawTooltip(staged_formatted.data());
|
||||
std::string staged_formatted = Utility::formatString("{} ({})", pair.second, pair.first);
|
||||
ImGui::Selectable(staged_formatted.c_str());
|
||||
if((ImGui::CalcTextSize(staged_formatted.c_str()).x + ImGui::GetStyle().FramePadding.x) > ImGui::GetContentRegionAvailWidth()) {
|
||||
drawTooltip(staged_formatted.c_str());
|
||||
}
|
||||
if(ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceNoHoldToOpenOthers)) {
|
||||
ImGui::SetDragDropPayload("StagedMass", &(pair.first), sizeof(Containers::String));
|
||||
ImGui::SetDragDropPayload("StagedMass", &(pair.first), sizeof(std::string));
|
||||
|
||||
ImGui::Text("%s - Staged", pair.second.data());
|
||||
ImGui::Text("%s - Staged", pair.second.c_str());
|
||||
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
ImGui::PushID(pair.first.data());
|
||||
ImGui::PushID(pair.first.c_str());
|
||||
if(ImGui::SmallButton(ICON_FA_TRASH_ALT)) {
|
||||
staged_mass_to_delete = pair.first;
|
||||
staged_mass_to_delete = Containers::Reference<const std::string>{pair.first};
|
||||
ImGui::OpenPopup(staged_mass_deletion_popup_ID);
|
||||
}
|
||||
drawTooltip("Delete");
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
|
@ -629,7 +622,7 @@ void SaveTool::drawMassManager() {
|
|||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
drawDeleteStagedMassPopup(staged_mass_to_delete);
|
||||
drawDeleteStagedMassPopup(staged_mass_to_delete.get());
|
||||
}
|
||||
|
||||
auto SaveTool::drawDeleteMassPopup(int mass_index) -> ImGuiID {
|
||||
|
@ -651,14 +644,14 @@ auto SaveTool::drawDeleteMassPopup(int mass_index) -> ImGuiID {
|
|||
return 0;
|
||||
}
|
||||
|
||||
ImGui::PushTextWrapPos(float(windowSize().x()) * 0.40f);
|
||||
ImGui::PushTextWrapPos(windowSize().x() * 0.40f);
|
||||
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.",
|
||||
mass_index + 1);
|
||||
}
|
||||
else {
|
||||
ImGui::Text("Are you sure you want to delete the M.A.S.S. named %s in hangar %.2i ? This operation is irreversible.",
|
||||
_massManager->hangar(mass_index).name().data(), mass_index + 1);
|
||||
(*_massManager->hangar(mass_index).name()).c_str(), mass_index + 1);
|
||||
}
|
||||
ImGui::PopTextWrapPos();
|
||||
|
||||
|
@ -688,16 +681,16 @@ auto SaveTool::drawDeleteMassPopup(int mass_index) -> ImGuiID {
|
|||
return 0;
|
||||
}
|
||||
|
||||
auto SaveTool::drawDeleteStagedMassPopup(Containers::StringView filename) -> ImGuiID {
|
||||
auto SaveTool::drawDeleteStagedMassPopup(const std::string& filename) -> ImGuiID {
|
||||
if(!ImGui::BeginPopupModal("Confirmation##DeleteStagedMassConfirmation", nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoMove))
|
||||
{
|
||||
return ImGui::GetID("Confirmation##DeleteStagedMassConfirmation");
|
||||
}
|
||||
|
||||
ImGui::PushTextWrapPos(float(windowSize().x()) * 0.40f);
|
||||
ImGui::PushTextWrapPos(windowSize().x() * 0.40f);
|
||||
ImGui::Text("Are you sure you want to delete the staged M.A.S.S. named %s ? This operation is irreversible.",
|
||||
_massManager->stagedMasses().at(filename).data());
|
||||
_massManager->stagedMasses().at(filename).c_str());
|
||||
ImGui::PopTextWrapPos();
|
||||
|
||||
if(ImGui::BeginTable("##DeleteStagedMassLayout", 2)) {
|
||||
|
|
|
@ -15,15 +15,16 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include <Corrade/Containers/ScopeGuard.h>
|
||||
#include <Corrade/Utility/Format.h>
|
||||
|
||||
#include <Magnum/ImGuiIntegration/Integration.h>
|
||||
|
||||
#include "../FontAwesome/IconsFontAwesome5.h"
|
||||
#include "../Maps/Accessories.h"
|
||||
|
||||
#define STYLENAMES_DEFINITION
|
||||
#include "../Maps/StyleNames.h"
|
||||
|
||||
#include "../FontAwesome/IconsFontAwesome5.h"
|
||||
|
||||
#include "SaveTool.h"
|
||||
|
||||
void SaveTool::drawMassViewer() {
|
||||
|
@ -60,8 +61,8 @@ void SaveTool::drawMassViewer() {
|
|||
ImGui::TableNextRow();
|
||||
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
ImGui::Text("M.A.S.S.: %s", _currentMass->name().data());
|
||||
drawTooltip(_currentMass->filename());
|
||||
ImGui::Text("M.A.S.S.: %s", (*_currentMass->name()).c_str());
|
||||
drawTooltip(_currentMass->filename().c_str());
|
||||
|
||||
ImGui::TableSetColumnIndex(2);
|
||||
if(_currentMass->dirty()) {
|
||||
|
@ -86,11 +87,10 @@ void SaveTool::drawMassViewer() {
|
|||
_eyeFlareDirty = false;
|
||||
_selectedArmourDecals = Containers::StaticArray<38, Int>{ValueInit};
|
||||
_selectedArmourAccessories = Containers::StaticArray<38, Int>{ValueInit};
|
||||
_selectedBLPlacement = 0;
|
||||
_selectedWeaponPart = 0;
|
||||
_selectedWeaponDecal = 0;
|
||||
_selectedWeaponAccessory = 0;
|
||||
}
|
||||
};
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ void SaveTool::drawMassViewer() {
|
|||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if(ImGui::BeginTabItem("Armour")) {
|
||||
if(ImGui::BeginTabItem("Armour parts")) {
|
||||
drawArmour();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ void SaveTool::drawMassViewer() {
|
|||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if(ImGui::BeginTabItem("Weapons")) {
|
||||
if(ImGui::BeginTabItem("Weapons (WIP)")) {
|
||||
drawWeapons();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
@ -137,12 +137,10 @@ void SaveTool::drawMassViewer() {
|
|||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
#ifdef SAVETOOL_DEBUG_BUILD
|
||||
if(ImGui::BeginTabItem("Tuning (WIP)")) {
|
||||
drawTuning();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
#endif
|
||||
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
|
@ -166,7 +164,7 @@ void SaveTool::drawGlobalStyles() {
|
|||
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(int(i));
|
||||
ImGui::PushID(i);
|
||||
DCSResult result;
|
||||
result = drawCustomStyle(_currentMass->globalStyles()[i]);
|
||||
switch(result) {
|
||||
|
@ -174,9 +172,7 @@ void SaveTool::drawGlobalStyles() {
|
|||
_currentMass->getGlobalStyles();
|
||||
break;
|
||||
case DCS_Save:
|
||||
_modifiedBySaveTool = true;
|
||||
if(!_currentMass->writeGlobalStyle(i)) {
|
||||
_modifiedBySaveTool = false;
|
||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||
}
|
||||
break;
|
||||
|
@ -302,14 +298,14 @@ auto SaveTool::drawCustomStyle(CustomStyle& style) -> DCSResult {
|
|||
}
|
||||
|
||||
if(ImGui::BeginMenuBar()) {
|
||||
ImGui::TextUnformatted(style.name.data());
|
||||
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.data(), 32);
|
||||
std::strncpy(name_buf.data(), style.name.c_str(), 32);
|
||||
ImGui::OpenPopup("name_edit");
|
||||
}
|
||||
if(drawRenamePopup(name_buf)) {
|
||||
|
@ -393,12 +389,9 @@ auto SaveTool::drawCustomStyle(CustomStyle& style) -> DCSResult {
|
|||
void SaveTool::drawDecalEditor(Decal& decal) {
|
||||
ImGui::Text("ID: %i", decal.id);
|
||||
|
||||
if(ImGui::BeginTable("##DecalTable", _advancedMode ? 2 : 1, ImGuiTableFlags_BordersInnerV)) {
|
||||
if(ImGui::BeginTable("##DecalTable", 2, ImGuiTableFlags_BordersInnerV)) {
|
||||
ImGui::TableSetupColumn("##Normal", ImGuiTableColumnFlags_WidthStretch);
|
||||
|
||||
if(_advancedMode) {
|
||||
ImGui::TableSetupColumn("##Advanced", ImGuiTableColumnFlags_WidthStretch);
|
||||
}
|
||||
ImGui::TableSetupColumn("##Advanced", ImGuiTableColumnFlags_WidthStretch);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
|
||||
|
@ -442,53 +435,52 @@ void SaveTool::drawDecalEditor(Decal& decal) {
|
|||
ImGui::Checkbox("##Wrap", &decal.wrap);
|
||||
ImGui::EndGroup();
|
||||
|
||||
if(_advancedMode) {
|
||||
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::TableNextColumn();
|
||||
|
||||
ImGui::BeginGroup();
|
||||
drawAlignedText("Position:");
|
||||
drawAlignedText("U axis:");
|
||||
drawAlignedText("V axis:");
|
||||
ImGui::EndGroup();
|
||||
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::SameLine();
|
||||
ImGui::BeginGroup();
|
||||
drawAlignedText("Position:");
|
||||
drawAlignedText("U axis:");
|
||||
drawAlignedText("V axis:");
|
||||
ImGui::EndGroup();
|
||||
|
||||
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::SameLine();
|
||||
|
||||
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::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("##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::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();
|
||||
}
|
||||
|
@ -499,149 +491,23 @@ void SaveTool::drawAccessoryEditor(Accessory& accessory, Containers::ArrayView<C
|
|||
ImGui::TextUnformatted("Accessory: <none>");
|
||||
}
|
||||
else if(accessories.find(accessory.id) != accessories.cend()) {
|
||||
ImGui::Text("Accessory #%.4i - %s", accessory.id, accessories.at(accessory.id).name.data());
|
||||
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.");
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
static Int tab = 0;
|
||||
static Containers::Optional<AccessorySize> size = Containers::NullOpt;
|
||||
if(ImGui::SmallButton("Change")) {
|
||||
ImGui::OpenPopup("##AccessoryPopup");
|
||||
if(accessory.id >= 3000) {
|
||||
tab = 3;
|
||||
}
|
||||
else if(accessory.id >= 2000) {
|
||||
tab = 2;
|
||||
}
|
||||
else if(accessory.id >= 1000) {
|
||||
tab = 1;
|
||||
}
|
||||
else {
|
||||
tab = 0;
|
||||
}
|
||||
}
|
||||
if(ImGui::BeginPopup("##AccessoryPopup")) {
|
||||
static const char* size_labels[] = {
|
||||
"S",
|
||||
"M",
|
||||
"L",
|
||||
"XL"
|
||||
};
|
||||
static const Float selectable_width = 90.0f;
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, {0.5f, 0.0f});
|
||||
if(ImGui::Selectable("Primitives", tab == 0, ImGuiSelectableFlags_DontClosePopups, {selectable_width, 0.0f})) {
|
||||
tab = 0;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Selectable("Armours", tab == 1, ImGuiSelectableFlags_DontClosePopups, {selectable_width, 0.0f})) {
|
||||
tab = 1;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Selectable("Components", tab == 2, ImGuiSelectableFlags_DontClosePopups, {selectable_width, 0.0f})) {
|
||||
tab = 2;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Selectable("Connectors", tab == 3, ImGuiSelectableFlags_DontClosePopups, {selectable_width, 0.0f})) {
|
||||
tab = 3;
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, {0.5f, 0.0f});
|
||||
if(ImGui::Selectable("All", !size, ImGuiSelectableFlags_DontClosePopups, {70.0f, 0.0f})) {
|
||||
size = Containers::NullOpt;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Selectable("S", size && *size == AccessorySize::S, ImGuiSelectableFlags_DontClosePopups, {70.0f, 0.0f})) {
|
||||
if(!size) {
|
||||
size.emplace();
|
||||
}
|
||||
*size = AccessorySize::S;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Selectable("M", size && *size == AccessorySize::M, ImGuiSelectableFlags_DontClosePopups, {70.0f, 0.0f})) {
|
||||
if(!size) {
|
||||
size.emplace();
|
||||
}
|
||||
*size = AccessorySize::M;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Selectable("L", size && *size == AccessorySize::L, ImGuiSelectableFlags_DontClosePopups, {70.0f, 0.0f})) {
|
||||
if(!size) {
|
||||
size.emplace();
|
||||
}
|
||||
*size = AccessorySize::L;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Selectable("XL", size && *size == AccessorySize::XL, ImGuiSelectableFlags_DontClosePopups, {70.0f, 0.0f})) {
|
||||
if(!size) {
|
||||
size.emplace();
|
||||
}
|
||||
*size = AccessorySize::XL;
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if(ImGui::BeginListBox("##AccessoryListbox", {-1.0f, 0.0f})) {
|
||||
for(const auto& acc : accessories) {
|
||||
if(acc.first >= tab * 1000 && acc.first < ((tab + 1) * 1000) && (!size || *size == acc.second.size)) {
|
||||
if(ImGui::Selectable(Utility::format("#{:.4d} - {} ({})", acc.first, acc.second.name, size_labels[acc.second.size]).data(),
|
||||
acc.first == accessory.id))
|
||||
{
|
||||
accessory.id = acc.first;
|
||||
accessory.attachIndex = 0;
|
||||
}
|
||||
if(acc.first == accessory.id) {
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndListBox();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if(accessory.id > 0) {
|
||||
ImGui::SameLine();
|
||||
if(ImGui::SmallButton("Unequip")) {
|
||||
accessory.id = 0;
|
||||
accessory.attachIndex = -1;
|
||||
}
|
||||
}
|
||||
#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:");
|
||||
if(_advancedMode) {
|
||||
drawAlignedText("Base position:");
|
||||
}
|
||||
drawAlignedText("Base position:");
|
||||
drawAlignedText("Position offset:");
|
||||
if(_advancedMode) {
|
||||
drawAlignedText("Base rotation:");
|
||||
}
|
||||
drawAlignedText("Base rotation:");
|
||||
drawAlignedText("Rotation offset:");
|
||||
drawAlignedText("Scale:");
|
||||
ImGui::EndGroup();
|
||||
|
@ -650,9 +516,9 @@ void SaveTool::drawAccessoryEditor(Accessory& accessory, Containers::ArrayView<C
|
|||
|
||||
ImGui::BeginGroup();
|
||||
ImGui::PushMultiItemsWidths(2, ImGui::CalcItemWidth());
|
||||
if(ImGui::BeginCombo("##Style1", getStyleName(accessory.styles[0], style_view).data())) {
|
||||
if(ImGui::BeginCombo("##Style1", getStyleName(accessory.styles[0], style_view))) {
|
||||
for(const auto& style : style_names) {
|
||||
if(ImGui::Selectable(getStyleName(style.first, style_view).data(), accessory.styles[0] == style.first)) {
|
||||
if(ImGui::Selectable(getStyleName(style.first, style_view), accessory.styles[0] == style.first)) {
|
||||
accessory.styles[0] = style.first;
|
||||
}
|
||||
}
|
||||
|
@ -661,9 +527,9 @@ void SaveTool::drawAccessoryEditor(Accessory& accessory, Containers::ArrayView<C
|
|||
}
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||
if(ImGui::BeginCombo("##Style2", getStyleName(accessory.styles[1], style_view).data())) {
|
||||
if(ImGui::BeginCombo("##Style2", getStyleName(accessory.styles[1], style_view))) {
|
||||
for(const auto& style : style_names) {
|
||||
if(ImGui::Selectable(getStyleName(style.first, style_view).data(), accessory.styles[1] == style.first)) {
|
||||
if(ImGui::Selectable(getStyleName(style.first, style_view), accessory.styles[1] == style.first)) {
|
||||
accessory.styles[1] = style.first;
|
||||
}
|
||||
}
|
||||
|
@ -672,17 +538,15 @@ void SaveTool::drawAccessoryEditor(Accessory& accessory, Containers::ArrayView<C
|
|||
}
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
if(_advancedMode) {
|
||||
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::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");
|
||||
|
@ -696,17 +560,15 @@ void SaveTool::drawAccessoryEditor(Accessory& accessory, Containers::ArrayView<C
|
|||
ImGui::SameLine();
|
||||
drawHelpMarker("+/-500.0 = +/-250 in-game");
|
||||
|
||||
if(_advancedMode) {
|
||||
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::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");
|
||||
|
@ -732,12 +594,12 @@ void SaveTool::drawAccessoryEditor(Accessory& accessory, Containers::ArrayView<C
|
|||
ImGui::EndGroup();
|
||||
}
|
||||
|
||||
auto SaveTool::getStyleName(Int id, Containers::ArrayView<CustomStyle> view) -> Containers::StringView {
|
||||
auto SaveTool::getStyleName(Int id, Containers::ArrayView<CustomStyle> view) -> const char* {
|
||||
if(id >= 0 && id <= 15) {
|
||||
return view[id].name;
|
||||
return view[id].name.c_str();
|
||||
}
|
||||
else if(id >= 50 && id <= 65) {
|
||||
return _currentMass->globalStyles()[id - 50].name;
|
||||
return _currentMass->globalStyles()[id - 50].name.c_str();
|
||||
}
|
||||
else {
|
||||
return style_names.at(id);
|
||||
|
|
|
@ -28,22 +28,21 @@ void SaveTool::drawArmour() {
|
|||
|
||||
if(ImGui::Button(ICON_FA_UNDO_ALT " Reset all")) {
|
||||
_currentMass->getArmourParts();
|
||||
_currentMass->getBulletLauncherAttachments();
|
||||
}
|
||||
|
||||
if(!ImGui::BeginChild("##ArmourParts", {0.0f, 0.0f}, true)) {
|
||||
if(!ImGui::BeginChild("##ArmourParts")) {
|
||||
ImGui::EndChild();
|
||||
return;
|
||||
}
|
||||
|
||||
static Containers::StringView slot_labels[] = {
|
||||
#define c(enumerator, strenum, name) name,
|
||||
#include "../Maps/ArmourSlots.hpp"
|
||||
#undef c
|
||||
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(int(i));
|
||||
ImGui::PushID(i);
|
||||
|
||||
auto& part = _currentMass->armourParts()[i];
|
||||
|
||||
|
@ -52,20 +51,20 @@ void SaveTool::drawArmour() {
|
|||
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)].data(), armour_sets.at(part.id).name.data(), UnsignedInt(part.slot));
|
||||
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)].data(), part.id, UnsignedInt(part.slot));
|
||||
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::GetContentRegionAvail().x * 0.491f);
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvailWidth() * 0.491f);
|
||||
if(ImGui::BeginListBox("##ChangePart")) {
|
||||
if(std::strncmp("Neck", slot_labels[UnsignedInt(part.slot)].data(), 4) != 0) {
|
||||
if(std::strncmp("Neck", slot_labels[UnsignedInt(part.slot)], 4) != 0) {
|
||||
for(auto& set : armour_sets) {
|
||||
if(ImGui::Selectable(set.second.name.data(), set.first == part.id, ImGuiSelectableFlags_SpanAvailWidth)) {
|
||||
if(ImGui::Selectable(set.second.name, set.first == part.id, ImGuiSelectableFlags_SpanAvailWidth)) {
|
||||
part.id = set.first;
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +75,7 @@ void SaveTool::drawArmour() {
|
|||
continue;
|
||||
}
|
||||
|
||||
if(ImGui::Selectable(set.second.name.data(), set.first == part.id, ImGuiSelectableFlags_SpanAvailWidth)) {
|
||||
if(ImGui::Selectable(set.second.name, set.first == part.id, ImGuiSelectableFlags_SpanAvailWidth)) {
|
||||
part.id = set.first;
|
||||
}
|
||||
}
|
||||
|
@ -103,10 +102,10 @@ void SaveTool::drawArmour() {
|
|||
|
||||
ImGui::PushID(j);
|
||||
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - 2.0f);
|
||||
if(ImGui::BeginCombo("##Style", getStyleName(part.styles[j], _currentMass->armourCustomStyles()).data())) {
|
||||
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()).data(), part.styles[j] == style.first)) {
|
||||
if(ImGui::Selectable(getStyleName(style.first, _currentMass->armourCustomStyles()), part.styles[j] == style.first)) {
|
||||
part.styles[j] = style.first;
|
||||
}
|
||||
}
|
||||
|
@ -126,14 +125,14 @@ void SaveTool::drawArmour() {
|
|||
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], int(j));
|
||||
ImGui::RadioButton(std::to_string(j + 1).c_str(), &_selectedArmourDecals[i], j);
|
||||
}
|
||||
|
||||
drawDecalEditor(part.decals[_selectedArmourDecals[i]]);
|
||||
|
||||
ImGui::PopID();
|
||||
|
||||
if(part.accessories.size() != 0) {
|
||||
if(!part.accessories.size()) {
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::PushID("Accessory");
|
||||
|
@ -141,7 +140,7 @@ void SaveTool::drawArmour() {
|
|||
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], int(j));
|
||||
ImGui::RadioButton(std::string{char(65 + j)}.c_str(), &_selectedArmourAccessories[i], j);
|
||||
}
|
||||
|
||||
drawAccessoryEditor(part.accessories[_selectedArmourAccessories[i]], _currentMass->armourCustomStyles());
|
||||
|
@ -152,9 +151,7 @@ void SaveTool::drawArmour() {
|
|||
ImGui::Separator();
|
||||
|
||||
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
||||
_modifiedBySaveTool = true;
|
||||
if(!_currentMass->writeArmourPart(part.slot)) {
|
||||
_modifiedBySaveTool = false;
|
||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||
}
|
||||
}
|
||||
|
@ -163,128 +160,6 @@ void SaveTool::drawArmour() {
|
|||
ImGui::PopID();
|
||||
}
|
||||
|
||||
if(_currentMass->bulletLauncherAttachmentStyle() != BulletLauncherAttachmentStyle::NotFound &&
|
||||
ImGui::CollapsingHeader("Bullet launcher placement"))
|
||||
{
|
||||
drawAlignedText("Attachment style:"_s);
|
||||
ImGui::SameLine();
|
||||
ImGui::RadioButton("Active one",
|
||||
_currentMass->bulletLauncherAttachmentStyle() == BulletLauncherAttachmentStyle::ActiveOne);
|
||||
ImGui::SameLine();
|
||||
ImGui::RadioButton("Active one per slot",
|
||||
_currentMass->bulletLauncherAttachmentStyle() == BulletLauncherAttachmentStyle::ActiveOnePerSlot);
|
||||
ImGui::SameLine();
|
||||
ImGui::RadioButton("All equipped",
|
||||
_currentMass->bulletLauncherAttachmentStyle() == BulletLauncherAttachmentStyle::AllEquipped);
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
drawAlignedText("Launcher slot:");
|
||||
ImGui::SameLine();
|
||||
ImGui::RadioButton("1", &_selectedBLPlacement, 0);
|
||||
ImGui::SameLine();
|
||||
ImGui::RadioButton("2", &_selectedBLPlacement, 1);
|
||||
ImGui::SameLine();
|
||||
ImGui::RadioButton("3", &_selectedBLPlacement, 2);
|
||||
ImGui::SameLine();
|
||||
ImGui::RadioButton("4", &_selectedBLPlacement, 3);
|
||||
|
||||
auto& placement = _currentMass->bulletLauncherAttachments()[_selectedBLPlacement];
|
||||
|
||||
static const Containers::StringView socket_labels[] = {
|
||||
#define c(enumerator, enumstr, name) name,
|
||||
#include "../Maps/BulletLauncherSockets.hpp"
|
||||
#undef c
|
||||
};
|
||||
|
||||
drawAlignedText("Socket:");
|
||||
ImGui::SameLine();
|
||||
if(ImGui::BeginCombo("##Socket", socket_labels[UnsignedInt(placement.socket)].data())) {
|
||||
for(UnsignedInt i = 0; i < (sizeof(socket_labels) / sizeof(socket_labels[0])); i++) {
|
||||
if(ImGui::Selectable(socket_labels[i].data(), i == UnsignedInt(placement.socket), ImGuiSelectableFlags_SpanAvailWidth)) {
|
||||
placement.socket = static_cast<BulletLauncherSocket>(i);
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
if(placement.socket != BulletLauncherSocket::Auto) {
|
||||
ImGui::BeginGroup();
|
||||
drawAlignedText("Relative position:");
|
||||
drawAlignedText("Offset position:");
|
||||
drawAlignedText("Relative rotation:");
|
||||
drawAlignedText("Offset rotation:");
|
||||
drawAlignedText("Scale:");
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::BeginGroup();
|
||||
ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());
|
||||
ImGui::DragFloat("##RelPosX", &placement.relativeLocation.x(), 1.0f, -FLT_MAX, +FLT_MAX, "X: %.3f");
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||
ImGui::DragFloat("##RelPosY", &placement.relativeLocation.y(), 1.0f, -FLT_MAX, +FLT_MAX, "Y: %.3f");
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||
ImGui::DragFloat("##RelPosZ", &placement.relativeLocation.z(), 1.0f, -FLT_MAX, +FLT_MAX, "Z: %.3f");
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());
|
||||
ImGui::SliderFloat("##OffPosX", &placement.offsetLocation.x(), -500.0f, +500.0f, "X: %.3f");
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||
ImGui::SliderFloat("##OffPosY", &placement.offsetLocation.y(), -500.0f, +500.0f, "Y: %.3f");
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||
ImGui::SliderFloat("##OffPosZ", &placement.offsetLocation.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", &placement.relativeRotation.x(), 1.0f, -FLT_MAX, +FLT_MAX, "Roll: %.3f");
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||
ImGui::DragFloat("##RotY", &placement.relativeRotation.y(), 1.0f, -FLT_MAX, +FLT_MAX, "Yaw: %.3f");
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||
ImGui::DragFloat("##RotZ", &placement.relativeRotation.z(), 1.0f, -FLT_MAX, +FLT_MAX, "Pitch: %.3f");
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());
|
||||
ImGui::SliderFloat("##RotOffsetZ", &placement.offsetRotation.z(), -180.0f, +180.0f, "Roll: %.3f");
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||
ImGui::SliderFloat("##RotOffsetX", &placement.offsetRotation.x(), -30.0f, +30.0f, "Pitch: %.3f");
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||
ImGui::SliderFloat("##RotOffsetY", &placement.offsetRotation.y(), -30.0f, +30.0f, "Yaw: %.3f");
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());
|
||||
ImGui::SliderFloat("##ScaleX", &placement.relativeScale.x(), 0.5f, 1.5f, "X: %.3f");
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||
ImGui::SliderFloat("##ScaleY", &placement.relativeScale.y(), 0.5f, 1.5f, "Y: %.3f");
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||
ImGui::SliderFloat("##ScaleZ", &placement.relativeScale.z(), 0.5f, 1.5f, "Z: %.3f");
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::SameLine();
|
||||
drawHelpMarker("0.5 = 50 in-game\n1.5 = 150 in-game");
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
|
||||
_modifiedBySaveTool = true;
|
||||
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); }) &&
|
||||
!_currentMass->writeBulletLauncherAttachments())
|
||||
{
|
||||
_modifiedBySaveTool = false;
|
||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
|
@ -301,7 +176,7 @@ void SaveTool::drawCustomArmourStyles() {
|
|||
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(int(i));
|
||||
ImGui::PushID(i);
|
||||
DCSResult result;
|
||||
result = drawCustomStyle(_currentMass->armourCustomStyles()[i]);
|
||||
switch(result) {
|
||||
|
@ -309,9 +184,7 @@ void SaveTool::drawCustomArmourStyles() {
|
|||
_currentMass->getArmourCustomStyles();
|
||||
break;
|
||||
case DCS_Save:
|
||||
_modifiedBySaveTool = true;
|
||||
if(!_currentMass->writeArmourCustomStyle(i)) {
|
||||
_modifiedBySaveTool = false;
|
||||
if(_currentMass->writeArmourCustomStyle(i)) {
|
||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -32,7 +32,7 @@ void SaveTool::drawFrameInfo() {
|
|||
|
||||
ImGui::BeginGroup();
|
||||
|
||||
if(ImGui::BeginChild("##JointSliders", {(ImGui::GetContentRegionAvail().x / 2.0f) - (ImGui::GetStyle().WindowPadding.x / 2.0f), 300.0f}, true, ImGuiWindowFlags_MenuBar)) {
|
||||
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");
|
||||
|
||||
|
@ -43,7 +43,7 @@ void SaveTool::drawFrameInfo() {
|
|||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
if(ImGui::BeginChild("##FrameStyles", {(ImGui::GetContentRegionAvail().x / 2.0f) - (ImGui::GetStyle().WindowPadding.x / 2.0f), 0.0f}, true, ImGuiWindowFlags_MenuBar)) {
|
||||
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");
|
||||
|
||||
|
@ -180,9 +180,7 @@ void SaveTool::drawJointSliders() {
|
|||
}
|
||||
else {
|
||||
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
||||
_modifiedBySaveTool = true;
|
||||
if(!_currentMass->writeJointSliders()) {
|
||||
_modifiedBySaveTool = false;
|
||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||
}
|
||||
_jointsDirty = false;
|
||||
|
@ -207,9 +205,9 @@ void SaveTool::drawFrameStyles() {
|
|||
|
||||
ImGui::PushID(i);
|
||||
|
||||
if(ImGui::BeginCombo("##Style", getStyleName(_currentMass->frameStyles()[i], _currentMass->frameCustomStyles()).data())) {
|
||||
if(ImGui::BeginCombo("##Style", getStyleName(_currentMass->frameStyles()[i], _currentMass->frameCustomStyles()))) {
|
||||
for(const auto& style : style_names) {
|
||||
if(ImGui::Selectable(getStyleName(style.first, _currentMass->frameCustomStyles()).data(), _currentMass->frameStyles()[i] == style.first)) {
|
||||
if(ImGui::Selectable(getStyleName(style.first, _currentMass->frameCustomStyles()), _currentMass->frameStyles()[i] == style.first)) {
|
||||
_currentMass->frameStyles()[i] = style.first;
|
||||
_stylesDirty = true;
|
||||
}
|
||||
|
@ -230,9 +228,7 @@ void SaveTool::drawFrameStyles() {
|
|||
}
|
||||
else {
|
||||
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
||||
_modifiedBySaveTool = true;
|
||||
if(!_currentMass->writeFrameStyles()) {
|
||||
_modifiedBySaveTool = false;
|
||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||
}
|
||||
_stylesDirty = false;
|
||||
|
@ -263,9 +259,7 @@ void SaveTool::drawEyeColourPicker() {
|
|||
}
|
||||
else {
|
||||
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
||||
_modifiedBySaveTool = true;
|
||||
if(!_currentMass->writeEyeFlareColour()) {
|
||||
_modifiedBySaveTool = false;
|
||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||
}
|
||||
_eyeFlareDirty = false;
|
||||
|
@ -291,7 +285,7 @@ void SaveTool::drawCustomFrameStyles() {
|
|||
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(int(i));
|
||||
ImGui::PushID(i);
|
||||
DCSResult result;
|
||||
result = drawCustomStyle(_currentMass->frameCustomStyles()[i]);
|
||||
switch(result) {
|
||||
|
@ -299,9 +293,7 @@ void SaveTool::drawCustomFrameStyles() {
|
|||
_currentMass->getFrameCustomStyles();
|
||||
break;
|
||||
case DCS_Save:
|
||||
_modifiedBySaveTool = true;
|
||||
if(!_currentMass->writeFrameCustomStyle(i)) {
|
||||
_modifiedBySaveTool = false;
|
||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include "../FontAwesome/IconsFontAwesome5.h"
|
||||
|
||||
#include "../Maps/StyleNames.h"
|
||||
#include "../Maps/WeaponParts.h"
|
||||
|
||||
#include "SaveTool.h"
|
||||
|
||||
|
@ -33,7 +32,7 @@ void SaveTool::drawWeapons() {
|
|||
|
||||
if(!ImGui::BeginTable("##WeaponsList", 1,
|
||||
ImGuiTableFlags_ScrollY|ImGuiTableFlags_BordersOuter|ImGuiTableFlags_BordersInnerH,
|
||||
{ImGui::GetContentRegionAvail().x * 0.2f, -footer_height_to_reserve}))
|
||||
{ImGui::GetContentRegionAvailWidth() * 0.2f, -footer_height_to_reserve}))
|
||||
{
|
||||
ImGui::EndGroup();
|
||||
return;
|
||||
|
@ -58,9 +57,7 @@ void SaveTool::drawWeapons() {
|
|||
|
||||
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
||||
if(_meleeDirty) {
|
||||
_modifiedBySaveTool = true;
|
||||
if(!_currentMass->writeMeleeWeapons()) {
|
||||
_modifiedBySaveTool = false;
|
||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||
}
|
||||
else {
|
||||
|
@ -69,9 +66,7 @@ void SaveTool::drawWeapons() {
|
|||
}
|
||||
|
||||
if(_shieldsDirty) {
|
||||
_modifiedBySaveTool = true;
|
||||
if(!_currentMass->writeShields()) {
|
||||
_modifiedBySaveTool = false;
|
||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||
}
|
||||
else {
|
||||
|
@ -80,9 +75,7 @@ void SaveTool::drawWeapons() {
|
|||
}
|
||||
|
||||
if(_bShootersDirty) {
|
||||
_modifiedBySaveTool = true;
|
||||
if(!_currentMass->writeBulletShooters()) {
|
||||
_modifiedBySaveTool = false;
|
||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||
}
|
||||
else {
|
||||
|
@ -91,9 +84,7 @@ void SaveTool::drawWeapons() {
|
|||
}
|
||||
|
||||
if(_eShootersDirty) {
|
||||
_modifiedBySaveTool = true;
|
||||
if(_currentMass->writeEnergyShooters()) {
|
||||
_modifiedBySaveTool = false;
|
||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||
}
|
||||
else {
|
||||
|
@ -102,9 +93,7 @@ void SaveTool::drawWeapons() {
|
|||
}
|
||||
|
||||
if(_bLaunchersDirty) {
|
||||
_modifiedBySaveTool = true;
|
||||
if(_currentMass->writeBulletLaunchers()) {
|
||||
_modifiedBySaveTool = false;
|
||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||
}
|
||||
else {
|
||||
|
@ -113,9 +102,7 @@ void SaveTool::drawWeapons() {
|
|||
}
|
||||
|
||||
if(_eLaunchersDirty) {
|
||||
_modifiedBySaveTool = true;
|
||||
if(_currentMass->writeEnergyLaunchers()) {
|
||||
_modifiedBySaveTool = false;
|
||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||
}
|
||||
else {
|
||||
|
@ -180,47 +167,40 @@ void SaveTool::drawWeapons() {
|
|||
ImGui::Separator();
|
||||
|
||||
if(drawUnsafeWidget([](){ return ImGui::Button(ICON_FA_SAVE " Save changes to weapon category"); })) {
|
||||
_modifiedBySaveTool = true;
|
||||
switch(_currentWeapon->type) {
|
||||
case WeaponType::Melee:
|
||||
if(!_currentMass->writeMeleeWeapons()) {
|
||||
_modifiedBySaveTool = false;
|
||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||
}
|
||||
break;
|
||||
case WeaponType::Shield:
|
||||
if(!_currentMass->writeShields()) {
|
||||
_modifiedBySaveTool = false;
|
||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||
}
|
||||
break;
|
||||
case WeaponType::BulletShooter:
|
||||
if(!_currentMass->writeBulletShooters()) {
|
||||
_modifiedBySaveTool = false;
|
||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||
}
|
||||
break;
|
||||
case WeaponType::EnergyShooter:
|
||||
if(!_currentMass->writeEnergyShooters()) {
|
||||
_modifiedBySaveTool = false;
|
||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||
}
|
||||
break;
|
||||
case WeaponType::BulletLauncher:
|
||||
if(!_currentMass->writeBulletLaunchers()) {
|
||||
_modifiedBySaveTool = false;
|
||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||
}
|
||||
break;
|
||||
case WeaponType::EnergyLauncher:
|
||||
if(!_currentMass->writeEnergyLaunchers()) {
|
||||
_modifiedBySaveTool = false;
|
||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_modifiedBySaveTool = false;
|
||||
_queue.addToast(Toast::Type::Error, "Unknown weapon type");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -254,14 +234,14 @@ void SaveTool::drawWeapons() {
|
|||
ImGui::EndGroup();
|
||||
}
|
||||
|
||||
void SaveTool::drawWeaponCategory(Containers::StringView name, Containers::ArrayView<Weapon> weapons_view, bool& dirty,
|
||||
Containers::StringView payload_type, Containers::StringView payload_tooltip)
|
||||
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.data());
|
||||
ImGui::TextUnformatted(name);
|
||||
|
||||
ImGui::PushID(payload_type.data());
|
||||
ImGui::PushID(payload_type);
|
||||
|
||||
for(UnsignedInt i = 0; i < weapons_view.size(); i++) {
|
||||
auto& weapon = weapons_view[i];
|
||||
|
@ -269,23 +249,23 @@ void SaveTool::drawWeaponCategory(Containers::StringView name, Containers::Array
|
|||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::PushID(int(i));
|
||||
ImGui::PushID(i);
|
||||
|
||||
if(ImGui::Selectable(weapon.name.data(), _currentWeapon == &weapon)) {
|
||||
if(ImGui::Selectable(weapon.name.c_str(), _currentWeapon == &weapon)) {
|
||||
_currentWeapon = &weapon;
|
||||
}
|
||||
if(ImGui::BeginDragDropSource()) {
|
||||
ImGui::SetDragDropPayload(payload_type.data(), &i, sizeof(UnsignedInt));
|
||||
ImGui::SetDragDropPayload(payload_type, &i, sizeof(UnsignedInt));
|
||||
if(ImGui::GetIO().KeyCtrl) {
|
||||
ImGui::Text("%s %i - %s (copy)", payload_tooltip.data(), i + 1, weapon.name.data());
|
||||
ImGui::Text("%s %i - %s (copy)", payload_tooltip, i + 1, weapon.name.c_str());
|
||||
}
|
||||
else {
|
||||
ImGui::Text("%s %i - %s", payload_tooltip.data(), i + 1, weapon.name.data());
|
||||
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.data())) {
|
||||
if(const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(payload_type)) {
|
||||
int index = *static_cast<int*>(payload->Data);
|
||||
|
||||
if(!ImGui::GetIO().KeyCtrl) {
|
||||
|
@ -309,7 +289,7 @@ void SaveTool::drawWeaponCategory(Containers::StringView name, Containers::Array
|
|||
|
||||
ImGui::PopID();
|
||||
|
||||
if(weapon.attached) {
|
||||
if(weapon.attached == true) {
|
||||
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, 0x1F008CFFu);
|
||||
}
|
||||
}
|
||||
|
@ -322,13 +302,13 @@ void SaveTool::drawWeaponEditor(Weapon& weapon) {
|
|||
return;
|
||||
}
|
||||
|
||||
static Containers::StringView labels[] {
|
||||
#define c(enumerator, strenum, name) name,
|
||||
#include "../Maps/WeaponTypes.hpp"
|
||||
#undef c
|
||||
static const char* labels[] {
|
||||
#define c(enumerator, strenum, name) name,
|
||||
#include "../Maps/WeaponTypes.hpp"
|
||||
#undef c
|
||||
};
|
||||
|
||||
drawAlignedText("%s: %s", labels[UnsignedInt(weapon.type)].data(), weapon.name.data());
|
||||
drawAlignedText("%s: %s", labels[UnsignedInt(weapon.type)], weapon.name.c_str());
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
|
@ -337,7 +317,7 @@ void SaveTool::drawWeaponEditor(Weapon& weapon) {
|
|||
for(auto& c : name_buf) {
|
||||
c = '\0';
|
||||
}
|
||||
std::strncpy(name_buf.data(), weapon.name.data(), 32);
|
||||
std::strncpy(name_buf.data(), weapon.name.c_str(), 32);
|
||||
ImGui::OpenPopup("name_edit");
|
||||
}
|
||||
if(drawRenamePopup(name_buf)) {
|
||||
|
@ -390,8 +370,8 @@ void SaveTool::drawWeaponEditor(Weapon& weapon) {
|
|||
weapon.damageType = DamageType::Freeze;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if(ImGui::RadioButton("Shock##Shock", weapon.damageType == DamageType::Shock)) {
|
||||
weapon.damageType = DamageType::Shock;
|
||||
if(ImGui::RadioButton("Shock##Shock", weapon.damageType == DamageType::Freeze)) {
|
||||
weapon.damageType = DamageType::Freeze;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -412,8 +392,6 @@ void SaveTool::drawWeaponEditor(Weapon& weapon) {
|
|||
}
|
||||
|
||||
ImGui::ColorEdit3("##CustomEffectColourPicker", &weapon.effectColour.x(), ImGuiColorEditFlags_HDR|ImGuiColorEditFlags_Float);
|
||||
ImGui::SameLine();
|
||||
drawHelpMarker("Click the coloured square for the full picker.");
|
||||
|
||||
if(!custom_effect) {
|
||||
ImGui::EndDisabled();
|
||||
|
@ -430,80 +408,12 @@ void SaveTool::drawWeaponEditor(Weapon& weapon) {
|
|||
_selectedWeaponPart = 0;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::RadioButton(std::to_string(i).c_str(), &_selectedWeaponPart, i);
|
||||
ImGui::RadioButton(std::to_string(i + 1).c_str(), &_selectedWeaponPart, i);
|
||||
}
|
||||
|
||||
auto& part = weapon.parts[_selectedWeaponPart];
|
||||
|
||||
const auto* map = [this, &weapon]()-> const std::map<Int, Containers::StringView>* {
|
||||
switch(weapon.type) {
|
||||
case WeaponType::Melee:
|
||||
return _selectedWeaponPart == 0 ? &melee_grips : &melee_assaulters;
|
||||
case WeaponType::Shield:
|
||||
return _selectedWeaponPart == 0 ? &shield_handles : &shield_shells;
|
||||
case WeaponType::BulletShooter:
|
||||
return _selectedWeaponPart == 0 ? &bshooter_triggers : &bshooter_barrels;
|
||||
case WeaponType::EnergyShooter:
|
||||
return _selectedWeaponPart == 0 ? &eshooter_triggers : &eshooter_busters;
|
||||
case WeaponType::BulletLauncher:
|
||||
return _selectedWeaponPart == 0 ? &blauncher_pods : &blauncher_projectiles;
|
||||
case WeaponType::EnergyLauncher:
|
||||
return _selectedWeaponPart == 0 ? &elauncher_generators : &elauncher_pods;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
if(!map) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(map->find(part.id) != map->cend()) {
|
||||
ImGui::TextUnformatted(map->at(part.id).data());
|
||||
}
|
||||
else if(part.id == -1) {
|
||||
ImGui::TextUnformatted("<none>");
|
||||
}
|
||||
else{
|
||||
ImGui::Text("ID: %i", part.id);
|
||||
}
|
||||
|
||||
if(!map->empty()) {
|
||||
ImGui::SameLine();
|
||||
if(ImGui::SmallButton("Change")) {
|
||||
ImGui::OpenPopup("##WeaponPartPopup");
|
||||
}
|
||||
if(ImGui::BeginPopup("##WeaponPartPopup")) {
|
||||
if(ImGui::BeginListBox("##WeaponParts")) {
|
||||
for(const auto& mapped_part : *map) {
|
||||
if(ImGui::Selectable(mapped_part.second.data(), mapped_part.first == part.id)) {
|
||||
part.id = mapped_part.first;
|
||||
}
|
||||
if(mapped_part.first == part.id) {
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndListBox();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
if(weapon.type == WeaponType::Shield ||
|
||||
(weapon.type == WeaponType::BulletLauncher && _selectedWeaponPart != 0))
|
||||
{
|
||||
ImGui::SameLine();
|
||||
if(ImGui::SmallButton("Unequip")) {
|
||||
part.id = -1;
|
||||
}
|
||||
if(weapon.type == WeaponType::Shield && _selectedWeaponPart == 0) {
|
||||
drawTooltip("This will make the whole shield and its accessories invisible.");
|
||||
}
|
||||
else {
|
||||
drawTooltip("This will make accessories invisible as well.");
|
||||
}
|
||||
}
|
||||
ImGui::Text("ID: %i", part.id);
|
||||
|
||||
if(ImGui::BeginChild("##PartDetails", {0.0f, 0.0f}, true)) {
|
||||
ImGui::TextUnformatted("Styles:");
|
||||
|
@ -515,9 +425,9 @@ void SaveTool::drawWeaponEditor(Weapon& weapon) {
|
|||
|
||||
ImGui::PushID(i);
|
||||
|
||||
if(ImGui::BeginCombo("##Style", getStyleName(part.styles[i], weapon.customStyles).data())) {
|
||||
if(ImGui::BeginCombo("##Style", getStyleName(part.styles[i], weapon.customStyles))) {
|
||||
for(const auto& style: style_names) {
|
||||
if(ImGui::Selectable(getStyleName(style.first, weapon.customStyles).data(),
|
||||
if(ImGui::Selectable(getStyleName(style.first, weapon.customStyles),
|
||||
part.styles[i] == style.first)) {
|
||||
part.styles[i] = style.first;
|
||||
}
|
||||
|
@ -536,7 +446,7 @@ void SaveTool::drawWeaponEditor(Weapon& weapon) {
|
|||
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, int(i));
|
||||
ImGui::RadioButton(std::to_string(i + 1).c_str(), &_selectedWeaponDecal, i);
|
||||
}
|
||||
|
||||
drawDecalEditor(part.decals[_selectedWeaponDecal]);
|
||||
|
@ -551,7 +461,7 @@ void SaveTool::drawWeaponEditor(Weapon& weapon) {
|
|||
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, int(i));
|
||||
ImGui::RadioButton(std::string{char(65 + i)}.c_str(), &_selectedWeaponAccessory, i);
|
||||
}
|
||||
|
||||
drawAccessoryEditor(part.accessories[_selectedWeaponAccessory], weapon.customStyles);
|
||||
|
|
|
@ -14,14 +14,12 @@
|
|||
// 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 "SaveTool.h"
|
||||
|
||||
#include <Magnum/ImGuiIntegration/Integration.h>
|
||||
|
||||
#include <SDL_messagebox.h>
|
||||
|
||||
#include "../FontAwesome/IconsFontAwesome5.h"
|
||||
|
||||
#include "SaveTool.h"
|
||||
|
||||
extern const ImVec2 center_pivot;
|
||||
|
||||
void SaveTool::drawProfileManager() {
|
||||
|
@ -52,8 +50,7 @@ void SaveTool::drawProfileManager() {
|
|||
ImGui::TableSetColumnIndex(1);
|
||||
if(ImGui::SmallButton("Refresh")) {
|
||||
if(!_profileManager->refreshProfiles()) {
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",
|
||||
_profileManager->lastError().data(), window());
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error in ProfileManager", _profileManager->lastError().c_str(), window());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
@ -80,36 +77,31 @@ void SaveTool::drawProfileManager() {
|
|||
ImGui::TextUnformatted("Actions");
|
||||
|
||||
for(std::size_t i = 0; i < _profileManager->profiles().size(); ++i) {
|
||||
Profile& profile = _profileManager->profiles()[i];
|
||||
|
||||
ImGui::TableNextRow();
|
||||
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
ImGui::PushID(int(i));
|
||||
if(ImGui::Selectable(profile.companyName().data(), false,
|
||||
ImGui::PushID(i);
|
||||
if(ImGui::Selectable(_profileManager->profiles()[i].companyName().c_str(), false,
|
||||
ImGuiSelectableFlags_SpanAllColumns|ImGuiSelectableFlags_AllowItemOverlap))
|
||||
{
|
||||
_currentProfile = _profileManager->getProfile(i);
|
||||
initialiseMassManager();
|
||||
initialiseFileWatcher();
|
||||
_uiState = UiState::MainManager;
|
||||
}
|
||||
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
ImGui::TextUnformatted(profile.isDemo() ? "Demo" : "Full");
|
||||
ImGui::TextUnformatted(_profileManager->profiles()[i].type() == ProfileType::Demo ? "Demo (legacy)" : "Full (legacy)");
|
||||
|
||||
ImGui::TableSetColumnIndex(2);
|
||||
if(ImGui::SmallButton(ICON_FA_FILE_ARCHIVE)) {
|
||||
profile_index = i;
|
||||
ImGui::OpenPopup(backup_popup_id);
|
||||
}
|
||||
drawTooltip("Backup");
|
||||
ImGui::SameLine(0.0f, 2.0f);
|
||||
if(drawUnsafeWidget(ImGui::SmallButton, ICON_FA_TRASH_ALT)) {
|
||||
profile_index = i;
|
||||
ImGui::OpenPopup(delete_popup_id);
|
||||
}
|
||||
drawTooltip("Delete");
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::EndTable();
|
||||
|
@ -138,9 +130,9 @@ auto SaveTool::drawBackupListPopup() -> ImGuiID {
|
|||
if(ImGui::BeginPopupModal("Restore backup", nullptr,
|
||||
ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_AlwaysAutoResize))
|
||||
{
|
||||
ImGui::PushTextWrapPos(float(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.",
|
||||
_profileManager->backups()[backup_index].company.data(),
|
||||
_profileManager->backups()[backup_index].company.c_str(),
|
||||
_profileManager->backups()[backup_index].timestamp.year,
|
||||
_profileManager->backups()[backup_index].timestamp.month,
|
||||
_profileManager->backups()[backup_index].timestamp.day,
|
||||
|
@ -160,11 +152,7 @@ auto SaveTool::drawBackupListPopup() -> ImGuiID {
|
|||
if(!_profileManager->restoreBackup(backup_index)) {
|
||||
_queue.addToast(Toast::Type::Error, _profileManager->lastError());
|
||||
}
|
||||
if(!_profileManager->refreshProfiles()) {
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",
|
||||
_profileManager->lastError().data(), window());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
_profileManager->refreshProfiles();
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
@ -181,9 +169,9 @@ auto SaveTool::drawBackupListPopup() -> ImGuiID {
|
|||
if(ImGui::BeginPopupModal("Delete backup", nullptr,
|
||||
ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_AlwaysAutoResize))
|
||||
{
|
||||
ImGui::PushTextWrapPos(float(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.",
|
||||
_profileManager->backups()[backup_index].company.data(),
|
||||
_profileManager->backups()[backup_index].company.c_str(),
|
||||
_profileManager->backups()[backup_index].timestamp.year,
|
||||
_profileManager->backups()[backup_index].timestamp.month,
|
||||
_profileManager->backups()[backup_index].timestamp.day,
|
||||
|
@ -235,7 +223,7 @@ auto SaveTool::drawBackupListPopup() -> ImGuiID {
|
|||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
if(_profileManager->backups().isEmpty()) {
|
||||
if(_profileManager->backups().empty()) {
|
||||
ImGui::TextDisabled("No backups were found.");
|
||||
}
|
||||
else if(ImGui::BeginTable("##Backups", 4,
|
||||
|
@ -258,44 +246,41 @@ auto SaveTool::drawBackupListPopup() -> ImGuiID {
|
|||
ImGui::TextUnformatted("Actions");
|
||||
|
||||
for(std::size_t i = 0; i < _profileManager->backups().size(); ++i) {
|
||||
auto& backup = _profileManager->backups()[i];
|
||||
ImGui::TableNextRow();
|
||||
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
ImGui::TextUnformatted(backup.company.data());
|
||||
ImGui::TextUnformatted(_profileManager->backups()[i].company.c_str());
|
||||
if(ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
for(const auto& file : backup.includedFiles) {
|
||||
ImGui::TextUnformatted(file.data());
|
||||
for(const auto& file : _profileManager->backups()[i].includedFiles) {
|
||||
ImGui::TextUnformatted(file.c_str());
|
||||
}
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
ImGui::Text("%.4i-%.2i-%.2i %.2i:%.2i:%.2i",
|
||||
backup.timestamp.year,
|
||||
backup.timestamp.month,
|
||||
backup.timestamp.day,
|
||||
backup.timestamp.hour,
|
||||
backup.timestamp.minute,
|
||||
backup.timestamp.second);
|
||||
_profileManager->backups()[i].timestamp.year,
|
||||
_profileManager->backups()[i].timestamp.month,
|
||||
_profileManager->backups()[i].timestamp.day,
|
||||
_profileManager->backups()[i].timestamp.hour,
|
||||
_profileManager->backups()[i].timestamp.minute,
|
||||
_profileManager->backups()[i].timestamp.second);
|
||||
|
||||
ImGui::TableSetColumnIndex(2);
|
||||
ImGui::TextUnformatted(backup.type == ProfileType::Demo ? "Demo" : "Full");
|
||||
ImGui::TextUnformatted(_profileManager->backups()[i].type == ProfileType::Demo ? "Demo" : "Full");
|
||||
|
||||
ImGui::TableSetColumnIndex(3);
|
||||
ImGui::PushID(int(i));
|
||||
ImGui::PushID(i);
|
||||
if(ImGui::SmallButton(ICON_FA_UNDO)) {
|
||||
backup_index = i;
|
||||
ImGui::OpenPopup(restore_backup_popup_id);
|
||||
}
|
||||
drawTooltip("Restore");
|
||||
ImGui::SameLine(0.0f, 2.0f);
|
||||
if(ImGui::SmallButton(ICON_FA_TRASH_ALT)) {
|
||||
backup_index = i;
|
||||
ImGui::OpenPopup(delete_backup_popup_id);
|
||||
}
|
||||
drawTooltip("Delete");
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::EndTable();
|
||||
|
@ -341,18 +326,12 @@ auto SaveTool::drawBackupProfilePopup(std::size_t profile_index) -> ImGuiID {
|
|||
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
if(ImGui::Button("Yes")) {
|
||||
if(!_profileManager->backupProfile(profile_index, true)) {
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",
|
||||
_profileManager->lastError().data(), window());
|
||||
}
|
||||
_profileManager->backupProfile(profile_index, true);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Button("No", ImGui::GetItemRectSize())) {
|
||||
if(!_profileManager->backupProfile(profile_index, false)) {
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",
|
||||
_profileManager->lastError().data(), window());
|
||||
}
|
||||
_profileManager->backupProfile(profile_index, false);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
@ -380,10 +359,10 @@ auto SaveTool::drawDeleteProfilePopup(std::size_t profile_index) -> ImGuiID {
|
|||
delete_builds = false;
|
||||
}
|
||||
|
||||
ImGui::PushTextWrapPos(float(windowSize().x()) * 0.40f);
|
||||
ImGui::Text("Are you sure you want to delete the %s profile named %s ? This operation is irreversible.",
|
||||
_profileManager->profiles()[profile_index].isDemo() ? "demo" : "full game",
|
||||
_profileManager->profiles()[profile_index].companyName().data());
|
||||
ImGui::PushTextWrapPos(windowSize().x() * 0.40f);
|
||||
ImGui::Text("Are you sure you want to delete the %s %s profile ? This operation is irreversible.",
|
||||
_profileManager->profiles()[profile_index].companyName().c_str(),
|
||||
_profileManager->profiles()[profile_index].type() == ProfileType::Demo ? "demo" : "full game");
|
||||
ImGui::PopTextWrapPos();
|
||||
|
||||
if(ImGui::BeginTable("##DeleteProfileLayout", 2)) {
|
||||
|
|
|
@ -1,176 +0,0 @@
|
|||
// 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/Format.h>
|
||||
|
||||
#include <SDL_events.h>
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "../Logger/Logger.h"
|
||||
|
||||
#include "SaveTool.h"
|
||||
|
||||
void SaveTool::updateCheckEvent(SDL_Event& event) {
|
||||
_updateThread.join();
|
||||
|
||||
if(event.user.code == CurlInitFailed) {
|
||||
_queue.addToast(Toast::Type::Error, "Couldn't initialise libcurl. Update check aborted."_s);
|
||||
LOG_ERROR("Couldn't initialise libcurl. Update check aborted.");
|
||||
return;
|
||||
}
|
||||
else if(event.user.code == CurlError) {
|
||||
Containers::String error{static_cast<char*>(event.user.data2), CURL_ERROR_SIZE, nullptr};
|
||||
_queue.addToast(Toast::Type::Error, error, std::chrono::milliseconds{5000});
|
||||
_queue.addToast(Toast::Type::Error, static_cast<char*>(event.user.data1),
|
||||
std::chrono::milliseconds{5000});
|
||||
LOG_ERROR_FORMAT("{}: {}", static_cast<char*>(event.user.data1), static_cast<char*>(event.user.data2));
|
||||
return;
|
||||
}
|
||||
else if(event.user.code == CurlTimeout) {
|
||||
_queue.addToast(Toast::Type::Error, "The request timed out."_s);
|
||||
LOG_ERROR("The request timed out.");
|
||||
return;
|
||||
}
|
||||
else if(event.user.code != 200) {
|
||||
_queue.addToast(Toast::Type::Error,
|
||||
Utility::format("The request failed with error code {}.", event.user.code));
|
||||
LOG_ERROR_FORMAT("The request failed with error code {}.", event.user.code);
|
||||
return;
|
||||
}
|
||||
|
||||
struct Version {
|
||||
explicit Version(Containers::StringView str) {
|
||||
std::size_t start_point = 0;
|
||||
|
||||
if(str[0] == 'v') {
|
||||
start_point++;
|
||||
}
|
||||
|
||||
auto components = Containers::StringView{str.data() + start_point}.split('.');
|
||||
|
||||
major = std::strtol(components[0].data(), nullptr, 10);
|
||||
minor = std::strtol(components[1].data(), nullptr, 10);
|
||||
patch = std::strtol(components[2].data(), nullptr, 10);
|
||||
|
||||
fullVersion = major * 10000 + minor * 100 + patch;
|
||||
|
||||
if(str.hasSuffix("-pre")) {
|
||||
prerelease = true;
|
||||
}
|
||||
}
|
||||
Int fullVersion;
|
||||
Int major = 0;
|
||||
Int minor = 0;
|
||||
Int patch = 0;
|
||||
bool prerelease = false;
|
||||
|
||||
bool operator==(const Version& other) const {
|
||||
return fullVersion == other.fullVersion && prerelease == other.prerelease;
|
||||
}
|
||||
bool operator>(const Version& other) const {
|
||||
if((fullVersion > other.fullVersion) ||
|
||||
(fullVersion == other.fullVersion && !prerelease && other.prerelease))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
explicit operator Containers::String() const {
|
||||
return Utility::format("{}.{}.{}{}", major, minor, patch, prerelease ? "-pre" : "");
|
||||
}
|
||||
};
|
||||
|
||||
static const Version current_ver{SAVETOOL_VERSION};
|
||||
|
||||
auto str = static_cast<char*>(event.user.data1);
|
||||
Containers::String response{str, strlen(str), nullptr};
|
||||
auto components = response.splitOnAnyWithoutEmptyParts("\r\n");
|
||||
|
||||
Version latest_ver{components.front()};
|
||||
|
||||
if(latest_ver > current_ver) {
|
||||
_queue.addToast(Toast::Type::Warning,
|
||||
"Your version is out of date.\nCheck the settings for more information."_s,
|
||||
std::chrono::milliseconds{5000});
|
||||
_updateAvailable = true;
|
||||
_latestVersion = Containers::String{latest_ver};
|
||||
_releaseLink = Utility::format("https://williamjcm.ovh/git/williamjcm/MassBuilderSaveTool/releases/tag/v{}",
|
||||
components.front());
|
||||
_downloadLink = components.back();
|
||||
}
|
||||
else if(latest_ver == current_ver || (current_ver > latest_ver && current_ver.prerelease)) {
|
||||
_queue.addToast(Toast::Type::Success, "The application is already up to date."_s);
|
||||
}
|
||||
else if(current_ver > latest_ver && !current_ver.prerelease) {
|
||||
_queue.addToast(Toast::Type::Warning,
|
||||
"Your version is more recent than the latest one in the repo. How???"_s);
|
||||
}
|
||||
}
|
||||
|
||||
inline auto writeData(char* ptr, std::size_t size, std::size_t nmemb, Containers::String* buf)-> std::size_t {
|
||||
if(!ptr || !buf) return 0;
|
||||
(*buf) = Utility::format("{}{}", *buf, Containers::StringView{ptr, size * nmemb});
|
||||
return size * nmemb;
|
||||
}
|
||||
|
||||
void SaveTool::checkForUpdates() {
|
||||
SDL_Event event;
|
||||
SDL_zero(event);
|
||||
event.type = _updateEventId;
|
||||
|
||||
auto curl = curl_easy_init();
|
||||
if(!curl) {
|
||||
event.user.code = CurlInitFailed;
|
||||
}
|
||||
|
||||
if(curl) {
|
||||
Containers::String response_body{Containers::AllocatedInit, ""};
|
||||
Containers::String error_buffer{ValueInit, CURL_ERROR_SIZE * 2};
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://williamjcm.ovh/mbst/version");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeData);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_body);
|
||||
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_buffer.data());
|
||||
curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 10000L);
|
||||
|
||||
auto code = curl_easy_perform(curl);
|
||||
|
||||
if(code == CURLE_OK) {
|
||||
long status = 0;
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status);
|
||||
event.user.code = Int(status);
|
||||
event.user.data1 = response_body.release();
|
||||
}
|
||||
else if(code == CURLE_OPERATION_TIMEDOUT) {
|
||||
event.user.code = CurlTimeout;
|
||||
}
|
||||
else {
|
||||
event.user.code = CurlError;
|
||||
event.user.data1 = const_cast<char*>(curl_easy_strerror(code));
|
||||
event.user.data2 = Containers::String{error_buffer}.release();
|
||||
}
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
|
||||
SDL_PushEvent(&event);
|
||||
}
|
|
@ -24,8 +24,6 @@
|
|||
|
||||
#include <zipconf.h>
|
||||
|
||||
#include <curl/curlver.h>
|
||||
|
||||
#include "../FontAwesome/IconsFontAwesome5.h"
|
||||
#include "../FontAwesome/IconsFontAwesome5Brands.h"
|
||||
|
||||
|
@ -33,7 +31,7 @@ extern const ImVec2 center_pivot;
|
|||
|
||||
void SaveTool::drawAbout() {
|
||||
ImGui::SetNextWindowPos(ImVec2{Vector2{windowSize() / 2.0f}}, ImGuiCond_Always, center_pivot);
|
||||
ImGui::SetNextWindowSize({float(windowSize().x()) * 0.8f, float(windowSize().y()) * 0.75f}, ImGuiCond_Always);
|
||||
ImGui::SetNextWindowSize({windowSize().x() * 0.8f, windowSize().y() * 0.75f}, ImGuiCond_Always);
|
||||
|
||||
ImGui::OpenPopup("About##AboutPopup");
|
||||
if(!ImGui::BeginPopupModal("About##AboutPopup", &_aboutPopup,
|
||||
|
@ -59,17 +57,7 @@ void SaveTool::drawAbout() {
|
|||
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).");
|
||||
|
||||
auto website = "https://williamjcm.ovh/coding/mbst";
|
||||
drawAlignedText(ICON_FA_GLOBE " %s", website);
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Button("Copy to clipboard")) {
|
||||
ImGui::SetClipboardText(website);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Button("Open in browser")) {
|
||||
openUri(website);
|
||||
}
|
||||
auto repo = "https://williamjcm.ovh/git/williamjcm/MassBuilderSaveTool";
|
||||
const char* repo = "https://williamjcm.ovh/git/williamjcm/MassBuilderSaveTool";
|
||||
drawAlignedText(ICON_FA_GIT_ALT " %s", repo);
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Button("Copy to clipboard")) {
|
||||
|
@ -85,10 +73,10 @@ void SaveTool::drawAbout() {
|
|||
if(ImGui::CollapsingHeader("Licence")) {
|
||||
ImGui::TextWrapped("This application is made available under the terms of the GNU General Public License, version 3, the full text of which is available below:");
|
||||
|
||||
if(ImGui::BeginChild("##GPL", {0.0f, float(windowSize().y()) * 0.3f}, true)) {
|
||||
static auto licence = _rs.getRaw("COPYING");
|
||||
if(ImGui::BeginChild("##GPL", {0.0f, windowSize().y() * 0.3f}, true)) {
|
||||
static const auto licence = _rs.get("COPYING");
|
||||
ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[1]);
|
||||
ImGui::TextEx(licence.data(), licence.data() + licence.size(), ImGuiTextFlags_None);
|
||||
ImGui::TextUnformatted(licence.c_str());
|
||||
ImGui::PopFont();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
@ -101,7 +89,7 @@ void SaveTool::drawAbout() {
|
|||
|
||||
if(ImGui::TreeNodeEx("Corrade", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
||||
ImGui::Text("Version used: %s", CORRADE_VERSION_STRING);
|
||||
auto corrade_website = "https://magnum.graphics/corrade";
|
||||
const char* corrade_website = "https://magnum.graphics/corrade";
|
||||
drawAlignedText(ICON_FA_GLOBE " %s", corrade_website);
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Button("Copy to clipboard")) {
|
||||
|
@ -114,10 +102,10 @@ void SaveTool::drawAbout() {
|
|||
|
||||
ImGui::TextUnformatted("Licence: MIT");
|
||||
|
||||
static auto corrade_licence = _rs.getRaw("COPYING.Corrade");
|
||||
if(ImGui::BeginChild("##CorradeLicence", {0.0f, float(windowSize().y()) * 0.3f}, true)) {
|
||||
static const auto corrade_licence = _rs.get("COPYING.Corrade");
|
||||
if(ImGui::BeginChild("##CorradeLicence", {0.0f, windowSize().y() * 0.3f}, true)) {
|
||||
ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[1]);
|
||||
ImGui::TextEx(corrade_licence.data(), corrade_licence.data() + corrade_licence.size(), ImGuiTextFlags_None);
|
||||
ImGui::TextUnformatted(corrade_licence.c_str());
|
||||
ImGui::PopFont();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
@ -129,7 +117,7 @@ void SaveTool::drawAbout() {
|
|||
ImGui::TextUnformatted("Versions used:");
|
||||
ImGui::BulletText("Magnum: %s", MAGNUM_VERSION_STRING);
|
||||
ImGui::BulletText("Integration: %s", MAGNUMINTEGRATION_VERSION_STRING);
|
||||
auto magnum_website = "https://magnum.graphics";
|
||||
const char* magnum_website = "https://magnum.graphics";
|
||||
drawAlignedText(ICON_FA_GLOBE " %s", magnum_website);
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Button("Copy to clipboard")) {
|
||||
|
@ -142,10 +130,10 @@ void SaveTool::drawAbout() {
|
|||
|
||||
ImGui::TextUnformatted("Licence: MIT");
|
||||
|
||||
static auto magnum_licence = _rs.getRaw("COPYING.Magnum");
|
||||
if(ImGui::BeginChild("##MagnumLicence", {0.0f, float(windowSize().y()) * 0.3f}, true)) {
|
||||
static const auto magnum_licence = _rs.get("COPYING.Magnum");
|
||||
if(ImGui::BeginChild("##MagnumLicence", {0.0f, windowSize().y() * 0.3f}, true)) {
|
||||
ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[1]);
|
||||
ImGui::TextEx(magnum_licence.data(), magnum_licence.data() + magnum_licence.size(), ImGuiTextFlags_None);
|
||||
ImGui::TextUnformatted(magnum_licence.c_str());
|
||||
ImGui::PopFont();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
@ -155,7 +143,7 @@ void SaveTool::drawAbout() {
|
|||
|
||||
if(ImGui::TreeNodeEx("Dear ImGui", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
||||
ImGui::Text("Version used: %s", IMGUI_VERSION);
|
||||
auto imgui_repo = "https://github.com/ocornut/imgui";
|
||||
const char* imgui_repo = "https://github.com/ocornut/imgui";
|
||||
drawAlignedText(ICON_FA_GITHUB " %s", imgui_repo);
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Button("Copy to clipboard")) {
|
||||
|
@ -168,10 +156,10 @@ void SaveTool::drawAbout() {
|
|||
|
||||
ImGui::TextUnformatted("Licence: MIT");
|
||||
|
||||
static auto imgui_licence = _rs.getRaw("LICENSE.ImGui");
|
||||
if(ImGui::BeginChild("##ImGuiLicence", {0.0f, float(windowSize().y()) * 0.3f}, true)) {
|
||||
static const auto imgui_licence = _rs.get("LICENSE.ImGui");
|
||||
if(ImGui::BeginChild("##ImGuiLicence", {0.0f, windowSize().y() * 0.3f}, true)) {
|
||||
ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[1]);
|
||||
ImGui::TextEx(imgui_licence.data(), imgui_licence.data() + imgui_licence.size(), ImGuiTextFlags_None);
|
||||
ImGui::TextUnformatted(imgui_licence.c_str());
|
||||
ImGui::PopFont();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
@ -181,7 +169,7 @@ void SaveTool::drawAbout() {
|
|||
|
||||
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);
|
||||
auto sdl_website = "https://www.libsdl.org/";
|
||||
const char* sdl_website = "https://www.libsdl.org/";
|
||||
drawAlignedText(ICON_FA_GLOBE " %s", sdl_website);
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Button("Copy to clipboard")) {
|
||||
|
@ -194,10 +182,10 @@ void SaveTool::drawAbout() {
|
|||
|
||||
ImGui::TextUnformatted("Licence: zlib");
|
||||
|
||||
static auto sdl_licence = _rs.getRaw("LICENSE.SDL");
|
||||
if(ImGui::BeginChild("##SDLLicence", {0.0f, float(windowSize().y()) * 0.3f}, true)) {
|
||||
static const auto sdl_licence = _rs.get("LICENSE.SDL");
|
||||
if(ImGui::BeginChild("##SDLLicence", {0.0f, windowSize().y() * 0.3f}, true)) {
|
||||
ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[1]);
|
||||
ImGui::TextEx(sdl_licence.data(), sdl_licence.data() + sdl_licence.size(), ImGuiTextFlags_None);
|
||||
ImGui::TextUnformatted(sdl_licence.c_str());
|
||||
ImGui::PopFont();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
@ -207,7 +195,7 @@ void SaveTool::drawAbout() {
|
|||
|
||||
if(ImGui::TreeNodeEx("libzip", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
||||
ImGui::Text("Version used: %s", LIBZIP_VERSION);
|
||||
auto libzip_website = "https://libzip.org/";
|
||||
const char* libzip_website = "https://libzip.org/";
|
||||
drawAlignedText(ICON_FA_GLOBE " %s", libzip_website);
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Button("Copy to clipboard")) {
|
||||
|
@ -220,10 +208,10 @@ void SaveTool::drawAbout() {
|
|||
|
||||
ImGui::TextUnformatted("Licence: 3-clause BSD");
|
||||
|
||||
static auto libzip_licence = _rs.getRaw("LICENSE.libzip");
|
||||
if(ImGui::BeginChild("##libzipLicence", {0.0f, float(windowSize().y()) * 0.3f}, true)) {
|
||||
static const auto libzip_licence = _rs.get("LICENSE.libzip");
|
||||
if(ImGui::BeginChild("##libzipLicence", {0.0f, windowSize().y() * 0.3f}, true)) {
|
||||
ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[1]);
|
||||
ImGui::TextEx(libzip_licence.data(), libzip_licence.data() + libzip_licence.size(), ImGuiTextFlags_None);
|
||||
ImGui::TextUnformatted(libzip_licence.c_str());
|
||||
ImGui::PopFont();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
@ -232,7 +220,7 @@ void SaveTool::drawAbout() {
|
|||
}
|
||||
|
||||
if(ImGui::TreeNodeEx("Entropia File System Watcher (efsw)", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
||||
auto efsw_repo = "https://github.com/SpartanJ/efsw";
|
||||
const char* efsw_repo = "https://github.com/SpartanJ/efsw";
|
||||
drawAlignedText(ICON_FA_GITHUB " %s", efsw_repo);
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Button("Copy to clipboard")) {
|
||||
|
@ -245,10 +233,10 @@ void SaveTool::drawAbout() {
|
|||
|
||||
ImGui::TextUnformatted("Licence: MIT");
|
||||
|
||||
static auto efsw_licence = _rs.getRaw("LICENSE.efsw");
|
||||
if(ImGui::BeginChild("##efswLicence", {0.0f, float(windowSize().y()) * 0.3f}, true)) {
|
||||
static const auto efsw_licence = _rs.get("LICENSE.efsw");
|
||||
if(ImGui::BeginChild("##efswLicence", {0.0f, windowSize().y() * 0.3f}, true)) {
|
||||
ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[1]);
|
||||
ImGui::TextEx(efsw_licence.data(), efsw_licence.data() + efsw_licence.size(), ImGuiTextFlags_None);
|
||||
ImGui::TextUnformatted(efsw_licence.c_str());
|
||||
ImGui::PopFont();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
@ -256,25 +244,49 @@ void SaveTool::drawAbout() {
|
|||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
if(ImGui::TreeNodeEx("libcurl", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
||||
ImGui::Text("Version used: %s", LIBCURL_VERSION);
|
||||
auto curl_website = "https://curl.se/libcurl";
|
||||
drawAlignedText(ICON_FA_GLOBE " %s", curl_website);
|
||||
if(ImGui::TreeNodeEx("C++ Requests (cpr)", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
||||
const char* cpr_website = "https://whoshuu.github.io/cpr/";
|
||||
drawAlignedText(ICON_FA_GLOBE " %s", cpr_website);
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Button("Copy to clipboard")) {
|
||||
ImGui::SetClipboardText(curl_website);
|
||||
ImGui::SetClipboardText(cpr_website);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Button("Open in browser")) {
|
||||
openUri(curl_website);
|
||||
openUri(cpr_website);
|
||||
}
|
||||
|
||||
ImGui::TextUnformatted("Licence: MIT/X derivative");
|
||||
ImGui::TextUnformatted("Licence: MIT");
|
||||
|
||||
static auto curl_licence = _rs.getRaw("LICENSE.curl");
|
||||
if(ImGui::BeginChild("##libcurlLicence", {0.0f, float(windowSize().y()) * 0.3f}, true)) {
|
||||
static const auto cpr_licence = _rs.get("LICENSE.cpr");
|
||||
if(ImGui::BeginChild("##cprLicence", {0.0f, windowSize().y() * 0.3f}, true)) {
|
||||
ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[1]);
|
||||
ImGui::TextEx(curl_licence.data(), curl_licence.data() + curl_licence.size(), ImGuiTextFlags_None);
|
||||
ImGui::TextUnformatted(cpr_licence.c_str());
|
||||
ImGui::PopFont();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
if(ImGui::TreeNodeEx("JSON for Modern C++ (aka json.hpp)", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
||||
const char* json_website = "https://json.nlohmann.me/";
|
||||
drawAlignedText(ICON_FA_GLOBE " %s", json_website);
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Button("Copy to clipboard")) {
|
||||
ImGui::SetClipboardText(json_website);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Button("Open in browser")) {
|
||||
openUri(json_website);
|
||||
}
|
||||
|
||||
ImGui::TextUnformatted("Licence: MIT");
|
||||
|
||||
static const auto json_licence = _rs.get("LICENSE.json");
|
||||
if(ImGui::BeginChild("##jsonLicence", {0.0f, windowSize().y() * 0.3f}, true)) {
|
||||
ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[1]);
|
||||
ImGui::TextUnformatted(json_licence.c_str());
|
||||
ImGui::PopFont();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
@ -284,7 +296,7 @@ void SaveTool::drawAbout() {
|
|||
|
||||
if(ImGui::TreeNodeEx("Font Awesome", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
||||
ImGui::TextUnformatted("Version used: 5.15.3");
|
||||
auto fa_website = "https://fontawesome.com/";
|
||||
const char* fa_website = "https://fontawesome.com/";
|
||||
drawAlignedText(ICON_FA_GLOBE " %s", fa_website);
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Button("Copy to clipboard")) {
|
||||
|
@ -301,7 +313,7 @@ void SaveTool::drawAbout() {
|
|||
}
|
||||
|
||||
if(ImGui::TreeNodeEx("IconFontCppHeaders", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
||||
auto icon_repo = "https://github.com/juliettef/IconFontCppHeaders";
|
||||
const char* icon_repo = "https://github.com/juliettef/IconFontCppHeaders";
|
||||
drawAlignedText(ICON_FA_GITHUB " %s", icon_repo);
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Button("Copy to clipboard")) {
|
||||
|
|
|
@ -14,39 +14,39 @@
|
|||
// 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/Path.h>
|
||||
#include "SaveTool.h"
|
||||
|
||||
#include <Corrade/Utility/Directory.h>
|
||||
|
||||
#include "../FontAwesome/IconsFontAwesome5.h"
|
||||
#include "../FontAwesome/IconsFontAwesome5Brands.h"
|
||||
|
||||
#include "SaveTool.h"
|
||||
|
||||
void SaveTool::drawMainMenu() {
|
||||
if(ImGui::BeginMainMenuBar()) {
|
||||
if(ImGui::BeginMenu("Save Tool##SaveToolMenu")) {
|
||||
if(ImGui::BeginMenu(ICON_FA_FOLDER_OPEN " Open game data directory", Utility::Path::exists(_gameDataDir))) {
|
||||
if(ImGui::MenuItem(ICON_FA_COG " Configuration", nullptr, false, Utility::Path::exists(_configDir))) {
|
||||
openUri(Utility::Path::toNativeSeparators(_configDir));
|
||||
if(ImGui::BeginMenu(ICON_FA_FOLDER_OPEN " Open game data directory", Utility::Directory::exists(_gameDataDir))) {
|
||||
if(ImGui::MenuItem(ICON_FA_COG " Configuration", nullptr, false, Utility::Directory::exists(_configDir))) {
|
||||
openUri(Utility::Directory::toNativeSeparators(_configDir));
|
||||
}
|
||||
|
||||
if(ImGui::MenuItem(ICON_FA_SAVE " Saves", nullptr, false, Utility::Path::exists(_saveDir))) {
|
||||
openUri(Utility::Path::toNativeSeparators(_saveDir));
|
||||
if(ImGui::MenuItem(ICON_FA_SAVE " Saves", nullptr, false, Utility::Directory::exists(_saveDir))) {
|
||||
openUri(Utility::Directory::toNativeSeparators(_saveDir));
|
||||
}
|
||||
|
||||
if(ImGui::MenuItem(ICON_FA_IMAGE " Screenshots", nullptr, false, Utility::Path::exists(_screenshotsDir))) {
|
||||
openUri(Utility::Path::toNativeSeparators(_screenshotsDir));
|
||||
if(ImGui::MenuItem(ICON_FA_IMAGE " Screenshots", nullptr, false, Utility::Directory::exists(_screenshotsDir))) {
|
||||
openUri(Utility::Directory::toNativeSeparators(_screenshotsDir));
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if(ImGui::BeginMenu(ICON_FA_FOLDER_OPEN " Open manager directory")) {
|
||||
if(ImGui::MenuItem(ICON_FA_FILE_ARCHIVE " Profile backups", nullptr, false, Utility::Path::exists(_backupsDir))) {
|
||||
openUri(Utility::Path::toNativeSeparators(_backupsDir));
|
||||
if(ImGui::MenuItem(ICON_FA_FILE_ARCHIVE " Profile backups", nullptr, false, Utility::Directory::exists(_backupsDir))) {
|
||||
openUri(Utility::Directory::toNativeSeparators(_backupsDir));
|
||||
}
|
||||
|
||||
if(ImGui::MenuItem(ICON_FA_EXCHANGE_ALT " Staging area", nullptr, false, Utility::Path::exists(_stagingDir))) {
|
||||
openUri(Utility::Path::toNativeSeparators(_stagingDir));
|
||||
if(ImGui::MenuItem(ICON_FA_EXCHANGE_ALT " Staging area", nullptr, false, Utility::Directory::exists(_stagingDir))) {
|
||||
openUri(Utility::Directory::toNativeSeparators(_stagingDir));
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
|
@ -55,59 +55,58 @@ void SaveTool::drawMainMenu() {
|
|||
ImGui::Separator();
|
||||
|
||||
if(ImGui::BeginMenu(ICON_FA_COG " Settings")) {
|
||||
ImGui::BeginGroup();
|
||||
drawAlignedText("Vertical sync:");
|
||||
if(_swapInterval == 0) {
|
||||
drawAlignedText("FPS cap:");
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
|
||||
drawAlignedText("Frame limiter:");
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::BeginGroup();
|
||||
|
||||
static const char* framelimit_labels[] = {
|
||||
"Off",
|
||||
"Every VBLANK",
|
||||
"Every second VBLANK",
|
||||
"Every third VBLANK",
|
||||
static UnsignedByte selection = static_cast<UnsignedByte>(_framelimit);
|
||||
static const char* framelimit_labels[3] = {
|
||||
"V-sync",
|
||||
"Half V-sync",
|
||||
"FPS cap, no V-sync"
|
||||
};
|
||||
|
||||
ImGui::PushItemWidth(300.0f);
|
||||
|
||||
if(ImGui::BeginCombo("##FrameLimit", framelimit_labels[_swapInterval])) {
|
||||
for(int i = 0; i <= 3; i++) {
|
||||
if(ImGui::Selectable(framelimit_labels[i], _swapInterval == i)) {
|
||||
_swapInterval = i;
|
||||
setSwapInterval(i);
|
||||
if(i == 0) {
|
||||
setMinimalLoopPeriod(0);
|
||||
}
|
||||
}
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvailWidth());
|
||||
if(ImGui::BeginCombo("##FrameLimit", framelimit_labels[selection])) {
|
||||
if(ImGui::Selectable(framelimit_labels[0], _framelimit == Framelimit::Vsync)) {
|
||||
selection = 0;
|
||||
_framelimit = Framelimit::Vsync;
|
||||
setSwapInterval(1);
|
||||
}
|
||||
if(ImGui::Selectable(framelimit_labels[1], _framelimit == Framelimit::HalfVsync)) {
|
||||
selection = 1;
|
||||
_framelimit = Framelimit::HalfVsync;
|
||||
setSwapInterval(2);
|
||||
}
|
||||
if(ImGui::Selectable(framelimit_labels[2], _framelimit == Framelimit::FpsCap)) {
|
||||
selection = 2;
|
||||
_framelimit = Framelimit::FpsCap;
|
||||
setSwapInterval(0);
|
||||
setMinimalLoopPeriod(1000 / _fpsCap);
|
||||
}
|
||||
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
if(_swapInterval == 0) {
|
||||
ImGui::SliderFloat("##FpsCapSlider", &_fpsCap, 15.0f, 301.0f,
|
||||
_fpsCap != 301.0f ? "%.0f" : "Uncapped", ImGuiSliderFlags_AlwaysClamp);
|
||||
if(_framelimit == Framelimit::FpsCap) {
|
||||
static constexpr UnsignedInt min_fps = 15;
|
||||
static constexpr UnsignedInt max_fps = 150;
|
||||
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvailWidth());
|
||||
if(ImGui::SliderScalar("##FpsSlider", ImGuiDataType_U32, &_fpsCap, &min_fps, &max_fps, "%u FPS", ImGuiSliderFlags_AlwaysClamp)) {
|
||||
setMinimalLoopPeriod(1000 / _fpsCap);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::Checkbox("Cheat mode", &_cheatMode);
|
||||
ImGui::SameLine();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
drawHelpMarker("This gives access to save edition features that can be considered cheats.",
|
||||
Float(windowSize().x()) * 0.4f);
|
||||
|
||||
ImGui::Checkbox("Advanced mode", &_advancedMode);
|
||||
ImGui::Checkbox("Unsafe mode", &_unsafeMode);
|
||||
ImGui::SameLine();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
drawHelpMarker("This gives access to editing values that have unknown purposes or are undocumented.",
|
||||
drawHelpMarker("This allows changing the state of save files in the game's save folder even when the game is running.",
|
||||
Float(windowSize().x()) * 0.4f);
|
||||
|
||||
ImGui::Checkbox("Check for updates on startup", &_checkUpdatesOnStartup);
|
||||
|
@ -118,7 +117,7 @@ void SaveTool::drawMainMenu() {
|
|||
}
|
||||
|
||||
if(_updateAvailable) {
|
||||
drawAlignedText("Version %s is available.", _latestVersion.data());
|
||||
drawAlignedText("Version %s is available.", _latestVersion.c_str());
|
||||
if(ImGui::Button(ICON_FA_FILE_SIGNATURE " Release notes")) {
|
||||
openUri(_releaseLink);
|
||||
}
|
||||
|
@ -156,11 +155,11 @@ void SaveTool::drawMainMenu() {
|
|||
|
||||
if(ImGui::BeginMenu(ICON_FA_DISCORD " Discord communities")) {
|
||||
if(ImGui::MenuItem("Official server")) {
|
||||
openUri("https://discord.gg/sekai-project");
|
||||
openUri("https://discord.gg/quS7E46");
|
||||
}
|
||||
|
||||
if(ImGui::MenuItem("Community server")) {
|
||||
openUri("https://discord.gg/massbuildercommunity");
|
||||
openUri("https://discord.gg/YSSRTRB");
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
|
@ -169,7 +168,7 @@ void SaveTool::drawMainMenu() {
|
|||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
#ifdef SAVETOOL_DEBUG_BUILD
|
||||
#ifdef SAVETOOL_DEBUG_BUILD
|
||||
if(ImGui::BeginMenu("Debug tools")) {
|
||||
ImGui::MenuItem("ImGui demo window", nullptr, &_demoWindow);
|
||||
ImGui::MenuItem("ImGui style editor", nullptr, &_styleEditor);
|
||||
|
@ -177,10 +176,10 @@ void SaveTool::drawMainMenu() {
|
|||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if(ImGui::BeginMenu("Help")) {
|
||||
if(ImGui::BeginMenu(ICON_FA_KEYBOARD " Keyboard shortcuts")) {
|
||||
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");
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
// 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/Format.h>
|
||||
#include <Corrade/Utility/FormatStl.h>
|
||||
|
||||
#include <Magnum/Math/Functions.h>
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
|||
|
||||
#include "ToastQueue.h"
|
||||
|
||||
using namespace Containers::Literals;
|
||||
using namespace Corrade;
|
||||
|
||||
constexpr UnsignedInt success_colour = 0xff67d23bu;
|
||||
constexpr UnsignedInt info_colour = 0xffcc832fu;
|
||||
|
@ -36,7 +36,7 @@ constexpr Float base_opacity = 1.0f;
|
|||
constexpr Vector2 padding{20.0f, 20.0f};
|
||||
constexpr Float toast_spacing = 10.0f;
|
||||
|
||||
Toast::Toast(Type type, Containers::StringView message, std::chrono::milliseconds timeout):
|
||||
Toast::Toast(Type type, const std::string& message, std::chrono::milliseconds timeout):
|
||||
_type{type}, _message{message}, _timeout{timeout}, _creationTime{std::chrono::steady_clock::now()}
|
||||
{
|
||||
_phaseTrack = Animation::Track<UnsignedInt, Phase>{{
|
||||
|
@ -51,7 +51,7 @@ auto Toast::type() -> Type {
|
|||
return _type;
|
||||
}
|
||||
|
||||
auto Toast::message() -> Containers::StringView {
|
||||
auto Toast::message() -> const std::string& {
|
||||
return _message;
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ void ToastQueue::addToast(Toast&& toast) {
|
|||
_toasts.push_back(std::move(toast));
|
||||
}
|
||||
|
||||
void ToastQueue::addToast(Toast::Type type, Containers::StringView message, std::chrono::milliseconds timeout) {
|
||||
void ToastQueue::addToast(Toast::Type type, const std::string& message, std::chrono::milliseconds timeout) {
|
||||
_toasts.emplace_back(type, message, timeout);
|
||||
}
|
||||
|
||||
|
@ -104,14 +104,14 @@ void ToastQueue::draw(Vector2i viewport_size) {
|
|||
continue;
|
||||
}
|
||||
|
||||
Containers::String win_id = Utility::format("##Toast{}", i);
|
||||
std::string win_id = Utility::formatString("##Toast{}", i);
|
||||
|
||||
Float opacity = base_opacity * current->opacity();
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, opacity);
|
||||
|
||||
ImGui::SetNextWindowPos({viewport_size.x() - padding.x(), viewport_size.y() - padding.y() - height}, ImGuiCond_Always, {1.0f, 1.0f});
|
||||
if(ImGui::Begin(win_id.data(), nullptr,
|
||||
if(ImGui::Begin(win_id.c_str(), nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoDecoration|
|
||||
ImGuiWindowFlags_NoInputs|ImGuiWindowFlags_NoNav|ImGuiWindowFlags_NoFocusOnAppearing))
|
||||
{
|
||||
|
@ -142,9 +142,12 @@ void ToastQueue::draw(Vector2i viewport_size) {
|
|||
ImGui::SameLine();
|
||||
}
|
||||
|
||||
ImGui::PushTextWrapPos(500.0f);
|
||||
ImGui::TextColored(colour, current->message().data());
|
||||
ImGui::PopTextWrapPos();
|
||||
if(current->message().length() > 127) {
|
||||
ImGui::TextColored(colour, "%.*s...", 127, current->message().c_str());
|
||||
}
|
||||
else {
|
||||
ImGui::TextColored(colour, current->message().c_str());
|
||||
}
|
||||
|
||||
height += ImGui::GetWindowHeight() + toast_spacing;
|
||||
}
|
||||
|
|
|
@ -17,14 +17,12 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <Corrade/Containers/String.h>
|
||||
|
||||
#include <Magnum/Magnum.h>
|
||||
#include <Magnum/Animation/Track.h>
|
||||
|
||||
using namespace Corrade;
|
||||
using namespace Magnum;
|
||||
|
||||
class Toast {
|
||||
|
@ -37,7 +35,7 @@ class Toast {
|
|||
FadeIn, Wait, FadeOut, TimedOut
|
||||
};
|
||||
|
||||
explicit Toast(Type type, Containers::StringView message,
|
||||
explicit Toast(Type type, const std::string& message,
|
||||
std::chrono::milliseconds timeout = std::chrono::milliseconds{3000});
|
||||
|
||||
Toast(const Toast& other) = delete;
|
||||
|
@ -48,7 +46,7 @@ class Toast {
|
|||
|
||||
auto type() -> Type;
|
||||
|
||||
auto message() -> Containers::StringView;
|
||||
auto message() -> std::string const&;
|
||||
|
||||
auto timeout() -> std::chrono::milliseconds;
|
||||
|
||||
|
@ -62,7 +60,7 @@ class Toast {
|
|||
|
||||
private:
|
||||
Type _type{Type::Default};
|
||||
Containers::String _message;
|
||||
std::string _message;
|
||||
std::chrono::milliseconds _timeout;
|
||||
std::chrono::steady_clock::time_point _creationTime;
|
||||
Animation::Track<UnsignedInt, Phase> _phaseTrack;
|
||||
|
@ -72,7 +70,7 @@ class ToastQueue {
|
|||
public:
|
||||
void addToast(Toast&& toast);
|
||||
|
||||
void addToast(Toast::Type type, Containers::StringView message,
|
||||
void addToast(Toast::Type type, const std::string& message,
|
||||
std::chrono::milliseconds timeout = std::chrono::milliseconds{3000});
|
||||
|
||||
void draw(Vector2i viewport_size);
|
||||
|
|
|
@ -16,18 +16,16 @@
|
|||
|
||||
#include <cstring>
|
||||
|
||||
#include <Corrade/Containers/Array.h>
|
||||
#include <Corrade/Containers/String.h>
|
||||
|
||||
#include "../Logger/Logger.h"
|
||||
#include <string>
|
||||
|
||||
#include "BinaryReader.h"
|
||||
|
||||
BinaryReader::BinaryReader(Containers::StringView filename) {
|
||||
_file = std::fopen(filename.data(), "rb");
|
||||
BinaryReader::BinaryReader(const std::string& filename) {
|
||||
_file = std::fopen(filename.c_str(), "rb");
|
||||
|
||||
if(!_file) {
|
||||
LOG_ERROR_FORMAT("Couldn't open {} for reading: {}", filename, std::strerror(errno));
|
||||
Utility::Error{} << "Couldn't open" << filename.c_str() << "for reading:\n"
|
||||
<< std::strerror(errno);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,15 +106,16 @@ auto BinaryReader::readArray(Containers::Array<char>& array, std::size_t count)
|
|||
return std::fread(array.data(), sizeof(char), count, _file) == count;
|
||||
}
|
||||
|
||||
auto BinaryReader::readUEString(Containers::String& str) -> bool {
|
||||
auto BinaryReader::readUEString(std::string& str) -> bool {
|
||||
UnsignedInt length = 0;
|
||||
if(!readUnsignedInt(length) || length == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
str = Containers::String{ValueInit, length - 1};
|
||||
str = std::string{};
|
||||
str.resize(length - 1);
|
||||
|
||||
return std::fread(str.data(), sizeof(char), length, _file) == length;
|
||||
return std::fread(&str[0], sizeof(char), length, _file) == length;
|
||||
}
|
||||
|
||||
auto BinaryReader::peekChar() -> Int {
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
|
||||
#include <cstdio>
|
||||
|
||||
#include <Corrade/Containers/Containers.h>
|
||||
#include <Corrade/Containers/Array.h>
|
||||
#include <Corrade/Containers/StaticArray.h>
|
||||
#include <Corrade/Containers/StringView.h>
|
||||
#include <Corrade/Utility/StlForwardString.h>
|
||||
|
||||
#include <Magnum/Types.h>
|
||||
|
||||
|
@ -29,7 +29,7 @@ using namespace Magnum;
|
|||
|
||||
class BinaryReader {
|
||||
public:
|
||||
explicit BinaryReader(Containers::StringView filename);
|
||||
explicit BinaryReader(const std::string& filename);
|
||||
~BinaryReader();
|
||||
|
||||
auto open() -> bool;
|
||||
|
@ -63,7 +63,7 @@ class BinaryReader {
|
|||
return std::fread(array.data(), sizeof(char), S, _file) == S;
|
||||
}
|
||||
|
||||
auto readUEString(Containers::String& str) -> bool;
|
||||
auto readUEString(std::string& str) -> bool;
|
||||
|
||||
auto peekChar() -> Int;
|
||||
|
||||
|
|
|
@ -16,16 +16,15 @@
|
|||
|
||||
#include <cstring>
|
||||
|
||||
#include "../Logger/Logger.h"
|
||||
#include <string>
|
||||
|
||||
#include "BinaryWriter.h"
|
||||
|
||||
using namespace Containers::Literals;
|
||||
|
||||
BinaryWriter::BinaryWriter(Containers::StringView filename) {
|
||||
_file = std::fopen(filename.data(), "wb");
|
||||
BinaryWriter::BinaryWriter(const std::string& filename) {
|
||||
_file = std::fopen(filename.c_str(), "wb");
|
||||
if(!_file) {
|
||||
LOG_ERROR_FORMAT("Couldn't open {} for reading: {}", filename, std::strerror(errno));
|
||||
Utility::Error{} << "Couldn't open" << filename.c_str() << "for reading:\n"
|
||||
<< std::strerror(errno);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,25 +114,24 @@ auto BinaryWriter::writeArray(Containers::ArrayView<const char> array) -> bool {
|
|||
return std::fwrite(array.data(), sizeof(char), array.size(), _file) == array.size();
|
||||
}
|
||||
|
||||
auto BinaryWriter::writeUEString(Containers::StringView str) -> bool {
|
||||
if(str.size() > UINT32_MAX) {
|
||||
LOG_ERROR_FORMAT("String is too big. Expected size() < UINT32_MAX, got {} instead.", str.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.size()) + 1);
|
||||
writeUnsignedInt(static_cast<UnsignedInt>(str.length()) + 1);
|
||||
|
||||
if(str.size() > 0) {
|
||||
std::size_t count = std::fwrite(str.data(), sizeof(char), str.size(), _file);
|
||||
if(count != str.size()) {
|
||||
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(Containers::StringView value) -> UnsignedLong {
|
||||
return writeValueToArray<UnsignedInt>(UnsignedInt(value.size()) + 1u) +
|
||||
writeDataToArray(Containers::ArrayView<const char>{value}) +
|
||||
writeValueToArray<char>('\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');
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include <Corrade/Containers/ArrayView.h>
|
||||
#include <Corrade/Containers/GrowableArray.h>
|
||||
#include <Corrade/Containers/StaticArray.h>
|
||||
#include <Corrade/Containers/StringView.h>
|
||||
#include <Corrade/Utility/StlForwardString.h>
|
||||
|
||||
#include <Magnum/Types.h>
|
||||
|
||||
|
@ -30,7 +30,7 @@ using namespace Magnum;
|
|||
|
||||
class BinaryWriter {
|
||||
public:
|
||||
explicit BinaryWriter(Containers::StringView filename);
|
||||
explicit BinaryWriter(const std::string& filename);
|
||||
~BinaryWriter();
|
||||
|
||||
BinaryWriter(const BinaryWriter& other) = delete;
|
||||
|
@ -71,7 +71,7 @@ class BinaryWriter {
|
|||
return std::fwrite(array.data(), sizeof(char), S, _file) == S;
|
||||
}
|
||||
|
||||
auto writeUEString(Containers::StringView str) -> bool;
|
||||
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 {
|
||||
|
@ -79,7 +79,7 @@ class BinaryWriter {
|
|||
return writeDataToArray(view);
|
||||
}
|
||||
|
||||
auto writeUEStringToArray(Containers::StringView value) -> UnsignedLong;
|
||||
auto writeUEStringToArray(const std::string& value) -> UnsignedLong;
|
||||
|
||||
template<typename T>
|
||||
void writeValueToArrayAt(T& value, UnsignedLong position) {
|
||||
|
|
|
@ -23,18 +23,18 @@
|
|||
#include "Debug.h"
|
||||
|
||||
Utility::Debug& operator<<(Utility::Debug& debug, const ArrayProperty* prop) {
|
||||
return debug << (*prop->name) << Utility::Debug::nospace << ":" <<
|
||||
prop->propertyType << "of" << prop->items.size() << prop->itemType;
|
||||
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) << Utility::Debug::nospace << ":" <<
|
||||
prop->propertyType << "of" << prop->items.size() << prop->itemType;
|
||||
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) << Utility::Debug::nospace << ":" <<
|
||||
prop->structType << "(" << Utility::Debug::nospace << prop->propertyType << Utility::Debug::nospace <<
|
||||
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();
|
||||
|
@ -48,8 +48,8 @@ Utility::Debug& operator<<(Utility::Debug& debug, const StructProperty* prop) {
|
|||
return debug << cast;
|
||||
}
|
||||
|
||||
return debug << (*prop->name) << Utility::Debug::nospace << ":" <<
|
||||
prop->structType << "(" << Utility::Debug::nospace << prop->propertyType << Utility::Debug::nospace << ")";
|
||||
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) {
|
||||
|
@ -72,5 +72,5 @@ Utility::Debug& operator<<(Utility::Debug& debug, const UnrealPropertyBase* prop
|
|||
}
|
||||
}
|
||||
|
||||
return debug << (*prop->name) << Utility::Debug::nospace << ":" << prop->propertyType;
|
||||
return debug << (*prop->name).c_str() << Utility::Debug::nospace << ":" << prop->propertyType.c_str();
|
||||
}
|
||||
|
|
|
@ -40,10 +40,9 @@
|
|||
#include "BinaryReader.h"
|
||||
#include "BinaryWriter.h"
|
||||
|
||||
#include "../Logger/Logger.h"
|
||||
|
||||
#include "PropertySerialiser.h"
|
||||
|
||||
|
||||
PropertySerialiser::PropertySerialiser() {
|
||||
arrayAppend(_serialisers, Containers::pointer<ArrayPropertySerialiser>());
|
||||
arrayAppend(_serialisers, Containers::pointer<BoolPropertySerialiser>());
|
||||
|
@ -67,17 +66,12 @@ PropertySerialiser::PropertySerialiser() {
|
|||
arrayAppend(_collectionSerialisers, Containers::pointer<StructSerialiser>());
|
||||
}
|
||||
|
||||
auto PropertySerialiser::instance() -> PropertySerialiser& {
|
||||
static PropertySerialiser serialiser;
|
||||
return serialiser;
|
||||
}
|
||||
|
||||
auto PropertySerialiser::read(BinaryReader& reader) -> UnrealPropertyBase::ptr {
|
||||
if(reader.peekChar() < 0 || reader.eof()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Containers::String name;
|
||||
std::string name;
|
||||
if(!reader.readUEString(name)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -86,7 +80,7 @@ auto PropertySerialiser::read(BinaryReader& reader) -> UnrealPropertyBase::ptr {
|
|||
return Containers::pointer<NoneProperty>();
|
||||
}
|
||||
|
||||
Containers::String type;
|
||||
std::string type;
|
||||
if(!reader.readUEString(type)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -99,8 +93,7 @@ auto PropertySerialiser::read(BinaryReader& reader) -> UnrealPropertyBase::ptr {
|
|||
return deserialise(std::move(name), std::move(type), value_length, reader);
|
||||
}
|
||||
|
||||
auto PropertySerialiser::readItem(BinaryReader& reader, Containers::String type, UnsignedLong value_length,
|
||||
Containers::String name) -> UnrealPropertyBase::ptr {
|
||||
auto PropertySerialiser::readItem(BinaryReader& reader, std::string type, UnsignedLong value_length, std::string name) -> UnrealPropertyBase::ptr {
|
||||
if(reader.peekChar() < 0 || reader.eof()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -108,9 +101,7 @@ auto PropertySerialiser::readItem(BinaryReader& reader, Containers::String type,
|
|||
return deserialise(std::move(name), std::move(type), value_length, reader);
|
||||
}
|
||||
|
||||
auto PropertySerialiser::readSet(BinaryReader& reader, Containers::StringView item_type,
|
||||
UnsignedInt count) -> Containers::Array<UnrealPropertyBase::ptr>
|
||||
{
|
||||
auto PropertySerialiser::readSet(BinaryReader& reader, const std::string& item_type, UnsignedInt count) -> Containers::Array<UnrealPropertyBase::ptr> {
|
||||
if(reader.peekChar() < 0 || reader.eof()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -120,12 +111,12 @@ auto PropertySerialiser::readSet(BinaryReader& reader, Containers::StringView it
|
|||
Containers::Array<UnrealPropertyBase::ptr> array;
|
||||
|
||||
if(serialiser) {
|
||||
Containers::String name;
|
||||
std::string name;
|
||||
if(!reader.readUEString(name)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Containers::String type;
|
||||
std::string type;
|
||||
if(!reader.readUEString(type)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -153,7 +144,7 @@ auto PropertySerialiser::readSet(BinaryReader& reader, Containers::StringView it
|
|||
return array;
|
||||
}
|
||||
|
||||
auto PropertySerialiser::deserialise(Containers::String name, Containers::String type, UnsignedLong value_length,
|
||||
auto PropertySerialiser::deserialise(std::string name, std::string type, UnsignedLong value_length,
|
||||
BinaryReader& reader) -> UnrealPropertyBase::ptr
|
||||
{
|
||||
UnrealPropertyBase::ptr prop;
|
||||
|
@ -166,7 +157,7 @@ auto PropertySerialiser::deserialise(Containers::String name, Containers::String
|
|||
prop = serialiser->deserialise(name, type, value_length, reader, *this);
|
||||
|
||||
if(!prop) {
|
||||
LOG_ERROR("No property.");
|
||||
!Utility::Error{} << "No prop in" << __func__;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -176,8 +167,8 @@ auto PropertySerialiser::deserialise(Containers::String name, Containers::String
|
|||
return prop;
|
||||
}
|
||||
|
||||
auto PropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, Containers::StringView item_type,
|
||||
UnsignedLong& bytes_written, BinaryWriter& writer) -> bool
|
||||
auto PropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, const std::string& item_type, UnsignedLong& bytes_written,
|
||||
BinaryWriter& writer) -> bool
|
||||
{
|
||||
auto serialiser = getSerialiser(item_type);
|
||||
if(!serialiser) {
|
||||
|
@ -209,7 +200,7 @@ auto PropertySerialiser::write(UnrealPropertyBase::ptr& prop, UnsignedLong& byte
|
|||
return ret;
|
||||
}
|
||||
|
||||
auto PropertySerialiser::writeItem(UnrealPropertyBase::ptr& prop, Containers::StringView item_type,
|
||||
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())) {
|
||||
|
@ -220,9 +211,8 @@ auto PropertySerialiser::writeItem(UnrealPropertyBase::ptr& prop, Containers::St
|
|||
return serialise(prop, item_type, bytes_written, writer);
|
||||
}
|
||||
|
||||
auto PropertySerialiser::writeSet(Containers::ArrayView<UnrealPropertyBase::ptr> props,
|
||||
Containers::StringView item_type, UnsignedLong& bytes_written,
|
||||
BinaryWriter& writer) -> bool
|
||||
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) {
|
||||
|
@ -239,9 +229,9 @@ auto PropertySerialiser::writeSet(Containers::ArrayView<UnrealPropertyBase::ptr>
|
|||
}
|
||||
}
|
||||
|
||||
auto PropertySerialiser::getSerialiser(Containers::StringView item_type) -> AbstractUnrealPropertySerialiser* {
|
||||
auto PropertySerialiser::getSerialiser(const std::string& item_type) -> AbstractUnrealPropertySerialiser* {
|
||||
for(auto& item : _serialisers) {
|
||||
for(auto serialiser_type : item->types()) {
|
||||
for(const std::string& serialiser_type : item->types()) {
|
||||
if(item_type == serialiser_type) {
|
||||
return item.get();
|
||||
}
|
||||
|
@ -251,9 +241,9 @@ auto PropertySerialiser::getSerialiser(Containers::StringView item_type) -> Abst
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
auto PropertySerialiser::getCollectionSerialiser(Containers::StringView item_type) -> AbstractUnrealCollectionPropertySerialiser* {
|
||||
auto PropertySerialiser::getCollectionSerialiser(const std::string& item_type) -> AbstractUnrealCollectionPropertySerialiser* {
|
||||
for(auto& item : _collectionSerialisers) {
|
||||
for(Containers::StringView serialiser_type : item->types()) {
|
||||
for(const std::string& serialiser_type : item->types()) {
|
||||
if(item_type == serialiser_type) {
|
||||
return item.get();
|
||||
}
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include <Corrade/Containers/GrowableArray.h>
|
||||
#include <Corrade/Containers/String.h>
|
||||
#include <Corrade/Containers/StringView.h>
|
||||
|
||||
#include "Serialisers/AbstractUnrealPropertySerialiser.h"
|
||||
#include "Serialisers/AbstractUnrealCollectionPropertySerialiser.h"
|
||||
|
@ -32,28 +30,21 @@ class BinaryWriter;
|
|||
|
||||
class PropertySerialiser {
|
||||
public:
|
||||
static auto instance() -> PropertySerialiser&;
|
||||
|
||||
auto read(BinaryReader& reader) -> UnrealPropertyBase::ptr;
|
||||
auto readItem(BinaryReader& reader, Containers::String type, UnsignedLong value_length,
|
||||
Containers::String name) -> UnrealPropertyBase::ptr;
|
||||
auto readSet(BinaryReader& reader, Containers::StringView item_type, UnsignedInt count) -> Containers::Array<UnrealPropertyBase::ptr>;
|
||||
auto deserialise(Containers::String name, Containers::String type, UnsignedLong value_length,
|
||||
BinaryReader& reader) -> UnrealPropertyBase::ptr;
|
||||
|
||||
auto serialise(UnrealPropertyBase::ptr& prop, Containers::StringView item_type, UnsignedLong& bytes_written,
|
||||
BinaryWriter& writer) -> bool;
|
||||
auto write(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer) -> bool;
|
||||
auto writeItem(UnrealPropertyBase::ptr& prop, Containers::StringView item_type, UnsignedLong& bytes_written,
|
||||
BinaryWriter& writer) -> bool;
|
||||
auto writeSet(Containers::ArrayView<UnrealPropertyBase::ptr> props, Containers::StringView item_type,
|
||||
UnsignedLong& bytes_written, BinaryWriter& writer) -> bool;
|
||||
|
||||
private:
|
||||
PropertySerialiser();
|
||||
|
||||
auto getSerialiser(Containers::StringView item_type) -> AbstractUnrealPropertySerialiser*;
|
||||
auto getCollectionSerialiser(Containers::StringView item_type) -> AbstractUnrealCollectionPropertySerialiser*;
|
||||
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;
|
||||
|
|
|
@ -16,10 +16,11 @@
|
|||
// 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 <Corrade/Containers/StringView.h>
|
||||
|
||||
#include <Magnum/Types.h>
|
||||
|
||||
|
@ -38,12 +39,9 @@ class AbstractUnrealCollectionPropertySerialiser {
|
|||
|
||||
virtual ~AbstractUnrealCollectionPropertySerialiser() = default;
|
||||
|
||||
virtual auto types() -> Containers::ArrayView<const Containers::String> = 0;
|
||||
virtual auto types() -> Containers::ArrayView<const std::string> = 0;
|
||||
|
||||
virtual auto deserialise(Containers::StringView name, Containers::StringView type,
|
||||
UnsignedLong value_length, UnsignedInt count, BinaryReader& reader,
|
||||
PropertySerialiser& serialiser) -> Containers::Array<UnrealPropertyBase::ptr> = 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, Containers::StringView item_type,
|
||||
UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool = 0;
|
||||
virtual auto serialise(Containers::ArrayView<UnrealPropertyBase::ptr> props, const std::string& item_type, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool = 0;
|
||||
};
|
||||
|
|
|
@ -16,9 +16,10 @@
|
|||
// 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 <Corrade/Containers/StringView.h>
|
||||
|
||||
#include <Magnum/Types.h>
|
||||
|
||||
|
@ -37,11 +38,9 @@ class AbstractUnrealPropertySerialiser {
|
|||
|
||||
virtual ~AbstractUnrealPropertySerialiser() = default;
|
||||
|
||||
virtual auto types() -> Containers::ArrayView<const Containers::String> = 0;
|
||||
virtual auto types() -> Containers::ArrayView<const std::string> = 0;
|
||||
|
||||
virtual auto deserialise(Containers::StringView name, Containers::StringView type, UnsignedLong value_length,
|
||||
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr = 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;
|
||||
virtual auto serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool = 0;
|
||||
};
|
||||
|
|
|
@ -16,10 +16,11 @@
|
|||
// 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 <Corrade/Containers/StringView.h>
|
||||
|
||||
#include <Magnum/Types.h>
|
||||
|
||||
|
@ -37,10 +38,9 @@ class AbstractUnrealStructSerialiser {
|
|||
|
||||
virtual ~AbstractUnrealStructSerialiser() = default;
|
||||
|
||||
virtual auto supportsType(Containers::StringView type) -> bool = 0;
|
||||
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;
|
||||
virtual auto serialise(UnrealPropertyBase::ptr& structProp, BinaryWriter& writer, UnsignedLong& bytes_written) -> bool = 0;
|
||||
};
|
||||
|
|
|
@ -14,34 +14,27 @@
|
|||
// 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/String.h>
|
||||
|
||||
#include "../BinaryReader.h"
|
||||
#include "../BinaryWriter.h"
|
||||
#include "../PropertySerialiser.h"
|
||||
#include "../../Logger/Logger.h"
|
||||
|
||||
#include "ArrayPropertySerialiser.h"
|
||||
|
||||
auto ArrayPropertySerialiser::deserialiseProperty(Containers::StringView name, Containers::StringView type,
|
||||
UnsignedLong value_length, BinaryReader& reader,
|
||||
PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||
auto ArrayPropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||
{
|
||||
Containers::String item_type;
|
||||
std::string item_type;
|
||||
if(!reader.readUEString(item_type)) {
|
||||
LOG_ERROR_FORMAT("Couldn't read the item type of array property {}.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char terminator;
|
||||
if(!reader.readChar(terminator) || terminator != '\0') {
|
||||
LOG_ERROR_FORMAT("Couldn't read a null byte in array property {}.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UnsignedInt item_count;
|
||||
if(!reader.readUnsignedInt(item_count)) {
|
||||
LOG_ERROR_FORMAT("Couldn't read array property {}'s item count.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -57,7 +50,6 @@ auto ArrayPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, U
|
|||
{
|
||||
auto array_prop = dynamic_cast<ArrayProperty*>(prop.get());
|
||||
if(!array_prop) {
|
||||
LOG_ERROR("The property is not a valid array property.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,24 +16,15 @@
|
|||
// 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/StringView.h>
|
||||
|
||||
#include <Magnum/Types.h>
|
||||
|
||||
#include "UnrealPropertySerialiser.h"
|
||||
|
||||
#include "../Types/ArrayProperty.h"
|
||||
|
||||
using namespace Corrade;
|
||||
using namespace Magnum;
|
||||
|
||||
class ArrayPropertySerialiser : public UnrealPropertySerialiser<ArrayProperty> {
|
||||
public:
|
||||
using ptr = Containers::Pointer<ArrayPropertySerialiser>;
|
||||
|
||||
private:
|
||||
auto deserialiseProperty(Containers::StringView name, Containers::StringView 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;
|
||||
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;
|
||||
};
|
||||
|
|
|
@ -16,33 +16,27 @@
|
|||
|
||||
#include "../BinaryReader.h"
|
||||
#include "../BinaryWriter.h"
|
||||
#include "../../Logger/Logger.h"
|
||||
|
||||
#include "BoolPropertySerialiser.h"
|
||||
|
||||
auto BoolPropertySerialiser::types() -> Containers::ArrayView<const Containers::String> {
|
||||
using namespace Containers::Literals;
|
||||
static const Containers::Array<Containers::String> types{InPlaceInit, {"BoolProperty"_s}};
|
||||
auto BoolPropertySerialiser::types() -> Containers::ArrayView<const std::string> {
|
||||
static const Containers::Array<std::string> types{InPlaceInit, {"BoolProperty"}};
|
||||
return types;
|
||||
}
|
||||
|
||||
auto BoolPropertySerialiser::deserialise(Containers::StringView name, Containers::StringView type,
|
||||
UnsignedLong value_length, BinaryReader& reader,
|
||||
PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||
auto BoolPropertySerialiser::deserialise(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||
{
|
||||
if(value_length != 0) {
|
||||
LOG_ERROR_FORMAT("Invalid value length for bool property {}. Expected 0, got {} instead.", name, value_length);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Short value;
|
||||
if(!reader.readShort(value)) {
|
||||
LOG_ERROR_FORMAT("Couldn't read bool property {}'s value.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(value > 1 || value < 0) {
|
||||
LOG_ERROR_FORMAT("Bool property {}'s value is invalid. Expected 1 or 0, got {} instead.", name, value);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -56,8 +50,8 @@ auto BoolPropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, UnsignedLo
|
|||
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||
{
|
||||
auto bool_prop = dynamic_cast<BoolProperty*>(prop.get());
|
||||
|
||||
if(!bool_prop) {
|
||||
LOG_ERROR("The property is not a valid bool property.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,24 +16,17 @@
|
|||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include <Corrade/Containers/ArrayView.h>
|
||||
#include <Corrade/Containers/StringView.h>
|
||||
|
||||
#include "AbstractUnrealPropertySerialiser.h"
|
||||
|
||||
#include "../Types/BoolProperty.h"
|
||||
|
||||
using namespace Corrade;
|
||||
|
||||
class BoolPropertySerialiser : public AbstractUnrealPropertySerialiser {
|
||||
public:
|
||||
using ptr = Containers::Pointer<BoolPropertySerialiser>;
|
||||
|
||||
auto types() -> Containers::ArrayView<const Containers::String> override;
|
||||
auto types() -> Containers::ArrayView<const std::string> override;
|
||||
|
||||
auto deserialise(Containers::StringView name, Containers::StringView type, UnsignedLong value_length,
|
||||
BinaryReader& reader, PropertySerialiser& serialiser) -> 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(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer,
|
||||
PropertySerialiser& serialiser) -> bool override;
|
||||
auto serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||
};
|
||||
|
|
|
@ -16,37 +16,31 @@
|
|||
|
||||
#include "../BinaryReader.h"
|
||||
#include "../BinaryWriter.h"
|
||||
#include "../../Logger/Logger.h"
|
||||
|
||||
#include "BytePropertySerialiser.h"
|
||||
|
||||
auto BytePropertySerialiser::types() -> Containers::ArrayView<const Containers::String> {
|
||||
using namespace Containers::Literals;
|
||||
static const Containers::Array<Containers::String> types{InPlaceInit, {"ByteProperty"_s}};
|
||||
auto BytePropertySerialiser::types() -> Containers::ArrayView<const std::string> {
|
||||
static const Containers::Array<std::string> types{InPlaceInit, {"ByteProperty"}};
|
||||
return types;
|
||||
}
|
||||
|
||||
auto BytePropertySerialiser::deserialise(Containers::StringView name, Containers::StringView type,
|
||||
UnsignedLong value_length, BinaryReader& reader,
|
||||
PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||
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)) {
|
||||
LOG_ERROR_FORMAT("Couldn't read byte property {}'s enum type.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char terminator;
|
||||
if(!reader.readChar(terminator) || terminator != '\0') {
|
||||
LOG_ERROR_FORMAT("Couldn't read a null byte in byte property {}.", name);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if(!reader.readUEString(prop->enumValue)) {
|
||||
LOG_ERROR("Couldn't read byte property's enum value.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -68,8 +62,8 @@ auto BytePropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, UnsignedLo
|
|||
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||
{
|
||||
auto byte_prop = dynamic_cast<ByteProperty*>(prop.get());
|
||||
|
||||
if(!byte_prop) {
|
||||
LOG_ERROR("The property is not a valid byte property.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include <Corrade/Containers/ArrayView.h>
|
||||
#include <Corrade/Containers/StringView.h>
|
||||
|
||||
#include "AbstractUnrealPropertySerialiser.h"
|
||||
|
||||
#include "../Types/ByteProperty.h"
|
||||
|
@ -27,11 +24,9 @@ class BytePropertySerialiser : public AbstractUnrealPropertySerialiser {
|
|||
public:
|
||||
using ptr = Containers::Pointer<BytePropertySerialiser>;
|
||||
|
||||
auto types() -> Containers::ArrayView<const Containers::String> override;
|
||||
auto types() -> Containers::ArrayView<const std::string> override;
|
||||
|
||||
auto deserialise(Containers::StringView name, Containers::StringView type, UnsignedLong value_length,
|
||||
BinaryReader& reader, PropertySerialiser& serialiser) -> 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(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer,
|
||||
PropertySerialiser& serialiser) -> bool override;
|
||||
auto serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||
};
|
||||
|
|
|
@ -16,20 +16,17 @@
|
|||
|
||||
#include "../BinaryReader.h"
|
||||
#include "../BinaryWriter.h"
|
||||
#include "../../Logger/Logger.h"
|
||||
|
||||
#include "ColourPropertySerialiser.h"
|
||||
|
||||
auto ColourPropertySerialiser::deserialiseProperty(Containers::StringView name, Containers::StringView type,
|
||||
UnsignedLong value_length, BinaryReader& reader,
|
||||
PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||
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))
|
||||
{
|
||||
LOG_ERROR_FORMAT("Couldn't read colour property {}'s value.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -40,8 +37,8 @@ auto ColourPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop,
|
|||
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||
{
|
||||
auto colour_prop = dynamic_cast<ColourStructProperty*>(prop.get());
|
||||
|
||||
if(!colour_prop) {
|
||||
LOG_ERROR("The property is not a valid colour property.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,21 +16,15 @@
|
|||
// 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/StringView.h>
|
||||
|
||||
#include "UnrealPropertySerialiser.h"
|
||||
|
||||
#include "../Types/ColourStructProperty.h"
|
||||
|
||||
using namespace Corrade;
|
||||
|
||||
class ColourPropertySerialiser : public UnrealPropertySerialiser<ColourStructProperty> {
|
||||
public:
|
||||
using ptr = Containers::Pointer<ColourPropertySerialiser>;
|
||||
|
||||
private:
|
||||
auto deserialiseProperty(Containers::StringView name, Containers::StringView 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;
|
||||
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;
|
||||
};
|
||||
|
|
|
@ -16,18 +16,15 @@
|
|||
|
||||
#include "../BinaryReader.h"
|
||||
#include "../BinaryWriter.h"
|
||||
#include "../../Logger/Logger.h"
|
||||
|
||||
#include "DateTimePropertySerialiser.h"
|
||||
|
||||
auto DateTimePropertySerialiser::deserialiseProperty(Containers::StringView name, Containers::StringView type,
|
||||
UnsignedLong value_length, BinaryReader& reader,
|
||||
PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||
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)) {
|
||||
LOG_ERROR_FORMAT("Couldn't read date/time property {}'s value.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -38,8 +35,8 @@ auto DateTimePropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop
|
|||
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||
{
|
||||
auto dt_prop = dynamic_cast<DateTimeStructProperty*>(prop.get());
|
||||
|
||||
if(!dt_prop) {
|
||||
LOG_ERROR("The property is not a valid date/time property.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
// 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/StringView.h>
|
||||
|
||||
#include "UnrealPropertySerialiser.h"
|
||||
|
||||
#include "../Types/DateTimeStructProperty.h"
|
||||
|
@ -27,8 +25,6 @@ class DateTimePropertySerialiser : public UnrealPropertySerialiser<DateTimeStruc
|
|||
using ptr = Containers::Pointer<DateTimePropertySerialiser>;
|
||||
|
||||
private:
|
||||
auto deserialiseProperty(Containers::StringView name, Containers::StringView 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;
|
||||
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;
|
||||
};
|
||||
|
|
|
@ -16,35 +16,29 @@
|
|||
|
||||
#include "../BinaryReader.h"
|
||||
#include "../BinaryWriter.h"
|
||||
#include "../../Logger/Logger.h"
|
||||
|
||||
#include "EnumPropertySerialiser.h"
|
||||
|
||||
auto EnumPropertySerialiser::types() -> Containers::ArrayView<const Containers::String> {
|
||||
using namespace Containers::Literals;
|
||||
static const Containers::Array<Containers::String> types{InPlaceInit, {"EnumProperty"_s}};
|
||||
auto EnumPropertySerialiser::types() -> Containers::ArrayView<const std::string> {
|
||||
static const Containers::Array<std::string> types{InPlaceInit, {"EnumProperty"}};
|
||||
return types;
|
||||
}
|
||||
|
||||
auto EnumPropertySerialiser::deserialise(Containers::StringView name, Containers::StringView type,
|
||||
UnsignedLong value_length, BinaryReader& reader,
|
||||
PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||
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)) {
|
||||
LOG_ERROR_FORMAT("Couldn't read enum property {}'s enum type.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char terminator;
|
||||
if(!reader.readChar(terminator) || terminator != '\0') {
|
||||
LOG_ERROR_FORMAT("Couldn't read a null byte in enum property {}.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(!reader.readUEString(prop->value)) {
|
||||
LOG_ERROR_FORMAT("Couldn't read enum property {}'s enum value.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -55,8 +49,8 @@ auto EnumPropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, UnsignedLo
|
|||
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||
{
|
||||
auto enum_prop = dynamic_cast<EnumProperty*>(prop.get());
|
||||
|
||||
if(!enum_prop) {
|
||||
LOG_ERROR("The property is not a valid enum property.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include <Corrade/Containers/ArrayView.h>
|
||||
#include <Corrade/Containers/StringView.h>
|
||||
|
||||
#include "AbstractUnrealPropertySerialiser.h"
|
||||
|
||||
#include "../Types/EnumProperty.h"
|
||||
|
@ -27,11 +24,9 @@ class EnumPropertySerialiser : public AbstractUnrealPropertySerialiser {
|
|||
public:
|
||||
using ptr = Containers::Pointer<EnumPropertySerialiser>;
|
||||
|
||||
auto types() -> Containers::ArrayView<const Containers::String> override;
|
||||
auto types() -> Containers::ArrayView<const std::string> override;
|
||||
|
||||
auto deserialise(Containers::StringView name, Containers::StringView type, UnsignedLong value_length,
|
||||
BinaryReader& reader, PropertySerialiser& serialiser) -> 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(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer,
|
||||
PropertySerialiser& serialiser) -> bool override;
|
||||
auto serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||
};
|
||||
|
|
|
@ -16,30 +16,25 @@
|
|||
|
||||
#include "../BinaryReader.h"
|
||||
#include "../BinaryWriter.h"
|
||||
#include "../../Logger/Logger.h"
|
||||
|
||||
#include "FloatPropertySerialiser.h"
|
||||
|
||||
auto FloatPropertySerialiser::types() -> Containers::ArrayView<const Containers::String> {
|
||||
using namespace Containers::Literals;
|
||||
static const Containers::Array<Containers::String> types{InPlaceInit, {"FloatProperty"_s}};
|
||||
auto FloatPropertySerialiser::types() -> Containers::ArrayView<const std::string> {
|
||||
static const Containers::Array<std::string> types{InPlaceInit, {"FloatProperty"}};
|
||||
return types;
|
||||
}
|
||||
|
||||
auto FloatPropertySerialiser::deserialise(Containers::StringView name, Containers::StringView type,
|
||||
UnsignedLong value_length, BinaryReader& reader,
|
||||
PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||
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') {
|
||||
LOG_ERROR_FORMAT("Couldn't read a null byte in float property {}.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(!reader.readFloat(prop->value)) {
|
||||
LOG_ERROR_FORMAT("Couldn't read float property {}'s value.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -50,8 +45,8 @@ auto FloatPropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, UnsignedL
|
|||
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||
{
|
||||
auto float_prop = dynamic_cast<FloatProperty*>(prop.get());
|
||||
|
||||
if(!float_prop) {
|
||||
LOG_ERROR("The property is not a valid float property.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include <Corrade/Containers/ArrayView.h>
|
||||
#include <Corrade/Containers/StringView.h>
|
||||
|
||||
#include "AbstractUnrealPropertySerialiser.h"
|
||||
|
||||
#include "../Types/FloatProperty.h"
|
||||
|
@ -27,11 +24,9 @@ class FloatPropertySerialiser : public AbstractUnrealPropertySerialiser {
|
|||
public:
|
||||
using ptr = Containers::Pointer<FloatPropertySerialiser>;
|
||||
|
||||
auto types() -> Containers::ArrayView<const Containers::String> override;
|
||||
auto types() -> Containers::ArrayView<const std::string> override;
|
||||
|
||||
auto deserialise(Containers::StringView name, Containers::StringView type, UnsignedLong value_length,
|
||||
BinaryReader& reader, PropertySerialiser& serialiser) -> 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(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer,
|
||||
PropertySerialiser& serialiser) -> bool override;
|
||||
auto serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||
};
|
||||
|
|
|
@ -16,20 +16,16 @@
|
|||
|
||||
#include "../BinaryReader.h"
|
||||
#include "../BinaryWriter.h"
|
||||
#include "../../Logger/Logger.h"
|
||||
|
||||
#include "GuidPropertySerialiser.h"
|
||||
|
||||
using namespace Containers::Literals;
|
||||
|
||||
auto GuidPropertySerialiser::deserialiseProperty(Containers::StringView name, Containers::StringView type,
|
||||
UnsignedLong value_length, BinaryReader& reader,
|
||||
PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||
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)) {
|
||||
LOG_ERROR_FORMAT("Couldn't read GUID property {}'s value.", name);
|
||||
Utility::Error{} << "Couldn't read guid in" << __func__;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -40,8 +36,8 @@ auto GuidPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, Un
|
|||
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||
{
|
||||
auto guid_prop = dynamic_cast<GuidStructProperty*>(prop.get());
|
||||
|
||||
if(!guid_prop) {
|
||||
LOG_ERROR("The property is not a valid byte property.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
// 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/StringView.h>
|
||||
|
||||
#include "UnrealPropertySerialiser.h"
|
||||
|
||||
#include "../Types/GuidStructProperty.h"
|
||||
|
@ -27,8 +25,7 @@ class GuidPropertySerialiser : public UnrealPropertySerialiser<GuidStructPropert
|
|||
using ptr = Containers::Pointer<GuidPropertySerialiser>;
|
||||
|
||||
private:
|
||||
auto deserialiseProperty(Containers::StringView name, Containers::StringView type, UnsignedLong value_length,
|
||||
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;
|
||||
auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override;
|
||||
};
|
||||
|
|
|
@ -16,19 +16,16 @@
|
|||
|
||||
#include "../BinaryReader.h"
|
||||
#include "../BinaryWriter.h"
|
||||
#include "../../Logger/Logger.h"
|
||||
|
||||
#include "IntPropertySerialiser.h"
|
||||
|
||||
auto IntPropertySerialiser::deserialiseProperty(Containers::StringView name, Containers::StringView type,
|
||||
UnsignedLong value_length, BinaryReader& reader,
|
||||
PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||
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)) {
|
||||
LOG_ERROR("Couldn't read int property's value.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -38,12 +35,10 @@ auto IntPropertySerialiser::deserialiseProperty(Containers::StringView name, Con
|
|||
|
||||
char terminator;
|
||||
if(!reader.readChar(terminator) || terminator != '\0') {
|
||||
LOG_ERROR_FORMAT("Couldn't read a null byte in int property {}.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(!reader.readInt(prop->value)) {
|
||||
LOG_ERROR_FORMAT("Couldn't read int property {}'s value.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -56,8 +51,8 @@ auto IntPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, Uns
|
|||
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||
{
|
||||
auto int_prop = dynamic_cast<IntProperty*>(prop.get());
|
||||
|
||||
if(!int_prop) {
|
||||
LOG_ERROR("The property is not a valid int property.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
// 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/StringView.h>
|
||||
|
||||
#include "UnrealPropertySerialiser.h"
|
||||
|
||||
#include "../Types/IntProperty.h"
|
||||
|
@ -27,8 +25,6 @@ class IntPropertySerialiser : public UnrealPropertySerialiser<IntProperty> {
|
|||
using ptr = Containers::Pointer<IntPropertySerialiser>;
|
||||
|
||||
private:
|
||||
auto deserialiseProperty(Containers::StringView name, Containers::StringView 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;
|
||||
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;
|
||||
};
|
||||
|
|
|
@ -17,44 +17,36 @@
|
|||
#include "../BinaryReader.h"
|
||||
#include "../BinaryWriter.h"
|
||||
#include "../PropertySerialiser.h"
|
||||
|
||||
#include "../Types/NoneProperty.h"
|
||||
#include "../../Logger/Logger.h"
|
||||
|
||||
#include "MapPropertySerialiser.h"
|
||||
|
||||
using namespace Containers::Literals;
|
||||
|
||||
auto MapPropertySerialiser::deserialiseProperty(Containers::StringView name, Containers::StringView type,
|
||||
UnsignedLong value_length, BinaryReader& reader,
|
||||
PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||
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)) {
|
||||
LOG_ERROR_FORMAT("Couldn't read map property {}'s key type.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(!reader.readUEString(prop->valueType)) {
|
||||
LOG_ERROR_FORMAT("Couldn't read map property {}'s value type.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char terminator;
|
||||
if(!reader.readChar(terminator) || terminator != '\0') {
|
||||
LOG_ERROR_FORMAT("Couldn't read a null byte in map property {}.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UnsignedInt null;
|
||||
if(!reader.readUnsignedInt(null) || null != 0u) {
|
||||
LOG_ERROR_FORMAT("Couldn't read a null int in map property {}.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UnsignedInt count;
|
||||
if(!reader.readUnsignedInt(count)) {
|
||||
LOG_ERROR_FORMAT("Couldn't read map property {}'s item count.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -66,32 +58,30 @@ auto MapPropertySerialiser::deserialiseProperty(Containers::StringView name, Con
|
|||
for(UnsignedInt i = 0; i < count; i++) {
|
||||
MapProperty::KeyValuePair pair;
|
||||
|
||||
if(prop->keyType == "IntProperty"_s || prop->keyType == "StrProperty"_s) {
|
||||
if(prop->keyType == "IntProperty" || prop->keyType == "StrProperty") {
|
||||
pair.key = serialiser.readItem(reader, prop->keyType, -1, name);
|
||||
if(pair.key == nullptr) {
|
||||
LOG_ERROR_FORMAT("Couldn't read a valid key in map property {}.", name);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else { // Add other branches depending on key type, should more maps appear in the future.
|
||||
LOG_ERROR_FORMAT("Key type {} not implemented.", prop->keyType);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UnrealPropertyBase::ptr value_item;
|
||||
if(prop->valueType == "StructProperty"_s) {
|
||||
if(prop->valueType == "StructProperty") {
|
||||
while((value_item = serialiser.read(reader)) != nullptr) {
|
||||
arrayAppend(pair.values, std::move(value_item));
|
||||
|
||||
if(pair.values.back()->name == "None"_s &&
|
||||
pair.values.back()->propertyType == "NoneProperty"_s &&
|
||||
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"_s) {
|
||||
else if(prop->valueType == "ByteProperty") {
|
||||
if((value_item = serialiser.readItem(reader, prop->valueType, -1, name)) == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -112,7 +102,6 @@ auto MapPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, Uns
|
|||
{
|
||||
auto map_prop = dynamic_cast<MapProperty*>(prop.get());
|
||||
if(!map_prop) {
|
||||
LOG_ERROR("The property is not a valid map property.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -128,20 +117,17 @@ auto MapPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, Uns
|
|||
UnsignedLong dummy_bytes_written = 0;
|
||||
for(auto& pair : map_prop->map) {
|
||||
if(!serialiser.writeItem(pair.key, map_prop->keyType, dummy_bytes_written, writer)) {
|
||||
LOG_ERROR("Couldn't write a key.");
|
||||
return false;
|
||||
}
|
||||
|
||||
for(auto& value : pair.values) {
|
||||
if(map_prop->valueType == "StructProperty"_s) {
|
||||
if(map_prop->valueType == "StructProperty") {
|
||||
if(!serialiser.write(value, dummy_bytes_written, writer)) {
|
||||
LOG_ERROR("Couldn't write a value.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(!serialiser.writeItem(value, map_prop->valueType, dummy_bytes_written, writer)) {
|
||||
LOG_ERROR("Couldn't write a value.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
// 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/StringView.h>
|
||||
|
||||
#include "UnrealPropertySerialiser.h"
|
||||
|
||||
#include "../Types/MapProperty.h"
|
||||
|
@ -27,8 +25,6 @@ class MapPropertySerialiser : public UnrealPropertySerialiser<MapProperty> {
|
|||
using ptr = Containers::Pointer<MapPropertySerialiser>;
|
||||
|
||||
private:
|
||||
auto deserialiseProperty(Containers::StringView name, Containers::StringView 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;
|
||||
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;
|
||||
};
|
||||
|
|
|
@ -17,60 +17,60 @@
|
|||
#include "../BinaryReader.h"
|
||||
#include "../BinaryWriter.h"
|
||||
#include "../PropertySerialiser.h"
|
||||
|
||||
#include "../Types/IntProperty.h"
|
||||
#include "../Types/NoneProperty.h"
|
||||
#include "../../Logger/Logger.h"
|
||||
|
||||
#include "ResourcePropertySerialiser.h"
|
||||
|
||||
using namespace Containers::Literals;
|
||||
|
||||
auto ResourcePropertySerialiser::deserialiseProperty(Containers::StringView name, Containers::StringView type,
|
||||
UnsignedLong value_length, BinaryReader& reader,
|
||||
PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||
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>();
|
||||
|
||||
auto id_prop = serialiser.read(reader);
|
||||
if(!id_prop) {
|
||||
LOG_ERROR("Couldn't read the ID property."_s);
|
||||
std::string str;
|
||||
if(!reader.readUEString(str) || str != "ID_4_AAE08F17428E229EC7A2209F51081A21") {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if((*id_prop->name) != "ID_4_AAE08F17428E229EC7A2209F51081A21"_s ||
|
||||
id_prop->propertyType != "IntProperty"_s ||
|
||||
dynamic_cast<IntProperty*>(id_prop.get()) == nullptr)
|
||||
{
|
||||
LOG_ERROR("The ID property is invalid."_s);
|
||||
if(!reader.readUEString(str) || str != "IntProperty") {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
prop->id = dynamic_cast<IntProperty*>(id_prop.get())->value;
|
||||
|
||||
auto value_prop = serialiser.read(reader);
|
||||
if(!value_prop) {
|
||||
LOG_ERROR("Couldn't read the value property."_s);
|
||||
if(!reader.readUnsignedLong(value_length) || value_length != 4ull) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if((*value_prop->name) != "Quantity_3_560F09B5485C365D3041888910019CE3"_s ||
|
||||
value_prop->propertyType != "IntProperty"_s ||
|
||||
dynamic_cast<IntProperty*>(value_prop.get()) == nullptr)
|
||||
{
|
||||
LOG_ERROR("The value property is invalid."_s);
|
||||
char terminator;
|
||||
if(!reader.readChar(terminator) || terminator != '\0') {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
prop->quantity = dynamic_cast<IntProperty*>(value_prop.get())->value;
|
||||
if(!reader.readInt(prop->id)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto none_prop = serialiser.read(reader);
|
||||
if(!reader.readUEString(str) || str != "Quantity_3_560F09B5485C365D3041888910019CE3") {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(!none_prop ||
|
||||
(*none_prop->name) != "None"_s ||
|
||||
none_prop->propertyType != "NoneProperty"_s ||
|
||||
!dynamic_cast<NoneProperty*>(none_prop.get()))
|
||||
{
|
||||
LOG_ERROR("Couldn't find a terminating NoneProperty."_s);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -82,23 +82,22 @@ auto ResourcePropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop
|
|||
{
|
||||
auto res_prop = dynamic_cast<ResourceItemValue*>(prop.get());
|
||||
if(!res_prop) {
|
||||
LOG_ERROR("The property is not a valid ResourceItemValue property.");
|
||||
return false;
|
||||
}
|
||||
|
||||
bytes_written += writer.writeUEStringToArray("ID_4_AAE08F17428E229EC7A2209F51081A21"_s) +
|
||||
writer.writeUEStringToArray("IntProperty"_s) +
|
||||
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"_s) +
|
||||
writer.writeUEStringToArray("IntProperty"_s) +
|
||||
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"_s);
|
||||
bytes_written += writer.writeUEStringToArray("None");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
// 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/StringView.h>
|
||||
|
||||
#include "UnrealPropertySerialiser.h"
|
||||
|
||||
#include "../Types/ResourceItemValue.h"
|
||||
|
@ -27,8 +25,6 @@ class ResourcePropertySerialiser : public UnrealPropertySerialiser<ResourceItemV
|
|||
using ptr = Containers::Pointer<ResourcePropertySerialiser>;
|
||||
|
||||
private:
|
||||
auto deserialiseProperty(Containers::StringView name, Containers::StringView 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;
|
||||
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;
|
||||
};
|
||||
|
|
|
@ -16,18 +16,15 @@
|
|||
|
||||
#include "../BinaryReader.h"
|
||||
#include "../BinaryWriter.h"
|
||||
#include "../../Logger/Logger.h"
|
||||
|
||||
#include "RotatorPropertySerialiser.h"
|
||||
|
||||
auto RotatorPropertySerialiser::deserialiseProperty(Containers::StringView name, Containers::StringView type,
|
||||
UnsignedLong value_length, BinaryReader& reader,
|
||||
PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||
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)) {
|
||||
LOG_ERROR_FORMAT("Couldn't read rotator property {}'s value.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -38,8 +35,8 @@ auto RotatorPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop,
|
|||
BinaryWriter& writer, PropertySerialiser& serialiser) -> bool
|
||||
{
|
||||
auto rotator = dynamic_cast<RotatorStructProperty*>(prop.get());
|
||||
|
||||
if(!rotator) {
|
||||
LOG_ERROR("The property is not a valid rotator property.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
// 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/StringView.h>
|
||||
|
||||
#include "UnrealPropertySerialiser.h"
|
||||
|
||||
#include "../Types/RotatorStructProperty.h"
|
||||
|
@ -27,8 +25,6 @@ class RotatorPropertySerialiser : public UnrealPropertySerialiser<RotatorStructP
|
|||
using ptr = Containers::Pointer<RotatorPropertySerialiser>;
|
||||
|
||||
private:
|
||||
auto deserialiseProperty(Containers::StringView name, Containers::StringView 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;
|
||||
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;
|
||||
};
|
||||
|
|
|
@ -17,35 +17,29 @@
|
|||
#include "../BinaryReader.h"
|
||||
#include "../BinaryWriter.h"
|
||||
#include "../PropertySerialiser.h"
|
||||
#include "../../Logger/Logger.h"
|
||||
|
||||
#include "SetPropertySerialiser.h"
|
||||
|
||||
auto SetPropertySerialiser::deserialiseProperty(Containers::StringView name, Containers::StringView type,
|
||||
UnsignedLong value_length, BinaryReader& reader,
|
||||
PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||
auto SetPropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length,
|
||||
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr
|
||||
{
|
||||
Containers::String item_type;
|
||||
std::string item_type;
|
||||
if(!reader.readUEString(item_type)) {
|
||||
LOG_ERROR_FORMAT("Couldn't read set property {}'s item type.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char terminator;
|
||||
if(!reader.readChar(terminator) || terminator != '\0') {
|
||||
LOG_ERROR_FORMAT("Couldn't read a null byte in set property {}.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UnsignedInt four_bytes;
|
||||
if(!reader.readUnsignedInt(four_bytes) || four_bytes != 0u) {
|
||||
LOG_ERROR_FORMAT("Couldn't read four null bytes in set property {}.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UnsignedInt item_count;
|
||||
if(!reader.readUnsignedInt(item_count)) {
|
||||
LOG_ERROR_FORMAT("Couldn't read set property {}'s item count.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -61,7 +55,6 @@ auto SetPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, Uns
|
|||
{
|
||||
auto set_prop = dynamic_cast<SetProperty*>(prop.get());
|
||||
if(!set_prop) {
|
||||
LOG_ERROR("The property is not a valid set property.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
// 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/StringView.h>
|
||||
|
||||
#include "UnrealPropertySerialiser.h"
|
||||
|
||||
#include "../Types/SetProperty.h"
|
||||
|
@ -27,8 +25,6 @@ class SetPropertySerialiser : public UnrealPropertySerialiser<SetProperty> {
|
|||
using ptr = Containers::Pointer<SetPropertySerialiser>;
|
||||
|
||||
private:
|
||||
auto deserialiseProperty(Containers::StringView name, Containers::StringView 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;
|
||||
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;
|
||||
};
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue